| //===--- Expr.h - Classes for representing expressions ----------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the Expr interface and subclasses. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_AST_EXPR_H |
| #define LLVM_CLANG_AST_EXPR_H |
| |
| #include "clang/AST/APValue.h" |
| #include "clang/AST/ASTVector.h" |
| #include "clang/AST/Decl.h" |
| #include "clang/AST/DeclAccessPair.h" |
| #include "clang/AST/OperationKinds.h" |
| #include "clang/AST/Stmt.h" |
| #include "clang/AST/TemplateBase.h" |
| #include "clang/AST/Type.h" |
| #include "clang/Basic/CharInfo.h" |
| #include "clang/Basic/LangOptions.h" |
| #include "clang/Basic/TypeTraits.h" |
| #include "llvm/ADT/APFloat.h" |
| #include "llvm/ADT/APSInt.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/Support/AtomicOrdering.h" |
| #include "llvm/Support/Compiler.h" |
| |
| namespace clang { |
| class APValue; |
| class ASTContext; |
| class BlockDecl; |
| class CXXBaseSpecifier; |
| class CXXMemberCallExpr; |
| class CXXOperatorCallExpr; |
| class CastExpr; |
| class Decl; |
| class IdentifierInfo; |
| class MaterializeTemporaryExpr; |
| class NamedDecl; |
| class ObjCPropertyRefExpr; |
| class OpaqueValueExpr; |
| class ParmVarDecl; |
| class StringLiteral; |
| class TargetInfo; |
| class ValueDecl; |
| |
| /// \brief A simple array of base specifiers. |
| typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; |
| |
| /// \brief An adjustment to be made to the temporary created when emitting a |
| /// reference binding, which accesses a particular subobject of that temporary. |
| struct SubobjectAdjustment { |
| enum { |
| DerivedToBaseAdjustment, |
| FieldAdjustment, |
| MemberPointerAdjustment |
| } Kind; |
| |
| struct DTB { |
| const CastExpr *BasePath; |
| const CXXRecordDecl *DerivedClass; |
| }; |
| |
| struct P { |
| const MemberPointerType *MPT; |
| Expr *RHS; |
| }; |
| |
| union { |
| struct DTB DerivedToBase; |
| FieldDecl *Field; |
| struct P Ptr; |
| }; |
| |
| SubobjectAdjustment(const CastExpr *BasePath, |
| const CXXRecordDecl *DerivedClass) |
| : Kind(DerivedToBaseAdjustment) { |
| DerivedToBase.BasePath = BasePath; |
| DerivedToBase.DerivedClass = DerivedClass; |
| } |
| |
| SubobjectAdjustment(FieldDecl *Field) |
| : Kind(FieldAdjustment) { |
| this->Field = Field; |
| } |
| |
| SubobjectAdjustment(const MemberPointerType *MPT, Expr *RHS) |
| : Kind(MemberPointerAdjustment) { |
| this->Ptr.MPT = MPT; |
| this->Ptr.RHS = RHS; |
| } |
| }; |
| |
| /// Expr - This represents one expression. Note that Expr's are subclasses of |
| /// Stmt. This allows an expression to be transparently used any place a Stmt |
| /// is required. |
| /// |
| class Expr : public Stmt { |
| QualType TR; |
| |
| protected: |
| Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK, |
| bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack) |
| : Stmt(SC) |
| { |
| ExprBits.TypeDependent = TD; |
| ExprBits.ValueDependent = VD; |
| ExprBits.InstantiationDependent = ID; |
| ExprBits.ValueKind = VK; |
| ExprBits.ObjectKind = OK; |
| ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; |
| setType(T); |
| } |
| |
| /// \brief Construct an empty expression. |
| explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { } |
| |
| public: |
| QualType getType() const { return TR; } |
| void setType(QualType t) { |
| // In C++, the type of an expression is always adjusted so that it |
| // will not have reference type (C++ [expr]p6). Use |
| // QualType::getNonReferenceType() to retrieve the non-reference |
| // type. Additionally, inspect Expr::isLvalue to determine whether |
| // an expression that is adjusted in this manner should be |
| // considered an lvalue. |
| assert((t.isNull() || !t->isReferenceType()) && |
| "Expressions can't have reference type"); |
| |
| TR = t; |
| } |
| |
| /// isValueDependent - Determines whether this expression is |
| /// value-dependent (C++ [temp.dep.constexpr]). For example, the |
| /// array bound of "Chars" in the following example is |
| /// value-dependent. |
| /// @code |
| /// template<int Size, char (&Chars)[Size]> struct meta_string; |
| /// @endcode |
| bool isValueDependent() const { return ExprBits.ValueDependent; } |
| |
| /// \brief Set whether this expression is value-dependent or not. |
| void setValueDependent(bool VD) { |
| ExprBits.ValueDependent = VD; |
| } |
| |
| /// isTypeDependent - Determines whether this expression is |
| /// type-dependent (C++ [temp.dep.expr]), which means that its type |
| /// could change from one template instantiation to the next. For |
| /// example, the expressions "x" and "x + y" are type-dependent in |
| /// the following code, but "y" is not type-dependent: |
| /// @code |
| /// template<typename T> |
| /// void add(T x, int y) { |
| /// x + y; |
| /// } |
| /// @endcode |
| bool isTypeDependent() const { return ExprBits.TypeDependent; } |
| |
| /// \brief Set whether this expression is type-dependent or not. |
| void setTypeDependent(bool TD) { |
| ExprBits.TypeDependent = TD; |
| } |
| |
| /// \brief Whether this expression is instantiation-dependent, meaning that |
| /// it depends in some way on a template parameter, even if neither its type |
| /// nor (constant) value can change due to the template instantiation. |
| /// |
| /// In the following example, the expression \c sizeof(sizeof(T() + T())) is |
| /// instantiation-dependent (since it involves a template parameter \c T), but |
| /// is neither type- nor value-dependent, since the type of the inner |
| /// \c sizeof is known (\c std::size_t) and therefore the size of the outer |
| /// \c sizeof is known. |
| /// |
| /// \code |
| /// template<typename T> |
| /// void f(T x, T y) { |
| /// sizeof(sizeof(T() + T()); |
| /// } |
| /// \endcode |
| /// |
| bool isInstantiationDependent() const { |
| return ExprBits.InstantiationDependent; |
| } |
| |
| /// \brief Set whether this expression is instantiation-dependent or not. |
| void setInstantiationDependent(bool ID) { |
| ExprBits.InstantiationDependent = ID; |
| } |
| |
| /// \brief Whether this expression contains an unexpanded parameter |
| /// pack (for C++11 variadic templates). |
| /// |
| /// Given the following function template: |
| /// |
| /// \code |
| /// template<typename F, typename ...Types> |
| /// void forward(const F &f, Types &&...args) { |
| /// f(static_cast<Types&&>(args)...); |
| /// } |
| /// \endcode |
| /// |
| /// The expressions \c args and \c static_cast<Types&&>(args) both |
| /// contain parameter packs. |
| bool containsUnexpandedParameterPack() const { |
| return ExprBits.ContainsUnexpandedParameterPack; |
| } |
| |
| /// \brief Set the bit that describes whether this expression |
| /// contains an unexpanded parameter pack. |
| void setContainsUnexpandedParameterPack(bool PP = true) { |
| ExprBits.ContainsUnexpandedParameterPack = PP; |
| } |
| |
| /// getExprLoc - Return the preferred location for the arrow when diagnosing |
| /// a problem with a generic expression. |
| SourceLocation getExprLoc() const LLVM_READONLY; |
| |
| /// isUnusedResultAWarning - Return true if this immediate expression should |
| /// be warned about if the result is unused. If so, fill in expr, location, |
| /// and ranges with expr to warn on and source locations/ranges appropriate |
| /// for a warning. |
| bool isUnusedResultAWarning(const Expr *&WarnExpr, SourceLocation &Loc, |
| SourceRange &R1, SourceRange &R2, |
| ASTContext &Ctx) const; |
| |
| /// isLValue - True if this expression is an "l-value" according to |
| /// the rules of the current language. C and C++ give somewhat |
| /// different rules for this concept, but in general, the result of |
| /// an l-value expression identifies a specific object whereas the |
| /// result of an r-value expression is a value detached from any |
| /// specific storage. |
| /// |
| /// C++11 divides the concept of "r-value" into pure r-values |
| /// ("pr-values") and so-called expiring values ("x-values"), which |
| /// identify specific objects that can be safely cannibalized for |
| /// their resources. This is an unfortunate abuse of terminology on |
| /// the part of the C++ committee. In Clang, when we say "r-value", |
| /// we generally mean a pr-value. |
| bool isLValue() const { return getValueKind() == VK_LValue; } |
| bool isRValue() const { return getValueKind() == VK_RValue; } |
| bool isXValue() const { return getValueKind() == VK_XValue; } |
| bool isGLValue() const { return getValueKind() != VK_RValue; } |
| |
| enum LValueClassification { |
| LV_Valid, |
| LV_NotObjectType, |
| LV_IncompleteVoidType, |
| LV_DuplicateVectorComponents, |
| LV_InvalidExpression, |
| LV_InvalidMessageExpression, |
| LV_MemberFunction, |
| LV_SubObjCPropertySetting, |
| LV_ClassTemporary, |
| LV_ArrayTemporary |
| }; |
| /// Reasons why an expression might not be an l-value. |
| LValueClassification ClassifyLValue(ASTContext &Ctx) const; |
| |
| enum isModifiableLvalueResult { |
| MLV_Valid, |
| MLV_NotObjectType, |
| MLV_IncompleteVoidType, |
| MLV_DuplicateVectorComponents, |
| MLV_InvalidExpression, |
| MLV_LValueCast, // Specialized form of MLV_InvalidExpression. |
| MLV_IncompleteType, |
| MLV_ConstQualified, |
| MLV_ConstAddrSpace, |
| MLV_ArrayType, |
| MLV_NoSetterProperty, |
| MLV_MemberFunction, |
| MLV_SubObjCPropertySetting, |
| MLV_InvalidMessageExpression, |
| MLV_ClassTemporary, |
| MLV_ArrayTemporary |
| }; |
| /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, |
| /// does not have an incomplete type, does not have a const-qualified type, |
| /// and if it is a structure or union, does not have any member (including, |
| /// recursively, any member or element of all contained aggregates or unions) |
| /// with a const-qualified type. |
| /// |
| /// \param Loc [in,out] - A source location which *may* be filled |
| /// in with the location of the expression making this a |
| /// non-modifiable lvalue, if specified. |
| isModifiableLvalueResult |
| isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = nullptr) const; |
| |
| /// \brief The return type of classify(). Represents the C++11 expression |
| /// taxonomy. |
| class Classification { |
| public: |
| /// \brief The various classification results. Most of these mean prvalue. |
| enum Kinds { |
| CL_LValue, |
| CL_XValue, |
| CL_Function, // Functions cannot be lvalues in C. |
| CL_Void, // Void cannot be an lvalue in C. |
| CL_AddressableVoid, // Void expression whose address can be taken in C. |
| CL_DuplicateVectorComponents, // A vector shuffle with dupes. |
| CL_MemberFunction, // An expression referring to a member function |
| CL_SubObjCPropertySetting, |
| CL_ClassTemporary, // A temporary of class type, or subobject thereof. |
| CL_ArrayTemporary, // A temporary of array type. |
| CL_ObjCMessageRValue, // ObjC message is an rvalue |
| CL_PRValue // A prvalue for any other reason, of any other type |
| }; |
| /// \brief The results of modification testing. |
| enum ModifiableType { |
| CM_Untested, // testModifiable was false. |
| CM_Modifiable, |
| CM_RValue, // Not modifiable because it's an rvalue |
| CM_Function, // Not modifiable because it's a function; C++ only |
| CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext |
| CM_NoSetterProperty,// Implicit assignment to ObjC property without setter |
| CM_ConstQualified, |
| CM_ConstAddrSpace, |
| CM_ArrayType, |
| CM_IncompleteType |
| }; |
| |
| private: |
| friend class Expr; |
| |
| unsigned short Kind; |
| unsigned short Modifiable; |
| |
| explicit Classification(Kinds k, ModifiableType m) |
| : Kind(k), Modifiable(m) |
| {} |
| |
| public: |
| Classification() {} |
| |
| Kinds getKind() const { return static_cast<Kinds>(Kind); } |
| ModifiableType getModifiable() const { |
| assert(Modifiable != CM_Untested && "Did not test for modifiability."); |
| return static_cast<ModifiableType>(Modifiable); |
| } |
| bool isLValue() const { return Kind == CL_LValue; } |
| bool isXValue() const { return Kind == CL_XValue; } |
| bool isGLValue() const { return Kind <= CL_XValue; } |
| bool isPRValue() const { return Kind >= CL_Function; } |
| bool isRValue() const { return Kind >= CL_XValue; } |
| bool isModifiable() const { return getModifiable() == CM_Modifiable; } |
| |
| /// \brief Create a simple, modifiably lvalue |
| static Classification makeSimpleLValue() { |
| return Classification(CL_LValue, CM_Modifiable); |
| } |
| |
| }; |
| /// \brief Classify - Classify this expression according to the C++11 |
| /// expression taxonomy. |
| /// |
| /// C++11 defines ([basic.lval]) a new taxonomy of expressions to replace the |
| /// old lvalue vs rvalue. This function determines the type of expression this |
| /// is. There are three expression types: |
| /// - lvalues are classical lvalues as in C++03. |
| /// - prvalues are equivalent to rvalues in C++03. |
| /// - xvalues are expressions yielding unnamed rvalue references, e.g. a |
| /// function returning an rvalue reference. |
| /// lvalues and xvalues are collectively referred to as glvalues, while |
| /// prvalues and xvalues together form rvalues. |
| Classification Classify(ASTContext &Ctx) const { |
| return ClassifyImpl(Ctx, nullptr); |
| } |
| |
| /// \brief ClassifyModifiable - Classify this expression according to the |
| /// C++11 expression taxonomy, and see if it is valid on the left side |
| /// of an assignment. |
| /// |
| /// This function extends classify in that it also tests whether the |
| /// expression is modifiable (C99 6.3.2.1p1). |
| /// \param Loc A source location that might be filled with a relevant location |
| /// if the expression is not modifiable. |
| Classification ClassifyModifiable(ASTContext &Ctx, SourceLocation &Loc) const{ |
| return ClassifyImpl(Ctx, &Loc); |
| } |
| |
| /// getValueKindForType - Given a formal return or parameter type, |
| /// give its value kind. |
| static ExprValueKind getValueKindForType(QualType T) { |
| if (const ReferenceType *RT = T->getAs<ReferenceType>()) |
| return (isa<LValueReferenceType>(RT) |
| ? VK_LValue |
| : (RT->getPointeeType()->isFunctionType() |
| ? VK_LValue : VK_XValue)); |
| return VK_RValue; |
| } |
| |
| /// getValueKind - The value kind that this expression produces. |
| ExprValueKind getValueKind() const { |
| return static_cast<ExprValueKind>(ExprBits.ValueKind); |
| } |
| |
| /// getObjectKind - The object kind that this expression produces. |
| /// Object kinds are meaningful only for expressions that yield an |
| /// l-value or x-value. |
| ExprObjectKind getObjectKind() const { |
| return static_cast<ExprObjectKind>(ExprBits.ObjectKind); |
| } |
| |
| bool isOrdinaryOrBitFieldObject() const { |
| ExprObjectKind OK = getObjectKind(); |
| return (OK == OK_Ordinary || OK == OK_BitField); |
| } |
| |
| /// setValueKind - Set the value kind produced by this expression. |
| void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; } |
| |
| /// setObjectKind - Set the object kind produced by this expression. |
| void setObjectKind(ExprObjectKind Cat) { ExprBits.ObjectKind = Cat; } |
| |
| private: |
| Classification ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const; |
| |
| public: |
| |
| /// \brief Returns true if this expression is a gl-value that |
| /// potentially refers to a bit-field. |
| /// |
| /// In C++, whether a gl-value refers to a bitfield is essentially |
| /// an aspect of the value-kind type system. |
| bool refersToBitField() const { return getObjectKind() == OK_BitField; } |
| |
| /// \brief If this expression refers to a bit-field, retrieve the |
| /// declaration of that bit-field. |
| /// |
| /// Note that this returns a non-null pointer in subtly different |
| /// places than refersToBitField returns true. In particular, this can |
| /// return a non-null pointer even for r-values loaded from |
| /// bit-fields, but it will return null for a conditional bit-field. |
| FieldDecl *getSourceBitField(); |
| |
| const FieldDecl *getSourceBitField() const { |
| return const_cast<Expr*>(this)->getSourceBitField(); |
| } |
| |
| /// \brief If this expression is an l-value for an Objective C |
| /// property, find the underlying property reference expression. |
| const ObjCPropertyRefExpr *getObjCProperty() const; |
| |
| /// \brief Check if this expression is the ObjC 'self' implicit parameter. |
| bool isObjCSelfExpr() const; |
| |
| /// \brief Returns whether this expression refers to a vector element. |
| bool refersToVectorElement() const; |
| |
| /// \brief Returns whether this expression refers to a global register |
| /// variable. |
| bool refersToGlobalRegisterVar() const; |
| |
| /// \brief Returns whether this expression has a placeholder type. |
| bool hasPlaceholderType() const { |
| return getType()->isPlaceholderType(); |
| } |
| |
| /// \brief Returns whether this expression has a specific placeholder type. |
| bool hasPlaceholderType(BuiltinType::Kind K) const { |
| assert(BuiltinType::isPlaceholderTypeKind(K)); |
| if (const BuiltinType *BT = dyn_cast<BuiltinType>(getType())) |
| return BT->getKind() == K; |
| return false; |
| } |
| |
| /// isKnownToHaveBooleanValue - Return true if this is an integer expression |
| /// that is known to return 0 or 1. This happens for _Bool/bool expressions |
| /// but also int expressions which are produced by things like comparisons in |
| /// C. |
| bool isKnownToHaveBooleanValue() const; |
| |
| /// isIntegerConstantExpr - Return true if this expression is a valid integer |
| /// constant expression, and, if so, return its value in Result. If not a |
| /// valid i-c-e, return false and fill in Loc (if specified) with the location |
| /// of the invalid expression. |
| /// |
| /// Note: This does not perform the implicit conversions required by C++11 |
| /// [expr.const]p5. |
| bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx, |
| SourceLocation *Loc = nullptr, |
| bool isEvaluated = true) const; |
| bool isIntegerConstantExpr(const ASTContext &Ctx, |
| SourceLocation *Loc = nullptr) const; |
| |
| /// isCXX98IntegralConstantExpr - Return true if this expression is an |
| /// integral constant expression in C++98. Can only be used in C++. |
| bool isCXX98IntegralConstantExpr(const ASTContext &Ctx) const; |
| |
| /// isCXX11ConstantExpr - Return true if this expression is a constant |
| /// expression in C++11. Can only be used in C++. |
| /// |
| /// Note: This does not perform the implicit conversions required by C++11 |
| /// [expr.const]p5. |
| bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = nullptr, |
| SourceLocation *Loc = nullptr) const; |
| |
| /// isPotentialConstantExpr - Return true if this function's definition |
| /// might be usable in a constant expression in C++11, if it were marked |
| /// constexpr. Return false if the function can never produce a constant |
| /// expression, along with diagnostics describing why not. |
| static bool isPotentialConstantExpr(const FunctionDecl *FD, |
| SmallVectorImpl< |
| PartialDiagnosticAt> &Diags); |
| |
| /// isPotentialConstantExprUnevaluted - Return true if this expression might |
| /// be usable in a constant expression in C++11 in an unevaluated context, if |
| /// it were in function FD marked constexpr. Return false if the function can |
| /// never produce a constant expression, along with diagnostics describing |
| /// why not. |
| static bool isPotentialConstantExprUnevaluated(Expr *E, |
| const FunctionDecl *FD, |
| SmallVectorImpl< |
| PartialDiagnosticAt> &Diags); |
| |
| /// isConstantInitializer - Returns true if this expression can be emitted to |
| /// IR as a constant, and thus can be used as a constant initializer in C. |
| /// If this expression is not constant and Culprit is non-null, |
| /// it is used to store the address of first non constant expr. |
| bool isConstantInitializer(ASTContext &Ctx, bool ForRef, |
| const Expr **Culprit = nullptr) const; |
| |
| /// EvalStatus is a struct with detailed info about an evaluation in progress. |
| struct EvalStatus { |
| /// \brief Whether the evaluated expression has side effects. |
| /// For example, (f() && 0) can be folded, but it still has side effects. |
| bool HasSideEffects; |
| |
| /// \brief Whether the evaluation hit undefined behavior. |
| /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior. |
| /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB. |
| bool HasUndefinedBehavior; |
| |
| /// Diag - If this is non-null, it will be filled in with a stack of notes |
| /// indicating why evaluation failed (or why it failed to produce a constant |
| /// expression). |
| /// If the expression is unfoldable, the notes will indicate why it's not |
| /// foldable. If the expression is foldable, but not a constant expression, |
| /// the notes will describes why it isn't a constant expression. If the |
| /// expression *is* a constant expression, no notes will be produced. |
| SmallVectorImpl<PartialDiagnosticAt> *Diag; |
| |
| EvalStatus() |
| : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {} |
| |
| // hasSideEffects - Return true if the evaluated expression has |
| // side effects. |
| bool hasSideEffects() const { |
| return HasSideEffects; |
| } |
| }; |
| |
| /// EvalResult is a struct with detailed info about an evaluated expression. |
| struct EvalResult : EvalStatus { |
| /// Val - This is the value the expression can be folded to. |
| APValue Val; |
| |
| // isGlobalLValue - Return true if the evaluated lvalue expression |
| // is global. |
| bool isGlobalLValue() const; |
| }; |
| |
| /// EvaluateAsRValue - Return true if this is a constant which we can fold to |
| /// an rvalue using any crazy technique (that has nothing to do with language |
| /// standards) that we want to, even if the expression has side-effects. If |
| /// this function returns true, it returns the folded constant in Result. If |
| /// the expression is a glvalue, an lvalue-to-rvalue conversion will be |
| /// applied. |
| bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const; |
| |
| /// EvaluateAsBooleanCondition - Return true if this is a constant |
| /// which we we can fold and convert to a boolean condition using |
| /// any crazy technique that we want to, even if the expression has |
| /// side-effects. |
| bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const; |
| |
| enum SideEffectsKind { |
| SE_NoSideEffects, ///< Strictly evaluate the expression. |
| SE_AllowUndefinedBehavior, ///< Allow UB that we can give a value, but not |
| ///< arbitrary unmodeled side effects. |
| SE_AllowSideEffects ///< Allow any unmodeled side effect. |
| }; |
| |
| /// EvaluateAsInt - Return true if this is a constant which we can fold and |
| /// convert to an integer, using any crazy technique that we want to. |
| bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, |
| SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; |
| |
| /// EvaluateAsFloat - Return true if this is a constant which we can fold and |
| /// convert to a floating point value, using any crazy technique that we |
| /// want to. |
| bool |
| EvaluateAsFloat(llvm::APFloat &Result, const ASTContext &Ctx, |
| SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; |
| |
| /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be |
| /// constant folded without side-effects, but discard the result. |
| bool isEvaluatable(const ASTContext &Ctx, |
| SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; |
| |
| /// HasSideEffects - This routine returns true for all those expressions |
| /// which have any effect other than producing a value. Example is a function |
| /// call, volatile variable read, or throwing an exception. If |
| /// IncludePossibleEffects is false, this call treats certain expressions with |
| /// potential side effects (such as function call-like expressions, |
| /// instantiation-dependent expressions, or invocations from a macro) as not |
| /// having side effects. |
| bool HasSideEffects(const ASTContext &Ctx, |
| bool IncludePossibleEffects = true) const; |
| |
| /// \brief Determine whether this expression involves a call to any function |
| /// that is not trivial. |
| bool hasNonTrivialCall(const ASTContext &Ctx) const; |
| |
| /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded |
| /// integer. This must be called on an expression that constant folds to an |
| /// integer. |
| llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, |
| SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const; |
| |
| void EvaluateForOverflow(const ASTContext &Ctx) const; |
| |
| /// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an |
| /// lvalue with link time known address, with no side-effects. |
| bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const; |
| |
| /// EvaluateAsInitializer - Evaluate an expression as if it were the |
| /// initializer of the given declaration. Returns true if the initializer |
| /// can be folded to a constant, and produces any relevant notes. In C++11, |
| /// notes will be produced if the expression is not a constant expression. |
| bool EvaluateAsInitializer(APValue &Result, const ASTContext &Ctx, |
| const VarDecl *VD, |
| SmallVectorImpl<PartialDiagnosticAt> &Notes) const; |
| |
| /// EvaluateWithSubstitution - Evaluate an expression as if from the context |
| /// of a call to the given function with the given arguments, inside an |
| /// unevaluated context. Returns true if the expression could be folded to a |
| /// constant. |
| bool EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx, |
| const FunctionDecl *Callee, |
| ArrayRef<const Expr*> Args) const; |
| |
| /// \brief If the current Expr is a pointer, this will try to statically |
| /// determine the number of bytes available where the pointer is pointing. |
| /// Returns true if all of the above holds and we were able to figure out the |
| /// size, false otherwise. |
| /// |
| /// \param Type - How to evaluate the size of the Expr, as defined by the |
| /// "type" parameter of __builtin_object_size |
| bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, |
| unsigned Type) const; |
| |
| /// \brief Enumeration used to describe the kind of Null pointer constant |
| /// returned from \c isNullPointerConstant(). |
| enum NullPointerConstantKind { |
| /// \brief Expression is not a Null pointer constant. |
| NPCK_NotNull = 0, |
| |
| /// \brief Expression is a Null pointer constant built from a zero integer |
| /// expression that is not a simple, possibly parenthesized, zero literal. |
| /// C++ Core Issue 903 will classify these expressions as "not pointers" |
| /// once it is adopted. |
| /// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903 |
| NPCK_ZeroExpression, |
| |
| /// \brief Expression is a Null pointer constant built from a literal zero. |
| NPCK_ZeroLiteral, |
| |
| /// \brief Expression is a C++11 nullptr. |
| NPCK_CXX11_nullptr, |
| |
| /// \brief Expression is a GNU-style __null constant. |
| NPCK_GNUNull |
| }; |
| |
| /// \brief Enumeration used to describe how \c isNullPointerConstant() |
| /// should cope with value-dependent expressions. |
| enum NullPointerConstantValueDependence { |
| /// \brief Specifies that the expression should never be value-dependent. |
| NPC_NeverValueDependent = 0, |
| |
| /// \brief Specifies that a value-dependent expression of integral or |
| /// dependent type should be considered a null pointer constant. |
| NPC_ValueDependentIsNull, |
| |
| /// \brief Specifies that a value-dependent expression should be considered |
| /// to never be a null pointer constant. |
| NPC_ValueDependentIsNotNull |
| }; |
| |
| /// isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to |
| /// a Null pointer constant. The return value can further distinguish the |
| /// kind of NULL pointer constant that was detected. |
| NullPointerConstantKind isNullPointerConstant( |
| ASTContext &Ctx, |
| NullPointerConstantValueDependence NPC) const; |
| |
| /// isOBJCGCCandidate - Return true if this expression may be used in a read/ |
| /// write barrier. |
| bool isOBJCGCCandidate(ASTContext &Ctx) const; |
| |
| /// \brief Returns true if this expression is a bound member function. |
| bool isBoundMemberFunction(ASTContext &Ctx) const; |
| |
| /// \brief Given an expression of bound-member type, find the type |
| /// of the member. Returns null if this is an *overloaded* bound |
| /// member expression. |
| static QualType findBoundMemberType(const Expr *expr); |
| |
| /// IgnoreImpCasts - Skip past any implicit casts which might |
| /// surround this expression. Only skips ImplicitCastExprs. |
| Expr *IgnoreImpCasts() LLVM_READONLY; |
| |
| /// IgnoreImplicit - Skip past any implicit AST nodes which might |
| /// surround this expression. |
| Expr *IgnoreImplicit() LLVM_READONLY { |
| return cast<Expr>(Stmt::IgnoreImplicit()); |
| } |
| |
| const Expr *IgnoreImplicit() const LLVM_READONLY { |
| return const_cast<Expr*>(this)->IgnoreImplicit(); |
| } |
| |
| /// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return |
| /// its subexpression. If that subexpression is also a ParenExpr, |
| /// then this method recursively returns its subexpression, and so forth. |
| /// Otherwise, the method returns the current Expr. |
| Expr *IgnoreParens() LLVM_READONLY; |
| |
| /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr |
| /// or CastExprs, returning their operand. |
| Expr *IgnoreParenCasts() LLVM_READONLY; |
| |
| /// Ignore casts. Strip off any CastExprs, returning their operand. |
| Expr *IgnoreCasts() LLVM_READONLY; |
| |
| /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off |
| /// any ParenExpr or ImplicitCastExprs, returning their operand. |
| Expr *IgnoreParenImpCasts() LLVM_READONLY; |
| |
| /// IgnoreConversionOperator - Ignore conversion operator. If this Expr is a |
| /// call to a conversion operator, return the argument. |
| Expr *IgnoreConversionOperator() LLVM_READONLY; |
| |
| const Expr *IgnoreConversionOperator() const LLVM_READONLY { |
| return const_cast<Expr*>(this)->IgnoreConversionOperator(); |
| } |
| |
| const Expr *IgnoreParenImpCasts() const LLVM_READONLY { |
| return const_cast<Expr*>(this)->IgnoreParenImpCasts(); |
| } |
| |
| /// Ignore parentheses and lvalue casts. Strip off any ParenExpr and |
| /// CastExprs that represent lvalue casts, returning their operand. |
| Expr *IgnoreParenLValueCasts() LLVM_READONLY; |
| |
| const Expr *IgnoreParenLValueCasts() const LLVM_READONLY { |
| return const_cast<Expr*>(this)->IgnoreParenLValueCasts(); |
| } |
| |
| /// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the |
| /// value (including ptr->int casts of the same size). Strip off any |
| /// ParenExpr or CastExprs, returning their operand. |
| Expr *IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY; |
| |
| /// Ignore parentheses and derived-to-base casts. |
| Expr *ignoreParenBaseCasts() LLVM_READONLY; |
| |
| const Expr *ignoreParenBaseCasts() const LLVM_READONLY { |
| return const_cast<Expr*>(this)->ignoreParenBaseCasts(); |
| } |
| |
| /// \brief Determine whether this expression is a default function argument. |
| /// |
| /// Default arguments are implicitly generated in the abstract syntax tree |
| /// by semantic analysis for function calls, object constructions, etc. in |
| /// C++. Default arguments are represented by \c CXXDefaultArgExpr nodes; |
| /// this routine also looks through any implicit casts to determine whether |
| /// the expression is a default argument. |
| bool isDefaultArgument() const; |
| |
| /// \brief Determine whether the result of this expression is a |
| /// temporary object of the given class type. |
| bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const; |
| |
| /// \brief Whether this expression is an implicit reference to 'this' in C++. |
| bool isImplicitCXXThis() const; |
| |
| const Expr *IgnoreImpCasts() const LLVM_READONLY { |
| return const_cast<Expr*>(this)->IgnoreImpCasts(); |
| } |
| const Expr *IgnoreParens() const LLVM_READONLY { |
| return const_cast<Expr*>(this)->IgnoreParens(); |
| } |
| const Expr *IgnoreParenCasts() const LLVM_READONLY { |
| return const_cast<Expr*>(this)->IgnoreParenCasts(); |
| } |
| /// Strip off casts, but keep parentheses. |
| const Expr *IgnoreCasts() const LLVM_READONLY { |
| return const_cast<Expr*>(this)->IgnoreCasts(); |
| } |
| |
| const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY { |
| return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx); |
| } |
| |
| static bool hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs); |
| |
| /// \brief For an expression of class type or pointer to class type, |
| /// return the most derived class decl the expression is known to refer to. |
| /// |
| /// If this expression is a cast, this method looks through it to find the |
| /// most derived decl that can be inferred from the expression. |
| /// This is valid because derived-to-base conversions have undefined |
| /// behavior if the object isn't dynamically of the derived type. |
| const CXXRecordDecl *getBestDynamicClassType() const; |
| |
| /// Walk outwards from an expression we want to bind a reference to and |
| /// find the expression whose lifetime needs to be extended. Record |
| /// the LHSs of comma expressions and adjustments needed along the path. |
| const Expr *skipRValueSubobjectAdjustments( |
| SmallVectorImpl<const Expr *> &CommaLHS, |
| SmallVectorImpl<SubobjectAdjustment> &Adjustments) const; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() >= firstExprConstant && |
| T->getStmtClass() <= lastExprConstant; |
| } |
| }; |
| |
| //===----------------------------------------------------------------------===// |
| // Primary Expressions. |
| //===----------------------------------------------------------------------===// |
| |
| /// OpaqueValueExpr - An expression referring to an opaque object of a |
| /// fixed type and value class. These don't correspond to concrete |
| /// syntax; instead they're used to express operations (usually copy |
| /// operations) on values whose source is generally obvious from |
| /// context. |
| class OpaqueValueExpr : public Expr { |
| friend class ASTStmtReader; |
| Expr *SourceExpr; |
| SourceLocation Loc; |
| |
| public: |
| OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, |
| ExprObjectKind OK = OK_Ordinary, |
| Expr *SourceExpr = nullptr) |
| : Expr(OpaqueValueExprClass, T, VK, OK, |
| T->isDependentType() || |
| (SourceExpr && SourceExpr->isTypeDependent()), |
| T->isDependentType() || |
| (SourceExpr && SourceExpr->isValueDependent()), |
| T->isInstantiationDependentType() || |
| (SourceExpr && SourceExpr->isInstantiationDependent()), |
| false), |
| SourceExpr(SourceExpr), Loc(Loc) { |
| } |
| |
| /// Given an expression which invokes a copy constructor --- i.e. a |
| /// CXXConstructExpr, possibly wrapped in an ExprWithCleanups --- |
| /// find the OpaqueValueExpr that's the source of the construction. |
| static const OpaqueValueExpr *findInCopyConstruct(const Expr *expr); |
| |
| explicit OpaqueValueExpr(EmptyShell Empty) |
| : Expr(OpaqueValueExprClass, Empty) { } |
| |
| /// \brief Retrieve the location of this expression. |
| SourceLocation getLocation() const { return Loc; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { |
| return SourceExpr ? SourceExpr->getLocStart() : Loc; |
| } |
| SourceLocation getLocEnd() const LLVM_READONLY { |
| return SourceExpr ? SourceExpr->getLocEnd() : Loc; |
| } |
| SourceLocation getExprLoc() const LLVM_READONLY { |
| if (SourceExpr) return SourceExpr->getExprLoc(); |
| return Loc; |
| } |
| |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| /// The source expression of an opaque value expression is the |
| /// expression which originally generated the value. This is |
| /// provided as a convenience for analyses that don't wish to |
| /// precisely model the execution behavior of the program. |
| /// |
| /// The source expression is typically set when building the |
| /// expression which binds the opaque value expression in the first |
| /// place. |
| Expr *getSourceExpr() const { return SourceExpr; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == OpaqueValueExprClass; |
| } |
| }; |
| |
| /// \brief A reference to a declared variable, function, enum, etc. |
| /// [C99 6.5.1p2] |
| /// |
| /// This encodes all the information about how a declaration is referenced |
| /// within an expression. |
| /// |
| /// There are several optional constructs attached to DeclRefExprs only when |
| /// they apply in order to conserve memory. These are laid out past the end of |
| /// the object, and flags in the DeclRefExprBitfield track whether they exist: |
| /// |
| /// DeclRefExprBits.HasQualifier: |
| /// Specifies when this declaration reference expression has a C++ |
| /// nested-name-specifier. |
| /// DeclRefExprBits.HasFoundDecl: |
| /// Specifies when this declaration reference expression has a record of |
| /// a NamedDecl (different from the referenced ValueDecl) which was found |
| /// during name lookup and/or overload resolution. |
| /// DeclRefExprBits.HasTemplateKWAndArgsInfo: |
| /// Specifies when this declaration reference expression has an explicit |
| /// C++ template keyword and/or template argument list. |
| /// DeclRefExprBits.RefersToEnclosingVariableOrCapture |
| /// Specifies when this declaration reference expression (validly) |
| /// refers to an enclosed local or a captured variable. |
| class DeclRefExpr final |
| : public Expr, |
| private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc, |
| NamedDecl *, ASTTemplateKWAndArgsInfo, |
| TemplateArgumentLoc> { |
| /// \brief The declaration that we are referencing. |
| ValueDecl *D; |
| |
| /// \brief The location of the declaration name itself. |
| SourceLocation Loc; |
| |
| /// \brief Provides source/type location info for the declaration name |
| /// embedded in D. |
| DeclarationNameLoc DNLoc; |
| |
| size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const { |
| return hasQualifier() ? 1 : 0; |
| } |
| |
| size_t numTrailingObjects(OverloadToken<NamedDecl *>) const { |
| return hasFoundDecl() ? 1 : 0; |
| } |
| |
| size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { |
| return hasTemplateKWAndArgsInfo() ? 1 : 0; |
| } |
| |
| /// \brief Test whether there is a distinct FoundDecl attached to the end of |
| /// this DRE. |
| bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; } |
| |
| DeclRefExpr(const ASTContext &Ctx, |
| NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, |
| ValueDecl *D, bool RefersToEnlosingVariableOrCapture, |
| const DeclarationNameInfo &NameInfo, |
| NamedDecl *FoundD, |
| const TemplateArgumentListInfo *TemplateArgs, |
| QualType T, ExprValueKind VK); |
| |
| /// \brief Construct an empty declaration reference expression. |
| explicit DeclRefExpr(EmptyShell Empty) |
| : Expr(DeclRefExprClass, Empty) { } |
| |
| /// \brief Computes the type- and value-dependence flags for this |
| /// declaration reference expression. |
| void computeDependence(const ASTContext &C); |
| |
| public: |
| DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T, |
| ExprValueKind VK, SourceLocation L, |
| const DeclarationNameLoc &LocInfo = DeclarationNameLoc()) |
| : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), |
| D(D), Loc(L), DNLoc(LocInfo) { |
| DeclRefExprBits.HasQualifier = 0; |
| DeclRefExprBits.HasTemplateKWAndArgsInfo = 0; |
| DeclRefExprBits.HasFoundDecl = 0; |
| DeclRefExprBits.HadMultipleCandidates = 0; |
| DeclRefExprBits.RefersToEnclosingVariableOrCapture = |
| RefersToEnclosingVariableOrCapture; |
| computeDependence(D->getASTContext()); |
| } |
| |
| static DeclRefExpr * |
| Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, ValueDecl *D, |
| bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, |
| QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr, |
| const TemplateArgumentListInfo *TemplateArgs = nullptr); |
| |
| static DeclRefExpr * |
| Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, ValueDecl *D, |
| bool RefersToEnclosingVariableOrCapture, |
| const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, |
| NamedDecl *FoundD = nullptr, |
| const TemplateArgumentListInfo *TemplateArgs = nullptr); |
| |
| /// \brief Construct an empty declaration reference expression. |
| static DeclRefExpr *CreateEmpty(const ASTContext &Context, |
| bool HasQualifier, |
| bool HasFoundDecl, |
| bool HasTemplateKWAndArgsInfo, |
| unsigned NumTemplateArgs); |
| |
| ValueDecl *getDecl() { return D; } |
| const ValueDecl *getDecl() const { return D; } |
| void setDecl(ValueDecl *NewD) { D = NewD; } |
| |
| DeclarationNameInfo getNameInfo() const { |
| return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc); |
| } |
| |
| SourceLocation getLocation() const { return Loc; } |
| void setLocation(SourceLocation L) { Loc = L; } |
| SourceLocation getLocStart() const LLVM_READONLY; |
| SourceLocation getLocEnd() const LLVM_READONLY; |
| |
| /// \brief Determine whether this declaration reference was preceded by a |
| /// C++ nested-name-specifier, e.g., \c N::foo. |
| bool hasQualifier() const { return DeclRefExprBits.HasQualifier; } |
| |
| /// \brief If the name was qualified, retrieves the nested-name-specifier |
| /// that precedes the name, with source-location information. |
| NestedNameSpecifierLoc getQualifierLoc() const { |
| if (!hasQualifier()) |
| return NestedNameSpecifierLoc(); |
| return *getTrailingObjects<NestedNameSpecifierLoc>(); |
| } |
| |
| /// \brief If the name was qualified, retrieves the nested-name-specifier |
| /// that precedes the name. Otherwise, returns NULL. |
| NestedNameSpecifier *getQualifier() const { |
| return getQualifierLoc().getNestedNameSpecifier(); |
| } |
| |
| /// \brief Get the NamedDecl through which this reference occurred. |
| /// |
| /// This Decl may be different from the ValueDecl actually referred to in the |
| /// presence of using declarations, etc. It always returns non-NULL, and may |
| /// simple return the ValueDecl when appropriate. |
| |
| NamedDecl *getFoundDecl() { |
| return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D; |
| } |
| |
| /// \brief Get the NamedDecl through which this reference occurred. |
| /// See non-const variant. |
| const NamedDecl *getFoundDecl() const { |
| return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D; |
| } |
| |
| bool hasTemplateKWAndArgsInfo() const { |
| return DeclRefExprBits.HasTemplateKWAndArgsInfo; |
| } |
| |
| /// \brief Retrieve the location of the template keyword preceding |
| /// this name, if any. |
| SourceLocation getTemplateKeywordLoc() const { |
| if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; |
| } |
| |
| /// \brief Retrieve the location of the left angle bracket starting the |
| /// explicit template argument list following the name, if any. |
| SourceLocation getLAngleLoc() const { |
| if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; |
| } |
| |
| /// \brief Retrieve the location of the right angle bracket ending the |
| /// explicit template argument list following the name, if any. |
| SourceLocation getRAngleLoc() const { |
| if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; |
| } |
| |
| /// \brief Determines whether the name in this declaration reference |
| /// was preceded by the template keyword. |
| bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } |
| |
| /// \brief Determines whether this declaration reference was followed by an |
| /// explicit template argument list. |
| bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } |
| |
| /// \brief Copies the template arguments (if present) into the given |
| /// structure. |
| void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { |
| if (hasExplicitTemplateArgs()) |
| getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( |
| getTrailingObjects<TemplateArgumentLoc>(), List); |
| } |
| |
| /// \brief Retrieve the template arguments provided as part of this |
| /// template-id. |
| const TemplateArgumentLoc *getTemplateArgs() const { |
| if (!hasExplicitTemplateArgs()) |
| return nullptr; |
| |
| return getTrailingObjects<TemplateArgumentLoc>(); |
| } |
| |
| /// \brief Retrieve the number of template arguments provided as part of this |
| /// template-id. |
| unsigned getNumTemplateArgs() const { |
| if (!hasExplicitTemplateArgs()) |
| return 0; |
| |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; |
| } |
| |
| ArrayRef<TemplateArgumentLoc> template_arguments() const { |
| return {getTemplateArgs(), getNumTemplateArgs()}; |
| } |
| |
| /// \brief Returns true if this expression refers to a function that |
| /// was resolved from an overloaded set having size greater than 1. |
| bool hadMultipleCandidates() const { |
| return DeclRefExprBits.HadMultipleCandidates; |
| } |
| /// \brief Sets the flag telling whether this expression refers to |
| /// a function that was resolved from an overloaded set having size |
| /// greater than 1. |
| void setHadMultipleCandidates(bool V = true) { |
| DeclRefExprBits.HadMultipleCandidates = V; |
| } |
| |
| /// \brief Does this DeclRefExpr refer to an enclosing local or a captured |
| /// variable? |
| bool refersToEnclosingVariableOrCapture() const { |
| return DeclRefExprBits.RefersToEnclosingVariableOrCapture; |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == DeclRefExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| friend TrailingObjects; |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| }; |
| |
| /// \brief [C99 6.4.2.2] - A predefined identifier such as __func__. |
| class PredefinedExpr : public Expr { |
| public: |
| enum IdentType { |
| Func, |
| Function, |
| LFunction, // Same as Function, but as wide string. |
| FuncDName, |
| FuncSig, |
| PrettyFunction, |
| /// \brief The same as PrettyFunction, except that the |
| /// 'virtual' keyword is omitted for virtual member functions. |
| PrettyFunctionNoVirtual |
| }; |
| |
| private: |
| SourceLocation Loc; |
| IdentType Type; |
| Stmt *FnName; |
| |
| public: |
| PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, |
| StringLiteral *SL); |
| |
| /// \brief Construct an empty predefined expression. |
| explicit PredefinedExpr(EmptyShell Empty) |
| : Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {} |
| |
| IdentType getIdentType() const { return Type; } |
| |
| SourceLocation getLocation() const { return Loc; } |
| void setLocation(SourceLocation L) { Loc = L; } |
| |
| StringLiteral *getFunctionName(); |
| const StringLiteral *getFunctionName() const { |
| return const_cast<PredefinedExpr *>(this)->getFunctionName(); |
| } |
| |
| static StringRef getIdentTypeName(IdentType IT); |
| static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Loc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == PredefinedExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&FnName, &FnName + 1); } |
| |
| friend class ASTStmtReader; |
| }; |
| |
| /// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without |
| /// leaking memory. |
| /// |
| /// For large floats/integers, APFloat/APInt will allocate memory from the heap |
| /// to represent these numbers. Unfortunately, when we use a BumpPtrAllocator |
| /// to allocate IntegerLiteral/FloatingLiteral nodes the memory associated with |
| /// the APFloat/APInt values will never get freed. APNumericStorage uses |
| /// ASTContext's allocator for memory allocation. |
| class APNumericStorage { |
| union { |
| uint64_t VAL; ///< Used to store the <= 64 bits integer value. |
| uint64_t *pVal; ///< Used to store the >64 bits integer value. |
| }; |
| unsigned BitWidth; |
| |
| bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; } |
| |
| APNumericStorage(const APNumericStorage &) = delete; |
| void operator=(const APNumericStorage &) = delete; |
| |
| protected: |
| APNumericStorage() : VAL(0), BitWidth(0) { } |
| |
| llvm::APInt getIntValue() const { |
| unsigned NumWords = llvm::APInt::getNumWords(BitWidth); |
| if (NumWords > 1) |
| return llvm::APInt(BitWidth, NumWords, pVal); |
| else |
| return llvm::APInt(BitWidth, VAL); |
| } |
| void setIntValue(const ASTContext &C, const llvm::APInt &Val); |
| }; |
| |
| class APIntStorage : private APNumericStorage { |
| public: |
| llvm::APInt getValue() const { return getIntValue(); } |
| void setValue(const ASTContext &C, const llvm::APInt &Val) { |
| setIntValue(C, Val); |
| } |
| }; |
| |
| class APFloatStorage : private APNumericStorage { |
| public: |
| llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const { |
| return llvm::APFloat(Semantics, getIntValue()); |
| } |
| void setValue(const ASTContext &C, const llvm::APFloat &Val) { |
| setIntValue(C, Val.bitcastToAPInt()); |
| } |
| }; |
| |
| class IntegerLiteral : public Expr, public APIntStorage { |
| SourceLocation Loc; |
| |
| /// \brief Construct an empty integer literal. |
| explicit IntegerLiteral(EmptyShell Empty) |
| : Expr(IntegerLiteralClass, Empty) { } |
| |
| public: |
| // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, |
| // or UnsignedLongLongTy |
| IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type, |
| SourceLocation l); |
| |
| /// \brief Returns a new integer literal with value 'V' and type 'type'. |
| /// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy, |
| /// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V |
| /// \param V - the value that the returned integer literal contains. |
| static IntegerLiteral *Create(const ASTContext &C, const llvm::APInt &V, |
| QualType type, SourceLocation l); |
| /// \brief Returns a new empty integer literal. |
| static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty); |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Loc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } |
| |
| /// \brief Retrieve the location of the literal. |
| SourceLocation getLocation() const { return Loc; } |
| |
| void setLocation(SourceLocation Location) { Loc = Location; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == IntegerLiteralClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| }; |
| |
| class CharacterLiteral : public Expr { |
| public: |
| enum CharacterKind { |
| Ascii, |
| Wide, |
| UTF8, |
| UTF16, |
| UTF32 |
| }; |
| |
| private: |
| unsigned Value; |
| SourceLocation Loc; |
| public: |
| // type should be IntTy |
| CharacterLiteral(unsigned value, CharacterKind kind, QualType type, |
| SourceLocation l) |
| : Expr(CharacterLiteralClass, type, VK_RValue, OK_Ordinary, false, false, |
| false, false), |
| Value(value), Loc(l) { |
| CharacterLiteralBits.Kind = kind; |
| } |
| |
| /// \brief Construct an empty character literal. |
| CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { } |
| |
| SourceLocation getLocation() const { return Loc; } |
| CharacterKind getKind() const { |
| return static_cast<CharacterKind>(CharacterLiteralBits.Kind); |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Loc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } |
| |
| unsigned getValue() const { return Value; } |
| |
| void setLocation(SourceLocation Location) { Loc = Location; } |
| void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; } |
| void setValue(unsigned Val) { Value = Val; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CharacterLiteralClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| }; |
| |
| class FloatingLiteral : public Expr, private APFloatStorage { |
| SourceLocation Loc; |
| |
| FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact, |
| QualType Type, SourceLocation L); |
| |
| /// \brief Construct an empty floating-point literal. |
| explicit FloatingLiteral(const ASTContext &C, EmptyShell Empty); |
| |
| public: |
| static FloatingLiteral *Create(const ASTContext &C, const llvm::APFloat &V, |
| bool isexact, QualType Type, SourceLocation L); |
| static FloatingLiteral *Create(const ASTContext &C, EmptyShell Empty); |
| |
| llvm::APFloat getValue() const { |
| return APFloatStorage::getValue(getSemantics()); |
| } |
| void setValue(const ASTContext &C, const llvm::APFloat &Val) { |
| assert(&getSemantics() == &Val.getSemantics() && "Inconsistent semantics"); |
| APFloatStorage::setValue(C, Val); |
| } |
| |
| /// Get a raw enumeration value representing the floating-point semantics of |
| /// this literal (32-bit IEEE, x87, ...), suitable for serialisation. |
| APFloatSemantics getRawSemantics() const { |
| return static_cast<APFloatSemantics>(FloatingLiteralBits.Semantics); |
| } |
| |
| /// Set the raw enumeration value representing the floating-point semantics of |
| /// this literal (32-bit IEEE, x87, ...), suitable for serialisation. |
| void setRawSemantics(APFloatSemantics Sem) { |
| FloatingLiteralBits.Semantics = Sem; |
| } |
| |
| /// Return the APFloat semantics this literal uses. |
| const llvm::fltSemantics &getSemantics() const; |
| |
| /// Set the APFloat semantics this literal uses. |
| void setSemantics(const llvm::fltSemantics &Sem); |
| |
| bool isExact() const { return FloatingLiteralBits.IsExact; } |
| void setExact(bool E) { FloatingLiteralBits.IsExact = E; } |
| |
| /// getValueAsApproximateDouble - This returns the value as an inaccurate |
| /// double. Note that this may cause loss of precision, but is useful for |
| /// debugging dumps, etc. |
| double getValueAsApproximateDouble() const; |
| |
| SourceLocation getLocation() const { return Loc; } |
| void setLocation(SourceLocation L) { Loc = L; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Loc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == FloatingLiteralClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| }; |
| |
| /// ImaginaryLiteral - We support imaginary integer and floating point literals, |
| /// like "1.0i". We represent these as a wrapper around FloatingLiteral and |
| /// IntegerLiteral classes. Instances of this class always have a Complex type |
| /// whose element type matches the subexpression. |
| /// |
| class ImaginaryLiteral : public Expr { |
| Stmt *Val; |
| public: |
| ImaginaryLiteral(Expr *val, QualType Ty) |
| : Expr(ImaginaryLiteralClass, Ty, VK_RValue, OK_Ordinary, false, false, |
| false, false), |
| Val(val) {} |
| |
| /// \brief Build an empty imaginary literal. |
| explicit ImaginaryLiteral(EmptyShell Empty) |
| : Expr(ImaginaryLiteralClass, Empty) { } |
| |
| const Expr *getSubExpr() const { return cast<Expr>(Val); } |
| Expr *getSubExpr() { return cast<Expr>(Val); } |
| void setSubExpr(Expr *E) { Val = E; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return Val->getLocStart(); } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Val->getLocEnd(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ImaginaryLiteralClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Val, &Val+1); } |
| }; |
| |
| /// StringLiteral - This represents a string literal expression, e.g. "foo" |
| /// or L"bar" (wide strings). The actual string is returned by getBytes() |
| /// is NOT null-terminated, and the length of the string is determined by |
| /// calling getByteLength(). The C type for a string is always a |
| /// ConstantArrayType. In C++, the char type is const qualified, in C it is |
| /// not. |
| /// |
| /// Note that strings in C can be formed by concatenation of multiple string |
| /// literal pptokens in translation phase #6. This keeps track of the locations |
| /// of each of these pieces. |
| /// |
| /// Strings in C can also be truncated and extended by assigning into arrays, |
| /// e.g. with constructs like: |
| /// char X[2] = "foobar"; |
| /// In this case, getByteLength() will return 6, but the string literal will |
| /// have type "char[2]". |
| class StringLiteral : public Expr { |
| public: |
| enum StringKind { |
| Ascii, |
| Wide, |
| UTF8, |
| UTF16, |
| UTF32 |
| }; |
| |
| private: |
| friend class ASTStmtReader; |
| |
| union { |
| const char *asChar; |
| const uint16_t *asUInt16; |
| const uint32_t *asUInt32; |
| } StrData; |
| unsigned Length; |
| unsigned CharByteWidth : 4; |
| unsigned Kind : 3; |
| unsigned IsPascal : 1; |
| unsigned NumConcatenated; |
| SourceLocation TokLocs[1]; |
| |
| StringLiteral(QualType Ty) : |
| Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false, |
| false) {} |
| |
| static int mapCharByteWidth(TargetInfo const &target,StringKind k); |
| |
| public: |
| /// This is the "fully general" constructor that allows representation of |
| /// strings formed from multiple concatenated tokens. |
| static StringLiteral *Create(const ASTContext &C, StringRef Str, |
| StringKind Kind, bool Pascal, QualType Ty, |
| const SourceLocation *Loc, unsigned NumStrs); |
| |
| /// Simple constructor for string literals made from one token. |
| static StringLiteral *Create(const ASTContext &C, StringRef Str, |
| StringKind Kind, bool Pascal, QualType Ty, |
| SourceLocation Loc) { |
| return Create(C, Str, Kind, Pascal, Ty, &Loc, 1); |
| } |
| |
| /// \brief Construct an empty string literal. |
| static StringLiteral *CreateEmpty(const ASTContext &C, unsigned NumStrs); |
| |
| StringRef getString() const { |
| assert(CharByteWidth==1 |
| && "This function is used in places that assume strings use char"); |
| return StringRef(StrData.asChar, getByteLength()); |
| } |
| |
| /// Allow access to clients that need the byte representation, such as |
| /// ASTWriterStmt::VisitStringLiteral(). |
| StringRef getBytes() const { |
| // FIXME: StringRef may not be the right type to use as a result for this. |
| if (CharByteWidth == 1) |
| return StringRef(StrData.asChar, getByteLength()); |
| if (CharByteWidth == 4) |
| return StringRef(reinterpret_cast<const char*>(StrData.asUInt32), |
| getByteLength()); |
| assert(CharByteWidth == 2 && "unsupported CharByteWidth"); |
| return StringRef(reinterpret_cast<const char*>(StrData.asUInt16), |
| getByteLength()); |
| } |
| |
| void outputString(raw_ostream &OS) const; |
| |
| uint32_t getCodeUnit(size_t i) const { |
| assert(i < Length && "out of bounds access"); |
| if (CharByteWidth == 1) |
| return static_cast<unsigned char>(StrData.asChar[i]); |
| if (CharByteWidth == 4) |
| return StrData.asUInt32[i]; |
| assert(CharByteWidth == 2 && "unsupported CharByteWidth"); |
| return StrData.asUInt16[i]; |
| } |
| |
| unsigned getByteLength() const { return CharByteWidth*Length; } |
| unsigned getLength() const { return Length; } |
| unsigned getCharByteWidth() const { return CharByteWidth; } |
| |
| /// \brief Sets the string data to the given string data. |
| void setString(const ASTContext &C, StringRef Str, |
| StringKind Kind, bool IsPascal); |
| |
| StringKind getKind() const { return static_cast<StringKind>(Kind); } |
| |
| |
| bool isAscii() const { return Kind == Ascii; } |
| bool isWide() const { return Kind == Wide; } |
| bool isUTF8() const { return Kind == UTF8; } |
| bool isUTF16() const { return Kind == UTF16; } |
| bool isUTF32() const { return Kind == UTF32; } |
| bool isPascal() const { return IsPascal; } |
| |
| bool containsNonAsciiOrNull() const { |
| StringRef Str = getString(); |
| for (unsigned i = 0, e = Str.size(); i != e; ++i) |
| if (!isASCII(Str[i]) || !Str[i]) |
| return true; |
| return false; |
| } |
| |
| /// getNumConcatenated - Get the number of string literal tokens that were |
| /// concatenated in translation phase #6 to form this string literal. |
| unsigned getNumConcatenated() const { return NumConcatenated; } |
| |
| SourceLocation getStrTokenLoc(unsigned TokNum) const { |
| assert(TokNum < NumConcatenated && "Invalid tok number"); |
| return TokLocs[TokNum]; |
| } |
| void setStrTokenLoc(unsigned TokNum, SourceLocation L) { |
| assert(TokNum < NumConcatenated && "Invalid tok number"); |
| TokLocs[TokNum] = L; |
| } |
| |
| /// getLocationOfByte - Return a source location that points to the specified |
| /// byte of this string literal. |
| /// |
| /// Strings are amazingly complex. They can be formed from multiple tokens |
| /// and can have escape sequences in them in addition to the usual trigraph |
| /// and escaped newline business. This routine handles this complexity. |
| /// |
| SourceLocation |
| getLocationOfByte(unsigned ByteNo, const SourceManager &SM, |
| const LangOptions &Features, const TargetInfo &Target, |
| unsigned *StartToken = nullptr, |
| unsigned *StartTokenByteOffset = nullptr) const; |
| |
| typedef const SourceLocation *tokloc_iterator; |
| tokloc_iterator tokloc_begin() const { return TokLocs; } |
| tokloc_iterator tokloc_end() const { return TokLocs + NumConcatenated; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return TokLocs[0]; } |
| SourceLocation getLocEnd() const LLVM_READONLY { |
| return TokLocs[NumConcatenated - 1]; |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == StringLiteralClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| }; |
| |
| /// ParenExpr - This represents a parethesized expression, e.g. "(1)". This |
| /// AST node is only formed if full location information is requested. |
| class ParenExpr : public Expr { |
| SourceLocation L, R; |
| Stmt *Val; |
| public: |
| ParenExpr(SourceLocation l, SourceLocation r, Expr *val) |
| : Expr(ParenExprClass, val->getType(), |
| val->getValueKind(), val->getObjectKind(), |
| val->isTypeDependent(), val->isValueDependent(), |
| val->isInstantiationDependent(), |
| val->containsUnexpandedParameterPack()), |
| L(l), R(r), Val(val) {} |
| |
| /// \brief Construct an empty parenthesized expression. |
| explicit ParenExpr(EmptyShell Empty) |
| : Expr(ParenExprClass, Empty) { } |
| |
| const Expr *getSubExpr() const { return cast<Expr>(Val); } |
| Expr *getSubExpr() { return cast<Expr>(Val); } |
| void setSubExpr(Expr *E) { Val = E; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return L; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return R; } |
| |
| /// \brief Get the location of the left parentheses '('. |
| SourceLocation getLParen() const { return L; } |
| void setLParen(SourceLocation Loc) { L = Loc; } |
| |
| /// \brief Get the location of the right parentheses ')'. |
| SourceLocation getRParen() const { return R; } |
| void setRParen(SourceLocation Loc) { R = Loc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ParenExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Val, &Val+1); } |
| }; |
| |
| /// UnaryOperator - This represents the unary-expression's (except sizeof and |
| /// alignof), the postinc/postdec operators from postfix-expression, and various |
| /// extensions. |
| /// |
| /// Notes on various nodes: |
| /// |
| /// Real/Imag - These return the real/imag part of a complex operand. If |
| /// applied to a non-complex value, the former returns its operand and the |
| /// later returns zero in the type of the operand. |
| /// |
| class UnaryOperator : public Expr { |
| public: |
| typedef UnaryOperatorKind Opcode; |
| |
| private: |
| unsigned Opc : 5; |
| SourceLocation Loc; |
| Stmt *Val; |
| public: |
| |
| UnaryOperator(Expr *input, Opcode opc, QualType type, |
| ExprValueKind VK, ExprObjectKind OK, SourceLocation l) |
| : Expr(UnaryOperatorClass, type, VK, OK, |
| input->isTypeDependent() || type->isDependentType(), |
| input->isValueDependent(), |
| (input->isInstantiationDependent() || |
| type->isInstantiationDependentType()), |
| input->containsUnexpandedParameterPack()), |
| Opc(opc), Loc(l), Val(input) {} |
| |
| /// \brief Build an empty unary operator. |
| explicit UnaryOperator(EmptyShell Empty) |
| : Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { } |
| |
| Opcode getOpcode() const { return static_cast<Opcode>(Opc); } |
| void setOpcode(Opcode O) { Opc = O; } |
| |
| Expr *getSubExpr() const { return cast<Expr>(Val); } |
| void setSubExpr(Expr *E) { Val = E; } |
| |
| /// getOperatorLoc - Return the location of the operator. |
| SourceLocation getOperatorLoc() const { return Loc; } |
| void setOperatorLoc(SourceLocation L) { Loc = L; } |
| |
| /// isPostfix - Return true if this is a postfix operation, like x++. |
| static bool isPostfix(Opcode Op) { |
| return Op == UO_PostInc || Op == UO_PostDec; |
| } |
| |
| /// isPrefix - Return true if this is a prefix operation, like --x. |
| static bool isPrefix(Opcode Op) { |
| return Op == UO_PreInc || Op == UO_PreDec; |
| } |
| |
| bool isPrefix() const { return isPrefix(getOpcode()); } |
| bool isPostfix() const { return isPostfix(getOpcode()); } |
| |
| static bool isIncrementOp(Opcode Op) { |
| return Op == UO_PreInc || Op == UO_PostInc; |
| } |
| bool isIncrementOp() const { |
| return isIncrementOp(getOpcode()); |
| } |
| |
| static bool isDecrementOp(Opcode Op) { |
| return Op == UO_PreDec || Op == UO_PostDec; |
| } |
| bool isDecrementOp() const { |
| return isDecrementOp(getOpcode()); |
| } |
| |
| static bool isIncrementDecrementOp(Opcode Op) { return Op <= UO_PreDec; } |
| bool isIncrementDecrementOp() const { |
| return isIncrementDecrementOp(getOpcode()); |
| } |
| |
| static bool isArithmeticOp(Opcode Op) { |
| return Op >= UO_Plus && Op <= UO_LNot; |
| } |
| bool isArithmeticOp() const { return isArithmeticOp(getOpcode()); } |
| |
| /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it |
| /// corresponds to, e.g. "sizeof" or "[pre]++" |
| static StringRef getOpcodeStr(Opcode Op); |
| |
| /// \brief Retrieve the unary opcode that corresponds to the given |
| /// overloaded operator. |
| static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix); |
| |
| /// \brief Retrieve the overloaded operator kind that corresponds to |
| /// the given unary opcode. |
| static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); |
| |
| SourceLocation getLocStart() const LLVM_READONLY { |
| return isPostfix() ? Val->getLocStart() : Loc; |
| } |
| SourceLocation getLocEnd() const LLVM_READONLY { |
| return isPostfix() ? Loc : Val->getLocEnd(); |
| } |
| SourceLocation getExprLoc() const LLVM_READONLY { return Loc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == UnaryOperatorClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Val, &Val+1); } |
| }; |
| |
| /// Helper class for OffsetOfExpr. |
| |
| // __builtin_offsetof(type, identifier(.identifier|[expr])*) |
| class OffsetOfNode { |
| public: |
| /// \brief The kind of offsetof node we have. |
| enum Kind { |
| /// \brief An index into an array. |
| Array = 0x00, |
| /// \brief A field. |
| Field = 0x01, |
| /// \brief A field in a dependent type, known only by its name. |
| Identifier = 0x02, |
| /// \brief An implicit indirection through a C++ base class, when the |
| /// field found is in a base class. |
| Base = 0x03 |
| }; |
| |
| private: |
| enum { MaskBits = 2, Mask = 0x03 }; |
| |
| /// \brief The source range that covers this part of the designator. |
| SourceRange Range; |
| |
| /// \brief The data describing the designator, which comes in three |
| /// different forms, depending on the lower two bits. |
| /// - An unsigned index into the array of Expr*'s stored after this node |
| /// in memory, for [constant-expression] designators. |
| /// - A FieldDecl*, for references to a known field. |
| /// - An IdentifierInfo*, for references to a field with a given name |
| /// when the class type is dependent. |
| /// - A CXXBaseSpecifier*, for references that look at a field in a |
| /// base class. |
| uintptr_t Data; |
| |
| public: |
| /// \brief Create an offsetof node that refers to an array element. |
| OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, |
| SourceLocation RBracketLoc) |
| : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) {} |
| |
| /// \brief Create an offsetof node that refers to a field. |
| OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc) |
| : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc), |
| Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) {} |
| |
| /// \brief Create an offsetof node that refers to an identifier. |
| OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name, |
| SourceLocation NameLoc) |
| : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc), |
| Data(reinterpret_cast<uintptr_t>(Name) | Identifier) {} |
| |
| /// \brief Create an offsetof node that refers into a C++ base class. |
| explicit OffsetOfNode(const CXXBaseSpecifier *Base) |
| : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {} |
| |
| /// \brief Determine what kind of offsetof node this is. |
| Kind getKind() const { return static_cast<Kind>(Data & Mask); } |
| |
| /// \brief For an array element node, returns the index into the array |
| /// of expressions. |
| unsigned getArrayExprIndex() const { |
| assert(getKind() == Array); |
| return Data >> 2; |
| } |
| |
| /// \brief For a field offsetof node, returns the field. |
| FieldDecl *getField() const { |
| assert(getKind() == Field); |
| return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask); |
| } |
| |
| /// \brief For a field or identifier offsetof node, returns the name of |
| /// the field. |
| IdentifierInfo *getFieldName() const; |
| |
| /// \brief For a base class node, returns the base specifier. |
| CXXBaseSpecifier *getBase() const { |
| assert(getKind() == Base); |
| return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); |
| } |
| |
| /// \brief Retrieve the source range that covers this offsetof node. |
| /// |
| /// For an array element node, the source range contains the locations of |
| /// the square brackets. For a field or identifier node, the source range |
| /// contains the location of the period (if there is one) and the |
| /// identifier. |
| SourceRange getSourceRange() const LLVM_READONLY { return Range; } |
| SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } |
| SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } |
| }; |
| |
| /// OffsetOfExpr - [C99 7.17] - This represents an expression of the form |
| /// offsetof(record-type, member-designator). For example, given: |
| /// @code |
| /// struct S { |
| /// float f; |
| /// double d; |
| /// }; |
| /// struct T { |
| /// int i; |
| /// struct S s[10]; |
| /// }; |
| /// @endcode |
| /// we can represent and evaluate the expression @c offsetof(struct T, s[2].d). |
| |
| class OffsetOfExpr final |
| : public Expr, |
| private llvm::TrailingObjects<OffsetOfExpr, OffsetOfNode, Expr *> { |
| SourceLocation OperatorLoc, RParenLoc; |
| // Base type; |
| TypeSourceInfo *TSInfo; |
| // Number of sub-components (i.e. instances of OffsetOfNode). |
| unsigned NumComps; |
| // Number of sub-expressions (i.e. array subscript expressions). |
| unsigned NumExprs; |
| |
| size_t numTrailingObjects(OverloadToken<OffsetOfNode>) const { |
| return NumComps; |
| } |
| |
| OffsetOfExpr(const ASTContext &C, QualType type, |
| SourceLocation OperatorLoc, TypeSourceInfo *tsi, |
| ArrayRef<OffsetOfNode> comps, ArrayRef<Expr*> exprs, |
| SourceLocation RParenLoc); |
| |
| explicit OffsetOfExpr(unsigned numComps, unsigned numExprs) |
| : Expr(OffsetOfExprClass, EmptyShell()), |
| TSInfo(nullptr), NumComps(numComps), NumExprs(numExprs) {} |
| |
| public: |
| |
| static OffsetOfExpr *Create(const ASTContext &C, QualType type, |
| SourceLocation OperatorLoc, TypeSourceInfo *tsi, |
| ArrayRef<OffsetOfNode> comps, |
| ArrayRef<Expr*> exprs, SourceLocation RParenLoc); |
| |
| static OffsetOfExpr *CreateEmpty(const ASTContext &C, |
| unsigned NumComps, unsigned NumExprs); |
| |
| /// getOperatorLoc - Return the location of the operator. |
| SourceLocation getOperatorLoc() const { return OperatorLoc; } |
| void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } |
| |
| /// \brief Return the location of the right parentheses. |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation R) { RParenLoc = R; } |
| |
| TypeSourceInfo *getTypeSourceInfo() const { |
| return TSInfo; |
| } |
| void setTypeSourceInfo(TypeSourceInfo *tsi) { |
| TSInfo = tsi; |
| } |
| |
| const OffsetOfNode &getComponent(unsigned Idx) const { |
| assert(Idx < NumComps && "Subscript out of range"); |
| return getTrailingObjects<OffsetOfNode>()[Idx]; |
| } |
| |
| void setComponent(unsigned Idx, OffsetOfNode ON) { |
| assert(Idx < NumComps && "Subscript out of range"); |
| getTrailingObjects<OffsetOfNode>()[Idx] = ON; |
| } |
| |
| unsigned getNumComponents() const { |
| return NumComps; |
| } |
| |
| Expr* getIndexExpr(unsigned Idx) { |
| assert(Idx < NumExprs && "Subscript out of range"); |
| return getTrailingObjects<Expr *>()[Idx]; |
| } |
| |
| const Expr *getIndexExpr(unsigned Idx) const { |
| assert(Idx < NumExprs && "Subscript out of range"); |
| return getTrailingObjects<Expr *>()[Idx]; |
| } |
| |
| void setIndexExpr(unsigned Idx, Expr* E) { |
| assert(Idx < NumComps && "Subscript out of range"); |
| getTrailingObjects<Expr *>()[Idx] = E; |
| } |
| |
| unsigned getNumExpressions() const { |
| return NumExprs; |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return OperatorLoc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == OffsetOfExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| Stmt **begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()); |
| return child_range(begin, begin + NumExprs); |
| } |
| friend TrailingObjects; |
| }; |
| |
| /// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) |
| /// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and |
| /// vec_step (OpenCL 1.1 6.11.12). |
| class UnaryExprOrTypeTraitExpr : public Expr { |
| union { |
| TypeSourceInfo *Ty; |
| Stmt *Ex; |
| } Argument; |
| SourceLocation OpLoc, RParenLoc; |
| |
| public: |
| UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo, |
| QualType resultType, SourceLocation op, |
| SourceLocation rp) : |
| Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary, |
| false, // Never type-dependent (C++ [temp.dep.expr]p3). |
| // Value-dependent if the argument is type-dependent. |
| TInfo->getType()->isDependentType(), |
| TInfo->getType()->isInstantiationDependentType(), |
| TInfo->getType()->containsUnexpandedParameterPack()), |
| OpLoc(op), RParenLoc(rp) { |
| UnaryExprOrTypeTraitExprBits.Kind = ExprKind; |
| UnaryExprOrTypeTraitExprBits.IsType = true; |
| Argument.Ty = TInfo; |
| } |
| |
| UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E, |
| QualType resultType, SourceLocation op, |
| SourceLocation rp); |
| |
| /// \brief Construct an empty sizeof/alignof expression. |
| explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty) |
| : Expr(UnaryExprOrTypeTraitExprClass, Empty) { } |
| |
| UnaryExprOrTypeTrait getKind() const { |
| return static_cast<UnaryExprOrTypeTrait>(UnaryExprOrTypeTraitExprBits.Kind); |
| } |
| void setKind(UnaryExprOrTypeTrait K) { UnaryExprOrTypeTraitExprBits.Kind = K;} |
| |
| bool isArgumentType() const { return UnaryExprOrTypeTraitExprBits.IsType; } |
| QualType getArgumentType() const { |
| return getArgumentTypeInfo()->getType(); |
| } |
| TypeSourceInfo *getArgumentTypeInfo() const { |
| assert(isArgumentType() && "calling getArgumentType() when arg is expr"); |
| return Argument.Ty; |
| } |
| Expr *getArgumentExpr() { |
| assert(!isArgumentType() && "calling getArgumentExpr() when arg is type"); |
| return static_cast<Expr*>(Argument.Ex); |
| } |
| const Expr *getArgumentExpr() const { |
| return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr(); |
| } |
| |
| void setArgument(Expr *E) { |
| Argument.Ex = E; |
| UnaryExprOrTypeTraitExprBits.IsType = false; |
| } |
| void setArgument(TypeSourceInfo *TInfo) { |
| Argument.Ty = TInfo; |
| UnaryExprOrTypeTraitExprBits.IsType = true; |
| } |
| |
| /// Gets the argument type, or the type of the argument expression, whichever |
| /// is appropriate. |
| QualType getTypeOfArgument() const { |
| return isArgumentType() ? getArgumentType() : getArgumentExpr()->getType(); |
| } |
| |
| SourceLocation getOperatorLoc() const { return OpLoc; } |
| void setOperatorLoc(SourceLocation L) { OpLoc = L; } |
| |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { return OpLoc; } |
| SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == UnaryExprOrTypeTraitExprClass; |
| } |
| |
| // Iterators |
| child_range children(); |
| }; |
| |
| //===----------------------------------------------------------------------===// |
| // Postfix Operators. |
| //===----------------------------------------------------------------------===// |
| |
| /// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. |
| class ArraySubscriptExpr : public Expr { |
| enum { LHS, RHS, END_EXPR=2 }; |
| Stmt* SubExprs[END_EXPR]; |
| SourceLocation RBracketLoc; |
| public: |
| ArraySubscriptExpr(Expr *lhs, Expr *rhs, QualType t, |
| ExprValueKind VK, ExprObjectKind OK, |
| SourceLocation rbracketloc) |
| : Expr(ArraySubscriptExprClass, t, VK, OK, |
| lhs->isTypeDependent() || rhs->isTypeDependent(), |
| lhs->isValueDependent() || rhs->isValueDependent(), |
| (lhs->isInstantiationDependent() || |
| rhs->isInstantiationDependent()), |
| (lhs->containsUnexpandedParameterPack() || |
| rhs->containsUnexpandedParameterPack())), |
| RBracketLoc(rbracketloc) { |
| SubExprs[LHS] = lhs; |
| SubExprs[RHS] = rhs; |
| } |
| |
| /// \brief Create an empty array subscript expression. |
| explicit ArraySubscriptExpr(EmptyShell Shell) |
| : Expr(ArraySubscriptExprClass, Shell) { } |
| |
| /// An array access can be written A[4] or 4[A] (both are equivalent). |
| /// - getBase() and getIdx() always present the normalized view: A[4]. |
| /// In this case getBase() returns "A" and getIdx() returns "4". |
| /// - getLHS() and getRHS() present the syntactic view. e.g. for |
| /// 4[A] getLHS() returns "4". |
| /// Note: Because vector element access is also written A[4] we must |
| /// predicate the format conversion in getBase and getIdx only on the |
| /// the type of the RHS, as it is possible for the LHS to be a vector of |
| /// integer type |
| Expr *getLHS() { return cast<Expr>(SubExprs[LHS]); } |
| const Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } |
| void setLHS(Expr *E) { SubExprs[LHS] = E; } |
| |
| Expr *getRHS() { return cast<Expr>(SubExprs[RHS]); } |
| const Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } |
| void setRHS(Expr *E) { SubExprs[RHS] = E; } |
| |
| Expr *getBase() { |
| return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); |
| } |
| |
| const Expr *getBase() const { |
| return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); |
| } |
| |
| Expr *getIdx() { |
| return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); |
| } |
| |
| const Expr *getIdx() const { |
| return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { |
| return getLHS()->getLocStart(); |
| } |
| SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; } |
| |
| SourceLocation getRBracketLoc() const { return RBracketLoc; } |
| void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } |
| |
| SourceLocation getExprLoc() const LLVM_READONLY { |
| return getBase()->getExprLoc(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ArraySubscriptExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(&SubExprs[0], &SubExprs[0]+END_EXPR); |
| } |
| }; |
| |
| /// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]). |
| /// CallExpr itself represents a normal function call, e.g., "f(x, 2)", |
| /// while its subclasses may represent alternative syntax that (semantically) |
| /// results in a function call. For example, CXXOperatorCallExpr is |
| /// a subclass for overloaded operator calls that use operator syntax, e.g., |
| /// "str1 + str2" to resolve to a function call. |
| class CallExpr : public Expr { |
| enum { FN=0, PREARGS_START=1 }; |
| Stmt **SubExprs; |
| unsigned NumArgs; |
| SourceLocation RParenLoc; |
| |
| void updateDependenciesFromArg(Expr *Arg); |
| |
| protected: |
| // These versions of the constructor are for derived classes. |
| CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, |
| ArrayRef<Expr *> preargs, ArrayRef<Expr *> args, QualType t, |
| ExprValueKind VK, SourceLocation rparenloc); |
| CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef<Expr *> args, |
| QualType t, ExprValueKind VK, SourceLocation rparenloc); |
| CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, |
| EmptyShell Empty); |
| |
| Stmt *getPreArg(unsigned i) { |
| assert(i < getNumPreArgs() && "Prearg access out of range!"); |
| return SubExprs[PREARGS_START+i]; |
| } |
| const Stmt *getPreArg(unsigned i) const { |
| assert(i < getNumPreArgs() && "Prearg access out of range!"); |
| return SubExprs[PREARGS_START+i]; |
| } |
| void setPreArg(unsigned i, Stmt *PreArg) { |
| assert(i < getNumPreArgs() && "Prearg access out of range!"); |
| SubExprs[PREARGS_START+i] = PreArg; |
| } |
| |
| unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; } |
| |
| public: |
| CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t, |
| ExprValueKind VK, SourceLocation rparenloc); |
| |
| /// \brief Build an empty call expression. |
| CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty); |
| |
| const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); } |
| Expr *getCallee() { return cast<Expr>(SubExprs[FN]); } |
| void setCallee(Expr *F) { SubExprs[FN] = F; } |
| |
| Decl *getCalleeDecl(); |
| const Decl *getCalleeDecl() const { |
| return const_cast<CallExpr*>(this)->getCalleeDecl(); |
| } |
| |
| /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0. |
| FunctionDecl *getDirectCallee(); |
| const FunctionDecl *getDirectCallee() const { |
| return const_cast<CallExpr*>(this)->getDirectCallee(); |
| } |
| |
| /// getNumArgs - Return the number of actual arguments to this call. |
| /// |
| unsigned getNumArgs() const { return NumArgs; } |
| |
| /// \brief Retrieve the call arguments. |
| Expr **getArgs() { |
| return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START); |
| } |
| const Expr *const *getArgs() const { |
| return reinterpret_cast<Expr **>(SubExprs + getNumPreArgs() + |
| PREARGS_START); |
| } |
| |
| /// getArg - Return the specified argument. |
| Expr *getArg(unsigned Arg) { |
| assert(Arg < NumArgs && "Arg access out of range!"); |
| return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); |
| } |
| const Expr *getArg(unsigned Arg) const { |
| assert(Arg < NumArgs && "Arg access out of range!"); |
| return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); |
| } |
| |
| /// setArg - Set the specified argument. |
| void setArg(unsigned Arg, Expr *ArgExpr) { |
| assert(Arg < NumArgs && "Arg access out of range!"); |
| SubExprs[Arg+getNumPreArgs()+PREARGS_START] = ArgExpr; |
| } |
| |
| /// setNumArgs - This changes the number of arguments present in this call. |
| /// Any orphaned expressions are deleted by this, and any new operands are set |
| /// to null. |
| void setNumArgs(const ASTContext& C, unsigned NumArgs); |
| |
| typedef ExprIterator arg_iterator; |
| typedef ConstExprIterator const_arg_iterator; |
| typedef llvm::iterator_range<arg_iterator> arg_range; |
| typedef llvm::iterator_range<const_arg_iterator> arg_const_range; |
| |
| arg_range arguments() { return arg_range(arg_begin(), arg_end()); } |
| arg_const_range arguments() const { |
| return arg_const_range(arg_begin(), arg_end()); |
| } |
| |
| arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); } |
| arg_iterator arg_end() { |
| return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); |
| } |
| const_arg_iterator arg_begin() const { |
| return SubExprs+PREARGS_START+getNumPreArgs(); |
| } |
| const_arg_iterator arg_end() const { |
| return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); |
| } |
| |
| /// This method provides fast access to all the subexpressions of |
| /// a CallExpr without going through the slower virtual child_iterator |
| /// interface. This provides efficient reverse iteration of the |
| /// subexpressions. This is currently used for CFG construction. |
| ArrayRef<Stmt*> getRawSubExprs() { |
| return llvm::makeArrayRef(SubExprs, |
| getNumPreArgs() + PREARGS_START + getNumArgs()); |
| } |
| |
| /// getNumCommas - Return the number of commas that must have been present in |
| /// this function call. |
| unsigned getNumCommas() const { return NumArgs ? NumArgs - 1 : 0; } |
| |
| /// getBuiltinCallee - If this is a call to a builtin, return the builtin ID |
| /// of the callee. If not, return 0. |
| unsigned getBuiltinCallee() const; |
| |
| /// \brief Returns \c true if this is a call to a builtin which does not |
| /// evaluate side-effects within its arguments. |
| bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) const; |
| |
| /// getCallReturnType - Get the return type of the call expr. This is not |
| /// always the type of the expr itself, if the return type is a reference |
| /// type. |
| QualType getCallReturnType(const ASTContext &Ctx) const; |
| |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY; |
| SourceLocation getLocEnd() const LLVM_READONLY; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() >= firstCallExprConstant && |
| T->getStmtClass() <= lastCallExprConstant; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(&SubExprs[0], |
| &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START); |
| } |
| }; |
| |
| /// Extra data stored in some MemberExpr objects. |
| struct MemberExprNameQualifier { |
| /// \brief The nested-name-specifier that qualifies the name, including |
| /// source-location information. |
| NestedNameSpecifierLoc QualifierLoc; |
| |
| /// \brief The DeclAccessPair through which the MemberDecl was found due to |
| /// name qualifiers. |
| DeclAccessPair FoundDecl; |
| }; |
| |
| /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. |
| /// |
| class MemberExpr final |
| : public Expr, |
| private llvm::TrailingObjects<MemberExpr, MemberExprNameQualifier, |
| ASTTemplateKWAndArgsInfo, |
| TemplateArgumentLoc> { |
| /// Base - the expression for the base pointer or structure references. In |
| /// X.F, this is "X". |
| Stmt *Base; |
| |
| /// MemberDecl - This is the decl being referenced by the field/member name. |
| /// In X.F, this is the decl referenced by F. |
| ValueDecl *MemberDecl; |
| |
| /// MemberDNLoc - Provides source/type location info for the |
| /// declaration name embedded in MemberDecl. |
| DeclarationNameLoc MemberDNLoc; |
| |
| /// MemberLoc - This is the location of the member name. |
| SourceLocation MemberLoc; |
| |
| /// This is the location of the -> or . in the expression. |
| SourceLocation OperatorLoc; |
| |
| /// IsArrow - True if this is "X->F", false if this is "X.F". |
| bool IsArrow : 1; |
| |
| /// \brief True if this member expression used a nested-name-specifier to |
| /// refer to the member, e.g., "x->Base::f", or found its member via a using |
| /// declaration. When true, a MemberExprNameQualifier |
| /// structure is allocated immediately after the MemberExpr. |
| bool HasQualifierOrFoundDecl : 1; |
| |
| /// \brief True if this member expression specified a template keyword |
| /// and/or a template argument list explicitly, e.g., x->f<int>, |
| /// x->template f, x->template f<int>. |
| /// When true, an ASTTemplateKWAndArgsInfo structure and its |
| /// TemplateArguments (if any) are present. |
| bool HasTemplateKWAndArgsInfo : 1; |
| |
| /// \brief True if this member expression refers to a method that |
| /// was resolved from an overloaded set having size greater than 1. |
| bool HadMultipleCandidates : 1; |
| |
| size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const { |
| return HasQualifierOrFoundDecl ? 1 : 0; |
| } |
| |
| size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { |
| return HasTemplateKWAndArgsInfo ? 1 : 0; |
| } |
| |
| public: |
| MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc, |
| ValueDecl *memberdecl, const DeclarationNameInfo &NameInfo, |
| QualType ty, ExprValueKind VK, ExprObjectKind OK) |
| : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(), |
| base->isValueDependent(), base->isInstantiationDependent(), |
| base->containsUnexpandedParameterPack()), |
| Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()), |
| MemberLoc(NameInfo.getLoc()), OperatorLoc(operatorloc), |
| IsArrow(isarrow), HasQualifierOrFoundDecl(false), |
| HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) { |
| assert(memberdecl->getDeclName() == NameInfo.getName()); |
| } |
| |
| // NOTE: this constructor should be used only when it is known that |
| // the member name can not provide additional syntactic info |
| // (i.e., source locations for C++ operator names or type source info |
| // for constructors, destructors and conversion operators). |
| MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc, |
| ValueDecl *memberdecl, SourceLocation l, QualType ty, |
| ExprValueKind VK, ExprObjectKind OK) |
| : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(), |
| base->isValueDependent(), base->isInstantiationDependent(), |
| base->containsUnexpandedParameterPack()), |
| Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l), |
| OperatorLoc(operatorloc), IsArrow(isarrow), |
| HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false), |
| HadMultipleCandidates(false) {} |
| |
| static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow, |
| SourceLocation OperatorLoc, |
| NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, ValueDecl *memberdecl, |
| DeclAccessPair founddecl, |
| DeclarationNameInfo MemberNameInfo, |
| const TemplateArgumentListInfo *targs, QualType ty, |
| ExprValueKind VK, ExprObjectKind OK); |
| |
| void setBase(Expr *E) { Base = E; } |
| Expr *getBase() const { return cast<Expr>(Base); } |
| |
| /// \brief Retrieve the member declaration to which this expression refers. |
| /// |
| /// The returned declaration will either be a FieldDecl or (in C++) |
| /// a CXXMethodDecl. |
| ValueDecl *getMemberDecl() const { return MemberDecl; } |
| void setMemberDecl(ValueDecl *D) { MemberDecl = D; } |
| |
| /// \brief Retrieves the declaration found by lookup. |
| DeclAccessPair getFoundDecl() const { |
| if (!HasQualifierOrFoundDecl) |
| return DeclAccessPair::make(getMemberDecl(), |
| getMemberDecl()->getAccess()); |
| return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl; |
| } |
| |
| /// \brief Determines whether this member expression actually had |
| /// a C++ nested-name-specifier prior to the name of the member, e.g., |
| /// x->Base::foo. |
| bool hasQualifier() const { return getQualifier() != nullptr; } |
| |
| /// \brief If the member name was qualified, retrieves the |
| /// nested-name-specifier that precedes the member name, with source-location |
| /// information. |
| NestedNameSpecifierLoc getQualifierLoc() const { |
| if (!HasQualifierOrFoundDecl) |
| return NestedNameSpecifierLoc(); |
| |
| return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc; |
| } |
| |
| /// \brief If the member name was qualified, retrieves the |
| /// nested-name-specifier that precedes the member name. Otherwise, returns |
| /// NULL. |
| NestedNameSpecifier *getQualifier() const { |
| return getQualifierLoc().getNestedNameSpecifier(); |
| } |
| |
| /// \brief Retrieve the location of the template keyword preceding |
| /// the member name, if any. |
| SourceLocation getTemplateKeywordLoc() const { |
| if (!HasTemplateKWAndArgsInfo) return SourceLocation(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; |
| } |
| |
| /// \brief Retrieve the location of the left angle bracket starting the |
| /// explicit template argument list following the member name, if any. |
| SourceLocation getLAngleLoc() const { |
| if (!HasTemplateKWAndArgsInfo) return SourceLocation(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; |
| } |
| |
| /// \brief Retrieve the location of the right angle bracket ending the |
| /// explicit template argument list following the member name, if any. |
| SourceLocation getRAngleLoc() const { |
| if (!HasTemplateKWAndArgsInfo) return SourceLocation(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; |
| } |
| |
| /// Determines whether the member name was preceded by the template keyword. |
| bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } |
| |
| /// \brief Determines whether the member name was followed by an |
| /// explicit template argument list. |
| bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } |
| |
| /// \brief Copies the template arguments (if present) into the given |
| /// structure. |
| void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { |
| if (hasExplicitTemplateArgs()) |
| getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( |
| getTrailingObjects<TemplateArgumentLoc>(), List); |
| } |
| |
| /// \brief Retrieve the template arguments provided as part of this |
| /// template-id. |
| const TemplateArgumentLoc *getTemplateArgs() const { |
| if (!hasExplicitTemplateArgs()) |
| return nullptr; |
| |
| return getTrailingObjects<TemplateArgumentLoc>(); |
| } |
| |
| /// \brief Retrieve the number of template arguments provided as part of this |
| /// template-id. |
| unsigned getNumTemplateArgs() const { |
| if (!hasExplicitTemplateArgs()) |
| return 0; |
| |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->NumTemplateArgs; |
| } |
| |
| ArrayRef<TemplateArgumentLoc> template_arguments() const { |
| return {getTemplateArgs(), getNumTemplateArgs()}; |
| } |
| |
| /// \brief Retrieve the member declaration name info. |
| DeclarationNameInfo getMemberNameInfo() const { |
| return DeclarationNameInfo(MemberDecl->getDeclName(), |
| MemberLoc, MemberDNLoc); |
| } |
| |
| SourceLocation getOperatorLoc() const LLVM_READONLY { return OperatorLoc; } |
| |
| bool isArrow() const { return IsArrow; } |
| void setArrow(bool A) { IsArrow = A; } |
| |
| /// getMemberLoc - Return the location of the "member", in X->F, it is the |
| /// location of 'F'. |
| SourceLocation getMemberLoc() const { return MemberLoc; } |
| void setMemberLoc(SourceLocation L) { MemberLoc = L; } |
| |
| SourceLocation getLocStart() const LLVM_READONLY; |
| SourceLocation getLocEnd() const LLVM_READONLY; |
| |
| SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; } |
| |
| /// \brief Determine whether the base of this explicit is implicit. |
| bool isImplicitAccess() const { |
| return getBase() && getBase()->isImplicitCXXThis(); |
| } |
| |
| /// \brief Returns true if this member expression refers to a method that |
| /// was resolved from an overloaded set having size greater than 1. |
| bool hadMultipleCandidates() const { |
| return HadMultipleCandidates; |
| } |
| /// \brief Sets the flag telling whether this expression refers to |
| /// a method that was resolved from an overloaded set having size |
| /// greater than 1. |
| void setHadMultipleCandidates(bool V = true) { |
| HadMultipleCandidates = V; |
| } |
| |
| /// \brief Returns true if virtual dispatch is performed. |
| /// If the member access is fully qualified, (i.e. X::f()), virtual |
| /// dispatching is not performed. In -fapple-kext mode qualified |
| /// calls to virtual method will still go through the vtable. |
| bool performsVirtualDispatch(const LangOptions &LO) const { |
| return LO.AppleKext || !hasQualifier(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == MemberExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Base, &Base+1); } |
| |
| friend TrailingObjects; |
| friend class ASTReader; |
| friend class ASTStmtWriter; |
| }; |
| |
| /// CompoundLiteralExpr - [C99 6.5.2.5] |
| /// |
| class CompoundLiteralExpr : public Expr { |
| /// LParenLoc - If non-null, this is the location of the left paren in a |
| /// compound literal like "(int){4}". This can be null if this is a |
| /// synthesized compound expression. |
| SourceLocation LParenLoc; |
| |
| /// The type as written. This can be an incomplete array type, in |
| /// which case the actual expression type will be different. |
| /// The int part of the pair stores whether this expr is file scope. |
| llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfoAndScope; |
| Stmt *Init; |
| public: |
| CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo, |
| QualType T, ExprValueKind VK, Expr *init, bool fileScope) |
| : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary, |
| tinfo->getType()->isDependentType(), |
| init->isValueDependent(), |
| (init->isInstantiationDependent() || |
| tinfo->getType()->isInstantiationDependentType()), |
| init->containsUnexpandedParameterPack()), |
| LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {} |
| |
| /// \brief Construct an empty compound literal. |
| explicit CompoundLiteralExpr(EmptyShell Empty) |
| : Expr(CompoundLiteralExprClass, Empty) { } |
| |
| const Expr *getInitializer() const { return cast<Expr>(Init); } |
| Expr *getInitializer() { return cast<Expr>(Init); } |
| void setInitializer(Expr *E) { Init = E; } |
| |
| bool isFileScope() const { return TInfoAndScope.getInt(); } |
| void setFileScope(bool FS) { TInfoAndScope.setInt(FS); } |
| |
| SourceLocation getLParenLoc() const { return LParenLoc; } |
| void setLParenLoc(SourceLocation L) { LParenLoc = L; } |
| |
| TypeSourceInfo *getTypeSourceInfo() const { |
| return TInfoAndScope.getPointer(); |
| } |
| void setTypeSourceInfo(TypeSourceInfo *tinfo) { |
| TInfoAndScope.setPointer(tinfo); |
| } |
| |
| SourceLocation getLocStart() const LLVM_READONLY { |
| // FIXME: Init should never be null. |
| if (!Init) |
| return SourceLocation(); |
| if (LParenLoc.isInvalid()) |
| return Init->getLocStart(); |
| return LParenLoc; |
| } |
| SourceLocation getLocEnd() const LLVM_READONLY { |
| // FIXME: Init should never be null. |
| if (!Init) |
| return SourceLocation(); |
| return Init->getLocEnd(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CompoundLiteralExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Init, &Init+1); } |
| }; |
| |
| /// CastExpr - Base class for type casts, including both implicit |
| /// casts (ImplicitCastExpr) and explicit casts that have some |
| /// representation in the source code (ExplicitCastExpr's derived |
| /// classes). |
| class CastExpr : public Expr { |
| private: |
| Stmt *Op; |
| |
| bool CastConsistency() const; |
| |
| const CXXBaseSpecifier * const *path_buffer() const { |
| return const_cast<CastExpr*>(this)->path_buffer(); |
| } |
| CXXBaseSpecifier **path_buffer(); |
| |
| void setBasePathSize(unsigned basePathSize) { |
| CastExprBits.BasePathSize = basePathSize; |
| assert(CastExprBits.BasePathSize == basePathSize && |
| "basePathSize doesn't fit in bits of CastExprBits.BasePathSize!"); |
| } |
| |
| protected: |
| CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind, |
| Expr *op, unsigned BasePathSize) |
| : Expr(SC, ty, VK, OK_Ordinary, |
| // Cast expressions are type-dependent if the type is |
| // dependent (C++ [temp.dep.expr]p3). |
| ty->isDependentType(), |
| // Cast expressions are value-dependent if the type is |
| // dependent or if the subexpression is value-dependent. |
| ty->isDependentType() || (op && op->isValueDependent()), |
| (ty->isInstantiationDependentType() || |
| (op && op->isInstantiationDependent())), |
| // An implicit cast expression doesn't (lexically) contain an |
| // unexpanded pack, even if its target type does. |
| ((SC != ImplicitCastExprClass && |
| ty->containsUnexpandedParameterPack()) || |
| (op && op->containsUnexpandedParameterPack()))), |
| Op(op) { |
| assert(kind != CK_Invalid && "creating cast with invalid cast kind"); |
| CastExprBits.Kind = kind; |
| setBasePathSize(BasePathSize); |
| assert(CastConsistency()); |
| } |
| |
| /// \brief Construct an empty cast. |
| CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) |
| : Expr(SC, Empty) { |
| setBasePathSize(BasePathSize); |
| } |
| |
| public: |
| CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; } |
| void setCastKind(CastKind K) { CastExprBits.Kind = K; } |
| const char *getCastKindName() const; |
| |
| Expr *getSubExpr() { return cast<Expr>(Op); } |
| const Expr *getSubExpr() const { return cast<Expr>(Op); } |
| void setSubExpr(Expr *E) { Op = E; } |
| |
| /// \brief Retrieve the cast subexpression as it was written in the source |
| /// code, looking through any implicit casts or other intermediate nodes |
| /// introduced by semantic analysis. |
| Expr *getSubExprAsWritten(); |
| const Expr *getSubExprAsWritten() const { |
| return const_cast<CastExpr *>(this)->getSubExprAsWritten(); |
| } |
| |
| typedef CXXBaseSpecifier **path_iterator; |
| typedef const CXXBaseSpecifier * const *path_const_iterator; |
| bool path_empty() const { return CastExprBits.BasePathSize == 0; } |
| unsigned path_size() const { return CastExprBits.BasePathSize; } |
| path_iterator path_begin() { return path_buffer(); } |
| path_iterator path_end() { return path_buffer() + path_size(); } |
| path_const_iterator path_begin() const { return path_buffer(); } |
| path_const_iterator path_end() const { return path_buffer() + path_size(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() >= firstCastExprConstant && |
| T->getStmtClass() <= lastCastExprConstant; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Op, &Op+1); } |
| }; |
| |
| /// ImplicitCastExpr - Allows us to explicitly represent implicit type |
| /// conversions, which have no direct representation in the original |
| /// source code. For example: converting T[]->T*, void f()->void |
| /// (*f)(), float->double, short->int, etc. |
| /// |
| /// In C, implicit casts always produce rvalues. However, in C++, an |
| /// implicit cast whose result is being bound to a reference will be |
| /// an lvalue or xvalue. For example: |
| /// |
| /// @code |
| /// class Base { }; |
| /// class Derived : public Base { }; |
| /// Derived &&ref(); |
| /// void f(Derived d) { |
| /// Base& b = d; // initializer is an ImplicitCastExpr |
| /// // to an lvalue of type Base |
| /// Base&& r = ref(); // initializer is an ImplicitCastExpr |
| /// // to an xvalue of type Base |
| /// } |
| /// @endcode |
| class ImplicitCastExpr final |
| : public CastExpr, |
| private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> { |
| private: |
| ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, |
| unsigned BasePathLength, ExprValueKind VK) |
| : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) { |
| } |
| |
| /// \brief Construct an empty implicit cast. |
| explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize) |
| : CastExpr(ImplicitCastExprClass, Shell, PathSize) { } |
| |
| public: |
| enum OnStack_t { OnStack }; |
| ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op, |
| ExprValueKind VK) |
| : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) { |
| } |
| |
| static ImplicitCastExpr *Create(const ASTContext &Context, QualType T, |
| CastKind Kind, Expr *Operand, |
| const CXXCastPath *BasePath, |
| ExprValueKind Cat); |
| |
| static ImplicitCastExpr *CreateEmpty(const ASTContext &Context, |
| unsigned PathSize); |
| |
| SourceLocation getLocStart() const LLVM_READONLY { |
| return getSubExpr()->getLocStart(); |
| } |
| SourceLocation getLocEnd() const LLVM_READONLY { |
| return getSubExpr()->getLocEnd(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ImplicitCastExprClass; |
| } |
| |
| friend TrailingObjects; |
| friend class CastExpr; |
| }; |
| |
| inline Expr *Expr::IgnoreImpCasts() { |
| Expr *e = this; |
| while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(e)) |
| e = ice->getSubExpr(); |
| return e; |
| } |
| |
| /// ExplicitCastExpr - An explicit cast written in the source |
| /// code. |
| /// |
| /// This class is effectively an abstract class, because it provides |
| /// the basic representation of an explicitly-written cast without |
| /// specifying which kind of cast (C cast, functional cast, static |
| /// cast, etc.) was written; specific derived classes represent the |
| /// particular style of cast and its location information. |
| /// |
| /// Unlike implicit casts, explicit cast nodes have two different |
| /// types: the type that was written into the source code, and the |
| /// actual type of the expression as determined by semantic |
| /// analysis. These types may differ slightly. For example, in C++ one |
| /// can cast to a reference type, which indicates that the resulting |
| /// expression will be an lvalue or xvalue. The reference type, however, |
| /// will not be used as the type of the expression. |
| class ExplicitCastExpr : public CastExpr { |
| /// TInfo - Source type info for the (written) type |
| /// this expression is casting to. |
| TypeSourceInfo *TInfo; |
| |
| protected: |
| ExplicitCastExpr(StmtClass SC, QualType exprTy, ExprValueKind VK, |
| CastKind kind, Expr *op, unsigned PathSize, |
| TypeSourceInfo *writtenTy) |
| : CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {} |
| |
| /// \brief Construct an empty explicit cast. |
| ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) |
| : CastExpr(SC, Shell, PathSize) { } |
| |
| public: |
| /// getTypeInfoAsWritten - Returns the type source info for the type |
| /// that this expression is casting to. |
| TypeSourceInfo *getTypeInfoAsWritten() const { return TInfo; } |
| void setTypeInfoAsWritten(TypeSourceInfo *writtenTy) { TInfo = writtenTy; } |
| |
| /// getTypeAsWritten - Returns the type that this expression is |
| /// casting to, as written in the source code. |
| QualType getTypeAsWritten() const { return TInfo->getType(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() >= firstExplicitCastExprConstant && |
| T->getStmtClass() <= lastExplicitCastExprConstant; |
| } |
| }; |
| |
| /// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style |
| /// cast in C++ (C++ [expr.cast]), which uses the syntax |
| /// (Type)expr. For example: @c (int)f. |
| class CStyleCastExpr final |
| : public ExplicitCastExpr, |
| private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> { |
| SourceLocation LPLoc; // the location of the left paren |
| SourceLocation RPLoc; // the location of the right paren |
| |
| CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op, |
| unsigned PathSize, TypeSourceInfo *writtenTy, |
| SourceLocation l, SourceLocation r) |
| : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize, |
| writtenTy), LPLoc(l), RPLoc(r) {} |
| |
| /// \brief Construct an empty C-style explicit cast. |
| explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize) |
| : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { } |
| |
| public: |
| static CStyleCastExpr *Create(const ASTContext &Context, QualType T, |
| ExprValueKind VK, CastKind K, |
| Expr *Op, const CXXCastPath *BasePath, |
| TypeSourceInfo *WrittenTy, SourceLocation L, |
| SourceLocation R); |
| |
| static CStyleCastExpr *CreateEmpty(const ASTContext &Context, |
| unsigned PathSize); |
| |
| SourceLocation getLParenLoc() const { return LPLoc; } |
| void setLParenLoc(SourceLocation L) { LPLoc = L; } |
| |
| SourceLocation getRParenLoc() const { return RPLoc; } |
|