diff options
Diffstat (limited to 'include/clang/AST/Stmt.h')
| -rw-r--r-- | include/clang/AST/Stmt.h | 359 |
1 files changed, 303 insertions, 56 deletions
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index ff5baa21adff5..403b88ac3a3c7 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -1,9 +1,8 @@ //===- Stmt.h - Classes for representing statements -------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -47,6 +46,7 @@ class Attr; class CapturedDecl; class Decl; class Expr; +class AddrLabelExpr; class LabelDecl; class ODRHash; class PrinterHelper; @@ -92,12 +92,20 @@ protected: //===--- Statement bitfields classes ---===// class StmtBitfields { + friend class ASTStmtReader; + friend class ASTStmtWriter; friend class Stmt; /// The statement class. unsigned sClass : 8; + + /// This bit is set only for the Stmts that are the structured-block of + /// OpenMP executable directives. Directives that have a structured block + /// are called "non-standalone" directives. + /// I.e. those returned by OMPExecutableDirective::getStructuredBlock(). + unsigned IsOMPStructuredBlock : 1; }; - enum { NumStmtBits = 8 }; + enum { NumStmtBits = 9 }; class NullStmtBitfields { friend class ASTStmtReader; @@ -314,6 +322,33 @@ protected: }; enum { NumExprBits = NumStmtBits + 9 }; + class ConstantExprBitfields { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend class ConstantExpr; + + unsigned : NumExprBits; + + /// The kind of result that is trail-allocated. + unsigned ResultKind : 2; + + /// Kind of Result as defined by APValue::Kind + unsigned APValueKind : 4; + + /// When ResultKind == RSK_Int64. whether the trail-allocated integer is + /// signed. + unsigned IsUnsigned : 1; + + /// When ResultKind == RSK_Int64. the BitWidth of the trail-allocated + /// integer. 7 bits because it is the minimal number of bit to represent a + /// value from 0 to 64 (the size of the trail-allocated number). + unsigned BitWidth : 7; + + /// When ResultKind == RSK_APValue. Wether the ASTContext will cleanup the + /// destructor on the trail-allocated APValue. + unsigned HasCleanup : 1; + }; + class PredefinedExprBitfields { friend class ASTStmtReader; friend class PredefinedExpr; @@ -343,19 +378,12 @@ protected: unsigned HasFoundDecl : 1; unsigned HadMultipleCandidates : 1; unsigned RefersToEnclosingVariableOrCapture : 1; + unsigned NonOdrUseReason : 2; /// The location of the declaration name itself. SourceLocation Loc; }; - enum APFloatSemantics { - IEEEhalf, - IEEEsingle, - IEEEdouble, - x87DoubleExtended, - IEEEquad, - PPCDoubleDouble - }; class FloatingLiteralBitfields { friend class FloatingLiteral; @@ -445,6 +473,7 @@ protected: enum { NumCallExprBits = 32 }; class MemberExprBitfields { + friend class ASTStmtReader; friend class MemberExpr; unsigned : NumExprBits; @@ -469,6 +498,11 @@ protected: /// was resolved from an overloaded set having size greater than 1. unsigned HadMultipleCandidates : 1; + /// Value of type NonOdrUseReason indicating why this MemberExpr does + /// not constitute an odr-use of the named declaration. Meaningful only + /// when naming a static member. + unsigned NonOdrUseReason : 2; + /// This is the location of the -> or . in the expression. SourceLocation OperatorLoc; }; @@ -521,6 +555,16 @@ protected: unsigned NumExprs; }; + class GenericSelectionExprBitfields { + friend class ASTStmtReader; + friend class GenericSelectionExpr; + + unsigned : NumExprBits; + + /// The location of the "_Generic". + SourceLocation GenericLoc; + }; + class PseudoObjectExprBitfields { friend class ASTStmtReader; // deserialization friend class PseudoObjectExpr; @@ -533,6 +577,17 @@ protected: unsigned ResultIndex : 32 - 8 - NumExprBits; }; + class SourceLocExprBitfields { + friend class ASTStmtReader; + friend class SourceLocExpr; + + unsigned : NumExprBits; + + /// The kind of source location builtin represented by the SourceLocExpr. + /// Ex. __builtin_LINE, __builtin_FUNCTION, ect. + unsigned Kind : 2; + }; + //===--- C++ Expression bitfields classes ---===// class CXXOperatorCallExprBitfields { @@ -902,6 +957,7 @@ protected: // Expressions ExprBitfields ExprBits; + ConstantExprBitfields ConstantExprBits; PredefinedExprBitfields PredefinedExprBits; DeclRefExprBitfields DeclRefExprBits; FloatingLiteralBitfields FloatingLiteralBits; @@ -916,7 +972,9 @@ protected: BinaryOperatorBitfields BinaryOperatorBits; InitListExprBitfields InitListExprBits; ParenListExprBitfields ParenListExprBits; + GenericSelectionExprBitfields GenericSelectionExprBits; PseudoObjectExprBitfields PseudoObjectExprBits; + SourceLocExprBitfields SourceLocExprBits; // C++ Expressions CXXOperatorCallExprBitfields CXXOperatorCallExprBits; @@ -976,38 +1034,31 @@ public: struct EmptyShell {}; protected: - /// Iterator for iterating over Stmt * arrays that contain only Expr * + /// Iterator for iterating over Stmt * arrays that contain only T *. /// /// This is needed because AST nodes use Stmt* arrays to store /// references to children (to be compatible with StmtIterator). - struct ExprIterator - : llvm::iterator_adaptor_base<ExprIterator, Stmt **, - std::random_access_iterator_tag, Expr *> { - ExprIterator() : iterator_adaptor_base(nullptr) {} - ExprIterator(Stmt **I) : iterator_adaptor_base(I) {} - - reference operator*() const { - assert((*I)->getStmtClass() >= firstExprConstant && - (*I)->getStmtClass() <= lastExprConstant); - return *reinterpret_cast<Expr **>(I); - } - }; + template<typename T, typename TPtr = T *, typename StmtPtr = Stmt *> + struct CastIterator + : llvm::iterator_adaptor_base<CastIterator<T, TPtr, StmtPtr>, StmtPtr *, + std::random_access_iterator_tag, TPtr> { + using Base = typename CastIterator::iterator_adaptor_base; - /// Const iterator for iterating over Stmt * arrays that contain only Expr * - struct ConstExprIterator - : llvm::iterator_adaptor_base<ConstExprIterator, const Stmt *const *, - std::random_access_iterator_tag, - const Expr *const> { - ConstExprIterator() : iterator_adaptor_base(nullptr) {} - ConstExprIterator(const Stmt *const *I) : iterator_adaptor_base(I) {} + CastIterator() : Base(nullptr) {} + CastIterator(StmtPtr *I) : Base(I) {} - reference operator*() const { - assert((*I)->getStmtClass() >= firstExprConstant && - (*I)->getStmtClass() <= lastExprConstant); - return *reinterpret_cast<const Expr *const *>(I); + typename Base::value_type operator*() const { + return cast_or_null<T>(*this->I); } }; + /// Const iterator for iterating over Stmt * arrays that contain only T *. + template <typename T> + using ConstCastIterator = CastIterator<T, const T *const, const Stmt *const>; + + using ExprIterator = CastIterator<Expr>; + using ConstExprIterator = ConstCastIterator<Expr>; + private: /// Whether statistic collection is enabled. static bool StatisticsEnabled; @@ -1017,12 +1068,19 @@ protected: explicit Stmt(StmtClass SC, EmptyShell) : Stmt(SC) {} public: + Stmt() = delete; + Stmt(const Stmt &) = delete; + Stmt(Stmt &&) = delete; + Stmt &operator=(const Stmt &) = delete; + Stmt &operator=(Stmt &&) = delete; + Stmt(StmtClass SC) { static_assert(sizeof(*this) <= 8, "changing bitfields changed sizeof(Stmt)"); static_assert(sizeof(*this) % alignof(void *) == 0, "Insufficient alignment!"); StmtBits.sClass = SC; + StmtBits.IsOMPStructuredBlock = false; if (StatisticsEnabled) Stmt::addStmtClass(SC); } @@ -1032,6 +1090,11 @@ public: const char *getStmtClassName() const; + bool isOMPStructuredBlock() const { return StmtBits.IsOMPStructuredBlock; } + void setIsOMPStructuredBlock(bool IsOMPStructuredBlock) { + StmtBits.IsOMPStructuredBlock = IsOMPStructuredBlock; + } + /// SourceLocation tokens are not useful in isolation - they are low level /// value objects created/interpreted by SourceManager. We assume AST /// clients will have a pointer to the respective SourceManager. @@ -1065,17 +1128,14 @@ public: StringRef NewlineSymbol = "\n", const ASTContext *Context = nullptr) const; + /// Pretty-prints in JSON format. + void printJson(raw_ostream &Out, PrinterHelper *Helper, + const PrintingPolicy &Policy, bool AddQuotes) const; + /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only /// works on systems with GraphViz (Mac OS X) or dot+gv installed. void viewAST() const; - /// Skip past any implicit AST nodes which might surround this - /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes. - Stmt *IgnoreImplicit(); - const Stmt *IgnoreImplicit() const { - return const_cast<Stmt *>(this)->IgnoreImplicit(); - } - /// Skip no-op (attributed, compound) container stmts and skip captured /// stmt at the top, if \a IgnoreCaptured is true. Stmt *IgnoreContainers(bool IgnoreCaptured = false); @@ -1178,6 +1238,11 @@ public: child_iterator(DG.end(), DG.end())); } + const_child_range children() const { + auto Children = const_cast<DeclStmt *>(this)->children(); + return const_child_range(Children); + } + using decl_iterator = DeclGroupRef::iterator; using const_decl_iterator = DeclGroupRef::const_iterator; using decl_range = llvm::iterator_range<decl_iterator>; @@ -1235,6 +1300,10 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// CompoundStmt - This represents a group of statements like { stmt stmt }. @@ -1280,11 +1349,6 @@ public: return !body_empty() ? body_begin()[size() - 1] : nullptr; } - void setLastStmt(Stmt *S) { - assert(!body_empty() && "setLastStmt"); - body_begin()[size() - 1] = S; - } - using const_body_iterator = Stmt *const *; using body_const_range = llvm::iterator_range<const_body_iterator>; @@ -1327,6 +1391,26 @@ public: return const_reverse_body_iterator(body_begin()); } + // Get the Stmt that StmtExpr would consider to be the result of this + // compound statement. This is used by StmtExpr to properly emulate the GCC + // compound expression extension, which ignores trailing NullStmts when + // getting the result of the expression. + // i.e. ({ 5;;; }) + // ^^ ignored + // If we don't find something that isn't a NullStmt, just return the last + // Stmt. + Stmt *getStmtExprResult() { + for (auto *B : llvm::reverse(body())) { + if (!isa<NullStmt>(B)) + return B; + } + return body_back(); + } + + const Stmt *getStmtExprResult() const { + return const_cast<CompoundStmt *>(this)->getStmtExprResult(); + } + SourceLocation getBeginLoc() const { return CompoundStmtBits.LBraceLoc; } SourceLocation getEndLoc() const { return RBraceLoc; } @@ -1539,6 +1623,12 @@ public: getTrailingObjects<Stmt *>() + numTrailingObjects(OverloadToken<Stmt *>())); } + + const_child_range children() const { + return const_child_range(getTrailingObjects<Stmt *>(), + getTrailingObjects<Stmt *>() + + numTrailingObjects(OverloadToken<Stmt *>())); + } }; class DefaultStmt : public SwitchCase { @@ -1570,6 +1660,10 @@ public: // Iterators child_range children() { return child_range(&SubStmt, &SubStmt + 1); } + + const_child_range children() const { + return const_child_range(&SubStmt, &SubStmt + 1); + } }; SourceLocation SwitchCase::getEndLoc() const { @@ -1588,21 +1682,44 @@ Stmt *SwitchCase::getSubStmt() { llvm_unreachable("SwitchCase is neither a CaseStmt nor a DefaultStmt!"); } +/// Represents a statement that could possibly have a value and type. This +/// covers expression-statements, as well as labels and attributed statements. +/// +/// Value statements have a special meaning when they are the last non-null +/// statement in a GNU statement expression, where they determine the value +/// of the statement expression. +class ValueStmt : public Stmt { +protected: + using Stmt::Stmt; + +public: + const Expr *getExprStmt() const; + Expr *getExprStmt() { + const ValueStmt *ConstThis = this; + return const_cast<Expr*>(ConstThis->getExprStmt()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() >= firstValueStmtConstant && + T->getStmtClass() <= lastValueStmtConstant; + } +}; + /// LabelStmt - Represents a label, which has a substatement. For example: /// foo: return; -class LabelStmt : public Stmt { +class LabelStmt : public ValueStmt { LabelDecl *TheDecl; Stmt *SubStmt; public: /// Build a label statement. LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt) - : Stmt(LabelStmtClass), TheDecl(D), SubStmt(substmt) { + : ValueStmt(LabelStmtClass), TheDecl(D), SubStmt(substmt) { setIdentLoc(IL); } /// Build an empty label statement. - explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) {} + explicit LabelStmt(EmptyShell Empty) : ValueStmt(LabelStmtClass, Empty) {} SourceLocation getIdentLoc() const { return LabelStmtBits.IdentLoc; } void setIdentLoc(SourceLocation L) { LabelStmtBits.IdentLoc = L; } @@ -1621,6 +1738,10 @@ public: child_range children() { return child_range(&SubStmt, &SubStmt + 1); } + const_child_range children() const { + return const_child_range(&SubStmt, &SubStmt + 1); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == LabelStmtClass; } @@ -1631,7 +1752,7 @@ public: /// Represents an attribute applied to a statement. For example: /// [[omp::for(...)]] for (...) { ... } class AttributedStmt final - : public Stmt, + : public ValueStmt, private llvm::TrailingObjects<AttributedStmt, const Attr *> { friend class ASTStmtReader; friend TrailingObjects; @@ -1640,14 +1761,14 @@ class AttributedStmt final AttributedStmt(SourceLocation Loc, ArrayRef<const Attr *> Attrs, Stmt *SubStmt) - : Stmt(AttributedStmtClass), SubStmt(SubStmt) { + : ValueStmt(AttributedStmtClass), SubStmt(SubStmt) { AttributedStmtBits.NumAttrs = Attrs.size(); AttributedStmtBits.AttrLoc = Loc; std::copy(Attrs.begin(), Attrs.end(), getAttrArrayPtr()); } explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs) - : Stmt(AttributedStmtClass, Empty) { + : ValueStmt(AttributedStmtClass, Empty) { AttributedStmtBits.NumAttrs = NumAttrs; AttributedStmtBits.AttrLoc = SourceLocation{}; std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr); @@ -1678,6 +1799,10 @@ public: child_range children() { return child_range(&SubStmt, &SubStmt + 1); } + const_child_range children() const { + return const_child_range(&SubStmt, &SubStmt + 1); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == AttributedStmtClass; } @@ -1877,6 +2002,12 @@ public: numTrailingObjects(OverloadToken<Stmt *>())); } + const_child_range children() const { + return const_child_range(getTrailingObjects<Stmt *>(), + getTrailingObjects<Stmt *>() + + numTrailingObjects(OverloadToken<Stmt *>())); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == IfStmtClass; } @@ -2054,6 +2185,12 @@ public: numTrailingObjects(OverloadToken<Stmt *>())); } + const_child_range children() const { + return const_child_range(getTrailingObjects<Stmt *>(), + getTrailingObjects<Stmt *>() + + numTrailingObjects(OverloadToken<Stmt *>())); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == SwitchStmtClass; } @@ -2179,6 +2316,12 @@ public: getTrailingObjects<Stmt *>() + numTrailingObjects(OverloadToken<Stmt *>())); } + + const_child_range children() const { + return const_child_range(getTrailingObjects<Stmt *>(), + getTrailingObjects<Stmt *>() + + numTrailingObjects(OverloadToken<Stmt *>())); + } }; /// DoStmt - This represents a 'do/while' stmt. @@ -2229,6 +2372,10 @@ public: child_range children() { return child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); } + + const_child_range children() const { + return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); + } }; /// ForStmt - This represents a 'for (init;cond;inc)' stmt. Note that any of @@ -2298,6 +2445,10 @@ public: child_range children() { return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); } + + const_child_range children() const { + return const_child_range(&SubExprs[0], &SubExprs[0] + END_EXPR); + } }; /// GotoStmt - This represents a direct goto. @@ -2333,6 +2484,10 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// IndirectGotoStmt - This represents an indirect goto. @@ -2378,6 +2533,10 @@ public: // Iterators child_range children() { return child_range(&Target, &Target + 1); } + + const_child_range children() const { + return const_child_range(&Target, &Target + 1); + } }; /// ContinueStmt - This represents a continue. @@ -2404,6 +2563,10 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// BreakStmt - This represents a break. @@ -2430,6 +2593,10 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// ReturnStmt - This represents a return, optionally of an expression: @@ -2514,6 +2681,12 @@ public: return child_range(&RetExpr, &RetExpr + 1); return child_range(child_iterator(), child_iterator()); } + + const_child_range children() const { + if (RetExpr) + return const_child_range(&RetExpr, &RetExpr + 1); + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// AsmStmt is the base class for GCCAsmStmt and MSAsmStmt. @@ -2669,6 +2842,10 @@ public: child_range children() { return child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs); } + + const_child_range children() const { + return const_child_range(&Exprs[0], &Exprs[0] + NumOutputs + NumInputs); + } }; /// This represents a GCC inline-assembly statement extension. @@ -2682,13 +2859,15 @@ class GCCAsmStmt : public AsmStmt { StringLiteral **Constraints = nullptr; StringLiteral **Clobbers = nullptr; IdentifierInfo **Names = nullptr; + unsigned NumLabels = 0; public: GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, unsigned numoutputs, unsigned numinputs, IdentifierInfo **names, StringLiteral **constraints, Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, - StringLiteral **clobbers, SourceLocation rparenloc); + StringLiteral **clobbers, unsigned numlabels, + SourceLocation rparenloc); /// Build an empty inline-assembly statement. explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty) {} @@ -2813,6 +2992,51 @@ public: return const_cast<GCCAsmStmt*>(this)->getInputExpr(i); } + //===--- Labels ---===// + + bool isAsmGoto() const { + return NumLabels > 0; + } + + unsigned getNumLabels() const { + return NumLabels; + } + + IdentifierInfo *getLabelIdentifier(unsigned i) const { + return Names[i + NumInputs]; + } + + AddrLabelExpr *getLabelExpr(unsigned i) const; + StringRef getLabelName(unsigned i) const; + using labels_iterator = CastIterator<AddrLabelExpr>; + using const_labels_iterator = ConstCastIterator<AddrLabelExpr>; + using labels_range = llvm::iterator_range<labels_iterator>; + using labels_const_range = llvm::iterator_range<const_labels_iterator>; + + labels_iterator begin_labels() { + return &Exprs[0] + NumInputs; + } + + labels_iterator end_labels() { + return &Exprs[0] + NumInputs + NumLabels; + } + + labels_range labels() { + return labels_range(begin_labels(), end_labels()); + } + + const_labels_iterator begin_labels() const { + return &Exprs[0] + NumInputs; + } + + const_labels_iterator end_labels() const { + return &Exprs[0] + NumInputs + NumLabels; + } + + labels_const_range labels() const { + return labels_const_range(begin_labels(), end_labels()); + } + private: void setOutputsAndInputsAndClobbers(const ASTContext &C, IdentifierInfo **Names, @@ -2820,6 +3044,7 @@ private: Stmt **Exprs, unsigned NumOutputs, unsigned NumInputs, + unsigned NumLabels, StringLiteral **Clobbers, unsigned NumClobbers); @@ -2945,6 +3170,10 @@ public: child_range children() { return child_range(&Exprs[0], &Exprs[NumInputs + NumOutputs]); } + + const_child_range children() const { + return const_child_range(&Exprs[0], &Exprs[NumInputs + NumOutputs]); + } }; class SEHExceptStmt : public Stmt { @@ -2982,6 +3211,10 @@ public: return child_range(Children, Children+2); } + const_child_range children() const { + return const_child_range(Children, Children + 2); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == SEHExceptStmtClass; } @@ -3013,6 +3246,10 @@ public: return child_range(&Block,&Block+1); } + const_child_range children() const { + return const_child_range(&Block, &Block + 1); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == SEHFinallyStmtClass; } @@ -3061,6 +3298,10 @@ public: return child_range(Children, Children+2); } + const_child_range children() const { + return const_child_range(Children, Children + 2); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == SEHTryStmtClass; } @@ -3091,6 +3332,10 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } + + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } }; /// This captures a statement into a function. For example, the following @@ -3311,6 +3556,8 @@ public: } child_range children(); + + const_child_range children() const; }; } // namespace clang |
