| //===--- ExprCXX.h - Classes for representing expressions -------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// \brief Defines the clang::Expr interface and subclasses for C++ expressions. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_AST_EXPRCXX_H |
| #define LLVM_CLANG_AST_EXPRCXX_H |
| |
| #include "clang/AST/Decl.h" |
| #include "clang/AST/DeclCXX.h" |
| #include "clang/AST/Expr.h" |
| #include "clang/AST/LambdaCapture.h" |
| #include "clang/AST/TemplateBase.h" |
| #include "clang/AST/UnresolvedSet.h" |
| #include "clang/Basic/ExpressionTraits.h" |
| #include "clang/Basic/TypeTraits.h" |
| #include "llvm/Support/Compiler.h" |
| |
| namespace clang { |
| |
| class CXXTemporary; |
| class MSPropertyDecl; |
| class TemplateArgumentListInfo; |
| class UuidAttr; |
| |
| //===--------------------------------------------------------------------===// |
| // C++ Expressions. |
| //===--------------------------------------------------------------------===// |
| |
| /// \brief A call to an overloaded operator written using operator |
| /// syntax. |
| /// |
| /// Represents a call to an overloaded operator written using operator |
| /// syntax, e.g., "x + y" or "*p". While semantically equivalent to a |
| /// normal call, this AST node provides better information about the |
| /// syntactic representation of the call. |
| /// |
| /// In a C++ template, this expression node kind will be used whenever |
| /// any of the arguments are type-dependent. In this case, the |
| /// 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 { |
| /// \brief The overloaded operator. |
| OverloadedOperatorKind Operator; |
| SourceRange Range; |
| |
| // Record the FP_CONTRACT state that applies to this operator call. Only |
| // meaningful for floating point types. For other types this value can be |
| // set to false. |
| unsigned FPContractable : 1; |
| |
| SourceRange getSourceRangeImpl() const LLVM_READONLY; |
| public: |
| CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, |
| ArrayRef<Expr*> args, QualType t, ExprValueKind VK, |
| SourceLocation operatorloc, bool fpContractable) |
| : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc), |
| Operator(Op), FPContractable(fpContractable) { |
| Range = getSourceRangeImpl(); |
| } |
| explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : |
| CallExpr(C, CXXOperatorCallExprClass, Empty) { } |
| |
| |
| /// \brief Returns the kind of overloaded operator that this |
| /// expression refers to. |
| OverloadedOperatorKind getOperator() const { return Operator; } |
| |
| /// \brief Returns the location of the operator symbol in the expression. |
| /// |
| /// When \c getOperator()==OO_Call, this is the location of the right |
| /// parentheses; when \c getOperator()==OO_Subscript, this is the location |
| /// of the right bracket. |
| SourceLocation getOperatorLoc() const { return getRParenLoc(); } |
| |
| SourceLocation getExprLoc() const LLVM_READONLY { |
| return (Operator < OO_Plus || Operator >= OO_Arrow || |
| Operator == OO_PlusPlus || Operator == OO_MinusMinus) |
| ? getLocStart() |
| : getOperatorLoc(); |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } |
| SourceRange getSourceRange() const { return Range; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXOperatorCallExprClass; |
| } |
| |
| // Set the FP contractability status of this operator. Only meaningful for |
| // operations on floating point types. |
| void setFPContractable(bool FPC) { FPContractable = FPC; } |
| |
| // Get the FP contractability status of this operator. Only meaningful for |
| // operations on floating point types. |
| bool isFPContractable() const { return FPContractable; } |
| |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| }; |
| |
| /// Represents a call to a member function that |
| /// may be written either with member call syntax (e.g., "obj.func()" |
| /// or "objptr->func()") or with normal function-call syntax |
| /// ("func()") within a member function that ends up calling a member |
| /// function. The callee in either case is a MemberExpr that contains |
| /// 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 { |
| public: |
| CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef<Expr*> args, |
| QualType t, ExprValueKind VK, SourceLocation RP) |
| : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP) {} |
| |
| CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) |
| : CallExpr(C, CXXMemberCallExprClass, Empty) { } |
| |
| /// \brief Retrieves the implicit object argument for the member call. |
| /// |
| /// For example, in "x.f(5)", this returns the sub-expression "x". |
| Expr *getImplicitObjectArgument() const; |
| |
| /// \brief Retrieves the declaration of the called method. |
| CXXMethodDecl *getMethodDecl() const; |
| |
| /// \brief Retrieves the CXXRecordDecl for the underlying type of |
| /// the implicit object argument. |
| /// |
| /// Note that this is may not be the same declaration as that of the class |
| /// context of the CXXMethodDecl which this function is calling. |
| /// FIXME: Returns 0 for member pointer call exprs. |
| CXXRecordDecl *getRecordDecl() const; |
| |
| SourceLocation getExprLoc() const LLVM_READONLY { |
| SourceLocation CLoc = getCallee()->getExprLoc(); |
| if (CLoc.isValid()) |
| return CLoc; |
| |
| return getLocStart(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXMemberCallExprClass; |
| } |
| }; |
| |
| /// \brief Represents a call to a CUDA kernel function. |
| class CUDAKernelCallExpr : public CallExpr { |
| private: |
| enum { CONFIG, END_PREARG }; |
| |
| 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) {} |
| |
| CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty) |
| : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) { } |
| |
| const CallExpr *getConfig() const { |
| return cast_or_null<CallExpr>(getPreArg(CONFIG)); |
| } |
| CallExpr *getConfig() { return cast_or_null<CallExpr>(getPreArg(CONFIG)); } |
| |
| /// \brief Sets the kernel configuration expression. |
| /// |
| /// Note that this method cannot be called if config has already been set to a |
| /// non-null value. |
| void setConfig(CallExpr *E) { |
| assert(!getConfig() && |
| "Cannot call setConfig if config is not null"); |
| setPreArg(CONFIG, E); |
| setInstantiationDependent(isInstantiationDependent() || |
| E->isInstantiationDependent()); |
| setContainsUnexpandedParameterPack(containsUnexpandedParameterPack() || |
| E->containsUnexpandedParameterPack()); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CUDAKernelCallExprClass; |
| } |
| }; |
| |
| /// \brief Abstract class common to all of the C++ "named"/"keyword" casts. |
| /// |
| /// This abstract class is inherited by all of the classes |
| /// representing "named" casts: CXXStaticCastExpr for \c static_cast, |
| /// CXXDynamicCastExpr for \c dynamic_cast, CXXReinterpretCastExpr for |
| /// reinterpret_cast, and CXXConstCastExpr for \c const_cast. |
| class CXXNamedCastExpr : public ExplicitCastExpr { |
| private: |
| SourceLocation Loc; // the location of the casting op |
| SourceLocation RParenLoc; // the location of the right parenthesis |
| SourceRange AngleBrackets; // range for '<' '>' |
| |
| protected: |
| CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK, |
| CastKind kind, Expr *op, unsigned PathSize, |
| TypeSourceInfo *writtenTy, SourceLocation l, |
| SourceLocation RParenLoc, |
| SourceRange AngleBrackets) |
| : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, writtenTy), Loc(l), |
| RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {} |
| |
| explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) |
| : ExplicitCastExpr(SC, Shell, PathSize) { } |
| |
| friend class ASTStmtReader; |
| |
| public: |
| const char *getCastName() const; |
| |
| /// \brief Retrieve the location of the cast operator keyword, e.g., |
| /// \c static_cast. |
| SourceLocation getOperatorLoc() const { return Loc; } |
| |
| /// \brief 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; } |
| SourceRange getAngleBrackets() const LLVM_READONLY { return AngleBrackets; } |
| |
| static bool classof(const Stmt *T) { |
| switch (T->getStmtClass()) { |
| case CXXStaticCastExprClass: |
| case CXXDynamicCastExprClass: |
| case CXXReinterpretCastExprClass: |
| case CXXConstCastExprClass: |
| return true; |
| default: |
| return false; |
| } |
| } |
| }; |
| |
| /// \brief A C++ \c static_cast expression (C++ [expr.static.cast]). |
| /// |
| /// This expression node represents a C++ static cast, e.g., |
| /// \c static_cast<int>(1.0). |
| class CXXStaticCastExpr final |
| : public CXXNamedCastExpr, |
| private llvm::TrailingObjects<CXXStaticCastExpr, CXXBaseSpecifier *> { |
| CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, |
| unsigned pathSize, TypeSourceInfo *writtenTy, |
| SourceLocation l, SourceLocation RParenLoc, |
| SourceRange AngleBrackets) |
| : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize, |
| writtenTy, l, RParenLoc, AngleBrackets) {} |
| |
| explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize) |
| : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { } |
| |
| public: |
| static CXXStaticCastExpr *Create(const ASTContext &Context, QualType T, |
| ExprValueKind VK, CastKind K, Expr *Op, |
| const CXXCastPath *Path, |
| TypeSourceInfo *Written, SourceLocation L, |
| SourceLocation RParenLoc, |
| SourceRange AngleBrackets); |
| static CXXStaticCastExpr *CreateEmpty(const ASTContext &Context, |
| unsigned PathSize); |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXStaticCastExprClass; |
| } |
| |
| friend TrailingObjects; |
| friend class CastExpr; |
| }; |
| |
| /// \brief A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]). |
| /// |
| /// This expression node represents a dynamic cast, e.g., |
| /// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time |
| /// check to determine how to perform the type conversion. |
| class CXXDynamicCastExpr final |
| : public CXXNamedCastExpr, |
| private llvm::TrailingObjects<CXXDynamicCastExpr, CXXBaseSpecifier *> { |
| CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, |
| Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, |
| SourceLocation l, SourceLocation RParenLoc, |
| SourceRange AngleBrackets) |
| : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, VK, kind, op, pathSize, |
| writtenTy, l, RParenLoc, AngleBrackets) {} |
| |
| explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) |
| : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { } |
| |
| public: |
| static CXXDynamicCastExpr *Create(const ASTContext &Context, QualType T, |
| ExprValueKind VK, CastKind Kind, Expr *Op, |
| const CXXCastPath *Path, |
| TypeSourceInfo *Written, SourceLocation L, |
| SourceLocation RParenLoc, |
| SourceRange AngleBrackets); |
| |
| static CXXDynamicCastExpr *CreateEmpty(const ASTContext &Context, |
| unsigned pathSize); |
| |
| bool isAlwaysNull() const; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXDynamicCastExprClass; |
| } |
| |
| friend TrailingObjects; |
| friend class CastExpr; |
| }; |
| |
| /// \brief A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]). |
| /// |
| /// This expression node represents a reinterpret cast, e.g., |
| /// @c reinterpret_cast<int>(VoidPtr). |
| /// |
| /// A reinterpret_cast provides a differently-typed view of a value but |
| /// (in Clang, as in most C++ implementations) performs no actual work at |
| /// run time. |
| class CXXReinterpretCastExpr final |
| : public CXXNamedCastExpr, |
| private llvm::TrailingObjects<CXXReinterpretCastExpr, |
| CXXBaseSpecifier *> { |
| CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, |
| Expr *op, unsigned pathSize, |
| TypeSourceInfo *writtenTy, SourceLocation l, |
| SourceLocation RParenLoc, |
| SourceRange AngleBrackets) |
| : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, vk, kind, op, |
| pathSize, writtenTy, l, RParenLoc, AngleBrackets) {} |
| |
| CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) |
| : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { } |
| |
| public: |
| static CXXReinterpretCastExpr *Create(const ASTContext &Context, QualType T, |
| ExprValueKind VK, CastKind Kind, |
| Expr *Op, const CXXCastPath *Path, |
| TypeSourceInfo *WrittenTy, SourceLocation L, |
| SourceLocation RParenLoc, |
| SourceRange AngleBrackets); |
| static CXXReinterpretCastExpr *CreateEmpty(const ASTContext &Context, |
| unsigned pathSize); |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXReinterpretCastExprClass; |
| } |
| |
| friend TrailingObjects; |
| friend class CastExpr; |
| }; |
| |
| /// \brief A C++ \c const_cast expression (C++ [expr.const.cast]). |
| /// |
| /// This expression node represents a const cast, e.g., |
| /// \c const_cast<char*>(PtrToConstChar). |
| /// |
| /// A const_cast can remove type qualifiers but does not change the underlying |
| /// value. |
| class CXXConstCastExpr final |
| : public CXXNamedCastExpr, |
| private llvm::TrailingObjects<CXXConstCastExpr, CXXBaseSpecifier *> { |
| CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, |
| TypeSourceInfo *writtenTy, SourceLocation l, |
| SourceLocation RParenLoc, SourceRange AngleBrackets) |
| : CXXNamedCastExpr(CXXConstCastExprClass, ty, VK, CK_NoOp, op, |
| 0, writtenTy, l, RParenLoc, AngleBrackets) {} |
| |
| explicit CXXConstCastExpr(EmptyShell Empty) |
| : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { } |
| |
| public: |
| static CXXConstCastExpr *Create(const ASTContext &Context, QualType T, |
| ExprValueKind VK, Expr *Op, |
| TypeSourceInfo *WrittenTy, SourceLocation L, |
| SourceLocation RParenLoc, |
| SourceRange AngleBrackets); |
| static CXXConstCastExpr *CreateEmpty(const ASTContext &Context); |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXConstCastExprClass; |
| } |
| |
| friend TrailingObjects; |
| friend class CastExpr; |
| }; |
| |
| /// \brief A call to a literal operator (C++11 [over.literal]) |
| /// written as a user-defined literal (C++11 [lit.ext]). |
| /// |
| /// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this |
| /// is semantically equivalent to a normal call, this AST node provides better |
| /// information about the syntactic representation of the literal. |
| /// |
| /// 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 { |
| /// \brief The location of a ud-suffix within the literal. |
| SourceLocation UDSuffixLoc; |
| |
| public: |
| 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) {} |
| explicit UserDefinedLiteral(const ASTContext &C, EmptyShell Empty) |
| : CallExpr(C, UserDefinedLiteralClass, Empty) {} |
| |
| /// The kind of literal operator which is invoked. |
| enum LiteralOperatorKind { |
| LOK_Raw, ///< Raw form: operator "" X (const char *) |
| LOK_Template, ///< Raw form: operator "" X<cs...> () |
| LOK_Integer, ///< operator "" X (unsigned long long) |
| LOK_Floating, ///< operator "" X (long double) |
| LOK_String, ///< operator "" X (const CharT *, size_t) |
| LOK_Character ///< operator "" X (CharT) |
| }; |
| |
| /// \brief Returns the kind of literal operator invocation |
| /// which this expression represents. |
| LiteralOperatorKind getLiteralOperatorKind() const; |
| |
| /// \brief If this is not a raw user-defined literal, get the |
| /// underlying cooked literal (representing the literal with the suffix |
| /// removed). |
| Expr *getCookedLiteral(); |
| const Expr *getCookedLiteral() const { |
| return const_cast<UserDefinedLiteral*>(this)->getCookedLiteral(); |
| } |
| |
| SourceLocation getLocStart() const { |
| if (getLiteralOperatorKind() == LOK_Template) |
| return getRParenLoc(); |
| return getArg(0)->getLocStart(); |
| } |
| SourceLocation getLocEnd() const { return getRParenLoc(); } |
| |
| |
| /// \brief Returns the location of a ud-suffix in the expression. |
| /// |
| /// For a string literal, there may be multiple identical suffixes. This |
| /// returns the first. |
| SourceLocation getUDSuffixLoc() const { return UDSuffixLoc; } |
| |
| /// \brief Returns the ud-suffix specified for this literal. |
| const IdentifierInfo *getUDSuffix() const; |
| |
| static bool classof(const Stmt *S) { |
| return S->getStmtClass() == UserDefinedLiteralClass; |
| } |
| |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| }; |
| |
| /// \brief 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) : |
| Expr(CXXBoolLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, |
| false, false), |
| Value(val), Loc(l) {} |
| |
| explicit CXXBoolLiteralExpr(EmptyShell Empty) |
| : Expr(CXXBoolLiteralExprClass, Empty) { } |
| |
| bool getValue() const { return Value; } |
| void setValue(bool V) { Value = V; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Loc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } |
| |
| SourceLocation getLocation() const { return Loc; } |
| void setLocation(SourceLocation L) { Loc = L; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXBoolLiteralExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| }; |
| |
| /// \brief The null pointer literal (C++11 [lex.nullptr]) |
| /// |
| /// 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) : |
| Expr(CXXNullPtrLiteralExprClass, Ty, VK_RValue, OK_Ordinary, false, false, |
| false, false), |
| Loc(l) {} |
| |
| explicit CXXNullPtrLiteralExpr(EmptyShell Empty) |
| : Expr(CXXNullPtrLiteralExprClass, Empty) { } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Loc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } |
| |
| SourceLocation getLocation() const { return Loc; } |
| void setLocation(SourceLocation L) { Loc = L; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXNullPtrLiteralExprClass; |
| } |
| |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| }; |
| |
| /// \brief Implicit construction of a std::initializer_list<T> object from an |
| /// array temporary within list-initialization (C++11 [dcl.init.list]p5). |
| class CXXStdInitializerListExpr : public Expr { |
| Stmt *SubExpr; |
| |
| CXXStdInitializerListExpr(EmptyShell Empty) |
| : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(nullptr) {} |
| |
| public: |
| CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr) |
| : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary, |
| Ty->isDependentType(), SubExpr->isValueDependent(), |
| SubExpr->isInstantiationDependent(), |
| SubExpr->containsUnexpandedParameterPack()), |
| SubExpr(SubExpr) {} |
| |
| 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 getLocEnd() const LLVM_READONLY { |
| return SubExpr->getLocEnd(); |
| } |
| SourceRange getSourceRange() const LLVM_READONLY { |
| return SubExpr->getSourceRange(); |
| } |
| |
| static bool classof(const Stmt *S) { |
| return S->getStmtClass() == CXXStdInitializerListExprClass; |
| } |
| |
| child_range children() { return child_range(&SubExpr, &SubExpr + 1); } |
| |
| friend class ASTReader; |
| friend class ASTStmtReader; |
| }; |
| |
| /// A C++ \c typeid expression (C++ [expr.typeid]), which gets |
| /// the \c type_info that corresponds to the supplied type, or the (possibly |
| /// dynamic) type of the supplied expression. |
| /// |
| /// This represents code like \c typeid(int) or \c typeid(*objPtr) |
| class CXXTypeidExpr : public Expr { |
| private: |
| llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; |
| SourceRange Range; |
| |
| public: |
| CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) |
| : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary, |
| // typeid is never type-dependent (C++ [temp.dep.expr]p4) |
| false, |
| // typeid is value-dependent if the type or expression are dependent |
| Operand->getType()->isDependentType(), |
| Operand->getType()->isInstantiationDependentType(), |
| Operand->getType()->containsUnexpandedParameterPack()), |
| Operand(Operand), Range(R) { } |
| |
| CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R) |
| : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary, |
| // typeid is never type-dependent (C++ [temp.dep.expr]p4) |
| false, |
| // typeid is value-dependent if the type or expression are dependent |
| Operand->isTypeDependent() || Operand->isValueDependent(), |
| Operand->isInstantiationDependent(), |
| Operand->containsUnexpandedParameterPack()), |
| Operand(Operand), Range(R) { } |
| |
| CXXTypeidExpr(EmptyShell Empty, bool isExpr) |
| : Expr(CXXTypeidExprClass, Empty) { |
| if (isExpr) |
| Operand = (Expr*)nullptr; |
| else |
| Operand = (TypeSourceInfo*)nullptr; |
| } |
| |
| /// Determine whether this typeid has a type operand which is potentially |
| /// evaluated, per C++11 [expr.typeid]p3. |
| bool isPotentiallyEvaluated() const; |
| |
| bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } |
| |
| /// \brief Retrieves the type operand of this typeid() expression after |
| /// various required adjustments (removing reference types, cv-qualifiers). |
| QualType getTypeOperand(ASTContext &Context) const; |
| |
| /// \brief Retrieve source information for the type operand. |
| TypeSourceInfo *getTypeOperandSourceInfo() const { |
| assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); |
| return Operand.get<TypeSourceInfo *>(); |
| } |
| |
| void setTypeOperandSourceInfo(TypeSourceInfo *TSI) { |
| assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); |
| Operand = TSI; |
| } |
| |
| Expr *getExprOperand() const { |
| assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); |
| return static_cast<Expr*>(Operand.get<Stmt *>()); |
| } |
| |
| void setExprOperand(Expr *E) { |
| assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); |
| Operand = E; |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } |
| SourceRange getSourceRange() const LLVM_READONLY { return Range; } |
| void setSourceRange(SourceRange R) { Range = R; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXTypeidExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| if (isTypeOperand()) |
| return child_range(child_iterator(), child_iterator()); |
| Stmt **begin = reinterpret_cast<Stmt**>(&Operand); |
| return child_range(begin, begin + 1); |
| } |
| }; |
| |
| /// \brief A member reference to an MSPropertyDecl. |
| /// |
| /// This expression always has pseudo-object type, and therefore it is |
| /// typically not encountered in a fully-typechecked expression except |
| /// within the syntactic form of a PseudoObjectExpr. |
| class MSPropertyRefExpr : public Expr { |
| Expr *BaseExpr; |
| MSPropertyDecl *TheDecl; |
| SourceLocation MemberLoc; |
| bool IsArrow; |
| NestedNameSpecifierLoc QualifierLoc; |
| |
| public: |
| MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow, |
| QualType ty, ExprValueKind VK, |
| NestedNameSpecifierLoc qualifierLoc, |
| SourceLocation nameLoc) |
| : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary, |
| /*type-dependent*/ false, baseExpr->isValueDependent(), |
| baseExpr->isInstantiationDependent(), |
| baseExpr->containsUnexpandedParameterPack()), |
| BaseExpr(baseExpr), TheDecl(decl), |
| MemberLoc(nameLoc), IsArrow(isArrow), |
| QualifierLoc(qualifierLoc) {} |
| |
| MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {} |
| |
| SourceRange getSourceRange() const LLVM_READONLY { |
| return SourceRange(getLocStart(), getLocEnd()); |
| } |
| bool isImplicitAccess() const { |
| return getBaseExpr() && getBaseExpr()->isImplicitCXXThis(); |
| } |
| SourceLocation getLocStart() const { |
| if (!isImplicitAccess()) |
| return BaseExpr->getLocStart(); |
| else if (QualifierLoc) |
| return QualifierLoc.getBeginLoc(); |
| else |
| return MemberLoc; |
| } |
| SourceLocation getLocEnd() const { return getMemberLoc(); } |
| |
| child_range children() { |
| return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1); |
| } |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == MSPropertyRefExprClass; |
| } |
| |
| Expr *getBaseExpr() const { return BaseExpr; } |
| MSPropertyDecl *getPropertyDecl() const { return TheDecl; } |
| bool isArrow() const { return IsArrow; } |
| SourceLocation getMemberLoc() const { return MemberLoc; } |
| NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } |
| |
| friend class ASTStmtReader; |
| }; |
| |
| /// MS property subscript expression. |
| /// MSVC supports 'property' attribute and allows to apply it to the |
| /// declaration of an empty array in a class or structure definition. |
| /// For example: |
| /// \code |
| /// __declspec(property(get=GetX, put=PutX)) int x[]; |
| /// \endcode |
| /// The above statement indicates that x[] can be used with one or more array |
| /// indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b), and |
| /// p->x[a][b] = i will be turned into p->PutX(a, b, i). |
| /// This is a syntactic pseudo-object expression. |
| class MSPropertySubscriptExpr : public Expr { |
| friend class ASTStmtReader; |
| enum { BASE_EXPR, IDX_EXPR, NUM_SUBEXPRS = 2 }; |
| Stmt *SubExprs[NUM_SUBEXPRS]; |
| SourceLocation RBracketLoc; |
| |
| void setBase(Expr *Base) { SubExprs[BASE_EXPR] = Base; } |
| void setIdx(Expr *Idx) { SubExprs[IDX_EXPR] = Idx; } |
| |
| public: |
| MSPropertySubscriptExpr(Expr *Base, Expr *Idx, QualType Ty, ExprValueKind VK, |
| ExprObjectKind OK, SourceLocation RBracketLoc) |
| : Expr(MSPropertySubscriptExprClass, Ty, VK, OK, Idx->isTypeDependent(), |
| Idx->isValueDependent(), Idx->isInstantiationDependent(), |
| Idx->containsUnexpandedParameterPack()), |
| RBracketLoc(RBracketLoc) { |
| SubExprs[BASE_EXPR] = Base; |
| SubExprs[IDX_EXPR] = Idx; |
| } |
| |
| /// \brief Create an empty array subscript expression. |
| explicit MSPropertySubscriptExpr(EmptyShell Shell) |
| : Expr(MSPropertySubscriptExprClass, Shell) {} |
| |
| Expr *getBase() { return cast<Expr>(SubExprs[BASE_EXPR]); } |
| const Expr *getBase() const { return cast<Expr>(SubExprs[BASE_EXPR]); } |
| |
| 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 getLocEnd() const LLVM_READONLY { return RBracketLoc; } |
| |
| SourceLocation getRBracketLoc() const { return RBracketLoc; } |
| void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } |
| |
| SourceLocation getExprLoc() const LLVM_READONLY { |
| return getBase()->getExprLoc(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == MSPropertySubscriptExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(&SubExprs[0], &SubExprs[0] + NUM_SUBEXPRS); |
| } |
| }; |
| |
| /// A Microsoft C++ @c __uuidof expression, which gets |
| /// the _GUID that corresponds to the supplied type or expression. |
| /// |
| /// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr) |
| class CXXUuidofExpr : public Expr { |
| private: |
| llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; |
| StringRef UuidStr; |
| SourceRange Range; |
| |
| public: |
| CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, StringRef UuidStr, |
| SourceRange R) |
| : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false, |
| Operand->getType()->isDependentType(), |
| Operand->getType()->isInstantiationDependentType(), |
| Operand->getType()->containsUnexpandedParameterPack()), |
| Operand(Operand), UuidStr(UuidStr), Range(R) {} |
| |
| CXXUuidofExpr(QualType Ty, Expr *Operand, StringRef UuidStr, SourceRange R) |
| : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false, |
| Operand->isTypeDependent(), Operand->isInstantiationDependent(), |
| Operand->containsUnexpandedParameterPack()), |
| Operand(Operand), UuidStr(UuidStr), Range(R) {} |
| |
| CXXUuidofExpr(EmptyShell Empty, bool isExpr) |
| : Expr(CXXUuidofExprClass, Empty) { |
| if (isExpr) |
| Operand = (Expr*)nullptr; |
| else |
| Operand = (TypeSourceInfo*)nullptr; |
| } |
| |
| bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } |
| |
| /// \brief Retrieves the type operand of this __uuidof() expression after |
| /// various required adjustments (removing reference types, cv-qualifiers). |
| QualType getTypeOperand(ASTContext &Context) const; |
| |
| /// \brief Retrieve source information for the type operand. |
| TypeSourceInfo *getTypeOperandSourceInfo() const { |
| assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); |
| return Operand.get<TypeSourceInfo *>(); |
| } |
| |
| void setTypeOperandSourceInfo(TypeSourceInfo *TSI) { |
| assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); |
| Operand = TSI; |
| } |
| |
| Expr *getExprOperand() const { |
| assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)"); |
| return static_cast<Expr*>(Operand.get<Stmt *>()); |
| } |
| |
| void setExprOperand(Expr *E) { |
| assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)"); |
| Operand = E; |
| } |
| |
| 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(); } |
| SourceRange getSourceRange() const LLVM_READONLY { return Range; } |
| void setSourceRange(SourceRange R) { Range = R; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXUuidofExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| if (isTypeOperand()) |
| return child_range(child_iterator(), child_iterator()); |
| Stmt **begin = reinterpret_cast<Stmt**>(&Operand); |
| return child_range(begin, begin + 1); |
| } |
| }; |
| |
| /// \brief Represents the \c this expression in C++. |
| /// |
| /// This is a pointer to the object on which the current member function is |
| /// executing (C++ [expr.prim]p3). Example: |
| /// |
| /// \code |
| /// class Foo { |
| /// public: |
| /// void bar(); |
| /// void test() { this->bar(); } |
| /// }; |
| /// \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, |
| // '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) { } |
| |
| CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} |
| |
| SourceLocation getLocation() const { return Loc; } |
| void setLocation(SourceLocation L) { Loc = L; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Loc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } |
| |
| bool isImplicit() const { return Implicit; } |
| void setImplicit(bool I) { Implicit = I; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXThisExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| }; |
| |
| /// \brief A C++ throw-expression (C++ [except.throw]). |
| /// |
| /// This handles 'throw' (for re-throwing the current exception) and |
| /// 'throw' assignment-expression. When assignment-expression isn't |
| /// present, Op will be null. |
| class CXXThrowExpr : public Expr { |
| Stmt *Op; |
| SourceLocation ThrowLoc; |
| /// \brief Whether the thrown variable (if any) is in scope. |
| unsigned IsThrownVariableInScope : 1; |
| |
| friend class ASTStmtReader; |
| |
| 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, |
| bool IsThrownVariableInScope) : |
| Expr(CXXThrowExprClass, Ty, VK_RValue, OK_Ordinary, false, false, |
| expr && expr->isInstantiationDependent(), |
| expr && expr->containsUnexpandedParameterPack()), |
| Op(expr), ThrowLoc(l), 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); } |
| |
| SourceLocation getThrowLoc() const { return ThrowLoc; } |
| |
| /// \brief 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; } |
| SourceLocation getLocEnd() const LLVM_READONLY { |
| if (!getSubExpr()) |
| return ThrowLoc; |
| return getSubExpr()->getLocEnd(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXThrowExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(&Op, Op ? &Op+1 : &Op); |
| } |
| }; |
| |
| /// \brief A default argument (C++ [dcl.fct.default]). |
| /// |
| /// This wraps up a function call argument that was created from the |
| /// corresponding parameter's default argument, when the call did not |
| /// explicitly supply arguments for all of the parameters. |
| class CXXDefaultArgExpr final : public Expr { |
| /// \brief The parameter whose default is being used. |
| ParmVarDecl *Param; |
| |
| /// \brief The location where the default argument expression was used. |
| SourceLocation Loc; |
| |
| 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, false), |
| Param(param), Loc(Loc) { } |
| |
| public: |
| CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} |
| |
| // \p Param is the parameter whose default argument is used by this |
| // expression. |
| static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc, |
| ParmVarDecl *Param) { |
| return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param); |
| } |
| |
| // Retrieve the parameter that the argument was created from. |
| const ParmVarDecl *getParam() const { return Param; } |
| ParmVarDecl *getParam() { return Param; } |
| |
| // Retrieve the actual argument to the function call. |
| const Expr *getExpr() const { |
| return getParam()->getDefaultArg(); |
| } |
| Expr *getExpr() { |
| return getParam()->getDefaultArg(); |
| } |
| |
| /// \brief Retrieve the location where this default argument was actually |
| /// used. |
| SourceLocation getUsedLocation() const { return 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 getExprLoc() const LLVM_READONLY { return Loc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXDefaultArgExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| }; |
| |
| /// \brief A use of a default initializer in a constructor or in aggregate |
| /// initialization. |
| /// |
| /// This wraps a use of a C++ default initializer (technically, |
| /// a brace-or-equal-initializer for a non-static data member) when it |
| /// is implicitly used in a mem-initializer-list in a constructor |
| /// (C++11 [class.base.init]p8) or in aggregate initialization |
| /// (C++1y [dcl.init.aggr]p7). |
| class CXXDefaultInitExpr : public Expr { |
| /// \brief The field whose default is being used. |
| FieldDecl *Field; |
| |
| /// \brief The location where the default initializer expression was used. |
| SourceLocation Loc; |
| |
| CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field, |
| QualType T); |
| |
| CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {} |
| |
| public: |
| /// \p Field is the non-static data member whose default initializer is used |
| /// by this expression. |
| static CXXDefaultInitExpr *Create(const ASTContext &C, SourceLocation Loc, |
| FieldDecl *Field) { |
| return new (C) CXXDefaultInitExpr(C, Loc, Field, Field->getType()); |
| } |
| |
| /// \brief Get the field whose initializer will be used. |
| FieldDecl *getField() { return Field; } |
| const FieldDecl *getField() const { return Field; } |
| |
| /// \brief Get the initialization expression that will be used. |
| const Expr *getExpr() const { |
| assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); |
| return Field->getInClassInitializer(); |
| } |
| Expr *getExpr() { |
| assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); |
| return Field->getInClassInitializer(); |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Loc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXDefaultInitExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| friend class ASTReader; |
| friend class ASTStmtReader; |
| }; |
| |
| /// \brief Represents a C++ temporary. |
| class CXXTemporary { |
| /// \brief The destructor that needs to be called. |
| const CXXDestructorDecl *Destructor; |
| |
| explicit CXXTemporary(const CXXDestructorDecl *destructor) |
| : Destructor(destructor) { } |
| |
| public: |
| static CXXTemporary *Create(const ASTContext &C, |
| const CXXDestructorDecl *Destructor); |
| |
| const CXXDestructorDecl *getDestructor() const { return Destructor; } |
| void setDestructor(const CXXDestructorDecl *Dtor) { |
| Destructor = Dtor; |
| } |
| }; |
| |
| /// \brief Represents binding an expression to a temporary. |
| /// |
| /// This ensures the destructor is called for the temporary. It should only be |
| /// needed for non-POD, non-trivially destructable class types. For example: |
| /// |
| /// \code |
| /// struct S { |
| /// S() { } // User defined constructor makes S non-POD. |
| /// ~S() { } // User defined destructor makes it non-trivial. |
| /// }; |
| /// void test() { |
| /// const S &s_ref = S(); // Requires a CXXBindTemporaryExpr. |
| /// } |
| /// \endcode |
| class CXXBindTemporaryExpr : public Expr { |
| CXXTemporary *Temp; |
| |
| Stmt *SubExpr; |
| |
| CXXBindTemporaryExpr(CXXTemporary *temp, Expr* SubExpr) |
| : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), |
| VK_RValue, OK_Ordinary, SubExpr->isTypeDependent(), |
| SubExpr->isValueDependent(), |
| SubExpr->isInstantiationDependent(), |
| SubExpr->containsUnexpandedParameterPack()), |
| Temp(temp), SubExpr(SubExpr) { } |
| |
| public: |
| CXXBindTemporaryExpr(EmptyShell Empty) |
| : Expr(CXXBindTemporaryExprClass, Empty), Temp(nullptr), SubExpr(nullptr) {} |
| |
| static CXXBindTemporaryExpr *Create(const ASTContext &C, CXXTemporary *Temp, |
| Expr* SubExpr); |
| |
| CXXTemporary *getTemporary() { return Temp; } |
| const CXXTemporary *getTemporary() const { return Temp; } |
| void setTemporary(CXXTemporary *T) { Temp = T; } |
| |
| const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } |
| Expr *getSubExpr() { return cast<Expr>(SubExpr); } |
| void setSubExpr(Expr *E) { SubExpr = E; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { |
| return SubExpr->getLocStart(); |
| } |
| SourceLocation getLocEnd() const LLVM_READONLY { return SubExpr->getLocEnd();} |
| |
| // Implement isa/cast/dyncast/etc. |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXBindTemporaryExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&SubExpr, &SubExpr + 1); } |
| }; |
| |
| /// \brief Represents a call to a C++ constructor. |
| class CXXConstructExpr : public Expr { |
| public: |
| enum ConstructionKind { |
| CK_Complete, |
| CK_NonVirtualBase, |
| CK_VirtualBase, |
| CK_Delegating |
| }; |
| |
| private: |
| CXXConstructorDecl *Constructor; |
| |
| SourceLocation Loc; |
| 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; |
| |
| void setConstructor(CXXConstructorDecl *C) { Constructor = C; } |
| |
| 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, |
| SourceRange ParenOrBraceRange); |
| |
| /// \brief Construct an empty C++ construction expression. |
| CXXConstructExpr(StmtClass SC, EmptyShell Empty) |
| : Expr(SC, Empty), Constructor(nullptr), NumArgs(0), Elidable(false), |
| HadMultipleCandidates(false), ListInitialization(false), |
| ZeroInitialization(false), ConstructKind(0), Args(nullptr) |
| { } |
| |
| public: |
| /// \brief Construct an empty C++ construction expression. |
| explicit CXXConstructExpr(EmptyShell Empty) |
| : CXXConstructExpr(CXXConstructExprClass, Empty) {} |
| |
| 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); |
| |
| /// \brief 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; } |
| |
| /// \brief Whether this construction is elidable. |
| bool isElidable() const { return Elidable; } |
| void setElidable(bool E) { Elidable = E; } |
| |
| /// \brief 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; } |
| |
| /// \brief Whether this constructor call was written as list-initialization. |
| 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; } |
| void setRequiresZeroInitialization(bool ZeroInit) { |
| ZeroInitialization = ZeroInit; |
| } |
| |
| /// \brief Determine whether this constructor is actually constructing |
| /// a base class (rather than a complete object). |
| ConstructionKind getConstructionKind() const { |
| return (ConstructionKind)ConstructKind; |
| } |
| void setConstructionKind(ConstructionKind CK) { |
| ConstructKind = CK; |
| } |
| |
| typedef ExprIterator arg_iterator; |
| typedef ConstExprIterator const_arg_iterator; |
| typedef llvm::iterator_range<arg_iterator> arg_range; |
| typedef llvm::iterator_range<const_arg_iterator> arg_const_range; |
| |
| arg_range arguments() { return arg_range(arg_begin(), arg_end()); } |
| arg_const_range arguments() const { |
| return arg_const_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; } |
| |
| 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. |
| Expr *getArg(unsigned Arg) { |
| assert(Arg < NumArgs && "Arg access out of range!"); |
| return cast<Expr>(Args[Arg]); |
| } |
| const Expr *getArg(unsigned Arg) const { |
| assert(Arg < NumArgs && "Arg access out of range!"); |
| return cast<Expr>(Args[Arg]); |
| } |
| |
| /// \brief Set the specified argument. |
| void setArg(unsigned Arg, Expr *ArgExpr) { |
| assert(Arg < NumArgs && "Arg access out of range!"); |
| Args[Arg] = ArgExpr; |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY; |
| SourceLocation getLocEnd() 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; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(&Args[0], &Args[0]+NumArgs); |
| } |
| |
| friend class ASTStmtReader; |
| }; |
| |
| /// \brief Represents a call to an inherited base class constructor from an |
| /// inheriting constructor. This call implicitly forwards the arguments from |
| /// the enclosing context (an inheriting constructor) to the specified inherited |
| /// base class constructor. |
| class CXXInheritedCtorInitExpr : public Expr { |
| private: |
| CXXConstructorDecl *Constructor; |
| |
| /// The location of the using declaration. |
| SourceLocation Loc; |
| |
| /// Whether this is the construction of a virtual base. |
| unsigned ConstructsVirtualBase : 1; |
| |
| /// Whether the constructor is inherited from a virtual base class of the |
| /// class that we construct. |
| unsigned InheritedFromVirtualBase : 1; |
| |
| public: |
| /// \brief Construct a C++ inheriting construction expression. |
| CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T, |
| CXXConstructorDecl *Ctor, bool ConstructsVirtualBase, |
| bool InheritedFromVirtualBase) |
| : Expr(CXXInheritedCtorInitExprClass, T, VK_RValue, OK_Ordinary, false, |
| false, false, false), |
| Constructor(Ctor), Loc(Loc), |
| ConstructsVirtualBase(ConstructsVirtualBase), |
| InheritedFromVirtualBase(InheritedFromVirtualBase) { |
| assert(!T->isDependentType()); |
| } |
| |
| /// \brief Construct an empty C++ inheriting construction expression. |
| explicit CXXInheritedCtorInitExpr(EmptyShell Empty) |
| : Expr(CXXInheritedCtorInitExprClass, Empty), Constructor(nullptr), |
| ConstructsVirtualBase(false), InheritedFromVirtualBase(false) {} |
| |
| /// \brief Get the constructor that this expression will call. |
| CXXConstructorDecl *getConstructor() const { return Constructor; } |
| |
| /// \brief Determine whether this constructor is actually constructing |
| /// a base class (rather than a complete object). |
| bool constructsVBase() const { return ConstructsVirtualBase; } |
| CXXConstructExpr::ConstructionKind getConstructionKind() const { |
| return ConstructsVirtualBase ? CXXConstructExpr::CK_VirtualBase |
| : CXXConstructExpr::CK_NonVirtualBase; |
| } |
| |
| /// \brief Determine whether the inherited constructor is inherited from a |
| /// virtual base of the object we construct. If so, we are not responsible |
| /// for calling the inherited constructor (the complete object constructor |
| /// does that), and so we don't need to pass any arguments. |
| 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; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXInheritedCtorInitExprClass; |
| } |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| friend class ASTStmtReader; |
| }; |
| |
| /// \brief Represents an explicit C++ type conversion that uses "functional" |
| /// notation (C++ [expr.type.conv]). |
| /// |
| /// Example: |
| /// \code |
| /// x = int(0.5); |
| /// \endcode |
| class CXXFunctionalCastExpr final |
| : public ExplicitCastExpr, |
| private llvm::TrailingObjects<CXXFunctionalCastExpr, CXXBaseSpecifier *> { |
| SourceLocation LParenLoc; |
| SourceLocation RParenLoc; |
| |
| CXXFunctionalCastExpr(QualType ty, ExprValueKind VK, |
| TypeSourceInfo *writtenTy, |
| CastKind kind, Expr *castExpr, unsigned pathSize, |
| SourceLocation lParenLoc, SourceLocation rParenLoc) |
| : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, |
| castExpr, pathSize, writtenTy), |
| LParenLoc(lParenLoc), RParenLoc(rParenLoc) {} |
| |
| explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) |
| : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { } |
| |
| public: |
| static CXXFunctionalCastExpr *Create(const ASTContext &Context, QualType T, |
| ExprValueKind VK, |
| TypeSourceInfo *Written, |
| CastKind Kind, Expr *Op, |
| const CXXCastPath *Path, |
| SourceLocation LPLoc, |
| SourceLocation RPLoc); |
| static CXXFunctionalCastExpr *CreateEmpty(const ASTContext &Context, |
| unsigned PathSize); |
| |
| SourceLocation getLParenLoc() const { return LParenLoc; } |
| void setLParenLoc(SourceLocation L) { LParenLoc = L; } |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY; |
| SourceLocation getLocEnd() const LLVM_READONLY; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXFunctionalCastExprClass; |
| } |
| |
| friend TrailingObjects; |
| friend class CastExpr; |
| }; |
| |
| /// @brief Represents a C++ functional cast expression that builds a |
| /// temporary object. |
| /// |
| /// This expression type represents a C++ "functional" cast |
| /// (C++[expr.type.conv]) with N != 1 arguments that invokes a |
| /// constructor to build a temporary object. With N == 1 arguments the |
| /// functional cast expression will be represented by CXXFunctionalCastExpr. |
| /// Example: |
| /// \code |
| /// struct X { X(int, float); } |
| /// |
| /// X create_X() { |
| /// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr |
| /// }; |
| /// \endcode |
| class CXXTemporaryObjectExpr : public CXXConstructExpr { |
| TypeSourceInfo *Type; |
| |
| public: |
| CXXTemporaryObjectExpr(const ASTContext &C, |
| CXXConstructorDecl *Cons, |
| TypeSourceInfo *Type, |
| ArrayRef<Expr *> Args, |
| SourceRange ParenOrBraceRange, |
| bool HadMultipleCandidates, |
| bool ListInitialization, |
| bool StdInitListInitialization, |
| bool ZeroInitialization); |
| explicit CXXTemporaryObjectExpr(EmptyShell Empty) |
| : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } |
| |
| TypeSourceInfo *getTypeSourceInfo() const { return Type; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY; |
| SourceLocation getLocEnd() const LLVM_READONLY; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXTemporaryObjectExprClass; |
| } |
| |
| friend class ASTStmtReader; |
| }; |
| |
| /// \brief A C++ lambda expression, which produces a function object |
| /// (of unspecified type) that can be invoked later. |
| /// |
| /// Example: |
| /// \code |
| /// void low_pass_filter(std::vector<double> &values, double cutoff) { |
| /// values.erase(std::remove_if(values.begin(), values.end(), |
| /// [=](double value) { return value > cutoff; }); |
| /// } |
| /// \endcode |
| /// |
| /// C++11 lambda expressions can capture local variables, either by copying |
| /// the values of those local variables at the time the function |
| /// object is constructed (not when it is called!) or by holding a |
| /// reference to the local variable. These captures can occur either |
| /// implicitly or can be written explicitly between the square |
| /// brackets ([...]) that start the lambda expression. |
| /// |
| /// C++1y introduces a new form of "capture" called an init-capture that |
| /// includes an initializing expression (rather than capturing a variable), |
| /// and which can never occur implicitly. |
| class LambdaExpr final |
| : public Expr, |
| private llvm::TrailingObjects<LambdaExpr, Stmt *, unsigned, VarDecl *> { |
| /// \brief The source range that covers the lambda introducer ([...]). |
| SourceRange IntroducerRange; |
| |
| /// \brief The source location of this lambda's capture-default ('=' or '&'). |
| SourceLocation CaptureDefaultLoc; |
| |
| /// \brief The number of captures. |
| unsigned NumCaptures : 16; |
| |
| /// \brief The default capture kind, which is a value of type |
| /// LambdaCaptureDefault. |
| unsigned CaptureDefault : 2; |
| |
| /// \brief Whether this lambda had an explicit parameter list vs. an |
| /// implicit (and empty) parameter list. |
| unsigned ExplicitParams : 1; |
| |
| /// \brief Whether this lambda had the result type explicitly specified. |
| unsigned ExplicitResultType : 1; |
| |
| /// \brief Whether there are any array index variables stored at the end of |
| /// this lambda expression. |
| unsigned HasArrayIndexVars : 1; |
| |
| /// \brief The location of the closing brace ('}') that completes |
| /// the lambda. |
| /// |
| /// The location of the brace is also available by looking up the |
| /// function call operator in the lambda class. However, it is |
| /// stored here to improve the performance of getSourceRange(), and |
| /// to avoid having to deserialize the function call operator from a |
| /// module file just to determine the source range. |
| SourceLocation ClosingBrace; |
| |
| size_t numTrailingObjects(OverloadToken<Stmt *>) const { |
| return NumCaptures + 1; |
| } |
| |
| size_t numTrailingObjects(OverloadToken<unsigned>) const { |
| return HasArrayIndexVars ? NumCaptures + 1 : 0; |
| } |
| |
| /// \brief Construct a lambda expression. |
| LambdaExpr(QualType T, SourceRange IntroducerRange, |
| LambdaCaptureDefault CaptureDefault, |
| SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, |
| bool ExplicitParams, bool ExplicitResultType, |
| ArrayRef<Expr *> CaptureInits, ArrayRef<VarDecl *> ArrayIndexVars, |
| ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, |
| bool ContainsUnexpandedParameterPack); |
| |
| /// \brief Construct an empty lambda expression. |
| LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars) |
| : Expr(LambdaExprClass, Empty), |
| NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false), |
| ExplicitResultType(false), HasArrayIndexVars(true) { |
| getStoredStmts()[NumCaptures] = nullptr; |
| } |
| |
| Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); } |
| |
| Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); } |
| |
| /// \brief Retrieve the mapping from captures to the first array index |
| /// variable. |
| unsigned *getArrayIndexStarts() { return getTrailingObjects<unsigned>(); } |
| |
| const unsigned *getArrayIndexStarts() const { |
| return getTrailingObjects<unsigned>(); |
| } |
| |
| /// \brief Retrieve the complete set of array-index variables. |
| VarDecl **getArrayIndexVars() { return getTrailingObjects<VarDecl *>(); } |
| |
| VarDecl *const *getArrayIndexVars() const { |
| return getTrailingObjects<VarDecl *>(); |
| } |
| |
| public: |
| /// \brief Construct a new lambda expression. |
| static LambdaExpr * |
| Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange, |
| LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, |
| ArrayRef<LambdaCapture> Captures, bool ExplicitParams, |
| bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, |
| ArrayRef<VarDecl *> ArrayIndexVars, |
| ArrayRef<unsigned> ArrayIndexStarts, SourceLocation ClosingBrace, |
| bool ContainsUnexpandedParameterPack); |
| |
| /// \brief Construct a new lambda expression that will be deserialized from |
| /// an external source. |
| static LambdaExpr *CreateDeserialized(const ASTContext &C, |
| unsigned NumCaptures, |
| unsigned NumArrayIndexVars); |
| |
| /// \brief Determine the default capture kind for this lambda. |
| LambdaCaptureDefault getCaptureDefault() const { |
| return static_cast<LambdaCaptureDefault>(CaptureDefault); |
| } |
| |
| /// \brief Retrieve the location of this lambda's capture-default, if any. |
| SourceLocation getCaptureDefaultLoc() const { |
| return CaptureDefaultLoc; |
| } |
| |
| /// \brief Determine whether one of this lambda's captures is an init-capture. |
| bool isInitCapture(const LambdaCapture *Capture) const; |
| |
| /// \brief An iterator that walks over the captures of the lambda, |
| /// both implicit and explicit. |
| typedef const LambdaCapture *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; |
| |
| /// \brief Retrieve an iterator pointing past the end of the |
| /// sequence of lambda captures. |
| capture_iterator capture_end() const; |
| |
| /// \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. |
| capture_iterator explicit_capture_begin() const; |
| |
| /// \brief Retrieve an iterator pointing past the end of the sequence of |
| /// 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; |
| |
| /// \brief Retrieve an iterator pointing past the end of the sequence of |
| /// implicit lambda captures. |
| capture_iterator implicit_capture_end() const; |
| |
| /// \brief Iterator that walks over the capture initialization |
| /// arguments. |
| typedef Expr **capture_init_iterator; |
| |
| /// \brief Const iterator that walks over the capture initialization |
| /// arguments. |
| typedef Expr *const *const_capture_init_iterator; |
| |
| /// \brief Retrieve the initialization expressions for this lambda's captures. |
| llvm::iterator_range<capture_init_iterator> capture_inits() { |
| return llvm::make_range(capture_init_begin(), capture_init_end()); |
| } |
| |
| /// \brief Retrieve the initialization expressions for this lambda's captures. |
| llvm::iterator_range<const_capture_init_iterator> capture_inits() const { |
| return llvm::make_range(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() { |
| return reinterpret_cast<Expr **>(getStoredStmts()); |
| } |
| |
| /// \brief Retrieve the first initialization argument for this |
| /// lambda expression (which initializes the first capture field). |
| const_capture_init_iterator capture_init_begin() const { |
| return reinterpret_cast<Expr *const *>(getStoredStmts()); |
| } |
| |
| /// \brief Retrieve the iterator pointing one past the last |
| /// initialization argument for this lambda expression. |
| capture_init_iterator capture_init_end() { |
| return capture_init_begin() + NumCaptures; |
| } |
| |
| /// \brief Retrieve the iterator pointing one past the last |
| /// initialization argument for this lambda expression. |
| const_capture_init_iterator capture_init_end() const { |
| return capture_init_begin() + NumCaptures; |
| } |
| |
| /// \brief Retrieve the set of index variables used in the capture |
| /// initializer of an array captured by copy. |
| /// |
| /// \param Iter The iterator that points at the capture initializer for |
| /// which we are extracting the corresponding index variables. |
| ArrayRef<VarDecl *> |
| getCaptureInitIndexVars(const_capture_init_iterator Iter) const; |
| |
| /// \brief Retrieve the source range covering the lambda introducer, |
| /// which contains the explicit capture list surrounded by square |
| /// brackets ([...]). |
| SourceRange getIntroducerRange() const { return IntroducerRange; } |
| |
| /// \brief Retrieve the class that corresponds to the lambda. |
| /// |
| /// This is the "closure type" (C++1y [expr.prim.lambda]), and stores the |
| /// captures in its fields and provides the various operations permitted |
| /// on a lambda (copying, calling). |
| CXXRecordDecl *getLambdaClass() const; |
| |
| /// \brief Retrieve the function call operator associated with this |
| /// lambda expression. |
| CXXMethodDecl *getCallOperator() const; |
| |
| /// \brief If this is a generic lambda expression, retrieve the template |
| /// parameter list associated with it, or else return null. |
| TemplateParameterList *getTemplateParameterList() const; |
| |
| /// \brief Whether this is a generic lambda. |
| bool isGenericLambda() const { return getTemplateParameterList(); } |
| |
| /// \brief Retrieve the body of the lambda. |
| CompoundStmt *getBody() const; |
| |
| /// \brief Determine whether the lambda is mutable, meaning that any |
| /// captures values can be modified. |
| bool isMutable() const; |
| |
| /// \brief Determine whether this lambda has an explicit parameter |
| /// list vs. an implicit (empty) parameter list. |
| bool hasExplicitParameters() const { return ExplicitParams; } |
| |
| /// \brief Whether this lambda had its result type explicitly specified. |
| bool hasExplicitResultType() const { return ExplicitResultType; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == LambdaExprClass; |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { |
| return IntroducerRange.getBegin(); |
| } |
| SourceLocation getLocEnd() const LLVM_READONLY { return ClosingBrace; } |
| |
| child_range children() { |
| // Includes initialization exprs plus body stmt |
| return child_range(getStoredStmts(), getStoredStmts() + NumCaptures + 1); |
| } |
| |
| friend TrailingObjects; |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| }; |
| |
| /// An expression "T()" which creates a value-initialized rvalue of type |
| /// T, which is a non-class type. See (C++98 [5.2.3p2]). |
| class CXXScalarValueInitExpr : public Expr { |
| SourceLocation RParenLoc; |
| TypeSourceInfo *TypeInfo; |
| |
| friend class ASTStmtReader; |
| |
| public: |
| /// \brief 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(), |
| Type->containsUnexpandedParameterPack()), |
| RParenLoc(rParenLoc), TypeInfo(TypeInfo) {} |
| |
| explicit CXXScalarValueInitExpr(EmptyShell Shell) |
| : Expr(CXXScalarValueInitExprClass, Shell) { } |
| |
| TypeSourceInfo *getTypeSourceInfo() const { |
| return TypeInfo; |
| } |
| |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY; |
| SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXScalarValueInitExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| }; |
| |
| /// \brief Represents a new-expression for memory allocation and constructor |
| /// calls, e.g: "new CXXNewExpr(foo)". |
| class CXXNewExpr : public Expr { |
| /// Contains an optional array size expression, an optional initialization |
| /// expression, and any number of optional placement arguments, in that order. |
| Stmt **SubExprs; |
| /// \brief Points to the allocation function used. |
| FunctionDecl *OperatorNew; |
| /// \brief Points to the deallocation function used in case of error. May be |
| /// null. |
| FunctionDecl *OperatorDelete; |
| |
| /// \brief The allocated type-source information, as written in the source. |
| TypeSourceInfo *AllocatedTypeInfo; |
| |
| /// \brief If the allocated type was expressed as a parenthesized type-id, |
| /// the source range covering the parenthesized type-id. |
| SourceRange TypeIdParens; |
| |
| /// \brief Range of the entire new expression. |
| SourceRange Range; |
| |
| /// \brief 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; |
| /// If this is an array allocation, does the usual deallocation |
| /// function for the allocated type want to know the allocated size? |
| unsigned UsualArrayDeleteWantsSize : 1; |
| /// The number of placement new arguments. |
| unsigned NumPlacementArgs : 13; |
| /// 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; |
| |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| public: |
| enum InitializationStyle { |
| NoInit, ///< New-expression has no initializer as written. |
| CallInit, ///< New-expression has a C++98 paren-delimited initializer. |
| ListInit ///< New-expression has a C++11 list-initializer. |
| }; |
| |
| CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew, |
| FunctionDecl *operatorDelete, 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), SubExprs(nullptr) { } |
| |
| void AllocateArgsArray(const ASTContext &C, bool isArray, |
| unsigned numPlaceArgs, bool hasInitializer); |
| |
| QualType getAllocatedType() const { |
| assert(getType()->isPointerType()); |
| return getType()->getAs<PointerType>()->getPointeeType(); |
| } |
| |
| TypeSourceInfo *getAllocatedTypeSourceInfo() const { |
| return AllocatedTypeInfo; |
| } |
| |
| /// \brief True if the allocation result needs to be null-checked. |
| /// |
| /// C++11 [expr.new]p13: |
| /// If the allocation function returns null, initialization shall |
| /// not be done, the deallocation function shall not be called, |
| /// and the value of the new-expression shall be null. |
| /// |
| /// C++ DR1748: |
| /// If the allocation function is a reserved placement allocation |
| /// function that returns null, the behavior is undefined. |
| /// |
| /// An allocation function is not allowed to return null unless it |
| /// 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; |
| |
| 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; } |
| Expr *getArraySize() { |
| return Array ? cast<Expr>(SubExprs[0]) : nullptr; |
| } |
| const Expr *getArraySize() const { |
| return Array ? cast<Expr>(SubExprs[0]) : nullptr; |
| } |
| |
| unsigned getNumPlacementArgs() const { return NumPlacementArgs; } |
| Expr **getPlacementArgs() { |
| return reinterpret_cast<Expr **>(SubExprs + Array + hasInitializer()); |
| } |
| |
| Expr *getPlacementArg(unsigned i) { |
| assert(i < NumPlacementArgs && "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); |
| } |
| |
| bool isParenTypeId() const { return TypeIdParens.isValid(); } |
| SourceRange getTypeIdParens() const { return TypeIdParens; } |
| |
| bool isGlobalNew() const { return GlobalNew; } |
| |
| /// \brief Whether this new-expression has any initializer at all. |
| bool hasInitializer() const { return StoredInitializationStyle > 0; } |
| |
| /// \brief The kind of initializer this new-expression has. |
| InitializationStyle getInitializationStyle() const { |
| if (StoredInitializationStyle == 0) |
| return NoInit; |
| return static_cast<InitializationStyle>(StoredInitializationStyle-1); |
| } |
| |
| /// \brief The initializer of this new-expression. |
| Expr *getInitializer() { |
| return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; |
| } |
| const Expr *getInitializer() const { |
| return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; |
| } |
| |
| /// \brief Returns the CXXConstructExpr from this new-expression, or null. |
| const CXXConstructExpr* getConstructExpr() const { |
| return dyn_cast_or_null<CXXConstructExpr>(getInitializer()); |
| } |
| |
| /// 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; |
| } |
| |
| typedef ExprIterator arg_iterator; |
| typedef ConstExprIterator const_arg_iterator; |
| |
| llvm::iterator_range<arg_iterator> placement_arguments() { |
| return llvm::make_range(placement_arg_begin(), placement_arg_end()); |
| } |
| |
| llvm::iterator_range<const_arg_iterator> placement_arguments() const { |
| return llvm::make_range(placement_arg_begin(), placement_arg_end()); |
| } |
| |
| arg_iterator placement_arg_begin() { |
| return SubExprs + Array + hasInitializer(); |
| } |
| arg_iterator placement_arg_end() { |
| return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); |
| } |
| const_arg_iterator placement_arg_begin() const { |
| return SubExprs + Array + hasInitializer(); |
| } |
| const_arg_iterator placement_arg_end() const { |
| return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); |
| } |
| |
| typedef Stmt **raw_arg_iterator; |
| raw_arg_iterator raw_arg_begin() { return SubExprs; } |
| raw_arg_iterator raw_arg_end() { |
| return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); |
| } |
| const_arg_iterator raw_arg_begin() const { return SubExprs; } |
| const_arg_iterator raw_arg_end() const { |
| return SubExprs + Array + hasInitializer() + getNumPlacementArgs(); |
| } |
| |
| SourceLocation getStartLoc() 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(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXNewExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(raw_arg_begin(), raw_arg_end()); |
| } |
| }; |
| |
| /// \brief Represents a \c delete expression for memory deallocation and |
| /// destructor calls, e.g. "delete[] pArray". |
| class CXXDeleteExpr : public Expr { |
| /// Points to the operator delete overload that is used. Could be a member. |
| FunctionDecl *OperatorDelete; |
| /// The pointer expression to be deleted. |
| Stmt *Argument; |
| /// 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: |
| 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), OperatorDelete(nullptr), |
| Argument(nullptr) {} |
| |
| bool isGlobalDelete() const { return GlobalDelete; } |
| bool isArrayForm() const { return ArrayForm; } |
| bool isArrayFormAsWritten() const { return 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; |
| } |
| |
| FunctionDecl *getOperatorDelete() const { return OperatorDelete; } |
| |
| Expr *getArgument() { return cast<Expr>(Argument); } |
| const Expr *getArgument() const { return cast<Expr>(Argument); } |
| |
| /// \brief Retrieve the type being destroyed. |
| /// |
| /// If the type being destroyed is a dependent type which may or may not |
| /// 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();} |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXDeleteExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Argument, &Argument+1); } |
| |
| friend class ASTStmtReader; |
| }; |
| |
| /// \brief Stores the type being destroyed by a pseudo-destructor expression. |
| class PseudoDestructorTypeStorage { |
| /// \brief Either the type source information or the name of the type, if |
| /// it couldn't be resolved due to type-dependence. |
| llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type; |
| |
| /// \brief The starting source location of the pseudo-destructor type. |
| SourceLocation Location; |
| |
| public: |
| PseudoDestructorTypeStorage() { } |
| |
| PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc) |
| : Type(II), Location(Loc) { } |
| |
| PseudoDestructorTypeStorage(TypeSourceInfo *Info); |
| |
| TypeSourceInfo *getTypeSourceInfo() const { |
| return Type.dyn_cast<TypeSourceInfo *>(); |
| } |
| |
| IdentifierInfo *getIdentifier() const { |
| return Type.dyn_cast<IdentifierInfo *>(); |
| } |
| |
| SourceLocation getLocation() const { return Location; } |
| }; |
| |
| /// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]). |
| /// |
| /// A pseudo-destructor is an expression that looks like a member access to a |
| /// destructor of a scalar type, except that scalar types don't have |
| /// destructors. For example: |
| /// |
| /// \code |
| /// typedef int T; |
| /// void f(int *p) { |
| /// p->T::~T(); |
| /// } |
| /// \endcode |
| /// |
| /// Pseudo-destructors typically occur when instantiating templates such as: |
| /// |
| /// \code |
| /// template<typename T> |
| /// void destroy(T* ptr) { |
| /// ptr->T::~T(); |
| /// } |
| /// \endcode |
| /// |
| /// for scalar types. A pseudo-destructor expression has no run-time semantics |
| /// beyond evaluating the base expression. |
| class CXXPseudoDestructorExpr : public Expr { |
| /// \brief The base expression (that is being destroyed). |
| Stmt *Base; |
| |
| /// \brief Whether the operator was an arrow ('->'); otherwise, it was a |
| /// period ('.'). |
| bool IsArrow : 1; |
| |
| /// \brief The location of the '.' or '->' operator. |
| SourceLocation OperatorLoc; |
| |
| /// \brief The nested-name-specifier that follows the operator, if present. |
| NestedNameSpecifierLoc QualifierLoc; |
| |
| /// \brief The type that precedes the '::' in a qualified pseudo-destructor |
| /// expression. |
| TypeSourceInfo *ScopeType; |
| |
| /// \brief The location of the '::' in a qualified pseudo-destructor |
| /// expression. |
| SourceLocation ColonColonLoc; |
| |
| /// \brief The location of the '~'. |
| SourceLocation TildeLoc; |
| |
| /// \brief The type being destroyed, or its name if we were unable to |
| /// resolve the name. |
| PseudoDestructorTypeStorage DestroyedType; |
| |
| friend class ASTStmtReader; |
| |
| public: |
| CXXPseudoDestructorExpr(const ASTContext &Context, |
| Expr *Base, bool isArrow, SourceLocation OperatorLoc, |
| NestedNameSpecifierLoc QualifierLoc, |
| TypeSourceInfo *ScopeType, |
| SourceLocation ColonColonLoc, |
| SourceLocation TildeLoc, |
| PseudoDestructorTypeStorage DestroyedType); |
| |
| explicit CXXPseudoDestructorExpr(EmptyShell Shell) |
| : Expr(CXXPseudoDestructorExprClass, Shell), |
| Base(nullptr), IsArrow(false), QualifierLoc(), ScopeType(nullptr) { } |
| |
| Expr *getBase() const { return cast<Expr>(Base); } |
| |
| /// \brief Determines whether this member expression actually had |
| /// a C++ nested-name-specifier prior to the name of the member, e.g., |
| /// x->Base::foo. |
| bool hasQualifier() const { return QualifierLoc.hasQualifier(); } |
| |
| /// \brief Retrieves the nested-name-specifier that qualifies the type name, |
| /// with source-location information. |
| NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } |
| |
| /// \brief If the member name was qualified, retrieves the |
| /// nested-name-specifier that precedes the member name. Otherwise, returns |
| /// null. |
| NestedNameSpecifier *getQualifier() const { |
| return QualifierLoc.getNestedNameSpecifier(); |
| } |
| |
| /// \brief Determine whether this pseudo-destructor expression was written |
| /// using an '->' (otherwise, it used a '.'). |
| bool isArrow() const { return IsArrow; } |
| |
| /// \brief Retrieve the location of the '.' or '->' operator. |
| SourceLocation getOperatorLoc() const { return OperatorLoc; } |
| |
| /// \brief Retrieve the scope type in a qualified pseudo-destructor |
| /// expression. |
| /// |
| /// Pseudo-destructor expressions can have extra qualification within them |
| /// that is not part of the nested-name-specifier, e.g., \c p->T::~T(). |
| /// Here, if the object type of the expression is (or may be) a scalar type, |
| /// \p T may also be a scalar type and, therefore, cannot be part of a |
| /// nested-name-specifier. It is stored as the "scope type" of the pseudo- |
| /// destructor expression. |
| TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; } |
| |
| /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor |
| /// expression. |
| SourceLocation getColonColonLoc() const { return ColonColonLoc; } |
| |
| /// \brief Retrieve the location of the '~'. |
| SourceLocation getTildeLoc() const { return TildeLoc; } |
| |
| /// \brief Retrieve the source location information for the type |
| /// being destroyed. |
| /// |
| /// This type-source information is available for non-dependent |
| /// pseudo-destructor expressions and some dependent pseudo-destructor |
| /// expressions. Returns null if we only have the identifier for a |
| /// dependent pseudo-destructor expression. |
| TypeSourceInfo *getDestroyedTypeInfo() const { |
| return DestroyedType.getTypeSourceInfo(); |
| } |
| |
| /// \brief In a dependent pseudo-destructor expression for which we do not |
| /// have full type information on the destroyed type, provides the name |
| /// of the destroyed type. |
| IdentifierInfo *getDestroyedTypeIdentifier() const { |
| return DestroyedType.getIdentifier(); |
| } |
| |
| /// \brief Retrieve the type being destroyed. |
| QualType getDestroyedType() const; |
| |
| /// \brief Retrieve the starting location of the type being destroyed. |
| SourceLocation getDestroyedTypeLoc() const { |
| return DestroyedType.getLocation(); |
| } |
| |
| /// \brief Set the name of destroyed type for a dependent pseudo-destructor |
| /// expression. |
| void setDestroyedType(IdentifierInfo *II, SourceLocation Loc) { |
| DestroyedType = PseudoDestructorTypeStorage(II, Loc); |
| } |
| |
| /// \brief Set the destroyed type. |
| void setDestroyedType(TypeSourceInfo *Info) { |
| DestroyedType = PseudoDestructorTypeStorage(Info); |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY {return Base->getLocStart();} |
| SourceLocation getLocEnd() const LLVM_READONLY; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXPseudoDestructorExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Base, &Base + 1); } |
| }; |
| |
| /// \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 final |
| : public Expr, |
| private llvm::TrailingObjects<TypeTraitExpr, TypeSourceInfo *> { |
| /// \brief The location of the type trait keyword. |
| SourceLocation Loc; |
| |
| /// \brief The location of the closing parenthesis. |
| SourceLocation RParenLoc; |
| |
| // Note: The TypeSourceInfos for the arguments are allocated after the |
| // TypeTraitExpr. |
| |
| TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind, |
| ArrayRef<TypeSourceInfo *> Args, |
| SourceLocation RParenLoc, |
| bool Value); |
| |
| TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) { } |
| |
| size_t numTrailingObjects(OverloadToken<TypeSourceInfo *>) const { |
| return getNumArgs(); |
| } |
| |
| public: |
| /// \brief Create a new type trait expression. |
| static TypeTraitExpr *Create(const ASTContext &C, QualType T, |
| SourceLocation Loc, TypeTrait Kind, |
| ArrayRef<TypeSourceInfo *> Args, |
| SourceLocation RParenLoc, |
| bool Value); |
| |
| static TypeTraitExpr *CreateDeserialized(const ASTContext &C, |
| unsigned NumArgs); |
| |
| /// \brief Determine which type trait this expression uses. |
| TypeTrait getTrait() const { |
| return static_cast<TypeTrait>(TypeTraitExprBits.Kind); |
| } |
| |
| bool getValue() const { |
| assert(!isValueDependent()); |
| return TypeTraitExprBits.Value; |
| } |
| |
| /// \brief Determine the number of arguments to this type trait. |
| unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; } |
| |
| /// \brief Retrieve the Ith argument. |
| TypeSourceInfo *getArg(unsigned I) const { |
| assert(I < getNumArgs() && "Argument out-of-range"); |
| return getArgs()[I]; |
| } |
| |
| /// \brief Retrieve the argument types. |
| ArrayRef<TypeSourceInfo *> getArgs() const { |
| return llvm::makeArrayRef(getTrailingObjects<TypeSourceInfo *>(), |
| getNumArgs()); |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Loc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == TypeTraitExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| friend TrailingObjects; |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| }; |
| |
| /// \brief An Embarcadero array type trait, as used in the implementation of |
| /// __array_rank and __array_extent. |
| /// |
| /// Example: |
| /// \code |
| /// __array_rank(int[10][20]) == 2 |
| /// __array_extent(int, 1) == 20 |
| /// \endcode |
| class ArrayTypeTraitExpr : public Expr { |
| virtual void anchor(); |
| |
| /// \brief The trait. An ArrayTypeTrait enum in MSVC compat unsigned. |
| unsigned ATT : 2; |
| |
| /// \brief The value of the type trait. Unspecified if dependent. |
| uint64_t Value; |
| |
| /// \brief The array dimension being queried, or -1 if not used. |
| Expr *Dimension; |
| |
| /// \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: |
| ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att, |
| TypeSourceInfo *queried, uint64_t value, |
| Expr *dimension, SourceLocation rparen, QualType ty) |
| : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, |
| false, queried->getType()->isDependentType(), |
| (queried->getType()->isInstantiationDependentType() || |
| (dimension && dimension->isInstantiationDependent())), |
| queried->getType()->containsUnexpandedParameterPack()), |
| ATT(att), Value(value), Dimension(dimension), |
| Loc(loc), RParen(rparen), QueriedType(queried) { } |
| |
| |
| explicit ArrayTypeTraitExpr(EmptyShell Empty) |
| : Expr(ArrayTypeTraitExprClass, Empty), ATT(0), Value(false), |
| QueriedType() { } |
| |
| virtual ~ArrayTypeTraitExpr() { } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Loc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } |
| |
| ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); } |
| |
| QualType getQueriedType() const { return QueriedType->getType(); } |
| |
| TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; } |
| |
| uint64_t getValue() const { assert(!isTypeDependent()); return Value; } |
| |
| Expr *getDimensionExpression() const { return Dimension; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ArrayTypeTraitExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| friend class ASTStmtReader; |
| }; |
| |
| /// \brief An expression trait intrinsic. |
| /// |
| /// Example: |
| /// \code |
| /// __is_lvalue_expr(std::cout) == true |
| /// __is_lvalue_expr(1) == false |
| /// \endcode |
| class ExpressionTraitExpr : public Expr { |
| /// \brief The trait. A ExpressionTrait enum in MSVC compatible unsigned. |
| unsigned ET : 31; |
| /// \brief The value of the type trait. Unspecified if dependent. |
| unsigned Value : 1; |
| |
| /// \brief The location of the type trait keyword. |
| SourceLocation Loc; |
| |
| /// \brief The location of the closing paren. |
| SourceLocation RParen; |
| |
| /// \brief The expression being queried. |
| Expr* QueriedExpression; |
| public: |
| ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, |
| Expr *queried, bool value, |
| SourceLocation rparen, QualType resultType) |
| : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary, |
| false, // Not type-dependent |
| // Value-dependent if the argument is type-dependent. |
| queried->isTypeDependent(), |
| queried->isInstantiationDependent(), |
| queried->containsUnexpandedParameterPack()), |
| ET(et), Value(value), Loc(loc), RParen(rparen), |
| QueriedExpression(queried) { } |
| |
| explicit ExpressionTraitExpr(EmptyShell Empty) |
| : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false), |
| QueriedExpression() { } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Loc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return RParen; } |
| |
| ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); } |
| |
| Expr *getQueriedExpression() const { return QueriedExpression; } |
| |
| bool getValue() const { return Value; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ExpressionTraitExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| friend class ASTStmtReader; |
| }; |
| |
| |
| /// \brief A reference to an overloaded function set, either an |
| /// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr. |
| class OverloadExpr : public Expr { |
| /// \brief The common name of these declarations. |
| DeclarationNameInfo NameInfo; |
| |
| /// \brief 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; |
| unsigned NumResults; |
| |
| protected: |
| /// \brief Whether the name includes info for explicit template |
| /// keyword and arguments. |
| bool HasTemplateKWAndArgsInfo; |
| |
| /// \brief Return the optional template keyword and arguments info. |
| ASTTemplateKWAndArgsInfo * |
| getTrailingASTTemplateKWAndArgsInfo(); // defined far below. |
| |
| /// \brief Return the optional template keyword and arguments info. |
| const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const { |
| return const_cast<OverloadExpr *>(this) |
| ->getTrailingASTTemplateKWAndArgsInfo(); |
| } |
| |
| /// Return the optional template arguments. |
| TemplateArgumentLoc *getTrailingTemplateArgumentLoc(); // defined far below |
| |
| OverloadExpr(StmtClass K, const ASTContext &C, |
| NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, |
| const DeclarationNameInfo &NameInfo, |
| const TemplateArgumentListInfo *TemplateArgs, |
| UnresolvedSetIterator Begin, UnresolvedSetIterator End, |
| bool KnownDependent, |
| bool KnownInstantiationDependent, |
| bool KnownContainsUnexpandedParameterPack); |
| |
| OverloadExpr(StmtClass K, EmptyShell Empty) |
| : Expr(K, Empty), QualifierLoc(), Results(nullptr), NumResults(0), |
| HasTemplateKWAndArgsInfo(false) { } |
| |
| void initializeResults(const ASTContext &C, |
| UnresolvedSetIterator Begin, |
| UnresolvedSetIterator End); |
| |
| public: |
| struct FindResult { |
| OverloadExpr *Expression; |
| bool IsAddressOfOperand; |
| bool HasFormOfMemberPointer; |
| }; |
| |
| /// \brief Finds the overloaded expression in the given expression \p E of |
| /// OverloadTy. |
| /// |
| /// \return the expression (which must be there) and true if it has |
| /// the particular form of a member pointer expression |
| static FindResult find(Expr *E) { |
| assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload)); |
| |
| FindResult Result; |
| |
| E = E->IgnoreParens(); |
| if (isa<UnaryOperator>(E)) { |
| assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf); |
| E = cast<UnaryOperator>(E)->getSubExpr(); |
| OverloadExpr *Ovl = cast<OverloadExpr>(E->IgnoreParens()); |
| |
| Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier()); |
| Result.IsAddressOfOperand = true; |
| Result.Expression = Ovl; |
| } else { |
| Result.HasFormOfMemberPointer = false; |
| Result.IsAddressOfOperand = false; |
| Result.Expression = cast<OverloadExpr>(E); |
| } |
| |
| return Result; |
| } |
| |
| /// \brief Gets the naming class of this lookup, if any. |
| CXXRecordDecl *getNamingClass() const; |
| |
| typedef UnresolvedSetImpl::iterator decls_iterator; |
| decls_iterator decls_begin() const { return UnresolvedSetIterator(Results); } |
| decls_iterator decls_end() const { |
| return UnresolvedSetIterator(Results + NumResults); |
| } |
| llvm::iterator_range<decls_iterator> decls() const { |
| return llvm::make_range(decls_begin(), decls_end()); |
| } |
| |
| /// \brief Gets the number of declarations in the unresolved set. |
| unsigned getNumDecls() const { return NumResults; } |
| |
| /// \brief Gets the full name info. |
| const DeclarationNameInfo &getNameInfo() const { return NameInfo; } |
| |
| /// \brief Gets the name looked up. |
| DeclarationName getName() const { return NameInfo.getName(); } |
| |
| /// \brief Gets the location of the name. |
| SourceLocation getNameLoc() const { return NameInfo.getLoc(); } |
| |
| /// \brief Fetches the nested-name qualifier, if one was given. |
| NestedNameSpecifier *getQualifier() const { |
| return QualifierLoc.getNestedNameSpecifier(); |
| } |
| |
| /// \brief Fetches the nested-name qualifier with source-location |
| /// information, if one was given. |
| NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } |
| |
| /// \brief Retrieve the location of the template keyword preceding |
| /// this name, if any. |
| SourceLocation getTemplateKeywordLoc() const { |
| if (!HasTemplateKWAndArgsInfo) return SourceLocation(); |
| return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc; |
| } |
| |
| /// \brief 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(); |
| return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc; |
| } |
| |
| /// \brief 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(); |
| return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc; |
| } |
| |
| /// \brief Determines whether the name was preceded by the template keyword. |
| bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } |
| |
| /// \brief Determines whether this expression had explicit template arguments. |
| bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } |
| |
| TemplateArgumentLoc const *getTemplateArgs() const { |
| if (!hasExplicitTemplateArgs()) |
| return nullptr; |
| return const_cast<OverloadExpr *>(this)->getTrailingTemplateArgumentLoc(); |
| } |
| |
| unsigned getNumTemplateArgs() const { |
| if (!hasExplicitTemplateArgs()) |
| return 0; |
| |
| return getTrailingASTTemplateKWAndArgsInfo()->NumTemplateArgs; |
| } |
| |
| ArrayRef<TemplateArgumentLoc> template_arguments() const { |
| return {getTemplateArgs(), getNumTemplateArgs()}; |
| } |
| |
| /// \brief Copies the template arguments into the given structure. |
| void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { |
| if (hasExplicitTemplateArgs()) |
| getTrailingASTTemplateKWAndArgsInfo()->copyInto(getTemplateArgs(), List); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == UnresolvedLookupExprClass || |
| T->getStmtClass() == UnresolvedMemberExprClass; |
| } |
| |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| }; |
| |
| /// \brief A reference to a name which we were able to look up during |
| /// parsing but could not resolve to a specific declaration. |
| /// |
| /// This arises in several ways: |
| /// * we might be waiting for argument-dependent lookup; |
| /// * the name might resolve to an overloaded function; |
| /// and eventually: |
| /// * the lookup might have included a function template. |
| /// |
| /// These never include UnresolvedUsingValueDecls, which are always class |
| /// members and therefore appear only in UnresolvedMemberLookupExprs. |
| class UnresolvedLookupExpr final |
| : public OverloadExpr, |
| private llvm::TrailingObjects< |
| UnresolvedLookupExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { |
| /// True if these lookup results should be extended by |
| /// argument-dependent lookup if this is the operand of a function |
| /// call. |
| bool RequiresADL; |
| |
| /// True if these lookup results are overloaded. This is pretty |
| /// trivially rederivable if we urgently need to kill this field. |
| bool Overloaded; |
| |
| /// 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; |
| |
| size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { |
| return HasTemplateKWAndArgsInfo ? 1 : 0; |
| } |
| |
| UnresolvedLookupExpr(const ASTContext &C, |
| CXXRecordDecl *NamingClass, |
| NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, |
| 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) |
| {} |
| |
| UnresolvedLookupExpr(EmptyShell Empty) |
| : OverloadExpr(UnresolvedLookupExprClass, Empty), |
| RequiresADL(false), Overloaded(false), NamingClass(nullptr) |
| {} |
| |
| friend TrailingObjects; |
| friend class OverloadExpr; |
| friend class ASTStmtReader; |
| |
| 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); |
| } |
| |
| static UnresolvedLookupExpr *Create(const ASTContext &C, |
| CXXRecordDecl *NamingClass, |
| NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, |
| const DeclarationNameInfo &NameInfo, |
| bool ADL, |
| const TemplateArgumentListInfo *Args, |
| UnresolvedSetIterator Begin, |
| UnresolvedSetIterator End); |
| |
| static UnresolvedLookupExpr *CreateEmpty(const ASTContext &C, |
| bool HasTemplateKWAndArgsInfo, |
| unsigned NumTemplateArgs); |
| |
| /// True if this declaration should be extended by |
| /// argument-dependent lookup. |
| bool requiresADL() const { return RequiresADL; } |
| |
| /// True if this lookup is overloaded. |
| bool isOverloaded() const { return 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; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { |
| if (NestedNameSpecifierLoc l = getQualifierLoc()) |
| return l.getBeginLoc(); |
| return getNameInfo().getLocStart(); |
| } |
| SourceLocation getLocEnd() const LLVM_READONLY { |
| if (hasExplicitTemplateArgs()) |
| return getRAngleLoc(); |
| return getNameInfo().getLocEnd(); |
| } |
| |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == UnresolvedLookupExprClass; |
| } |
| }; |
| |
| /// \brief A qualified reference to a name whose declaration cannot |
| /// yet be resolved. |
| /// |
| /// DependentScopeDeclRefExpr is similar to DeclRefExpr in that |
| /// it expresses a reference to a declaration such as |
| /// X<T>::value. The difference, however, is that an |
| /// DependentScopeDeclRefExpr node is used only within C++ templates when |
| /// the qualification (e.g., X<T>::) refers to a dependent type. In |
| /// this case, X<T>::value cannot resolve to a declaration because the |
| /// declaration will differ from one instantiation of X<T> to the |
| /// next. Therefore, DependentScopeDeclRefExpr keeps track of the |
| /// qualifier (X<T>::) and the name of the entity being referenced |
| /// ("value"). Such expressions will instantiate to a DeclRefExpr once the |
| /// declaration can be found. |
| class DependentScopeDeclRefExpr final |
| : public Expr, |
| private llvm::TrailingObjects<DependentScopeDeclRefExpr, |
| ASTTemplateKWAndArgsInfo, |
| TemplateArgumentLoc> { |
| /// \brief The nested-name-specifier that qualifies this unresolved |
| /// declaration name. |
| NestedNameSpecifierLoc QualifierLoc; |
| |
| /// \brief The name of the entity we will be referencing. |
| DeclarationNameInfo NameInfo; |
| |
| /// \brief Whether the name includes info for explicit template |
| /// keyword and arguments. |
| bool HasTemplateKWAndArgsInfo; |
| |
| size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { |
| return HasTemplateKWAndArgsInfo ? 1 : 0; |
| } |
| |
| DependentScopeDeclRefExpr(QualType T, |
| NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, |
| const DeclarationNameInfo &NameInfo, |
| const TemplateArgumentListInfo *Args); |
| |
| public: |
| static DependentScopeDeclRefExpr *Create(const ASTContext &C, |
| NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, |
| const DeclarationNameInfo &NameInfo, |
| const TemplateArgumentListInfo *TemplateArgs); |
| |
| static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &C, |
| bool HasTemplateKWAndArgsInfo, |
| unsigned NumTemplateArgs); |
| |
| /// \brief Retrieve the name that this expression refers to. |
| const DeclarationNameInfo &getNameInfo() const { return NameInfo; } |
| |
| /// \brief Retrieve the name that this expression refers to. |
| DeclarationName getDeclName() const { return NameInfo.getName(); } |
| |
| /// \brief Retrieve the location of the name within the expression. |
| /// |
| /// For example, in "X<T>::value" this is the location of "value". |
| SourceLocation getLocation() const { return NameInfo.getLoc(); } |
| |
| /// \brief Retrieve the nested-name-specifier that qualifies the |
| /// name, with source location information. |
| NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } |
| |
| /// \brief Retrieve the nested-name-specifier that qualifies this |
| /// declaration. |
| NestedNameSpecifier *getQualifier() const { |
| return QualifierLoc.getNestedNameSpecifier(); |
| } |
| |
| /// \brief Retrieve the location of the template keyword preceding |
| /// this name, if any. |
| SourceLocation getTemplateKeywordLoc() const { |
| if (!HasTemplateKWAndArgsInfo) return SourceLocation(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; |
| } |
| |
| /// \brief 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(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; |
| } |
| |
| /// \brief 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(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; |
| } |
| |
| /// Determines whet
|