diff options
Diffstat (limited to 'include/clang/AST/ExprCXX.h')
-rw-r--r-- | include/clang/AST/ExprCXX.h | 392 |
1 files changed, 114 insertions, 278 deletions
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 6356ee7aee63..3a43d6dac140 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -20,7 +20,7 @@ #include "clang/AST/TemplateBase.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/ExpressionTraits.h" -#include "clang/Basic/Lambda.h" +#include "clang/AST/LambdaCapture.h" #include "clang/Basic/TypeTraits.h" #include "llvm/Support/Compiler.h" @@ -486,7 +486,7 @@ class CXXStdInitializerListExpr : public Expr { Stmt *SubExpr; CXXStdInitializerListExpr(EmptyShell Empty) - : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(0) {} + : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(nullptr) {} public: CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr) @@ -553,9 +553,9 @@ public: CXXTypeidExpr(EmptyShell Empty, bool isExpr) : Expr(CXXTypeidExprClass, Empty) { if (isExpr) - Operand = (Expr*)0; + Operand = (Expr*)nullptr; else - Operand = (TypeSourceInfo*)0; + Operand = (TypeSourceInfo*)nullptr; } /// Determine whether this typeid has a type operand which is potentially @@ -692,9 +692,9 @@ public: CXXUuidofExpr(EmptyShell Empty, bool isExpr) : Expr(CXXUuidofExprClass, Empty) { if (isExpr) - Operand = (Expr*)0; + Operand = (Expr*)nullptr; else - Operand = (TypeSourceInfo*)0; + Operand = (TypeSourceInfo*)nullptr; } bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } @@ -737,8 +737,8 @@ public: /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to /// a single GUID. - static UuidAttr *GetUuidAttrOfType(QualType QT, - bool *HasMultipleGUIDsPtr = 0); + static const UuidAttr *GetUuidAttrOfType(QualType QT, + bool *HasMultipleGUIDsPtr = nullptr); // Iterators child_range children() { @@ -832,7 +832,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return ThrowLoc; } SourceLocation getLocEnd() const LLVM_READONLY { - if (getSubExpr() == 0) + if (!getSubExpr()) return ThrowLoc; return getSubExpr()->getLocEnd(); } @@ -1031,7 +1031,7 @@ class CXXBindTemporaryExpr : public Expr { public: CXXBindTemporaryExpr(EmptyShell Empty) - : Expr(CXXBindTemporaryExprClass, Empty), Temp(0), SubExpr(0) {} + : Expr(CXXBindTemporaryExprClass, Empty), Temp(nullptr), SubExpr(nullptr) {} static CXXBindTemporaryExpr *Create(const ASTContext &C, CXXTemporary *Temp, Expr* SubExpr); @@ -1077,6 +1077,7 @@ private: bool Elidable : 1; bool HadMultipleCandidates : 1; bool ListInitialization : 1; + bool StdInitListInitialization : 1; bool ZeroInitialization : 1; unsigned ConstructKind : 2; Stmt **Args; @@ -1088,24 +1089,25 @@ protected: ArrayRef<Expr *> Args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); /// \brief Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), Constructor(0), NumArgs(0), Elidable(false), + : Expr(SC, Empty), Constructor(nullptr), NumArgs(0), Elidable(false), HadMultipleCandidates(false), ListInitialization(false), - ZeroInitialization(false), ConstructKind(0), Args(0) + ZeroInitialization(false), ConstructKind(0), Args(nullptr) { } public: /// \brief Construct an empty C++ construction expression. explicit CXXConstructExpr(EmptyShell Empty) - : Expr(CXXConstructExprClass, Empty), Constructor(0), + : Expr(CXXConstructExprClass, Empty), Constructor(nullptr), NumArgs(0), Elidable(false), HadMultipleCandidates(false), ListInitialization(false), ZeroInitialization(false), - ConstructKind(0), Args(0) + ConstructKind(0), Args(nullptr) { } static CXXConstructExpr *Create(const ASTContext &C, QualType T, @@ -1114,6 +1116,7 @@ public: ArrayRef<Expr *> Args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); @@ -1137,6 +1140,13 @@ public: bool isListInitialization() const { return ListInitialization; } void setListInitialization(bool V) { ListInitialization = V; } + /// \brief 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; } + /// \brief Whether this construction first requires /// zero-initialization before the initializer is called. bool requiresZeroInitialization() const { return ZeroInitialization; } @@ -1161,7 +1171,10 @@ public: const_arg_iterator arg_begin() const { return Args; } const_arg_iterator arg_end() const { return Args + NumArgs; } - Expr **getArgs() const { return reinterpret_cast<Expr **>(Args); } + Expr **getArgs() { return reinterpret_cast<Expr **>(Args); } + const Expr *const *getArgs() const { + return const_cast<CXXConstructExpr *>(this)->getArgs(); + } unsigned getNumArgs() const { return NumArgs; } /// \brief Return the specified argument. @@ -1269,6 +1282,7 @@ public: SourceRange ParenOrBraceRange, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization); explicit CXXTemporaryObjectExpr(EmptyShell Empty) : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } @@ -1307,18 +1321,6 @@ public: /// includes an initializing expression (rather than capturing a variable), /// and which can never occur implicitly. class LambdaExpr : public Expr { - enum { - /// \brief Flag used by the Capture class to indicate that the given - /// capture was implicit. - Capture_Implicit = 0x01, - - /// \brief Flag used by the Capture class to indicate that the - /// given capture was by-copy. - /// - /// This includes the case of a non-reference init-capture. - Capture_ByCopy = 0x02 - }; - /// \brief The source range that covers the lambda introducer ([...]). SourceRange IntroducerRange; @@ -1357,93 +1359,8 @@ class LambdaExpr : public Expr { // expression, along with the index variables used to initialize by-copy // array captures. -public: - /// \brief Describes the capture of a variable or of \c this, or of a - /// C++1y init-capture. - class Capture { - llvm::PointerIntPair<Decl *, 2> DeclAndBits; - SourceLocation Loc; - SourceLocation EllipsisLoc; - - friend class ASTStmtReader; - friend class ASTStmtWriter; - - public: - /// \brief Create a new capture of a variable or of \c this. - /// - /// \param Loc The source location associated with this capture. - /// - /// \param Kind The kind of capture (this, byref, bycopy), which must - /// not be init-capture. - /// - /// \param Implicit Whether the capture was implicit or explicit. - /// - /// \param Var The local variable being captured, or null if capturing - /// \c this. - /// - /// \param EllipsisLoc The location of the ellipsis (...) for a - /// capture that is a pack expansion, or an invalid source - /// location to indicate that this is not a pack expansion. - Capture(SourceLocation Loc, bool Implicit, - LambdaCaptureKind Kind, VarDecl *Var = 0, - SourceLocation EllipsisLoc = SourceLocation()); - - /// \brief Determine the kind of capture. - LambdaCaptureKind getCaptureKind() const; - - /// \brief Determine whether this capture handles the C++ \c this - /// pointer. - bool capturesThis() const { return DeclAndBits.getPointer() == 0; } - - /// \brief Determine whether this capture handles a variable. - bool capturesVariable() const { - return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer()); - } - - /// \brief Determine whether this is an init-capture. - bool isInitCapture() const { - return capturesVariable() && getCapturedVar()->isInitCapture(); - } - - /// \brief Retrieve the declaration of the local variable being - /// captured. - /// - /// This operation is only valid if this capture is a variable capture - /// (other than a capture of \c this). - VarDecl *getCapturedVar() const { - assert(capturesVariable() && "No variable available for 'this' capture"); - return cast<VarDecl>(DeclAndBits.getPointer()); - } - - /// \brief Determine whether this was an implicit capture (not - /// written between the square brackets introducing the lambda). - bool isImplicit() const { return DeclAndBits.getInt() & Capture_Implicit; } - - /// \brief Determine whether this was an explicit capture (written - /// between the square brackets introducing the lambda). - bool isExplicit() const { return !isImplicit(); } - - /// \brief Retrieve the source location of the capture. - /// - /// For an explicit capture, this returns the location of the - /// explicit capture in the source. For an implicit capture, this - /// returns the location at which the variable or \c this was first - /// used. - SourceLocation getLocation() const { return Loc; } - - /// \brief Determine whether this capture is a pack expansion, - /// which captures a function parameter pack. - bool isPackExpansion() const { return EllipsisLoc.isValid(); } - - /// \brief Retrieve the location of the ellipsis for a capture - /// that is a pack expansion. - SourceLocation getEllipsisLoc() const { - assert(isPackExpansion() && "No ellipsis location for a non-expansion"); - return EllipsisLoc; - } - }; + typedef LambdaCapture Capture; -private: /// \brief Construct a lambda expression. LambdaExpr(QualType T, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, @@ -1462,7 +1379,7 @@ private: : Expr(LambdaExprClass, Empty), NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false), ExplicitResultType(false), HasArrayIndexVars(true) { - getStoredStmts()[NumCaptures] = 0; + getStoredStmts()[NumCaptures] = nullptr; } Stmt **getStoredStmts() const { @@ -1520,6 +1437,12 @@ public: /// both implicit and explicit. typedef const Capture *capture_iterator; + /// \brief An iterator over a range of lambda captures. + typedef llvm::iterator_range<capture_iterator> capture_range; + + /// \brief Retrieve this lambda's captures. + capture_range captures() const; + /// \brief Retrieve an iterator pointing to the first lambda capture. capture_iterator capture_begin() const; @@ -1529,6 +1452,9 @@ public: /// \brief Determine the number of captures in this lambda. unsigned capture_size() const { return NumCaptures; } + + /// \brief Retrieve this lambda's explicit captures. + capture_range explicit_captures() const; /// \brief Retrieve an iterator pointing to the first explicit /// lambda capture. @@ -1538,6 +1464,9 @@ public: /// explicit lambda captures. capture_iterator explicit_capture_end() const; + /// \brief Retrieve this lambda's implicit captures. + capture_range implicit_captures() const; + /// \brief Retrieve an iterator pointing to the first implicit /// lambda capture. capture_iterator implicit_capture_begin() const; @@ -1550,6 +1479,12 @@ public: /// arguments. typedef Expr **capture_init_iterator; + /// \brief Retrieve the initialization expressions for this lambda's captures. + llvm::iterator_range<capture_init_iterator> capture_inits() const { + return llvm::iterator_range<capture_init_iterator>(capture_init_begin(), + capture_init_end()); + } + /// \brief Retrieve the first initialization argument for this /// lambda expression (which initializes the first capture field). capture_init_iterator capture_init_begin() const { @@ -1717,7 +1652,7 @@ public: QualType ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, SourceRange directInitRange); explicit CXXNewExpr(EmptyShell Shell) - : Expr(CXXNewExprClass, Shell), SubExprs(0) { } + : Expr(CXXNewExprClass, Shell), SubExprs(nullptr) { } void AllocateArgsArray(const ASTContext &C, bool isArray, unsigned numPlaceArgs, bool hasInitializer); @@ -1751,10 +1686,10 @@ public: bool isArray() const { return Array; } Expr *getArraySize() { - return Array ? cast<Expr>(SubExprs[0]) : 0; + return Array ? cast<Expr>(SubExprs[0]) : nullptr; } const Expr *getArraySize() const { - return Array ? cast<Expr>(SubExprs[0]) : 0; + return Array ? cast<Expr>(SubExprs[0]) : nullptr; } unsigned getNumPlacementArgs() const { return NumPlacementArgs; } @@ -1788,10 +1723,10 @@ public: /// \brief The initializer of this new-expression. Expr *getInitializer() { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : 0; + return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; } const Expr *getInitializer() const { - return hasInitializer() ? cast<Expr>(SubExprs[Array]) : 0; + return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; } /// \brief Returns the CXXConstructExpr from this new-expression, or null. @@ -1885,7 +1820,8 @@ public: ArrayForm(arrayForm), ArrayFormAsWritten(arrayFormAsWritten), UsualArrayDeleteWantsSize(usualArrayDeleteWantsSize) { } explicit CXXDeleteExpr(EmptyShell Shell) - : Expr(CXXDeleteExprClass, Shell), OperatorDelete(0), Argument(0) { } + : Expr(CXXDeleteExprClass, Shell), OperatorDelete(nullptr), + Argument(nullptr) {} bool isGlobalDelete() const { return GlobalDelete; } bool isArrayForm() const { return ArrayForm; } @@ -2017,7 +1953,7 @@ public: explicit CXXPseudoDestructorExpr(EmptyShell Shell) : Expr(CXXPseudoDestructorExprClass, Shell), - Base(0), IsArrow(false), QualifierLoc(), ScopeType(0) { } + Base(nullptr), IsArrow(false), QualifierLoc(), ScopeType(nullptr) { } Expr *getBase() const { return cast<Expr>(Base); } @@ -2110,138 +2046,12 @@ public: child_range children() { return child_range(&Base, &Base + 1); } }; -/// \brief Represents a GCC or MS unary type trait, as used in the -/// implementation of TR1/C++11 type trait templates. -/// -/// Example: -/// \code -/// __is_pod(int) == true -/// __is_enum(std::string) == false -/// \endcode -class UnaryTypeTraitExpr : public Expr { - /// \brief The trait. A UnaryTypeTrait enum in MSVC compatible unsigned. - unsigned UTT : 31; - /// The value of the type trait. Unspecified if dependent. - bool Value : 1; - - /// \brief The location of the type trait keyword. - SourceLocation Loc; - - /// \brief The location of the closing paren. - SourceLocation RParen; - - /// \brief The type being queried. - TypeSourceInfo *QueriedType; - -public: - UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, - TypeSourceInfo *queried, bool value, - SourceLocation rparen, QualType ty) - : Expr(UnaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, - false, queried->getType()->isDependentType(), - queried->getType()->isInstantiationDependentType(), - queried->getType()->containsUnexpandedParameterPack()), - UTT(utt), Value(value), Loc(loc), RParen(rparen), QueriedType(queried) { } - - explicit UnaryTypeTraitExpr(EmptyShell Empty) - : Expr(UnaryTypeTraitExprClass, Empty), UTT(0), Value(false), - QueriedType() { } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } - - UnaryTypeTrait getTrait() const { return static_cast<UnaryTypeTrait>(UTT); } - - QualType getQueriedType() const { return QueriedType->getType(); } - - TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; } - - bool getValue() const { return Value; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == UnaryTypeTraitExprClass; - } - - // Iterators - child_range children() { return child_range(); } - - friend class ASTStmtReader; -}; - -/// \brief Represents a GCC or MS binary type trait, as used in the -/// implementation of TR1/C++11 type trait templates. -/// -/// Example: -/// \code -/// __is_base_of(Base, Derived) == true -/// \endcode -class BinaryTypeTraitExpr : public Expr { - /// \brief The trait. A BinaryTypeTrait enum in MSVC compatible unsigned. - unsigned BTT : 8; - - /// The value of the type trait. Unspecified if dependent. - bool Value : 1; - - /// \brief The location of the type trait keyword. - SourceLocation Loc; - - /// \brief The location of the closing paren. - SourceLocation RParen; - - /// \brief The lhs type being queried. - TypeSourceInfo *LhsType; - - /// \brief The rhs type being queried. - TypeSourceInfo *RhsType; - -public: - BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt, - TypeSourceInfo *lhsType, TypeSourceInfo *rhsType, - bool value, SourceLocation rparen, QualType ty) - : Expr(BinaryTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, false, - lhsType->getType()->isDependentType() || - rhsType->getType()->isDependentType(), - (lhsType->getType()->isInstantiationDependentType() || - rhsType->getType()->isInstantiationDependentType()), - (lhsType->getType()->containsUnexpandedParameterPack() || - rhsType->getType()->containsUnexpandedParameterPack())), - BTT(btt), Value(value), Loc(loc), RParen(rparen), - LhsType(lhsType), RhsType(rhsType) { } - - - explicit BinaryTypeTraitExpr(EmptyShell Empty) - : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false), - LhsType(), RhsType() { } - - SourceLocation getLocStart() const LLVM_READONLY { return Loc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } - - BinaryTypeTrait getTrait() const { - return static_cast<BinaryTypeTrait>(BTT); - } - - QualType getLhsType() const { return LhsType->getType(); } - QualType getRhsType() const { return RhsType->getType(); } - - TypeSourceInfo *getLhsTypeSourceInfo() const { return LhsType; } - TypeSourceInfo *getRhsTypeSourceInfo() const { return RhsType; } - - bool getValue() const { assert(!isTypeDependent()); return Value; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == BinaryTypeTraitExprClass; - } - - // Iterators - child_range children() { return child_range(); } - - friend class ASTStmtReader; -}; - /// \brief A type trait used in the implementation of various C++11 and /// Library TR1 trait templates. /// /// \code +/// __is_pod(int) == true +/// __is_enum(std::string) == false /// __is_trivially_constructible(vector<int>, int*, int*) /// \endcode class TypeTraitExpr : public Expr { @@ -2334,7 +2144,7 @@ public: friend class ASTStmtWriter; }; - + /// \brief An Embarcadero array type trait, as used in the implementation of /// __array_rank and __array_extent. /// @@ -2504,7 +2314,7 @@ protected: bool KnownContainsUnexpandedParameterPack); OverloadExpr(StmtClass K, EmptyShell Empty) - : Expr(K, Empty), QualifierLoc(), Results(0), NumResults(0), + : Expr(K, Empty), QualifierLoc(), Results(nullptr), NumResults(0), HasTemplateKWAndArgsInfo(false) { } void initializeResults(const ASTContext &C, @@ -2554,6 +2364,9 @@ public: decls_iterator decls_end() const { return UnresolvedSetIterator(Results + NumResults); } + llvm::iterator_range<decls_iterator> decls() const { + return llvm::iterator_range<decls_iterator>(decls_begin(), decls_end()); + } /// \brief Gets the number of declarations in the unresolved set. unsigned getNumDecls() const { return NumResults; } @@ -2634,7 +2447,7 @@ public: /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return 0; + if (!hasExplicitTemplateArgs()) return nullptr; return &getExplicitTemplateArgs(); } @@ -2691,7 +2504,7 @@ class UnresolvedLookupExpr : public OverloadExpr { UnresolvedLookupExpr(EmptyShell Empty) : OverloadExpr(UnresolvedLookupExprClass, Empty), - RequiresADL(false), Overloaded(false), NamingClass(0) + RequiresADL(false), Overloaded(false), NamingClass(nullptr) {} friend class ASTStmtReader; @@ -2706,7 +2519,7 @@ public: UnresolvedSetIterator End) { return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, SourceLocation(), NameInfo, - ADL, Overloaded, 0, Begin, End); + ADL, Overloaded, nullptr, Begin, End); } static UnresolvedLookupExpr *Create(const ASTContext &C, @@ -2781,7 +2594,7 @@ class DependentScopeDeclRefExpr : public Expr { /// \brief Return the optional template keyword and arguments info. ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return 0; + if (!HasTemplateKWAndArgsInfo) return nullptr; return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1); } /// \brief Return the optional template keyword and arguments info. @@ -2875,7 +2688,7 @@ public: /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return 0; + if (!hasExplicitTemplateArgs()) return nullptr; return &getExplicitTemplateArgs(); } @@ -3151,7 +2964,7 @@ class CXXDependentScopeMemberExpr : public Expr { /// \brief Return the optional template keyword and arguments info. ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return 0; + if (!HasTemplateKWAndArgsInfo) return nullptr; return reinterpret_cast<ASTTemplateKWAndArgsInfo*>(this + 1); } /// \brief Return the optional template keyword and arguments info. @@ -3296,7 +3109,7 @@ public: /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { - if (!hasExplicitTemplateArgs()) return 0; + if (!hasExplicitTemplateArgs()) return nullptr; return &getExplicitTemplateArgs(); } @@ -3398,7 +3211,7 @@ class UnresolvedMemberExpr : public OverloadExpr { UnresolvedMemberExpr(EmptyShell Empty) : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), - HasUnresolvedUsing(false), Base(0) { } + HasUnresolvedUsing(false), Base(nullptr) { } friend class ASTStmtReader; @@ -3612,7 +3425,7 @@ public: }; inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() { - if (!HasTemplateKWAndArgsInfo) return 0; + if (!HasTemplateKWAndArgsInfo) return nullptr; if (isa<UnresolvedLookupExpr>(this)) return reinterpret_cast<ASTTemplateKWAndArgsInfo*> (cast<UnresolvedLookupExpr>(this) + 1); @@ -3904,39 +3717,51 @@ public: /// temporary. When either happens, the expression will also track the /// declaration which is responsible for the lifetime extension. class MaterializeTemporaryExpr : public Expr { -public: - /// \brief The temporary-generating expression whose value will be - /// materialized. - Stmt *Temporary; +private: + struct ExtraState { + /// \brief The temporary-generating expression whose value will be + /// materialized. + Stmt *Temporary; - /// \brief The declaration which lifetime-extended this reference, if any. - /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl. - const ValueDecl *ExtendingDecl; + /// \brief The declaration which lifetime-extended this reference, if any. + /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl. + const ValueDecl *ExtendingDecl; + + unsigned ManglingNumber; + }; + llvm::PointerUnion<Stmt *, ExtraState *> State; friend class ASTStmtReader; friend class ASTStmtWriter; + void initializeExtraState(const ValueDecl *ExtendedBy, + unsigned ManglingNumber); + public: MaterializeTemporaryExpr(QualType T, Expr *Temporary, - bool BoundToLvalueReference, - const ValueDecl *ExtendedBy) + bool BoundToLvalueReference) : Expr(MaterializeTemporaryExprClass, T, BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary, Temporary->isTypeDependent(), Temporary->isValueDependent(), Temporary->isInstantiationDependent(), Temporary->containsUnexpandedParameterPack()), - Temporary(Temporary), ExtendingDecl(ExtendedBy) { - } + State(Temporary) {} MaterializeTemporaryExpr(EmptyShell Empty) : Expr(MaterializeTemporaryExprClass, Empty) { } + Stmt *getTemporary() const { + return State.is<Stmt *>() ? State.get<Stmt *>() + : State.get<ExtraState *>()->Temporary; + } + /// \brief Retrieve the temporary-generating subexpression whose value will /// be materialized into a glvalue. - Expr *GetTemporaryExpr() const { return static_cast<Expr *>(Temporary); } + Expr *GetTemporaryExpr() const { return static_cast<Expr *>(getTemporary()); } /// \brief Retrieve the storage duration for the materialized temporary. StorageDuration getStorageDuration() const { + const ValueDecl *ExtendingDecl = getExtendingDecl(); if (!ExtendingDecl) return SD_FullExpression; // FIXME: This is not necessarily correct for a temporary materialized @@ -3948,10 +3773,15 @@ public: /// \brief Get the declaration which triggered the lifetime-extension of this /// temporary, if any. - const ValueDecl *getExtendingDecl() const { return ExtendingDecl; } + const ValueDecl *getExtendingDecl() const { + return State.is<Stmt *>() ? nullptr + : State.get<ExtraState *>()->ExtendingDecl; + } + + void setExtendingDecl(const ValueDecl *ExtendedBy, unsigned ManglingNumber); - void setExtendingDecl(const ValueDecl *ExtendedBy) { - ExtendingDecl = ExtendedBy; + unsigned getManglingNumber() const { + return State.is<Stmt *>() ? 0 : State.get<ExtraState *>()->ManglingNumber; } /// \brief Determine whether this materialized temporary is bound to an @@ -3961,10 +3791,10 @@ public: } SourceLocation getLocStart() const LLVM_READONLY { - return Temporary->getLocStart(); + return getTemporary()->getLocStart(); } SourceLocation getLocEnd() const LLVM_READONLY { - return Temporary->getLocEnd(); + return getTemporary()->getLocEnd(); } static bool classof(const Stmt *T) { @@ -3972,7 +3802,13 @@ public: } // Iterators - child_range children() { return child_range(&Temporary, &Temporary + 1); } + child_range children() { + if (State.is<Stmt *>()) + return child_range(State.getAddrOfPtr1(), State.getAddrOfPtr1() + 1); + + auto ES = State.get<ExtraState *>(); + return child_range(&ES->Temporary, &ES->Temporary + 1); + } }; } // end namespace clang |