summaryrefslogtreecommitdiff
path: root/include/clang/AST/Stmt.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/Stmt.h')
-rw-r--r--include/clang/AST/Stmt.h1763
1 files changed, 1398 insertions, 365 deletions
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index aa0f88b71023..ff5baa21adff 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -89,6 +89,8 @@ protected:
llvm_unreachable("Stmts cannot be released with regular 'delete'.");
}
+ //===--- Statement bitfields classes ---===//
+
class StmtBitfields {
friend class Stmt;
@@ -97,22 +99,186 @@ protected:
};
enum { NumStmtBits = 8 };
+ class NullStmtBitfields {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend class NullStmt;
+
+ unsigned : NumStmtBits;
+
+ /// True if the null statement was preceded by an empty macro, e.g:
+ /// @code
+ /// #define CALL(x)
+ /// CALL(0);
+ /// @endcode
+ unsigned HasLeadingEmptyMacro : 1;
+
+ /// The location of the semi-colon.
+ SourceLocation SemiLoc;
+ };
+
class CompoundStmtBitfields {
+ friend class ASTStmtReader;
friend class CompoundStmt;
unsigned : NumStmtBits;
unsigned NumStmts : 32 - NumStmtBits;
+
+ /// The location of the opening "{".
+ SourceLocation LBraceLoc;
+ };
+
+ class LabelStmtBitfields {
+ friend class LabelStmt;
+
+ unsigned : NumStmtBits;
+
+ SourceLocation IdentLoc;
+ };
+
+ class AttributedStmtBitfields {
+ friend class ASTStmtReader;
+ friend class AttributedStmt;
+
+ unsigned : NumStmtBits;
+
+ /// Number of attributes.
+ unsigned NumAttrs : 32 - NumStmtBits;
+
+ /// The location of the attribute.
+ SourceLocation AttrLoc;
};
class IfStmtBitfields {
+ friend class ASTStmtReader;
friend class IfStmt;
unsigned : NumStmtBits;
+ /// True if this if statement is a constexpr if.
unsigned IsConstexpr : 1;
+
+ /// True if this if statement has storage for an else statement.
+ unsigned HasElse : 1;
+
+ /// True if this if statement has storage for a variable declaration.
+ unsigned HasVar : 1;
+
+ /// True if this if statement has storage for an init statement.
+ unsigned HasInit : 1;
+
+ /// The location of the "if".
+ SourceLocation IfLoc;
+ };
+
+ class SwitchStmtBitfields {
+ friend class SwitchStmt;
+
+ unsigned : NumStmtBits;
+
+ /// True if the SwitchStmt has storage for an init statement.
+ unsigned HasInit : 1;
+
+ /// True if the SwitchStmt has storage for a condition variable.
+ unsigned HasVar : 1;
+
+ /// 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 to be a hint for possible clients.
+ unsigned AllEnumCasesCovered : 1;
+
+ /// The location of the "switch".
+ SourceLocation SwitchLoc;
+ };
+
+ class WhileStmtBitfields {
+ friend class ASTStmtReader;
+ friend class WhileStmt;
+
+ unsigned : NumStmtBits;
+
+ /// True if the WhileStmt has storage for a condition variable.
+ unsigned HasVar : 1;
+
+ /// The location of the "while".
+ SourceLocation WhileLoc;
+ };
+
+ class DoStmtBitfields {
+ friend class DoStmt;
+
+ unsigned : NumStmtBits;
+
+ /// The location of the "do".
+ SourceLocation DoLoc;
+ };
+
+ class ForStmtBitfields {
+ friend class ForStmt;
+
+ unsigned : NumStmtBits;
+
+ /// The location of the "for".
+ SourceLocation ForLoc;
+ };
+
+ class GotoStmtBitfields {
+ friend class GotoStmt;
+ friend class IndirectGotoStmt;
+
+ unsigned : NumStmtBits;
+
+ /// The location of the "goto".
+ SourceLocation GotoLoc;
+ };
+
+ class ContinueStmtBitfields {
+ friend class ContinueStmt;
+
+ unsigned : NumStmtBits;
+
+ /// The location of the "continue".
+ SourceLocation ContinueLoc;
+ };
+
+ class BreakStmtBitfields {
+ friend class BreakStmt;
+
+ unsigned : NumStmtBits;
+
+ /// The location of the "break".
+ SourceLocation BreakLoc;
+ };
+
+ class ReturnStmtBitfields {
+ friend class ReturnStmt;
+
+ unsigned : NumStmtBits;
+
+ /// True if this ReturnStmt has storage for an NRVO candidate.
+ unsigned HasNRVOCandidate : 1;
+
+ /// The location of the "return".
+ SourceLocation RetLoc;
+ };
+
+ class SwitchCaseBitfields {
+ friend class SwitchCase;
+ friend class CaseStmt;
+
+ unsigned : NumStmtBits;
+
+ /// Used by CaseStmt to store whether it is a case statement
+ /// of the form case LHS ... RHS (a GNU extension).
+ unsigned CaseStmtIsGNURange : 1;
+
+ /// The location of the "case" or "default" keyword.
+ SourceLocation KeywordLoc;
};
+ //===--- Expression bitfields classes ---===//
+
class ExprBitfields {
friend class ASTStmtReader; // deserialization
friend class AtomicExpr; // ctor
@@ -146,14 +312,40 @@ protected:
unsigned InstantiationDependent : 1;
unsigned ContainsUnexpandedParameterPack : 1;
};
- enum { NumExprBits = 17 };
+ enum { NumExprBits = NumStmtBits + 9 };
- class CharacterLiteralBitfields {
- friend class CharacterLiteral;
+ class PredefinedExprBitfields {
+ friend class ASTStmtReader;
+ friend class PredefinedExpr;
unsigned : NumExprBits;
- unsigned Kind : 3;
+ /// The kind of this PredefinedExpr. One of the enumeration values
+ /// in PredefinedExpr::IdentKind.
+ unsigned Kind : 4;
+
+ /// True if this PredefinedExpr has a trailing "StringLiteral *"
+ /// for the predefined identifier.
+ unsigned HasFunctionName : 1;
+
+ /// The location of this PredefinedExpr.
+ SourceLocation Loc;
+ };
+
+ class DeclRefExprBitfields {
+ friend class ASTStmtReader; // deserialization
+ friend class DeclRefExpr;
+
+ unsigned : NumExprBits;
+
+ unsigned HasQualifier : 1;
+ unsigned HasTemplateKWAndArgsInfo : 1;
+ unsigned HasFoundDecl : 1;
+ unsigned HadMultipleCandidates : 1;
+ unsigned RefersToEnclosingVariableOrCapture : 1;
+
+ /// The location of the declaration name itself.
+ SourceLocation Loc;
};
enum APFloatSemantics {
@@ -174,26 +366,111 @@ protected:
unsigned IsExact : 1;
};
+ class StringLiteralBitfields {
+ friend class ASTStmtReader;
+ friend class StringLiteral;
+
+ unsigned : NumExprBits;
+
+ /// The kind of this string literal.
+ /// One of the enumeration values of StringLiteral::StringKind.
+ unsigned Kind : 3;
+
+ /// The width of a single character in bytes. Only values of 1, 2,
+ /// and 4 bytes are supported. StringLiteral::mapCharByteWidth maps
+ /// the target + string kind to the appropriate CharByteWidth.
+ unsigned CharByteWidth : 3;
+
+ unsigned IsPascal : 1;
+
+ /// The number of concatenated token this string is made of.
+ /// This is the number of trailing SourceLocation.
+ unsigned NumConcatenated;
+ };
+
+ class CharacterLiteralBitfields {
+ friend class CharacterLiteral;
+
+ unsigned : NumExprBits;
+
+ unsigned Kind : 3;
+ };
+
+ class UnaryOperatorBitfields {
+ friend class UnaryOperator;
+
+ unsigned : NumExprBits;
+
+ unsigned Opc : 5;
+ unsigned CanOverflow : 1;
+
+ SourceLocation Loc;
+ };
+
class UnaryExprOrTypeTraitExprBitfields {
friend class UnaryExprOrTypeTraitExpr;
unsigned : NumExprBits;
- unsigned Kind : 2;
+ unsigned Kind : 3;
unsigned IsType : 1; // true if operand is a type, false if an expression.
};
- class DeclRefExprBitfields {
- friend class ASTStmtReader; // deserialization
- friend class DeclRefExpr;
+ class ArraySubscriptExprBitfields {
+ friend class ArraySubscriptExpr;
unsigned : NumExprBits;
- unsigned HasQualifier : 1;
+ SourceLocation RBracketLoc;
+ };
+
+ class CallExprBitfields {
+ friend class CallExpr;
+
+ unsigned : NumExprBits;
+
+ unsigned NumPreArgs : 1;
+
+ /// True if the callee of the call expression was found using ADL.
+ unsigned UsesADL : 1;
+
+ /// Padding used to align OffsetToTrailingObjects to a byte multiple.
+ unsigned : 24 - 2 - NumExprBits;
+
+ /// The offset in bytes from the this pointer to the start of the
+ /// trailing objects belonging to CallExpr. Intentionally byte sized
+ /// for faster access.
+ unsigned OffsetToTrailingObjects : 8;
+ };
+ enum { NumCallExprBits = 32 };
+
+ class MemberExprBitfields {
+ friend class MemberExpr;
+
+ unsigned : NumExprBits;
+
+ /// IsArrow - True if this is "X->F", false if this is "X.F".
+ unsigned IsArrow : 1;
+
+ /// True if this member expression used a nested-name-specifier to
+ /// refer to the member, e.g., "x->Base::f", or found its member via
+ /// a using declaration. When true, a MemberExprNameQualifier
+ /// structure is allocated immediately after the MemberExpr.
+ unsigned HasQualifierOrFoundDecl : 1;
+
+ /// True if this member expression specified a template keyword
+ /// and/or a template argument list explicitly, e.g., x->f<int>,
+ /// x->template f, x->template f<int>.
+ /// When true, an ASTTemplateKWAndArgsInfo structure and its
+ /// TemplateArguments (if any) are present.
unsigned HasTemplateKWAndArgsInfo : 1;
- unsigned HasFoundDecl : 1;
+
+ /// True if this member expression refers to a method that
+ /// was resolved from an overloaded set having size greater than 1.
unsigned HadMultipleCandidates : 1;
- unsigned RefersToEnclosingVariableOrCapture : 1;
+
+ /// This is the location of the -> or . in the expression.
+ SourceLocation OperatorLoc;
};
class CastExprBitfields {
@@ -204,27 +481,44 @@ protected:
unsigned Kind : 6;
unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr.
- unsigned BasePathIsEmpty : 1;
+
+ /// The number of CXXBaseSpecifiers in the cast. 14 bits would be enough
+ /// here. ([implimits] Direct and indirect base classes [16384]).
+ unsigned BasePathSize;
};
- class CallExprBitfields {
- friend class CallExpr;
+ class BinaryOperatorBitfields {
+ friend class BinaryOperator;
unsigned : NumExprBits;
- unsigned NumPreArgs : 1;
+ unsigned Opc : 6;
+
+ /// This is only meaningful for operations on floating point
+ /// types and 0 otherwise.
+ unsigned FPFeatures : 3;
+
+ SourceLocation OpLoc;
};
- class ExprWithCleanupsBitfields {
- friend class ASTStmtReader; // deserialization
- friend class ExprWithCleanups;
+ class InitListExprBitfields {
+ friend class InitListExpr;
unsigned : NumExprBits;
- // When false, it must not have side effects.
- unsigned CleanupsHaveSideEffects : 1;
+ /// Whether this initializer list originally had a GNU array-range
+ /// designator in it. This is a temporary marker used by CodeGen.
+ unsigned HadArrayRangeDesignator : 1;
+ };
- unsigned NumObjects : 32 - 1 - NumExprBits;
+ class ParenListExprBitfields {
+ friend class ASTStmtReader;
+ friend class ParenListExpr;
+
+ unsigned : NumExprBits;
+
+ /// The number of expressions in the paren list.
+ unsigned NumExprs;
};
class PseudoObjectExprBitfields {
@@ -239,32 +533,153 @@ protected:
unsigned ResultIndex : 32 - 8 - NumExprBits;
};
- class OpaqueValueExprBitfields {
- friend class OpaqueValueExpr;
+ //===--- C++ Expression bitfields classes ---===//
+
+ class CXXOperatorCallExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXOperatorCallExpr;
+
+ unsigned : NumCallExprBits;
+
+ /// The kind of this overloaded operator. One of the enumerator
+ /// value of OverloadedOperatorKind.
+ unsigned OperatorKind : 6;
+
+ // Only meaningful for floating point types.
+ unsigned FPFeatures : 3;
+ };
+
+ class CXXBoolLiteralExprBitfields {
+ friend class CXXBoolLiteralExpr;
unsigned : NumExprBits;
- /// The OVE is a unique semantic reference to its source expressio if this
- /// bit is set to true.
- unsigned IsUnique : 1;
+ /// The value of the boolean literal.
+ unsigned Value : 1;
+
+ /// The location of the boolean literal.
+ SourceLocation Loc;
};
- class ObjCIndirectCopyRestoreExprBitfields {
- friend class ObjCIndirectCopyRestoreExpr;
+ class CXXNullPtrLiteralExprBitfields {
+ friend class CXXNullPtrLiteralExpr;
unsigned : NumExprBits;
- unsigned ShouldCopy : 1;
+ /// The location of the null pointer literal.
+ SourceLocation Loc;
};
- class InitListExprBitfields {
- friend class InitListExpr;
+ class CXXThisExprBitfields {
+ friend class CXXThisExpr;
unsigned : NumExprBits;
- /// Whether this initializer list originally had a GNU array-range
- /// designator in it. This is a temporary marker used by CodeGen.
- unsigned HadArrayRangeDesignator : 1;
+ /// Whether this is an implicit "this".
+ unsigned IsImplicit : 1;
+
+ /// The location of the "this".
+ SourceLocation Loc;
+ };
+
+ class CXXThrowExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXThrowExpr;
+
+ unsigned : NumExprBits;
+
+ /// Whether the thrown variable (if any) is in scope.
+ unsigned IsThrownVariableInScope : 1;
+
+ /// The location of the "throw".
+ SourceLocation ThrowLoc;
+ };
+
+ class CXXDefaultArgExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXDefaultArgExpr;
+
+ unsigned : NumExprBits;
+
+ /// The location where the default argument expression was used.
+ SourceLocation Loc;
+ };
+
+ class CXXDefaultInitExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXDefaultInitExpr;
+
+ unsigned : NumExprBits;
+
+ /// The location where the default initializer expression was used.
+ SourceLocation Loc;
+ };
+
+ class CXXScalarValueInitExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXScalarValueInitExpr;
+
+ unsigned : NumExprBits;
+
+ SourceLocation RParenLoc;
+ };
+
+ class CXXNewExprBitfields {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend class CXXNewExpr;
+
+ unsigned : NumExprBits;
+
+ /// Was the usage ::new, i.e. is the global new to be used?
+ unsigned IsGlobalNew : 1;
+
+ /// Do we allocate an array? If so, the first trailing "Stmt *" is the
+ /// size expression.
+ unsigned IsArray : 1;
+
+ /// Should the alignment be passed to the allocation function?
+ unsigned ShouldPassAlignment : 1;
+
+ /// If this is an array allocation, does the usual deallocation
+ /// function for the allocated type want to know the allocated size?
+ unsigned UsualArrayDeleteWantsSize : 1;
+
+ /// What kind of initializer do we have? Could be none, parens, or braces.
+ /// In storage, we distinguish between "none, and no initializer expr", and
+ /// "none, but an implicit initializer expr".
+ unsigned StoredInitializationStyle : 2;
+
+ /// True if the allocated type was expressed as a parenthesized type-id.
+ unsigned IsParenTypeId : 1;
+
+ /// The number of placement new arguments.
+ unsigned NumPlacementArgs;
+ };
+
+ class CXXDeleteExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXDeleteExpr;
+
+ unsigned : NumExprBits;
+
+ /// Is this a forced global delete, i.e. "::delete"?
+ unsigned GlobalDelete : 1;
+
+ /// Is this the array form of delete, i.e. "delete[]"?
+ unsigned ArrayForm : 1;
+
+ /// ArrayFormAsWritten can be different from ArrayForm if 'delete' is
+ /// applied to pointer-to-array type (ArrayFormAsWritten will be false
+ /// while ArrayForm will be true).
+ unsigned ArrayFormAsWritten : 1;
+
+ /// Does the usual deallocation function for the element type require
+ /// a size_t argument?
+ unsigned UsualArrayDeleteWantsSize : 1;
+
+ /// Location of the expression.
+ SourceLocation Loc;
};
class TypeTraitExprBitfields {
@@ -285,6 +700,154 @@ protected:
unsigned NumArgs : 32 - 8 - 1 - NumExprBits;
};
+ class DependentScopeDeclRefExprBitfields {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ friend class DependentScopeDeclRefExpr;
+
+ unsigned : NumExprBits;
+
+ /// Whether the name includes info for explicit template
+ /// keyword and arguments.
+ unsigned HasTemplateKWAndArgsInfo : 1;
+ };
+
+ class CXXConstructExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXConstructExpr;
+
+ unsigned : NumExprBits;
+
+ unsigned Elidable : 1;
+ unsigned HadMultipleCandidates : 1;
+ unsigned ListInitialization : 1;
+ unsigned StdInitListInitialization : 1;
+ unsigned ZeroInitialization : 1;
+ unsigned ConstructionKind : 3;
+
+ SourceLocation Loc;
+ };
+
+ class ExprWithCleanupsBitfields {
+ friend class ASTStmtReader; // deserialization
+ friend class ExprWithCleanups;
+
+ unsigned : NumExprBits;
+
+ // When false, it must not have side effects.
+ unsigned CleanupsHaveSideEffects : 1;
+
+ unsigned NumObjects : 32 - 1 - NumExprBits;
+ };
+
+ class CXXUnresolvedConstructExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXUnresolvedConstructExpr;
+
+ unsigned : NumExprBits;
+
+ /// The number of arguments used to construct the type.
+ unsigned NumArgs;
+ };
+
+ class CXXDependentScopeMemberExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXDependentScopeMemberExpr;
+
+ unsigned : NumExprBits;
+
+ /// Whether this member expression used the '->' operator or
+ /// the '.' operator.
+ unsigned IsArrow : 1;
+
+ /// Whether this member expression has info for explicit template
+ /// keyword and arguments.
+ unsigned HasTemplateKWAndArgsInfo : 1;
+
+ /// See getFirstQualifierFoundInScope() and the comment listing
+ /// the trailing objects.
+ unsigned HasFirstQualifierFoundInScope : 1;
+
+ /// The location of the '->' or '.' operator.
+ SourceLocation OperatorLoc;
+ };
+
+ class OverloadExprBitfields {
+ friend class ASTStmtReader;
+ friend class OverloadExpr;
+
+ unsigned : NumExprBits;
+
+ /// Whether the name includes info for explicit template
+ /// keyword and arguments.
+ unsigned HasTemplateKWAndArgsInfo : 1;
+
+ /// Padding used by the derived classes to store various bits. If you
+ /// need to add some data here, shrink this padding and add your data
+ /// above. NumOverloadExprBits also needs to be updated.
+ unsigned : 32 - NumExprBits - 1;
+
+ /// The number of results.
+ unsigned NumResults;
+ };
+ enum { NumOverloadExprBits = NumExprBits + 1 };
+
+ class UnresolvedLookupExprBitfields {
+ friend class ASTStmtReader;
+ friend class UnresolvedLookupExpr;
+
+ unsigned : NumOverloadExprBits;
+
+ /// True if these lookup results should be extended by
+ /// argument-dependent lookup if this is the operand of a function call.
+ unsigned RequiresADL : 1;
+
+ /// True if these lookup results are overloaded. This is pretty trivially
+ /// rederivable if we urgently need to kill this field.
+ unsigned Overloaded : 1;
+ };
+ static_assert(sizeof(UnresolvedLookupExprBitfields) <= 4,
+ "UnresolvedLookupExprBitfields must be <= than 4 bytes to"
+ "avoid trashing OverloadExprBitfields::NumResults!");
+
+ class UnresolvedMemberExprBitfields {
+ friend class ASTStmtReader;
+ friend class UnresolvedMemberExpr;
+
+ unsigned : NumOverloadExprBits;
+
+ /// Whether this member expression used the '->' operator or
+ /// the '.' operator.
+ unsigned IsArrow : 1;
+
+ /// Whether the lookup results contain an unresolved using declaration.
+ unsigned HasUnresolvedUsing : 1;
+ };
+ static_assert(sizeof(UnresolvedMemberExprBitfields) <= 4,
+ "UnresolvedMemberExprBitfields must be <= than 4 bytes to"
+ "avoid trashing OverloadExprBitfields::NumResults!");
+
+ class CXXNoexceptExprBitfields {
+ friend class ASTStmtReader;
+ friend class CXXNoexceptExpr;
+
+ unsigned : NumExprBits;
+
+ unsigned Value : 1;
+ };
+
+ class SubstNonTypeTemplateParmExprBitfields {
+ friend class ASTStmtReader;
+ friend class SubstNonTypeTemplateParmExpr;
+
+ unsigned : NumExprBits;
+
+ /// The location of the non-type template parameter reference.
+ SourceLocation NameLoc;
+ };
+
+ //===--- C++ Coroutines TS bitfields classes ---===//
+
class CoawaitExprBitfields {
friend class CoawaitExpr;
@@ -293,24 +856,99 @@ protected:
unsigned IsImplicit : 1;
};
+ //===--- Obj-C Expression bitfields classes ---===//
+
+ class ObjCIndirectCopyRestoreExprBitfields {
+ friend class ObjCIndirectCopyRestoreExpr;
+
+ unsigned : NumExprBits;
+
+ unsigned ShouldCopy : 1;
+ };
+
+ //===--- Clang Extensions bitfields classes ---===//
+
+ class OpaqueValueExprBitfields {
+ friend class ASTStmtReader;
+ friend class OpaqueValueExpr;
+
+ unsigned : NumExprBits;
+
+ /// The OVE is a unique semantic reference to its source expression if this
+ /// bit is set to true.
+ unsigned IsUnique : 1;
+
+ SourceLocation Loc;
+ };
+
union {
+ // Same order as in StmtNodes.td.
+ // Statements
StmtBitfields StmtBits;
+ NullStmtBitfields NullStmtBits;
CompoundStmtBitfields CompoundStmtBits;
+ LabelStmtBitfields LabelStmtBits;
+ AttributedStmtBitfields AttributedStmtBits;
IfStmtBitfields IfStmtBits;
+ SwitchStmtBitfields SwitchStmtBits;
+ WhileStmtBitfields WhileStmtBits;
+ DoStmtBitfields DoStmtBits;
+ ForStmtBitfields ForStmtBits;
+ GotoStmtBitfields GotoStmtBits;
+ ContinueStmtBitfields ContinueStmtBits;
+ BreakStmtBitfields BreakStmtBits;
+ ReturnStmtBitfields ReturnStmtBits;
+ SwitchCaseBitfields SwitchCaseBits;
+
+ // Expressions
ExprBitfields ExprBits;
- CharacterLiteralBitfields CharacterLiteralBits;
+ PredefinedExprBitfields PredefinedExprBits;
+ DeclRefExprBitfields DeclRefExprBits;
FloatingLiteralBitfields FloatingLiteralBits;
+ StringLiteralBitfields StringLiteralBits;
+ CharacterLiteralBitfields CharacterLiteralBits;
+ UnaryOperatorBitfields UnaryOperatorBits;
UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits;
- DeclRefExprBitfields DeclRefExprBits;
- CastExprBitfields CastExprBits;
+ ArraySubscriptExprBitfields ArraySubscriptExprBits;
CallExprBitfields CallExprBits;
- ExprWithCleanupsBitfields ExprWithCleanupsBits;
- PseudoObjectExprBitfields PseudoObjectExprBits;
- OpaqueValueExprBitfields OpaqueValueExprBits;
- ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
+ MemberExprBitfields MemberExprBits;
+ CastExprBitfields CastExprBits;
+ BinaryOperatorBitfields BinaryOperatorBits;
InitListExprBitfields InitListExprBits;
+ ParenListExprBitfields ParenListExprBits;
+ PseudoObjectExprBitfields PseudoObjectExprBits;
+
+ // C++ Expressions
+ CXXOperatorCallExprBitfields CXXOperatorCallExprBits;
+ CXXBoolLiteralExprBitfields CXXBoolLiteralExprBits;
+ CXXNullPtrLiteralExprBitfields CXXNullPtrLiteralExprBits;
+ CXXThisExprBitfields CXXThisExprBits;
+ CXXThrowExprBitfields CXXThrowExprBits;
+ CXXDefaultArgExprBitfields CXXDefaultArgExprBits;
+ CXXDefaultInitExprBitfields CXXDefaultInitExprBits;
+ CXXScalarValueInitExprBitfields CXXScalarValueInitExprBits;
+ CXXNewExprBitfields CXXNewExprBits;
+ CXXDeleteExprBitfields CXXDeleteExprBits;
TypeTraitExprBitfields TypeTraitExprBits;
+ DependentScopeDeclRefExprBitfields DependentScopeDeclRefExprBits;
+ CXXConstructExprBitfields CXXConstructExprBits;
+ ExprWithCleanupsBitfields ExprWithCleanupsBits;
+ CXXUnresolvedConstructExprBitfields CXXUnresolvedConstructExprBits;
+ CXXDependentScopeMemberExprBitfields CXXDependentScopeMemberExprBits;
+ OverloadExprBitfields OverloadExprBits;
+ UnresolvedLookupExprBitfields UnresolvedLookupExprBits;
+ UnresolvedMemberExprBitfields UnresolvedMemberExprBits;
+ CXXNoexceptExprBitfields CXXNoexceptExprBits;
+ SubstNonTypeTemplateParmExprBitfields SubstNonTypeTemplateParmExprBits;
+
+ // C++ Coroutines TS expressions
CoawaitExprBitfields CoawaitBits;
+
+ // Obj-C Expressions
+ ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
+
+ // Clang Extensions
+ OpaqueValueExprBitfields OpaqueValueExprBits;
};
public:
@@ -380,7 +1018,7 @@ protected:
public:
Stmt(StmtClass SC) {
- static_assert(sizeof(*this) == sizeof(void *),
+ static_assert(sizeof(*this) <= 8,
"changing bitfields changed sizeof(Stmt)");
static_assert(sizeof(*this) % alignof(void *) == 0,
"Insufficient alignment!");
@@ -398,8 +1036,8 @@ public:
/// value objects created/interpreted by SourceManager. We assume AST
/// clients will have a pointer to the respective SourceManager.
SourceRange getSourceRange() const LLVM_READONLY;
- SourceLocation getLocStart() const LLVM_READONLY;
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const LLVM_READONLY;
+ SourceLocation getEndLoc() const LLVM_READONLY;
// global temp stats (until we have a per-module visitor)
static void addStmtClass(const StmtClass s);
@@ -413,6 +1051,9 @@ public:
void dump(raw_ostream &OS, SourceManager &SM) const;
void dump(raw_ostream &OS) const;
+ /// \return Unique reproducible object identifier
+ int64_t getID(const ASTContext &Context) const;
+
/// dumpColor - same as dump(), but forces color highlighting.
void dumpColor() const;
@@ -421,6 +1062,7 @@ public:
void dumpPretty(const ASTContext &Context) const;
void printPretty(raw_ostream &OS, PrinterHelper *Helper,
const PrintingPolicy &Policy, unsigned Indentation = 0,
+ StringRef NewlineSymbol = "\n",
const ASTContext *Context = nullptr) const;
/// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only
@@ -511,9 +1153,7 @@ public:
/// isSingleDecl - This method returns true if this DeclStmt refers
/// to a single Decl.
- bool isSingleDecl() const {
- return DG.isSingleDecl();
- }
+ bool isSingleDecl() const { return DG.isSingleDecl(); }
const Decl *getSingleDecl() const { return DG.getSingleDecl(); }
Decl *getSingleDecl() { return DG.getSingleDecl(); }
@@ -522,13 +1162,11 @@ public:
DeclGroupRef getDeclGroup() { return DG; }
void setDeclGroup(DeclGroupRef DGR) { DG = DGR; }
- SourceLocation getStartLoc() const { return StartLoc; }
void setStartLoc(SourceLocation L) { StartLoc = L; }
SourceLocation getEndLoc() const { return EndLoc; }
void setEndLoc(SourceLocation L) { EndLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return StartLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return StartLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == DeclStmtClass;
@@ -570,33 +1208,25 @@ public:
/// NullStmt - This is the null statement ";": C99 6.8.3p3.
///
class NullStmt : public Stmt {
- SourceLocation SemiLoc;
-
- /// True if the null statement was preceded by an empty macro, e.g:
- /// @code
- /// #define CALL(x)
- /// CALL(0);
- /// @endcode
- bool HasLeadingEmptyMacro = false;
-
public:
- friend class ASTStmtReader;
- friend class ASTStmtWriter;
-
NullStmt(SourceLocation L, bool hasLeadingEmptyMacro = false)
- : Stmt(NullStmtClass), SemiLoc(L),
- HasLeadingEmptyMacro(hasLeadingEmptyMacro) {}
+ : Stmt(NullStmtClass) {
+ NullStmtBits.HasLeadingEmptyMacro = hasLeadingEmptyMacro;
+ setSemiLoc(L);
+ }
/// Build an empty null statement.
explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) {}
- SourceLocation getSemiLoc() const { return SemiLoc; }
- void setSemiLoc(SourceLocation L) { SemiLoc = L; }
+ SourceLocation getSemiLoc() const { return NullStmtBits.SemiLoc; }
+ void setSemiLoc(SourceLocation L) { NullStmtBits.SemiLoc = L; }
- bool hasLeadingEmptyMacro() const { return HasLeadingEmptyMacro; }
+ bool hasLeadingEmptyMacro() const {
+ return NullStmtBits.HasLeadingEmptyMacro;
+ }
- SourceLocation getLocStart() const LLVM_READONLY { return SemiLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return SemiLoc; }
+ SourceLocation getBeginLoc() const { return getSemiLoc(); }
+ SourceLocation getEndLoc() const { return getSemiLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == NullStmtClass;
@@ -613,7 +1243,8 @@ class CompoundStmt final : public Stmt,
friend class ASTStmtReader;
friend TrailingObjects;
- SourceLocation LBraceLoc, RBraceLoc;
+ /// The location of the closing "}". LBraceLoc is stored in CompoundStmtBits.
+ SourceLocation RBraceLoc;
CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB, SourceLocation RB);
explicit CompoundStmt(EmptyShell Empty) : Stmt(CompoundStmtClass, Empty) {}
@@ -626,8 +1257,9 @@ public:
// Build an empty compound statement with a location.
explicit CompoundStmt(SourceLocation Loc)
- : Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(Loc) {
+ : Stmt(CompoundStmtClass), RBraceLoc(Loc) {
CompoundStmtBits.NumStmts = 0;
+ CompoundStmtBits.LBraceLoc = Loc;
}
// Build an empty compound statement.
@@ -653,7 +1285,7 @@ public:
body_begin()[size() - 1] = S;
}
- using const_body_iterator = Stmt* const *;
+ using const_body_iterator = Stmt *const *;
using body_const_range = llvm::iterator_range<const_body_iterator>;
body_const_range body() const {
@@ -695,10 +1327,10 @@ public:
return const_reverse_body_iterator(body_begin());
}
- SourceLocation getLocStart() const LLVM_READONLY { return LBraceLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RBraceLoc; }
+ SourceLocation getBeginLoc() const { return CompoundStmtBits.LBraceLoc; }
+ SourceLocation getEndLoc() const { return RBraceLoc; }
- SourceLocation getLBracLoc() const { return LBraceLoc; }
+ SourceLocation getLBracLoc() const { return CompoundStmtBits.LBraceLoc; }
SourceLocation getRBracLoc() const { return RBraceLoc; }
static bool classof(const Stmt *T) {
@@ -716,36 +1348,40 @@ public:
// SwitchCase is the base class for CaseStmt and DefaultStmt,
class SwitchCase : public Stmt {
protected:
- // A pointer to the following CaseStmt or DefaultStmt class,
- // used by SwitchStmt.
- SwitchCase *NextSwitchCase = nullptr;
- SourceLocation KeywordLoc;
+ /// The location of the ":".
SourceLocation ColonLoc;
+ // The location of the "case" or "default" keyword. Stored in SwitchCaseBits.
+ // SourceLocation KeywordLoc;
+
+ /// A pointer to the following CaseStmt or DefaultStmt class,
+ /// used by SwitchStmt.
+ SwitchCase *NextSwitchCase = nullptr;
+
SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc)
- : Stmt(SC), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {}
+ : Stmt(SC), ColonLoc(ColonLoc) {
+ setKeywordLoc(KWLoc);
+ }
SwitchCase(StmtClass SC, EmptyShell) : Stmt(SC) {}
public:
const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
-
SwitchCase *getNextSwitchCase() { return NextSwitchCase; }
-
void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; }
- SourceLocation getKeywordLoc() const { return KeywordLoc; }
- void setKeywordLoc(SourceLocation L) { KeywordLoc = L; }
+ SourceLocation getKeywordLoc() const { return SwitchCaseBits.KeywordLoc; }
+ void setKeywordLoc(SourceLocation L) { SwitchCaseBits.KeywordLoc = L; }
SourceLocation getColonLoc() const { return ColonLoc; }
void setColonLoc(SourceLocation L) { ColonLoc = L; }
- Stmt *getSubStmt();
+ inline Stmt *getSubStmt();
const Stmt *getSubStmt() const {
- return const_cast<SwitchCase*>(this)->getSubStmt();
+ return const_cast<SwitchCase *>(this)->getSubStmt();
}
- SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY;
+ SourceLocation getBeginLoc() const { return getKeywordLoc(); }
+ inline SourceLocation getEndLoc() const LLVM_READONLY;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CaseStmtClass ||
@@ -753,59 +1389,144 @@ public:
}
};
-class CaseStmt : public SwitchCase {
- SourceLocation EllipsisLoc;
- enum { LHS, RHS, SUBSTMT, END_EXPR };
- Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for
- // GNU "case 1 ... 4" extension
+/// CaseStmt - Represent a case statement. It can optionally be a GNU case
+/// statement of the form LHS ... RHS representing a range of cases.
+class CaseStmt final
+ : public SwitchCase,
+ private llvm::TrailingObjects<CaseStmt, Stmt *, SourceLocation> {
+ friend TrailingObjects;
-public:
+ // CaseStmt is followed by several trailing objects, some of which optional.
+ // Note that it would be more convenient to put the optional trailing objects
+ // at the end but this would impact children().
+ // The trailing objects are in order:
+ //
+ // * A "Stmt *" for the LHS of the case statement. Always present.
+ //
+ // * A "Stmt *" for the RHS of the case statement. This is a GNU extension
+ // which allow ranges in cases statement of the form LHS ... RHS.
+ // Present if and only if caseStmtIsGNURange() is true.
+ //
+ // * A "Stmt *" for the substatement of the case statement. Always present.
+ //
+ // * A SourceLocation for the location of the ... if this is a case statement
+ // with a range. Present if and only if caseStmtIsGNURange() is true.
+ enum { LhsOffset = 0, SubStmtOffsetFromRhs = 1 };
+ enum { NumMandatoryStmtPtr = 2 };
+
+ unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+ return NumMandatoryStmtPtr + caseStmtIsGNURange();
+ }
+
+ unsigned numTrailingObjects(OverloadToken<SourceLocation>) const {
+ return caseStmtIsGNURange();
+ }
+
+ unsigned lhsOffset() const { return LhsOffset; }
+ unsigned rhsOffset() const { return LhsOffset + caseStmtIsGNURange(); }
+ unsigned subStmtOffset() const { return rhsOffset() + SubStmtOffsetFromRhs; }
+
+ /// Build a case statement assuming that the storage for the
+ /// trailing objects has been properly allocated.
CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
SourceLocation ellipsisLoc, SourceLocation colonLoc)
- : SwitchCase(CaseStmtClass, caseLoc, colonLoc) {
- SubExprs[SUBSTMT] = nullptr;
- SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
- SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
- EllipsisLoc = ellipsisLoc;
+ : SwitchCase(CaseStmtClass, caseLoc, colonLoc) {
+ // Handle GNU case statements of the form LHS ... RHS.
+ bool IsGNURange = rhs != nullptr;
+ SwitchCaseBits.CaseStmtIsGNURange = IsGNURange;
+ setLHS(lhs);
+ setSubStmt(nullptr);
+ if (IsGNURange) {
+ setRHS(rhs);
+ setEllipsisLoc(ellipsisLoc);
+ }
}
/// Build an empty switch case statement.
- explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) {}
+ explicit CaseStmt(EmptyShell Empty, bool CaseStmtIsGNURange)
+ : SwitchCase(CaseStmtClass, Empty) {
+ SwitchCaseBits.CaseStmtIsGNURange = CaseStmtIsGNURange;
+ }
- SourceLocation getCaseLoc() const { return KeywordLoc; }
- void setCaseLoc(SourceLocation L) { KeywordLoc = L; }
- SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
- void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; }
- SourceLocation getColonLoc() const { return ColonLoc; }
- void setColonLoc(SourceLocation L) { ColonLoc = L; }
+public:
+ /// Build a case statement.
+ static CaseStmt *Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
+ SourceLocation caseLoc, SourceLocation ellipsisLoc,
+ SourceLocation colonLoc);
+
+ /// Build an empty case statement.
+ static CaseStmt *CreateEmpty(const ASTContext &Ctx, bool CaseStmtIsGNURange);
+
+ /// True if this case statement is of the form case LHS ... RHS, which
+ /// is a GNU extension. In this case the RHS can be obtained with getRHS()
+ /// and the location of the ellipsis can be obtained with getEllipsisLoc().
+ bool caseStmtIsGNURange() const { return SwitchCaseBits.CaseStmtIsGNURange; }
+
+ SourceLocation getCaseLoc() const { return getKeywordLoc(); }
+ void setCaseLoc(SourceLocation L) { setKeywordLoc(L); }
+
+ /// Get the location of the ... in a case statement of the form LHS ... RHS.
+ SourceLocation getEllipsisLoc() const {
+ return caseStmtIsGNURange() ? *getTrailingObjects<SourceLocation>()
+ : SourceLocation();
+ }
- Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); }
- Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); }
- Stmt *getSubStmt() { return SubExprs[SUBSTMT]; }
+ /// Set the location of the ... in a case statement of the form LHS ... RHS.
+ /// Assert that this case statement is of this form.
+ void setEllipsisLoc(SourceLocation L) {
+ assert(
+ caseStmtIsGNURange() &&
+ "setEllipsisLoc but this is not a case stmt of the form LHS ... RHS!");
+ *getTrailingObjects<SourceLocation>() = L;
+ }
+
+ Expr *getLHS() {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[lhsOffset()]);
+ }
const Expr *getLHS() const {
- return reinterpret_cast<const Expr*>(SubExprs[LHS]);
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[lhsOffset()]);
+ }
+
+ void setLHS(Expr *Val) {
+ getTrailingObjects<Stmt *>()[lhsOffset()] = reinterpret_cast<Stmt *>(Val);
+ }
+
+ Expr *getRHS() {
+ return caseStmtIsGNURange() ? reinterpret_cast<Expr *>(
+ getTrailingObjects<Stmt *>()[rhsOffset()])
+ : nullptr;
}
const Expr *getRHS() const {
- return reinterpret_cast<const Expr*>(SubExprs[RHS]);
+ return caseStmtIsGNURange() ? reinterpret_cast<Expr *>(
+ getTrailingObjects<Stmt *>()[rhsOffset()])
+ : nullptr;
}
- const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; }
+ void setRHS(Expr *Val) {
+ assert(caseStmtIsGNURange() &&
+ "setRHS but this is not a case stmt of the form LHS ... RHS!");
+ getTrailingObjects<Stmt *>()[rhsOffset()] = reinterpret_cast<Stmt *>(Val);
+ }
- void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; }
- void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); }
- void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); }
+ Stmt *getSubStmt() { return getTrailingObjects<Stmt *>()[subStmtOffset()]; }
+ const Stmt *getSubStmt() const {
+ return getTrailingObjects<Stmt *>()[subStmtOffset()];
+ }
- SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
+ void setSubStmt(Stmt *S) {
+ getTrailingObjects<Stmt *>()[subStmtOffset()] = S;
+ }
- SourceLocation getLocEnd() const LLVM_READONLY {
+ SourceLocation getBeginLoc() const { return getKeywordLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
// Handle deeply nested case statements with iteration instead of recursion.
const CaseStmt *CS = this;
while (const auto *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt()))
CS = CS2;
- return CS->getSubStmt()->getLocEnd();
+ return CS->getSubStmt()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -814,16 +1535,18 @@ public:
// Iterators
child_range children() {
- return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
+ return child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() +
+ numTrailingObjects(OverloadToken<Stmt *>()));
}
};
class DefaultStmt : public SwitchCase {
- Stmt* SubStmt;
+ Stmt *SubStmt;
public:
- DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
- SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {}
+ DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt)
+ : SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {}
/// Build an empty default statement.
explicit DefaultStmt(EmptyShell Empty)
@@ -833,59 +1556,70 @@ public:
const Stmt *getSubStmt() const { return SubStmt; }
void setSubStmt(Stmt *S) { SubStmt = S; }
- SourceLocation getDefaultLoc() const { return KeywordLoc; }
- void setDefaultLoc(SourceLocation L) { KeywordLoc = L; }
- SourceLocation getColonLoc() const { return ColonLoc; }
- void setColonLoc(SourceLocation L) { ColonLoc = L; }
+ SourceLocation getDefaultLoc() const { return getKeywordLoc(); }
+ void setDefaultLoc(SourceLocation L) { setKeywordLoc(L); }
- SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+ SourceLocation getBeginLoc() const { return getKeywordLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return SubStmt->getEndLoc();
+ }
static bool classof(const Stmt *T) {
return T->getStmtClass() == DefaultStmtClass;
}
// Iterators
- child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+ child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
};
-inline SourceLocation SwitchCase::getLocEnd() const {
+SourceLocation SwitchCase::getEndLoc() const {
if (const auto *CS = dyn_cast<CaseStmt>(this))
- return CS->getLocEnd();
- return cast<DefaultStmt>(this)->getLocEnd();
+ return CS->getEndLoc();
+ else if (const auto *DS = dyn_cast<DefaultStmt>(this))
+ return DS->getEndLoc();
+ llvm_unreachable("SwitchCase is neither a CaseStmt nor a DefaultStmt!");
+}
+
+Stmt *SwitchCase::getSubStmt() {
+ if (auto *CS = dyn_cast<CaseStmt>(this))
+ return CS->getSubStmt();
+ else if (auto *DS = dyn_cast<DefaultStmt>(this))
+ return DS->getSubStmt();
+ llvm_unreachable("SwitchCase is neither a CaseStmt nor a DefaultStmt!");
}
/// LabelStmt - Represents a label, which has a substatement. For example:
/// foo: return;
class LabelStmt : public Stmt {
- SourceLocation IdentLoc;
LabelDecl *TheDecl;
Stmt *SubStmt;
public:
+ /// Build a label statement.
LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)
- : Stmt(LabelStmtClass), IdentLoc(IL), TheDecl(D), SubStmt(substmt) {
- static_assert(sizeof(LabelStmt) ==
- 2 * sizeof(SourceLocation) + 2 * sizeof(void *),
- "LabelStmt too big");
+ : Stmt(LabelStmtClass), TheDecl(D), SubStmt(substmt) {
+ setIdentLoc(IL);
}
- // Build an empty label statement.
+ /// Build an empty label statement.
explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) {}
- SourceLocation getIdentLoc() const { return IdentLoc; }
+ SourceLocation getIdentLoc() const { return LabelStmtBits.IdentLoc; }
+ void setIdentLoc(SourceLocation L) { LabelStmtBits.IdentLoc = L; }
+
LabelDecl *getDecl() const { return TheDecl; }
void setDecl(LabelDecl *D) { TheDecl = D; }
+
const char *getName() const;
Stmt *getSubStmt() { return SubStmt; }
+
const Stmt *getSubStmt() const { return SubStmt; }
- void setIdentLoc(SourceLocation L) { IdentLoc = L; }
void setSubStmt(Stmt *SS) { SubStmt = SS; }
- SourceLocation getLocStart() const LLVM_READONLY { return IdentLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+ SourceLocation getBeginLoc() const { return getIdentLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return SubStmt->getEndLoc();}
- child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+ child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == LabelStmtClass;
@@ -903,17 +1637,19 @@ class AttributedStmt final
friend TrailingObjects;
Stmt *SubStmt;
- SourceLocation AttrLoc;
- unsigned NumAttrs;
- AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
- : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
- NumAttrs(Attrs.size()) {
+ AttributedStmt(SourceLocation Loc, ArrayRef<const Attr *> Attrs,
+ Stmt *SubStmt)
+ : Stmt(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), NumAttrs(NumAttrs) {
+ : Stmt(AttributedStmtClass, Empty) {
+ AttributedStmtBits.NumAttrs = NumAttrs;
+ AttributedStmtBits.AttrLoc = SourceLocation{};
std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr);
}
@@ -924,21 +1660,21 @@ class AttributedStmt final
public:
static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
- ArrayRef<const Attr*> Attrs, Stmt *SubStmt);
+ ArrayRef<const Attr *> Attrs, Stmt *SubStmt);
// Build an empty attributed statement.
static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs);
- SourceLocation getAttrLoc() const { return AttrLoc; }
- ArrayRef<const Attr*> getAttrs() const {
- return llvm::makeArrayRef(getAttrArrayPtr(), NumAttrs);
+ SourceLocation getAttrLoc() const { return AttributedStmtBits.AttrLoc; }
+ ArrayRef<const Attr *> getAttrs() const {
+ return llvm::makeArrayRef(getAttrArrayPtr(), AttributedStmtBits.NumAttrs);
}
Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; }
- SourceLocation getLocStart() const LLVM_READONLY { return AttrLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();}
+ SourceLocation getBeginLoc() const { return getAttrLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return SubStmt->getEndLoc();}
child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
@@ -948,21 +1684,117 @@ public:
};
/// IfStmt - This represents an if/then/else.
-class IfStmt : public Stmt {
- enum { INIT, VAR, COND, THEN, ELSE, END_EXPR };
- Stmt* SubExprs[END_EXPR];
+class IfStmt final
+ : public Stmt,
+ private llvm::TrailingObjects<IfStmt, Stmt *, SourceLocation> {
+ friend TrailingObjects;
- SourceLocation IfLoc;
- SourceLocation ElseLoc;
+ // IfStmt is followed by several trailing objects, some of which optional.
+ // Note that it would be more convenient to put the optional trailing
+ // objects at then end but this would change the order of the children.
+ // The trailing objects are in order:
+ //
+ // * A "Stmt *" for the init statement.
+ // Present if and only if hasInitStorage().
+ //
+ // * A "Stmt *" for the condition variable.
+ // Present if and only if hasVarStorage(). This is in fact a "DeclStmt *".
+ //
+ // * A "Stmt *" for the condition.
+ // Always present. This is in fact a "Expr *".
+ //
+ // * A "Stmt *" for the then statement.
+ // Always present.
+ //
+ // * A "Stmt *" for the else statement.
+ // Present if and only if hasElseStorage().
+ //
+ // * A "SourceLocation" for the location of the "else".
+ // Present if and only if hasElseStorage().
+ enum { InitOffset = 0, ThenOffsetFromCond = 1, ElseOffsetFromCond = 2 };
+ enum { NumMandatoryStmtPtr = 2 };
+
+ unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+ return NumMandatoryStmtPtr + hasElseStorage() + hasVarStorage() +
+ hasInitStorage();
+ }
+
+ unsigned numTrailingObjects(OverloadToken<SourceLocation>) const {
+ return hasElseStorage();
+ }
+
+ unsigned initOffset() const { return InitOffset; }
+ unsigned varOffset() const { return InitOffset + hasInitStorage(); }
+ unsigned condOffset() const {
+ return InitOffset + hasInitStorage() + hasVarStorage();
+ }
+ unsigned thenOffset() const { return condOffset() + ThenOffsetFromCond; }
+ unsigned elseOffset() const { return condOffset() + ElseOffsetFromCond; }
+
+ /// Build an if/then/else statement.
+ IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr, Stmt *Init,
+ VarDecl *Var, Expr *Cond, Stmt *Then, SourceLocation EL, Stmt *Else);
+
+ /// Build an empty if/then/else statement.
+ explicit IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit);
public:
- IfStmt(const ASTContext &C, SourceLocation IL,
- bool IsConstexpr, Stmt *init, VarDecl *var, Expr *cond,
- Stmt *then, SourceLocation EL = SourceLocation(),
- Stmt *elsev = nullptr);
+ /// Create an IfStmt.
+ static IfStmt *Create(const ASTContext &Ctx, SourceLocation IL,
+ bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond,
+ Stmt *Then, SourceLocation EL = SourceLocation(),
+ Stmt *Else = nullptr);
+
+ /// Create an empty IfStmt optionally with storage for an else statement,
+ /// condition variable and init expression.
+ static IfStmt *CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar,
+ bool HasInit);
- /// Build an empty if/then/else statement
- explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) {}
+ /// True if this IfStmt has the storage for an init statement.
+ bool hasInitStorage() const { return IfStmtBits.HasInit; }
+
+ /// True if this IfStmt has storage for a variable declaration.
+ bool hasVarStorage() const { return IfStmtBits.HasVar; }
+
+ /// True if this IfStmt has storage for an else statement.
+ bool hasElseStorage() const { return IfStmtBits.HasElse; }
+
+ Expr *getCond() {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ const Expr *getCond() const {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ void setCond(Expr *Cond) {
+ getTrailingObjects<Stmt *>()[condOffset()] = reinterpret_cast<Stmt *>(Cond);
+ }
+
+ Stmt *getThen() { return getTrailingObjects<Stmt *>()[thenOffset()]; }
+ const Stmt *getThen() const {
+ return getTrailingObjects<Stmt *>()[thenOffset()];
+ }
+
+ void setThen(Stmt *Then) {
+ getTrailingObjects<Stmt *>()[thenOffset()] = Then;
+ }
+
+ Stmt *getElse() {
+ return hasElseStorage() ? getTrailingObjects<Stmt *>()[elseOffset()]
+ : nullptr;
+ }
+
+ const Stmt *getElse() const {
+ return hasElseStorage() ? getTrailingObjects<Stmt *>()[elseOffset()]
+ : nullptr;
+ }
+
+ void setElse(Stmt *Else) {
+ assert(hasElseStorage() &&
+ "This if statement has no storage for an else statement!");
+ getTrailingObjects<Stmt *>()[elseOffset()] = Else;
+ }
/// Retrieve the variable declared in this "if" statement, if any.
///
@@ -972,52 +1804,77 @@ public:
/// printf("x is %d", x);
/// }
/// \endcode
- VarDecl *getConditionVariable() const;
- void setConditionVariable(const ASTContext &C, VarDecl *V);
+ VarDecl *getConditionVariable();
+ const VarDecl *getConditionVariable() const {
+ return const_cast<IfStmt *>(this)->getConditionVariable();
+ }
+
+ /// Set the condition variable for this if statement.
+ /// The if statement must have storage for the condition variable.
+ void setConditionVariable(const ASTContext &Ctx, VarDecl *V);
/// If this IfStmt has a condition variable, return the faux DeclStmt
/// associated with the creation of that condition variable.
+ DeclStmt *getConditionVariableDeclStmt() {
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
+ }
+
const DeclStmt *getConditionVariableDeclStmt() const {
- return reinterpret_cast<DeclStmt*>(SubExprs[VAR]);
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
}
- Stmt *getInit() { return SubExprs[INIT]; }
- const Stmt *getInit() const { return SubExprs[INIT]; }
- void setInit(Stmt *S) { SubExprs[INIT] = S; }
- const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
- void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
- const Stmt *getThen() const { return SubExprs[THEN]; }
- void setThen(Stmt *S) { SubExprs[THEN] = S; }
- const Stmt *getElse() const { return SubExprs[ELSE]; }
- void setElse(Stmt *S) { SubExprs[ELSE] = S; }
+ Stmt *getInit() {
+ return hasInitStorage() ? getTrailingObjects<Stmt *>()[initOffset()]
+ : nullptr;
+ }
- Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
- Stmt *getThen() { return SubExprs[THEN]; }
- Stmt *getElse() { return SubExprs[ELSE]; }
+ const Stmt *getInit() const {
+ return hasInitStorage() ? getTrailingObjects<Stmt *>()[initOffset()]
+ : nullptr;
+ }
- SourceLocation getIfLoc() const { return IfLoc; }
- void setIfLoc(SourceLocation L) { IfLoc = L; }
- SourceLocation getElseLoc() const { return ElseLoc; }
- void setElseLoc(SourceLocation L) { ElseLoc = L; }
+ void setInit(Stmt *Init) {
+ assert(hasInitStorage() &&
+ "This if statement has no storage for an init statement!");
+ getTrailingObjects<Stmt *>()[initOffset()] = Init;
+ }
+
+ SourceLocation getIfLoc() const { return IfStmtBits.IfLoc; }
+ void setIfLoc(SourceLocation IfLoc) { IfStmtBits.IfLoc = IfLoc; }
+
+ SourceLocation getElseLoc() const {
+ return hasElseStorage() ? *getTrailingObjects<SourceLocation>()
+ : SourceLocation();
+ }
+
+ void setElseLoc(SourceLocation ElseLoc) {
+ assert(hasElseStorage() &&
+ "This if statement has no storage for an else statement!");
+ *getTrailingObjects<SourceLocation>() = ElseLoc;
+ }
bool isConstexpr() const { return IfStmtBits.IsConstexpr; }
void setConstexpr(bool C) { IfStmtBits.IsConstexpr = C; }
bool isObjCAvailabilityCheck() const;
- SourceLocation getLocStart() const LLVM_READONLY { return IfLoc; }
-
- SourceLocation getLocEnd() const LLVM_READONLY {
- if (SubExprs[ELSE])
- return SubExprs[ELSE]->getLocEnd();
- else
- return SubExprs[THEN]->getLocEnd();
+ SourceLocation getBeginLoc() const { return getIfLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ if (getElse())
+ return getElse()->getEndLoc();
+ return getThen()->getEndLoc();
}
// Iterators over subexpressions. The iterators will include iterating
// over the initialization expression referenced by the condition variable.
child_range children() {
- return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ return child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() +
+ numTrailingObjects(OverloadToken<Stmt *>()));
}
static bool classof(const Stmt *T) {
@@ -1026,22 +1883,102 @@ public:
};
/// SwitchStmt - This represents a 'switch' stmt.
-class SwitchStmt : public Stmt {
- SourceLocation SwitchLoc;
- enum { INIT, VAR, COND, BODY, END_EXPR };
- Stmt* SubExprs[END_EXPR];
+class SwitchStmt final : public Stmt,
+ private llvm::TrailingObjects<SwitchStmt, Stmt *> {
+ friend TrailingObjects;
- // 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
- // to be a hint for possible clients.
- llvm::PointerIntPair<SwitchCase *, 1, bool> FirstCase;
+ /// Points to a linked list of case and default statements.
+ SwitchCase *FirstCase;
+
+ // SwitchStmt is followed by several trailing objects,
+ // some of which optional. Note that it would be more convenient to
+ // put the optional trailing objects at the end but this would change
+ // the order in children().
+ // The trailing objects are in order:
+ //
+ // * A "Stmt *" for the init statement.
+ // Present if and only if hasInitStorage().
+ //
+ // * A "Stmt *" for the condition variable.
+ // Present if and only if hasVarStorage(). This is in fact a "DeclStmt *".
+ //
+ // * A "Stmt *" for the condition.
+ // Always present. This is in fact an "Expr *".
+ //
+ // * A "Stmt *" for the body.
+ // Always present.
+ enum { InitOffset = 0, BodyOffsetFromCond = 1 };
+ enum { NumMandatoryStmtPtr = 2 };
+
+ unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+ return NumMandatoryStmtPtr + hasInitStorage() + hasVarStorage();
+ }
+
+ unsigned initOffset() const { return InitOffset; }
+ unsigned varOffset() const { return InitOffset + hasInitStorage(); }
+ unsigned condOffset() const {
+ return InitOffset + hasInitStorage() + hasVarStorage();
+ }
+ unsigned bodyOffset() const { return condOffset() + BodyOffsetFromCond; }
+
+ /// Build a switch statement.
+ SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, Expr *Cond);
+
+ /// Build a empty switch statement.
+ explicit SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar);
public:
- SwitchStmt(const ASTContext &C, Stmt *Init, VarDecl *Var, Expr *cond);
+ /// Create a switch statement.
+ static SwitchStmt *Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
+ Expr *Cond);
- /// Build a empty switch statement.
- explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) {}
+ /// Create an empty switch statement optionally with storage for
+ /// an init expression and a condition variable.
+ static SwitchStmt *CreateEmpty(const ASTContext &Ctx, bool HasInit,
+ bool HasVar);
+
+ /// True if this SwitchStmt has storage for an init statement.
+ bool hasInitStorage() const { return SwitchStmtBits.HasInit; }
+
+ /// True if this SwitchStmt has storage for a condition variable.
+ bool hasVarStorage() const { return SwitchStmtBits.HasVar; }
+
+ Expr *getCond() {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ const Expr *getCond() const {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ void setCond(Expr *Cond) {
+ getTrailingObjects<Stmt *>()[condOffset()] = reinterpret_cast<Stmt *>(Cond);
+ }
+
+ Stmt *getBody() { return getTrailingObjects<Stmt *>()[bodyOffset()]; }
+ const Stmt *getBody() const {
+ return getTrailingObjects<Stmt *>()[bodyOffset()];
+ }
+
+ void setBody(Stmt *Body) {
+ getTrailingObjects<Stmt *>()[bodyOffset()] = Body;
+ }
+
+ Stmt *getInit() {
+ return hasInitStorage() ? getTrailingObjects<Stmt *>()[initOffset()]
+ : nullptr;
+ }
+
+ const Stmt *getInit() const {
+ return hasInitStorage() ? getTrailingObjects<Stmt *>()[initOffset()]
+ : nullptr;
+ }
+
+ void setInit(Stmt *Init) {
+ assert(hasInitStorage() &&
+ "This switch statement has no storage for an init statement!");
+ getTrailingObjects<Stmt *>()[initOffset()] = Init;
+ }
/// Retrieve the variable declared in this "switch" statement, if any.
///
@@ -1052,63 +1989,69 @@ public:
/// // ...
/// }
/// \endcode
- VarDecl *getConditionVariable() const;
- void setConditionVariable(const ASTContext &C, VarDecl *V);
+ VarDecl *getConditionVariable();
+ const VarDecl *getConditionVariable() const {
+ return const_cast<SwitchStmt *>(this)->getConditionVariable();
+ }
+
+ /// Set the condition variable in this switch statement.
+ /// The switch statement must have storage for it.
+ void setConditionVariable(const ASTContext &Ctx, VarDecl *VD);
/// If this SwitchStmt has a condition variable, return the faux DeclStmt
/// associated with the creation of that condition variable.
- const DeclStmt *getConditionVariableDeclStmt() const {
- return reinterpret_cast<DeclStmt*>(SubExprs[VAR]);
+ DeclStmt *getConditionVariableDeclStmt() {
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
}
- Stmt *getInit() { return SubExprs[INIT]; }
- const Stmt *getInit() const { return SubExprs[INIT]; }
- void setInit(Stmt *S) { SubExprs[INIT] = S; }
- const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
- const Stmt *getBody() const { return SubExprs[BODY]; }
- const SwitchCase *getSwitchCaseList() const { return FirstCase.getPointer(); }
-
- Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);}
- void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
- Stmt *getBody() { return SubExprs[BODY]; }
- void setBody(Stmt *S) { SubExprs[BODY] = S; }
- SwitchCase *getSwitchCaseList() { return FirstCase.getPointer(); }
+ const DeclStmt *getConditionVariableDeclStmt() const {
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
+ }
- /// Set the case list for this switch statement.
- void setSwitchCaseList(SwitchCase *SC) { FirstCase.setPointer(SC); }
+ SwitchCase *getSwitchCaseList() { return FirstCase; }
+ const SwitchCase *getSwitchCaseList() const { return FirstCase; }
+ void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
- SourceLocation getSwitchLoc() const { return SwitchLoc; }
- void setSwitchLoc(SourceLocation L) { SwitchLoc = L; }
+ SourceLocation getSwitchLoc() const { return SwitchStmtBits.SwitchLoc; }
+ void setSwitchLoc(SourceLocation L) { SwitchStmtBits.SwitchLoc = L; }
void setBody(Stmt *S, SourceLocation SL) {
- SubExprs[BODY] = S;
- SwitchLoc = SL;
+ setBody(S);
+ setSwitchLoc(SL);
}
void addSwitchCase(SwitchCase *SC) {
- assert(!SC->getNextSwitchCase()
- && "case/default already added to a switch");
- SC->setNextSwitchCase(FirstCase.getPointer());
- FirstCase.setPointer(SC);
+ assert(!SC->getNextSwitchCase() &&
+ "case/default already added to a switch");
+ SC->setNextSwitchCase(FirstCase);
+ FirstCase = SC;
}
/// Set a flag in the SwitchStmt indicating that if the 'switch (X)' is a
/// switch over an enum value then all cases have been explicitly covered.
- void setAllEnumCasesCovered() { FirstCase.setInt(true); }
+ void setAllEnumCasesCovered() { SwitchStmtBits.AllEnumCasesCovered = true; }
/// Returns true if the SwitchStmt is a switch of an enum value and all cases
/// have been explicitly covered.
- bool isAllEnumCasesCovered() const { return FirstCase.getInt(); }
-
- SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; }
+ bool isAllEnumCasesCovered() const {
+ return SwitchStmtBits.AllEnumCasesCovered;
+ }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return SubExprs[BODY] ? SubExprs[BODY]->getLocEnd() : SubExprs[COND]->getLocEnd();
+ SourceLocation getBeginLoc() const { return getSwitchLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getBody() ? getBody()->getEndLoc()
+ : reinterpret_cast<const Stmt *>(getCond())->getEndLoc();
}
// Iterators
child_range children() {
- return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ return child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() +
+ numTrailingObjects(OverloadToken<Stmt *>()));
}
static bool classof(const Stmt *T) {
@@ -1117,17 +2060,75 @@ public:
};
/// WhileStmt - This represents a 'while' stmt.
-class WhileStmt : public Stmt {
- SourceLocation WhileLoc;
- enum { VAR, COND, BODY, END_EXPR };
- Stmt* SubExprs[END_EXPR];
+class WhileStmt final : public Stmt,
+ private llvm::TrailingObjects<WhileStmt, Stmt *> {
+ friend TrailingObjects;
-public:
- WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
+ // WhileStmt is followed by several trailing objects,
+ // some of which optional. Note that it would be more
+ // convenient to put the optional trailing object at the end
+ // but this would affect children().
+ // The trailing objects are in order:
+ //
+ // * A "Stmt *" for the condition variable.
+ // Present if and only if hasVarStorage(). This is in fact a "DeclStmt *".
+ //
+ // * A "Stmt *" for the condition.
+ // Always present. This is in fact an "Expr *".
+ //
+ // * A "Stmt *" for the body.
+ // Always present.
+ //
+ enum { VarOffset = 0, BodyOffsetFromCond = 1 };
+ enum { NumMandatoryStmtPtr = 2 };
+
+ unsigned varOffset() const { return VarOffset; }
+ unsigned condOffset() const { return VarOffset + hasVarStorage(); }
+ unsigned bodyOffset() const { return condOffset() + BodyOffsetFromCond; }
+
+ unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+ return NumMandatoryStmtPtr + hasVarStorage();
+ }
+
+ /// Build a while statement.
+ WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, Stmt *Body,
SourceLocation WL);
/// Build an empty while statement.
- explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) {}
+ explicit WhileStmt(EmptyShell Empty, bool HasVar);
+
+public:
+ /// Create a while statement.
+ static WhileStmt *Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
+ Stmt *Body, SourceLocation WL);
+
+ /// Create an empty while statement optionally with storage for
+ /// a condition variable.
+ static WhileStmt *CreateEmpty(const ASTContext &Ctx, bool HasVar);
+
+ /// True if this WhileStmt has storage for a condition variable.
+ bool hasVarStorage() const { return WhileStmtBits.HasVar; }
+
+ Expr *getCond() {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ const Expr *getCond() const {
+ return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[condOffset()]);
+ }
+
+ void setCond(Expr *Cond) {
+ getTrailingObjects<Stmt *>()[condOffset()] = reinterpret_cast<Stmt *>(Cond);
+ }
+
+ Stmt *getBody() { return getTrailingObjects<Stmt *>()[bodyOffset()]; }
+ const Stmt *getBody() const {
+ return getTrailingObjects<Stmt *>()[bodyOffset()];
+ }
+
+ void setBody(Stmt *Body) {
+ getTrailingObjects<Stmt *>()[bodyOffset()] = Body;
+ }
/// Retrieve the variable declared in this "while" statement, if any.
///
@@ -1137,29 +2138,35 @@ public:
/// // ...
/// }
/// \endcode
- VarDecl *getConditionVariable() const;
- void setConditionVariable(const ASTContext &C, VarDecl *V);
+ VarDecl *getConditionVariable();
+ const VarDecl *getConditionVariable() const {
+ return const_cast<WhileStmt *>(this)->getConditionVariable();
+ }
+
+ /// Set the condition variable of this while statement.
+ /// The while statement must have storage for it.
+ void setConditionVariable(const ASTContext &Ctx, VarDecl *V);
/// If this WhileStmt has a condition variable, return the faux DeclStmt
/// associated with the creation of that condition variable.
- const DeclStmt *getConditionVariableDeclStmt() const {
- return reinterpret_cast<DeclStmt*>(SubExprs[VAR]);
+ DeclStmt *getConditionVariableDeclStmt() {
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
}
- Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
- const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
- void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
- Stmt *getBody() { return SubExprs[BODY]; }
- const Stmt *getBody() const { return SubExprs[BODY]; }
- void setBody(Stmt *S) { SubExprs[BODY] = S; }
-
- SourceLocation getWhileLoc() const { return WhileLoc; }
- void setWhileLoc(SourceLocation L) { WhileLoc = L; }
+ const DeclStmt *getConditionVariableDeclStmt() const {
+ return hasVarStorage() ? static_cast<DeclStmt *>(
+ getTrailingObjects<Stmt *>()[varOffset()])
+ : nullptr;
+ }
- SourceLocation getLocStart() const LLVM_READONLY { return WhileLoc; }
+ SourceLocation getWhileLoc() const { return WhileStmtBits.WhileLoc; }
+ void setWhileLoc(SourceLocation L) { WhileStmtBits.WhileLoc = L; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return SubExprs[BODY]->getLocEnd();
+ SourceLocation getBeginLoc() const { return getWhileLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getBody()->getEndLoc();
}
static bool classof(const Stmt *T) {
@@ -1168,46 +2175,51 @@ public:
// Iterators
child_range children() {
- return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ return child_range(getTrailingObjects<Stmt *>(),
+ getTrailingObjects<Stmt *>() +
+ numTrailingObjects(OverloadToken<Stmt *>()));
}
};
/// DoStmt - This represents a 'do/while' stmt.
class DoStmt : public Stmt {
- SourceLocation DoLoc;
enum { BODY, COND, END_EXPR };
- Stmt* SubExprs[END_EXPR];
+ Stmt *SubExprs[END_EXPR];
SourceLocation WhileLoc;
- SourceLocation RParenLoc; // Location of final ')' in do stmt condition.
+ SourceLocation RParenLoc; // Location of final ')' in do stmt condition.
public:
- DoStmt(Stmt *body, Expr *cond, SourceLocation DL, SourceLocation WL,
+ DoStmt(Stmt *Body, Expr *Cond, SourceLocation DL, SourceLocation WL,
SourceLocation RP)
- : Stmt(DoStmtClass), DoLoc(DL), WhileLoc(WL), RParenLoc(RP) {
- SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
- SubExprs[BODY] = body;
+ : Stmt(DoStmtClass), WhileLoc(WL), RParenLoc(RP) {
+ setCond(Cond);
+ setBody(Body);
+ setDoLoc(DL);
}
/// Build an empty do-while statement.
explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) {}
- Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
- const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
- void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); }
+ Expr *getCond() { return reinterpret_cast<Expr *>(SubExprs[COND]); }
+ const Expr *getCond() const {
+ return reinterpret_cast<Expr *>(SubExprs[COND]);
+ }
+
+ void setCond(Expr *Cond) { SubExprs[COND] = reinterpret_cast<Stmt *>(Cond); }
+
Stmt *getBody() { return SubExprs[BODY]; }
const Stmt *getBody() const { return SubExprs[BODY]; }
- void setBody(Stmt *S) { SubExprs[BODY] = S; }
+ void setBody(Stmt *Body) { SubExprs[BODY] = Body; }
- SourceLocation getDoLoc() const { return DoLoc; }
- void setDoLoc(SourceLocation L) { DoLoc = L; }
+ SourceLocation getDoLoc() const { return DoStmtBits.DoLoc; }
+ void setDoLoc(SourceLocation L) { DoStmtBits.DoLoc = L; }
SourceLocation getWhileLoc() const { return WhileLoc; }
void setWhileLoc(SourceLocation L) { WhileLoc = L; }
-
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return DoLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const { return getDoLoc(); }
+ SourceLocation getEndLoc() const { return getRParenLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == DoStmtClass;
@@ -1215,7 +2227,7 @@ public:
// Iterators
child_range children() {
- return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR);
+ return child_range(&SubExprs[0], &SubExprs[0] + END_EXPR);
}
};
@@ -1223,7 +2235,6 @@ public:
/// 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 };
Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
SourceLocation LParenLoc, RParenLoc;
@@ -1269,18 +2280,15 @@ public:
void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); }
void setBody(Stmt *S) { SubExprs[BODY] = S; }
- SourceLocation getForLoc() const { return ForLoc; }
- void setForLoc(SourceLocation L) { ForLoc = L; }
+ SourceLocation getForLoc() const { return ForStmtBits.ForLoc; }
+ void setForLoc(SourceLocation L) { ForStmtBits.ForLoc = L; }
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; }
-
- SourceLocation getLocEnd() const LLVM_READONLY {
- return SubExprs[BODY]->getLocEnd();
- }
+ SourceLocation getBeginLoc() const { return getForLoc(); }
+ SourceLocation getEndLoc() const { return getBody()->getEndLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ForStmtClass;
@@ -1295,12 +2303,13 @@ 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), LabelLoc(LL) {
+ setGotoLoc(GL);
+ }
/// Build an empty goto statement.
explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) {}
@@ -1308,13 +2317,13 @@ public:
LabelDecl *getLabel() const { return Label; }
void setLabel(LabelDecl *D) { Label = D; }
- SourceLocation getGotoLoc() const { return GotoLoc; }
- void setGotoLoc(SourceLocation L) { GotoLoc = L; }
+ SourceLocation getGotoLoc() const { return GotoStmtBits.GotoLoc; }
+ void setGotoLoc(SourceLocation L) { GotoStmtBits.GotoLoc = L; }
SourceLocation getLabelLoc() const { return LabelLoc; }
void setLabelLoc(SourceLocation L) { LabelLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return GotoLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return LabelLoc; }
+ SourceLocation getBeginLoc() const { return getGotoLoc(); }
+ SourceLocation getEndLoc() const { return getLabelLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == GotoStmtClass;
@@ -1328,62 +2337,64 @@ 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)
- : Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc),
- Target((Stmt*)target) {}
+ IndirectGotoStmt(SourceLocation gotoLoc, SourceLocation starLoc, Expr *target)
+ : Stmt(IndirectGotoStmtClass), StarLoc(starLoc) {
+ setTarget(target);
+ setGotoLoc(gotoLoc);
+ }
/// Build an empty indirect goto statement.
explicit IndirectGotoStmt(EmptyShell Empty)
: Stmt(IndirectGotoStmtClass, Empty) {}
- void setGotoLoc(SourceLocation L) { GotoLoc = L; }
- SourceLocation getGotoLoc() const { return GotoLoc; }
+ void setGotoLoc(SourceLocation L) { GotoStmtBits.GotoLoc = L; }
+ SourceLocation getGotoLoc() const { return GotoStmtBits.GotoLoc; }
void setStarLoc(SourceLocation L) { StarLoc = L; }
SourceLocation getStarLoc() const { return StarLoc; }
- Expr *getTarget() { return reinterpret_cast<Expr*>(Target); }
- const Expr *getTarget() const {return reinterpret_cast<const Expr*>(Target);}
- void setTarget(Expr *E) { Target = reinterpret_cast<Stmt*>(E); }
+ Expr *getTarget() { return reinterpret_cast<Expr *>(Target); }
+ const Expr *getTarget() const {
+ return reinterpret_cast<const Expr *>(Target);
+ }
+ void setTarget(Expr *E) { Target = reinterpret_cast<Stmt *>(E); }
/// getConstantTarget - Returns the fixed target of this indirect
/// goto, if one exists.
LabelDecl *getConstantTarget();
const LabelDecl *getConstantTarget() const {
- return const_cast<IndirectGotoStmt*>(this)->getConstantTarget();
+ return const_cast<IndirectGotoStmt *>(this)->getConstantTarget();
}
- SourceLocation getLocStart() const LLVM_READONLY { return GotoLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return Target->getLocEnd(); }
+ SourceLocation getBeginLoc() const { return getGotoLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY { return Target->getEndLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == IndirectGotoStmtClass;
}
// Iterators
- child_range children() { return child_range(&Target, &Target+1); }
+ 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) {}
+ ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass) {
+ setContinueLoc(CL);
+ }
/// Build an empty continue statement.
explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) {}
- SourceLocation getContinueLoc() const { return ContinueLoc; }
- void setContinueLoc(SourceLocation L) { ContinueLoc = L; }
+ SourceLocation getContinueLoc() const { return ContinueStmtBits.ContinueLoc; }
+ void setContinueLoc(SourceLocation L) { ContinueStmtBits.ContinueLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return ContinueLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return ContinueLoc; }
+ SourceLocation getBeginLoc() const { return getContinueLoc(); }
+ SourceLocation getEndLoc() const { return getContinueLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ContinueStmtClass;
@@ -1397,22 +2408,19 @@ public:
/// BreakStmt - This represents a break.
class BreakStmt : public Stmt {
- SourceLocation BreakLoc;
-
public:
- BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {
- static_assert(sizeof(BreakStmt) == 2 * sizeof(SourceLocation),
- "BreakStmt too large");
+ BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass) {
+ setBreakLoc(BL);
}
/// Build an empty break statement.
explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) {}
- SourceLocation getBreakLoc() const { return BreakLoc; }
- void setBreakLoc(SourceLocation L) { BreakLoc = L; }
+ SourceLocation getBreakLoc() const { return BreakStmtBits.BreakLoc; }
+ void setBreakLoc(SourceLocation L) { BreakStmtBits.BreakLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return BreakLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return BreakLoc; }
+ SourceLocation getBeginLoc() const { return getBreakLoc(); }
+ SourceLocation getEndLoc() const { return getBreakLoc(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == BreakStmtClass;
@@ -1432,40 +2440,68 @@ 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;
+class ReturnStmt final
+ : public Stmt,
+ private llvm::TrailingObjects<ReturnStmt, const VarDecl *> {
+ friend TrailingObjects;
+
+ /// The return expression.
Stmt *RetExpr;
- const VarDecl *NRVOCandidate;
-public:
- explicit ReturnStmt(SourceLocation RL) : ReturnStmt(RL, nullptr, nullptr) {}
+ // ReturnStmt is followed optionally by a trailing "const VarDecl *"
+ // for the NRVO candidate. Present if and only if hasNRVOCandidate().
- ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
- : Stmt(ReturnStmtClass), RetLoc(RL), RetExpr((Stmt *)E),
- NRVOCandidate(NRVOCandidate) {}
+ /// True if this ReturnStmt has storage for an NRVO candidate.
+ bool hasNRVOCandidate() const { return ReturnStmtBits.HasNRVOCandidate; }
- /// Build an empty return expression.
- explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) {}
+ unsigned numTrailingObjects(OverloadToken<const VarDecl *>) const {
+ return hasNRVOCandidate();
+ }
+
+ /// Build a return statement.
+ ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate);
+
+ /// Build an empty return statement.
+ explicit ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate);
+
+public:
+ /// Create a return statement.
+ static ReturnStmt *Create(const ASTContext &Ctx, SourceLocation RL, Expr *E,
+ const VarDecl *NRVOCandidate);
- const Expr *getRetValue() const;
- Expr *getRetValue();
- void setRetValue(Expr *E) { RetExpr = reinterpret_cast<Stmt*>(E); }
+ /// Create an empty return statement, optionally with
+ /// storage for an NRVO candidate.
+ static ReturnStmt *CreateEmpty(const ASTContext &Ctx, bool HasNRVOCandidate);
- SourceLocation getReturnLoc() const { return RetLoc; }
- void setReturnLoc(SourceLocation L) { RetLoc = L; }
+ Expr *getRetValue() { return reinterpret_cast<Expr *>(RetExpr); }
+ const Expr *getRetValue() const { return reinterpret_cast<Expr *>(RetExpr); }
+ void setRetValue(Expr *E) { RetExpr = reinterpret_cast<Stmt *>(E); }
/// Retrieve the variable that might be used for the named return
/// value optimization.
///
/// The optimization itself can only be performed if the variable is
/// also marked as an NRVO object.
- const VarDecl *getNRVOCandidate() const { return NRVOCandidate; }
- void setNRVOCandidate(const VarDecl *Var) { NRVOCandidate = Var; }
+ const VarDecl *getNRVOCandidate() const {
+ return hasNRVOCandidate() ? *getTrailingObjects<const VarDecl *>()
+ : nullptr;
+ }
+
+ /// Set the variable that might be used for the named return value
+ /// optimization. The return statement must have storage for it,
+ /// which is the case if and only if hasNRVOCandidate() is true.
+ void setNRVOCandidate(const VarDecl *Var) {
+ assert(hasNRVOCandidate() &&
+ "This return statement has no storage for an NRVO candidate!");
+ *getTrailingObjects<const VarDecl *>() = Var;
+ }
- SourceLocation getLocStart() const LLVM_READONLY { return RetLoc; }
+ SourceLocation getReturnLoc() const { return ReturnStmtBits.RetLoc; }
+ void setReturnLoc(SourceLocation L) { ReturnStmtBits.RetLoc = L; }
- SourceLocation getLocEnd() const LLVM_READONLY {
- return RetExpr ? RetExpr->getLocEnd() : RetLoc;
+ SourceLocation getBeginLoc() const { return getReturnLoc(); }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return RetExpr ? RetExpr->getEndLoc() : getReturnLoc();
}
static bool classof(const Stmt *T) {
@@ -1474,7 +2510,8 @@ public:
// Iterators
child_range children() {
- if (RetExpr) return child_range(&RetExpr, &RetExpr+1);
+ if (RetExpr)
+ return child_range(&RetExpr, &RetExpr + 1);
return child_range(child_iterator(), child_iterator());
}
};
@@ -1519,8 +2556,8 @@ public:
bool isVolatile() const { return IsVolatile; }
void setVolatile(bool V) { IsVolatile = V; }
- SourceLocation getLocStart() const LLVM_READONLY { return {}; }
- SourceLocation getLocEnd() const LLVM_READONLY { return {}; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return {}; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return {}; }
//===--- Asm String Analysis ---===//
@@ -1801,8 +2838,8 @@ public:
return Clobbers[i];
}
- SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AsmLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == GCCAsmStmtClass;
@@ -1899,8 +2936,7 @@ private:
ArrayRef<Expr*> Exprs, ArrayRef<StringRef> Clobbers);
public:
- SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return EndLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return AsmLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == MSAsmStmtClass;
@@ -1929,11 +2965,10 @@ public:
Expr *FilterExpr,
Stmt *Block);
- SourceLocation getLocStart() const LLVM_READONLY { return getExceptLoc(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return getExceptLoc(); }
SourceLocation getExceptLoc() const { return Loc; }
- SourceLocation getEndLoc() const { return getBlock()->getLocEnd(); }
+ SourceLocation getEndLoc() const { return getBlock()->getEndLoc(); }
Expr *getFilterExpr() const {
return reinterpret_cast<Expr*>(Children[FILTER_EXPR]);
@@ -1967,11 +3002,10 @@ public:
SourceLocation FinallyLoc,
Stmt *Block);
- SourceLocation getLocStart() const LLVM_READONLY { return getFinallyLoc(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return getFinallyLoc(); }
SourceLocation getFinallyLoc() const { return Loc; }
- SourceLocation getEndLoc() const { return Block->getLocEnd(); }
+ SourceLocation getEndLoc() const { return Block->getEndLoc(); }
CompoundStmt *getBlock() const { return cast<CompoundStmt>(Block); }
@@ -2006,11 +3040,10 @@ public:
SourceLocation TryLoc, Stmt *TryBlock,
Stmt *Handler);
- SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
- SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return getTryLoc(); }
SourceLocation getTryLoc() const { return TryLoc; }
- SourceLocation getEndLoc() const { return Children[HANDLER]->getLocEnd(); }
+ SourceLocation getEndLoc() const { return Children[HANDLER]->getEndLoc(); }
bool getIsCXXTry() const { return IsCXXTry; }
@@ -2047,8 +3080,8 @@ public:
SourceLocation getLeaveLoc() const { return LeaveLoc; }
void setLeaveLoc(SourceLocation L) { LeaveLoc = L; }
- SourceLocation getLocStart() const LLVM_READONLY { return LeaveLoc; }
- SourceLocation getLocEnd() const LLVM_READONLY { return LeaveLoc; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return LeaveLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return LeaveLoc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == SEHLeaveStmtClass;
@@ -2261,12 +3294,12 @@ public:
return capture_init_begin() + NumCaptures;
}
- SourceLocation getLocStart() const LLVM_READONLY {
- return getCapturedStmt()->getLocStart();
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getCapturedStmt()->getBeginLoc();
}
- SourceLocation getLocEnd() const LLVM_READONLY {
- return getCapturedStmt()->getLocEnd();
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getCapturedStmt()->getEndLoc();
}
SourceRange getSourceRange() const LLVM_READONLY {