diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 3fe9054b76f3..6bd07af1affa 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -1,4 +1,4 @@ -//===--- Stmt.h - Classes for representing statements -----------*- C++ -*-===// +//===- Stmt.h - Classes for representing statements -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -22,34 +22,40 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include +#include +#include +#include #include namespace llvm { - class FoldingSetNodeID; -} + +class FoldingSetNodeID; + +} // namespace llvm namespace clang { - class ASTContext; - class Attr; - class CapturedDecl; - class Decl; - class Expr; - class IdentifierInfo; - class LabelDecl; - class ODRHash; - class ParmVarDecl; - class PrinterHelper; - struct PrintingPolicy; - class QualType; - class RecordDecl; - class SourceManager; - class StringLiteral; - class SwitchStmt; - class Token; - class VarDecl; + +class ASTContext; +class Attr; +class CapturedDecl; +class Decl; +class Expr; +class LabelDecl; +class ODRHash; +class PrinterHelper; +struct PrintingPolicy; +class RecordDecl; +class SourceManager; +class StringLiteral; +class Token; +class VarDecl; //===----------------------------------------------------------------------===// // AST classes for statements. @@ -72,9 +78,13 @@ public: // Make vanilla 'new' and 'delete' illegal for Stmts. protected: + friend class ASTStmtReader; + friend class ASTStmtWriter; + void *operator new(size_t bytes) noexcept { llvm_unreachable("Stmts cannot be allocated with regular 'new'."); } + void operator delete(void *data) noexcept { llvm_unreachable("Stmts cannot be released with regular 'delete'."); } @@ -89,6 +99,7 @@ protected: class CompoundStmtBitfields { friend class CompoundStmt; + unsigned : NumStmtBits; unsigned NumStmts : 32 - NumStmtBits; @@ -96,34 +107,36 @@ protected: class IfStmtBitfields { friend class IfStmt; + unsigned : NumStmtBits; unsigned IsConstexpr : 1; }; class ExprBitfields { - friend class Expr; - friend class DeclRefExpr; // computeDependence - friend class InitListExpr; // ctor - friend class DesignatedInitExpr; // ctor - friend class BlockDeclRefExpr; // ctor friend class ASTStmtReader; // deserialization - friend class CXXNewExpr; // ctor - friend class DependentScopeDeclRefExpr; // ctor - friend class CXXConstructExpr; // ctor + friend class AtomicExpr; // ctor + friend class BlockDeclRefExpr; // ctor friend class CallExpr; // ctor - friend class OffsetOfExpr; // ctor - friend class ObjCMessageExpr; // ctor + friend class CXXConstructExpr; // ctor + friend class CXXDependentScopeMemberExpr; // ctor + friend class CXXNewExpr; // ctor + friend class CXXUnresolvedConstructExpr; // ctor + friend class DeclRefExpr; // computeDependence + friend class DependentScopeDeclRefExpr; // ctor + friend class DesignatedInitExpr; // ctor + friend class Expr; + friend class InitListExpr; // ctor friend class ObjCArrayLiteral; // ctor friend class ObjCDictionaryLiteral; // ctor - friend class ShuffleVectorExpr; // ctor - friend class ParenListExpr; // ctor - friend class CXXUnresolvedConstructExpr; // ctor - friend class CXXDependentScopeMemberExpr; // ctor - friend class OverloadExpr; // ctor - friend class PseudoObjectExpr; // ctor - friend class AtomicExpr; // ctor + friend class ObjCMessageExpr; // ctor + friend class OffsetOfExpr; // ctor friend class OpaqueValueExpr; // ctor + friend class OverloadExpr; // ctor + friend class ParenListExpr; // ctor + friend class PseudoObjectExpr; // ctor + friend class ShuffleVectorExpr; // ctor + unsigned : NumStmtBits; unsigned ValueKind : 2; @@ -137,6 +150,7 @@ protected: class CharacterLiteralBitfields { friend class CharacterLiteral; + unsigned : NumExprBits; unsigned Kind : 3; @@ -153,6 +167,7 @@ protected: class FloatingLiteralBitfields { friend class FloatingLiteral; + unsigned : NumExprBits; unsigned Semantics : 3; // Provides semantics for APFloat construction @@ -161,6 +176,7 @@ protected: class UnaryExprOrTypeTraitExprBitfields { friend class UnaryExprOrTypeTraitExpr; + unsigned : NumExprBits; unsigned Kind : 2; @@ -168,8 +184,9 @@ protected: }; class DeclRefExprBitfields { - friend class DeclRefExpr; friend class ASTStmtReader; // deserialization + friend class DeclRefExpr; + unsigned : NumExprBits; unsigned HasQualifier : 1; @@ -181,6 +198,7 @@ protected: class CastExprBitfields { friend class CastExpr; + unsigned : NumExprBits; unsigned Kind : 6; @@ -189,14 +207,15 @@ protected: class CallExprBitfields { friend class CallExpr; + unsigned : NumExprBits; unsigned NumPreArgs : 1; }; class ExprWithCleanupsBitfields { - friend class ExprWithCleanups; friend class ASTStmtReader; // deserialization + friend class ExprWithCleanups; unsigned : NumExprBits; @@ -207,8 +226,8 @@ protected: }; class PseudoObjectExprBitfields { - friend class PseudoObjectExpr; friend class ASTStmtReader; // deserialization + friend class PseudoObjectExpr; unsigned : NumExprBits; @@ -220,6 +239,7 @@ protected: class ObjCIndirectCopyRestoreExprBitfields { friend class ObjCIndirectCopyRestoreExpr; + unsigned : NumExprBits; unsigned ShouldCopy : 1; @@ -236,9 +256,9 @@ protected: }; class TypeTraitExprBitfields { - friend class TypeTraitExpr; friend class ASTStmtReader; friend class ASTStmtWriter; + friend class TypeTraitExpr; unsigned : NumExprBits; @@ -280,9 +300,6 @@ protected: CoawaitExprBitfields CoawaitBits; }; - friend class ASTStmtReader; - friend class ASTStmtWriter; - public: // Only allow allocation of Stmts using the allocator in ASTContext // or by doing a placement new. @@ -305,7 +322,7 @@ public: /// \brief A placeholder type used to construct an empty shell of a /// type, that will be filled in later (e.g., by some /// de-serialization). - struct EmptyShell { }; + struct EmptyShell {}; protected: /// Iterator for iterating over Stmt * arrays that contain only Expr * @@ -361,6 +378,7 @@ public: StmtClass getStmtClass() const { return static_cast(StmtBits.sClass); } + const char *getStmtClassName() const; /// SourceLocation tokens are not useful in isolation - they are low level @@ -419,11 +437,11 @@ public: /// Child Iterators: All subclasses must implement 'children' /// to permit easy iteration over the substatements/subexpessions of an /// AST node. This permits easy iteration over all nodes in the AST. - typedef StmtIterator child_iterator; - typedef ConstStmtIterator const_child_iterator; + using child_iterator = StmtIterator; + using const_child_iterator = ConstStmtIterator; - typedef llvm::iterator_range child_range; - typedef llvm::iterator_range const_child_range; + using child_range = llvm::iterator_range; + using const_child_range = llvm::iterator_range; child_range children(); const_child_range children() const { @@ -466,18 +484,16 @@ public: /// expressions. For example, CompoundStmt mixes statements, expressions /// and declarations (variables, types). Another example is ForStmt, where /// the first statement can be an expression or a declaration. -/// class DeclStmt : public Stmt { DeclGroupRef DG; SourceLocation StartLoc, EndLoc; public: - DeclStmt(DeclGroupRef dg, SourceLocation startLoc, - SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg), - StartLoc(startLoc), EndLoc(endLoc) {} + DeclStmt(DeclGroupRef dg, SourceLocation startLoc, SourceLocation endLoc) + : Stmt(DeclStmtClass), DG(dg), StartLoc(startLoc), EndLoc(endLoc) {} /// \brief Build an empty declaration statement. - explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) { } + explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) {} /// isSingleDecl - This method returns true if this DeclStmt refers /// to a single Decl. @@ -510,10 +526,10 @@ public: child_iterator(DG.end(), DG.end())); } - typedef DeclGroupRef::iterator decl_iterator; - typedef DeclGroupRef::const_iterator const_decl_iterator; - typedef llvm::iterator_range decl_range; - typedef llvm::iterator_range decl_const_range; + using decl_iterator = DeclGroupRef::iterator; + using const_decl_iterator = DeclGroupRef::const_iterator; + using decl_range = llvm::iterator_range; + using decl_const_range = llvm::iterator_range; decl_range decls() { return decl_range(decl_begin(), decl_end()); } decl_const_range decls() const { @@ -524,10 +540,12 @@ public: const_decl_iterator decl_begin() const { return DG.begin(); } const_decl_iterator decl_end() const { return DG.end(); } - typedef std::reverse_iterator reverse_decl_iterator; + using reverse_decl_iterator = std::reverse_iterator; + reverse_decl_iterator decl_rbegin() { return reverse_decl_iterator(decl_end()); } + reverse_decl_iterator decl_rend() { return reverse_decl_iterator(decl_begin()); } @@ -543,15 +561,18 @@ class NullStmt : public Stmt { /// #define CALL(x) /// CALL(0); /// @endcode - bool HasLeadingEmptyMacro; + bool HasLeadingEmptyMacro = false; + public: + friend class ASTStmtReader; + friend class ASTStmtWriter; + NullStmt(SourceLocation L, bool hasLeadingEmptyMacro = false) - : Stmt(NullStmtClass), SemiLoc(L), - HasLeadingEmptyMacro(hasLeadingEmptyMacro) {} + : Stmt(NullStmtClass), SemiLoc(L), + HasLeadingEmptyMacro(hasLeadingEmptyMacro) {} /// \brief Build an empty null statement. - explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty), - HasLeadingEmptyMacro(false) { } + explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) {} SourceLocation getSemiLoc() const { return SemiLoc; } void setSemiLoc(SourceLocation L) { SemiLoc = L; } @@ -568,32 +589,27 @@ public: child_range children() { return child_range(child_iterator(), child_iterator()); } - - friend class ASTStmtReader; - friend class ASTStmtWriter; }; /// CompoundStmt - This represents a group of statements like { stmt stmt }. -/// class CompoundStmt : public Stmt { - Stmt** Body; - SourceLocation LBraceLoc, RBraceLoc; - friend class ASTStmtReader; + Stmt** Body = nullptr; + SourceLocation LBraceLoc, RBraceLoc; + public: CompoundStmt(const ASTContext &C, ArrayRef Stmts, SourceLocation LB, SourceLocation RB); // \brief Build an empty compound statement with a location. explicit CompoundStmt(SourceLocation Loc) - : Stmt(CompoundStmtClass), Body(nullptr), LBraceLoc(Loc), RBraceLoc(Loc) { + : Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(Loc) { CompoundStmtBits.NumStmts = 0; } // \brief Build an empty compound statement. - explicit CompoundStmt(EmptyShell Empty) - : Stmt(CompoundStmtClass, Empty), Body(nullptr) { + explicit CompoundStmt(EmptyShell Empty) : Stmt(CompoundStmtClass, Empty) { CompoundStmtBits.NumStmts = 0; } @@ -602,8 +618,8 @@ public: bool body_empty() const { return CompoundStmtBits.NumStmts == 0; } unsigned size() const { return CompoundStmtBits.NumStmts; } - typedef Stmt** body_iterator; - typedef llvm::iterator_range body_range; + using body_iterator = Stmt **; + using body_range = llvm::iterator_range; body_range body() { return body_range(body_begin(), body_end()); } body_iterator body_begin() { return Body; } @@ -616,31 +632,36 @@ public: Body[size()-1] = S; } - typedef Stmt* const * const_body_iterator; - typedef llvm::iterator_range body_const_range; + using const_body_iterator = Stmt* const *; + using body_const_range = llvm::iterator_range; body_const_range body() const { return body_const_range(body_begin(), body_end()); } + const_body_iterator body_begin() const { return Body; } const_body_iterator body_end() const { return Body + size(); } + const Stmt *body_front() const { return !body_empty() ? Body[0] : nullptr; } + const Stmt *body_back() const { return !body_empty() ? Body[size() - 1] : nullptr; } - typedef std::reverse_iterator reverse_body_iterator; + using reverse_body_iterator = std::reverse_iterator; + reverse_body_iterator body_rbegin() { return reverse_body_iterator(body_end()); } + reverse_body_iterator body_rend() { return reverse_body_iterator(body_begin()); } - typedef std::reverse_iterator - const_reverse_body_iterator; + using const_reverse_body_iterator = + std::reverse_iterator; const_reverse_body_iterator body_rbegin() const { return const_reverse_body_iterator(body_end()); @@ -676,16 +697,14 @@ class SwitchCase : public Stmt { protected: // A pointer to the following CaseStmt or DefaultStmt class, // used by SwitchStmt. - SwitchCase *NextSwitchCase; + SwitchCase *NextSwitchCase = nullptr; SourceLocation KeywordLoc; SourceLocation ColonLoc; SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc) - : Stmt(SC), NextSwitchCase(nullptr), KeywordLoc(KWLoc), ColonLoc(ColonLoc) { - } + : Stmt(SC), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {} - SwitchCase(StmtClass SC, EmptyShell) - : Stmt(SC), NextSwitchCase(nullptr) {} + SwitchCase(StmtClass SC, EmptyShell) : Stmt(SC) {} public: const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; } @@ -718,6 +737,7 @@ class CaseStmt : public SwitchCase { enum { LHS, RHS, SUBSTMT, END_EXPR }; Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for // GNU "case 1 ... 4" extension + public: CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc, SourceLocation ellipsisLoc, SourceLocation colonLoc) @@ -729,7 +749,7 @@ public: } /// \brief Build an empty switch case statement. - explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) { } + explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) {} SourceLocation getCaseLoc() const { return KeywordLoc; } void setCaseLoc(SourceLocation L) { KeywordLoc = L; } @@ -745,9 +765,11 @@ public: const Expr *getLHS() const { return reinterpret_cast(SubExprs[LHS]); } + const Expr *getRHS() const { return reinterpret_cast(SubExprs[RHS]); } + const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; } void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; } @@ -755,6 +777,7 @@ public: void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast(Val); } SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { // Handle deeply nested case statements with iteration instead of recursion. const CaseStmt *CS = this; @@ -776,13 +799,14 @@ public: class DefaultStmt : public SwitchCase { Stmt* SubStmt; + public: DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) : SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {} /// \brief Build an empty default statement. explicit DefaultStmt(EmptyShell Empty) - : SwitchCase(DefaultStmtClass, Empty) { } + : SwitchCase(DefaultStmtClass, Empty) {} Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } @@ -812,7 +836,6 @@ inline SourceLocation SwitchCase::getLocEnd() const { /// LabelStmt - Represents a label, which has a substatement. For example: /// foo: return; -/// class LabelStmt : public Stmt { SourceLocation IdentLoc; LabelDecl *TheDecl; @@ -827,7 +850,7 @@ public: } // \brief Build an empty label statement. - explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { } + explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) {} SourceLocation getIdentLoc() const { return IdentLoc; } LabelDecl *getDecl() const { return TheDecl; } @@ -848,19 +871,17 @@ public: } }; - /// \brief Represents an attribute applied to a statement. /// /// Represents an attribute applied to a statement. For example: /// [[omp::for(...)]] for (...) { ... } -/// class AttributedStmt : public Stmt { + friend class ASTStmtReader; + Stmt *SubStmt; SourceLocation AttrLoc; unsigned NumAttrs; - friend class ASTStmtReader; - AttributedStmt(SourceLocation Loc, ArrayRef Attrs, Stmt *SubStmt) : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc), NumAttrs(Attrs.size()) { @@ -882,6 +903,7 @@ class AttributedStmt : public Stmt { public: static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc, ArrayRef Attrs, Stmt *SubStmt); + // \brief Build an empty attributed statement. static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs); @@ -889,6 +911,7 @@ public: ArrayRef getAttrs() const { return llvm::makeArrayRef(getAttrArrayPtr(), NumAttrs); } + Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } @@ -902,9 +925,7 @@ public: } }; - /// IfStmt - This represents an if/then/else. -/// class IfStmt : public Stmt { enum { INIT, VAR, COND, THEN, ELSE, END_EXPR }; Stmt* SubExprs[END_EXPR]; @@ -919,7 +940,7 @@ public: Stmt *elsev = nullptr); /// \brief Build an empty if/then/else statement - explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { } + explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) {} /// \brief Retrieve the variable declared in this "if" statement, if any. /// @@ -963,6 +984,7 @@ public: bool isObjCAvailabilityCheck() const; SourceLocation getLocStart() const LLVM_READONLY { return IfLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { if (SubExprs[ELSE]) return SubExprs[ELSE]->getLocEnd(); @@ -982,11 +1004,11 @@ public: }; /// SwitchStmt - This represents a 'switch' stmt. -/// class SwitchStmt : public Stmt { SourceLocation SwitchLoc; enum { INIT, VAR, COND, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; + // This points to a linked list of case and default statements and, if the // SwitchStmt is a switch on an enum value, records whether all the enum // values were covered by CaseStmts. The coverage information value is meant @@ -997,7 +1019,7 @@ public: SwitchStmt(const ASTContext &C, Stmt *Init, VarDecl *Var, Expr *cond); /// \brief Build a empty switch statement. - explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { } + explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) {} /// \brief Retrieve the variable declared in this "switch" statement, if any. /// @@ -1040,6 +1062,7 @@ public: SubExprs[BODY] = S; SwitchLoc = SL; } + void addSwitchCase(SwitchCase *SC) { assert(!SC->getNextSwitchCase() && "case/default already added to a switch"); @@ -1056,6 +1079,7 @@ public: bool isAllEnumCasesCovered() const { return FirstCase.getInt(); } SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SubExprs[BODY] ? SubExprs[BODY]->getLocEnd() : SubExprs[COND]->getLocEnd(); } @@ -1070,19 +1094,18 @@ public: } }; - /// WhileStmt - This represents a 'while' stmt. -/// class WhileStmt : public Stmt { SourceLocation WhileLoc; enum { VAR, COND, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; + public: WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL); /// \brief Build an empty while statement. - explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { } + explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) {} /// \brief Retrieve the variable declared in this "while" statement, if any. /// @@ -1112,6 +1135,7 @@ public: void setWhileLoc(SourceLocation L) { WhileLoc = L; } SourceLocation getLocStart() const LLVM_READONLY { return WhileLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SubExprs[BODY]->getLocEnd(); } @@ -1127,7 +1151,6 @@ public: }; /// DoStmt - This represents a 'do/while' stmt. -/// class DoStmt : public Stmt { SourceLocation DoLoc; enum { BODY, COND, END_EXPR }; @@ -1144,7 +1167,7 @@ public: } /// \brief Build an empty do-while statement. - explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) { } + explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) {} Expr *getCond() { return reinterpret_cast(SubExprs[COND]); } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} @@ -1174,11 +1197,9 @@ public: } }; - /// ForStmt - This represents a 'for (init;cond;inc)' stmt. Note that any of /// the init/cond/inc parts of the ForStmt will be null if they were not /// specified in the source. -/// class ForStmt : public Stmt { SourceLocation ForLoc; enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR }; @@ -1191,7 +1212,7 @@ public: SourceLocation RP); /// \brief Build an empty for statement. - explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { } + explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) {} Stmt *getInit() { return SubExprs[INIT]; } @@ -1234,6 +1255,7 @@ public: void setRParenLoc(SourceLocation L) { RParenLoc = L; } SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return SubExprs[BODY]->getLocEnd(); } @@ -1249,17 +1271,17 @@ public: }; /// GotoStmt - This represents a direct goto. -/// class GotoStmt : public Stmt { LabelDecl *Label; SourceLocation GotoLoc; SourceLocation LabelLoc; + public: GotoStmt(LabelDecl *label, SourceLocation GL, SourceLocation LL) - : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {} + : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {} /// \brief Build an empty goto statement. - explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { } + explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) {} LabelDecl *getLabel() const { return Label; } void setLabel(LabelDecl *D) { Label = D; } @@ -1283,11 +1305,11 @@ public: }; /// IndirectGotoStmt - This represents an indirect goto. -/// class IndirectGotoStmt : public Stmt { SourceLocation GotoLoc; SourceLocation StarLoc; Stmt *Target; + public: IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc, Expr *target) @@ -1296,7 +1318,7 @@ public: /// \brief Build an empty indirect goto statement. explicit IndirectGotoStmt(EmptyShell Empty) - : Stmt(IndirectGotoStmtClass, Empty) { } + : Stmt(IndirectGotoStmtClass, Empty) {} void setGotoLoc(SourceLocation L) { GotoLoc = L; } SourceLocation getGotoLoc() const { return GotoLoc; } @@ -1325,16 +1347,15 @@ public: child_range children() { return child_range(&Target, &Target+1); } }; - /// ContinueStmt - This represents a continue. -/// class ContinueStmt : public Stmt { SourceLocation ContinueLoc; + public: ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {} /// \brief Build an empty continue statement. - explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) { } + explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) {} SourceLocation getContinueLoc() const { return ContinueLoc; } void setContinueLoc(SourceLocation L) { ContinueLoc = L; } @@ -1353,7 +1374,6 @@ public: }; /// BreakStmt - This represents a break. -/// class BreakStmt : public Stmt { SourceLocation BreakLoc; @@ -1364,7 +1384,7 @@ public: } /// \brief Build an empty break statement. - explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { } + explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) {} SourceLocation getBreakLoc() const { return BreakLoc; } void setBreakLoc(SourceLocation L) { BreakLoc = L; } @@ -1382,7 +1402,6 @@ public: } }; - /// ReturnStmt - This represents a return, optionally of an expression: /// return; /// return 4; @@ -1391,7 +1410,6 @@ public: /// return a value, and it allows returning a value in functions declared to /// return void. We explicitly model this in the AST, which means you can't /// depend on the return type of the function and the presence of an argument. -/// class ReturnStmt : public Stmt { SourceLocation RetLoc; Stmt *RetExpr; @@ -1405,7 +1423,7 @@ public: NRVOCandidate(NRVOCandidate) {} /// \brief Build an empty return expression. - explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { } + explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) {} const Expr *getRetValue() const; Expr *getRetValue(); @@ -1423,6 +1441,7 @@ public: void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; } SourceLocation getLocStart() const LLVM_READONLY { return RetLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RetExpr ? RetExpr->getLocEnd() : RetLoc; } @@ -1439,10 +1458,12 @@ public: }; /// AsmStmt is the base class for GCCAsmStmt and MSAsmStmt. -/// class AsmStmt : public Stmt { protected: + friend class ASTStmtReader; + SourceLocation AsmLoc; + /// \brief True if the assembly statement does not have any input or output /// operands. bool IsSimple; @@ -1455,19 +1476,17 @@ protected: unsigned NumInputs; unsigned NumClobbers; - Stmt **Exprs; + Stmt **Exprs = nullptr; AsmStmt(StmtClass SC, SourceLocation asmloc, bool issimple, bool isvolatile, - unsigned numoutputs, unsigned numinputs, unsigned numclobbers) : - Stmt (SC), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile), - NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) { } - - friend class ASTStmtReader; + unsigned numoutputs, unsigned numinputs, unsigned numclobbers) + : Stmt (SC), AsmLoc(asmloc), IsSimple(issimple), IsVolatile(isvolatile), + NumOutputs(numoutputs), NumInputs(numinputs), + NumClobbers(numclobbers) {} public: /// \brief Build an empty inline-assembly statement. - explicit AsmStmt(StmtClass SC, EmptyShell Empty) : - Stmt(SC, Empty), Exprs(nullptr) { } + explicit AsmStmt(StmtClass SC, EmptyShell Empty) : Stmt(SC, Empty) {} SourceLocation getAsmLoc() const { return AsmLoc; } void setAsmLoc(SourceLocation L) { AsmLoc = L; } @@ -1530,10 +1549,10 @@ public: // Input expr iterators. - typedef ExprIterator inputs_iterator; - typedef ConstExprIterator const_inputs_iterator; - typedef llvm::iterator_range inputs_range; - typedef llvm::iterator_range inputs_const_range; + using inputs_iterator = ExprIterator; + using const_inputs_iterator = ConstExprIterator; + using inputs_range = llvm::iterator_range; + using inputs_const_range = llvm::iterator_range; inputs_iterator begin_inputs() { return &Exprs[0] + NumOutputs; @@ -1559,17 +1578,19 @@ public: // Output expr iterators. - typedef ExprIterator outputs_iterator; - typedef ConstExprIterator const_outputs_iterator; - typedef llvm::iterator_range outputs_range; - typedef llvm::iterator_range outputs_const_range; + using outputs_iterator = ExprIterator; + using const_outputs_iterator = ConstExprIterator; + using outputs_range = llvm::iterator_range; + using outputs_const_range = llvm::iterator_range; outputs_iterator begin_outputs() { return &Exprs[0]; } + outputs_iterator end_outputs() { return &Exprs[0] + NumOutputs; } + outputs_range outputs() { return outputs_range(begin_outputs(), end_outputs()); } @@ -1577,9 +1598,11 @@ public: const_outputs_iterator begin_outputs() const { return &Exprs[0]; } + const_outputs_iterator end_outputs() const { return &Exprs[0] + NumOutputs; } + outputs_const_range outputs() const { return outputs_const_range(begin_outputs(), end_outputs()); } @@ -1590,17 +1613,16 @@ public: }; /// This represents a GCC inline-assembly statement extension. -/// class GCCAsmStmt : public AsmStmt { + friend class ASTStmtReader; + SourceLocation RParenLoc; StringLiteral *AsmStr; // FIXME: If we wanted to, we could allocate all of these in one big array. - StringLiteral **Constraints; - StringLiteral **Clobbers; - IdentifierInfo **Names; - - friend class ASTStmtReader; + StringLiteral **Constraints = nullptr; + StringLiteral **Clobbers = nullptr; + IdentifierInfo **Names = nullptr; public: GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple, @@ -1610,8 +1632,7 @@ public: StringLiteral **clobbers, SourceLocation rparenloc); /// \brief Build an empty inline-assembly statement. - explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty), - Constraints(nullptr), Clobbers(nullptr), Names(nullptr) { } + explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty) {} SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } @@ -1631,6 +1652,7 @@ public: String, // String in .ll asm string form, "$" -> "$$" and "%%" -> "%". Operand // Operand reference, with optional modifier %c4. }; + private: Kind MyKind; std::string Str; @@ -1638,13 +1660,13 @@ public: // Source range for operand references. CharSourceRange Range; + public: AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {} AsmStringPiece(unsigned OpNo, const std::string &S, SourceLocation Begin, SourceLocation End) - : MyKind(Operand), Str(S), OperandNo(OpNo), - Range(CharSourceRange::getCharRange(Begin, End)) { - } + : MyKind(Operand), Str(S), OperandNo(OpNo), + Range(CharSourceRange::getCharRange(Begin, End)) {} bool isString() const { return MyKind == String; } bool isOperand() const { return MyKind == Operand; } @@ -1745,8 +1767,8 @@ private: unsigned NumInputs, StringLiteral **Clobbers, unsigned NumClobbers); -public: +public: //===--- Other ---===// /// getNamedOperand - Given a symbolic operand reference like %[foo], @@ -1755,6 +1777,7 @@ public: int getNamedOperand(StringRef SymbolicName) const; StringRef getClobber(unsigned i) const; + StringLiteral *getClobberStringLiteral(unsigned i) { return Clobbers[i]; } const StringLiteral *getClobberStringLiteral(unsigned i) const { return Clobbers[i]; @@ -1769,18 +1792,17 @@ public: }; /// This represents a Microsoft inline-assembly statement extension. -/// class MSAsmStmt : public AsmStmt { + friend class ASTStmtReader; + SourceLocation LBraceLoc, EndLoc; StringRef AsmStr; - unsigned NumAsmToks; + unsigned NumAsmToks = 0; - Token *AsmToks; - StringRef *Constraints; - StringRef *Clobbers; - - friend class ASTStmtReader; + Token *AsmToks = nullptr; + StringRef *Constraints = nullptr; + StringRef *Clobbers = nullptr; public: MSAsmStmt(const ASTContext &C, SourceLocation asmloc, @@ -1791,8 +1813,7 @@ public: ArrayRef clobbers, SourceLocation endloc); /// \brief Build an empty MS-style inline-assembly statement. - explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty), - NumAsmToks(0), AsmToks(nullptr), Constraints(nullptr), Clobbers(nullptr) { } + explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty) {} SourceLocation getLBraceLoc() const { return LBraceLoc; } void setLBraceLoc(SourceLocation L) { LBraceLoc = L; } @@ -1842,9 +1863,11 @@ public: ArrayRef getAllConstraints() const { return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs); } + ArrayRef getClobbers() const { return llvm::makeArrayRef(Clobbers, NumClobbers); } + ArrayRef getAllExprs() const { return llvm::makeArrayRef(reinterpret_cast(Exprs), NumInputs + NumOutputs); @@ -1856,8 +1879,8 @@ private: void initialize(const ASTContext &C, StringRef AsmString, ArrayRef AsmToks, ArrayRef Constraints, ArrayRef Exprs, ArrayRef Clobbers); -public: +public: SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; } SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; } @@ -1871,18 +1894,16 @@ public: }; class SEHExceptStmt : public Stmt { + friend class ASTReader; + friend class ASTStmtReader; + SourceLocation Loc; - Stmt *Children[2]; + Stmt *Children[2]; enum { FILTER_EXPR, BLOCK }; - SEHExceptStmt(SourceLocation Loc, - Expr *FilterExpr, - Stmt *Block); - - friend class ASTReader; - friend class ASTStmtReader; - explicit SEHExceptStmt(EmptyShell E) : Stmt(SEHExceptStmtClass, E) { } + SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block); + explicit SEHExceptStmt(EmptyShell E) : Stmt(SEHExceptStmtClass, E) {} public: static SEHExceptStmt* Create(const ASTContext &C, @@ -1911,19 +1932,17 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == SEHExceptStmtClass; } - }; class SEHFinallyStmt : public Stmt { - SourceLocation Loc; - Stmt *Block; - - SEHFinallyStmt(SourceLocation Loc, - Stmt *Block); - friend class ASTReader; friend class ASTStmtReader; - explicit SEHFinallyStmt(EmptyShell E) : Stmt(SEHFinallyStmtClass, E) { } + + SourceLocation Loc; + Stmt *Block; + + SEHFinallyStmt(SourceLocation Loc, Stmt *Block); + explicit SEHFinallyStmt(EmptyShell E) : Stmt(SEHFinallyStmtClass, E) {} public: static SEHFinallyStmt* Create(const ASTContext &C, @@ -1945,13 +1964,15 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == SEHFinallyStmtClass; } - }; class SEHTryStmt : public Stmt { - bool IsCXXTry; + friend class ASTReader; + friend class ASTStmtReader; + + bool IsCXXTry; SourceLocation TryLoc; - Stmt *Children[2]; + Stmt *Children[2]; enum { TRY = 0, HANDLER = 1 }; @@ -1960,9 +1981,7 @@ class SEHTryStmt : public Stmt { Stmt *TryBlock, Stmt *Handler); - friend class ASTReader; - friend class ASTStmtReader; - explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { } + explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) {} public: static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry, @@ -1997,15 +2016,15 @@ public: }; /// Represents a __leave statement. -/// class SEHLeaveStmt : public Stmt { SourceLocation LeaveLoc; + public: explicit SEHLeaveStmt(SourceLocation LL) : Stmt(SEHLeaveStmtClass), LeaveLoc(LL) {} /// \brief Build an empty __leave statement. - explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) { } + explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) {} SourceLocation getLeaveLoc() const { return LeaveLoc; } void setLeaveLoc(SourceLocation L) { LeaveLoc = L; } @@ -2050,6 +2069,8 @@ public: SourceLocation Loc; public: + friend class ASTStmtReader; + /// \brief Create a new capture. /// /// \param Loc The source location associated with this capture. @@ -2057,7 +2078,6 @@ public: /// \param Kind The kind of capture (this, ByRef, ...). /// /// \param Var The variable being captured, or null if capturing this. - /// Capture(SourceLocation Loc, VariableCaptureKind Kind, VarDecl *Var = nullptr); @@ -2089,8 +2109,6 @@ public: /// /// This operation is only valid if this capture captures a variable. VarDecl *getCapturedVar() const; - - friend class ASTStmtReader; }; private: @@ -2102,7 +2120,7 @@ private: llvm::PointerIntPair CapDeclAndKind; /// \brief The record for captured variables, a RecordDecl or CXXRecordDecl. - RecordDecl *TheRecordDecl; + RecordDecl *TheRecordDecl = nullptr; /// \brief Construct a captured statement. CapturedStmt(Stmt *S, CapturedRegionKind Kind, ArrayRef Captures, @@ -2122,6 +2140,8 @@ private: void setCapturedStmt(Stmt *S) { getStoredStmts()[NumCaptures] = S; } public: + friend class ASTStmtReader; + static CapturedStmt *Create(const ASTContext &Context, Stmt *S, CapturedRegionKind Kind, ArrayRef Captures, @@ -2161,10 +2181,10 @@ public: bool capturesVariable(const VarDecl *Var) const; /// \brief An iterator that walks over the captures. - typedef Capture *capture_iterator; - typedef const Capture *const_capture_iterator; - typedef llvm::iterator_range capture_range; - typedef llvm::iterator_range capture_const_range; + using capture_iterator = Capture *; + using const_capture_iterator = const Capture *; + using capture_range = llvm::iterator_range; + using capture_const_range = llvm::iterator_range; capture_range captures() { return capture_range(capture_begin(), capture_end()); @@ -2187,14 +2207,14 @@ public: unsigned capture_size() const { return NumCaptures; } /// \brief Iterator that walks over the capture initialization arguments. - typedef Expr **capture_init_iterator; - typedef llvm::iterator_range capture_init_range; + using capture_init_iterator = Expr **; + using capture_init_range = llvm::iterator_range; /// \brief Const iterator that walks over the capture initialization /// arguments. - typedef Expr *const *const_capture_init_iterator; - typedef llvm::iterator_range - const_capture_init_range; + using const_capture_init_iterator = Expr *const *; + using const_capture_init_range = + llvm::iterator_range; capture_init_range capture_inits() { return capture_init_range(capture_init_begin(), capture_init_end()); @@ -2226,9 +2246,11 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return getCapturedStmt()->getLocStart(); } + SourceLocation getLocEnd() const LLVM_READONLY { return getCapturedStmt()->getLocEnd(); } + SourceRange getSourceRange() const LLVM_READONLY { return getCapturedStmt()->getSourceRange(); } @@ -2238,10 +2260,8 @@ public: } child_range children(); - - friend class ASTStmtReader; }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_AST_STMT_H diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 922ff1f8dea7..8d240c1336ab 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1,4 +1,4 @@ -//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===// +//===- Stmt.cpp - Statement AST Node Implementation -----------------------===// // // The LLVM Compiler Infrastructure // @@ -13,6 +13,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclGroup.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" @@ -22,10 +24,24 @@ #include "clang/AST/StmtOpenMP.h" #include "clang/AST/Type.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Token.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +#include + using namespace clang; static struct StmtClassNameTable { @@ -150,6 +166,7 @@ const Stmt *Stmt::stripLabelLikeStatements() const { } namespace { + struct good {}; struct bad {}; @@ -191,7 +208,8 @@ namespace { (void) is_good(implements_getLocStart(&type::getLocStart)) #define ASSERT_IMPLEMENTS_getLocEnd(type) \ (void) is_good(implements_getLocEnd(&type::getLocEnd)) -} + +} // namespace /// Check whether the various Stmt classes implement their member /// functions. @@ -222,6 +240,7 @@ Stmt::child_range Stmt::children() { // // See also Expr.cpp:getExprLoc(). namespace { + /// This implementation is used when a class provides a custom /// implementation of getSourceRange. template @@ -240,7 +259,8 @@ namespace { return SourceRange(static_cast(stmt)->getLocStart(), static_cast(stmt)->getLocEnd()); } -} + +} // namespace SourceRange Stmt::getSourceRange() const { switch (getStmtClass()) { @@ -286,7 +306,7 @@ CompoundStmt::CompoundStmt(const ASTContext &C, ArrayRef Stmts, assert(CompoundStmtBits.NumStmts == Stmts.size() && "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); - if (Stmts.size() == 0) { + if (Stmts.empty()) { Body = nullptr; return; } @@ -408,6 +428,7 @@ StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const { Expr *GCCAsmStmt::getInputExpr(unsigned i) { return cast(Exprs[i + NumOutputs]); } + void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) { Exprs[i + NumOutputs] = E; } @@ -506,7 +527,7 @@ unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl&Pieces, unsigned LastAsmStringToken = 0; unsigned LastAsmStringOffset = 0; - while (1) { + while (true) { // Done with the string? if (CurPtr == StrEnd) { if (!CurStringPiece.empty()) @@ -682,6 +703,7 @@ Expr *MSAsmStmt::getOutputExpr(unsigned i) { Expr *MSAsmStmt::getInputExpr(unsigned i) { return cast(Exprs[i + NumOutputs]); } + void MSAsmStmt::setInputExpr(unsigned i, Expr *E) { Exprs[i + NumOutputs] = E; } @@ -696,9 +718,8 @@ GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, StringLiteral **constraints, Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, StringLiteral **clobbers, SourceLocation rparenloc) - : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, - numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) { - + : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, + numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) { unsigned NumExprs = NumOutputs + NumInputs; Names = new (C) IdentifierInfo*[NumExprs]; @@ -721,10 +742,9 @@ MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc, ArrayRef constraints, ArrayRef exprs, StringRef asmstr, ArrayRef clobbers, SourceLocation endloc) - : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, - numinputs, clobbers.size()), LBraceLoc(lbraceloc), - EndLoc(endloc), NumAsmToks(asmtoks.size()) { - + : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, + numinputs, clobbers.size()), LBraceLoc(lbraceloc), + EndLoc(endloc), NumAsmToks(asmtoks.size()) { initialize(C, asmstr, asmtoks, constraints, exprs, clobbers); } @@ -909,14 +929,9 @@ Expr* ReturnStmt::getRetValue() { return cast_or_null(RetExpr); } -SEHTryStmt::SEHTryStmt(bool IsCXXTry, - SourceLocation TryLoc, - Stmt *TryBlock, +SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler) - : Stmt(SEHTryStmtClass), - IsCXXTry(IsCXXTry), - TryLoc(TryLoc) -{ + : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) { Children[TRY] = TryBlock; Children[HANDLER] = Handler; } @@ -935,12 +950,8 @@ SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const { return dyn_cast(getHandler()); } -SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, - Expr *FilterExpr, - Stmt *Block) - : Stmt(SEHExceptStmtClass), - Loc(Loc) -{ +SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block) + : Stmt(SEHExceptStmtClass), Loc(Loc) { Children[FILTER_EXPR] = FilterExpr; Children[BLOCK] = Block; } @@ -950,12 +961,8 @@ SEHExceptStmt* SEHExceptStmt::Create(const ASTContext &C, SourceLocation Loc, return new(C) SEHExceptStmt(Loc,FilterExpr,Block); } -SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, - Stmt *Block) - : Stmt(SEHFinallyStmtClass), - Loc(Loc), - Block(Block) -{} +SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block) + : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {} SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc, Stmt *Block) { @@ -1037,7 +1044,7 @@ CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind, CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures) : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures), - CapDeclAndKind(nullptr, CR_Default), TheRecordDecl(nullptr) { + CapDeclAndKind(nullptr, CR_Default) { getStoredStmts()[NumCaptures] = nullptr; } @@ -1090,6 +1097,7 @@ Stmt::child_range CapturedStmt::children() { CapturedDecl *CapturedStmt::getCapturedDecl() { return CapDeclAndKind.getPointer(); } + const CapturedDecl *CapturedStmt::getCapturedDecl() const { return CapDeclAndKind.getPointer(); }