| //===--- Expr.h - Classes for representing expressions ----------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // 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/FixedPoint.h" |
| #include "clang/Basic/LangOptions.h" |
| #include "clang/Basic/SyncScope.h" |
| #include "clang/Basic/TypeTraits.h" |
| #include "llvm/ADT/APFloat.h" |
| #include "llvm/ADT/APSInt.h" |
| #include "llvm/ADT/iterator.h" |
| #include "llvm/ADT/iterator_range.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/Support/AtomicOrdering.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Support/TrailingObjects.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; |
| |
| /// A simple array of base specifiers. |
| typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; |
| |
| /// 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; |
| } |
| }; |
| |
| /// 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 ValueStmt { |
| QualType TR; |
| |
| public: |
| Expr() = delete; |
| Expr(const Expr&) = delete; |
| Expr(Expr &&) = delete; |
| Expr &operator=(const Expr&) = delete; |
| Expr &operator=(Expr&&) = delete; |
| |
| protected: |
| Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK, |
| bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack) |
| : ValueStmt(SC) |
| { |
| ExprBits.TypeDependent = TD; |
| ExprBits.ValueDependent = VD; |
| ExprBits.InstantiationDependent = ID; |
| ExprBits.ValueKind = VK; |
| ExprBits.ObjectKind = OK; |
| assert(ExprBits.ObjectKind == OK && "truncated kind"); |
| ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; |
| setType(T); |
| } |
| |
| /// Construct an empty expression. |
| explicit Expr(StmtClass SC, EmptyShell) : ValueStmt(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; } |
| |
| /// 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; } |
| |
| /// Set whether this expression is type-dependent or not. |
| void setTypeDependent(bool TD) { |
| ExprBits.TypeDependent = TD; |
| } |
| |
| /// 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; |
| } |
| |
| /// Set whether this expression is instantiation-dependent or not. |
| void setInstantiationDependent(bool ID) { |
| ExprBits.InstantiationDependent = ID; |
| } |
| |
| /// 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; |
| } |
| |
| /// 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_ConstQualifiedField, |
| 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; |
| |
| /// The return type of classify(). Represents the C++11 expression |
| /// taxonomy. |
| class Classification { |
| public: |
| /// 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 |
| }; |
| /// 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_ConstQualifiedField, |
| 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; } |
| |
| /// Create a simple, modifiably lvalue |
| static Classification makeSimpleLValue() { |
| return Classification(CL_LValue, CM_Modifiable); |
| } |
| |
| }; |
| /// 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); |
| } |
| |
| /// 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: |
| |
| /// 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; } |
| |
| /// 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(); |
| } |
| |
| Decl *getReferencedDeclOfCallee(); |
| const Decl *getReferencedDeclOfCallee() const { |
| return const_cast<Expr*>(this)->getReferencedDeclOfCallee(); |
| } |
| |
| /// If this expression is an l-value for an Objective C |
| /// property, find the underlying property reference expression. |
| const ObjCPropertyRefExpr *getObjCProperty() const; |
| |
| /// Check if this expression is the ObjC 'self' implicit parameter. |
| bool isObjCSelfExpr() const; |
| |
| /// Returns whether this expression refers to a vector element. |
| bool refersToVectorElement() const; |
| |
| /// Returns whether this expression refers to a global register |
| /// variable. |
| bool refersToGlobalRegisterVar() const; |
| |
| /// Returns whether this expression has a placeholder type. |
| bool hasPlaceholderType() const { |
| return getType()->isPlaceholderType(); |
| } |
| |
| /// 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 { |
| /// Whether the evaluated expression has side effects. |
| /// For example, (f() && 0) can be folded, but it still has side effects. |
| bool HasSideEffects; |
| |
| /// 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, |
| bool InConstantContext = false) const; |
| |
| /// EvaluateAsBooleanCondition - Return true if this is a constant |
| /// which 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, |
| bool InConstantContext = false) 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(EvalResult &Result, const ASTContext &Ctx, |
| SideEffectsKind AllowSideEffects = SE_NoSideEffects, |
| bool InConstantContext = false) 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, |
| bool InConstantContext = false) const; |
| |
| /// EvaluateAsFloat - Return true if this is a constant which we can fold and |
| /// convert to a fixed point value. |
| bool EvaluateAsFixedPoint(EvalResult &Result, const ASTContext &Ctx, |
| SideEffectsKind AllowSideEffects = SE_NoSideEffects, |
| bool InConstantContext = false) 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; |
| |
| /// 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; |
| |
| llvm::APSInt EvaluateKnownConstIntCheckOverflow( |
| 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, |
| bool InConstantContext = false) 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 Expr *This = nullptr) const; |
| |
| /// Indicates how the constant expression will be used. |
| enum ConstExprUsage { EvaluateForCodeGen, EvaluateForMangling }; |
| |
| /// Evaluate an expression that is required to be a constant expression. |
| bool EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage, |
| const ASTContext &Ctx) const; |
| |
| /// 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; |
| |
| /// Enumeration used to describe the kind of Null pointer constant |
| /// returned from \c isNullPointerConstant(). |
| enum NullPointerConstantKind { |
| /// Expression is not a Null pointer constant. |
| NPCK_NotNull = 0, |
| |
| /// 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, |
| |
| /// Expression is a Null pointer constant built from a literal zero. |
| NPCK_ZeroLiteral, |
| |
| /// Expression is a C++11 nullptr. |
| NPCK_CXX11_nullptr, |
| |
| /// Expression is a GNU-style __null constant. |
| NPCK_GNUNull |
| }; |
| |
| /// Enumeration used to describe how \c isNullPointerConstant() |
| /// should cope with value-dependent expressions. |
| enum NullPointerConstantValueDependence { |
| /// Specifies that the expression should never be value-dependent. |
| NPC_NeverValueDependent = 0, |
| |
| /// Specifies that a value-dependent expression of integral or |
| /// dependent type should be considered a null pointer constant. |
| NPC_ValueDependentIsNull, |
| |
| /// 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; |
| |
| /// Returns true if this expression is a bound member function. |
| bool isBoundMemberFunction(ASTContext &Ctx) const; |
| |
| /// 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); |
| |
| /// Skip past any implicit casts which might surround this expression until |
| /// reaching a fixed point. Skips: |
| /// * ImplicitCastExpr |
| /// * FullExpr |
| Expr *IgnoreImpCasts() LLVM_READONLY; |
| const Expr *IgnoreImpCasts() const { |
| return const_cast<Expr *>(this)->IgnoreImpCasts(); |
| } |
| |
| /// Skip past any casts which might surround this expression until reaching |
| /// a fixed point. Skips: |
| /// * CastExpr |
| /// * FullExpr |
| /// * MaterializeTemporaryExpr |
| /// * SubstNonTypeTemplateParmExpr |
| Expr *IgnoreCasts() LLVM_READONLY; |
| const Expr *IgnoreCasts() const { |
| return const_cast<Expr *>(this)->IgnoreCasts(); |
| } |
| |
| /// Skip past any implicit AST nodes which might surround this expression |
| /// until reaching a fixed point. Skips: |
| /// * What IgnoreImpCasts() skips |
| /// * MaterializeTemporaryExpr |
| /// * CXXBindTemporaryExpr |
| Expr *IgnoreImplicit() LLVM_READONLY; |
| const Expr *IgnoreImplicit() const { |
| return const_cast<Expr *>(this)->IgnoreImplicit(); |
| } |
| |
| /// Skip past any parentheses which might surround this expression until |
| /// reaching a fixed point. Skips: |
| /// * ParenExpr |
| /// * UnaryOperator if `UO_Extension` |
| /// * GenericSelectionExpr if `!isResultDependent()` |
| /// * ChooseExpr if `!isConditionDependent()` |
| /// * ConstantExpr |
| Expr *IgnoreParens() LLVM_READONLY; |
| const Expr *IgnoreParens() const { |
| return const_cast<Expr *>(this)->IgnoreParens(); |
| } |
| |
| /// Skip past any parentheses and implicit casts which might surround this |
| /// expression until reaching a fixed point. |
| /// FIXME: IgnoreParenImpCasts really ought to be equivalent to |
| /// IgnoreParens() + IgnoreImpCasts() until reaching a fixed point. However |
| /// this is currently not the case. Instead IgnoreParenImpCasts() skips: |
| /// * What IgnoreParens() skips |
| /// * What IgnoreImpCasts() skips |
| /// * MaterializeTemporaryExpr |
| /// * SubstNonTypeTemplateParmExpr |
| Expr *IgnoreParenImpCasts() LLVM_READONLY; |
| const Expr *IgnoreParenImpCasts() const { |
| return const_cast<Expr *>(this)->IgnoreParenImpCasts(); |
| } |
| |
| /// Skip past any parentheses and casts which might surround this expression |
| /// until reaching a fixed point. Skips: |
| /// * What IgnoreParens() skips |
| /// * What IgnoreCasts() skips |
| Expr *IgnoreParenCasts() LLVM_READONLY; |
| const Expr *IgnoreParenCasts() const { |
| return const_cast<Expr *>(this)->IgnoreParenCasts(); |
| } |
| |
| /// Skip conversion operators. If this Expr is a call to a conversion |
| /// operator, return the argument. |
| Expr *IgnoreConversionOperator() LLVM_READONLY; |
| const Expr *IgnoreConversionOperator() const { |
| return const_cast<Expr *>(this)->IgnoreConversionOperator(); |
| } |
| |
| /// Skip past any parentheses and lvalue casts which might surround this |
| /// expression until reaching a fixed point. Skips: |
| /// * What IgnoreParens() skips |
| /// * What IgnoreCasts() skips, except that only lvalue-to-rvalue |
| /// casts are skipped |
| /// FIXME: This is intended purely as a temporary workaround for code |
| /// that hasn't yet been rewritten to do the right thing about those |
| /// casts, and may disappear along with the last internal use. |
| Expr *IgnoreParenLValueCasts() LLVM_READONLY; |
| const Expr *IgnoreParenLValueCasts() const { |
| return const_cast<Expr *>(this)->IgnoreParenLValueCasts(); |
| } |
| |
| /// Skip past any parenthese and casts which do not change the value |
| /// (including ptr->int casts of the same size) until reaching a fixed point. |
| /// Skips: |
| /// * What IgnoreParens() skips |
| /// * CastExpr which do not change the value |
| /// * SubstNonTypeTemplateParmExpr |
| Expr *IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY; |
| const Expr *IgnoreParenNoopCasts(const ASTContext &Ctx) const { |
| return const_cast<Expr *>(this)->IgnoreParenNoopCasts(Ctx); |
| } |
| |
| /// Skip past any parentheses and derived-to-base casts until reaching a |
| /// fixed point. Skips: |
| /// * What IgnoreParens() skips |
| /// * CastExpr which represent a derived-to-base cast (CK_DerivedToBase, |
| /// CK_UncheckedDerivedToBase and CK_NoOp) |
| Expr *ignoreParenBaseCasts() LLVM_READONLY; |
| const Expr *ignoreParenBaseCasts() const { |
| return const_cast<Expr *>(this)->ignoreParenBaseCasts(); |
| } |
| |
| /// 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; |
| |
| /// Determine whether the result of this expression is a |
| /// temporary object of the given class type. |
| bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const; |
| |
| /// Whether this expression is an implicit reference to 'this' in C++. |
| bool isImplicitCXXThis() const; |
| |
| static bool hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs); |
| |
| /// 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; |
| |
| /// Get the inner expression that determines the best dynamic class. |
| /// If this is a prvalue, we guarantee that it is of the most-derived type |
| /// for the object itself. |
| const Expr *getBestDynamicClassTypeExpr() 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; |
| const Expr *skipRValueSubobjectAdjustments() const { |
| SmallVector<const Expr *, 8> CommaLHSs; |
| SmallVector<SubobjectAdjustment, 8> Adjustments; |
| return skipRValueSubobjectAdjustments(CommaLHSs, Adjustments); |
| } |
| |
| /// Checks that the two Expr's will refer to the same value as a comparison |
| /// operand. The caller must ensure that the values referenced by the Expr's |
| /// are not modified between E1 and E2 or the result my be invalid. |
| static bool isSameComparisonOperand(const Expr* E1, const Expr* E2); |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() >= firstExprConstant && |
| T->getStmtClass() <= lastExprConstant; |
| } |
| }; |
| |
| //===----------------------------------------------------------------------===// |
| // Wrapper Expressions. |
| //===----------------------------------------------------------------------===// |
| |
| /// FullExpr - Represents a "full-expression" node. |
| class FullExpr : public Expr { |
| protected: |
| Stmt *SubExpr; |
| |
| FullExpr(StmtClass SC, Expr *subexpr) |
| : Expr(SC, subexpr->getType(), |
| subexpr->getValueKind(), subexpr->getObjectKind(), |
| subexpr->isTypeDependent(), subexpr->isValueDependent(), |
| subexpr->isInstantiationDependent(), |
| subexpr->containsUnexpandedParameterPack()), SubExpr(subexpr) {} |
| FullExpr(StmtClass SC, EmptyShell Empty) |
| : Expr(SC, Empty) {} |
| public: |
| const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } |
| Expr *getSubExpr() { return cast<Expr>(SubExpr); } |
| |
| /// As with any mutator of the AST, be very careful when modifying an |
| /// existing AST to preserve its invariants. |
| void setSubExpr(Expr *E) { SubExpr = E; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() >= firstFullExprConstant && |
| T->getStmtClass() <= lastFullExprConstant; |
| } |
| }; |
| |
| /// ConstantExpr - An expression that occurs in a constant context and |
| /// optionally the result of evaluating the expression. |
| class ConstantExpr final |
| : public FullExpr, |
| private llvm::TrailingObjects<ConstantExpr, APValue, uint64_t> { |
| static_assert(std::is_same<uint64_t, llvm::APInt::WordType>::value, |
| "this class assumes llvm::APInt::WordType is uint64_t for " |
| "trail-allocated storage"); |
| |
| public: |
| /// Describes the kind of result that can be trail-allocated. |
| enum ResultStorageKind { RSK_None, RSK_Int64, RSK_APValue }; |
| |
| private: |
| size_t numTrailingObjects(OverloadToken<APValue>) const { |
| return ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue; |
| } |
| size_t numTrailingObjects(OverloadToken<uint64_t>) const { |
| return ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64; |
| } |
| |
| void DefaultInit(ResultStorageKind StorageKind); |
| uint64_t &Int64Result() { |
| assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64 && |
| "invalid accessor"); |
| return *getTrailingObjects<uint64_t>(); |
| } |
| const uint64_t &Int64Result() const { |
| return const_cast<ConstantExpr *>(this)->Int64Result(); |
| } |
| APValue &APValueResult() { |
| assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue && |
| "invalid accessor"); |
| return *getTrailingObjects<APValue>(); |
| } |
| const APValue &APValueResult() const { |
| return const_cast<ConstantExpr *>(this)->APValueResult(); |
| } |
| |
| ConstantExpr(Expr *subexpr, ResultStorageKind StorageKind); |
| ConstantExpr(ResultStorageKind StorageKind, EmptyShell Empty); |
| |
| public: |
| friend TrailingObjects; |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| static ConstantExpr *Create(const ASTContext &Context, Expr *E, |
| const APValue &Result); |
| static ConstantExpr *Create(const ASTContext &Context, Expr *E, |
| ResultStorageKind Storage = RSK_None); |
| static ConstantExpr *CreateEmpty(const ASTContext &Context, |
| ResultStorageKind StorageKind, |
| EmptyShell Empty); |
| |
| static ResultStorageKind getStorageKind(const APValue &Value); |
| static ResultStorageKind getStorageKind(const Type *T, |
| const ASTContext &Context); |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return SubExpr->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return SubExpr->getEndLoc(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ConstantExprClass; |
| } |
| |
| void SetResult(APValue Value, const ASTContext &Context) { |
| MoveIntoResult(Value, Context); |
| } |
| void MoveIntoResult(APValue &Value, const ASTContext &Context); |
| |
| APValue::ValueKind getResultAPValueKind() const { |
| return static_cast<APValue::ValueKind>(ConstantExprBits.APValueKind); |
| } |
| ResultStorageKind getResultStorageKind() const { |
| return static_cast<ResultStorageKind>(ConstantExprBits.ResultKind); |
| } |
| APValue getAPValueResult() const; |
| const APValue &getResultAsAPValue() const { return APValueResult(); } |
| llvm::APSInt getResultAsAPSInt() const; |
| // Iterators |
| child_range children() { return child_range(&SubExpr, &SubExpr+1); } |
| const_child_range children() const { |
| return const_child_range(&SubExpr, &SubExpr + 1); |
| } |
| }; |
| |
| //===----------------------------------------------------------------------===// |
| // 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; |
| |
| 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) { |
| setIsUnique(false); |
| OpaqueValueExprBits.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) {} |
| |
| /// Retrieve the location of this expression. |
| SourceLocation getLocation() const { return OpaqueValueExprBits.Loc; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return SourceExpr ? SourceExpr->getBeginLoc() : getLocation(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return SourceExpr ? SourceExpr->getEndLoc() : getLocation(); |
| } |
| SourceLocation getExprLoc() const LLVM_READONLY { |
| return SourceExpr ? SourceExpr->getExprLoc() : getLocation(); |
| } |
| |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| |
| /// The 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; } |
| |
| void setIsUnique(bool V) { |
| assert((!V || SourceExpr) && |
| "unique OVEs are expected to have source expressions"); |
| OpaqueValueExprBits.IsUnique = V; |
| } |
| |
| bool isUnique() const { return OpaqueValueExprBits.IsUnique; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == OpaqueValueExprClass; |
| } |
| }; |
| |
| /// 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> { |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| friend TrailingObjects; |
| |
| /// The declaration that we are referencing. |
| ValueDecl *D; |
| |
| /// Provides source/type location info for the declaration name |
| /// embedded in D. |
| DeclarationNameLoc DNLoc; |
| |
| size_t numTrailingObjects(OverloadToken<NestedNameSpecifierLoc>) const { |
| return hasQualifier(); |
| } |
| |
| size_t numTrailingObjects(OverloadToken<NamedDecl *>) const { |
| return hasFoundDecl(); |
| } |
| |
| size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { |
| return hasTemplateKWAndArgsInfo(); |
| } |
| |
| /// 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, NonOdrUseReason NOUR); |
| |
| /// Construct an empty declaration reference expression. |
| explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) {} |
| |
| /// Computes the type- and value-dependence flags for this |
| /// declaration reference expression. |
| void computeDependence(const ASTContext &Ctx); |
| |
| public: |
| DeclRefExpr(const ASTContext &Ctx, ValueDecl *D, |
| bool RefersToEnclosingVariableOrCapture, QualType T, |
| ExprValueKind VK, SourceLocation L, |
| const DeclarationNameLoc &LocInfo = DeclarationNameLoc(), |
| NonOdrUseReason NOUR = NOUR_None); |
| |
| 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, |
| NonOdrUseReason NOUR = NOUR_None); |
| |
| 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, |
| NonOdrUseReason NOUR = NOUR_None); |
| |
| /// 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(), getLocation(), DNLoc); |
| } |
| |
| SourceLocation getLocation() const { return DeclRefExprBits.Loc; } |
| void setLocation(SourceLocation L) { DeclRefExprBits.Loc = L; } |
| SourceLocation getBeginLoc() const LLVM_READONLY; |
| SourceLocation getEndLoc() const LLVM_READONLY; |
| |
| /// Determine whether this declaration reference was preceded by a |
| /// C++ nested-name-specifier, e.g., \c N::foo. |
| bool hasQualifier() const { return DeclRefExprBits.HasQualifier; } |
| |
| /// 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>(); |
| } |
| |
| /// If the name was qualified, retrieves the nested-name-specifier |
| /// that precedes the name. Otherwise, returns NULL. |
| NestedNameSpecifier *getQualifier() const { |
| return getQualifierLoc().getNestedNameSpecifier(); |
| } |
| |
| /// 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; |
| } |
| |
| /// 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; |
| } |
| |
| /// Retrieve the location of the template keyword preceding |
| /// this name, if any. |
| SourceLocation getTemplateKeywordLoc() const { |
| if (!hasTemplateKWAndArgsInfo()) |
| return SourceLocation(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; |
| } |
| |
| /// Retrieve the location of the left angle bracket starting the |
| /// explicit template argument list following the name, if any. |
| SourceLocation getLAngleLoc() const { |
| if (!hasTemplateKWAndArgsInfo()) |
| return SourceLocation(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; |
| } |
| |
| /// Retrieve the location of the right angle bracket ending the |
| /// explicit template argument list following the name, if any. |
| SourceLocation getRAngleLoc() const { |
| if (!hasTemplateKWAndArgsInfo()) |
| return SourceLocation(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; |
| } |
| |
| /// Determines whether the name in this declaration reference |
| /// was preceded by the template keyword. |
| bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } |
| |
| /// Determines whether this declaration reference was followed by an |
| /// explicit template argument list. |
| bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } |
| |
| /// Copies the template arguments (if present) into the given |
| /// structure. |
| void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { |
| if (hasExplicitTemplateArgs()) |
| getTrailingObjects<ASTTemplateKWAndArgsInfo>()->copyInto( |
| getTrailingObjects<TemplateArgumentLoc>(), List); |
| } |
| |
| /// Retrieve the template arguments provided as part of this |
| /// template-id. |
| const TemplateArgumentLoc *getTemplateArgs() const { |
| if (!hasExplicitTemplateArgs()) |
| return nullptr; |
| return getTrailingObjects<TemplateArgumentLoc>(); |
| } |
| |
| /// 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()}; |
| } |
| |
| /// 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; |
| } |
| /// 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; |
| } |
| |
| /// Is this expression a non-odr-use reference, and if so, why? |
| NonOdrUseReason isNonOdrUse() const { |
| return static_cast<NonOdrUseReason>(DeclRefExprBits.NonOdrUseReason); |
| } |
| |
| /// 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()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// 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; |
| |
| /// 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); |
| |
| /// 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); |
| /// Returns a new empty integer literal. |
| static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty); |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return Loc; } |
| |
| /// 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()); |
| } |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| class FixedPointLiteral : public Expr, public APIntStorage { |
| SourceLocation Loc; |
| unsigned Scale; |
| |
| /// \brief Construct an empty integer literal. |
| explicit FixedPointLiteral(EmptyShell Empty) |
| : Expr(FixedPointLiteralClass, Empty) {} |
| |
| public: |
| FixedPointLiteral(const ASTContext &C, const llvm::APInt &V, QualType type, |
| SourceLocation l, unsigned Scale); |
| |
| // Store the int as is without any bit shifting. |
| static FixedPointLiteral *CreateFromRawInt(const ASTContext &C, |
| const llvm::APInt &V, |
| QualType type, SourceLocation l, |
| unsigned Scale); |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; } |
| SourceLocation getEndLoc() 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() == FixedPointLiteralClass; |
| } |
| |
| std::string getValueAsString(unsigned Radix) const; |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| 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; |
| } |
| |
| /// 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 getBeginLoc() const LLVM_READONLY { return Loc; } |
| SourceLocation getEndLoc() 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()); |
| } |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| class FloatingLiteral : public Expr, private APFloatStorage { |
| SourceLocation Loc; |
| |
| FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact, |
| QualType Type, SourceLocation L); |
| |
| /// 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. |
| llvm::APFloatBase::Semantics getRawSemantics() const { |
| return static_cast<llvm::APFloatBase::Semantics>( |
| FloatingLiteralBits.Semantics); |
| } |
| |
| /// Set the raw enumeration value representing the floating-point semantics of |
| /// this literal (32-bit IEEE, x87, ...), suitable for serialisation. |
| void setRawSemantics(llvm::APFloatBase::Semantics Sem) { |
| FloatingLiteralBits.Semantics = Sem; |
| } |
| |
| /// Return the APFloat semantics this literal uses. |
| const llvm::fltSemantics &getSemantics() const { |
| return llvm::APFloatBase::EnumToSemantics( |
| static_cast<llvm::APFloatBase::Semantics>( |
| FloatingLiteralBits.Semantics)); |
| } |
| |
| /// Set the APFloat semantics this literal uses. |
| void setSemantics(const llvm::fltSemantics &Sem) { |
| FloatingLiteralBits.Semantics = llvm::APFloatBase::SemanticsToEnum(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 getBeginLoc() const LLVM_READONLY { return Loc; } |
| SourceLocation getEndLoc() 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()); |
| } |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_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) {} |
| |
| /// 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 getBeginLoc() const LLVM_READONLY { |
| return Val->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { return Val->getEndLoc(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ImaginaryLiteralClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Val, &Val+1); } |
| const_child_range children() const { |
| return const_child_range(&Val, &Val + 1); |
| } |
| }; |
| |
| /// StringLiteral - This represents a string literal expression, e.g. "foo" |
| /// or L"bar" (wide strings). The actual string data can be obtained with |
| /// getBytes() and is NOT null-terminated. The length of the string data 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 final |
| : public Expr, |
| private llvm::TrailingObjects<StringLiteral, unsigned, SourceLocation, |
| char> { |
| friend class ASTStmtReader; |
| friend TrailingObjects; |
| |
| /// StringLiteral is followed by several trailing objects. They are in order: |
| /// |
| /// * A single unsigned storing the length in characters of this string. The |
| /// length in bytes is this length times the width of a single character. |
| /// Always present and stored as a trailing objects because storing it in |
| /// StringLiteral would increase the size of StringLiteral by sizeof(void *) |
| /// due to alignment requirements. If you add some data to StringLiteral, |
| /// consider moving it inside StringLiteral. |
| /// |
| /// * An array of getNumConcatenated() SourceLocation, one for each of the |
| /// token this string is made of. |
| /// |
| /// * An array of getByteLength() char used to store the string data. |
| |
| public: |
| enum StringKind { Ascii, Wide, UTF8, UTF16, UTF32 }; |
| |
| private: |
| unsigned numTrailingObjects(OverloadToken<unsigned>) const { return 1; } |
| unsigned numTrailingObjects(OverloadToken<SourceLocation>) const { |
| return getNumConcatenated(); |
| } |
| |
| unsigned numTrailingObjects(OverloadToken<char>) const { |
| return getByteLength(); |
| } |
| |
| char *getStrDataAsChar() { return getTrailingObjects<char>(); } |
| const char *getStrDataAsChar() const { return getTrailingObjects<char>(); } |
| |
| const uint16_t *getStrDataAsUInt16() const { |
| return reinterpret_cast<const uint16_t *>(getTrailingObjects<char>()); |
| } |
| |
| const uint32_t *getStrDataAsUInt32() const { |
| return reinterpret_cast<const uint32_t *>(getTrailingObjects<char>()); |
| } |
| |
| /// Build a string literal. |
| StringLiteral(const ASTContext &Ctx, StringRef Str, StringKind Kind, |
| bool Pascal, QualType Ty, const SourceLocation *Loc, |
| unsigned NumConcatenated); |
| |
| /// Build an empty string literal. |
| StringLiteral(EmptyShell Empty, unsigned NumConcatenated, unsigned Length, |
| unsigned CharByteWidth); |
| |
| /// Map a target and string kind to the appropriate character width. |
| static unsigned mapCharByteWidth(TargetInfo const &Target, StringKind SK); |
| |
| /// Set one of the string literal token. |
| void setStrTokenLoc(unsigned TokNum, SourceLocation L) { |
| assert(TokNum < getNumConcatenated() && "Invalid tok number"); |
| getTrailingObjects<SourceLocation>()[TokNum] = L; |
| } |
| |
| public: |
| /// This is the "fully general" constructor that allows representation of |
| /// strings formed from multiple concatenated tokens. |
| static StringLiteral *Create(const ASTContext &Ctx, StringRef Str, |
| StringKind Kind, bool Pascal, QualType Ty, |
| const SourceLocation *Loc, |
| unsigned NumConcatenated); |
| |
| /// Simple constructor for string literals made from one token. |
| static StringLiteral *Create(const ASTContext &Ctx, StringRef Str, |
| StringKind Kind, bool Pascal, QualType Ty, |
| SourceLocation Loc) { |
| return Create(Ctx, Str, Kind, Pascal, Ty, &Loc, 1); |
| } |
| |
| /// Construct an empty string literal. |
| static StringLiteral *CreateEmpty(const ASTContext &Ctx, |
| unsigned NumConcatenated, unsigned Length, |
| unsigned CharByteWidth); |
| |
| StringRef getString() const { |
| assert(getCharByteWidth() == 1 && |
| "This function is used in places that assume strings use char"); |
| return StringRef(getStrDataAsChar(), 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. |
| return StringRef(getStrDataAsChar(), getByteLength()); |
| } |
| |
| void outputString(raw_ostream &OS) const; |
| |
| uint32_t getCodeUnit(size_t i) const { |
| assert(i < getLength() && "out of bounds access"); |
| switch (getCharByteWidth()) { |
| case 1: |
| return static_cast<unsigned char>(getStrDataAsChar()[i]); |
| case 2: |
| return getStrDataAsUInt16()[i]; |
| case 4: |
| return getStrDataAsUInt32()[i]; |
| } |
| llvm_unreachable("Unsupported character width!"); |
| } |
| |
| unsigned getByteLength() const { return getCharByteWidth() * getLength(); } |
| unsigned getLength() const { return *getTrailingObjects<unsigned>(); } |
| unsigned getCharByteWidth() const { return StringLiteralBits.CharByteWidth; } |
| |
| StringKind getKind() const { |
| return static_cast<StringKind>(StringLiteralBits.Kind); |
| } |
| |
| bool isAscii() const { return getKind() == Ascii; } |
| bool isWide() const { return getKind() == Wide; } |
| bool isUTF8() const { return getKind() == UTF8; } |
| bool isUTF16() const { return getKind() == UTF16; } |
| bool isUTF32() const { return getKind() == UTF32; } |
| bool isPascal() const { return StringLiteralBits.IsPascal; } |
| |
| bool containsNonAscii() const { |
| for (auto c : getString()) |
| if (!isASCII(c)) |
| return true; |
| return false; |
| } |
| |
| bool containsNonAsciiOrNull() const { |
| for (auto c : getString()) |
| if (!isASCII(c) || !c) |
| 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 StringLiteralBits.NumConcatenated; |
| } |
| |
| /// Get one of the string literal token. |
| SourceLocation getStrTokenLoc(unsigned TokNum) const { |
| assert(TokNum < getNumConcatenated() && "Invalid tok number"); |
| return getTrailingObjects<SourceLocation>()[TokNum]; |
| } |
| |
| /// 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 getTrailingObjects<SourceLocation>(); |
| } |
| |
| tokloc_iterator tokloc_end() const { |
| return getTrailingObjects<SourceLocation>() + getNumConcatenated(); |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return *tokloc_begin(); } |
| SourceLocation getEndLoc() const LLVM_READONLY { return *(tokloc_end() - 1); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == StringLiteralClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// [C99 6.4.2.2] - A predefined identifier such as __func__. |
| class PredefinedExpr final |
| : public Expr, |
| private llvm::TrailingObjects<PredefinedExpr, Stmt *> { |
| friend class ASTStmtReader; |
| friend TrailingObjects; |
| |
| // PredefinedExpr is optionally followed by a single trailing |
| // "Stmt *" for the predefined identifier. It is present if and only if |
| // hasFunctionName() is true and is always a "StringLiteral *". |
| |
| public: |
| enum IdentKind { |
| Func, |
| Function, |
| LFunction, // Same as Function, but as wide string. |
| FuncDName, |
| FuncSig, |
| LFuncSig, // Same as FuncSig, but as as wide string |
| PrettyFunction, |
| /// The same as PrettyFunction, except that the |
| /// 'virtual' keyword is omitted for virtual member functions. |
| PrettyFunctionNoVirtual |
| }; |
| |
| private: |
| PredefinedExpr(SourceLocation L, QualType FNTy, IdentKind IK, |
| StringLiteral *SL); |
| |
| explicit PredefinedExpr(EmptyShell Empty, bool HasFunctionName); |
| |
| /// True if this PredefinedExpr has storage for a function name. |
| bool hasFunctionName() const { return PredefinedExprBits.HasFunctionName; } |
| |
| void setFunctionName(StringLiteral *SL) { |
| assert(hasFunctionName() && |
| "This PredefinedExpr has no storage for a function name!"); |
| *getTrailingObjects<Stmt *>() = SL; |
| } |
| |
| public: |
| /// Create a PredefinedExpr. |
| static PredefinedExpr *Create(const ASTContext &Ctx, SourceLocation L, |
| QualType FNTy, IdentKind IK, StringLiteral *SL); |
| |
| /// Create an empty PredefinedExpr. |
| static PredefinedExpr *CreateEmpty(const ASTContext &Ctx, |
| bool HasFunctionName); |
| |
| IdentKind getIdentKind() const { |
| return static_cast<IdentKind>(PredefinedExprBits.Kind); |
| } |
| |
| SourceLocation getLocation() const { return PredefinedExprBits.Loc; } |
| void setLocation(SourceLocation L) { PredefinedExprBits.Loc = L; } |
| |
| StringLiteral *getFunctionName() { |
| return hasFunctionName() |
| ? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>()) |
| : nullptr; |
| } |
| |
| const StringLiteral *getFunctionName() const { |
| return hasFunctionName() |
| ? static_cast<StringLiteral *>(*getTrailingObjects<Stmt *>()) |
| : nullptr; |
| } |
| |
| static StringRef getIdentKindName(IdentKind IK); |
| static std::string ComputeName(IdentKind IK, const Decl *CurrentDecl); |
| |
| SourceLocation getBeginLoc() const { return getLocation(); } |
| SourceLocation getEndLoc() const { return getLocation(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == PredefinedExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(getTrailingObjects<Stmt *>(), |
| getTrailingObjects<Stmt *>() + hasFunctionName()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(getTrailingObjects<Stmt *>(), |
| getTrailingObjects<Stmt *>() + hasFunctionName()); |
| } |
| }; |
| |
| /// 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) {} |
| |
| /// 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 getBeginLoc() const LLVM_READONLY { return L; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return R; } |
| |
| /// Get the location of the left parentheses '('. |
| SourceLocation getLParen() const { return L; } |
| void setLParen(SourceLocation Loc) { L = Loc; } |
| |
| /// 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); } |
| const_child_range children() const { |
| return const_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 { |
| Stmt *Val; |
| |
| public: |
| typedef UnaryOperatorKind Opcode; |
| |
| UnaryOperator(Expr *input, Opcode opc, QualType type, ExprValueKind VK, |
| ExprObjectKind OK, SourceLocation l, bool CanOverflow) |
| : Expr(UnaryOperatorClass, type, VK, OK, |
| input->isTypeDependent() || type->isDependentType(), |
| input->isValueDependent(), |
| (input->isInstantiationDependent() || |
| type->isInstantiationDependentType()), |
| input->containsUnexpandedParameterPack()), |
| Val(input) { |
| UnaryOperatorBits.Opc = opc; |
| UnaryOperatorBits.CanOverflow = CanOverflow; |
| UnaryOperatorBits.Loc = l; |
| } |
| |
| /// Build an empty unary operator. |
| explicit UnaryOperator(EmptyShell Empty) : Expr(UnaryOperatorClass, Empty) { |
| UnaryOperatorBits.Opc = UO_AddrOf; |
| } |
| |
| Opcode getOpcode() const { |
| return static_cast<Opcode>(UnaryOperatorBits.Opc); |
| } |
| void setOpcode(Opcode Opc) { UnaryOperatorBits.Opc = Opc; } |
| |
| Expr *getSubExpr() const { return cast<Expr>(Val); } |
| void setSubExpr(Expr *E) { Val = E; } |
| |
| /// getOperatorLoc - Return the location of the operator. |
| SourceLocation getOperatorLoc() const { return UnaryOperatorBits.Loc; } |
| void setOperatorLoc(SourceLocation L) { UnaryOperatorBits.Loc = L; } |
| |
| /// Returns true if the unary operator can cause an overflow. For instance, |
| /// signed int i = INT_MAX; i++; |
| /// signed char c = CHAR_MAX; c++; |
| /// Due to integer promotions, c++ is promoted to an int before the postfix |
| /// increment, and the result is an int that cannot overflow. However, i++ |
| /// can overflow. |
| bool canOverflow() const { return UnaryOperatorBits.CanOverflow; } |
| void setCanOverflow(bool C) { UnaryOperatorBits.CanOverflow = C; } |
| |
| /// 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); |
| |
| /// Retrieve the unary opcode that corresponds to the given |
| /// overloaded operator. |
| static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix); |
| |
| /// Retrieve the overloaded operator kind that corresponds to |
| /// the given unary opcode. |
| static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return isPostfix() ? Val->getBeginLoc() : getOperatorLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return isPostfix() ? getOperatorLoc() : Val->getEndLoc(); |
| } |
| SourceLocation getExprLoc() const { return getOperatorLoc(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == UnaryOperatorClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Val, &Val+1); } |
| const_child_range children() const { |
| return const_child_range(&Val, &Val + 1); |
| } |
| }; |
| |
| /// Helper class for OffsetOfExpr. |
| |
| // __builtin_offsetof(type, identifier(.identifier|[expr])*) |
| class OffsetOfNode { |
| public: |
| /// The kind of offsetof node we have. |
| enum Kind { |
| /// An index into an array. |
| Array = 0x00, |
| /// A field. |
| Field = 0x01, |
| /// A field in a dependent type, known only by its name. |
| Identifier = 0x02, |
| /// 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 }; |
| |
| /// The source range that covers this part of the designator. |
| SourceRange Range; |
| |
| /// 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: |
| /// Create an offsetof node that refers to an array element. |
| OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, |
| SourceLocation RBracketLoc) |
| : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) {} |
| |
| /// 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) {} |
| |
| /// 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) {} |
| |
| /// 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) {} |
| |
| /// Determine what kind of offsetof node this is. |
| Kind getKind() const { return static_cast<Kind>(Data & Mask); } |
| |
| /// For an array element node, returns the index into the array |
| /// of expressions. |
| unsigned getArrayExprIndex() const { |
| assert(getKind() == Array); |
| return Data >> 2; |
| } |
| |
| /// For a field offsetof node, returns the field. |
| FieldDecl *getField() const { |
| assert(getKind() == Field); |
| return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask); |
| } |
| |
| /// For a field or identifier offsetof node, returns the name of |
| /// the field. |
| IdentifierInfo *getFieldName() const; |
| |
| /// For a base class node, returns the base specifier. |
| CXXBaseSpecifier *getBase() const { |
| assert(getKind() == Base); |
| return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); |
| } |
| |
| /// 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 getBeginLoc() const LLVM_READONLY { return Range.getBegin(); } |
| SourceLocation getEndLoc() 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; } |
| |
| /// 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 getBeginLoc() const LLVM_READONLY { return OperatorLoc; } |
| SourceLocation getEndLoc() 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); |
| } |
| const_child_range children() const { |
| Stmt *const *begin = |
| reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>()); |
| return const_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); |
| |
| /// 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 getBeginLoc() const LLVM_READONLY { return OpLoc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == UnaryExprOrTypeTraitExprClass; |
| } |
| |
| // Iterators |
| child_range children(); |
| const_child_range children() const; |
| }; |
| |
| //===----------------------------------------------------------------------===// |
| // Postfix Operators. |
| //===----------------------------------------------------------------------===// |
| |
| /// ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting. |
| class ArraySubscriptExpr : public Expr { |
| enum { LHS, RHS, END_EXPR }; |
| Stmt *SubExprs[END_EXPR]; |
| |
| bool lhsIsBase() const { return getRHS()->getType()->isIntegerType(); } |
| |
| 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())) { |
| SubExprs[LHS] = lhs; |
| SubExprs[RHS] = rhs; |
| ArraySubscriptExprBits.RBracketLoc = rbracketloc; |
| } |
| |
| /// 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 lhsIsBase() ? getLHS() : getRHS(); } |
| const Expr *getBase() const { return lhsIsBase() ? getLHS() : getRHS(); } |
| |
| Expr *getIdx() { return lhsIsBase() ? getRHS() : getLHS(); } |
| const Expr *getIdx() const { return lhsIsBase() ? getRHS() : getLHS(); } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return getLHS()->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const { return getRBracketLoc(); } |
| |
| SourceLocation getRBracketLoc() const { |
| return ArraySubscriptExprBits.RBracketLoc; |
| } |
| void setRBracketLoc(SourceLocation L) { |
| ArraySubscriptExprBits.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); |
| } |
| const_child_range children() const { |
| return const_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 }; |
| |
| /// The number of arguments in the call expression. |
| unsigned NumArgs; |
| |
| /// The location of the right parenthese. This has a different meaning for |
| /// the derived classes of CallExpr. |
| SourceLocation RParenLoc; |
| |
| void updateDependenciesFromArg(Expr *Arg); |
| |
| // CallExpr store some data in trailing objects. However since CallExpr |
| // is used a base of other expression classes we cannot use |
| // llvm::TrailingObjects. Instead we manually perform the pointer arithmetic |
| // and casts. |
| // |
| // The trailing objects are in order: |
| // |
| // * A single "Stmt *" for the callee expression. |
| // |
| // * An array of getNumPreArgs() "Stmt *" for the pre-argument expressions. |
| // |
| // * An array of getNumArgs() "Stmt *" for the argument expressions. |
| // |
| // Note that we store the offset in bytes from the this pointer to the start |
| // of the trailing objects. It would be perfectly possible to compute it |
| // based on the dynamic kind of the CallExpr. However 1.) we have plenty of |
| // space in the bit-fields of Stmt. 2.) It was benchmarked to be faster to |
| // compute this once and then load the offset from the bit-fields of Stmt, |
| // instead of re-computing the offset each time the trailing objects are |
| // accessed. |
| |
| /// Return a pointer to the start of the trailing array of "Stmt *". |
| Stmt **getTrailingStmts() { |
| return reinterpret_cast<Stmt **>(reinterpret_cast<char *>(this) + |
| CallExprBits.OffsetToTrailingObjects); |
| } |
| Stmt *const *getTrailingStmts() const { |
| return const_cast<CallExpr *>(this)->getTrailingStmts(); |
| } |
| |
| /// Map a statement class to the appropriate offset in bytes from the |
| /// this pointer to the trailing objects. |
| static unsigned offsetToTrailingObjects(StmtClass SC); |
| |
| public: |
| enum class ADLCallKind : bool { NotADL, UsesADL }; |
| static constexpr ADLCallKind NotADL = ADLCallKind::NotADL; |
| static constexpr ADLCallKind UsesADL = ADLCallKind::UsesADL; |
| |
| protected: |
| /// Build a call expression, assuming that appropriate storage has been |
| /// allocated for the trailing objects. |
| CallExpr(StmtClass SC, Expr *Fn, ArrayRef<Expr *> PreArgs, |
| ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, |
| SourceLocation RParenLoc, unsigned MinNumArgs, ADLCallKind UsesADL); |
| |
| /// Build an empty call expression, for deserialization. |
| CallExpr(StmtClass SC, unsigned NumPreArgs, unsigned NumArgs, |
| EmptyShell Empty); |
| |
| /// Return the size in bytes needed for the trailing objects. |
| /// Used by the derived classes to allocate the right amount of storage. |
| static unsigned sizeOfTrailingObjects(unsigned NumPreArgs, unsigned NumArgs) { |
| return (1 + NumPreArgs + NumArgs) * sizeof(Stmt *); |
| } |
| |
| Stmt *getPreArg(unsigned I) { |
| assert(I < getNumPreArgs() && "Prearg access out of range!"); |
| return getTrailingStmts()[PREARGS_START + I]; |
| } |
| const Stmt *getPreArg(unsigned I) const { |
| assert(I < getNumPreArgs() && "Prearg access out of range!"); |
| return getTrailingStmts()[PREARGS_START + I]; |
| } |
| void setPreArg(unsigned I, Stmt *PreArg) { |
| assert(I < getNumPreArgs() && "Prearg access out of range!"); |
| getTrailingStmts()[PREARGS_START + I] = PreArg; |
| } |
| |
| unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; } |
| |
| public: |
| /// Create a call expression. Fn is the callee expression, Args is the |
| /// argument array, Ty is the type of the call expression (which is *not* |
| /// the return type in general), VK is the value kind of the call expression |
| /// (lvalue, rvalue, ...), and RParenLoc is the location of the right |
| /// parenthese in the call expression. MinNumArgs specifies the minimum |
| /// number of arguments. The actual number of arguments will be the greater |
| /// of Args.size() and MinNumArgs. This is used in a few places to allocate |
| /// enough storage for the default arguments. UsesADL specifies whether the |
| /// callee was found through argument-dependent lookup. |
| /// |
| /// Note that you can use CreateTemporary if you need a temporary call |
| /// expression on the stack. |
| static CallExpr *Create(const ASTContext &Ctx, Expr *Fn, |
| ArrayRef<Expr *> Args, QualType Ty, ExprValueKind VK, |
| SourceLocation RParenLoc, unsigned MinNumArgs = 0, |
| ADLCallKind UsesADL = NotADL); |
| |
| /// Create a temporary call expression with no arguments in the memory |
| /// pointed to by Mem. Mem must points to at least sizeof(CallExpr) |
| /// + sizeof(Stmt *) bytes of storage, aligned to alignof(CallExpr): |
| /// |
| /// \code{.cpp} |
| /// alignas(CallExpr) char Buffer[sizeof(CallExpr) + sizeof(Stmt *)]; |
| /// CallExpr *TheCall = CallExpr::CreateTemporary(Buffer, etc); |
| /// \endcode |
| static CallExpr *CreateTemporary(void *Mem, Expr *Fn, QualType Ty, |
| ExprValueKind VK, SourceLocation RParenLoc, |
| ADLCallKind UsesADL = NotADL); |
| |
| /// Create an empty call expression, for deserialization. |
| static CallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, |
| EmptyShell Empty); |
| |
| Expr *getCallee() { return cast<Expr>(getTrailingStmts()[FN]); } |
| const Expr *getCallee() const { return cast<Expr>(getTrailingStmts()[FN]); } |
| void setCallee(Expr *F) { getTrailingStmts()[FN] = F; } |
| |
| ADLCallKind getADLCallKind() const { |
| return static_cast<ADLCallKind>(CallExprBits.UsesADL); |
| } |
| void setADLCallKind(ADLCallKind V = UsesADL) { |
| CallExprBits.UsesADL = static_cast<bool>(V); |
| } |
| bool usesADL() const { return getADLCallKind() == UsesADL; } |
| |
| Decl *getCalleeDecl() { return getCallee()->getReferencedDeclOfCallee(); } |
| const Decl *getCalleeDecl() const { |
| return getCallee()->getReferencedDeclOfCallee(); |
| } |
| |
| /// If the callee is a FunctionDecl, return it. Otherwise return null. |
| FunctionDecl *getDirectCallee() { |
| return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); |
| } |
| const FunctionDecl *getDirectCallee() const { |
| return dyn_cast_or_null<FunctionDecl>(getCalleeDecl()); |
| } |
| |
| /// getNumArgs - Return the number of actual arguments to this call. |
| unsigned getNumArgs() const { return NumArgs; } |
| |
| /// Retrieve the call arguments. |
| Expr **getArgs() { |
| return reinterpret_cast<Expr **>(getTrailingStmts() + PREARGS_START + |
| getNumPreArgs()); |
| } |
| const Expr *const *getArgs() const { |
| return reinterpret_cast<const Expr *const *>( |
| getTrailingStmts() + PREARGS_START + getNumPreArgs()); |
| } |
| |
| /// getArg - Return the specified argument. |
| Expr *getArg(unsigned Arg) { |
| assert(Arg < getNumArgs() && "Arg access out of range!"); |
| return getArgs()[Arg]; |
| } |
| const Expr *getArg(unsigned Arg) const { |
| assert(Arg < getNumArgs() && "Arg access out of range!"); |
| return getArgs()[Arg]; |
| } |
| |
| /// setArg - Set the specified argument. |
| void setArg(unsigned Arg, Expr *ArgExpr) { |
| assert(Arg < getNumArgs() && "Arg access out of range!"); |
| getArgs()[Arg] = ArgExpr; |
| } |
| |
| /// Reduce the number of arguments in this call expression. This is used for |
| /// example during error recovery to drop extra arguments. There is no way |
| /// to perform the opposite because: 1.) We don't track how much storage |
| /// we have for the argument array 2.) This would potentially require growing |
| /// the argument array, something we cannot support since the arguments are |
| /// stored in a trailing array. |
| void shrinkNumArgs(unsigned NewNumArgs) { |
| assert((NewNumArgs <= getNumArgs()) && |
| "shrinkNumArgs cannot increase the number of arguments!"); |
| NumArgs = NewNumArgs; |
| } |
| |
| /// Bluntly set a new number of arguments without doing any checks whatsoever. |
| /// Only used during construction of a CallExpr in a few places in Sema. |
| /// FIXME: Find a way to remove it. |
| void setNumArgsUnsafe(unsigned NewNumArgs) { NumArgs = NewNumArgs; } |
| |
| typedef ExprIterator arg_iterator; |
| typedef ConstExprIterator const_arg_iterator; |
| typedef llvm::iterator_range<arg_iterator> arg_range; |
| typedef llvm::iterator_range<const_arg_iterator> const_arg_range; |
| |
| arg_range arguments() { return arg_range(arg_begin(), arg_end()); } |
| const_arg_range arguments() const { |
| return const_arg_range(arg_begin(), arg_end()); |
| } |
| |
| arg_iterator arg_begin() { |
| return getTrailingStmts() + PREARGS_START + getNumPreArgs(); |
| } |
| arg_iterator arg_end() { return arg_begin() + getNumArgs(); } |
| |
| const_arg_iterator arg_begin() const { |
| return getTrailingStmts() + PREARGS_START + getNumPreArgs(); |
| } |
| const_arg_iterator arg_end() const { return arg_begin() + 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(getTrailingStmts(), |
| PREARGS_START + getNumPreArgs() + getNumArgs()); |
| } |
| |
| /// getNumCommas - Return the number of commas that must have been present in |
| /// this function call. |
| unsigned getNumCommas() const { return getNumArgs() ? getNumArgs() - 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; |
| |
| /// 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; |
| |
| /// Returns the WarnUnusedResultAttr that is either declared on the called |
| /// function, or its return type declaration. |
| const Attr *getUnusedResultAttr(const ASTContext &Ctx) const; |
| |
| /// Returns true if this call expression should warn on unused results. |
| bool hasUnusedResultAttr(const ASTContext &Ctx) const { |
| return getUnusedResultAttr(Ctx) != nullptr; |
| } |
| |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY; |
| SourceLocation getEndLoc() const LLVM_READONLY; |
| |
| /// Return true if this is a call to __assume() or __builtin_assume() with |
| /// a non-value-dependent constant parameter evaluating as false. |
| bool isBuiltinAssumeFalse(const ASTContext &Ctx) const; |
| |
| bool isCallToStdMove() const { |
| const FunctionDecl *FD = getDirectCallee(); |
| return getNumArgs() == 1 && FD && FD->isInStdNamespace() && |
| FD->getIdentifier() && FD->getIdentifier()->isStr("move"); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() >= firstCallExprConstant && |
| T->getStmtClass() <= lastCallExprConstant; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(getTrailingStmts(), getTrailingStmts() + PREARGS_START + |
| getNumPreArgs() + getNumArgs()); |
| } |
| |
| const_child_range children() const { |
| return const_child_range(getTrailingStmts(), |
| getTrailingStmts() + PREARGS_START + |
| getNumPreArgs() + getNumArgs()); |
| } |
| }; |
| |
| /// Extra data stored in some MemberExpr objects. |
| struct MemberExprNameQualifier { |
| /// The nested-name-specifier that qualifies the name, including |
| /// source-location information. |
| NestedNameSpecifierLoc QualifierLoc; |
| |
| /// 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> { |
| friend class ASTReader; |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| friend TrailingObjects; |
| |
| /// 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; |
| |
| size_t numTrailingObjects(OverloadToken<MemberExprNameQualifier>) const { |
| return hasQualifierOrFoundDecl(); |
| } |
| |
| size_t numTrailingObjects(OverloadToken<ASTTemplateKWAndArgsInfo>) const { |
| return hasTemplateKWAndArgsInfo(); |
| } |
| |
| bool hasQualifierOrFoundDecl() const { |
| return MemberExprBits.HasQualifierOrFoundDecl; |
| } |
| |
| bool hasTemplateKWAndArgsInfo() const { |
| return MemberExprBits.HasTemplateKWAndArgsInfo; |
| } |
| |
| MemberExpr(Expr *Base, bool IsArrow, SourceLocation OperatorLoc, |
| ValueDecl *MemberDecl, const DeclarationNameInfo &NameInfo, |
| QualType T, ExprValueKind VK, ExprObjectKind OK, |
| NonOdrUseReason NOUR); |
| MemberExpr(EmptyShell Empty) |
| : Expr(MemberExprClass, Empty), Base(), MemberDecl() {} |
| |
| public: |
| static MemberExpr *Create(const ASTContext &C, Expr *Base, bool IsArrow, |
| SourceLocation OperatorLoc, |
| NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, |
| DeclAccessPair FoundDecl, |
| DeclarationNameInfo MemberNameInfo, |
| const TemplateArgumentListInfo *TemplateArgs, |
| QualType T, ExprValueKind VK, ExprObjectKind OK, |
| NonOdrUseReason NOUR); |
| |
| /// Create an implicit MemberExpr, with no location, qualifier, template |
| /// arguments, and so on. Suitable only for non-static member access. |
| static MemberExpr *CreateImplicit(const ASTContext &C, Expr *Base, |
| bool IsArrow, ValueDecl *MemberDecl, |
| QualType T, ExprValueKind VK, |
| ExprObjectKind OK) { |
| return Create(C, Base, IsArrow, SourceLocation(), NestedNameSpecifierLoc(), |
| SourceLocation(), MemberDecl, |
| DeclAccessPair::make(MemberDecl, MemberDecl->getAccess()), |
| DeclarationNameInfo(), nullptr, T, VK, OK, NOUR_None); |
|