| //===- ExprCXX.h - Classes for representing expressions ---------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| /// \file |
| /// 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/ASTConcept.h" |
| #include "clang/AST/ComputeDependence.h" |
| #include "clang/AST/Decl.h" |
| #include "clang/AST/DeclBase.h" |
| #include "clang/AST/DeclCXX.h" |
| #include "clang/AST/DeclTemplate.h" |
| #include "clang/AST/DeclarationName.h" |
| #include "clang/AST/DependenceFlags.h" |
| #include "clang/AST/Expr.h" |
| #include "clang/AST/NestedNameSpecifier.h" |
| #include "clang/AST/OperationKinds.h" |
| #include "clang/AST/Stmt.h" |
| #include "clang/AST/StmtCXX.h" |
| #include "clang/AST/TemplateBase.h" |
| #include "clang/AST/Type.h" |
| #include "clang/AST/UnresolvedSet.h" |
| #include "clang/Basic/ExceptionSpecificationType.h" |
| #include "clang/Basic/ExpressionTraits.h" |
| #include "clang/Basic/LLVM.h" |
| #include "clang/Basic/Lambda.h" |
| #include "clang/Basic/LangOptions.h" |
| #include "clang/Basic/OperatorKinds.h" |
| #include "clang/Basic/SourceLocation.h" |
| #include "clang/Basic/Specifiers.h" |
| #include "clang/Basic/TypeTraits.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/None.h" |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/ADT/PointerUnion.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/ADT/iterator_range.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Support/TrailingObjects.h" |
| #include <cassert> |
| #include <cstddef> |
| #include <cstdint> |
| #include <memory> |
| |
| namespace clang { |
| |
| class ASTContext; |
| class DeclAccessPair; |
| class IdentifierInfo; |
| class LambdaCapture; |
| class NonTypeTemplateParmDecl; |
| class TemplateParameterList; |
| |
| //===--------------------------------------------------------------------===// |
| // C++ Expressions. |
| //===--------------------------------------------------------------------===// |
| |
| /// 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 final : public CallExpr { |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| |
| SourceRange Range; |
| |
| // CXXOperatorCallExpr has some trailing objects belonging |
| // to CallExpr. See CallExpr for the details. |
| |
| SourceRange getSourceRangeImpl() const LLVM_READONLY; |
| |
| CXXOperatorCallExpr(OverloadedOperatorKind OpKind, Expr *Fn, |
| ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, |
| SourceLocation OperatorLoc, FPOptionsOverride FPFeatures, |
| ADLCallKind UsesADL); |
| |
| CXXOperatorCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); |
| |
| public: |
| static CXXOperatorCallExpr * |
| Create(const ASTContext &Ctx, OverloadedOperatorKind OpKind, Expr *Fn, |
| ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, |
| SourceLocation OperatorLoc, FPOptionsOverride FPFeatures, |
| ADLCallKind UsesADL = NotADL); |
| |
| static CXXOperatorCallExpr *CreateEmpty(const ASTContext &Ctx, |
| unsigned NumArgs, bool HasFPFeatures, |
| EmptyShell Empty); |
| |
| /// Returns the kind of overloaded operator that this expression refers to. |
| OverloadedOperatorKind getOperator() const { |
| return static_cast<OverloadedOperatorKind>( |
| CXXOperatorCallExprBits.OperatorKind); |
| } |
| |
| static bool isAssignmentOp(OverloadedOperatorKind Opc) { |
| return Opc == OO_Equal || Opc == OO_StarEqual || Opc == OO_SlashEqual || |
| Opc == OO_PercentEqual || Opc == OO_PlusEqual || |
| Opc == OO_MinusEqual || Opc == OO_LessLessEqual || |
| Opc == OO_GreaterGreaterEqual || Opc == OO_AmpEqual || |
| Opc == OO_CaretEqual || Opc == OO_PipeEqual; |
| } |
| bool isAssignmentOp() const { return isAssignmentOp(getOperator()); } |
| |
| static bool isComparisonOp(OverloadedOperatorKind Opc) { |
| switch (Opc) { |
| case OO_EqualEqual: |
| case OO_ExclaimEqual: |
| case OO_Greater: |
| case OO_GreaterEqual: |
| case OO_Less: |
| case OO_LessEqual: |
| case OO_Spaceship: |
| return true; |
| default: |
| return false; |
| } |
| } |
| bool isComparisonOp() const { return isComparisonOp(getOperator()); } |
| |
| /// Is this written as an infix binary operator? |
| bool isInfixBinaryOp() const; |
| |
| /// 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 { |
| OverloadedOperatorKind Operator = getOperator(); |
| return (Operator < OO_Plus || Operator >= OO_Arrow || |
| Operator == OO_PlusPlus || Operator == OO_MinusMinus) |
| ? getBeginLoc() |
| : getOperatorLoc(); |
| } |
| |
| SourceLocation getBeginLoc() const { return Range.getBegin(); } |
| SourceLocation getEndLoc() const { return Range.getEnd(); } |
| SourceRange getSourceRange() const { return Range; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXOperatorCallExprClass; |
| } |
| }; |
| |
| /// 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 final : public CallExpr { |
| // CXXMemberCallExpr has some trailing objects belonging |
| // to CallExpr. See CallExpr for the details. |
| |
| CXXMemberCallExpr(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, |
| ExprValueKind VK, SourceLocation RP, |
| FPOptionsOverride FPOptions, unsigned MinNumArgs); |
| |
| CXXMemberCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); |
| |
| public: |
| static CXXMemberCallExpr *Create(const ASTContext &Ctx, Expr *Fn, |
| ArrayRef<Expr *> Args, QualType Ty, |
| ExprValueKind VK, SourceLocation RP, |
| FPOptionsOverride FPFeatures, |
| unsigned MinNumArgs = 0); |
| |
| static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, |
| bool HasFPFeatures, EmptyShell Empty); |
| |
| /// Retrieve the implicit object argument for the member call. |
| /// |
| /// For example, in "x.f(5)", this returns the sub-expression "x". |
| Expr *getImplicitObjectArgument() const; |
| |
| /// Retrieve the type of the object argument. |
| /// |
| /// Note that this always returns a non-pointer type. |
| QualType getObjectType() const; |
| |
| /// Retrieve the declaration of the called method. |
| CXXMethodDecl *getMethodDecl() const; |
| |
| /// Retrieve 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 getBeginLoc(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXMemberCallExprClass; |
| } |
| }; |
| |
| /// Represents a call to a CUDA kernel function. |
| class CUDAKernelCallExpr final : public CallExpr { |
| friend class ASTStmtReader; |
| |
| enum { CONFIG, END_PREARG }; |
| |
| // CUDAKernelCallExpr has some trailing objects belonging |
| // to CallExpr. See CallExpr for the details. |
| |
| CUDAKernelCallExpr(Expr *Fn, CallExpr *Config, ArrayRef<Expr *> Args, |
| QualType Ty, ExprValueKind VK, SourceLocation RP, |
| FPOptionsOverride FPFeatures, unsigned MinNumArgs); |
| |
| CUDAKernelCallExpr(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); |
| |
| public: |
| static CUDAKernelCallExpr *Create(const ASTContext &Ctx, Expr *Fn, |
| CallExpr *Config, ArrayRef<Expr *> Args, |
| QualType Ty, ExprValueKind VK, |
| SourceLocation RP, |
| FPOptionsOverride FPFeatures, |
| unsigned MinNumArgs = 0); |
| |
| static CUDAKernelCallExpr *CreateEmpty(const ASTContext &Ctx, |
| unsigned NumArgs, bool HasFPFeatures, |
| EmptyShell Empty); |
| |
| const CallExpr *getConfig() const { |
| return cast_or_null<CallExpr>(getPreArg(CONFIG)); |
| } |
| CallExpr *getConfig() { return cast_or_null<CallExpr>(getPreArg(CONFIG)); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CUDAKernelCallExprClass; |
| } |
| }; |
| |
| /// A rewritten comparison expression that was originally written using |
| /// operator syntax. |
| /// |
| /// In C++20, the following rewrites are performed: |
| /// - <tt>a == b</tt> -> <tt>b == a</tt> |
| /// - <tt>a != b</tt> -> <tt>!(a == b)</tt> |
| /// - <tt>a != b</tt> -> <tt>!(b == a)</tt> |
| /// - For \c \@ in \c <, \c <=, \c >, \c >=, \c <=>: |
| /// - <tt>a @ b</tt> -> <tt>(a <=> b) @ 0</tt> |
| /// - <tt>a @ b</tt> -> <tt>0 @ (b <=> a)</tt> |
| /// |
| /// This expression provides access to both the original syntax and the |
| /// rewritten expression. |
| /// |
| /// Note that the rewritten calls to \c ==, \c <=>, and \c \@ are typically |
| /// \c CXXOperatorCallExprs, but could theoretically be \c BinaryOperators. |
| class CXXRewrittenBinaryOperator : public Expr { |
| friend class ASTStmtReader; |
| |
| /// The rewritten semantic form. |
| Stmt *SemanticForm; |
| |
| public: |
| CXXRewrittenBinaryOperator(Expr *SemanticForm, bool IsReversed) |
| : Expr(CXXRewrittenBinaryOperatorClass, SemanticForm->getType(), |
| SemanticForm->getValueKind(), SemanticForm->getObjectKind()), |
| SemanticForm(SemanticForm) { |
| CXXRewrittenBinaryOperatorBits.IsReversed = IsReversed; |
| setDependence(computeDependence(this)); |
| } |
| CXXRewrittenBinaryOperator(EmptyShell Empty) |
| : Expr(CXXRewrittenBinaryOperatorClass, Empty), SemanticForm() {} |
| |
| /// Get an equivalent semantic form for this expression. |
| Expr *getSemanticForm() { return cast<Expr>(SemanticForm); } |
| const Expr *getSemanticForm() const { return cast<Expr>(SemanticForm); } |
| |
| struct DecomposedForm { |
| /// The original opcode, prior to rewriting. |
| BinaryOperatorKind Opcode; |
| /// The original left-hand side. |
| const Expr *LHS; |
| /// The original right-hand side. |
| const Expr *RHS; |
| /// The inner \c == or \c <=> operator expression. |
| const Expr *InnerBinOp; |
| }; |
| |
| /// Decompose this operator into its syntactic form. |
| DecomposedForm getDecomposedForm() const LLVM_READONLY; |
| |
| /// Determine whether this expression was rewritten in reverse form. |
| bool isReversed() const { return CXXRewrittenBinaryOperatorBits.IsReversed; } |
| |
| BinaryOperatorKind getOperator() const { return getDecomposedForm().Opcode; } |
| BinaryOperatorKind getOpcode() const { return getOperator(); } |
| static StringRef getOpcodeStr(BinaryOperatorKind Op) { |
| return BinaryOperator::getOpcodeStr(Op); |
| } |
| StringRef getOpcodeStr() const { |
| return BinaryOperator::getOpcodeStr(getOpcode()); |
| } |
| bool isComparisonOp() const { return true; } |
| bool isAssignmentOp() const { return false; } |
| |
| const Expr *getLHS() const { return getDecomposedForm().LHS; } |
| const Expr *getRHS() const { return getDecomposedForm().RHS; } |
| |
| SourceLocation getOperatorLoc() const LLVM_READONLY { |
| return getDecomposedForm().InnerBinOp->getExprLoc(); |
| } |
| SourceLocation getExprLoc() const LLVM_READONLY { return getOperatorLoc(); } |
| |
| /// Compute the begin and end locations from the decomposed form. |
| /// The locations of the semantic form are not reliable if this is |
| /// a reversed expression. |
| //@{ |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return getDecomposedForm().LHS->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return getDecomposedForm().RHS->getEndLoc(); |
| } |
| SourceRange getSourceRange() const LLVM_READONLY { |
| DecomposedForm DF = getDecomposedForm(); |
| return SourceRange(DF.LHS->getBeginLoc(), DF.RHS->getEndLoc()); |
| } |
| //@} |
| |
| child_range children() { |
| return child_range(&SemanticForm, &SemanticForm + 1); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXRewrittenBinaryOperatorClass; |
| } |
| }; |
| |
| /// 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, CXXConstCastExpr for \c const_cast and |
| /// CXXAddrspaceCastExpr for addrspace_cast (in OpenCL). |
| class CXXNamedCastExpr : public ExplicitCastExpr { |
| private: |
| // the location of the casting op |
| SourceLocation Loc; |
| |
| // the location of the right parenthesis |
| SourceLocation RParenLoc; |
| |
| // range for '<' '>' |
| SourceRange AngleBrackets; |
| |
| protected: |
| friend class ASTStmtReader; |
| |
| CXXNamedCastExpr(StmtClass SC, QualType ty, ExprValueKind VK, CastKind kind, |
| Expr *op, unsigned PathSize, bool HasFPFeatures, |
| TypeSourceInfo *writtenTy, SourceLocation l, |
| SourceLocation RParenLoc, SourceRange AngleBrackets) |
| : ExplicitCastExpr(SC, ty, VK, kind, op, PathSize, HasFPFeatures, |
| writtenTy), |
| Loc(l), RParenLoc(RParenLoc), AngleBrackets(AngleBrackets) {} |
| |
| explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize, |
| bool HasFPFeatures) |
| : ExplicitCastExpr(SC, Shell, PathSize, HasFPFeatures) {} |
| |
| public: |
| const char *getCastName() const; |
| |
| /// Retrieve the location of the cast operator keyword, e.g., |
| /// \c static_cast. |
| SourceLocation getOperatorLoc() const { return Loc; } |
| |
| /// Retrieve the location of the closing parenthesis. |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
| SourceRange getAngleBrackets() const LLVM_READONLY { return AngleBrackets; } |
| |
| static bool classof(const Stmt *T) { |
| switch (T->getStmtClass()) { |
| case CXXStaticCastExprClass: |
| case CXXDynamicCastExprClass: |
| case CXXReinterpretCastExprClass: |
| case CXXConstCastExprClass: |
| case CXXAddrspaceCastExprClass: |
| return true; |
| default: |
| return false; |
| } |
| } |
| }; |
| |
| /// 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 *, |
| FPOptionsOverride> { |
| CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, |
| unsigned pathSize, TypeSourceInfo *writtenTy, |
| FPOptionsOverride FPO, SourceLocation l, |
| SourceLocation RParenLoc, SourceRange AngleBrackets) |
| : CXXNamedCastExpr(CXXStaticCastExprClass, ty, vk, kind, op, pathSize, |
| FPO.requiresTrailingStorage(), writtenTy, l, RParenLoc, |
| AngleBrackets) { |
| if (hasStoredFPFeatures()) |
| *getTrailingFPFeatures() = FPO; |
| } |
| |
| explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize, |
| bool HasFPFeatures) |
| : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize, |
| HasFPFeatures) {} |
| |
| unsigned numTrailingObjects(OverloadToken<CXXBaseSpecifier *>) const { |
| return path_size(); |
| } |
| |
| public: |
| friend class CastExpr; |
| friend TrailingObjects; |
| |
| static CXXStaticCastExpr * |
| Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, |
| Expr *Op, const CXXCastPath *Path, TypeSourceInfo *Written, |
| FPOptionsOverride FPO, SourceLocation L, SourceLocation RParenLoc, |
| SourceRange AngleBrackets); |
| static CXXStaticCastExpr *CreateEmpty(const ASTContext &Context, |
| unsigned PathSize, bool hasFPFeatures); |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXStaticCastExprClass; |
| } |
| }; |
| |
| /// 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, |
| /*HasFPFeatures*/ false, writtenTy, l, RParenLoc, |
| AngleBrackets) {} |
| |
| explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize) |
| : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize, |
| /*HasFPFeatures*/ false) {} |
| |
| public: |
| friend class CastExpr; |
| friend TrailingObjects; |
| |
| 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; |
| } |
| }; |
| |
| /// 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, /*HasFPFeatures*/ false, writtenTy, l, |
| RParenLoc, AngleBrackets) {} |
| |
| CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize) |
| : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize, |
| /*HasFPFeatures*/ false) {} |
| |
| public: |
| friend class CastExpr; |
| friend TrailingObjects; |
| |
| 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; |
| } |
| }; |
| |
| /// 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, |
| /*HasFPFeatures*/ false, writtenTy, l, RParenLoc, |
| AngleBrackets) {} |
| |
| explicit CXXConstCastExpr(EmptyShell Empty) |
| : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0, |
| /*HasFPFeatures*/ false) {} |
| |
| public: |
| friend class CastExpr; |
| friend TrailingObjects; |
| |
| 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; |
| } |
| }; |
| |
| /// A C++ addrspace_cast expression (currently only enabled for OpenCL). |
| /// |
| /// This expression node represents a cast between pointers to objects in |
| /// different address spaces e.g., |
| /// \c addrspace_cast<global int*>(PtrToGenericInt). |
| /// |
| /// A addrspace_cast can cast address space type qualifiers but does not change |
| /// the underlying value. |
| class CXXAddrspaceCastExpr final |
| : public CXXNamedCastExpr, |
| private llvm::TrailingObjects<CXXAddrspaceCastExpr, CXXBaseSpecifier *> { |
| CXXAddrspaceCastExpr(QualType ty, ExprValueKind VK, CastKind Kind, Expr *op, |
| TypeSourceInfo *writtenTy, SourceLocation l, |
| SourceLocation RParenLoc, SourceRange AngleBrackets) |
| : CXXNamedCastExpr(CXXAddrspaceCastExprClass, ty, VK, Kind, op, 0, |
| /*HasFPFeatures*/ false, writtenTy, l, RParenLoc, |
| AngleBrackets) {} |
| |
| explicit CXXAddrspaceCastExpr(EmptyShell Empty) |
| : CXXNamedCastExpr(CXXAddrspaceCastExprClass, Empty, 0, |
| /*HasFPFeatures*/ false) {} |
| |
| public: |
| friend class CastExpr; |
| friend TrailingObjects; |
| |
| static CXXAddrspaceCastExpr * |
| Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind, |
| Expr *Op, TypeSourceInfo *WrittenTy, SourceLocation L, |
| SourceLocation RParenLoc, SourceRange AngleBrackets); |
| static CXXAddrspaceCastExpr *CreateEmpty(const ASTContext &Context); |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXAddrspaceCastExprClass; |
| } |
| }; |
| |
| /// 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 final : public CallExpr { |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| |
| /// The location of a ud-suffix within the literal. |
| SourceLocation UDSuffixLoc; |
| |
| // UserDefinedLiteral has some trailing objects belonging |
| // to CallExpr. See CallExpr for the details. |
| |
| UserDefinedLiteral(Expr *Fn, ArrayRef<Expr *> Args, QualType Ty, |
| ExprValueKind VK, SourceLocation LitEndLoc, |
| SourceLocation SuffixLoc, FPOptionsOverride FPFeatures); |
| |
| UserDefinedLiteral(unsigned NumArgs, bool HasFPFeatures, EmptyShell Empty); |
| |
| public: |
| static UserDefinedLiteral *Create(const ASTContext &Ctx, Expr *Fn, |
| ArrayRef<Expr *> Args, QualType Ty, |
| ExprValueKind VK, SourceLocation LitEndLoc, |
| SourceLocation SuffixLoc, |
| FPOptionsOverride FPFeatures); |
| |
| static UserDefinedLiteral *CreateEmpty(const ASTContext &Ctx, |
| unsigned NumArgs, bool HasFPOptions, |
| EmptyShell Empty); |
| |
| /// The kind of literal operator which is invoked. |
| enum LiteralOperatorKind { |
| /// Raw form: operator "" X (const char *) |
| LOK_Raw, |
| |
| /// Raw form: operator "" X<cs...> () |
| LOK_Template, |
| |
| /// operator "" X (unsigned long long) |
| LOK_Integer, |
| |
| /// operator "" X (long double) |
| LOK_Floating, |
| |
| /// operator "" X (const CharT *, size_t) |
| LOK_String, |
| |
| /// operator "" X (CharT) |
| LOK_Character |
| }; |
| |
| /// Returns the kind of literal operator invocation |
| /// which this expression represents. |
| LiteralOperatorKind getLiteralOperatorKind() const; |
| |
| /// 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 getBeginLoc() const { |
| if (getLiteralOperatorKind() == LOK_Template) |
| return getRParenLoc(); |
| return getArg(0)->getBeginLoc(); |
| } |
| |
| SourceLocation getEndLoc() const { return getRParenLoc(); } |
| |
| /// 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; } |
| |
| /// Returns the ud-suffix specified for this literal. |
| const IdentifierInfo *getUDSuffix() const; |
| |
| static bool classof(const Stmt *S) { |
| return S->getStmtClass() == UserDefinedLiteralClass; |
| } |
| }; |
| |
| /// A boolean literal, per ([C++ lex.bool] Boolean literals). |
| class CXXBoolLiteralExpr : public Expr { |
| public: |
| CXXBoolLiteralExpr(bool Val, QualType Ty, SourceLocation Loc) |
| : Expr(CXXBoolLiteralExprClass, Ty, VK_PRValue, OK_Ordinary) { |
| CXXBoolLiteralExprBits.Value = Val; |
| CXXBoolLiteralExprBits.Loc = Loc; |
| setDependence(ExprDependence::None); |
| } |
| |
| explicit CXXBoolLiteralExpr(EmptyShell Empty) |
| : Expr(CXXBoolLiteralExprClass, Empty) {} |
| |
| bool getValue() const { return CXXBoolLiteralExprBits.Value; } |
| void setValue(bool V) { CXXBoolLiteralExprBits.Value = V; } |
| |
| SourceLocation getBeginLoc() const { return getLocation(); } |
| SourceLocation getEndLoc() const { return getLocation(); } |
| |
| SourceLocation getLocation() const { return CXXBoolLiteralExprBits.Loc; } |
| void setLocation(SourceLocation L) { CXXBoolLiteralExprBits.Loc = L; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXBoolLiteralExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// 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 { |
| public: |
| CXXNullPtrLiteralExpr(QualType Ty, SourceLocation Loc) |
| : Expr(CXXNullPtrLiteralExprClass, Ty, VK_PRValue, OK_Ordinary) { |
| CXXNullPtrLiteralExprBits.Loc = Loc; |
| setDependence(ExprDependence::None); |
| } |
| |
| explicit CXXNullPtrLiteralExpr(EmptyShell Empty) |
| : Expr(CXXNullPtrLiteralExprClass, Empty) {} |
| |
| SourceLocation getBeginLoc() const { return getLocation(); } |
| SourceLocation getEndLoc() const { return getLocation(); } |
| |
| SourceLocation getLocation() const { return CXXNullPtrLiteralExprBits.Loc; } |
| void setLocation(SourceLocation L) { CXXNullPtrLiteralExprBits.Loc = L; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXNullPtrLiteralExprClass; |
| } |
| |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// 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 = nullptr; |
| |
| CXXStdInitializerListExpr(EmptyShell Empty) |
| : Expr(CXXStdInitializerListExprClass, Empty) {} |
| |
| public: |
| friend class ASTReader; |
| friend class ASTStmtReader; |
| |
| CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr) |
| : Expr(CXXStdInitializerListExprClass, Ty, VK_PRValue, OK_Ordinary), |
| SubExpr(SubExpr) { |
| setDependence(computeDependence(this)); |
| } |
| |
| Expr *getSubExpr() { return static_cast<Expr*>(SubExpr); } |
| const Expr *getSubExpr() const { return static_cast<const Expr*>(SubExpr); } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return SubExpr->getBeginLoc(); |
| } |
| |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return SubExpr->getEndLoc(); |
| } |
| |
| /// Retrieve the source range of the expression. |
| 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); } |
| |
| const_child_range children() const { |
| return const_child_range(&SubExpr, &SubExpr + 1); |
| } |
| }; |
| |
| /// 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 { |
| friend class ASTStmtReader; |
| |
| private: |
| llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; |
| SourceRange Range; |
| |
| public: |
| CXXTypeidExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) |
| : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), |
| Range(R) { |
| setDependence(computeDependence(this)); |
| } |
| |
| CXXTypeidExpr(QualType Ty, Expr *Operand, SourceRange R) |
| : Expr(CXXTypeidExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), |
| Range(R) { |
| setDependence(computeDependence(this)); |
| } |
| |
| 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; |
| |
| /// Best-effort check if the expression operand refers to a most derived |
| /// object. This is not a strong guarantee. |
| bool isMostDerived(ASTContext &Context) const; |
| |
| bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } |
| |
| /// Retrieves the type operand of this typeid() expression after |
| /// various required adjustments (removing reference types, cv-qualifiers). |
| QualType getTypeOperand(ASTContext &Context) const; |
| |
| /// Retrieve source information for the type operand. |
| TypeSourceInfo *getTypeOperandSourceInfo() const { |
| assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); |
| return Operand.get<TypeSourceInfo *>(); |
| } |
| Expr *getExprOperand() const { |
| assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)"); |
| return static_cast<Expr*>(Operand.get<Stmt *>()); |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } |
| SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } |
| SourceRange getSourceRange() const LLVM_READONLY { return Range; } |
| void setSourceRange(SourceRange R) { Range = R; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXTypeidExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| if (isTypeOperand()) |
| return child_range(child_iterator(), child_iterator()); |
| auto **begin = reinterpret_cast<Stmt **>(&Operand); |
| return child_range(begin, begin + 1); |
| } |
| |
| const_child_range children() const { |
| if (isTypeOperand()) |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| |
| auto **begin = |
| reinterpret_cast<Stmt **>(&const_cast<CXXTypeidExpr *>(this)->Operand); |
| return const_child_range(begin, begin + 1); |
| } |
| }; |
| |
| /// 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: |
| friend class ASTStmtReader; |
| |
| MSPropertyRefExpr(Expr *baseExpr, MSPropertyDecl *decl, bool isArrow, |
| QualType ty, ExprValueKind VK, |
| NestedNameSpecifierLoc qualifierLoc, SourceLocation nameLoc) |
| : Expr(MSPropertyRefExprClass, ty, VK, OK_Ordinary), BaseExpr(baseExpr), |
| TheDecl(decl), MemberLoc(nameLoc), IsArrow(isArrow), |
| QualifierLoc(qualifierLoc) { |
| setDependence(computeDependence(this)); |
| } |
| |
| MSPropertyRefExpr(EmptyShell Empty) : Expr(MSPropertyRefExprClass, Empty) {} |
| |
| SourceRange getSourceRange() const LLVM_READONLY { |
| return SourceRange(getBeginLoc(), getEndLoc()); |
| } |
| |
| bool isImplicitAccess() const { |
| return getBaseExpr() && getBaseExpr()->isImplicitCXXThis(); |
| } |
| |
| SourceLocation getBeginLoc() const { |
| if (!isImplicitAccess()) |
| return BaseExpr->getBeginLoc(); |
| else if (QualifierLoc) |
| return QualifierLoc.getBeginLoc(); |
| else |
| return MemberLoc; |
| } |
| |
| SourceLocation getEndLoc() const { return getMemberLoc(); } |
| |
| child_range children() { |
| return child_range((Stmt**)&BaseExpr, (Stmt**)&BaseExpr + 1); |
| } |
| |
| const_child_range children() const { |
| auto Children = const_cast<MSPropertyRefExpr *>(this)->children(); |
| return const_child_range(Children.begin(), Children.end()); |
| } |
| |
| 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; } |
| }; |
| |
| /// 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), |
| RBracketLoc(RBracketLoc) { |
| SubExprs[BASE_EXPR] = Base; |
| SubExprs[IDX_EXPR] = Idx; |
| setDependence(computeDependence(this)); |
| } |
| |
| /// 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 getBeginLoc() const LLVM_READONLY { |
| return getBase()->getBeginLoc(); |
| } |
| |
| SourceLocation getEndLoc() 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); |
| } |
| |
| const_child_range children() const { |
| return const_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 { |
| friend class ASTStmtReader; |
| |
| private: |
| llvm::PointerUnion<Stmt *, TypeSourceInfo *> Operand; |
| MSGuidDecl *Guid; |
| SourceRange Range; |
| |
| public: |
| CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, MSGuidDecl *Guid, |
| SourceRange R) |
| : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), |
| Guid(Guid), Range(R) { |
| setDependence(computeDependence(this)); |
| } |
| |
| CXXUuidofExpr(QualType Ty, Expr *Operand, MSGuidDecl *Guid, SourceRange R) |
| : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary), Operand(Operand), |
| Guid(Guid), Range(R) { |
| setDependence(computeDependence(this)); |
| } |
| |
| CXXUuidofExpr(EmptyShell Empty, bool isExpr) |
| : Expr(CXXUuidofExprClass, Empty) { |
| if (isExpr) |
| Operand = (Expr*)nullptr; |
| else |
| Operand = (TypeSourceInfo*)nullptr; |
| } |
| |
| bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } |
| |
| /// Retrieves the type operand of this __uuidof() expression after |
| /// various required adjustments (removing reference types, cv-qualifiers). |
| QualType getTypeOperand(ASTContext &Context) const; |
| |
| /// Retrieve source information for the type operand. |
| TypeSourceInfo *getTypeOperandSourceInfo() const { |
| assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); |
| return Operand.get<TypeSourceInfo *>(); |
| } |
| Expr *getExprOperand() const { |
| assert(!isTypeOperand() && "Cannot call getExprOperand for __uuidof(type)"); |
| return static_cast<Expr*>(Operand.get<Stmt *>()); |
| } |
| |
| MSGuidDecl *getGuidDecl() const { return Guid; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } |
| SourceLocation getEndLoc() const LLVM_READONLY { return Range.getEnd(); } |
| SourceRange getSourceRange() const LLVM_READONLY { return Range; } |
| void setSourceRange(SourceRange R) { Range = R; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXUuidofExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| if (isTypeOperand()) |
| return child_range(child_iterator(), child_iterator()); |
| auto **begin = reinterpret_cast<Stmt **>(&Operand); |
| return child_range(begin, begin + 1); |
| } |
| |
| const_child_range children() const { |
| if (isTypeOperand()) |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| auto **begin = |
| reinterpret_cast<Stmt **>(&const_cast<CXXUuidofExpr *>(this)->Operand); |
| return const_child_range(begin, begin + 1); |
| } |
| }; |
| |
| /// 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 { |
| public: |
| CXXThisExpr(SourceLocation L, QualType Ty, bool IsImplicit) |
| : Expr(CXXThisExprClass, Ty, VK_PRValue, OK_Ordinary) { |
| CXXThisExprBits.IsImplicit = IsImplicit; |
| CXXThisExprBits.Loc = L; |
| setDependence(computeDependence(this)); |
| } |
| |
| CXXThisExpr(EmptyShell Empty) : Expr(CXXThisExprClass, Empty) {} |
| |
| SourceLocation getLocation() const { return CXXThisExprBits.Loc; } |
| void setLocation(SourceLocation L) { CXXThisExprBits.Loc = L; } |
| |
| SourceLocation getBeginLoc() const { return getLocation(); } |
| SourceLocation getEndLoc() const { return getLocation(); } |
| |
| bool isImplicit() const { return CXXThisExprBits.IsImplicit; } |
| void setImplicit(bool I) { CXXThisExprBits.IsImplicit = I; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXThisExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// 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 { |
| friend class ASTStmtReader; |
| |
| /// The optional expression in the throw statement. |
| Stmt *Operand; |
| |
| public: |
| // \p Ty is the void type which is used as the result type of the |
| // expression. The \p Loc is the location of the throw keyword. |
| // \p Operand is the expression in the throw statement, and can be |
| // null if not present. |
| CXXThrowExpr(Expr *Operand, QualType Ty, SourceLocation Loc, |
| bool IsThrownVariableInScope) |
| : Expr(CXXThrowExprClass, Ty, VK_PRValue, OK_Ordinary), Operand(Operand) { |
| CXXThrowExprBits.ThrowLoc = Loc; |
| CXXThrowExprBits.IsThrownVariableInScope = IsThrownVariableInScope; |
| setDependence(computeDependence(this)); |
| } |
| CXXThrowExpr(EmptyShell Empty) : Expr(CXXThrowExprClass, Empty) {} |
| |
| const Expr *getSubExpr() const { return cast_or_null<Expr>(Operand); } |
| Expr *getSubExpr() { return cast_or_null<Expr>(Operand); } |
| |
| SourceLocation getThrowLoc() const { return CXXThrowExprBits.ThrowLoc; } |
| |
| /// Determines whether the variable thrown by this expression (if any!) |
| /// is within the innermost try block. |
| /// |
| /// This information is required to determine whether the NRVO can apply to |
| /// this variable. |
| bool isThrownVariableInScope() const { |
| return CXXThrowExprBits.IsThrownVariableInScope; |
| } |
| |
| SourceLocation getBeginLoc() const { return getThrowLoc(); } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| if (!getSubExpr()) |
| return getThrowLoc(); |
| return getSubExpr()->getEndLoc(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXThrowExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(&Operand, Operand ? &Operand + 1 : &Operand); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(&Operand, Operand ? &Operand + 1 : &Operand); |
| } |
| }; |
| |
| /// 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 { |
| friend class ASTStmtReader; |
| |
| /// The parameter whose default is being used. |
| ParmVarDecl *Param; |
| |
| /// The context where the default argument expression was used. |
| DeclContext *UsedContext; |
| |
| CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *Param, |
| DeclContext *UsedContext) |
| : Expr(SC, |
| Param->hasUnparsedDefaultArg() |
| ? Param->getType().getNonReferenceType() |
| : Param->getDefaultArg()->getType(), |
| Param->getDefaultArg()->getValueKind(), |
| Param->getDefaultArg()->getObjectKind()), |
| Param(Param), UsedContext(UsedContext) { |
| CXXDefaultArgExprBits.Loc = Loc; |
| setDependence(computeDependence(this)); |
| } |
| |
| 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, |
| DeclContext *UsedContext) { |
| return new (C) |
| CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param, UsedContext); |
| } |
| |
| // 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(); } |
| |
| const DeclContext *getUsedContext() const { return UsedContext; } |
| DeclContext *getUsedContext() { return UsedContext; } |
| |
| /// Retrieve the location where this default argument was actually used. |
| SourceLocation getUsedLocation() const { return CXXDefaultArgExprBits.Loc; } |
| |
| /// Default argument expressions have no representation in the |
| /// source, so they have an empty source range. |
| SourceLocation getBeginLoc() const { return SourceLocation(); } |
| SourceLocation getEndLoc() const { return SourceLocation(); } |
| |
| SourceLocation getExprLoc() const { return getUsedLocation(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXDefaultArgExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// 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 { |
| friend class ASTReader; |
| friend class ASTStmtReader; |
| |
| /// The field whose default is being used. |
| FieldDecl *Field; |
| |
| /// The context where the default initializer expression was used. |
| DeclContext *UsedContext; |
| |
| CXXDefaultInitExpr(const ASTContext &Ctx, SourceLocation Loc, |
| FieldDecl *Field, QualType Ty, DeclContext *UsedContext); |
| |
| 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 &Ctx, SourceLocation Loc, |
| FieldDecl *Field, DeclContext *UsedContext) { |
| return new (Ctx) CXXDefaultInitExpr(Ctx, Loc, Field, Field->getType(), UsedContext); |
| } |
| |
| /// Get the field whose initializer will be used. |
| FieldDecl *getField() { return Field; } |
| const FieldDecl *getField() const { return Field; } |
| |
| /// 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(); |
| } |
| |
| const DeclContext *getUsedContext() const { return UsedContext; } |
| DeclContext *getUsedContext() { return UsedContext; } |
| |
| /// Retrieve the location where this default initializer expression was |
| /// actually used. |
| SourceLocation getUsedLocation() const { return getBeginLoc(); } |
| |
| SourceLocation getBeginLoc() const { return CXXDefaultInitExprBits.Loc; } |
| SourceLocation getEndLoc() const { return CXXDefaultInitExprBits.Loc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXDefaultInitExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// Represents a C++ temporary. |
| class CXXTemporary { |
| /// 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; |
| } |
| }; |
| |
| /// 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 = nullptr; |
| Stmt *SubExpr = nullptr; |
| |
| CXXBindTemporaryExpr(CXXTemporary *temp, Expr *SubExpr) |
| : Expr(CXXBindTemporaryExprClass, SubExpr->getType(), VK_PRValue, |
| OK_Ordinary), |
| Temp(temp), SubExpr(SubExpr) { |
| setDependence(computeDependence(this)); |
| } |
| |
| public: |
| CXXBindTemporaryExpr(EmptyShell Empty) |
| : Expr(CXXBindTemporaryExprClass, Empty) {} |
| |
| 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 getBeginLoc() const LLVM_READONLY { |
| return SubExpr->getBeginLoc(); |
| } |
| |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return SubExpr->getEndLoc(); |
| } |
| |
| // 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); } |
| |
| const_child_range children() const { |
| return const_child_range(&SubExpr, &SubExpr + 1); |
| } |
| }; |
| |
| /// Represents a call to a C++ constructor. |
| class CXXConstructExpr : public Expr { |
| friend class ASTStmtReader; |
| |
| public: |
| enum ConstructionKind { |
| CK_Complete, |
| CK_NonVirtualBase, |
| CK_VirtualBase, |
| CK_Delegating |
| }; |
| |
| private: |
| /// A pointer to the constructor which will be ultimately called. |
| CXXConstructorDecl *Constructor; |
| |
| SourceRange ParenOrBraceRange; |
| |
| /// The number of arguments. |
| unsigned NumArgs; |
| |
| // We would like to stash the arguments of the constructor call after |
| // CXXConstructExpr. However CXXConstructExpr is used as a base class of |
| // CXXTemporaryObjectExpr which makes the use of llvm::TrailingObjects |
| // impossible. |
| // |
| // Instead we manually stash the trailing object after the full object |
| // containing CXXConstructExpr (that is either CXXConstructExpr or |
| // CXXTemporaryObjectExpr). |
| // |
| // The trailing objects are: |
| // |
| // * An array of getNumArgs() "Stmt *" for the arguments of the |
| // constructor call. |
| |
| /// Return a pointer to the start of the trailing arguments. |
| /// Defined just after CXXTemporaryObjectExpr. |
| inline Stmt **getTrailingArgs(); |
| const Stmt *const *getTrailingArgs() const { |
| return const_cast<CXXConstructExpr *>(this)->getTrailingArgs(); |
| } |
| |
| protected: |
| /// Build a C++ construction expression. |
| CXXConstructExpr(StmtClass SC, QualType Ty, SourceLocation Loc, |
| CXXConstructorDecl *Ctor, bool Elidable, |
| ArrayRef<Expr *> Args, bool HadMultipleCandidates, |
| bool ListInitialization, bool StdInitListInitialization, |
| bool ZeroInitialization, ConstructionKind ConstructKind, |
| SourceRange ParenOrBraceRange); |
| |
| /// Build an empty C++ construction expression. |
| CXXConstructExpr(StmtClass SC, EmptyShell Empty, unsigned NumArgs); |
| |
| /// Return the size in bytes of the trailing objects. Used by |
| /// CXXTemporaryObjectExpr to allocate the right amount of storage. |
| static unsigned sizeOfTrailingObjects(unsigned NumArgs) { |
| return NumArgs * sizeof(Stmt *); |
| } |
| |
| public: |
| /// Create a C++ construction expression. |
| static CXXConstructExpr * |
| Create(const ASTContext &Ctx, QualType Ty, SourceLocation Loc, |
| CXXConstructorDecl *Ctor, bool Elidable, ArrayRef<Expr *> Args, |
| bool HadMultipleCandidates, bool ListInitialization, |
| bool StdInitListInitialization, bool ZeroInitialization, |
| ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); |
| |
| /// Create an empty C++ construction expression. |
| static CXXConstructExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs); |
| |
| /// Get the constructor that this expression will (ultimately) call. |
| CXXConstructorDecl *getConstructor() const { return Constructor; } |
| |
| SourceLocation getLocation() const { return CXXConstructExprBits.Loc; } |
| void setLocation(SourceLocation Loc) { CXXConstructExprBits.Loc = Loc; } |
| |
| /// Whether this construction is elidable. |
| bool isElidable() const { return CXXConstructExprBits.Elidable; } |
| void setElidable(bool E) { CXXConstructExprBits.Elidable = E; } |
| |
| /// Whether the referred constructor was resolved from |
| /// an overloaded set having size greater than 1. |
| bool hadMultipleCandidates() const { |
| return CXXConstructExprBits.HadMultipleCandidates; |
| } |
| void setHadMultipleCandidates(bool V) { |
| CXXConstructExprBits.HadMultipleCandidates = V; |
| } |
| |
| /// Whether this constructor call was written as list-initialization. |
| bool isListInitialization() const { |
| return CXXConstructExprBits.ListInitialization; |
| } |
| void setListInitialization(bool V) { |
| CXXConstructExprBits.ListInitialization = V; |
| } |
| |
| /// Whether this constructor call was written as list-initialization, |
| /// but was interpreted as forming a std::initializer_list<T> from the list |
| /// and passing that as a single constructor argument. |
| /// See C++11 [over.match.list]p1 bullet 1. |
| bool isStdInitListInitialization() const { |
| return CXXConstructExprBits.StdInitListInitialization; |
| } |
| void setStdInitListInitialization(bool V) { |
| CXXConstructExprBits.StdInitListInitialization = V; |
| } |
| |
| /// Whether this construction first requires |
| /// zero-initialization before the initializer is called. |
| bool requiresZeroInitialization() const { |
| return CXXConstructExprBits.ZeroInitialization; |
| } |
| void setRequiresZeroInitialization(bool ZeroInit) { |
| CXXConstructExprBits.ZeroInitialization = ZeroInit; |
| } |
| |
| /// Determine whether this constructor is actually constructing |
| /// a base class (rather than a complete object). |
| ConstructionKind getConstructionKind() const { |
| return static_cast<ConstructionKind>(CXXConstructExprBits.ConstructionKind); |
| } |
| void setConstructionKind(ConstructionKind CK) { |
| CXXConstructExprBits.ConstructionKind = CK; |
| } |
| |
| using arg_iterator = ExprIterator; |
| using const_arg_iterator = ConstExprIterator; |
| using arg_range = llvm::iterator_range<arg_iterator>; |
| using const_arg_range = llvm::iterator_range<const_arg_iterator>; |
| |
| arg_range arguments() { return arg_range(arg_begin(), arg_end()); } |
| const_arg_range arguments() const { |
| return const_arg_range(arg_begin(), arg_end()); |
| } |
| |
| arg_iterator arg_begin() { return getTrailingArgs(); } |
| arg_iterator arg_end() { return arg_begin() + getNumArgs(); } |
| const_arg_iterator arg_begin() const { return getTrailingArgs(); } |
| const_arg_iterator arg_end() const { return arg_begin() + getNumArgs(); } |
| |
| Expr **getArgs() { return reinterpret_cast<Expr **>(getTrailingArgs()); } |
| const Expr *const *getArgs() const { |
| return reinterpret_cast<const Expr *const *>(getTrailingArgs()); |
| } |
| |
| /// Return the number of arguments to the constructor call. |
| unsigned getNumArgs() const { return NumArgs; } |
| |
| /// Return the specified argument. |
| Expr *getArg(unsigned Arg) { |
| assert(Arg < getNumArgs() && "Arg access out of range!"); |
| return getArgs()[Arg]; |
| } |
| const Expr *getArg(unsigned Arg) const { |
| assert(Arg < getNumArgs() && "Arg access out of range!"); |
| return getArgs()[Arg]; |
| } |
| |
| /// Set the specified argument. |
| void setArg(unsigned Arg, Expr *ArgExpr) { |
| assert(Arg < getNumArgs() && "Arg access out of range!"); |
| getArgs()[Arg] = ArgExpr; |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY; |
| SourceLocation getEndLoc() const LLVM_READONLY; |
| SourceRange getParenOrBraceRange() const { return ParenOrBraceRange; } |
| void setParenOrBraceRange(SourceRange Range) { ParenOrBraceRange = Range; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXConstructExprClass || |
| T->getStmtClass() == CXXTemporaryObjectExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(getTrailingArgs(), getTrailingArgs() + getNumArgs()); |
| } |
| |
| const_child_range children() const { |
| auto Children = const_cast<CXXConstructExpr *>(this)->children(); |
| return const_child_range(Children.begin(), Children.end()); |
| } |
| }; |
| |
| /// 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 = nullptr; |
| |
| /// 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: |
| friend class ASTStmtReader; |
| |
| /// Construct a C++ inheriting construction expression. |
| CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T, |
| CXXConstructorDecl *Ctor, bool ConstructsVirtualBase, |
| bool InheritedFromVirtualBase) |
| : Expr(CXXInheritedCtorInitExprClass, T, VK_PRValue, OK_Ordinary), |
| Constructor(Ctor), Loc(Loc), |
| ConstructsVirtualBase(ConstructsVirtualBase), |
| InheritedFromVirtualBase(InheritedFromVirtualBase) { |
| assert(!T->isDependentType()); |
| setDependence(ExprDependence::None); |
| } |
| |
| /// Construct an empty C++ inheriting construction expression. |
| explicit CXXInheritedCtorInitExpr(EmptyShell Empty) |
| : Expr(CXXInheritedCtorInitExprClass, Empty), |
| ConstructsVirtualBase(false), InheritedFromVirtualBase(false) {} |
| |
| /// Get the constructor that this expression will call. |
| CXXConstructorDecl *getConstructor() const { return Constructor; } |
| |
| /// 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; |
| } |
| |
| /// 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 getBeginLoc() const LLVM_READONLY { return Loc; } |
| SourceLocation getEndLoc() 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()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// 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 *, |
| FPOptionsOverride> { |
| SourceLocation LParenLoc; |
| SourceLocation RParenLoc; |
| |
| CXXFunctionalCastExpr(QualType ty, ExprValueKind VK, |
| TypeSourceInfo *writtenTy, CastKind kind, |
| Expr *castExpr, unsigned pathSize, |
| FPOptionsOverride FPO, SourceLocation lParenLoc, |
| SourceLocation rParenLoc) |
| : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, castExpr, |
| pathSize, FPO.requiresTrailingStorage(), writtenTy), |
| LParenLoc(lParenLoc), RParenLoc(rParenLoc) { |
| if (hasStoredFPFeatures()) |
| *getTrailingFPFeatures() = FPO; |
| } |
| |
| explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize, |
| bool HasFPFeatures) |
| : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize, |
| HasFPFeatures) {} |
| |
| unsigned numTrailingObjects(OverloadToken<CXXBaseSpecifier *>) const { |
| return path_size(); |
| } |
| |
| public: |
| friend class CastExpr; |
| friend TrailingObjects; |
| |
| static CXXFunctionalCastExpr * |
| Create(const ASTContext &Context, QualType T, ExprValueKind VK, |
| TypeSourceInfo *Written, CastKind Kind, Expr *Op, |
| const CXXCastPath *Path, FPOptionsOverride FPO, SourceLocation LPLoc, |
| SourceLocation RPLoc); |
| static CXXFunctionalCastExpr * |
| CreateEmpty(const ASTContext &Context, unsigned PathSize, bool HasFPFeatures); |
| |
| SourceLocation getLParenLoc() const { return LParenLoc; } |
| void setLParenLoc(SourceLocation L) { LParenLoc = L; } |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
| |
| /// Determine whether this expression models list-initialization. |
| bool isListInitialization() const { return LParenLoc.isInvalid(); } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY; |
| SourceLocation getEndLoc() const LLVM_READONLY; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXFunctionalCastExprClass; |
| } |
| }; |
| |
| /// 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 final : public CXXConstructExpr { |
| friend class ASTStmtReader; |
| |
| // CXXTemporaryObjectExpr has some trailing objects belonging |
| // to CXXConstructExpr. See the comment inside CXXConstructExpr |
| // for more details. |
| |
| TypeSourceInfo *TSI; |
| |
| CXXTemporaryObjectExpr(CXXConstructorDecl *Cons, QualType Ty, |
| TypeSourceInfo *TSI, ArrayRef<Expr *> Args, |
| SourceRange ParenOrBraceRange, |
| bool HadMultipleCandidates, bool ListInitialization, |
| bool StdInitListInitialization, |
| bool ZeroInitialization); |
| |
| CXXTemporaryObjectExpr(EmptyShell Empty, unsigned NumArgs); |
| |
| public: |
| static CXXTemporaryObjectExpr * |
| Create(const ASTContext &Ctx, CXXConstructorDecl *Cons, QualType Ty, |
| TypeSourceInfo *TSI, ArrayRef<Expr *> Args, |
| SourceRange ParenOrBraceRange, bool HadMultipleCandidates, |
| bool ListInitialization, bool StdInitListInitialization, |
| bool ZeroInitialization); |
| |
| static CXXTemporaryObjectExpr *CreateEmpty(const ASTContext &Ctx, |
| unsigned NumArgs); |
| |
| TypeSourceInfo *getTypeSourceInfo() const { return TSI; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY; |
| SourceLocation getEndLoc() const LLVM_READONLY; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXTemporaryObjectExprClass; |
| } |
| }; |
| |
| Stmt **CXXConstructExpr::getTrailingArgs() { |
| if (auto *E = dyn_cast<CXXTemporaryObjectExpr>(this)) |
| return reinterpret_cast<Stmt **>(E + 1); |
| assert((getStmtClass() == CXXConstructExprClass) && |
| "Unexpected class deriving from CXXConstructExpr!"); |
| return reinterpret_cast<Stmt **>(this + 1); |
| } |
| |
| /// A C++ lambda expression, which produces a function object |
| /// (of unspecified type) that can be invoked later. |
| /// |
| /// 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 *> { |
| // LambdaExpr has some data stored in LambdaExprBits. |
| |
| /// The source range that covers the lambda introducer ([...]). |
| SourceRange IntroducerRange; |
| |
| /// The source location of this lambda's capture-default ('=' or '&'). |
| SourceLocation CaptureDefaultLoc; |
| |
| /// 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; |
| |
| /// Construct a lambda expression. |
| LambdaExpr(QualType T, SourceRange IntroducerRange, |
| LambdaCaptureDefault CaptureDefault, |
| SourceLocation CaptureDefaultLoc, bool ExplicitParams, |
| bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, |
| SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack); |
| |
| /// Construct an empty lambda expression. |
| LambdaExpr(EmptyShell Empty, unsigned NumCaptures); |
| |
| Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); } |
| Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); } |
| |
| void initBodyIfNeeded() const; |
| |
| public: |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| friend TrailingObjects; |
| |
| /// Construct a new lambda expression. |
| static LambdaExpr * |
| Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange, |
| LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, |
| bool ExplicitParams, bool ExplicitResultType, |
| ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace, |
| bool ContainsUnexpandedParameterPack); |
| |
| /// Construct a new lambda expression that will be deserialized from |
| /// an external source. |
| static LambdaExpr *CreateDeserialized(const ASTContext &C, |
| unsigned NumCaptures); |
| |
| /// Determine the default capture kind for this lambda. |
| LambdaCaptureDefault getCaptureDefault() const { |
| return static_cast<LambdaCaptureDefault>(LambdaExprBits.CaptureDefault); |
| } |
| |
| /// Retrieve the location of this lambda's capture-default, if any. |
| SourceLocation getCaptureDefaultLoc() const { return CaptureDefaultLoc; } |
| |
| /// Determine whether one of this lambda's captures is an init-capture. |
| bool isInitCapture(const LambdaCapture *Capture) const; |
| |
| /// An iterator that walks over the captures of the lambda, |
| /// both implicit and explicit. |
| using capture_iterator = const LambdaCapture *; |
| |
| /// An iterator over a range of lambda captures. |
| using capture_range = llvm::iterator_range<capture_iterator>; |
| |
| /// Retrieve this lambda's captures. |
| capture_range captures() const; |
| |
| /// Retrieve an iterator pointing to the first lambda capture. |
| capture_iterator capture_begin() const; |
| |
| /// Retrieve an iterator pointing past the end of the |
| /// sequence of lambda captures. |
| capture_iterator capture_end() const; |
| |
| /// Determine the number of captures in this lambda. |
| unsigned capture_size() const { return LambdaExprBits.NumCaptures; } |
| |
| /// Retrieve this lambda's explicit captures. |
| capture_range explicit_captures() const; |
| |
| /// Retrieve an iterator pointing to the first explicit |
| /// lambda capture. |
| capture_iterator explicit_capture_begin() const; |
| |
| /// Retrieve an iterator pointing past the end of the sequence of |
| /// explicit lambda captures. |
| capture_iterator explicit_capture_end() const; |
| |
| /// Retrieve this lambda's implicit captures. |
| capture_range implicit_captures() const; |
| |
| /// Retrieve an iterator pointing to the first implicit |
| /// lambda capture. |
| capture_iterator implicit_capture_begin() const; |
| |
| /// Retrieve an iterator pointing past the end of the sequence of |
| /// implicit lambda captures. |
| capture_iterator implicit_capture_end() const; |
| |
| /// Iterator that walks over the capture initialization |
| /// arguments. |
| using capture_init_iterator = Expr **; |
| |
| /// Const iterator that walks over the capture initialization |
| /// arguments. |
| /// FIXME: This interface is prone to being used incorrectly. |
| using const_capture_init_iterator = Expr *const *; |
| |
| /// 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()); |
| } |
| |
| /// 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()); |
| } |
| |
| /// 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()); |
| } |
| |
| /// 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()); |
| } |
| |
| /// Retrieve the iterator pointing one past the last |
| /// initialization argument for this lambda expression. |
| capture_init_iterator capture_init_end() { |
| return capture_init_begin() + capture_size(); |
| } |
| |
| /// 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() + capture_size(); |
| } |
| |
| /// Retrieve the source range covering the lambda introducer, |
| /// which contains the explicit capture list surrounded by square |
| /// brackets ([...]). |
| SourceRange getIntroducerRange() const { return IntroducerRange; } |
| |
| /// 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; |
| |
| /// Retrieve the function call operator associated with this |
| /// lambda expression. |
| CXXMethodDecl *getCallOperator() const; |
| |
| /// Retrieve the function template call operator associated with this |
| /// lambda expression. |
| FunctionTemplateDecl *getDependentCallOperator() const; |
| |
| /// If this is a generic lambda expression, retrieve the template |
| /// parameter list associated with it, or else return null. |
| TemplateParameterList *getTemplateParameterList() const; |
| |
| /// Get the template parameters were explicitly specified (as opposed to being |
| /// invented by use of an auto parameter). |
| ArrayRef<NamedDecl *> getExplicitTemplateParameters() const; |
| |
| /// Get the trailing requires clause, if any. |
| Expr *getTrailingRequiresClause() const; |
| |
| /// Whether this is a generic lambda. |
| bool isGenericLambda() const { return getTemplateParameterList(); } |
| |
| /// Retrieve the body of the lambda. This will be most of the time |
| /// a \p CompoundStmt, but can also be \p CoroutineBodyStmt wrapping |
| /// a \p CompoundStmt. Note that unlike functions, lambda-expressions |
| /// cannot have a function-try-block. |
| Stmt *getBody() const; |
| |
| /// Retrieve the \p CompoundStmt representing the body of the lambda. |
| /// This is a convenience function for callers who do not need |
| /// to handle node(s) which may wrap a \p CompoundStmt. |
| const CompoundStmt *getCompoundStmtBody() const; |
| CompoundStmt *getCompoundStmtBody() { |
| const auto *ConstThis = this; |
| return const_cast<CompoundStmt *>(ConstThis->getCompoundStmtBody()); |
| } |
| |
| /// Determine whether the lambda is mutable, meaning that any |
| /// captures values can be modified. |
| bool isMutable() const; |
| |
| /// Determine whether this lambda has an explicit parameter |
| /// list vs. an implicit (empty) parameter list. |
| bool hasExplicitParameters() const { return LambdaExprBits.ExplicitParams; } |
| |
| /// Whether this lambda had its result type explicitly specified. |
| bool hasExplicitResultType() const { |
| return LambdaExprBits.ExplicitResultType; |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == LambdaExprClass; |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return IntroducerRange.getBegin(); |
| } |
| |
| SourceLocation getEndLoc() const LLVM_READONLY { return ClosingBrace; } |
| |
| /// Includes the captures and the body of the lambda. |
| child_range children(); |
| const_child_range children() const; |
| }; |
| |
| /// 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 { |
| friend class ASTStmtReader; |
| |
| TypeSourceInfo *TypeInfo; |
| |
| public: |
| /// Create an explicitly-written scalar-value initialization |
| /// expression. |
| CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo, |
| SourceLocation RParenLoc) |
| : Expr(CXXScalarValueInitExprClass, Type, VK_PRValue, OK_Ordinary), |
| TypeInfo(TypeInfo) { |
| CXXScalarValueInitExprBits.RParenLoc = RParenLoc; |
| setDependence(computeDependence(this)); |
| } |
| |
| explicit CXXScalarValueInitExpr(EmptyShell Shell) |
| : Expr(CXXScalarValueInitExprClass, Shell) {} |
| |
| TypeSourceInfo *getTypeSourceInfo() const { |
| return TypeInfo; |
| } |
| |
| SourceLocation getRParenLoc() const { |
| return CXXScalarValueInitExprBits.RParenLoc; |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY; |
| SourceLocation getEndLoc() const { return getRParenLoc(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXScalarValueInitExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// Represents a new-expression for memory allocation and constructor |
| /// calls, e.g: "new CXXNewExpr(foo)". |
| class CXXNewExpr final |
| : public Expr, |
| private llvm::TrailingObjects<CXXNewExpr, Stmt *, SourceRange> { |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| friend TrailingObjects; |
| |
| /// Points to the allocation function used. |
| FunctionDecl *OperatorNew; |
| |
| /// Points to the deallocation function used in case of error. May be null. |
| FunctionDecl *OperatorDelete; |
| |
| /// The allocated type-source information, as written in the source. |
| TypeSourceInfo *AllocatedTypeInfo; |
| |
| /// Range of the entire new expression. |
| SourceRange Range; |
| |
| /// Source-range of a paren-delimited initializer. |
| SourceRange DirectInitRange; |
| |
| // CXXNewExpr is followed by several optional trailing objects. |
| // They are in order: |
| // |
| // * An optional "Stmt *" for the array size expression. |
| // Present if and ony if isArray(). |
| // |
| // * An optional "Stmt *" for the init expression. |
| // Present if and only if hasInitializer(). |
| // |
| // * An array of getNumPlacementArgs() "Stmt *" for the placement new |
| // arguments, if any. |
| // |
| // * An optional SourceRange for the range covering the parenthesized type-id |
| // if the allocated type was expressed as a parenthesized type-id. |
| // Present if and only if isParenTypeId(). |
| unsigned arraySizeOffset() const { return 0; } |
| unsigned initExprOffset() const { return arraySizeOffset() + isArray(); } |
| unsigned placementNewArgsOffset() const { |
| return initExprOffset() + hasInitializer(); |
| } |
| |
| unsigned numTrailingObjects(OverloadToken<Stmt *>) const { |
| return isArray() + hasInitializer() + getNumPlacementArgs(); |
| } |
| |
| unsigned numTrailingObjects(OverloadToken<SourceRange>) const { |
| return isParenTypeId(); |
| } |
| |
| public: |
| enum InitializationStyle { |
| /// New-expression has no initializer as written. |
| NoInit, |
| |
| /// New-expression has a C++98 paren-delimited initializer. |
| CallInit, |
| |
| /// New-expression has a C++11 list-initializer. |
| ListInit |
| }; |
| |
| private: |
| /// Build a c++ new expression. |
| CXXNewExpr(bool IsGlobalNew, FunctionDecl *OperatorNew, |
| FunctionDecl *OperatorDelete, bool ShouldPassAlignment, |
| bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, |
| SourceRange TypeIdParens, Optional<Expr *> ArraySize, |
| InitializationStyle InitializationStyle, Expr *Initializer, |
| QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, |
| SourceRange DirectInitRange); |
| |
| /// Build an empty c++ new expression. |
| CXXNewExpr(EmptyShell Empty, bool IsArray, unsigned NumPlacementArgs, |
| bool IsParenTypeId); |
| |
| public: |
| /// Create a c++ new expression. |
| static CXXNewExpr * |
| Create(const ASTContext &Ctx, bool IsGlobalNew, FunctionDecl *OperatorNew, |
| FunctionDecl *OperatorDelete, bool ShouldPassAlignment, |
| bool UsualArrayDeleteWantsSize, ArrayRef<Expr *> PlacementArgs, |
| SourceRange TypeIdParens, Optional<Expr *> ArraySize, |
| InitializationStyle InitializationStyle, Expr *Initializer, |
| QualType Ty, TypeSourceInfo *AllocatedTypeInfo, SourceRange Range, |
| SourceRange DirectInitRange); |
| |
| /// Create an empty c++ new expression. |
| static CXXNewExpr *CreateEmpty(const ASTContext &Ctx, bool IsArray, |
| bool HasInit, unsigned NumPlacementArgs, |
| bool IsParenTypeId); |
| |
| QualType getAllocatedType() const { |
| return getType()->castAs<PointerType>()->getPointeeType(); |
| } |
| |
| TypeSourceInfo *getAllocatedTypeSourceInfo() const { |
| return AllocatedTypeInfo; |
| } |
| |
| /// 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; |
| |
| 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 CXXNewExprBits.IsArray; } |
| |
| Optional<Expr *> getArraySize() { |
| if (!isArray()) |
| return None; |
| return cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]); |
| } |
| Optional<const Expr *> getArraySize() const { |
| if (!isArray()) |
| return None; |
| return cast_or_null<Expr>(getTrailingObjects<Stmt *>()[arraySizeOffset()]); |
| } |
| |
| unsigned getNumPlacementArgs() const { |
| return CXXNewExprBits.NumPlacementArgs; |
| } |
| |
| Expr **getPlacementArgs() { |
| return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>() + |
| placementNewArgsOffset()); |
| } |
| |
| Expr *getPlacementArg(unsigned I) { |
| assert((I < getNumPlacementArgs()) && "Index out of range!"); |
| return getPlacementArgs()[I]; |
| } |
| const Expr *getPlacementArg(unsigned I) const { |
| return const_cast<CXXNewExpr *>(this)->getPlacementArg(I); |
| } |
| |
| bool isParenTypeId() const { return CXXNewExprBits.IsParenTypeId; } |
| SourceRange getTypeIdParens() const { |
| return isParenTypeId() ? getTrailingObjects<SourceRange>()[0] |
| : SourceRange(); |
| } |
| |
| bool isGlobalNew() const { return CXXNewExprBits.IsGlobalNew; } |
| |
| /// Whether this new-expression has any initializer at all. |
| bool hasInitializer() const { |
| return CXXNewExprBits.StoredInitializationStyle > 0; |
| } |
| |
| /// The kind of initializer this new-expression has. |
| InitializationStyle getInitializationStyle() const { |
| if (CXXNewExprBits.StoredInitializationStyle == 0) |
| return NoInit; |
| return static_cast<InitializationStyle>( |
| CXXNewExprBits.StoredInitializationStyle - 1); |
| } |
| |
| /// The initializer of this new-expression. |
| Expr *getInitializer() { |
| return hasInitializer() |
| ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()]) |
| : nullptr; |
| } |
| const Expr *getInitializer() const { |
| return hasInitializer() |
| ? cast<Expr>(getTrailingObjects<Stmt *>()[initExprOffset()]) |
| : nullptr; |
| } |
| |
| /// Returns the CXXConstructExpr from this new-expression, or null. |
| const CXXConstructExpr *getConstructExpr() const { |
| return dyn_cast_or_null<CXXConstructExpr>(getInitializer()); |
| } |
| |
| /// Indicates whether the required alignment should be implicitly passed to |
| /// the allocation function. |
| bool passAlignment() const { return CXXNewExprBits.ShouldPassAlignment; } |
| |
| /// Answers whether the usual array deallocation function for the |
| /// allocated type expects the size of the allocation as a |
| /// parameter. |
| bool doesUsualArrayDeleteWantSize() const { |
| return CXXNewExprBits.UsualArrayDeleteWantsSize; |
| } |
| |
| using arg_iterator = ExprIterator; |
| using const_arg_iterator = ConstExprIterator; |
| |
| 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 getTrailingObjects<Stmt *>() + placementNewArgsOffset(); |
| } |
| arg_iterator placement_arg_end() { |
| return placement_arg_begin() + getNumPlacementArgs(); |
| } |
| const_arg_iterator placement_arg_begin() const { |
| return getTrailingObjects<Stmt *>() + placementNewArgsOffset(); |
| } |
| const_arg_iterator placement_arg_end() const { |
| return placement_arg_begin() + getNumPlacementArgs(); |
| } |
| |
| using raw_arg_iterator = Stmt **; |
| |
| raw_arg_iterator raw_arg_begin() { return getTrailingObjects<Stmt *>(); } |
| raw_arg_iterator raw_arg_end() { |
| return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>()); |
| } |
| const_arg_iterator raw_arg_begin() const { |
| return getTrailingObjects<Stmt *>(); |
| } |
| const_arg_iterator raw_arg_end() const { |
| return raw_arg_begin() + numTrailingObjects(OverloadToken<Stmt *>()); |
| } |
| |
| SourceLocation getBeginLoc() const { return Range.getBegin(); } |
| SourceLocation getEndLoc() const { return Range.getEnd(); } |
| |
| SourceRange getDirectInitRange() const { return DirectInitRange; } |
| SourceRange getSourceRange() const { return Range; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXNewExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(raw_arg_begin(), raw_arg_end()); } |
| |
| const_child_range children() const { |
| return const_child_range(const_cast<CXXNewExpr *>(this)->children()); |
| } |
| }; |
| |
| /// Represents a \c delete expression for memory deallocation and |
| /// destructor calls, e.g. "delete[] pArray". |
| class CXXDeleteExpr : public Expr { |
| friend class ASTStmtReader; |
| |
| /// Points to the operator delete overload that is used. Could be a member. |
| FunctionDecl *OperatorDelete = nullptr; |
| |
| /// The pointer expression to be deleted. |
| Stmt *Argument = nullptr; |
| |
| public: |
| CXXDeleteExpr(QualType Ty, bool GlobalDelete, bool ArrayForm, |
| bool ArrayFormAsWritten, bool UsualArrayDeleteWantsSize, |
| FunctionDecl *OperatorDelete, Expr *Arg, SourceLocation Loc) |
| : Expr(CXXDeleteExprClass, Ty, VK_PRValue, OK_Ordinary), |
| OperatorDelete(OperatorDelete), Argument(Arg) { |
| CXXDeleteExprBits.GlobalDelete = GlobalDelete; |
| CXXDeleteExprBits.ArrayForm = ArrayForm; |
| CXXDeleteExprBits.ArrayFormAsWritten = ArrayFormAsWritten; |
| CXXDeleteExprBits.UsualArrayDeleteWantsSize = UsualArrayDeleteWantsSize; |
| CXXDeleteExprBits.Loc = Loc; |
| setDependence(computeDependence(this)); |
| } |
| |
| explicit CXXDeleteExpr(EmptyShell Shell) : Expr(CXXDeleteExprClass, Shell) {} |
| |
| bool isGlobalDelete() const { return CXXDeleteExprBits.GlobalDelete; } |
| bool isArrayForm() const { return CXXDeleteExprBits.ArrayForm; } |
| bool isArrayFormAsWritten() const { |
| return CXXDeleteExprBits.ArrayFormAsWritten; |
| } |
| |
| /// Answers whether the usual array deallocation function for the |
| /// allocated type expects the size of the allocation as a |
| /// parameter. This can be true even if the actual deallocation |
| /// function that we're using doesn't want a size. |
| bool doesUsualArrayDeleteWantSize() const { |
| return CXXDeleteExprBits.UsualArrayDeleteWantsSize; |
| } |
| |
| FunctionDecl *getOperatorDelete() const { return OperatorDelete; } |
| |
| Expr *getArgument() { return cast<Expr>(Argument); } |
| const Expr *getArgument() const { return cast<Expr>(Argument); } |
| |
| /// 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 getBeginLoc() const { return CXXDeleteExprBits.Loc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return Argument->getEndLoc(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXDeleteExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Argument, &Argument + 1); } |
| |
| const_child_range children() const { |
| return const_child_range(&Argument, &Argument + 1); |
| } |
| }; |
| |
| /// Stores the type being destroyed by a pseudo-destructor expression. |
| class PseudoDestructorTypeStorage { |
| /// 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; |
| |
| /// The starting source location of the pseudo-destructor type. |
| SourceLocation Location; |
| |
| public: |
| PseudoDestructorTypeStorage() = default; |
| |
| 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; } |
| }; |
| |
| /// 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 { |
| friend class ASTStmtReader; |
| |
| /// The base expression (that is being destroyed). |
| Stmt *Base = nullptr; |
| |
| /// Whether the operator was an arrow ('->'); otherwise, it was a |
| /// period ('.'). |
| bool IsArrow : 1; |
| |
| /// The location of the '.' or '->' operator. |
| SourceLocation OperatorLoc; |
| |
| /// The nested-name-specifier that follows the operator, if present. |
| NestedNameSpecifierLoc QualifierLoc; |
| |
| /// The type that precedes the '::' in a qualified pseudo-destructor |
| /// expression. |
| TypeSourceInfo *ScopeType = nullptr; |
| |
| /// The location of the '::' in a qualified pseudo-destructor |
| /// expression. |
| SourceLocation ColonColonLoc; |
| |
| /// The location of the '~'. |
| SourceLocation TildeLoc; |
| |
| /// The type being destroyed, or its name if we were unable to |
| /// resolve the name. |
| PseudoDestructorTypeStorage DestroyedType; |
| |
| 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), IsArrow(false) {} |
| |
| Expr *getBase() const { return cast<Expr>(Base); } |
| |
| /// 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(); } |
| |
| /// Retrieves the nested-name-specifier that qualifies the type name, |
| /// with source-location information. |
| NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } |
| |
| /// 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(); |
| } |
| |
| /// Determine whether this pseudo-destructor expression was written |
| /// using an '->' (otherwise, it used a '.'). |
| bool isArrow() const { return IsArrow; } |
| |
| /// Retrieve the location of the '.' or '->' operator. |
| SourceLocation getOperatorLoc() const { return OperatorLoc; } |
| |
| /// 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; } |
| |
| /// Retrieve the location of the '::' in a qualified pseudo-destructor |
| /// expression. |
| SourceLocation getColonColonLoc() const { return ColonColonLoc; } |
| |
| /// Retrieve the location of the '~'. |
| SourceLocation getTildeLoc() const { return TildeLoc; } |
| |
| /// 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(); |
| } |
| |
| /// 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(); |
| } |
| |
| /// Retrieve the type being destroyed. |
| QualType getDestroyedType() const; |
| |
| /// Retrieve the starting location of the type being destroyed. |
| SourceLocation getDestroyedTypeLoc() const { |
| return DestroyedType.getLocation(); |
| } |
| |
| /// Set the name of destroyed type for a dependent pseudo-destructor |
| /// expression. |
| void setDestroyedType(IdentifierInfo *II, SourceLocation Loc) { |
| DestroyedType = PseudoDestructorTypeStorage(II, Loc); |
| } |
| |
| /// Set the destroyed type. |
| void setDestroyedType(TypeSourceInfo *Info) { |
| DestroyedType = PseudoDestructorTypeStorage(Info); |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return Base->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CXXPseudoDestructorExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Base, &Base + 1); } |
| |
| const_child_range children() const { |
| return const_child_range(&Base, &Base + 1); |
| } |
| }; |
| |
| /// 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 *> { |
| /// The location of the type trait keyword. |
| SourceLocation Loc; |
| |
| /// 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: |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| friend TrailingObjects; |
| |
| /// 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); |
| |
| /// Determine which type trait this expression uses. |
| TypeTrait getTrait() const { |
| return static_cast<TypeTrait>(TypeTraitExprBits.Kind); |
| } |
| |
| bool getValue() const { |
| assert(!isValueDependent()); |
| return TypeTraitExprBits.Value; |
| } |
| |
| /// Determine the number of arguments to this type trait. |
| unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; } |
| |
| /// Retrieve the Ith argument. |
| TypeSourceInfo *getArg(unsigned I) const { |
| assert(I < getNumArgs() && "Argument out-of-range"); |
| return getArgs()[I]; |
| } |
| |
| /// Retrieve the argument types. |
| ArrayRef<TypeSourceInfo *> getArgs() const { |
| return llvm::makeArrayRef(getTrailingObjects<TypeSourceInfo *>(), |
| getNumArgs()); |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } |
| SourceLocation getEndLoc() 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()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// 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 { |
| /// The trait. An ArrayTypeTrait enum in MSVC compat unsigned. |
| unsigned ATT : 2; |
| |
| /// The value of the type trait. Unspecified if dependent. |
| uint64_t Value = 0; |
| |
| /// The array dimension being queried, or -1 if not used. |
| Expr *Dimension; |
| |
| /// The location of the type trait keyword. |
| SourceLocation Loc; |
| |
| /// The location of the closing paren. |
| SourceLocation RParen; |
| |
| /// The type being queried. |
| TypeSourceInfo *QueriedType = nullptr; |
| |
| public: |
| friend class ASTStmtReader; |
| |
| ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att, |
| TypeSourceInfo *queried, uint64_t value, Expr *dimension, |
| SourceLocation rparen, QualType ty) |
| : Expr(ArrayTypeTraitExprClass, ty, VK_PRValue, OK_Ordinary), ATT(att), |
| Value(value), Dimension(dimension), Loc(loc), RParen(rparen), |
| QueriedType(queried) { |
| assert(att <= ATT_Last && "invalid enum value!"); |
| assert(static_cast<unsigned>(att) == ATT && "ATT overflow!"); |
| setDependence(computeDependence(this)); |
| } |
| |
| explicit ArrayTypeTraitExpr(EmptyShell Empty) |
| : Expr(ArrayTypeTraitExprClass, Empty), ATT(0) {} |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } |
| SourceLocation getEndLoc() 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()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// An expression trait intrinsic. |
| /// |
| /// Example: |
| /// \code |
| /// __is_lvalue_expr(std::cout) == true |
| /// __is_lvalue_expr(1) == false |
| /// \endcode |
| class ExpressionTraitExpr : public Expr { |
| /// The trait. A ExpressionTrait enum in MSVC compatible unsigned. |
| unsigned ET : 31; |
| |
| /// The value of the type trait. Unspecified if dependent. |
| unsigned Value : 1; |
| |
| /// The location of the type trait keyword. |
| SourceLocation Loc; |
| |
| /// The location of the closing paren. |
| SourceLocation RParen; |
| |
| /// The expression being queried. |
| Expr* QueriedExpression = nullptr; |
| |
| public: |
| friend class ASTStmtReader; |
| |
| ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, Expr *queried, |
| bool value, SourceLocation rparen, QualType resultType) |
| : Expr(ExpressionTraitExprClass, resultType, VK_PRValue, OK_Ordinary), |
| ET(et), Value(value), Loc(loc), RParen(rparen), |
| QueriedExpression(queried) { |
| assert(et <= ET_Last && "invalid enum value!"); |
| assert(static_cast<unsigned>(et) == ET && "ET overflow!"); |
| setDependence(computeDependence(this)); |
| } |
| |
| explicit ExpressionTraitExpr(EmptyShell Empty) |
| : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false) {} |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } |
| SourceLocation getEndLoc() 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()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// A reference to an overloaded function set, either an |
| /// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr. |
| class OverloadExpr : public Expr { |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| |
| /// The common name of these declarations. |
| DeclarationNameInfo NameInfo; |
| |
| /// The nested-name-specifier that qualifies the name, if any. |
| NestedNameSpecifierLoc QualifierLoc; |
| |
| protected: |
| OverloadExpr(StmtClass SC, const ASTContext &Context, |
| NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, |
| const DeclarationNameInfo &NameInfo, |
| const TemplateArgumentListInfo *TemplateArgs, |
| UnresolvedSetIterator Begin |