diff options
Diffstat (limited to 'include/clang/AST/ExprCXX.h')
| -rw-r--r-- | include/clang/AST/ExprCXX.h | 1605 |
1 files changed, 845 insertions, 760 deletions
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 7ab8020dec64..6ef837a2fc40 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -75,43 +75,46 @@ class TemplateParameterList; /// function itself will be a (possibly empty) set of functions and /// function templates that were found by name lookup at template /// definition time. -class CXXOperatorCallExpr : public CallExpr { - /// The overloaded operator. - OverloadedOperatorKind Operator; +class CXXOperatorCallExpr final : public CallExpr { + friend class ASTStmtReader; + friend class ASTStmtWriter; SourceRange Range; - // Only meaningful for floating point types. - FPOptions FPFeatures; + // CXXOperatorCallExpr has some trailing objects belonging + // to CallExpr. See CallExpr for the details. SourceRange getSourceRangeImpl() const LLVM_READONLY; -public: - friend class ASTStmtReader; - friend class ASTStmtWriter; + CXXOperatorCallExpr(OverloadedOperatorKind OpKind, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation OperatorLoc, FPOptions FPFeatures, + ADLCallKind UsesADL); - CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, - ArrayRef<Expr*> args, QualType t, ExprValueKind VK, - SourceLocation operatorloc, FPOptions FPFeatures) - : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc), - Operator(Op), FPFeatures(FPFeatures) { - Range = getSourceRangeImpl(); - } + CXXOperatorCallExpr(unsigned NumArgs, EmptyShell Empty); - explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) - : CallExpr(C, CXXOperatorCallExprClass, Empty) {} +public: + static CXXOperatorCallExpr * + Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, + SourceLocation OperatorLoc, FPOptions FPFeatures, + ADLCallKind UsesADL = NotADL); - /// Returns the kind of overloaded operator that this - /// expression refers to. - OverloadedOperatorKind getOperator() const { return Operator; } + static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, EmptyShell Empty); + + /// Returns the kind of overloaded operator that this expression refers to. + OverloadedOperatorKind getOperator() const { + return static_cast<OverloadedOperatorKind>( + CXXOperatorCallExprBits.OperatorKind); + } static bool isAssignmentOp(OverloadedOperatorKind Opc) { - return Opc == OO_Equal || Opc == OO_StarEqual || - Opc == OO_SlashEqual || Opc == OO_PercentEqual || - Opc == OO_PlusEqual || Opc == OO_MinusEqual || - Opc == OO_LessLessEqual || Opc == OO_GreaterGreaterEqual || - Opc == OO_AmpEqual || Opc == OO_CaretEqual || - Opc == OO_PipeEqual; + return Opc == OO_Equal || Opc == OO_StarEqual || Opc == OO_SlashEqual || + Opc == OO_PercentEqual || Opc == OO_PlusEqual || + Opc == OO_MinusEqual || Opc == OO_LessLessEqual || + Opc == OO_GreaterGreaterEqual || Opc == OO_AmpEqual || + Opc == OO_CaretEqual || Opc == OO_PipeEqual; } bool isAssignmentOp() const { return isAssignmentOp(getOperator()); } @@ -126,14 +129,15 @@ public: SourceLocation getOperatorLoc() const { return getRParenLoc(); } SourceLocation getExprLoc() const LLVM_READONLY { + OverloadedOperatorKind Operator = getOperator(); return (Operator < OO_Plus || Operator >= OO_Arrow || Operator == OO_PlusPlus || Operator == OO_MinusMinus) - ? getLocStart() + ? getBeginLoc() : getOperatorLoc(); } - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } + SourceLocation getBeginLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } SourceRange getSourceRange() const { return Range; } static bool classof(const Stmt *T) { @@ -142,14 +146,17 @@ public: // Set the FP contractability status of this operator. Only meaningful for // operations on floating point types. - void setFPFeatures(FPOptions F) { FPFeatures = F; } - - FPOptions getFPFeatures() const { return FPFeatures; } + void setFPFeatures(FPOptions F) { + CXXOperatorCallExprBits.FPFeatures = F.getInt(); + } + FPOptions getFPFeatures() const { + return FPOptions(CXXOperatorCallExprBits.FPFeatures); + } // Get the FP contractability status of this operator. Only meaningful for // operations on floating point types. bool isFPContractableWithinStatement() const { - return FPFeatures.allowFPContractWithinStatement(); + return getFPFeatures().allowFPContractWithinStatement(); } }; @@ -161,14 +168,23 @@ public: /// both the object argument and the member function, while the /// arguments are the arguments within the parentheses (not including /// the object argument). -class CXXMemberCallExpr : public CallExpr { +class CXXMemberCallExpr final : public CallExpr { + // CXXMemberCallExpr has some trailing objects belonging + // to CallExpr. See CallExpr for the details. + + CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation RP, unsigned MinNumArgs); + + CXXMemberCallExpr(unsigned NumArgs, EmptyShell Empty); + public: - CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef<Expr*> args, - QualType t, ExprValueKind VK, SourceLocation RP) - : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP) {} + static CXXMemberCallExpr *Create(const ASTContext &Ctx, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation RP, + unsigned MinNumArgs = 0); - CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) - : CallExpr(C, CXXMemberCallExprClass, Empty) {} + static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, + EmptyShell Empty); /// Retrieves the implicit object argument for the member call. /// @@ -191,7 +207,7 @@ public: if (CLoc.isValid()) return CLoc; - return getLocStart(); + return getBeginLoc(); } static bool classof(const Stmt *T) { @@ -200,18 +216,26 @@ public: }; /// Represents a call to a CUDA kernel function. -class CUDAKernelCallExpr : public CallExpr { -private: +class CUDAKernelCallExpr final : public CallExpr { enum { CONFIG, END_PREARG }; + // CUDAKernelCallExpr has some trailing objects belonging + // to CallExpr. See CallExpr for the details. + + CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef<Expr *> Args, + QualType Ty, ExprValueKind VK, SourceLocation RP, + unsigned MinNumArgs); + + CUDAKernelCallExpr(unsigned NumArgs, EmptyShell Empty); + public: - CUDAKernelCallExpr(ASTContext &C, Expr *fn, CallExpr *Config, - ArrayRef<Expr*> args, QualType t, ExprValueKind VK, - SourceLocation RP) - : CallExpr(C, CUDAKernelCallExprClass, fn, Config, args, t, VK, RP) {} + static CUDAKernelCallExpr *Create(const ASTContext &Ctx, Expr *Fn, + CallExpr *Config, ArrayRef<Expr *> Args, + QualType Ty, ExprValueKind VK, + SourceLocation RP, unsigned MinNumArgs = 0); - CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty) - : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) {} + static CUDAKernelCallExpr *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, EmptyShell Empty); const CallExpr *getConfig() const { return cast_or_null<CallExpr>(getPreArg(CONFIG)); @@ -278,8 +302,8 @@ public: /// Retrieve the location of the closing parenthesis. SourceLocation getRParenLoc() const { return RParenLoc; } - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } SourceRange getAngleBrackets() const LLVM_READONLY { return AngleBrackets; } static bool classof(const Stmt *T) { @@ -301,8 +325,7 @@ public: /// \c static_cast<int>(1.0). class CXXStaticCastExpr final : public CXXNamedCastExpr, - private llvm::TrailingObjects<CXXStaticCastExpr, CastExpr::BasePathSizeTy, - CXXBaseSpecifier *> { + private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> { CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, @@ -313,10 +336,6 @@ class CXXStaticCastExpr final explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize) : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) {} - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: friend class CastExpr; friend TrailingObjects; @@ -342,8 +361,7 @@ public: /// check to determine how to perform the type conversion. class CXXDynamicCastExpr final : public CXXNamedCastExpr, - private llvm::TrailingObjects< - CXXDynamicCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> { + private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> { CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, @@ -354,10 +372,6 @@ class CXXDynamicCastExpr final explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) {} - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: friend class CastExpr; friend TrailingObjects; @@ -390,7 +404,6 @@ public: class CXXReinterpretCastExpr final : public CXXNamedCastExpr, private llvm::TrailingObjects<CXXReinterpretCastExpr, - CastExpr::BasePathSizeTy, CXXBaseSpecifier *> { CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, @@ -403,10 +416,6 @@ class CXXReinterpretCastExpr final CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) {} - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: friend class CastExpr; friend TrailingObjects; @@ -434,8 +443,7 @@ public: /// value. class CXXConstCastExpr final : public CXXNamedCastExpr, - private llvm::TrailingObjects<CXXConstCastExpr, CastExpr::BasePathSizeTy, - CXXBaseSpecifier *> { + private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> { CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l, SourceLocation RParenLoc, SourceRange AngleBrackets) @@ -445,10 +453,6 @@ class CXXConstCastExpr final explicit CXXConstCastExpr(EmptyShell Empty) : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) {} - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: friend class CastExpr; friend TrailingObjects; @@ -474,22 +478,30 @@ public: /// /// Since literal operators are never found by ADL and can only be declared at /// namespace scope, a user-defined literal is never dependent. -class UserDefinedLiteral : public CallExpr { +class UserDefinedLiteral final : public CallExpr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + /// The location of a ud-suffix within the literal. SourceLocation UDSuffixLoc; -public: - friend class ASTStmtReader; - friend class ASTStmtWriter; + // UserDefinedLiteral has some trailing objects belonging + // to CallExpr. See CallExpr for the details. - UserDefinedLiteral(const ASTContext &C, Expr *Fn, ArrayRef<Expr*> Args, - QualType T, ExprValueKind VK, SourceLocation LitEndLoc, - SourceLocation SuffixLoc) - : CallExpr(C, UserDefinedLiteralClass, Fn, Args, T, VK, LitEndLoc), - UDSuffixLoc(SuffixLoc) {} + UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation LitEndLoc, + SourceLocation SuffixLoc); - explicit UserDefinedLiteral(const ASTContext &C, EmptyShell Empty) - : CallExpr(C, UserDefinedLiteralClass, Empty) {} + UserDefinedLiteral(unsigned NumArgs, EmptyShell Empty); + +public: + static UserDefinedLiteral *Create(const ASTContext &Ctx, Expr *Fn, + ArrayRef<Expr *> Args, QualType Ty, + ExprValueKind VK, SourceLocation LitEndLoc, + SourceLocation SuffixLoc); + + static UserDefinedLiteral *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs, EmptyShell Empty); /// The kind of literal operator which is invoked. enum LiteralOperatorKind { @@ -524,13 +536,13 @@ public: return const_cast<UserDefinedLiteral*>(this)->getCookedLiteral(); } - SourceLocation getLocStart() const { + SourceLocation getBeginLoc() const { if (getLiteralOperatorKind() == LOK_Template) return getRParenLoc(); - return getArg(0)->getLocStart(); + return getArg(0)->getBeginLoc(); } - SourceLocation getLocEnd() const { return getRParenLoc(); } + SourceLocation getEndLoc() const { return getRParenLoc(); } /// Returns the location of a ud-suffix in the expression. /// @@ -548,26 +560,25 @@ public: /// A boolean literal, per ([C++ lex.bool] Boolean literals). class CXXBoolLiteralExpr : public Expr { - bool Value; - SourceLocation Loc; - public: - CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) + CXXBoolLiteralExpr(bool Val, QualType Ty, SourceLocation Loc) : Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - false, false), - Value(val), Loc(l) {} + false, false) { + CXXBoolLiteralExprBits.Value = Val; + CXXBoolLiteralExprBits.Loc = Loc; + } explicit CXXBoolLiteralExpr(EmptyShell Empty) : Expr(CXXBoolLiteralExprClass, Empty) {} - bool getValue() const { return Value; } - void setValue(bool V) { Value = V; } + bool getValue() const { return CXXBoolLiteralExprBits.Value; } + void setValue(bool V) { CXXBoolLiteralExprBits.Value = V; } - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + SourceLocation getBeginLoc() const { return getLocation(); } + SourceLocation getEndLoc() const { return getLocation(); } - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } + SourceLocation getLocation() const { return CXXBoolLiteralExprBits.Loc; } + void setLocation(SourceLocation L) { CXXBoolLiteralExprBits.Loc = L; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXBoolLiteralExprClass; @@ -583,22 +594,21 @@ public: /// /// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr. class CXXNullPtrLiteralExpr : public Expr { - SourceLocation Loc; - public: - CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) + CXXNullPtrLiteralExpr(QualType Ty, SourceLocation Loc) : Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, - false, false, false), - Loc(l) {} + false, false, false) { + CXXNullPtrLiteralExprBits.Loc = Loc; + } explicit CXXNullPtrLiteralExpr(EmptyShell Empty) : Expr(CXXNullPtrLiteralExprClass, Empty) {} - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + SourceLocation getBeginLoc() const { return getLocation(); } + SourceLocation getEndLoc() const { return getLocation(); } - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } + SourceLocation getLocation() const { return CXXNullPtrLiteralExprBits.Loc; } + void setLocation(SourceLocation L) { CXXNullPtrLiteralExprBits.Loc = L; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNullPtrLiteralExprClass; @@ -631,12 +641,12 @@ public: Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); } const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); } - SourceLocation getLocStart() const LLVM_READONLY { - return SubExpr->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return SubExpr->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { - return SubExpr->getLocEnd(); + SourceLocation getEndLoc() const LLVM_READONLY { + return SubExpr->getEndLoc(); } /// Retrieve the source range of the expression. @@ -723,8 +733,8 @@ public: Operand = E; } - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } + SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } void setSourceRange(SourceRange R) { Range = R; } @@ -771,23 +781,23 @@ public: MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {} SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(getLocStart(), getLocEnd()); + return SourceRange(getBeginLoc(), getEndLoc()); } bool isImplicitAccess() const { return getBaseExpr() && getBaseExpr()->isImplicitCXXThis(); } - SourceLocation getLocStart() const { + SourceLocation getBeginLoc() const { if (!isImplicitAccess()) - return BaseExpr->getLocStart(); + return BaseExpr->getBeginLoc(); else if (QualifierLoc) return QualifierLoc.getBeginLoc(); else return MemberLoc; } - SourceLocation getLocEnd() const { return getMemberLoc(); } + SourceLocation getEndLoc() const { return getMemberLoc(); } child_range children() { return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1); @@ -847,11 +857,11 @@ public: Expr *getIdx() { return cast<Expr>(SubExprs[IDX_EXPR]); } const Expr *getIdx() const { return cast<Expr>(SubExprs[IDX_EXPR]); } - SourceLocation getLocStart() const LLVM_READONLY { - return getBase()->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return getBase()->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; } SourceLocation getRBracketLoc() const { return RBracketLoc; } void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } @@ -933,8 +943,8 @@ public: void setUuidStr(StringRef US) { UuidStr = US; } StringRef getUuidStr() const { return UuidStr; } - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } + SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } void setSourceRange(SourceRange R) { Range = R; } @@ -964,29 +974,28 @@ public: /// }; /// \endcode class CXXThisExpr : public Expr { - SourceLocation Loc; - bool Implicit : 1; - public: - CXXThisExpr(SourceLocation L, QualType Type, bool isImplicit) - : Expr(CXXThisExprClass, Type, VK_RValue, OK_Ordinary, + CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit) + : Expr(CXXThisExprClass, Ty, VK_RValue, OK_Ordinary, // 'this' is type-dependent if the class type of the enclosing // member function is dependent (C++ [temp.dep.expr]p2) - Type->isDependentType(), Type->isDependentType(), - Type->isInstantiationDependentType(), - /*ContainsUnexpandedParameterPack=*/false), - Loc(L), Implicit(isImplicit) {} + Ty->isDependentType(), Ty->isDependentType(), + Ty->isInstantiationDependentType(), + /*ContainsUnexpandedParameterPack=*/false) { + CXXThisExprBits.IsImplicit = IsImplicit; + CXXThisExprBits.Loc = L; + } CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } + SourceLocation getLocation() const { return CXXThisExprBits.Loc; } + void setLocation(SourceLocation L) { CXXThisExprBits.Loc = L; } - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + SourceLocation getBeginLoc() const { return getLocation(); } + SourceLocation getEndLoc() const { return getLocation(); } - bool isImplicit() const { return Implicit; } - void setImplicit(bool I) { Implicit = I; } + bool isImplicit() const { return CXXThisExprBits.IsImplicit; } + void setImplicit(bool I) { CXXThisExprBits.IsImplicit = I; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXThisExprClass; @@ -1006,43 +1015,44 @@ public: class CXXThrowExpr : public Expr { friend class ASTStmtReader; - Stmt *Op; - SourceLocation ThrowLoc; - - /// Whether the thrown variable (if any) is in scope. - unsigned IsThrownVariableInScope : 1; + /// The optional expression in the throw statement. + Stmt *Operand; public: // \p Ty is the void type which is used as the result type of the - // expression. The \p l is the location of the throw keyword. \p expr - // can by null, if the optional expression to throw isn't present. - CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l, + // expression. The \p Loc is the location of the throw keyword. + // \p Operand is the expression in the throw statement, and can be + // null if not present. + CXXThrowExpr(Expr *Operand, QualType Ty, SourceLocation Loc, bool IsThrownVariableInScope) : Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false, - expr && expr->isInstantiationDependent(), - expr && expr->containsUnexpandedParameterPack()), - Op(expr), ThrowLoc(l), - IsThrownVariableInScope(IsThrownVariableInScope) {} + Operand && Operand->isInstantiationDependent(), + Operand && Operand->containsUnexpandedParameterPack()), + Operand(Operand) { + CXXThrowExprBits.ThrowLoc = Loc; + CXXThrowExprBits.IsThrownVariableInScope = IsThrownVariableInScope; + } CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {} - const Expr *getSubExpr() const { return cast_or_null<Expr>(Op); } - Expr *getSubExpr() { return cast_or_null<Expr>(Op); } + const Expr *getSubExpr() const { return cast_or_null<Expr>(Operand); } + Expr *getSubExpr() { return cast_or_null<Expr>(Operand); } - SourceLocation getThrowLoc() const { return ThrowLoc; } + SourceLocation getThrowLoc() const { return CXXThrowExprBits.ThrowLoc; } /// Determines whether the variable thrown by this expression (if any!) /// is within the innermost try block. /// /// This information is required to determine whether the NRVO can apply to /// this variable. - bool isThrownVariableInScope() const { return IsThrownVariableInScope; } - - SourceLocation getLocStart() const LLVM_READONLY { return ThrowLoc; } + bool isThrownVariableInScope() const { + return CXXThrowExprBits.IsThrownVariableInScope; + } - SourceLocation getLocEnd() const LLVM_READONLY { + SourceLocation getBeginLoc() const { return getThrowLoc(); } + SourceLocation getEndLoc() const LLVM_READONLY { if (!getSubExpr()) - return ThrowLoc; - return getSubExpr()->getLocEnd(); + return getThrowLoc(); + return getSubExpr()->getEndLoc(); } static bool classof(const Stmt *T) { @@ -1051,7 +1061,7 @@ public: // Iterators child_range children() { - return child_range(&Op, Op ? &Op+1 : &Op); + return child_range(&Operand, Operand ? &Operand + 1 : &Operand); } }; @@ -1061,26 +1071,24 @@ public: /// corresponding parameter's default argument, when the call did not /// explicitly supply arguments for all of the parameters. class CXXDefaultArgExpr final : public Expr { + friend class ASTStmtReader; + /// The parameter whose default is being used. ParmVarDecl *Param; - /// The location where the default argument expression was used. - SourceLocation Loc; - - CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param) + CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param) : Expr(SC, - param->hasUnparsedDefaultArg() - ? param->getType().getNonReferenceType() - : param->getDefaultArg()->getType(), - param->getDefaultArg()->getValueKind(), - param->getDefaultArg()->getObjectKind(), false, false, false, + Param->hasUnparsedDefaultArg() + ? Param->getType().getNonReferenceType() + : Param->getDefaultArg()->getType(), + Param->getDefaultArg()->getValueKind(), + Param->getDefaultArg()->getObjectKind(), false, false, false, false), - Param(param), Loc(Loc) {} + Param(Param) { + CXXDefaultArgExprBits.Loc = Loc; + } public: - friend class ASTStmtReader; - friend class ASTStmtWriter; - CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} // \p Param is the parameter whose default argument is used by this @@ -1095,23 +1103,18 @@ public: ParmVarDecl *getParam() { return Param; } // Retrieve the actual argument to the function call. - const Expr *getExpr() const { - return getParam()->getDefaultArg(); - } - Expr *getExpr() { - return getParam()->getDefaultArg(); - } + const Expr *getExpr() const { return getParam()->getDefaultArg(); } + Expr *getExpr() { return getParam()->getDefaultArg(); } - /// Retrieve the location where this default argument was actually - /// used. - SourceLocation getUsedLocation() const { return Loc; } + /// Retrieve the location where this default argument was actually used. + SourceLocation getUsedLocation() const { return CXXDefaultArgExprBits.Loc; } /// Default argument expressions have no representation in the /// source, so they have an empty source range. - SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getBeginLoc() const { return SourceLocation(); } + SourceLocation getEndLoc() const { return SourceLocation(); } - SourceLocation getExprLoc() const LLVM_READONLY { return Loc; } + SourceLocation getExprLoc() const { return getUsedLocation(); } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDefaultArgExprClass; @@ -1132,26 +1135,23 @@ public: /// (C++11 [class.base.init]p8) or in aggregate initialization /// (C++1y [dcl.init.aggr]p7). class CXXDefaultInitExpr : public Expr { + friend class ASTReader; + friend class ASTStmtReader; + /// The field whose default is being used. FieldDecl *Field; - /// The location where the default initializer expression was used. - SourceLocation Loc; - - CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field, - QualType T); + CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc, + FieldDecl *Field, QualType Ty); CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {} public: - friend class ASTReader; - friend class ASTStmtReader; - /// \p Field is the non-static data member whose default initializer is used /// by this expression. - static CXXDefaultInitExpr *Create(const ASTContext &C, SourceLocation Loc, + static CXXDefaultInitExpr *Create(const ASTContext &Ctx, SourceLocation Loc, FieldDecl *Field) { - return new (C) CXXDefaultInitExpr(C, Loc, Field, Field->getType()); + return new (Ctx) CXXDefaultInitExpr(Ctx, Loc, Field, Field->getType()); } /// Get the field whose initializer will be used. @@ -1168,8 +1168,8 @@ public: return Field->getInClassInitializer(); } - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + SourceLocation getBeginLoc() const { return CXXDefaultInitExprBits.Loc; } + SourceLocation getEndLoc() const { return CXXDefaultInitExprBits.Loc; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDefaultInitExprClass; @@ -1241,11 +1241,13 @@ public: Expr *getSubExpr() { return cast<Expr>(SubExpr); } void setSubExpr(Expr *E) { SubExpr = E; } - SourceLocation getLocStart() const LLVM_READONLY { - return SubExpr->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return SubExpr->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();} + SourceLocation getEndLoc() const LLVM_READONLY { + return SubExpr->getEndLoc(); + } // Implement isa/cast/dyncast/etc. static bool classof(const Stmt *T) { @@ -1258,6 +1260,8 @@ public: /// Represents a call to a C++ constructor. class CXXConstructExpr : public Expr { + friend class ASTStmtReader; + public: enum ConstructionKind { CK_Complete, @@ -1267,150 +1271,173 @@ public: }; private: - CXXConstructorDecl *Constructor = nullptr; - SourceLocation Loc; + /// A pointer to the constructor which will be ultimately called. + CXXConstructorDecl *Constructor; + SourceRange ParenOrBraceRange; - unsigned NumArgs : 16; - unsigned Elidable : 1; - unsigned HadMultipleCandidates : 1; - unsigned ListInitialization : 1; - unsigned StdInitListInitialization : 1; - unsigned ZeroInitialization : 1; - unsigned ConstructKind : 2; - Stmt **Args = nullptr; - void setConstructor(CXXConstructorDecl *C) { Constructor = C; } + /// The number of arguments. + unsigned NumArgs; + + // We would like to stash the arguments of the constructor call after + // CXXConstructExpr. However CXXConstructExpr is used as a base class of + // CXXTemporaryObjectExpr which makes the use of llvm::TrailingObjects + // impossible. + // + // Instead we manually stash the trailing object after the full object + // containing CXXConstructExpr (that is either CXXConstructExpr or + // CXXTemporaryObjectExpr). + // + // The trailing objects are: + // + // * An array of getNumArgs() "Stmt *" for the arguments of the + // constructor call. + + /// Return a pointer to the start of the trailing arguments. + /// Defined just after CXXTemporaryObjectExpr. + inline Stmt **getTrailingArgs(); + const Stmt *const *getTrailingArgs() const { + return const_cast<CXXConstructExpr *>(this)->getTrailingArgs(); + } protected: - CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T, - SourceLocation Loc, - CXXConstructorDecl *Ctor, - bool Elidable, - ArrayRef<Expr *> Args, - bool HadMultipleCandidates, - bool ListInitialization, - bool StdInitListInitialization, - bool ZeroInitialization, - ConstructionKind ConstructKind, + /// Build a C++ construction expression. + CXXConstructExpr(StmtClass SC, QualType Ty, SourceLocation Loc, + CXXConstructorDecl *Ctor, bool Elidable, + ArrayRef<Expr *> Args, bool HadMultipleCandidates, + bool ListInitialization, bool StdInitListInitialization, + bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); - /// Construct an empty C++ construction expression. - CXXConstructExpr(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), NumArgs(0), Elidable(false), - HadMultipleCandidates(false), ListInitialization(false), - ZeroInitialization(false), ConstructKind(0) {} + /// Build an empty C++ construction expression. + CXXConstructExpr(StmtClass SC, EmptyShell Empty, unsigned NumArgs); -public: - friend class ASTStmtReader; + /// Return the size in bytes of the trailing objects. Used by + /// CXXTemporaryObjectExpr to allocate the right amount of storage. + static unsigned sizeOfTrailingObjects(unsigned NumArgs) { + return NumArgs * sizeof(Stmt *); + } - /// Construct an empty C++ construction expression. - explicit CXXConstructExpr(EmptyShell Empty) - : CXXConstructExpr(CXXConstructExprClass, Empty) {} +public: + /// Create a C++ construction expression. + static CXXConstructExpr * + Create(const ASTContext &Ctx, QualType Ty, SourceLocation Loc, + CXXConstructorDecl *Ctor, bool Elidable, ArrayRef<Expr *> Args, + bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, + ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); - static CXXConstructExpr *Create(const ASTContext &C, QualType T, - SourceLocation Loc, - CXXConstructorDecl *Ctor, - bool Elidable, - ArrayRef<Expr *> Args, - bool HadMultipleCandidates, - bool ListInitialization, - bool StdInitListInitialization, - bool ZeroInitialization, - ConstructionKind ConstructKind, - SourceRange ParenOrBraceRange); + /// Create an empty C++ construction expression. + static CXXConstructExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs); /// Get the constructor that this expression will (ultimately) call. CXXConstructorDecl *getConstructor() const { return Constructor; } - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation Loc) { this->Loc = Loc; } + SourceLocation getLocation() const { return CXXConstructExprBits.Loc; } + void setLocation(SourceLocation Loc) { CXXConstructExprBits.Loc = Loc; } /// Whether this construction is elidable. - bool isElidable() const { return Elidable; } - void setElidable(bool E) { Elidable = E; } + bool isElidable() const { return CXXConstructExprBits.Elidable; } + void setElidable(bool E) { CXXConstructExprBits.Elidable = E; } /// Whether the referred constructor was resolved from /// an overloaded set having size greater than 1. - bool hadMultipleCandidates() const { return HadMultipleCandidates; } - void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; } + bool hadMultipleCandidates() const { + return CXXConstructExprBits.HadMultipleCandidates; + } + void setHadMultipleCandidates(bool V) { + CXXConstructExprBits.HadMultipleCandidates = V; + } /// Whether this constructor call was written as list-initialization. - bool isListInitialization() const { return ListInitialization; } - void setListInitialization(bool V) { ListInitialization = V; } + bool isListInitialization() const { + return CXXConstructExprBits.ListInitialization; + } + void setListInitialization(bool V) { + CXXConstructExprBits.ListInitialization = V; + } /// Whether this constructor call was written as list-initialization, /// but was interpreted as forming a std::initializer_list<T> from the list /// and passing that as a single constructor argument. /// See C++11 [over.match.list]p1 bullet 1. - bool isStdInitListInitialization() const { return StdInitListInitialization; } - void setStdInitListInitialization(bool V) { StdInitListInitialization = V; } + bool isStdInitListInitialization() const { + return CXXConstructExprBits.StdInitListInitialization; + } + void setStdInitListInitialization(bool V) { + CXXConstructExprBits.StdInitListInitialization = V; + } /// Whether this construction first requires /// zero-initialization before the initializer is called. - bool requiresZeroInitialization() const { return ZeroInitialization; } + bool requiresZeroInitialization() const { + return CXXConstructExprBits.ZeroInitialization; + } void setRequiresZeroInitialization(bool ZeroInit) { - ZeroInitialization = ZeroInit; + CXXConstructExprBits.ZeroInitialization = ZeroInit; } /// Determine whether this constructor is actually constructing /// a base class (rather than a complete object). ConstructionKind getConstructionKind() const { - return (ConstructionKind)ConstructKind; + return static_cast<ConstructionKind>(CXXConstructExprBits.ConstructionKind); } void setConstructionKind(ConstructionKind CK) { - ConstructKind = CK; + CXXConstructExprBits.ConstructionKind = CK; } using arg_iterator = ExprIterator; using const_arg_iterator = ConstExprIterator; using arg_range = llvm::iterator_range<arg_iterator>; - using arg_const_range = llvm::iterator_range<const_arg_iterator>; + using const_arg_range = llvm::iterator_range<const_arg_iterator>; arg_range arguments() { return arg_range(arg_begin(), arg_end()); } - arg_const_range arguments() const { - return arg_const_range(arg_begin(), arg_end()); + const_arg_range arguments() const { + return const_arg_range(arg_begin(), arg_end()); } - arg_iterator arg_begin() { return Args; } - arg_iterator arg_end() { return Args + NumArgs; } - const_arg_iterator arg_begin() const { return Args; } - const_arg_iterator arg_end() const { return Args + NumArgs; } + arg_iterator arg_begin() { return getTrailingArgs(); } + arg_iterator arg_end() { return arg_begin() + getNumArgs(); } + const_arg_iterator arg_begin() const { return getTrailingArgs(); } + const_arg_iterator arg_end() const { return arg_begin() + getNumArgs(); } - Expr **getArgs() { return reinterpret_cast<Expr **>(Args); } + Expr **getArgs() { return reinterpret_cast<Expr **>(getTrailingArgs()); } const Expr *const *getArgs() const { - return const_cast<CXXConstructExpr *>(this)->getArgs(); + return reinterpret_cast<const Expr *const *>(getTrailingArgs()); } + + /// Return the number of arguments to the constructor call. unsigned getNumArgs() const { return NumArgs; } /// Return the specified argument. Expr *getArg(unsigned Arg) { - assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(Args[Arg]); + assert(Arg < getNumArgs() && "Arg access out of range!"); + return getArgs()[Arg]; } const Expr *getArg(unsigned Arg) const { - assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(Args[Arg]); + assert(Arg < getNumArgs() && "Arg access out of range!"); + return getArgs()[Arg]; } /// Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { - assert(Arg < NumArgs && "Arg access out of range!"); - Args[Arg] = ArgExpr; + assert(Arg < getNumArgs() && "Arg access out of range!"); + getArgs()[Arg] = ArgExpr; } - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; SourceRange getParenOrBraceRange() const { return ParenOrBraceRange; } void setParenOrBraceRange(SourceRange Range) { ParenOrBraceRange = Range; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstructExprClass || - T->getStmtClass() == CXXTemporaryObjectExprClass; + T->getStmtClass() == CXXTemporaryObjectExprClass; } // Iterators child_range children() { - return child_range(&Args[0], &Args[0]+NumArgs); + return child_range(getTrailingArgs(), getTrailingArgs() + getNumArgs()); } }; @@ -1470,8 +1497,8 @@ public: bool inheritedFromVBase() const { return InheritedFromVirtualBase; } SourceLocation getLocation() const LLVM_READONLY { return Loc; } - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXInheritedCtorInitExprClass; @@ -1491,8 +1518,7 @@ public: /// \endcode class CXXFunctionalCastExpr final : public ExplicitCastExpr, - private llvm::TrailingObjects< - CXXFunctionalCastExpr, CastExpr::BasePathSizeTy, CXXBaseSpecifier *> { + private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> { SourceLocation LParenLoc; SourceLocation RParenLoc; @@ -1507,10 +1533,6 @@ class CXXFunctionalCastExpr final explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) {} - size_t numTrailingObjects(OverloadToken<CastExpr::BasePathSizeTy>) const { - return path_empty() ? 0 : 1; - } - public: friend class CastExpr; friend TrailingObjects; @@ -1533,8 +1555,8 @@ public: /// Determine whether this expression models list-initialization. bool isListInitialization() const { return LParenLoc.isInvalid(); } - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXFunctionalCastExprClass; @@ -1556,35 +1578,53 @@ public: /// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr /// }; /// \endcode -class CXXTemporaryObjectExpr : public CXXConstructExpr { - TypeSourceInfo *Type = nullptr; - -public: +class CXXTemporaryObjectExpr final : public CXXConstructExpr { friend class ASTStmtReader; - CXXTemporaryObjectExpr(const ASTContext &C, - CXXConstructorDecl *Cons, - QualType Type, - TypeSourceInfo *TSI, - ArrayRef<Expr *> Args, + // CXXTemporaryObjectExpr has some trailing objects belonging + // to CXXConstructExpr. See the comment inside CXXConstructExpr + // for more details. + + TypeSourceInfo *TSI; + + CXXTemporaryObjectExpr(CXXConstructorDecl *Cons, QualType Ty, + TypeSourceInfo *TSI, ArrayRef<Expr *> Args, SourceRange ParenOrBraceRange, - bool HadMultipleCandidates, - bool ListInitialization, + bool HadMultipleCandidates, bool ListInitialization, bool StdInitListInitialization, bool ZeroInitialization); - explicit CXXTemporaryObjectExpr(EmptyShell Empty) - : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) {} - TypeSourceInfo *getTypeSourceInfo() const { return Type; } + CXXTemporaryObjectExpr(EmptyShell Empty, unsigned NumArgs); + +public: + static CXXTemporaryObjectExpr * + Create(const ASTContext &Ctx, CXXConstructorDecl *Cons, QualType Ty, + TypeSourceInfo *TSI, ArrayRef<Expr *> Args, + SourceRange ParenOrBraceRange, bool HadMultipleCandidates, + bool ListInitialization, bool StdInitListInitialization, + bool ZeroInitialization); - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY; + static CXXTemporaryObjectExpr *CreateEmpty(const ASTContext &Ctx, + unsigned NumArgs); + + TypeSourceInfo *getTypeSourceInfo() const { return TSI; } + + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXTemporaryObjectExprClass; } }; +Stmt **CXXConstructExpr::getTrailingArgs() { + if (auto *E = dyn_cast<CXXTemporaryObjectExpr>(this)) + return reinterpret_cast<Stmt **>(E + 1); + assert((getStmtClass() == CXXConstructExprClass) && + "Unexpected class deriving from CXXConstructExpr!"); + return reinterpret_cast<Stmt **>(this + 1); +} + /// A C++ lambda expression, which produces a function object /// (of unspecified type) that can be invoked later. /// @@ -1814,11 +1854,11 @@ public: return T->getStmtClass() == LambdaExprClass; } - SourceLocation getLocStart() const LLVM_READONLY { + SourceLocation getBeginLoc() const LLVM_READONLY { return IntroducerRange.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return ClosingBrace; } + SourceLocation getEndLoc() const LLVM_READONLY { return ClosingBrace; } child_range children() { // Includes initialization exprs plus body stmt @@ -1831,18 +1871,19 @@ public: class CXXScalarValueInitExpr : public Expr { friend class ASTStmtReader; - SourceLocation RParenLoc; TypeSourceInfo *TypeInfo; public: /// Create an explicitly-written scalar-value initialization /// expression. CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo, - SourceLocation rParenLoc) - : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, - false, false, Type->isInstantiationDependentType(), + SourceLocation RParenLoc) + : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, false, + false, Type->isInstantiationDependentType(), Type->containsUnexpandedParameterPack()), - RParenLoc(rParenLoc), TypeInfo(TypeInfo) {} + TypeInfo(TypeInfo) { + CXXScalarValueInitExprBits.RParenLoc = RParenLoc; + } explicit CXXScalarValueInitExpr(EmptyShell Shell) : Expr(CXXScalarValueInitExprClass, Shell) {} @@ -1851,10 +1892,12 @@ public: return TypeInfo; } - SourceLocation getRParenLoc() const { return RParenLoc; } + SourceLocation getRParenLoc() const { + return CXXScalarValueInitExprBits.RParenLoc; + } - SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const { return getRParenLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXScalarValueInitExprClass; @@ -1868,54 +1911,56 @@ public: /// Represents a new-expression for memory allocation and constructor /// calls, e.g: "new CXXNewExpr(foo)". -class CXXNewExpr : public Expr { +class CXXNewExpr final + : public Expr, + private llvm::TrailingObjects<CXXNewExpr, Stmt *, SourceRange> { friend class ASTStmtReader; friend class ASTStmtWriter; - - /// Contains an optional array size expression, an optional initialization - /// expression, and any number of optional placement arguments, in that order. - Stmt **SubExprs = nullptr; + friend TrailingObjects; /// Points to the allocation function used. FunctionDecl *OperatorNew; - /// Points to the deallocation function used in case of error. May be - /// null. + /// Points to the deallocation function used in case of error. May be null. FunctionDecl *OperatorDelete; /// The allocated type-source information, as written in the source. TypeSourceInfo *AllocatedTypeInfo; - /// If the allocated type was expressed as a parenthesized type-id, - /// the source range covering the parenthesized type-id. - SourceRange TypeIdParens; - /// Range of the entire new expression. SourceRange Range; /// Source-range of a paren-delimited initializer. SourceRange DirectInitRange; - /// Was the usage ::new, i.e. is the global new to be used? - unsigned GlobalNew : 1; - - /// Do we allocate an array? If so, the first SubExpr is the size expression. - unsigned Array : 1; - - /// Should the alignment be passed to the allocation function? - unsigned PassAlignment : 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; + // CXXNewExpr is followed by several optional trailing objects. + // They are in order: + // + // * An optional "Stmt *" for the array size expression. + // Present if and ony if isArray(). + // + // * An optional "Stmt *" for the init expression. + // Present if and only if hasInitializer(). + // + // * An array of getNumPlacementArgs() "Stmt *" for the placement new + // arguments, if any. + // + // * An optional SourceRange for the range covering the parenthesized type-id + // if the allocated type was expressed as a parenthesized type-id. + // Present if and only if isParenTypeId(). + unsigned arraySizeOffset() const { return 0; } + unsigned initExprOffset() const { return arraySizeOffset() + isArray(); } + unsigned placementNewArgsOffset() const { + return initExprOffset() + hasInitializer(); + } - /// The number of placement new arguments. - unsigned NumPlacementArgs : 26; + unsigned numTrailingObjects(OverloadToken<Stmt *>) const { + return isArray() + hasInitializer() + getNumPlacementArgs(); + } - /// 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; + unsigned numTrailingObjects(OverloadToken<SourceRange>) const { + return isParenTypeId(); + } public: enum InitializationStyle { @@ -1929,18 +1974,35 @@ public: ListInit }; - CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew, - FunctionDecl *operatorDelete, bool PassAlignment, - bool usualArrayDeleteWantsSize, ArrayRef<Expr*> placementArgs, - SourceRange typeIdParens, Expr *arraySize, - InitializationStyle initializationStyle, Expr *initializer, - QualType ty, TypeSourceInfo *AllocatedTypeInfo, - SourceRange Range, SourceRange directInitRange); - explicit CXXNewExpr(EmptyShell Shell) - : Expr(CXXNewExprClass, Shell) {} +private: + /// Build a c++ new expression. + CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, + FunctionDecl *OperatorDelete, bool ShouldPassAlignment, + bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, + SourceRange TypeIdParens, Expr *ArraySize, + InitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange); + + /// Build an empty c++ new expression. + CXXNewExpr(EmptyShell Empty, bool IsArray, unsigned NumPlacementArgs, + bool IsParenTypeId); + +public: + /// Create a c++ new expression. + static CXXNewExpr * + Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew, + FunctionDecl *OperatorDelete, bool ShouldPassAlignment, + bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, + SourceRange TypeIdParens, Expr *ArraySize, + InitializationStyle InitializationStyle, Expr *Initializer, + QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, + SourceRange DirectInitRange); - void AllocateArgsArray(const ASTContext &C, bool isArray, - unsigned numPlaceArgs, bool hasInitializer); + /// Create an empty c++ new expression. + static CXXNewExpr *CreateEmpty(const ASTContext &Ctx, bool IsArray, + bool HasInit, unsigned NumPlacementArgs, + bool IsParenTypeId); QualType getAllocatedType() const { assert(getType()->isPointerType()); @@ -1966,58 +2028,74 @@ public: /// has a non-throwing exception-specification. The '03 rule is /// identical except that the definition of a non-throwing /// exception specification is just "is it throw()?". - bool shouldNullCheckAllocation(const ASTContext &Ctx) const; + bool shouldNullCheckAllocation() const; FunctionDecl *getOperatorNew() const { return OperatorNew; } void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } FunctionDecl *getOperatorDelete() const { return OperatorDelete; } void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } - bool isArray() const { return Array; } + bool isArray() const { return CXXNewExprBits.IsArray; } Expr *getArraySize() { - return Array ? cast<Expr>(SubExprs[0]) : nullptr; + return isArray() + ? cast<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]) + : nullptr; } const Expr *getArraySize() const { - return Array ? cast<Expr>(SubExprs[0]) : nullptr; + return isArray() + ? cast<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]) + : nullptr; } - unsigned getNumPlacementArgs() const { return NumPlacementArgs; } + unsigned getNumPlacementArgs() const { + return CXXNewExprBits.NumPlacementArgs; + } Expr **getPlacementArgs() { - return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer()); + return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>() + + placementNewArgsOffset()); } - Expr *getPlacementArg(unsigned i) { - assert(i < NumPlacementArgs && "Index out of range"); - return getPlacementArgs()[i]; + Expr *getPlacementArg(unsigned I) { + assert((I < getNumPlacementArgs()) && "Index out of range!"); + return getPlacementArgs()[I]; } - const Expr *getPlacementArg(unsigned i) const { - assert(i < NumPlacementArgs && "Index out of range"); - return const_cast<CXXNewExpr*>(this)->getPlacementArg(i); + const Expr *getPlacementArg(unsigned I) const { + return const_cast<CXXNewExpr *>(this)->getPlacementArg(I); } - bool isParenTypeId() const { return TypeIdParens.isValid(); } - SourceRange getTypeIdParens() const { return TypeIdParens; } + bool isParenTypeId() const { return CXXNewExprBits.IsParenTypeId; } + SourceRange getTypeIdParens() const { + return isParenTypeId() ? getTrailingObjects<SourceRange>()[0] + : SourceRange(); + } - bool isGlobalNew() const { return GlobalNew; } + bool isGlobalNew() const { return CXXNewExprBits.IsGlobalNew; } /// Whether this new-expression has any initializer at all. - bool hasInitializer() const { return StoredInitializationStyle > 0; } + bool hasInitializer() const { + return CXXNewExprBits.StoredInitializationStyle > 0; + } /// The kind of initializer this new-expression has. InitializationStyle getInitializationStyle() const { - if (StoredInitializationStyle == 0) + if (CXXNewExprBits.StoredInitializationStyle == 0) return NoInit; - return static_cast<InitializationStyle>(StoredInitializationStyle-1); + return static_cast<InitializationStyle>( + CXXNewExprBits.StoredInitializationStyle - 1); } /// The initializer of this new-expression. Expr *getInitializer() { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; + return hasInitializer() + ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()]) + : nullptr; } const Expr *getInitializer() const { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; + return hasInitializer() + ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()]) + : nullptr; } /// Returns the CXXConstructExpr from this new-expression, or null. @@ -2027,15 +2105,13 @@ public: /// Indicates whether the required alignment should be implicitly passed to /// the allocation function. - bool passAlignment() const { - return PassAlignment; - } + bool passAlignment() const { return CXXNewExprBits.ShouldPassAlignment; } /// Answers whether the usual array deallocation function for the /// allocated type expects the size of the allocation as a /// parameter. bool doesUsualArrayDeleteWantSize() const { - return UsualArrayDeleteWantsSize; + return CXXNewExprBits.UsualArrayDeleteWantsSize; } using arg_iterator = ExprIterator; @@ -2050,103 +2126,85 @@ public: } arg_iterator placement_arg_begin() { - return SubExprs + Array + hasInitializer(); + return getTrailingObjects<Stmt *>() + placementNewArgsOffset(); } arg_iterator placement_arg_end() { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return placement_arg_begin() + getNumPlacementArgs(); } const_arg_iterator placement_arg_begin() const { - return SubExprs + Array + hasInitializer(); + return getTrailingObjects<Stmt *>() + placementNewArgsOffset(); } const_arg_iterator placement_arg_end() const { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return placement_arg_begin() + getNumPlacementArgs(); } using raw_arg_iterator = Stmt **; - raw_arg_iterator raw_arg_begin() { return SubExprs; } + raw_arg_iterator raw_arg_begin() { return getTrailingObjects<Stmt *>(); } raw_arg_iterator raw_arg_end() { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>()); + } + const_arg_iterator raw_arg_begin() const { + return getTrailingObjects<Stmt *>(); } - const_arg_iterator raw_arg_begin() const { return SubExprs; } const_arg_iterator raw_arg_end() const { - return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); + return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>()); } - SourceLocation getStartLoc() const { return Range.getBegin(); } + SourceLocation getBeginLoc() const { return Range.getBegin(); } SourceLocation getEndLoc() const { return Range.getEnd(); } SourceRange getDirectInitRange() const { return DirectInitRange; } - - SourceRange getSourceRange() const LLVM_READONLY { - return Range; - } - - SourceLocation getLocStart() const LLVM_READONLY { return getStartLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } + SourceRange getSourceRange() const { return Range; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNewExprClass; } // Iterators - child_range children() { - return child_range(raw_arg_begin(), raw_arg_end()); - } + child_range children() { return child_range(raw_arg_begin(), raw_arg_end()); } }; /// Represents a \c delete expression for memory deallocation and /// destructor calls, e.g. "delete[] pArray". class CXXDeleteExpr : public Expr { + friend class ASTStmtReader; + /// Points to the operator delete overload that is used. Could be a member. FunctionDecl *OperatorDelete = nullptr; /// The pointer expression to be deleted. Stmt *Argument = nullptr; - /// Location of the expression. - SourceLocation Loc; - - /// Is this a forced global delete, i.e. "::delete"? - bool GlobalDelete : 1; - - /// Is this the array form of delete, i.e. "delete[]"? - bool 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). - bool ArrayFormAsWritten : 1; - - /// Does the usual deallocation function for the element type require - /// a size_t argument? - bool UsualArrayDeleteWantsSize : 1; - public: - friend class ASTStmtReader; + CXXDeleteExpr(QualType Ty, bool GlobalDelete, bool ArrayForm, + bool ArrayFormAsWritten, bool UsualArrayDeleteWantsSize, + FunctionDecl *OperatorDelete, Expr *Arg, SourceLocation Loc) + : Expr(CXXDeleteExprClass, Ty, VK_RValue, OK_Ordinary, false, false, + Arg->isInstantiationDependent(), + Arg->containsUnexpandedParameterPack()), + OperatorDelete(OperatorDelete), Argument(Arg) { + CXXDeleteExprBits.GlobalDelete = GlobalDelete; + CXXDeleteExprBits.ArrayForm = ArrayForm; + CXXDeleteExprBits.ArrayFormAsWritten = ArrayFormAsWritten; + CXXDeleteExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize; + CXXDeleteExprBits.Loc = Loc; + } - CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm, - bool arrayFormAsWritten, bool usualArrayDeleteWantsSize, - FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc) - : Expr(CXXDeleteExprClass, ty, VK_RValue, OK_Ordinary, false, false, - arg->isInstantiationDependent(), - arg->containsUnexpandedParameterPack()), - OperatorDelete(operatorDelete), Argument(arg), Loc(loc), - GlobalDelete(globalDelete), - ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), - UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) {} explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell) {} - bool isGlobalDelete() const { return GlobalDelete; } - bool isArrayForm() const { return ArrayForm; } - bool isArrayFormAsWritten() const { return ArrayFormAsWritten; } + bool isGlobalDelete() const { return CXXDeleteExprBits.GlobalDelete; } + bool isArrayForm() const { return CXXDeleteExprBits.ArrayForm; } + bool isArrayFormAsWritten() const { + return CXXDeleteExprBits.ArrayFormAsWritten; + } /// Answers whether the usual array deallocation function for the /// allocated type expects the size of the allocation as a /// parameter. This can be true even if the actual deallocation /// function that we're using doesn't want a size. bool doesUsualArrayDeleteWantSize() const { - return UsualArrayDeleteWantsSize; + return CXXDeleteExprBits.UsualArrayDeleteWantsSize; } FunctionDecl *getOperatorDelete() const { return OperatorDelete; } @@ -2160,15 +2218,17 @@ public: /// be a pointer, return an invalid type. QualType getDestroyedType() const; - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY {return Argument->getLocEnd();} + SourceLocation getBeginLoc() const { return CXXDeleteExprBits.Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { + return Argument->getEndLoc(); + } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDeleteExprClass; } // Iterators - child_range children() { return child_range(&Argument, &Argument+1); } + child_range children() { return child_range(&Argument, &Argument + 1); } }; /// Stores the type being destroyed by a pseudo-destructor expression. @@ -2346,8 +2406,10 @@ public: DestroyedType = PseudoDestructorTypeStorage(Info); } - SourceLocation getLocStart() const LLVM_READONLY {return Base->getLocStart();} - SourceLocation getLocEnd() const LLVM_READONLY; + SourceLocation getBeginLoc() const LLVM_READONLY { + return Base->getBeginLoc(); + } + SourceLocation getEndLoc() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXPseudoDestructorExprClass; @@ -2428,8 +2490,8 @@ public: getNumArgs()); } - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == TypeTraitExprClass; @@ -2468,8 +2530,6 @@ class ArrayTypeTraitExpr : public Expr { /// The type being queried. TypeSourceInfo *QueriedType = nullptr; - virtual void anchor(); - public: friend class ASTStmtReader; @@ -2487,10 +2547,8 @@ public: explicit ArrayTypeTraitExpr(EmptyShell Empty) : Expr(ArrayTypeTraitExprClass, Empty), ATT(0) {} - virtual ~ArrayTypeTraitExpr() = default; - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParen; } ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); } @@ -2553,8 +2611,8 @@ public: explicit ExpressionTraitExpr(EmptyShell Empty) : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false) {} - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } + SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParen; } ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); } @@ -2575,58 +2633,54 @@ public: /// A reference to an overloaded function set, either an /// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr. class OverloadExpr : public Expr { + friend class ASTStmtReader; + friend class ASTStmtWriter; + /// The common name of these declarations. DeclarationNameInfo NameInfo; /// The nested-name-specifier that qualifies the name, if any. NestedNameSpecifierLoc QualifierLoc; - /// The results. These are undesugared, which is to say, they may - /// include UsingShadowDecls. Access is relative to the naming - /// class. - // FIXME: Allocate this data after the OverloadExpr subclass. - DeclAccessPair *Results = nullptr; - - unsigned NumResults = 0; - protected: - /// Whether the name includes info for explicit template - /// keyword and arguments. - bool HasTemplateKWAndArgsInfo = false; - - OverloadExpr(StmtClass K, const ASTContext &C, + OverloadExpr(StmtClass SC, const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent, - bool KnownInstantiationDependent, + bool KnownDependent, bool KnownInstantiationDependent, bool KnownContainsUnexpandedParameterPack); - OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty) {} + OverloadExpr(StmtClass SC, EmptyShell Empty, unsigned NumResults, + bool HasTemplateKWAndArgsInfo); - /// Return the optional template keyword and arguments info. - ASTTemplateKWAndArgsInfo * - getTrailingASTTemplateKWAndArgsInfo(); // defined far below. + /// Return the results. Defined after UnresolvedMemberExpr. + inline DeclAccessPair *getTrailingResults(); + const DeclAccessPair *getTrailingResults() const { + return const_cast<OverloadExpr *>(this)->getTrailingResults(); + } /// Return the optional template keyword and arguments info. + /// Defined after UnresolvedMemberExpr. + inline ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo(); const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const { return const_cast<OverloadExpr *>(this) ->getTrailingASTTemplateKWAndArgsInfo(); } - /// Return the optional template arguments. - TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); // defined far below + /// Return the optional template arguments. Defined after + /// UnresolvedMemberExpr. + inline TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); + const TemplateArgumentLoc *getTrailingTemplateArgumentLoc() const { + return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc(); + } - void initializeResults(const ASTContext &C, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End); + bool hasTemplateKWAndArgsInfo() const { + return OverloadExprBits.HasTemplateKWAndArgsInfo; + } public: - friend class ASTStmtReader; - friend class ASTStmtWriter; - struct FindResult { OverloadExpr *Expression; bool IsAddressOfOperand; @@ -2662,20 +2716,26 @@ public: } /// Gets the naming class of this lookup, if any. - CXXRecordDecl *getNamingClass() const; + /// Defined after UnresolvedMemberExpr. + inline CXXRecordDecl *getNamingClass(); + const CXXRecordDecl *getNamingClass() const { + return const_cast<OverloadExpr *>(this)->getNamingClass(); + } using decls_iterator = UnresolvedSetImpl::iterator; - decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); } + decls_iterator decls_begin() const { + return UnresolvedSetIterator(getTrailingResults()); + } decls_iterator decls_end() const { - return UnresolvedSetIterator(Results + NumResults); + return UnresolvedSetIterator(getTrailingResults() + getNumDecls()); } llvm::iterator_range<decls_iterator> decls() const { return llvm::make_range(decls_begin(), decls_end()); } /// Gets the number of declarations in the unresolved set. - unsigned getNumDecls() const { return NumResults; } + unsigned getNumDecls() const { return OverloadExprBits.NumResults; } /// Gets the full name info. const DeclarationNameInfo &getNameInfo() const { return NameInfo; } @@ -2698,21 +2758,24 @@ public: /// Retrieve the location of the template keyword preceding /// this name, if any. SourceLocation getTemplateKeywordLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc; } /// Retrieve the location of the left angle bracket starting the /// explicit template argument list following the name, if any. SourceLocation getLAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc; } /// Retrieve the location of the right angle bracket ending the /// explicit template argument list following the name, if any. SourceLocation getRAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc; } @@ -2764,97 +2827,93 @@ public: /// members and therefore appear only in UnresolvedMemberLookupExprs. class UnresolvedLookupExpr final : public OverloadExpr, - private llvm::TrailingObjects< - UnresolvedLookupExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { + private llvm::TrailingObjects<UnresolvedLookupExpr, DeclAccessPair, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { friend class ASTStmtReader; friend class OverloadExpr; friend TrailingObjects; - /// True if these lookup results should be extended by - /// argument-dependent lookup if this is the operand of a function - /// call. - bool RequiresADL = false; - - /// True if these lookup results are overloaded. This is pretty - /// trivially rederivable if we urgently need to kill this field. - bool Overloaded = false; - /// The naming class (C++ [class.access.base]p5) of the lookup, if /// any. This can generally be recalculated from the context chain, - /// but that can be fairly expensive for unqualified lookups. If we - /// want to improve memory use here, this could go in a union - /// against the qualified-lookup bits. - CXXRecordDecl *NamingClass = nullptr; + /// but that can be fairly expensive for unqualified lookups. + CXXRecordDecl *NamingClass; + + // UnresolvedLookupExpr is followed by several trailing objects. + // They are in order: + // + // * An array of getNumResults() DeclAccessPair for the results. These are + // undesugared, which is to say, they may include UsingShadowDecls. + // Access is relative to the naming class. + // + // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified + // template keyword and arguments. Present if and only if + // hasTemplateKWAndArgsInfo(). + // + // * An array of getNumTemplateArgs() TemplateArgumentLoc containing + // location information for the explicitly specified template arguments. - UnresolvedLookupExpr(const ASTContext &C, - CXXRecordDecl *NamingClass, + UnresolvedLookupExpr(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - bool RequiresADL, bool Overloaded, + const DeclarationNameInfo &NameInfo, bool RequiresADL, + bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End) - : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, TemplateKWLoc, - NameInfo, TemplateArgs, Begin, End, false, false, false), - RequiresADL(RequiresADL), - Overloaded(Overloaded), NamingClass(NamingClass) {} + UnresolvedSetIterator Begin, UnresolvedSetIterator End); - UnresolvedLookupExpr(EmptyShell Empty) - : OverloadExpr(UnresolvedLookupExprClass, Empty) {} + UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults, + bool HasTemplateKWAndArgsInfo); - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; + unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const { + return getNumDecls(); } -public: - static UnresolvedLookupExpr *Create(const ASTContext &C, - CXXRecordDecl *NamingClass, - NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, - bool ADL, bool Overloaded, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { - return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, - SourceLocation(), NameInfo, - ADL, Overloaded, nullptr, Begin, End); + unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return hasTemplateKWAndArgsInfo(); } - static UnresolvedLookupExpr *Create(const ASTContext &C, - CXXRecordDecl *NamingClass, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - bool ADL, - const TemplateArgumentListInfo *Args, - UnresolvedSetIterator Begin, - UnresolvedSetIterator End); +public: + static UnresolvedLookupExpr * + Create(const ASTContext &Context, CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, + UnresolvedSetIterator Begin, UnresolvedSetIterator End); + + static UnresolvedLookupExpr * + Create(const ASTContext &Context, CXXRecordDecl *NamingClass, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, bool RequiresADL, + const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, + UnresolvedSetIterator End); - static UnresolvedLookupExpr *CreateEmpty(const ASTContext &C, + static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context, + unsigned NumResults, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); /// True if this declaration should be extended by /// argument-dependent lookup. - bool requiresADL() const { return RequiresADL; } + bool requiresADL() const { return UnresolvedLookupExprBits.RequiresADL; } /// True if this lookup is overloaded. - bool isOverloaded() const { return Overloaded; } + bool isOverloaded() const { return UnresolvedLookupExprBits.Overloaded; } /// Gets the 'naming class' (in the sense of C++0x /// [class.access.base]p5) of the lookup. This is the scope /// that was looked in to find these results. - CXXRecordDecl *getNamingClass() const { return NamingClass; } + CXXRecordDecl *getNamingClass() { return NamingClass; } + const CXXRecordDecl *getNamingClass() const { return NamingClass; } - SourceLocation getLocStart() const LLVM_READONLY { + SourceLocation getBeginLoc() const LLVM_READONLY { if (NestedNameSpecifierLoc l = getQualifierLoc()) return l.getBeginLoc(); - return getNameInfo().getLocStart(); + return getNameInfo().getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { + SourceLocation getEndLoc() const LLVM_READONLY { if (hasExplicitTemplateArgs()) return getRAngleLoc(); - return getNameInfo().getLocEnd(); + return getNameInfo().getEndLoc(); } child_range children() { @@ -2885,6 +2944,10 @@ class DependentScopeDeclRefExpr final private llvm::TrailingObjects<DependentScopeDeclRefExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + /// The nested-name-specifier that qualifies this unresolved /// declaration name. NestedNameSpecifierLoc QualifierLoc; @@ -2892,32 +2955,26 @@ class DependentScopeDeclRefExpr final /// The name of the entity we will be referencing. DeclarationNameInfo NameInfo; - /// Whether the name includes info for explicit template - /// keyword and arguments. - bool HasTemplateKWAndArgsInfo; - - DependentScopeDeclRefExpr(QualType T, - NestedNameSpecifierLoc QualifierLoc, + DependentScopeDeclRefExpr(QualType Ty, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *Args); size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; + return hasTemplateKWAndArgsInfo(); } -public: - friend class ASTStmtReader; - friend class ASTStmtWriter; - friend TrailingObjects; + bool hasTemplateKWAndArgsInfo() const { + return DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo; + } - static DependentScopeDeclRefExpr *Create(const ASTContext &C, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs); +public: + static DependentScopeDeclRefExpr * + Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs); - static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &C, + static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &Context, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); @@ -2945,21 +3002,24 @@ public: /// Retrieve the location of the template keyword preceding /// this name, if any. SourceLocation getTemplateKeywordLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// Retrieve the location of the left angle bracket starting the /// explicit template argument list following the name, if any. SourceLocation getLAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// Retrieve the location of the right angle bracket ending the /// explicit template argument list following the name, if any. SourceLocation getRAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } @@ -2995,13 +3055,13 @@ public: return {getTemplateArgs(), getNumTemplateArgs()}; } - /// Note: getLocStart() is the start of the whole DependentScopeDeclRefExpr, + /// Note: getBeginLoc() is the start of the whole DependentScopeDeclRefExpr, /// and differs from getLocation().getStart(). - SourceLocation getLocStart() const LLVM_READONLY { + SourceLocation getBeginLoc() const LLVM_READONLY { return QualifierLoc.getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { + SourceLocation getEndLoc() const LLVM_READONLY { if (hasExplicitTemplateArgs()) return getRAngleLoc(); return getLocation(); @@ -3027,7 +3087,7 @@ public: /// potentially-evaluated block literal. The lifetime of a block /// literal is the extent of the enclosing scope. class ExprWithCleanups final - : public Expr, + : public FullExpr, private llvm::TrailingObjects<ExprWithCleanups, BlockDecl *> { public: /// The type of objects that are kept in the cleanup. @@ -3040,8 +3100,6 @@ private: friend class ASTStmtReader; friend TrailingObjects; - Stmt *SubExpr; - ExprWithCleanups(EmptyShell, unsigned NumObjects); ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> Objects); @@ -3066,22 +3124,17 @@ public: return getObjects()[i]; } - Expr *getSubExpr() { return cast<Expr>(SubExpr); } - const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } - bool cleanupsHaveSideEffects() const { return ExprWithCleanupsBits.CleanupsHaveSideEffects; } - /// As with any mutator of the AST, be very careful - /// when modifying an existing AST to preserve its invariants. - void setSubExpr(Expr *E) { SubExpr = E; } - - SourceLocation getLocStart() const LLVM_READONLY { - return SubExpr->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return SubExpr->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();} + SourceLocation getEndLoc() const LLVM_READONLY { + return SubExpr->getEndLoc(); + } // Implement isa/cast/dyncast/etc. static bool classof(const Stmt *T) { @@ -3120,7 +3173,7 @@ class CXXUnresolvedConstructExpr final friend TrailingObjects; /// The type being constructed. - TypeSourceInfo *Type = nullptr; + TypeSourceInfo *TSI; /// The location of the left parentheses ('('). SourceLocation LParenLoc; @@ -3128,34 +3181,31 @@ class CXXUnresolvedConstructExpr final /// The location of the right parentheses (')'). SourceLocation RParenLoc; - /// The number of arguments used to construct the type. - unsigned NumArgs; - - CXXUnresolvedConstructExpr(TypeSourceInfo *Type, - SourceLocation LParenLoc, - ArrayRef<Expr*> Args, - SourceLocation RParenLoc); + CXXUnresolvedConstructExpr(TypeSourceInfo *TSI, SourceLocation LParenLoc, + ArrayRef<Expr *> Args, SourceLocation RParenLoc); CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) - : Expr(CXXUnresolvedConstructExprClass, Empty), NumArgs(NumArgs) {} + : Expr(CXXUnresolvedConstructExprClass, Empty) { + CXXUnresolvedConstructExprBits.NumArgs = NumArgs; + } public: - static CXXUnresolvedConstructExpr *Create(const ASTContext &C, + static CXXUnresolvedConstructExpr *Create(const ASTContext &Context, TypeSourceInfo *Type, SourceLocation LParenLoc, - ArrayRef<Expr*> Args, + ArrayRef<Expr *> Args, SourceLocation RParenLoc); - static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &C, + static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &Context, unsigned NumArgs); /// Retrieve the type that is being constructed, as specified /// in the source code. - QualType getTypeAsWritten() const { return Type->getType(); } + QualType getTypeAsWritten() const { return TSI->getType(); } /// Retrieve the type source information for the type being /// constructed. - TypeSourceInfo *getTypeSourceInfo() const { return Type; } + TypeSourceInfo *getTypeSourceInfo() const { return TSI; } /// Retrieve the location of the left parentheses ('(') that /// precedes the argument list. @@ -3173,40 +3223,43 @@ public: bool isListInitialization() const { return LParenLoc.isInvalid(); } /// Retrieve the number of arguments. - unsigned arg_size() const { return NumArgs; } + unsigned arg_size() const { return CXXUnresolvedConstructExprBits.NumArgs; } using arg_iterator = Expr **; + using arg_range = llvm::iterator_range<arg_iterator>; arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); } - arg_iterator arg_end() { return arg_begin() + NumArgs; } + arg_iterator arg_end() { return arg_begin() + arg_size(); } + arg_range arguments() { return arg_range(arg_begin(), arg_end()); } using const_arg_iterator = const Expr* const *; + using const_arg_range = llvm::iterator_range<const_arg_iterator>; const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); } - const_arg_iterator arg_end() const { - return arg_begin() + NumArgs; + const_arg_iterator arg_end() const { return arg_begin() + arg_size(); } + const_arg_range arguments() const { + return const_arg_range(arg_begin(), arg_end()); } Expr *getArg(unsigned I) { - assert(I < NumArgs && "Argument index out-of-range"); - return *(arg_begin() + I); + assert(I < arg_size() && "Argument index out-of-range"); + return arg_begin()[I]; } const Expr *getArg(unsigned I) const { - assert(I < NumArgs && "Argument index out-of-range"); - return *(arg_begin() + I); + assert(I < arg_size() && "Argument index out-of-range"); + return arg_begin()[I]; } void setArg(unsigned I, Expr *E) { - assert(I < NumArgs && "Argument index out-of-range"); - *(arg_begin() + I) = E; + assert(I < arg_size() && "Argument index out-of-range"); + arg_begin()[I] = E; } - SourceLocation getLocStart() const LLVM_READONLY; - - SourceLocation getLocEnd() const LLVM_READONLY { - if (!RParenLoc.isValid() && NumArgs > 0) - return getArg(NumArgs - 1)->getLocEnd(); + SourceLocation getBeginLoc() const LLVM_READONLY; + SourceLocation getEndLoc() const LLVM_READONLY { + if (!RParenLoc.isValid() && arg_size() > 0) + return getArg(arg_size() - 1)->getEndLoc(); return RParenLoc; } @@ -3217,7 +3270,7 @@ public: // Iterators child_range children() { auto **begin = reinterpret_cast<Stmt **>(arg_begin()); - return child_range(begin, begin + NumArgs); + return child_range(begin, begin + arg_size()); } }; @@ -3232,7 +3285,11 @@ class CXXDependentScopeMemberExpr final : public Expr, private llvm::TrailingObjects<CXXDependentScopeMemberExpr, ASTTemplateKWAndArgsInfo, - TemplateArgumentLoc> { + TemplateArgumentLoc, NamedDecl *> { + friend class ASTStmtReader; + friend class ASTStmtWriter; + friend TrailingObjects; + /// The expression for the base pointer or class reference, /// e.g., the \c x in x.f. Can be null in implicit accesses. Stmt *Base; @@ -3241,40 +3298,53 @@ class CXXDependentScopeMemberExpr final /// implicit accesses. QualType BaseType; - /// Whether this member expression used the '->' operator or - /// the '.' operator. - bool IsArrow : 1; - - /// Whether this member expression has info for explicit template - /// keyword and arguments. - bool HasTemplateKWAndArgsInfo : 1; - - /// The location of the '->' or '.' operator. - SourceLocation OperatorLoc; - /// The nested-name-specifier that precedes the member name, if any. + /// FIXME: This could be in principle store as a trailing object. + /// However the performance impact of doing so should be investigated first. NestedNameSpecifierLoc QualifierLoc; - /// In a qualified member access expression such as t->Base::f, this - /// member stores the resolves of name lookup in the context of the member - /// access expression, to be used at instantiation time. - /// - /// FIXME: This member, along with the QualifierLoc, could - /// be stuck into a structure that is optionally allocated at the end of - /// the CXXDependentScopeMemberExpr, to save space in the common case. - NamedDecl *FirstQualifierFoundInScope; - /// The member to which this member expression refers, which /// can be name, overloaded operator, or destructor. /// /// FIXME: could also be a template-id DeclarationNameInfo MemberNameInfo; - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; + // CXXDependentScopeMemberExpr is followed by several trailing objects, + // some of which optional. They are in order: + // + // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified + // template keyword and arguments. Present if and only if + // hasTemplateKWAndArgsInfo(). + // + // * An array of getNumTemplateArgs() TemplateArgumentLoc containing location + // information for the explicitly specified template arguments. + // + // * An optional NamedDecl *. In a qualified member access expression such + // as t->Base::f, this member stores the resolves of name lookup in the + // context of the member access expression, to be used at instantiation + // time. Present if and only if hasFirstQualifierFoundInScope(). + + bool hasTemplateKWAndArgsInfo() const { + return CXXDependentScopeMemberExprBits.HasTemplateKWAndArgsInfo; } - CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, + bool hasFirstQualifierFoundInScope() const { + return CXXDependentScopeMemberExprBits.HasFirstQualifierFoundInScope; + } + + unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return hasTemplateKWAndArgsInfo(); + } + + unsigned numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const { + return getNumTemplateArgs(); + } + + unsigned numTrailingObjects(OverloadToken<NamedDecl *>) const { + return hasFirstQualifierFoundInScope(); + } + + CXXDependentScopeMemberExpr(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, @@ -3283,33 +3353,29 @@ class CXXDependentScopeMemberExpr final DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); -public: - friend class ASTStmtReader; - friend class ASTStmtWriter; - friend TrailingObjects; - - CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, - QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - NamedDecl *FirstQualifierFoundInScope, - DeclarationNameInfo MemberNameInfo); + CXXDependentScopeMemberExpr(EmptyShell Empty, bool HasTemplateKWAndArgsInfo, + bool HasFirstQualifierFoundInScope); +public: static CXXDependentScopeMemberExpr * - Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, + Create(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); static CXXDependentScopeMemberExpr * - CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, - unsigned NumTemplateArgs); + CreateEmpty(const ASTContext &Ctx, bool HasTemplateKWAndArgsInfo, + unsigned NumTemplateArgs, bool HasFirstQualifierFoundInScope); /// True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source /// location of the operator is invalid in this case. - bool isImplicitAccess() const; + bool isImplicitAccess() const { + if (!Base) + return true; + return cast<Expr>(Base)->isImplicitCXXThis(); + } /// Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. @@ -3322,13 +3388,14 @@ public: /// Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. - bool isArrow() const { return IsArrow; } + bool isArrow() const { return CXXDependentScopeMemberExprBits.IsArrow; } /// Retrieve the location of the '->' or '.' operator. - SourceLocation getOperatorLoc() const { return OperatorLoc; } + SourceLocation getOperatorLoc() const { + return CXXDependentScopeMemberExprBits.OperatorLoc; + } - /// Retrieve the nested-name-specifier that qualifies the member - /// name. + /// Retrieve the nested-name-specifier that qualifies the member name. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -3349,17 +3416,17 @@ public: /// combined with the results of name lookup into the type of the object /// expression itself (the class type of x). NamedDecl *getFirstQualifierFoundInScope() const { - return FirstQualifierFoundInScope; + if (!hasFirstQualifierFoundInScope()) + return nullptr; + return *getTrailingObjects<NamedDecl *>(); } - /// Retrieve the name of the member that this expression - /// refers to. + /// Retrieve the name of the member that this expression refers to. const DeclarationNameInfo &getMemberNameInfo() const { return MemberNameInfo; } - /// Retrieve the name of the member that this expression - /// refers to. + /// Retrieve the name of the member that this expression refers to. DeclarationName getMember() const { return MemberNameInfo.getName(); } // Retrieve the location of the name of the member that this @@ -3369,21 +3436,24 @@ public: /// Retrieve the location of the template keyword preceding the /// member name, if any. SourceLocation getTemplateKeywordLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } /// Retrieve the location of the left angle bracket starting the /// explicit template argument list following the member name, if any. SourceLocation getLAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } /// Retrieve the location of the right angle bracket ending the /// explicit template argument list following the member name, if any. SourceLocation getRAngleLoc() const { - if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + if (!hasTemplateKWAndArgsInfo()) + return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } @@ -3424,15 +3494,15 @@ public: return {getTemplateArgs(), getNumTemplateArgs()}; } - SourceLocation getLocStart() const LLVM_READONLY { + SourceLocation getBeginLoc() const LLVM_READONLY { if (!isImplicitAccess()) - return Base->getLocStart(); + return Base->getBeginLoc(); if (getQualifier()) return getQualifierLoc().getBeginLoc(); return MemberNameInfo.getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { + SourceLocation getEndLoc() const LLVM_READONLY { if (hasExplicitTemplateArgs()) return getRAngleLoc(); return MemberNameInfo.getEndLoc(); @@ -3467,25 +3537,18 @@ public: /// DeclRefExpr, depending on whether the member is static. class UnresolvedMemberExpr final : public OverloadExpr, - private llvm::TrailingObjects< - UnresolvedMemberExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { + private llvm::TrailingObjects<UnresolvedMemberExpr, DeclAccessPair, + ASTTemplateKWAndArgsInfo, + TemplateArgumentLoc> { friend class ASTStmtReader; friend class OverloadExpr; friend TrailingObjects; - /// Whether this member expression used the '->' operator or - /// the '.' operator. - bool IsArrow : 1; - - /// Whether the lookup results contain an unresolved using - /// declaration. - bool HasUnresolvedUsing : 1; - /// The expression for the base pointer or class reference, /// e.g., the \c x in x.f. /// /// This can be null if this is an 'unbased' member expression. - Stmt *Base = nullptr; + Stmt *Base; /// The type of the base expression; never null. QualType BaseType; @@ -3493,7 +3556,21 @@ class UnresolvedMemberExpr final /// The location of the '->' or '.' operator. SourceLocation OperatorLoc; - UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing, + // UnresolvedMemberExpr is followed by several trailing objects. + // They are in order: + // + // * An array of getNumResults() DeclAccessPair for the results. These are + // undesugared, which is to say, they may include UsingShadowDecls. + // Access is relative to the naming class. + // + // * An optional ASTTemplateKWAndArgsInfo for the explicitly specified + // template keyword and arguments. Present if and only if + // hasTemplateKWAndArgsInfo(). + // + // * An array of getNumTemplateArgs() TemplateArgumentLoc containing + // location information for the explicitly specified template arguments. + + UnresolvedMemberExpr(const ASTContext &Context, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, @@ -3502,28 +3579,30 @@ class UnresolvedMemberExpr final const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); - UnresolvedMemberExpr(EmptyShell Empty) - : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), - HasUnresolvedUsing(false) {} + UnresolvedMemberExpr(EmptyShell Empty, unsigned NumResults, + bool HasTemplateKWAndArgsInfo); - size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { - return HasTemplateKWAndArgsInfo ? 1 : 0; + unsigned numTrailingObjects(OverloadToken<DeclAccessPair>) const { + return getNumDecls(); + } + + unsigned numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { + return hasTemplateKWAndArgsInfo(); } public: static UnresolvedMemberExpr * - Create(const ASTContext &C, bool HasUnresolvedUsing, - Expr *Base, QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, + Create(const ASTContext &Context, bool HasUnresolvedUsing, Expr *Base, + QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); - static UnresolvedMemberExpr * - CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, - unsigned NumTemplateArgs); + static UnresolvedMemberExpr *CreateEmpty(const ASTContext &Context, + unsigned NumResults, + bool HasTemplateKWAndArgsInfo, + unsigned NumTemplateArgs); /// True if this is an implicit access, i.e., one in which the /// member being accessed was not written in the source. @@ -3546,46 +3625,50 @@ public: /// Determine whether the lookup results contain an unresolved using /// declaration. - bool hasUnresolvedUsing() const { return HasUnresolvedUsing; } + bool hasUnresolvedUsing() const { + return UnresolvedMemberExprBits.HasUnresolvedUsing; + } /// Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. - bool isArrow() const { return IsArrow; } + bool isArrow() const { return UnresolvedMemberExprBits.IsArrow; } /// Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } /// Retrieve the naming class of this lookup. - CXXRecordDecl *getNamingClass() const; + CXXRecordDecl *getNamingClass(); + const CXXRecordDecl *getNamingClass() const { + return const_cast<UnresolvedMemberExpr *>(this)->getNamingClass(); + } /// Retrieve the full name info for the member that this expression /// refers to. const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); } - /// Retrieve the name of the member that this expression - /// refers to. + /// Retrieve the name of the member that this expression refers to. DeclarationName getMemberName() const { return getName(); } - // Retrieve the location of the name of the member that this - // expression refers to. + /// Retrieve the location of the name of the member that this + /// expression refers to. SourceLocation getMemberLoc() const { return getNameLoc(); } - // Return the preferred location (the member name) for the arrow when - // diagnosing a problem with this expression. + /// Return the preferred location (the member name) for the arrow when + /// diagnosing a problem with this expression. SourceLocation getExprLoc() const LLVM_READONLY { return getMemberLoc(); } - SourceLocation getLocStart() const LLVM_READONLY { + SourceLocation getBeginLoc() const LLVM_READONLY { if (!isImplicitAccess()) - return Base->getLocStart(); + return Base->getBeginLoc(); if (NestedNameSpecifierLoc l = getQualifierLoc()) return l.getBeginLoc(); - return getMemberNameInfo().getLocStart(); + return getMemberNameInfo().getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { + SourceLocation getEndLoc() const LLVM_READONLY { if (hasExplicitTemplateArgs()) return getRAngleLoc(); - return getMemberNameInfo().getLocEnd(); + return getMemberNameInfo().getEndLoc(); } static bool classof(const Stmt *T) { @@ -3600,26 +3683,33 @@ public: } }; -inline ASTTemplateKWAndArgsInfo * -OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) +DeclAccessPair *OverloadExpr::getTrailingResults() { + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getTrailingObjects<DeclAccessPair>(); + return cast<UnresolvedMemberExpr>(this)->getTrailingObjects<DeclAccessPair>(); +} + +ASTTemplateKWAndArgsInfo *OverloadExpr::getTrailingASTTemplateKWAndArgsInfo() { + if (!hasTemplateKWAndArgsInfo()) return nullptr; - if (isa<UnresolvedLookupExpr>(this)) - return cast<UnresolvedLookupExpr>(this) - ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); - else - return cast<UnresolvedMemberExpr>(this) - ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); + return cast<UnresolvedMemberExpr>(this) + ->getTrailingObjects<ASTTemplateKWAndArgsInfo>(); +} + +TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() { + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getTrailingObjects<TemplateArgumentLoc>(); + return cast<UnresolvedMemberExpr>(this) + ->getTrailingObjects<TemplateArgumentLoc>(); } -inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() { - if (isa<UnresolvedLookupExpr>(this)) - return cast<UnresolvedLookupExpr>(this) - ->getTrailingObjects<TemplateArgumentLoc>(); - else - return cast<UnresolvedMemberExpr>(this) - ->getTrailingObjects<TemplateArgumentLoc>(); +CXXRecordDecl *OverloadExpr::getNamingClass() { + if (auto *ULE = dyn_cast<UnresolvedLookupExpr>(this)) + return ULE->getNamingClass(); + return cast<UnresolvedMemberExpr>(this)->getNamingClass(); } /// Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]). @@ -3629,7 +3719,6 @@ inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() { class CXXNoexceptExpr : public Expr { friend class ASTStmtReader; - bool Value : 1; Stmt *Operand; SourceRange Range; @@ -3637,21 +3726,23 @@ public: CXXNoexceptExpr(QualType Ty, Expr *Operand, CanThrowResult Val, SourceLocation Keyword, SourceLocation RParen) : Expr(CXXNoexceptExprClass, Ty, VK_RValue, OK_Ordinary, - /*TypeDependent*/false, - /*ValueDependent*/Val == CT_Dependent, + /*TypeDependent*/ false, + /*ValueDependent*/ Val == CT_Dependent, Val == CT_Dependent || Operand->isInstantiationDependent(), Operand->containsUnexpandedParameterPack()), - Value(Val == CT_Cannot), Operand(Operand), Range(Keyword, RParen) {} + Operand(Operand), Range(Keyword, RParen) { + CXXNoexceptExprBits.Value = Val == CT_Cannot; + } CXXNoexceptExpr(EmptyShell Empty) : Expr(CXXNoexceptExprClass, Empty) {} - Expr *getOperand() const { return static_cast<Expr*>(Operand); } + Expr *getOperand() const { return static_cast<Expr *>(Operand); } - SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } - SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - SourceRange getSourceRange() const LLVM_READONLY { return Range; } + SourceLocation getBeginLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } + SourceRange getSourceRange() const { return Range; } - bool getValue() const { return Value; } + bool getValue() const { return CXXNoexceptExprBits.Value; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXNoexceptExprClass; @@ -3725,11 +3816,11 @@ public: return None; } - SourceLocation getLocStart() const LLVM_READONLY { - return Pattern->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return Pattern->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { return EllipsisLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return EllipsisLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == PackExpansionExprClass; @@ -3849,8 +3940,8 @@ public: return llvm::makeArrayRef(Args, Args + Length); } - SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return OperatorLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == SizeOfPackExprClass; @@ -3874,27 +3965,27 @@ class SubstNonTypeTemplateParmExpr : public Expr { /// The replacement expression. Stmt *Replacement; - /// The location of the non-type template parameter reference. - SourceLocation NameLoc; - explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty) : Expr(SubstNonTypeTemplateParmExprClass, Empty) {} public: - SubstNonTypeTemplateParmExpr(QualType type, - ExprValueKind valueKind, - SourceLocation loc, - NonTypeTemplateParmDecl *param, - Expr *replacement) - : Expr(SubstNonTypeTemplateParmExprClass, type, valueKind, OK_Ordinary, - replacement->isTypeDependent(), replacement->isValueDependent(), - replacement->isInstantiationDependent(), - replacement->containsUnexpandedParameterPack()), - Param(param), Replacement(replacement), NameLoc(loc) {} + SubstNonTypeTemplateParmExpr(QualType Ty, ExprValueKind ValueKind, + SourceLocation Loc, + NonTypeTemplateParmDecl *Param, + Expr *Replacement) + : Expr(SubstNonTypeTemplateParmExprClass, Ty, ValueKind, OK_Ordinary, + Replacement->isTypeDependent(), Replacement->isValueDependent(), + Replacement->isInstantiationDependent(), + Replacement->containsUnexpandedParameterPack()), + Param(Param), Replacement(Replacement) { + SubstNonTypeTemplateParmExprBits.NameLoc = Loc; + } - SourceLocation getNameLoc() const { return NameLoc; } - SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; } + SourceLocation getNameLoc() const { + return SubstNonTypeTemplateParmExprBits.NameLoc; + } + SourceLocation getBeginLoc() const { return getNameLoc(); } + SourceLocation getEndLoc() const { return getNameLoc(); } Expr *getReplacement() const { return cast<Expr>(Replacement); } @@ -3905,7 +3996,7 @@ public: } // Iterators - child_range children() { return child_range(&Replacement, &Replacement+1); } + child_range children() { return child_range(&Replacement, &Replacement + 1); } }; /// Represents a reference to a non-type template parameter pack that @@ -3957,8 +4048,8 @@ public: /// template arguments. TemplateArgument getArgumentPack() const; - SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return NameLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return NameLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == SubstNonTypeTemplateParmPackExprClass; @@ -4030,8 +4121,8 @@ public: /// Get an expansion of the parameter pack by index. ParmVarDecl *getExpansion(unsigned I) const { return begin()[I]; } - SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return NameLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return NameLoc; } + SourceLocation getEndLoc() const LLVM_READONLY { return NameLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == FunctionParmPackExprClass; @@ -4142,12 +4233,12 @@ public: return getValueKind() == VK_LValue; } - SourceLocation getLocStart() const LLVM_READONLY { - return getTemporary()->getLocStart(); + SourceLocation getBeginLoc() const LLVM_READONLY { + return getTemporary()->getBeginLoc(); } - SourceLocation getLocEnd() const LLVM_READONLY { - return getTemporary()->getLocEnd(); + SourceLocation getEndLoc() const LLVM_READONLY { + return getTemporary()->getEndLoc(); } static bool classof(const Stmt *T) { @@ -4217,13 +4308,9 @@ public: SourceLocation getEllipsisLoc() const { return EllipsisLoc; } BinaryOperatorKind getOperator() const { return Opcode; } - SourceLocation getLocStart() const LLVM_READONLY { - return LParenLoc; - } + SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return RParenLoc; - } + SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXFoldExprClass; @@ -4312,12 +4399,10 @@ public: return static_cast<Expr*>(SubExprs[SubExpr::Resume]); } - SourceLocation getLocStart() const LLVM_READONLY { - return KeywordLoc; - } + SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return getCommonExpr()->getLocEnd(); + SourceLocation getEndLoc() const LLVM_READONLY { + return getCommonExpr()->getEndLoc(); } child_range children() { @@ -4400,10 +4485,10 @@ public: SourceLocation getKeywordLoc() const { return KeywordLoc; } - SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } + SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { - return getOperand()->getLocEnd(); + SourceLocation getEndLoc() const LLVM_READONLY { + return getOperand()->getEndLoc(); } child_range children() { return child_range(SubExprs, SubExprs + 2); } |
