| //===--- 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 Stmt { |
| QualType TR; |
| |
| protected: |
| Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK, |
| bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack) |
| : Stmt(SC) |
| { |
| ExprBits.TypeDependent = TD; |
| ExprBits.ValueDependent = VD; |
| ExprBits.InstantiationDependent = ID; |
| ExprBits.ValueKind = VK; |
| ExprBits.ObjectKind = OK; |
| assert(ExprBits.ObjectKind == OK && "truncated kind"); |
| ExprBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack; |
| setType(T); |
| } |
| |
| /// Construct an empty expression. |
| explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { } |
| |
| public: |
| QualType getType() const { return TR; } |
| void setType(QualType t) { |
| // In C++, the type of an expression is always adjusted so that it |
| // will not have reference type (C++ [expr]p6). Use |
| // QualType::getNonReferenceType() to retrieve the non-reference |
| // type. Additionally, inspect Expr::isLvalue to determine whether |
| // an expression that is adjusted in this manner should be |
| // considered an lvalue. |
| assert((t.isNull() || !t->isReferenceType()) && |
| "Expressions can't have reference type"); |
| |
| TR = t; |
| } |
| |
| /// isValueDependent - Determines whether this expression is |
| /// value-dependent (C++ [temp.dep.constexpr]). For example, the |
| /// array bound of "Chars" in the following example is |
| /// value-dependent. |
| /// @code |
| /// template<int Size, char (&Chars)[Size]> struct meta_string; |
| /// @endcode |
| bool isValueDependent() const { return ExprBits.ValueDependent; } |
| |
| /// 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) 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) const; |
| |
| /// EvaluateAsFloat - Return true if this is a constant which we can fold and |
| /// convert to a floating point value, using any crazy technique that we |
| /// want to. |
| bool |
| EvaluateAsFloat(llvm::APFloat &Result, const ASTContext &Ctx, |
| SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; |
| |
| /// 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) 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) 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 |
| /// * ImplicitCastExpr |
| /// * 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); |
| } |
| |
| 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. |
| class ConstantExpr : public FullExpr { |
| ConstantExpr(Expr *subexpr) |
| : FullExpr(ConstantExprClass, subexpr) {} |
| |
| public: |
| static ConstantExpr *Create(const ASTContext &Context, Expr *E) { |
| assert(!isa<ConstantExpr>(E)); |
| return new (Context) ConstantExpr(E); |
| } |
| |
| /// Build an empty constant expression wrapper. |
| explicit ConstantExpr(EmptyShell Empty) |
| : FullExpr(ConstantExprClass, Empty) {} |
| |
| 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; |
| } |
| |
| // 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); |
| |
| /// 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()); |
| |
| static DeclRefExpr * |
| Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, ValueDecl *D, |
| bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, |
| QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr, |
| const TemplateArgumentListInfo *TemplateArgs = nullptr); |
| |
| static DeclRefExpr * |
| Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, ValueDecl *D, |
| bool RefersToEnclosingVariableOrCapture, |
| const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, |
| NamedDecl *FoundD = nullptr, |
| const TemplateArgumentListInfo *TemplateArgs = nullptr); |
| |
| /// 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; |
| } |
| |
| /// 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. |
| APFloatSemantics getRawSemantics() const { |
| return static_cast<APFloatSemantics>(FloatingLiteralBits.Semantics); |
| } |
| |
| /// Set the raw enumeration value representing the floating-point semantics of |
| /// this literal (32-bit IEEE, x87, ...), suitable for serialisation. |
| void setRawSemantics(APFloatSemantics Sem) { |
| FloatingLiteralBits.Semantics = Sem; |
| } |
| |
| /// Return the APFloat semantics this literal uses. |
| const llvm::fltSemantics &getSemantics() const; |
| |
| /// Set the APFloat semantics this literal uses. |
| void setSemantics(const llvm::fltSemantics &Sem); |
| |
| bool isExact() const { return FloatingLiteralBits.IsExact; } |
| void setExact(bool E) { FloatingLiteralBits.IsExact = E; } |
| |
| /// getValueAsApproximateDouble - This returns the value as an inaccurate |
| /// double. Note that this may cause loss of precision, but is useful for |
| /// debugging dumps, etc. |
| double getValueAsApproximateDouble() const; |
| |
| SourceLocation getLocation() const { return Loc; } |
| void setLocation(SourceLocation L) { Loc = L; } |
| |
| SourceLocation 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()); |
| } |
| }; |
| |
| /// 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} |
| /// llvm::AlignedCharArray<alignof(CallExpr), |
| /// sizeof(CallExpr) + sizeof(Stmt *)> Buffer; |
| /// CallExpr *TheCall = CallExpr::CreateTemporary(Buffer.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; |
| } |
| |
| 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 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; |
| } |
| |
| public: |
| MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc, |
| ValueDecl *memberdecl, const DeclarationNameInfo &NameInfo, |
| QualType ty, ExprValueKind VK, ExprObjectKind OK) |
| : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(), |
| base->isValueDependent(), base->isInstantiationDependent(), |
| base->containsUnexpandedParameterPack()), |
| Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()), |
| MemberLoc(NameInfo.getLoc()) { |
| assert(memberdecl->getDeclName() == NameInfo.getName()); |
| MemberExprBits.IsArrow = isarrow; |
| MemberExprBits.HasQualifierOrFoundDecl = false; |
| MemberExprBits.HasTemplateKWAndArgsInfo = false; |
| MemberExprBits.HadMultipleCandidates = false; |
| MemberExprBits.OperatorLoc = operatorloc; |
| } |
| |
| // NOTE: this constructor should be used only when it is known that |
| // the member name can not provide additional syntactic info |
| // (i.e., source locations for C++ operator names or type source info |
| // for constructors, destructors and conversion operators). |
| MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc, |
| ValueDecl *memberdecl, SourceLocation l, QualType ty, |
| ExprValueKind VK, ExprObjectKind OK) |
| : Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(), |
| base->isValueDependent(), base->isInstantiationDependent(), |
| base->containsUnexpandedParameterPack()), |
| Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l) { |
| MemberExprBits.IsArrow = isarrow; |
| MemberExprBits.HasQualifierOrFoundDecl = false; |
| MemberExprBits.HasTemplateKWAndArgsInfo = false; |
| MemberExprBits.HadMultipleCandidates = false; |
| MemberExprBits.OperatorLoc = operatorloc; |
| } |
| |
| static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow, |
| SourceLocation OperatorLoc, |
| NestedNameSpecifierLoc QualifierLoc, |
| SourceLocation TemplateKWLoc, ValueDecl *memberdecl, |
| DeclAccessPair founddecl, |
| DeclarationNameInfo MemberNameInfo, |
| const TemplateArgumentListInfo *targs, QualType ty, |
| ExprValueKind VK, ExprObjectKind OK); |
| |
| void setBase(Expr *E) { Base = E; } |
| Expr *getBase() const { return cast<Expr>(Base); } |
| |
| /// Retrieve the member declaration to which this expression refers. |
| /// |
| /// The returned declaration will be a FieldDecl or (in C++) a VarDecl (for |
| /// static data members), a CXXMethodDecl, or an EnumConstantDecl. |
| ValueDecl *getMemberDecl() const { return MemberDecl; } |
| void setMemberDecl(ValueDecl *D) { MemberDecl = D; } |
| |
| /// Retrieves the declaration found by lookup. |
| DeclAccessPair getFoundDecl() const { |
| if (!hasQualifierOrFoundDecl()) |
| return DeclAccessPair::make(getMemberDecl(), |
| getMemberDecl()->getAccess()); |
| return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl; |
| } |
| |
| /// Determines whether this member expression actually had |
| /// a C++ nested-name-specifier prior to the name of the member, e.g., |
| /// x->Base::foo. |
| bool hasQualifier() const { return getQualifier() != nullptr; } |
| |
| /// If the member name was qualified, retrieves the |
| /// nested-name-specifier that precedes the member name, with source-location |
| /// information. |
| NestedNameSpecifierLoc getQualifierLoc() const { |
| if (!hasQualifierOrFoundDecl()) |
| return NestedNameSpecifierLoc(); |
| return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc; |
| } |
| |
| /// If the member name was qualified, retrieves the |
| /// nested-name-specifier that precedes the member name. Otherwise, returns |
| /// NULL. |
| NestedNameSpecifier *getQualifier() const { |
| return getQualifierLoc().getNestedNameSpecifier(); |
| } |
| |
| /// Retrieve the location of the template keyword preceding |
| /// the member 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 member 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 member name, if any. |
| SourceLocation getRAngleLoc() const { |
| if (!hasTemplateKWAndArgsInfo()) |
| return SourceLocation(); |
| return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; |
| } |
| |
| /// Determines whether the member name was preceded by the template keyword. |
| bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } |
| |
| /// Determines whether the member name 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()}; |
| } |
| |
| /// Retrieve the member declaration name info. |
| DeclarationNameInfo getMemberNameInfo() const { |
| return DeclarationNameInfo(MemberDecl->getDeclName(), |
| MemberLoc, MemberDNLoc); |
| } |
| |
| SourceLocation getOperatorLoc() const { return MemberExprBits.OperatorLoc; } |
| |
| bool isArrow() const { return MemberExprBits.IsArrow; } |
| void setArrow(bool A) { MemberExprBits.IsArrow = A; } |
| |
| /// getMemberLoc - Return the location of the "member", in X->F, it is the |
| /// location of 'F'. |
| SourceLocation getMemberLoc() const { return MemberLoc; } |
| void setMemberLoc(SourceLocation L) { MemberLoc = L; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY; |
| SourceLocation getEndLoc() const LLVM_READONLY; |
| |
| SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; } |
| |
| /// Determine whether the base of this explicit is implicit. |
| bool isImplicitAccess() const { |
| return getBase() && getBase()->isImplicitCXXThis(); |
| } |
| |
| /// Returns true if this member expression refers to a method that |
| /// was resolved from an overloaded set having size greater than 1. |
| bool hadMultipleCandidates() const { |
| return MemberExprBits.HadMultipleCandidates; |
| } |
| /// Sets the flag telling whether this expression refers to |
| /// a method that was resolved from an overloaded set having size |
| /// greater than 1. |
| void setHadMultipleCandidates(bool V = true) { |
| MemberExprBits.HadMultipleCandidates = V; |
| } |
| |
| /// Returns true if virtual dispatch is performed. |
| /// If the member access is fully qualified, (i.e. X::f()), virtual |
| /// dispatching is not performed. In -fapple-kext mode qualified |
| /// calls to virtual method will still go through the vtable. |
| bool performsVirtualDispatch(const LangOptions &LO) const { |
| return LO.AppleKext || !hasQualifier(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == MemberExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Base, &Base+1); } |
| const_child_range children() const { |
| return const_child_range(&Base, &Base + 1); |
| } |
| }; |
| |
| /// CompoundLiteralExpr - [C99 6.5.2.5] |
| /// |
| class CompoundLiteralExpr : public Expr { |
| /// LParenLoc - If non-null, this is the location of the left paren in a |
| /// compound literal like "(int){4}". This can be null if this is a |
| /// synthesized compound expression. |
| SourceLocation LParenLoc; |
| |
| /// The type as written. This can be an incomplete array type, in |
| /// which case the actual expression type will be different. |
| /// The int part of the pair stores whether this expr is file scope. |
| llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfoAndScope; |
| Stmt *Init; |
| public: |
| CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo, |
| QualType T, ExprValueKind VK, Expr *init, bool fileScope) |
| : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary, |
| tinfo->getType()->isDependentType(), |
| init->isValueDependent(), |
| (init->isInstantiationDependent() || |
| tinfo->getType()->isInstantiationDependentType()), |
| init->containsUnexpandedParameterPack()), |
| LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {} |
| |
| /// Construct an empty compound literal. |
| explicit CompoundLiteralExpr(EmptyShell Empty) |
| : Expr(CompoundLiteralExprClass, Empty) { } |
| |
| const Expr *getInitializer() const { return cast<Expr>(Init); } |
| Expr *getInitializer() { return cast<Expr>(Init); } |
| void setInitializer(Expr *E) { Init = E; } |
| |
| bool isFileScope() const { return TInfoAndScope.getInt(); } |
| void setFileScope(bool FS) { TInfoAndScope.setInt(FS); } |
| |
| SourceLocation getLParenLoc() const { return LParenLoc; } |
| void setLParenLoc(SourceLocation L) { LParenLoc = L; } |
| |
| TypeSourceInfo *getTypeSourceInfo() const { |
| return TInfoAndScope.getPointer(); |
| } |
| void setTypeSourceInfo(TypeSourceInfo *tinfo) { |
| TInfoAndScope.setPointer(tinfo); |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| // FIXME: Init should never be null. |
| if (!Init) |
| return SourceLocation(); |
| if (LParenLoc.isInvalid()) |
| return Init->getBeginLoc(); |
| return LParenLoc; |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| // FIXME: Init should never be null. |
| if (!Init) |
| return SourceLocation(); |
| return Init->getEndLoc(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CompoundLiteralExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Init, &Init+1); } |
| const_child_range children() const { |
| return const_child_range(&Init, &Init + 1); |
| } |
| }; |
| |
| /// CastExpr - Base class for type casts, including both implicit |
| /// casts (ImplicitCastExpr) and explicit casts that have some |
| /// representation in the source code (ExplicitCastExpr's derived |
| /// classes). |
| class CastExpr : public Expr { |
| Stmt *Op; |
| |
| bool CastConsistency() const; |
| |
| const CXXBaseSpecifier * const *path_buffer() const { |
| return const_cast<CastExpr*>(this)->path_buffer(); |
| } |
| CXXBaseSpecifier **path_buffer(); |
| |
| protected: |
| CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind, |
| Expr *op, unsigned BasePathSize) |
| : Expr(SC, ty, VK, OK_Ordinary, |
| // Cast expressions are type-dependent if the type is |
| // dependent (C++ [temp.dep.expr]p3). |
| ty->isDependentType(), |
| // Cast expressions are value-dependent if the type is |
| // dependent or if the subexpression is value-dependent. |
| ty->isDependentType() || (op && op->isValueDependent()), |
| (ty->isInstantiationDependentType() || |
| (op && op->isInstantiationDependent())), |
| // An implicit cast expression doesn't (lexically) contain an |
| // unexpanded pack, even if its target type does. |
| ((SC != ImplicitCastExprClass && |
| ty->containsUnexpandedParameterPack()) || |
| (op && op->containsUnexpandedParameterPack()))), |
| Op(op) { |
| CastExprBits.Kind = kind; |
| CastExprBits.PartOfExplicitCast = false; |
| CastExprBits.BasePathSize = BasePathSize; |
| assert((CastExprBits.BasePathSize == BasePathSize) && |
| "BasePathSize overflow!"); |
| assert(CastConsistency()); |
| } |
| |
| /// Construct an empty cast. |
| CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) |
| : Expr(SC, Empty) { |
| CastExprBits.PartOfExplicitCast = false; |
| CastExprBits.BasePathSize = BasePathSize; |
| assert((CastExprBits.BasePathSize == BasePathSize) && |
| "BasePathSize overflow!"); |
| } |
| |
| public: |
| CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; } |
| void setCastKind(CastKind K) { CastExprBits.Kind = K; } |
| |
| static const char *getCastKindName(CastKind CK); |
| const char *getCastKindName() const { return getCastKindName(getCastKind()); } |
| |
| Expr *getSubExpr() { return cast<Expr>(Op); } |
| const Expr *getSubExpr() const { return cast<Expr>(Op); } |
| void setSubExpr(Expr *E) { Op = E; } |
| |
| /// Retrieve the cast subexpression as it was written in the source |
| /// code, looking through any implicit casts or other intermediate nodes |
| /// introduced by semantic analysis. |
| Expr *getSubExprAsWritten(); |
| const Expr *getSubExprAsWritten() const { |
| return const_cast<CastExpr *>(this)->getSubExprAsWritten(); |
| } |
| |
| /// If this cast applies a user-defined conversion, retrieve the conversion |
| /// function that it invokes. |
| NamedDecl *getConversionFunction() const; |
| |
| typedef CXXBaseSpecifier **path_iterator; |
| typedef const CXXBaseSpecifier *const *path_const_iterator; |
| bool path_empty() const { return path_size() == 0; } |
| unsigned path_size() const { return CastExprBits.BasePathSize; } |
| path_iterator path_begin() { return path_buffer(); } |
| path_iterator path_end() { return path_buffer() + path_size(); } |
| path_const_iterator path_begin() const { return path_buffer(); } |
| path_const_iterator path_end() const { return path_buffer() + path_size(); } |
| |
| const FieldDecl *getTargetUnionField() const { |
| assert(getCastKind() == CK_ToUnion); |
| return getTargetFieldForToUnionCast(getType(), getSubExpr()->getType()); |
| } |
| |
| static const FieldDecl *getTargetFieldForToUnionCast(QualType unionType, |
| QualType opType); |
| static const FieldDecl *getTargetFieldForToUnionCast(const RecordDecl *RD, |
| QualType opType); |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() >= firstCastExprConstant && |
| T->getStmtClass() <= lastCastExprConstant; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Op, &Op+1); } |
| const_child_range children() const { return const_child_range(&Op, &Op + 1); } |
| }; |
| |
| /// ImplicitCastExpr - Allows us to explicitly represent implicit type |
| /// conversions, which have no direct representation in the original |
| /// source code. For example: converting T[]->T*, void f()->void |
| /// (*f)(), float->double, short->int, etc. |
| /// |
| /// In C, implicit casts always produce rvalues. However, in C++, an |
| /// implicit cast whose result is being bound to a reference will be |
| /// an lvalue or xvalue. For example: |
| /// |
| /// @code |
| /// class Base { }; |
| /// class Derived : public Base { }; |
| /// Derived &&ref(); |
| /// void f(Derived d) { |
| /// Base& b = d; // initializer is an ImplicitCastExpr |
| /// // to an lvalue of type Base |
| /// Base&& r = ref(); // initializer is an ImplicitCastExpr |
| /// // to an xvalue of type Base |
| /// } |
| /// @endcode |
| class ImplicitCastExpr final |
| : public CastExpr, |
| private llvm::TrailingObjects<ImplicitCastExpr, CXXBaseSpecifier *> { |
| |
| ImplicitCastExpr(QualType ty, CastKind kind, Expr *op, |
| unsigned BasePathLength, ExprValueKind VK) |
| : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) { } |
| |
| /// Construct an empty implicit cast. |
| explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize) |
| : CastExpr(ImplicitCastExprClass, Shell, PathSize) { } |
| |
| public: |
| enum OnStack_t { OnStack }; |
| ImplicitCastExpr(OnStack_t _, QualType ty, CastKind kind, Expr *op, |
| ExprValueKind VK) |
| : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) { |
| } |
| |
| bool isPartOfExplicitCast() const { return CastExprBits.PartOfExplicitCast; } |
| void setIsPartOfExplicitCast(bool PartOfExplicitCast) { |
| CastExprBits.PartOfExplicitCast = PartOfExplicitCast; |
| } |
| |
| static ImplicitCastExpr *Create(const ASTContext &Context, QualType T, |
| CastKind Kind, Expr *Operand, |
| const CXXCastPath *BasePath, |
| ExprValueKind Cat); |
| |
| static ImplicitCastExpr *CreateEmpty(const ASTContext &Context, |
| unsigned PathSize); |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return getSubExpr()->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return getSubExpr()->getEndLoc(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ImplicitCastExprClass; |
| } |
| |
| friend TrailingObjects; |
| friend class CastExpr; |
| }; |
| |
| /// ExplicitCastExpr - An explicit cast written in the source |
| /// code. |
| /// |
| /// This class is effectively an abstract class, because it provides |
| /// the basic representation of an explicitly-written cast without |
| /// specifying which kind of cast (C cast, functional cast, static |
| /// cast, etc.) was written; specific derived classes represent the |
| /// particular style of cast and its location information. |
| /// |
| /// Unlike implicit casts, explicit cast nodes have two different |
| /// types: the type that was written into the source code, and the |
| /// actual type of the expression as determined by semantic |
| /// analysis. These types may differ slightly. For example, in C++ one |
| /// can cast to a reference type, which indicates that the resulting |
| /// expression will be an lvalue or xvalue. The reference type, however, |
| /// will not be used as the type of the expression. |
| class ExplicitCastExpr : public CastExpr { |
| /// TInfo - Source type info for the (written) type |
| /// this expression is casting to. |
| TypeSourceInfo *TInfo; |
| |
| protected: |
| ExplicitCastExpr(StmtClass SC, QualType exprTy, ExprValueKind VK, |
| CastKind kind, Expr *op, unsigned PathSize, |
| TypeSourceInfo *writtenTy) |
| : CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {} |
| |
| /// Construct an empty explicit cast. |
| ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) |
| : CastExpr(SC, Shell, PathSize) { } |
| |
| public: |
| /// getTypeInfoAsWritten - Returns the type source info for the type |
| /// that this expression is casting to. |
| TypeSourceInfo *getTypeInfoAsWritten() const { return TInfo; } |
| void setTypeInfoAsWritten(TypeSourceInfo *writtenTy) { TInfo = writtenTy; } |
| |
| /// getTypeAsWritten - Returns the type that this expression is |
| /// casting to, as written in the source code. |
| QualType getTypeAsWritten() const { return TInfo->getType(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() >= firstExplicitCastExprConstant && |
| T->getStmtClass() <= lastExplicitCastExprConstant; |
| } |
| }; |
| |
| /// CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style |
| /// cast in C++ (C++ [expr.cast]), which uses the syntax |
| /// (Type)expr. For example: @c (int)f. |
| class CStyleCastExpr final |
| : public ExplicitCastExpr, |
| private llvm::TrailingObjects<CStyleCastExpr, CXXBaseSpecifier *> { |
| SourceLocation LPLoc; // the location of the left paren |
| SourceLocation RPLoc; // the location of the right paren |
| |
| CStyleCastExpr(QualType exprTy, ExprValueKind vk, CastKind kind, Expr *op, |
| unsigned PathSize, TypeSourceInfo *writtenTy, |
| SourceLocation l, SourceLocation r) |
| : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize, |
| writtenTy), LPLoc(l), RPLoc(r) {} |
| |
| /// Construct an empty C-style explicit cast. |
| explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize) |
| : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { } |
| |
| public: |
| static CStyleCastExpr *Create(const ASTContext &Context, QualType T, |
| ExprValueKind VK, CastKind K, |
| Expr *Op, const CXXCastPath *BasePath, |
| TypeSourceInfo *WrittenTy, SourceLocation L, |
| SourceLocation R); |
| |
| static CStyleCastExpr *CreateEmpty(const ASTContext &Context, |
| unsigned PathSize); |
| |
| SourceLocation getLParenLoc() const { return LPLoc; } |
| void setLParenLoc(SourceLocation L) { LPLoc = L; } |
| |
| SourceLocation getRParenLoc() const { return RPLoc; } |
| void setRParenLoc(SourceLocation L) { RPLoc = L; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return LPLoc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return getSubExpr()->getEndLoc(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == CStyleCastExprClass; |
| } |
| |
| friend TrailingObjects; |
| friend class CastExpr; |
| }; |
| |
| /// A builtin binary operation expression such as "x + y" or "x <= y". |
| /// |
| /// This expression node kind describes a builtin binary operation, |
| /// such as "x + y" for integer values "x" and "y". The operands will |
| /// already have been converted to appropriate types (e.g., by |
| /// performing promotions or conversions). |
| /// |
| /// In C++, where operators may be overloaded, a different kind of |
| /// expression node (CXXOperatorCallExpr) is used to express the |
| /// invocation of an overloaded operator with operator syntax. Within |
| /// a C++ template, whether BinaryOperator or CXXOperatorCallExpr is |
| /// used to store an expression "x + y" depends on the subexpressions |
| /// for x and y. If neither x or y is type-dependent, and the "+" |
| /// operator resolves to a built-in operation, BinaryOperator will be |
| /// used to express the computation (x and y may still be |
| /// value-dependent). If either x or y is type-dependent, or if the |
| /// "+" resolves to an overloaded operator, CXXOperatorCallExpr will |
| /// be used to express the computation. |
| class BinaryOperator : public Expr { |
| enum { LHS, RHS, END_EXPR }; |
| Stmt *SubExprs[END_EXPR]; |
| |
| public: |
| typedef BinaryOperatorKind Opcode; |
| |
| BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, |
| ExprValueKind VK, ExprObjectKind OK, |
| SourceLocation opLoc, FPOptions FPFeatures) |
| : Expr(BinaryOperatorClass, ResTy, VK, OK, |
| lhs->isTypeDependent() || rhs->isTypeDependent(), |
| lhs->isValueDependent() || rhs->isValueDependent(), |
| (lhs->isInstantiationDependent() || |
| rhs->isInstantiationDependent()), |
| (lhs->containsUnexpandedParameterPack() || |
| rhs->containsUnexpandedParameterPack())) { |
| BinaryOperatorBits.Opc = opc; |
| BinaryOperatorBits.FPFeatures = FPFeatures.getInt(); |
| BinaryOperatorBits.OpLoc = opLoc; |
| SubExprs[LHS] = lhs; |
| SubExprs[RHS] = rhs; |
| assert(!isCompoundAssignmentOp() && |
| "Use CompoundAssignOperator for compound assignments"); |
| } |
| |
| /// Construct an empty binary operator. |
| explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty) { |
| BinaryOperatorBits.Opc = BO_Comma; |
| } |
| |
| SourceLocation getExprLoc() const { return getOperatorLoc(); } |
| SourceLocation getOperatorLoc() const { return BinaryOperatorBits.OpLoc; } |
| void setOperatorLoc(SourceLocation L) { BinaryOperatorBits.OpLoc = L; } |
| |
| Opcode getOpcode() const { |
| return static_cast<Opcode>(BinaryOperatorBits.Opc); |
| } |
| void setOpcode(Opcode Opc) { BinaryOperatorBits.Opc = Opc; } |
| |
| Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } |
| void setLHS(Expr *E) { SubExprs[LHS] = E; } |
| Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } |
| void setRHS(Expr *E) { SubExprs[RHS] = E; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return getLHS()->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return getRHS()->getEndLoc(); |
| } |
| |
| /// getOpcodeStr - Turn an Opcode enum value into the punctuation char it |
| /// corresponds to, e.g. "<<=". |
| static StringRef getOpcodeStr(Opcode Op); |
| |
| StringRef getOpcodeStr() const { return getOpcodeStr(getOpcode()); } |
| |
| /// Retrieve the binary opcode that corresponds to the given |
| /// overloaded operator. |
| static Opcode getOverloadedOpcode(OverloadedOperatorKind OO); |
| |
| /// Retrieve the overloaded operator kind that corresponds to |
| /// the given binary opcode. |
| static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); |
| |
| /// predicates to categorize the respective opcodes. |
| static bool isPtrMemOp(Opcode Opc) { |
| return Opc == BO_PtrMemD || Opc == BO_PtrMemI; |
| } |
| bool isPtrMemOp() const { return isPtrMemOp(getOpcode()); } |
| |
| static bool isMultiplicativeOp(Opcode Opc) { |
| return Opc >= BO_Mul && Opc <= BO_Rem; |
| } |
| bool isMultiplicativeOp() const { return isMultiplicativeOp(getOpcode()); } |
| static bool isAdditiveOp(Opcode Opc) { return Opc == BO_Add || Opc==BO_Sub; } |
| bool isAdditiveOp() const { return isAdditiveOp(getOpcode()); } |
| static bool isShiftOp(Opcode Opc) { return Opc == BO_Shl || Opc == BO_Shr; } |
| bool isShiftOp() const { return isShiftOp(getOpcode()); } |
| |
| static bool isBitwiseOp(Opcode Opc) { return Opc >= BO_And && Opc <= BO_Or; } |
| bool isBitwiseOp() const { return isBitwiseOp(getOpcode()); } |
| |
| static bool isRelationalOp(Opcode Opc) { return Opc >= BO_LT && Opc<=BO_GE; } |
| bool isRelationalOp() const { return isRelationalOp(getOpcode()); } |
| |
| static bool isEqualityOp(Opcode Opc) { return Opc == BO_EQ || Opc == BO_NE; } |
| bool isEqualityOp() const { return isEqualityOp(getOpcode()); } |
| |
| static bool isComparisonOp(Opcode Opc) { return Opc >= BO_Cmp && Opc<=BO_NE; } |
| bool isComparisonOp() const { return isComparisonOp(getOpcode()); } |
| |
| static Opcode negateComparisonOp(Opcode Opc) { |
| switch (Opc) { |
| default: |
| llvm_unreachable("Not a comparison operator."); |
| case BO_LT: return BO_GE; |
| case BO_GT: return BO_LE; |
| case BO_LE: return BO_GT; |
| case BO_GE: return BO_LT; |
| case BO_EQ: return BO_NE; |
| case BO_NE: return BO_EQ; |
| } |
| } |
| |
| static Opcode reverseComparisonOp(Opcode Opc) { |
| switch (Opc) { |
| default: |
| llvm_unreachable("Not a comparison operator."); |
| case BO_LT: return BO_GT; |
| case BO_GT: return BO_LT; |
| case BO_LE: return BO_GE; |
| case BO_GE: return BO_LE; |
| case BO_EQ: |
| case BO_NE: |
| return Opc; |
| } |
| } |
| |
| static bool isLogicalOp(Opcode Opc) { return Opc == BO_LAnd || Opc==BO_LOr; } |
| bool isLogicalOp() const { return isLogicalOp(getOpcode()); } |
| |
| static bool isAssignmentOp(Opcode Opc) { |
| return Opc >= BO_Assign && Opc <= BO_OrAssign; |
| } |
| bool isAssignmentOp() const { return isAssignmentOp(getOpcode()); } |
| |
| static bool isCompoundAssignmentOp(Opcode Opc) { |
| return Opc > BO_Assign && Opc <= BO_OrAssign; |
| } |
| bool isCompoundAssignmentOp() const { |
| return isCompoundAssignmentOp(getOpcode()); |
| } |
| static Opcode getOpForCompoundAssignment(Opcode Opc) { |
| assert(isCompoundAssignmentOp(Opc)); |
| if (Opc >= BO_AndAssign) |
| return Opcode(unsigned(Opc) - BO_AndAssign + BO_And); |
| else |
| return Opcode(unsigned(Opc) - BO_MulAssign + BO_Mul); |
| } |
| |
| static bool isShiftAssignOp(Opcode Opc) { |
| return Opc == BO_ShlAssign || Opc == BO_ShrAssign; |
| } |
| bool isShiftAssignOp() const { |
| return isShiftAssignOp(getOpcode()); |
| } |
| |
| // Return true if a binary operator using the specified opcode and operands |
| // would match the 'p = (i8*)nullptr + n' idiom for casting a pointer-sized |
| // integer to a pointer. |
| static bool isNullPointerArithmeticExtension(ASTContext &Ctx, Opcode Opc, |
| Expr *LHS, Expr *RHS); |
| |
| static bool classof(const Stmt *S) { |
| return S->getStmtClass() >= firstBinaryOperatorConstant && |
| S->getStmtClass() <= lastBinaryOperatorConstant; |
| } |
| |
| // 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); |
| } |
| |
| // Set the FP contractability status of this operator. Only meaningful for |
| // operations on floating point types. |
| void setFPFeatures(FPOptions F) { |
| BinaryOperatorBits.FPFeatures = F.getInt(); |
| } |
| |
| FPOptions getFPFeatures() const { |
| return FPOptions(BinaryOperatorBits.FPFeatures); |
| } |
| |
| // Get the FP contractability status of this operator. Only meaningful for |
| // operations on floating point types. |
| bool isFPContractableWithinStatement() const { |
| return getFPFeatures().allowFPContractWithinStatement(); |
| } |
| |
| // Get the FENV_ACCESS status of this operator. Only meaningful for |
| // operations on floating point types. |
| bool isFEnvAccessOn() const { return getFPFeatures().allowFEnvAccess(); } |
| |
| protected: |
| BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, |
| ExprValueKind VK, ExprObjectKind OK, |
| SourceLocation opLoc, FPOptions FPFeatures, bool dead2) |
| : Expr(CompoundAssignOperatorClass, ResTy, VK, OK, |
| lhs->isTypeDependent() || rhs->isTypeDependent(), |
| lhs->isValueDependent() || rhs->isValueDependent(), |
| (lhs->isInstantiationDependent() || |
| rhs->isInstantiationDependent()), |
| (lhs->containsUnexpandedParameterPack() || |
| rhs->containsUnexpandedParameterPack())) { |
| BinaryOperatorBits.Opc = opc; |
| BinaryOperatorBits.FPFeatures = FPFeatures.getInt(); |
| BinaryOperatorBits.OpLoc = opLoc; |
| SubExprs[LHS] = lhs; |
| SubExprs[RHS] = rhs; |
| } |
| |
| BinaryOperator(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty) { |
| BinaryOperatorBits.Opc = BO_MulAssign; |
| } |
| }; |
| |
| /// CompoundAssignOperator - For compound assignments (e.g. +=), we keep |
| /// track of the type the operation is performed in. Due to the semantics of |
| /// these operators, the operands are promoted, the arithmetic performed, an |
| /// implicit conversion back to the result type done, then the assignment takes |
| /// place. This captures the intermediate type which the computation is done |
| /// in. |
| class CompoundAssignOperator : public BinaryOperator { |
| QualType ComputationLHSType; |
| QualType ComputationResultType; |
| public: |
| CompoundAssignOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResType, |
| ExprValueKind VK, ExprObjectKind OK, |
| QualType CompLHSType, QualType CompResultType, |
| SourceLocation OpLoc, FPOptions FPFeatures) |
| : BinaryOperator(lhs, rhs, opc, ResType, VK, OK, OpLoc, FPFeatures, |
| true), |
| ComputationLHSType(CompLHSType), |
| ComputationResultType(CompResultType) { |
| assert(isCompoundAssignmentOp() && |
| "Only should be used for compound assignments"); |
| } |
| |
| /// Build an empty compound assignment operator expression. |
| explicit CompoundAssignOperator(EmptyShell Empty) |
| : BinaryOperator(CompoundAssignOperatorClass, Empty) { } |
| |
| // The two computation types are the type the LHS is converted |
| // to for the computation and the type of the result; the two are |
| // distinct in a few cases (specifically, int+=ptr and ptr-=ptr). |
| QualType getComputationLHSType() const { return ComputationLHSType; } |
| void setComputationLHSType(QualType T) { ComputationLHSType = T; } |
| |
| QualType getComputationResultType() const { return ComputationResultType; } |
| void setComputationResultType(QualType T) { ComputationResultType = T; } |
| |
| static bool classof(const Stmt *S) { |
| return S->getStmtClass() == CompoundAssignOperatorClass; |
| } |
| }; |
| |
| /// AbstractConditionalOperator - An abstract base class for |
| /// ConditionalOperator and BinaryConditionalOperator. |
| class AbstractConditionalOperator : public Expr { |
| SourceLocation QuestionLoc, ColonLoc; |
| friend class ASTStmtReader; |
| |
| protected: |
| AbstractConditionalOperator(StmtClass SC, QualType T, |
| ExprValueKind VK, ExprObjectKind OK, |
| bool TD, bool VD, bool ID, |
| bool ContainsUnexpandedParameterPack, |
| SourceLocation qloc, |
| SourceLocation cloc) |
| : Expr(SC, T, VK, OK, TD, VD, ID, ContainsUnexpandedParameterPack), |
| QuestionLoc(qloc), ColonLoc(cloc) {} |
| |
| AbstractConditionalOperator(StmtClass SC, EmptyShell Empty) |
| : Expr(SC, Empty) { } |
| |
| public: |
| // getCond - Return the expression representing the condition for |
| // the ?: operator. |
| Expr *getCond() const; |
| |
| // getTrueExpr - Return the subexpression representing the value of |
| // the expression if the condition evaluates to true. |
| Expr *getTrueExpr() const; |
| |
| // getFalseExpr - Return the subexpression representing the value of |
| // the expression if the condition evaluates to false. This is |
| // the same as getRHS. |
| Expr *getFalseExpr() const; |
| |
| SourceLocation getQuestionLoc() const { return QuestionLoc; } |
| SourceLocation getColonLoc() const { return ColonLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ConditionalOperatorClass || |
| T->getStmtClass() == BinaryConditionalOperatorClass; |
| } |
| }; |
| |
| /// ConditionalOperator - The ?: ternary operator. The GNU "missing |
| /// middle" extension is a BinaryConditionalOperator. |
| class ConditionalOperator : public AbstractConditionalOperator { |
| enum { COND, LHS, RHS, END_EXPR }; |
| Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. |
| |
| friend class ASTStmtReader; |
| public: |
| ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs, |
| SourceLocation CLoc, Expr *rhs, |
| QualType t, ExprValueKind VK, ExprObjectKind OK) |
| : AbstractConditionalOperator(ConditionalOperatorClass, t, VK, OK, |
| // FIXME: the type of the conditional operator doesn't |
| // depend on the type of the conditional, but the standard |
| // seems to imply that it could. File a bug! |
| (lhs->isTypeDependent() || rhs->isTypeDependent()), |
| (cond->isValueDependent() || lhs->isValueDependent() || |
| rhs->isValueDependent()), |
| (cond->isInstantiationDependent() || |
| lhs->isInstantiationDependent() || |
| rhs->isInstantiationDependent()), |
| (cond->containsUnexpandedParameterPack() || |
| lhs->containsUnexpandedParameterPack() || |
| rhs->containsUnexpandedParameterPack()), |
| QLoc, CLoc) { |
| SubExprs[COND] = cond; |
| SubExprs[LHS] = lhs; |
| SubExprs[RHS] = rhs; |
| } |
| |
| /// Build an empty conditional operator. |
| explicit ConditionalOperator(EmptyShell Empty) |
| : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { } |
| |
| // getCond - Return the expression representing the condition for |
| // the ?: operator. |
| Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } |
| |
| // getTrueExpr - Return the subexpression representing the value of |
| // the expression if the condition evaluates to true. |
| Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS]); } |
| |
| // getFalseExpr - Return the subexpression representing the value of |
| // the expression if the condition evaluates to false. This is |
| // the same as getRHS. |
| Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); } |
| |
| Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } |
| Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return getCond()->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return getRHS()->getEndLoc(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ConditionalOperatorClass; |
| } |
| |
| // 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); |
| } |
| }; |
| |
| /// BinaryConditionalOperator - The GNU extension to the conditional |
| /// operator which allows the middle operand to be omitted. |
| /// |
| /// This is a different expression kind on the assumption that almost |
| /// every client ends up needing to know that these are different. |
| class BinaryConditionalOperator : public AbstractConditionalOperator { |
| enum { COMMON, COND, LHS, RHS, NUM_SUBEXPRS }; |
| |
| /// - the common condition/left-hand-side expression, which will be |
| /// evaluated as the opaque value |
| /// - the condition, expressed in terms of the opaque value |
| /// - the left-hand-side, expressed in terms of the opaque value |
| /// - the right-hand-side |
| Stmt *SubExprs[NUM_SUBEXPRS]; |
| OpaqueValueExpr *OpaqueValue; |
| |
| friend class ASTStmtReader; |
| public: |
| BinaryConditionalOperator(Expr *common, OpaqueValueExpr *opaqueValue, |
| Expr *cond, Expr *lhs, Expr *rhs, |
| SourceLocation qloc, SourceLocation cloc, |
| QualType t, ExprValueKind VK, ExprObjectKind OK) |
| : AbstractConditionalOperator(BinaryConditionalOperatorClass, t, VK, OK, |
| (common->isTypeDependent() || rhs->isTypeDependent()), |
| (common->isValueDependent() || rhs->isValueDependent()), |
| (common->isInstantiationDependent() || |
| rhs->isInstantiationDependent()), |
| (common->containsUnexpandedParameterPack() || |
| rhs->containsUnexpandedParameterPack()), |
| qloc, cloc), |
| OpaqueValue(opaqueValue) { |
| SubExprs[COMMON] = common; |
| SubExprs[COND] = cond; |
| SubExprs[LHS] = lhs; |
| SubExprs[RHS] = rhs; |
| assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value"); |
| } |
| |
| /// Build an empty conditional operator. |
| explicit BinaryConditionalOperator(EmptyShell Empty) |
| : AbstractConditionalOperator(BinaryConditionalOperatorClass, Empty) { } |
| |
| /// getCommon - Return the common expression, written to the |
| /// left of the condition. The opaque value will be bound to the |
| /// result of this expression. |
| Expr *getCommon() const { return cast<Expr>(SubExprs[COMMON]); } |
| |
| /// getOpaqueValue - Return the opaque value placeholder. |
| OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; } |
| |
| /// getCond - Return the condition expression; this is defined |
| /// in terms of the opaque value. |
| Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } |
| |
| /// getTrueExpr - Return the subexpression which will be |
| /// evaluated if the condition evaluates to true; this is defined |
| /// in terms of the opaque value. |
| Expr *getTrueExpr() const { |
| return cast<Expr>(SubExprs[LHS]); |
| } |
| |
| /// getFalseExpr - Return the subexpression which will be |
| /// evaluated if the condnition evaluates to false; this is |
| /// defined in terms of the opaque value. |
| Expr *getFalseExpr() const { |
| return cast<Expr>(SubExprs[RHS]); |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return getCommon()->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return getFalseExpr()->getEndLoc(); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == BinaryConditionalOperatorClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(SubExprs, SubExprs + NUM_SUBEXPRS); |
| } |
| const_child_range children() const { |
| return const_child_range(SubExprs, SubExprs + NUM_SUBEXPRS); |
| } |
| }; |
| |
| inline Expr *AbstractConditionalOperator::getCond() const { |
| if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this)) |
| return co->getCond(); |
| return cast<BinaryConditionalOperator>(this)->getCond(); |
| } |
| |
| inline Expr *AbstractConditionalOperator::getTrueExpr() const { |
| if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this)) |
| return co->getTrueExpr(); |
| return cast<BinaryConditionalOperator>(this)->getTrueExpr(); |
| } |
| |
| inline Expr *AbstractConditionalOperator::getFalseExpr() const { |
| if (const ConditionalOperator *co = dyn_cast<ConditionalOperator>(this)) |
| return co->getFalseExpr(); |
| return cast<BinaryConditionalOperator>(this)->getFalseExpr(); |
| } |
| |
| /// AddrLabelExpr - The GNU address of label extension, representing &&label. |
| class AddrLabelExpr : public Expr { |
| SourceLocation AmpAmpLoc, LabelLoc; |
| LabelDecl *Label; |
| public: |
| AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L, |
| QualType t) |
| : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false, |
| false), |
| AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {} |
| |
| /// Build an empty address of a label expression. |
| explicit AddrLabelExpr(EmptyShell Empty) |
| : Expr(AddrLabelExprClass, Empty) { } |
| |
| SourceLocation getAmpAmpLoc() const { return AmpAmpLoc; } |
| void setAmpAmpLoc(SourceLocation L) { AmpAmpLoc = L; } |
| SourceLocation getLabelLoc() const { return LabelLoc; } |
| void setLabelLoc(SourceLocation L) { LabelLoc = L; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return AmpAmpLoc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return LabelLoc; } |
| |
| LabelDecl *getLabel() const { return Label; } |
| void setLabel(LabelDecl *L) { Label = L; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == AddrLabelExprClass; |
| } |
| |
| // 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()); |
| } |
| }; |
| |
| /// StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}). |
| /// The StmtExpr contains a single CompoundStmt node, which it evaluates and |
| /// takes the value of the last subexpression. |
| /// |
| /// A StmtExpr is always an r-value; values "returned" out of a |
| /// StmtExpr will be copied. |
| class StmtExpr : public Expr { |
| Stmt *SubStmt; |
| SourceLocation LParenLoc, RParenLoc; |
| public: |
| // FIXME: Does type-dependence need to be computed differently? |
| // FIXME: Do we need to compute instantiation instantiation-dependence for |
| // statements? (ugh!) |
| StmtExpr(CompoundStmt *substmt, QualType T, |
| SourceLocation lp, SourceLocation rp) : |
| Expr(StmtExprClass, T, VK_RValue, OK_Ordinary, |
| T->isDependentType(), false, false, false), |
| SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { } |
| |
| /// Build an empty statement expression. |
| explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { } |
| |
| CompoundStmt *getSubStmt() { return cast<CompoundStmt>(SubStmt); } |
| const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); } |
| void setSubStmt(CompoundStmt *S) { SubStmt = S; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return LParenLoc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
| |
| SourceLocation getLParenLoc() const { return LParenLoc; } |
| void setLParenLoc(SourceLocation L) { LParenLoc = L; } |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == StmtExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&SubStmt, &SubStmt+1); } |
| const_child_range children() const { |
| return const_child_range(&SubStmt, &SubStmt + 1); |
| } |
| }; |
| |
| /// ShuffleVectorExpr - clang-specific builtin-in function |
| /// __builtin_shufflevector. |
| /// This AST node represents a operator that does a constant |
| /// shuffle, similar to LLVM's shufflevector instruction. It takes |
| /// two vectors and a variable number of constant indices, |
| /// and returns the appropriately shuffled vector. |
| class ShuffleVectorExpr : public Expr { |
| SourceLocation BuiltinLoc, RParenLoc; |
| |
| // SubExprs - the list of values passed to the __builtin_shufflevector |
| // function. The first two are vectors, and the rest are constant |
| // indices. The number of values in this list is always |
| // 2+the number of indices in the vector type. |
| Stmt **SubExprs; |
| unsigned NumExprs; |
| |
| public: |
| ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args, QualType Type, |
| SourceLocation BLoc, SourceLocation RP); |
| |
| /// Build an empty vector-shuffle expression. |
| explicit ShuffleVectorExpr(EmptyShell Empty) |
| : Expr(ShuffleVectorExprClass, Empty), SubExprs(nullptr) { } |
| |
| SourceLocation getBuiltinLoc() const { return BuiltinLoc; } |
| void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } |
| |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ShuffleVectorExprClass; |
| } |
| |
| /// getNumSubExprs - Return the size of the SubExprs array. This includes the |
| /// constant expression, the actual arguments passed in, and the function |
| /// pointers. |
| unsigned getNumSubExprs() const { return NumExprs; } |
| |
| /// Retrieve the array of expressions. |
| Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); } |
| |
| /// getExpr - Return the Expr at the specified index. |
| Expr *getExpr(unsigned Index) { |
| assert((Index < NumExprs) && "Arg access out of range!"); |
| return cast<Expr>(SubExprs[Index]); |
| } |
| const Expr *getExpr(unsigned Index) const { |
| assert((Index < NumExprs) && "Arg access out of range!"); |
| return cast<Expr>(SubExprs[Index]); |
| } |
| |
| void setExprs(const ASTContext &C, ArrayRef<Expr *> Exprs); |
| |
| llvm::APSInt getShuffleMaskIdx(const ASTContext &Ctx, unsigned N) const { |
| assert((N < NumExprs - 2) && "Shuffle idx out of range!"); |
| return getExpr(N+2)->EvaluateKnownConstInt(Ctx); |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(&SubExprs[0], &SubExprs[0]+NumExprs); |
| } |
| const_child_range children() const { |
| return const_child_range(&SubExprs[0], &SubExprs[0] + NumExprs); |
| } |
| }; |
| |
| /// ConvertVectorExpr - Clang builtin function __builtin_convertvector |
| /// This AST node provides support for converting a vector type to another |
| /// vector type of the same arity. |
| class ConvertVectorExpr : public Expr { |
| private: |
| Stmt *SrcExpr; |
| TypeSourceInfo *TInfo; |
| SourceLocation BuiltinLoc, RParenLoc; |
| |
| friend class ASTReader; |
| friend class ASTStmtReader; |
| explicit ConvertVectorExpr(EmptyShell Empty) : Expr(ConvertVectorExprClass, Empty) {} |
| |
| public: |
| ConvertVectorExpr(Expr* SrcExpr, TypeSourceInfo *TI, QualType DstType, |
| ExprValueKind VK, ExprObjectKind OK, |
| SourceLocation BuiltinLoc, SourceLocation RParenLoc) |
| : Expr(ConvertVectorExprClass, DstType, VK, OK, |
| DstType->isDependentType(), |
| DstType->isDependentType() || SrcExpr->isValueDependent(), |
| (DstType->isInstantiationDependentType() || |
| SrcExpr->isInstantiationDependent()), |
| (DstType->containsUnexpandedParameterPack() || |
| SrcExpr->containsUnexpandedParameterPack())), |
| SrcExpr(SrcExpr), TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} |
| |
| /// getSrcExpr - Return the Expr to be converted. |
| Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); } |
| |
| /// getTypeSourceInfo - Return the destination type. |
| TypeSourceInfo *getTypeSourceInfo() const { |
| return TInfo; |
| } |
| void setTypeSourceInfo(TypeSourceInfo *ti) { |
| TInfo = ti; |
| } |
| |
| /// getBuiltinLoc - Return the location of the __builtin_convertvector token. |
| SourceLocation getBuiltinLoc() const { return BuiltinLoc; } |
| |
| /// getRParenLoc - Return the location of final right parenthesis. |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ConvertVectorExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } |
| const_child_range children() const { |
| return const_child_range(&SrcExpr, &SrcExpr + 1); |
| } |
| }; |
| |
| /// ChooseExpr - GNU builtin-in function __builtin_choose_expr. |
| /// This AST node is similar to the conditional operator (?:) in C, with |
| /// the following exceptions: |
| /// - the test expression must be a integer constant expression. |
| /// - the expression returned acts like the chosen subexpression in every |
| /// visible way: the type is the same as that of the chosen subexpression, |
| /// and all predicates (whether it's an l-value, whether it's an integer |
| /// constant expression, etc.) return the same result as for the chosen |
| /// sub-expression. |
| class ChooseExpr : public Expr { |
| enum { COND, LHS, RHS, END_EXPR }; |
| Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. |
| SourceLocation BuiltinLoc, RParenLoc; |
| bool CondIsTrue; |
| public: |
| ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, |
| QualType t, ExprValueKind VK, ExprObjectKind OK, |
| SourceLocation RP, bool condIsTrue, |
| bool TypeDependent, bool ValueDependent) |
| : Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent, |
| (cond->isInstantiationDependent() || |
| lhs->isInstantiationDependent() || |
| rhs->isInstantiationDependent()), |
| (cond->containsUnexpandedParameterPack() || |
| lhs->containsUnexpandedParameterPack() || |
| rhs->containsUnexpandedParameterPack())), |
| BuiltinLoc(BLoc), RParenLoc(RP), CondIsTrue(condIsTrue) { |
| SubExprs[COND] = cond; |
| SubExprs[LHS] = lhs; |
| SubExprs[RHS] = rhs; |
| } |
| |
| /// Build an empty __builtin_choose_expr. |
| explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { } |
| |
| /// isConditionTrue - Return whether the condition is true (i.e. not |
| /// equal to zero). |
| bool isConditionTrue() const { |
| assert(!isConditionDependent() && |
| "Dependent condition isn't true or false"); |
| return CondIsTrue; |
| } |
| void setIsConditionTrue(bool isTrue) { CondIsTrue = isTrue; } |
| |
| bool isConditionDependent() const { |
| return getCond()->isTypeDependent() || getCond()->isValueDependent(); |
| } |
| |
| /// getChosenSubExpr - Return the subexpression chosen according to the |
| /// condition. |
| Expr *getChosenSubExpr() const { |
| return isConditionTrue() ? getLHS() : getRHS(); |
| } |
| |
| Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } |
| void setCond(Expr *E) { SubExprs[COND] = E; } |
| Expr *getLHS() const { return cast<Expr>(SubExprs[LHS]); } |
| void setLHS(Expr *E) { SubExprs[LHS] = E; } |
| Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } |
| void setRHS(Expr *E) { SubExprs[RHS] = E; } |
| |
| SourceLocation getBuiltinLoc() const { return BuiltinLoc; } |
| void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } |
| |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ChooseExprClass; |
| } |
| |
| // 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); |
| } |
| }; |
| |
| /// GNUNullExpr - Implements the GNU __null extension, which is a name |
| /// for a null pointer constant that has integral type (e.g., int or |
| /// long) and is the same size and alignment as a pointer. The __null |
| /// extension is typically only used by system headers, which define |
| /// NULL as __null in C++ rather than using 0 (which is an integer |
| /// that may not match the size of a pointer). |
| class GNUNullExpr : public Expr { |
| /// TokenLoc - The location of the __null keyword. |
| SourceLocation TokenLoc; |
| |
| public: |
| GNUNullExpr(QualType Ty, SourceLocation Loc) |
| : Expr(GNUNullExprClass, Ty, VK_RValue, OK_Ordinary, false, false, false, |
| false), |
| TokenLoc(Loc) { } |
| |
| /// Build an empty GNU __null expression. |
| explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { } |
| |
| /// getTokenLocation - The location of the __null token. |
| SourceLocation getTokenLocation() const { return TokenLoc; } |
| void setTokenLocation(SourceLocation L) { TokenLoc = L; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return TokenLoc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return TokenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == GNUNullExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(child_iterator(), child_iterator()); |
| } |
| const_child_range children() const { |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| } |
| }; |
| |
| /// Represents a call to the builtin function \c __builtin_va_arg. |
| class VAArgExpr : public Expr { |
| Stmt *Val; |
| llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfo; |
| SourceLocation BuiltinLoc, RParenLoc; |
| public: |
| VAArgExpr(SourceLocation BLoc, Expr *e, TypeSourceInfo *TInfo, |
| SourceLocation RPLoc, QualType t, bool IsMS) |
| : Expr(VAArgExprClass, t, VK_RValue, OK_Ordinary, t->isDependentType(), |
| false, (TInfo->getType()->isInstantiationDependentType() || |
| e->isInstantiationDependent()), |
| (TInfo->getType()->containsUnexpandedParameterPack() || |
| e->containsUnexpandedParameterPack())), |
| Val(e), TInfo(TInfo, IsMS), BuiltinLoc(BLoc), RParenLoc(RPLoc) {} |
| |
| /// Create an empty __builtin_va_arg expression. |
| explicit VAArgExpr(EmptyShell Empty) |
| : Expr(VAArgExprClass, Empty), Val(nullptr), TInfo(nullptr, false) {} |
| |
| const Expr *getSubExpr() const { return cast<Expr>(Val); } |
| Expr *getSubExpr() { return cast<Expr>(Val); } |
| void setSubExpr(Expr *E) { Val = E; } |
| |
| /// Returns whether this is really a Win64 ABI va_arg expression. |
| bool isMicrosoftABI() const { return TInfo.getInt(); } |
| void setIsMicrosoftABI(bool IsMS) { TInfo.setInt(IsMS); } |
| |
| TypeSourceInfo *getWrittenTypeInfo() const { return TInfo.getPointer(); } |
| void setWrittenTypeInfo(TypeSourceInfo *TI) { TInfo.setPointer(TI); } |
| |
| SourceLocation getBuiltinLoc() const { return BuiltinLoc; } |
| void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } |
| |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| void setRParenLoc(SourceLocation L) { RParenLoc = L; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == VAArgExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Val, &Val+1); } |
| const_child_range children() const { |
| return const_child_range(&Val, &Val + 1); |
| } |
| }; |
| |
| /// Describes an C or C++ initializer list. |
| /// |
| /// InitListExpr describes an initializer list, which can be used to |
| /// initialize objects of different types, including |
| /// struct/class/union types, arrays, and vectors. For example: |
| /// |
| /// @code |
| /// struct foo x = { 1, { 2, 3 } }; |
| /// @endcode |
| /// |
| /// Prior to semantic analysis, an initializer list will represent the |
| /// initializer list as written by the user, but will have the |
| /// placeholder type "void". This initializer list is called the |
| /// syntactic form of the initializer, and may contain C99 designated |
| /// initializers (represented as DesignatedInitExprs), initializations |
| /// of subobject members without explicit braces, and so on. Clients |
| /// interested in the original syntax of the initializer list should |
| /// use the syntactic form of the initializer list. |
| /// |
| /// After semantic analysis, the initializer list will represent the |
| /// semantic form of the initializer, where the initializations of all |
| /// subobjects are made explicit with nested InitListExpr nodes and |
| /// C99 designators have been eliminated by placing the designated |
| /// initializations into the subobject they initialize. Additionally, |
| /// any "holes" in the initialization, where no initializer has been |
| /// specified for a particular subobject, will be replaced with |
| /// implicitly-generated ImplicitValueInitExpr expressions that |
| /// value-initialize the subobjects. Note, however, that the |
| /// initializer lists may still have fewer initializers than there are |
| /// elements to initialize within the object. |
| /// |
| /// After semantic analysis has completed, given an initializer list, |
| /// method isSemanticForm() returns true if and only if this is the |
| /// semantic form of the initializer list (note: the same AST node |
| /// may at the same time be the syntactic form). |
| /// Given the semantic form of the initializer list, one can retrieve |
| /// the syntactic form of that initializer list (when different) |
| /// using method getSyntacticForm(); the method returns null if applied |
| /// to a initializer list which is already in syntactic form. |
| /// Similarly, given the syntactic form (i.e., an initializer list such |
| /// that isSemanticForm() returns false), one can retrieve the semantic |
| /// form using method getSemanticForm(). |
| /// Since many initializer lists have the same syntactic and semantic forms, |
| /// getSyntacticForm() may return NULL, indicating that the current |
| /// semantic initializer list also serves as its syntactic form. |
| class InitListExpr : public Expr { |
| // FIXME: Eliminate this vector in favor of ASTContext allocation |
| typedef ASTVector<Stmt *> InitExprsTy; |
| InitExprsTy InitExprs; |
| SourceLocation LBraceLoc, RBraceLoc; |
| |
| /// The alternative form of the initializer list (if it exists). |
| /// The int part of the pair stores whether this initializer list is |
| /// in semantic form. If not null, the pointer points to: |
| /// - the syntactic form, if this is in semantic form; |
| /// - the semantic form, if this is in syntactic form. |
| llvm::PointerIntPair<InitListExpr *, 1, bool> AltForm; |
| |
| /// Either: |
| /// If this initializer list initializes an array with more elements than |
| /// there are initializers in the list, specifies an expression to be used |
| /// for value initialization of the rest of the elements. |
| /// Or |
| /// If this initializer list initializes a union, specifies which |
| /// field within the union will be initialized. |
| llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit; |
| |
| public: |
| InitListExpr(const ASTContext &C, SourceLocation lbraceloc, |
| ArrayRef<Expr*> initExprs, SourceLocation rbraceloc); |
| |
| /// Build an empty initializer list. |
| explicit InitListExpr(EmptyShell Empty) |
| : Expr(InitListExprClass, Empty), AltForm(nullptr, true) { } |
| |
| unsigned getNumInits() const { return InitExprs.size(); } |
| |
| /// Retrieve the set of initializers. |
| Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); } |
| |
| /// Retrieve the set of initializers. |
| Expr * const *getInits() const { |
| return reinterpret_cast<Expr * const *>(InitExprs.data()); |
| } |
| |
| ArrayRef<Expr *> inits() { |
| return llvm::makeArrayRef(getInits(), getNumInits()); |
| } |
| |
| ArrayRef<Expr *> inits() const { |
| return llvm::makeArrayRef(getInits(), getNumInits()); |
| } |
| |
| const Expr *getInit(unsigned Init) const { |
| assert(Init < getNumInits() && "Initializer access out of range!"); |
| return cast_or_null<Expr>(InitExprs[Init]); |
| } |
| |
| Expr *getInit(unsigned Init) { |
| assert(Init < getNumInits() && "Initializer access out of range!"); |
| return cast_or_null<Expr>(InitExprs[Init]); |
| } |
| |
| void setInit(unsigned Init, Expr *expr) { |
| assert(Init < getNumInits() && "Initializer access out of range!"); |
| InitExprs[Init] = expr; |
| |
| if (expr) { |
| ExprBits.TypeDependent |= expr->isTypeDependent(); |
| ExprBits.ValueDependent |= expr->isValueDependent(); |
| ExprBits.InstantiationDependent |= expr->isInstantiationDependent(); |
| ExprBits.ContainsUnexpandedParameterPack |= |
| expr->containsUnexpandedParameterPack(); |
| } |
| } |
| |
| /// Reserve space for some number of initializers. |
| void reserveInits(const ASTContext &C, unsigned NumInits); |
| |
| /// Specify the number of initializers |
| /// |
| /// If there are more than @p NumInits initializers, the remaining |
| /// initializers will be destroyed. If there are fewer than @p |
| /// NumInits initializers, NULL expressions will be added for the |
| /// unknown initializers. |
| void resizeInits(const ASTContext &Context, unsigned NumInits); |
| |
| /// Updates the initializer at index @p Init with the new |
| /// expression @p expr, and returns the old expression at that |
| /// location. |
| /// |
| /// When @p Init is out of range for this initializer list, the |
| /// initializer list will be extended with NULL expressions to |
| /// accommodate the new entry. |
| Expr *updateInit(const ASTContext &C, unsigned Init, Expr *expr); |
| |
| /// If this initializer list initializes an array with more elements |
| /// than there are initializers in the list, specifies an expression to be |
| /// used for value initialization of the rest of the elements. |
| Expr *getArrayFiller() { |
| return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>(); |
| } |
| const Expr *getArrayFiller() const { |
| return const_cast<InitListExpr *>(this)->getArrayFiller(); |
| } |
| void setArrayFiller(Expr *filler); |
| |
| /// Return true if this is an array initializer and its array "filler" |
| /// has been set. |
| bool hasArrayFiller() const { return getArrayFiller(); } |
| |
| /// If this initializes a union, specifies which field in the |
| /// union to initialize. |
| /// |
| /// Typically, this field is the first named field within the |
| /// union. However, a designated initializer can specify the |
| /// initialization of a different field within the union. |
| FieldDecl *getInitializedFieldInUnion() { |
| return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>(); |
| } |
| const FieldDecl *getInitializedFieldInUnion() const { |
| return const_cast<InitListExpr *>(this)->getInitializedFieldInUnion(); |
| } |
| void setInitializedFieldInUnion(FieldDecl *FD) { |
| assert((FD == nullptr |
| || getInitializedFieldInUnion() == nullptr |
| || getInitializedFieldInUnion() == FD) |
| && "Only one field of a union may be initialized at a time!"); |
| ArrayFillerOrUnionFieldInit = FD; |
| } |
| |
| // Explicit InitListExpr's originate from source code (and have valid source |
| // locations). Implicit InitListExpr's are created by the semantic analyzer. |
| bool isExplicit() const { |
| return LBraceLoc.isValid() && RBraceLoc.isValid(); |
| } |
| |
| // Is this an initializer for an array of characters, initialized by a string |
| // literal or an @encode? |
| bool isStringLiteralInit() const; |
| |
| /// Is this a transparent initializer list (that is, an InitListExpr that is |
| /// purely syntactic, and whose semantics are that of the sole contained |
| /// initializer)? |
| bool isTransparent() const; |
| |
| /// Is this the zero initializer {0} in a language which considers it |
| /// idiomatic? |
| bool isIdiomaticZeroInitializer(const LangOptions &LangOpts) const; |
| |
| SourceLocation getLBraceLoc() const { return LBraceLoc; } |
| void setLBraceLoc(SourceLocation Loc) { LBraceLoc = Loc; } |
| SourceLocation getRBraceLoc() const { return RBraceLoc; } |
| void setRBraceLoc(SourceLocation Loc) { RBraceLoc = Loc; } |
| |
| bool isSemanticForm() const { return AltForm.getInt(); } |
| InitListExpr *getSemanticForm() const { |
| return isSemanticForm() ? nullptr : AltForm.getPointer(); |
| } |
| bool isSyntacticForm() const { |
| return !AltForm.getInt() || !AltForm.getPointer(); |
| } |
| InitListExpr *getSyntacticForm() const { |
| return isSemanticForm() ? AltForm.getPointer() : nullptr; |
| } |
| |
| void setSyntacticForm(InitListExpr *Init) { |
| AltForm.setPointer(Init); |
| AltForm.setInt(true); |
| Init->AltForm.setPointer(this); |
| Init->AltForm.setInt(false); |
| } |
| |
| bool hadArrayRangeDesignator() const { |
| return InitListExprBits.HadArrayRangeDesignator != 0; |
| } |
| void sawArrayRangeDesignator(bool ARD = true) { |
| InitListExprBits.HadArrayRangeDesignator = ARD; |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY; |
| SourceLocation getEndLoc() const LLVM_READONLY; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == InitListExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| const_child_range CCR = const_cast<const InitListExpr *>(this)->children(); |
| return child_range(cast_away_const(CCR.begin()), |
| cast_away_const(CCR.end())); |
| } |
| |
| const_child_range children() const { |
| // FIXME: This does not include the array filler expression. |
| if (InitExprs.empty()) |
| return const_child_range(const_child_iterator(), const_child_iterator()); |
| return const_child_range(&InitExprs[0], &InitExprs[0] + InitExprs.size()); |
| } |
| |
| typedef InitExprsTy::iterator iterator; |
| typedef InitExprsTy::const_iterator const_iterator; |
| typedef InitExprsTy::reverse_iterator reverse_iterator; |
| typedef InitExprsTy::const_reverse_iterator const_reverse_iterator; |
| |
| iterator begin() { return InitExprs.begin(); } |
| const_iterator begin() const { return InitExprs.begin(); } |
| iterator end() { return InitExprs.end(); } |
| const_iterator end() const { return InitExprs.end(); } |
| reverse_iterator rbegin() { return InitExprs.rbegin(); } |
| const_reverse_iterator rbegin() const { return InitExprs.rbegin(); } |
| reverse_iterator rend() { return InitExprs.rend(); } |
| const_reverse_iterator rend() const { return InitExprs.rend(); } |
| |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| }; |
| |
| /// Represents a C99 designated initializer expression. |
| /// |
| /// A designated initializer expression (C99 6.7.8) contains one or |
| /// more designators (which can be field designators, array |
| /// designators, or GNU array-range designators) followed by an |
| /// expression that initializes the field or element(s) that the |
| /// designators refer to. For example, given: |
| /// |
| /// @code |
| /// struct point { |
| /// double x; |
| /// double y; |
| /// }; |
| /// struct point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; |
| /// @endcode |
| /// |
| /// The InitListExpr contains three DesignatedInitExprs, the first of |
| /// which covers @c [2].y=1.0. This DesignatedInitExpr will have two |
| /// designators, one array designator for @c [2] followed by one field |
| /// designator for @c .y. The initialization expression will be 1.0. |
| class DesignatedInitExpr final |
| : public Expr, |
| private llvm::TrailingObjects<DesignatedInitExpr, Stmt *> { |
| public: |
| /// Forward declaration of the Designator class. |
| class Designator; |
| |
| private: |
| /// The location of the '=' or ':' prior to the actual initializer |
| /// expression. |
| SourceLocation EqualOrColonLoc; |
| |
| /// Whether this designated initializer used the GNU deprecated |
| /// syntax rather than the C99 '=' syntax. |
| unsigned GNUSyntax : 1; |
| |
| /// The number of designators in this initializer expression. |
| unsigned NumDesignators : 15; |
| |
| /// The number of subexpressions of this initializer expression, |
| /// which contains both the initializer and any additional |
| /// expressions used by array and array-range designators. |
| unsigned NumSubExprs : 16; |
| |
| /// The designators in this designated initialization |
| /// expression. |
| Designator *Designators; |
| |
| DesignatedInitExpr(const ASTContext &C, QualType Ty, |
| llvm::ArrayRef<Designator> Designators, |
| SourceLocation EqualOrColonLoc, bool GNUSyntax, |
| ArrayRef<Expr *> IndexExprs, Expr *Init); |
| |
| explicit DesignatedInitExpr(unsigned NumSubExprs) |
| : Expr(DesignatedInitExprClass, EmptyShell()), |
| NumDesignators(0), NumSubExprs(NumSubExprs), Designators(nullptr) { } |
| |
| public: |
| /// A field designator, e.g., ".x". |
| struct FieldDesignator { |
| /// Refers to the field that is being initialized. The low bit |
| /// of this field determines whether this is actually a pointer |
| /// to an IdentifierInfo (if 1) or a FieldDecl (if 0). When |
| /// initially constructed, a field designator will store an |
| /// IdentifierInfo*. After semantic analysis has resolved that |
| /// name, the field designator will instead store a FieldDecl*. |
| uintptr_t NameOrField; |
| |
| /// The location of the '.' in the designated initializer. |
| unsigned DotLoc; |
| |
| /// The location of the field name in the designated initializer. |
| unsigned FieldLoc; |
| }; |
| |
| /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". |
| struct ArrayOrRangeDesignator { |
| /// Location of the first index expression within the designated |
| /// initializer expression's list of subexpressions. |
| unsigned Index; |
| /// The location of the '[' starting the array range designator. |
| unsigned LBracketLoc; |
| /// The location of the ellipsis separating the start and end |
| /// indices. Only valid for GNU array-range designators. |
| unsigned EllipsisLoc; |
| /// The location of the ']' terminating the array range designator. |
| unsigned RBracketLoc; |
| }; |
| |
| /// Represents a single C99 designator. |
| /// |
| /// @todo This class is infuriatingly similar to clang::Designator, |
| /// but minor differences (storing indices vs. storing pointers) |
| /// keep us from reusing it. Try harder, later, to rectify these |
| /// differences. |
| class Designator { |
| /// The kind of designator this describes. |
| enum { |
| FieldDesignator, |
| ArrayDesignator, |
| ArrayRangeDesignator |
| } Kind; |
| |
| union { |
| /// A field designator, e.g., ".x". |
| struct FieldDesignator Field; |
| /// An array or GNU array-range designator, e.g., "[9]" or "[10..15]". |
| struct ArrayOrRangeDesignator ArrayOrRange; |
| }; |
| friend class DesignatedInitExpr; |
| |
| public: |
| Designator() {} |
| |
| /// Initializes a field designator. |
| Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc, |
| SourceLocation FieldLoc) |
| : Kind(FieldDesignator) { |
| Field.NameOrField = reinterpret_cast<uintptr_t>(FieldName) | 0x01; |
| Field.DotLoc = DotLoc.getRawEncoding(); |
| Field.FieldLoc = FieldLoc.getRawEncoding(); |
| } |
| |
| /// Initializes an array designator. |
| Designator(unsigned Index, SourceLocation LBracketLoc, |
| SourceLocation RBracketLoc) |
| : Kind(ArrayDesignator) { |
| ArrayOrRange.Index = Index; |
| ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding(); |
| ArrayOrRange.EllipsisLoc = SourceLocation().getRawEncoding(); |
| ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding(); |
| } |
| |
| /// Initializes a GNU array-range designator. |
| Designator(unsigned Index, SourceLocation LBracketLoc, |
| SourceLocation EllipsisLoc, SourceLocation RBracketLoc) |
| : Kind(ArrayRangeDesignator) { |
| ArrayOrRange.Index = Index; |
| ArrayOrRange.LBracketLoc = LBracketLoc.getRawEncoding(); |
| ArrayOrRange.EllipsisLoc = EllipsisLoc.getRawEncoding(); |
| ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding(); |
| } |
| |
| bool isFieldDesignator() const { return Kind == FieldDesignator; } |
| bool isArrayDesignator() const { return Kind == ArrayDesignator; } |
| bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; } |
| |
| IdentifierInfo *getFieldName() const; |
| |
| FieldDecl *getField() const { |
| assert(Kind == FieldDesignator && "Only valid on a field designator"); |
| if (Field.NameOrField & 0x01) |
| return nullptr; |
| else |
| return reinterpret_cast<FieldDecl *>(Field.NameOrField); |
| } |
| |
| void setField(FieldDecl *FD) { |
| assert(Kind == FieldDesignator && "Only valid on a field designator"); |
| Field.NameOrField = reinterpret_cast<uintptr_t>(FD); |
| } |
| |
| SourceLocation getDotLoc() const { |
| assert(Kind == FieldDesignator && "Only valid on a field designator"); |
| return SourceLocation::getFromRawEncoding(Field.DotLoc); |
| } |
| |
| SourceLocation getFieldLoc() const { |
| assert(Kind == FieldDesignator && "Only valid on a field designator"); |
| return SourceLocation::getFromRawEncoding(Field.FieldLoc); |
| } |
| |
| SourceLocation getLBracketLoc() const { |
| assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && |
| "Only valid on an array or array-range designator"); |
| return SourceLocation::getFromRawEncoding(ArrayOrRange.LBracketLoc); |
| } |
| |
| SourceLocation getRBracketLoc() const { |
| assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && |
| "Only valid on an array or array-range designator"); |
| return SourceLocation::getFromRawEncoding(ArrayOrRange.RBracketLoc); |
| } |
| |
| SourceLocation getEllipsisLoc() const { |
| assert(Kind == ArrayRangeDesignator && |
| "Only valid on an array-range designator"); |
| return SourceLocation::getFromRawEncoding(ArrayOrRange.EllipsisLoc); |
| } |
| |
| unsigned getFirstExprIndex() const { |
| assert((Kind == ArrayDesignator || Kind == ArrayRangeDesignator) && |
| "Only valid on an array or array-range designator"); |
| return ArrayOrRange.Index; |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| if (Kind == FieldDesignator) |
| return getDotLoc().isInvalid()? getFieldLoc() : getDotLoc(); |
| else |
| return getLBracketLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc(); |
| } |
| SourceRange getSourceRange() const LLVM_READONLY { |
| return SourceRange(getBeginLoc(), getEndLoc()); |
| } |
| }; |
| |
| static DesignatedInitExpr *Create(const ASTContext &C, |
| llvm::ArrayRef<Designator> Designators, |
| ArrayRef<Expr*> IndexExprs, |
| SourceLocation EqualOrColonLoc, |
| bool GNUSyntax, Expr *Init); |
| |
| static DesignatedInitExpr *CreateEmpty(const ASTContext &C, |
| unsigned NumIndexExprs); |
| |
| /// Returns the number of designators in this initializer. |
| unsigned size() const { return NumDesignators; } |
| |
| // Iterator access to the designators. |
| llvm::MutableArrayRef<Designator> designators() { |
| return {Designators, NumDesignators}; |
| } |
| |
| llvm::ArrayRef<Designator> designators() const { |
| return {Designators, NumDesignators}; |
| } |
| |
| Designator *getDesignator(unsigned Idx) { return &designators()[Idx]; } |
| const Designator *getDesignator(unsigned Idx) const { |
| return &designators()[Idx]; |
| } |
| |
| void setDesignators(const ASTContext &C, const Designator *Desigs, |
| unsigned NumDesigs); |
| |
| Expr *getArrayIndex(const Designator &D) const; |
| Expr *getArrayRangeStart(const Designator &D) const; |
| Expr *getArrayRangeEnd(const Designator &D) const; |
| |
| /// Retrieve the location of the '=' that precedes the |
| /// initializer value itself, if present. |
| SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; } |
| void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; } |
| |
| /// Determines whether this designated initializer used the |
| /// deprecated GNU syntax for designated initializers. |
| bool usesGNUSyntax() const { return GNUSyntax; } |
| void setGNUSyntax(bool GNU) { GNUSyntax = GNU; } |
| |
| /// Retrieve the initializer value. |
| Expr *getInit() const { |
| return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin()); |
| } |
| |
| void setInit(Expr *init) { |
| *child_begin() = init; |
| } |
| |
| /// Retrieve the total number of subexpressions in this |
| /// designated initializer expression, including the actual |
| /// initialized value and any expressions that occur within array |
| /// and array-range designators. |
| unsigned getNumSubExprs() const { return NumSubExprs; } |
| |
| Expr *getSubExpr(unsigned Idx) const { |
| assert(Idx < NumSubExprs && "Subscript out of range"); |
| return cast<Expr>(getTrailingObjects<Stmt *>()[Idx]); |
| } |
| |
| void setSubExpr(unsigned Idx, Expr *E) { |
| assert(Idx < NumSubExprs && "Subscript out of range"); |
| getTrailingObjects<Stmt *>()[Idx] = E; |
| } |
| |
| /// Replaces the designator at index @p Idx with the series |
| /// of designators in [First, Last). |
| void ExpandDesignator(const ASTContext &C, unsigned Idx, |
| const Designator *First, const Designator *Last); |
| |
| SourceRange getDesignatorsSourceRange() const; |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY; |
| SourceLocation getEndLoc() const LLVM_READONLY; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == DesignatedInitExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| Stmt **begin = getTrailingObjects<Stmt *>(); |
| return child_range(begin, begin + NumSubExprs); |
| } |
| const_child_range children() const { |
| Stmt * const *begin = getTrailingObjects<Stmt *>(); |
| return const_child_range(begin, begin + NumSubExprs); |
| } |
| |
| friend TrailingObjects; |
| }; |
| |
| /// Represents a place-holder for an object not to be initialized by |
| /// anything. |
| /// |
| /// This only makes sense when it appears as part of an updater of a |
| /// DesignatedInitUpdateExpr (see below). The base expression of a DIUE |
| /// initializes a big object, and the NoInitExpr's mark the spots within the |
| /// big object not to be overwritten by the updater. |
| /// |
| /// \see DesignatedInitUpdateExpr |
| class NoInitExpr : public Expr { |
| public: |
| explicit NoInitExpr(QualType ty) |
| : Expr(NoInitExprClass, ty, VK_RValue, OK_Ordinary, |
| false, false, ty->isInstantiationDependentType(), false) { } |
| |
| explicit NoInitExpr(EmptyShell Empty) |
| : Expr(NoInitExprClass, Empty) { } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == NoInitExprClass; |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); } |
| SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); } |
| |
| // 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()); |
| } |
| }; |
| |
| // In cases like: |
| // struct Q { int a, b, c; }; |
| // Q *getQ(); |
| // void foo() { |
| // struct A { Q q; } a = { *getQ(), .q.b = 3 }; |
| // } |
| // |
| // We will have an InitListExpr for a, with type A, and then a |
| // DesignatedInitUpdateExpr for "a.q" with type Q. The "base" for this DIUE |
| // is the call expression *getQ(); the "updater" for the DIUE is ".q.b = 3" |
| // |
| class DesignatedInitUpdateExpr : public Expr { |
| // BaseAndUpdaterExprs[0] is the base expression; |
| // BaseAndUpdaterExprs[1] is an InitListExpr overwriting part of the base. |
| Stmt *BaseAndUpdaterExprs[2]; |
| |
| public: |
| DesignatedInitUpdateExpr(const ASTContext &C, SourceLocation lBraceLoc, |
| Expr *baseExprs, SourceLocation rBraceLoc); |
| |
| explicit DesignatedInitUpdateExpr(EmptyShell Empty) |
| : Expr(DesignatedInitUpdateExprClass, Empty) { } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY; |
| SourceLocation getEndLoc() const LLVM_READONLY; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == DesignatedInitUpdateExprClass; |
| } |
| |
| Expr *getBase() const { return cast<Expr>(BaseAndUpdaterExprs[0]); } |
| void setBase(Expr *Base) { BaseAndUpdaterExprs[0] = Base; } |
| |
| InitListExpr *getUpdater() const { |
| return cast<InitListExpr>(BaseAndUpdaterExprs[1]); |
| } |
| void setUpdater(Expr *Updater) { BaseAndUpdaterExprs[1] = Updater; } |
| |
| // Iterators |
| // children = the base and the updater |
| child_range children() { |
| return child_range(&BaseAndUpdaterExprs[0], &BaseAndUpdaterExprs[0] + 2); |
| } |
| const_child_range children() const { |
| return const_child_range(&BaseAndUpdaterExprs[0], |
| &BaseAndUpdaterExprs[0] + 2); |
| } |
| }; |
| |
| /// Represents a loop initializing the elements of an array. |
| /// |
| /// The need to initialize the elements of an array occurs in a number of |
| /// contexts: |
| /// |
| /// * in the implicit copy/move constructor for a class with an array member |
| /// * when a lambda-expression captures an array by value |
| /// * when a decomposition declaration decomposes an array |
| /// |
| /// There are two subexpressions: a common expression (the source array) |
| /// that is evaluated once up-front, and a per-element initializer that |
| /// runs once for each array element. |
| /// |
| /// Within the per-element initializer, the common expression may be referenced |
| /// via an OpaqueValueExpr, and the current index may be obtained via an |
| /// ArrayInitIndexExpr. |
| class ArrayInitLoopExpr : public Expr { |
| Stmt *SubExprs[2]; |
| |
| explicit ArrayInitLoopExpr(EmptyShell Empty) |
| : Expr(ArrayInitLoopExprClass, Empty), SubExprs{} {} |
| |
| public: |
| explicit ArrayInitLoopExpr(QualType T, Expr *CommonInit, Expr *ElementInit) |
| : Expr(ArrayInitLoopExprClass, T, VK_RValue, OK_Ordinary, false, |
| CommonInit->isValueDependent() || ElementInit->isValueDependent(), |
| T->isInstantiationDependentType(), |
| CommonInit->containsUnexpandedParameterPack() || |
| ElementInit->containsUnexpandedParameterPack()), |
| SubExprs{CommonInit, ElementInit} {} |
| |
| /// Get the common subexpression shared by all initializations (the source |
| /// array). |
| OpaqueValueExpr *getCommonExpr() const { |
| return cast<OpaqueValueExpr>(SubExprs[0]); |
| } |
| |
| /// Get the initializer to use for each array element. |
| Expr *getSubExpr() const { return cast<Expr>(SubExprs[1]); } |
| |
| llvm::APInt getArraySize() const { |
| return cast<ConstantArrayType>(getType()->castAsArrayTypeUnsafe()) |
| ->getSize(); |
| } |
| |
| static bool classof(const Stmt *S) { |
| return S->getStmtClass() == ArrayInitLoopExprClass; |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return getCommonExpr()->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return getCommonExpr()->getEndLoc(); |
| } |
| |
| child_range children() { |
| return child_range(SubExprs, SubExprs + 2); |
| } |
| const_child_range children() const { |
| return const_child_range(SubExprs, SubExprs + 2); |
| } |
| |
| friend class ASTReader; |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| }; |
| |
| /// Represents the index of the current element of an array being |
| /// initialized by an ArrayInitLoopExpr. This can only appear within the |
| /// subexpression of an ArrayInitLoopExpr. |
| class ArrayInitIndexExpr : public Expr { |
| explicit ArrayInitIndexExpr(EmptyShell Empty) |
| : Expr(ArrayInitIndexExprClass, Empty) {} |
| |
| public: |
| explicit ArrayInitIndexExpr(QualType T) |
| : Expr(ArrayInitIndexExprClass, T, VK_RValue, OK_Ordinary, |
| false, false, false, false) {} |
| |
| static bool classof(const Stmt *S) { |
| return S->getStmtClass() == ArrayInitIndexExprClass; |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); } |
| SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); } |
| |
| 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()); |
| } |
| |
| friend class ASTReader; |
| friend class ASTStmtReader; |
| }; |
| |
| /// Represents an implicitly-generated value initialization of |
| /// an object of a given type. |
| /// |
| /// Implicit value initializations occur within semantic initializer |
| /// list expressions (InitListExpr) as placeholders for subobject |
| /// initializations not explicitly specified by the user. |
| /// |
| /// \see InitListExpr |
| class ImplicitValueInitExpr : public Expr { |
| public: |
| explicit ImplicitValueInitExpr(QualType ty) |
| : Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary, |
| false, false, ty->isInstantiationDependentType(), false) { } |
| |
| /// Construct an empty implicit value initialization. |
| explicit ImplicitValueInitExpr(EmptyShell Empty) |
| : Expr(ImplicitValueInitExprClass, Empty) { } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ImplicitValueInitExprClass; |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); } |
| SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); } |
| |
| // 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 ParenListExpr final |
| : public Expr, |
| private llvm::TrailingObjects<ParenListExpr, Stmt *> { |
| friend class ASTStmtReader; |
| friend TrailingObjects; |
| |
| /// The location of the left and right parentheses. |
| SourceLocation LParenLoc, RParenLoc; |
| |
| /// Build a paren list. |
| ParenListExpr(SourceLocation LParenLoc, ArrayRef<Expr *> Exprs, |
| SourceLocation RParenLoc); |
| |
| /// Build an empty paren list. |
| ParenListExpr(EmptyShell Empty, unsigned NumExprs); |
| |
| public: |
| /// Create a paren list. |
| static ParenListExpr *Create(const ASTContext &Ctx, SourceLocation LParenLoc, |
| ArrayRef<Expr *> Exprs, |
| SourceLocation RParenLoc); |
| |
| /// Create an empty paren list. |
| static ParenListExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumExprs); |
| |
| /// Return the number of expressions in this paren list. |
| unsigned getNumExprs() const { return ParenListExprBits.NumExprs; } |
| |
| Expr *getExpr(unsigned Init) { |
| assert(Init < getNumExprs() && "Initializer access out of range!"); |
| return getExprs()[Init]; |
| } |
| |
| const Expr *getExpr(unsigned Init) const { |
| return const_cast<ParenListExpr *>(this)->getExpr(Init); |
| } |
| |
| Expr **getExprs() { |
| return reinterpret_cast<Expr **>(getTrailingObjects<Stmt *>()); |
| } |
| |
| ArrayRef<Expr *> exprs() { |
| return llvm::makeArrayRef(getExprs(), getNumExprs()); |
| } |
| |
| SourceLocation getLParenLoc() const { return LParenLoc; } |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| SourceLocation getBeginLoc() const { return getLParenLoc(); } |
| SourceLocation getEndLoc() const { return getRParenLoc(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ParenListExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(getTrailingObjects<Stmt *>(), |
| getTrailingObjects<Stmt *>() + getNumExprs()); |
| } |
| const_child_range children() const { |
| return const_child_range(getTrailingObjects<Stmt *>(), |
| getTrailingObjects<Stmt *>() + getNumExprs()); |
| } |
| }; |
| |
| /// Represents a C11 generic selection. |
| /// |
| /// A generic selection (C11 6.5.1.1) contains an unevaluated controlling |
| /// expression, followed by one or more generic associations. Each generic |
| /// association specifies a type name and an expression, or "default" and an |
| /// expression (in which case it is known as a default generic association). |
| /// The type and value of the generic selection are identical to those of its |
| /// result expression, which is defined as the expression in the generic |
| /// association with a type name that is compatible with the type of the |
| /// controlling expression, or the expression in the default generic association |
| /// if no types are compatible. For example: |
| /// |
| /// @code |
| /// _Generic(X, double: 1, float: 2, default: 3) |
| /// @endcode |
| /// |
| /// The above expression evaluates to 1 if 1.0 is substituted for X, 2 if 1.0f |
| /// or 3 if "hello". |
| /// |
| /// As an extension, generic selections are allowed in C++, where the following |
| /// additional semantics apply: |
| /// |
| /// Any generic selection whose controlling expression is type-dependent or |
| /// which names a dependent type in its association list is result-dependent, |
| /// which means that the choice of result expression is dependent. |
| /// Result-dependent generic associations are both type- and value-dependent. |
| class GenericSelectionExpr final |
| : public Expr, |
| private llvm::TrailingObjects<GenericSelectionExpr, Stmt *, |
| TypeSourceInfo *> { |
| friend class ASTStmtReader; |
| friend class ASTStmtWriter; |
| friend TrailingObjects; |
| |
| /// The number of association expressions and the index of the result |
| /// expression in the case where the generic selection expression is not |
| /// result-dependent. The result index is equal to ResultDependentIndex |
| /// if and only if the generic selection expression is result-dependent. |
| unsigned NumAssocs, ResultIndex; |
| enum : unsigned { |
| ResultDependentIndex = std::numeric_limits<unsigned>::max(), |
| ControllingIndex = 0, |
| AssocExprStartIndex = 1 |
| }; |
| |
| /// The location of the "default" and of the right parenthesis. |
| SourceLocation DefaultLoc, RParenLoc; |
| |
| // GenericSelectionExpr is followed by several trailing objects. |
| // They are (in order): |
| // |
| // * A single Stmt * for the controlling expression. |
| // * An array of getNumAssocs() Stmt * for the association expressions. |
| // * An array of getNumAssocs() TypeSourceInfo *, one for each of the |
| // association expressions. |
| unsigned numTrailingObjects(OverloadToken<Stmt *>) const { |
| // Add one to account for the controlling expression; the remainder |
| // are the associated expressions. |
| return 1 + getNumAssocs(); |
| } |
| |
| unsigned numTrailingObjects(OverloadToken<TypeSourceInfo *>) const { |
| return getNumAssocs(); |
| } |
| |
| template <bool Const> class AssociationIteratorTy; |
| /// Bundle together an association expression and its TypeSourceInfo. |
| /// The Const template parameter is for the const and non-const versions |
| /// of AssociationTy. |
| template <bool Const> class AssociationTy { |
| friend class GenericSelectionExpr; |
| template <bool OtherConst> friend class AssociationIteratorTy; |
| using ExprPtrTy = |
| typename std::conditional<Const, const Expr *, Expr *>::type; |
| using TSIPtrTy = typename std::conditional<Const, const TypeSourceInfo *, |
| TypeSourceInfo *>::type; |
| ExprPtrTy E; |
| TSIPtrTy TSI; |
| bool Selected; |
| AssociationTy(ExprPtrTy E, TSIPtrTy TSI, bool Selected) |
| : E(E), TSI(TSI), Selected(Selected) {} |
| |
| public: |
| ExprPtrTy getAssociationExpr() const { return E; } |
| TSIPtrTy getTypeSourceInfo() const { return TSI; } |
| QualType getType() const { return TSI ? TSI->getType() : QualType(); } |
| bool isSelected() const { return Selected; } |
| AssociationTy *operator->() { return this; } |
| const AssociationTy *operator->() const { return this; } |
| }; // class AssociationTy |
| |
| /// Iterator over const and non-const Association objects. The Association |
| /// objects are created on the fly when the iterator is dereferenced. |
| /// This abstract over how exactly the association expressions and the |
| /// corresponding TypeSourceInfo * are stored. |
| template <bool Const> |
| class AssociationIteratorTy |
| : public llvm::iterator_facade_base< |
| AssociationIteratorTy<Const>, std::input_iterator_tag, |
| AssociationTy<Const>, std::ptrdiff_t, AssociationTy<Const>, |
| AssociationTy<Const>> { |
| friend class GenericSelectionExpr; |
| // FIXME: This iterator could conceptually be a random access iterator, and |
| // it would be nice if we could strengthen the iterator category someday. |
| // However this iterator does not satisfy two requirements of forward |
| // iterators: |
| // a) reference = T& or reference = const T& |
| // b) If It1 and It2 are both dereferenceable, then It1 == It2 if and only |
| // if *It1 and *It2 are bound to the same objects. |
| // An alternative design approach was discussed during review; |
| // store an Association object inside the iterator, and return a reference |
| // to it when dereferenced. This idea was discarded beacuse of nasty |
| // lifetime issues: |
| // AssociationIterator It = ...; |
| // const Association &Assoc = *It++; // Oops, Assoc is dangling. |
| using BaseTy = typename AssociationIteratorTy::iterator_facade_base; |
| using StmtPtrPtrTy = |
| typename std::conditional<Const, const Stmt *const *, Stmt **>::type; |
| using TSIPtrPtrTy = |
| typename std::conditional<Const, const TypeSourceInfo *const *, |
| TypeSourceInfo **>::type; |
| StmtPtrPtrTy E; // = nullptr; FIXME: Once support for gcc 4.8 is dropped. |
| TSIPtrPtrTy TSI; // Kept in sync with E. |
| unsigned Offset = 0, SelectedOffset = 0; |
| AssociationIteratorTy(StmtPtrPtrTy E, TSIPtrPtrTy TSI, unsigned Offset, |
| unsigned SelectedOffset) |
| : E(E), TSI(TSI), Offset(Offset), SelectedOffset(SelectedOffset) {} |
| |
| public: |
| AssociationIteratorTy() : E(nullptr), TSI(nullptr) {} |
| typename BaseTy::reference operator*() const { |
| return AssociationTy<Const>(cast<Expr>(*E), *TSI, |
| Offset == SelectedOffset); |
| } |
| typename BaseTy::pointer operator->() const { return **this; } |
| using BaseTy::operator++; |
| AssociationIteratorTy &operator++() { |
| ++E; |
| ++TSI; |
| ++Offset; |
| return *this; |
| } |
| bool operator==(AssociationIteratorTy Other) const { return E == Other.E; } |
| }; // class AssociationIterator |
| |
| /// Build a non-result-dependent generic selection expression. |
| GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, |
| Expr *ControllingExpr, |
| ArrayRef<TypeSourceInfo *> AssocTypes, |
| ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc, |
| SourceLocation RParenLoc, |
| bool ContainsUnexpandedParameterPack, |
| unsigned ResultIndex); |
| |
| /// Build a result-dependent generic selection expression. |
| GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, |
| Expr *ControllingExpr, |
| ArrayRef<TypeSourceInfo *> AssocTypes, |
| ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc, |
| SourceLocation RParenLoc, |
| bool ContainsUnexpandedParameterPack); |
| |
| /// Build an empty generic selection expression for deserialization. |
| explicit GenericSelectionExpr(EmptyShell Empty, unsigned NumAssocs); |
| |
| public: |
| /// Create a non-result-dependent generic selection expression. |
| static GenericSelectionExpr * |
| Create(const ASTContext &Context, SourceLocation GenericLoc, |
| Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes, |
| ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc, |
| SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack, |
| unsigned ResultIndex); |
| |
| /// Create a result-dependent generic selection expression. |
| static GenericSelectionExpr * |
| Create(const ASTContext &Context, SourceLocation GenericLoc, |
| Expr *ControllingExpr, ArrayRef<TypeSourceInfo *> AssocTypes, |
| ArrayRef<Expr *> AssocExprs, SourceLocation DefaultLoc, |
| SourceLocation RParenLoc, bool ContainsUnexpandedParameterPack); |
| |
| /// Create an empty generic selection expression for deserialization. |
| static GenericSelectionExpr *CreateEmpty(const ASTContext &Context, |
| unsigned NumAssocs); |
| |
| using Association = AssociationTy<false>; |
| using ConstAssociation = AssociationTy<true>; |
| using AssociationIterator = AssociationIteratorTy<false>; |
| using ConstAssociationIterator = AssociationIteratorTy<true>; |
| using association_range = llvm::iterator_range<AssociationIterator>; |
| using const_association_range = |
| llvm::iterator_range<ConstAssociationIterator>; |
| |
| /// The number of association expressions. |
| unsigned getNumAssocs() const { return NumAssocs; } |
| |
| /// The zero-based index of the result expression's generic association in |
| /// the generic selection's association list. Defined only if the |
| /// generic selection is not result-dependent. |
| unsigned getResultIndex() const { |
| assert(!isResultDependent() && |
| "Generic selection is result-dependent but getResultIndex called!"); |
| return ResultIndex; |
| } |
| |
| /// Whether this generic selection is result-dependent. |
| bool isResultDependent() const { return ResultIndex == ResultDependentIndex; } |
| |
| /// Return the controlling expression of this generic selection expression. |
| Expr *getControllingExpr() { |
| return cast<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]); |
| } |
| const Expr *getControllingExpr() const { |
| return cast<Expr>(getTrailingObjects<Stmt *>()[ControllingIndex]); |
| } |
| |
| /// Return the result expression of this controlling expression. Defined if |
| /// and only if the generic selection expression is not result-dependent. |
| Expr *getResultExpr() { |
| return cast<Expr>( |
| getTrailingObjects<Stmt *>()[AssocExprStartIndex + getResultIndex()]); |
| } |
| const Expr *getResultExpr() const { |
| return cast<Expr>( |
| getTrailingObjects<Stmt *>()[AssocExprStartIndex + getResultIndex()]); |
| } |
| |
| ArrayRef<Expr *> getAssocExprs() const { |
| return {reinterpret_cast<Expr *const *>(getTrailingObjects<Stmt *>() + |
| AssocExprStartIndex), |
| NumAssocs}; |
| } |
| ArrayRef<TypeSourceInfo *> getAssocTypeSourceInfos() const { |
| return {getTrailingObjects<TypeSourceInfo *>(), NumAssocs}; |
| } |
| |
| /// Return the Ith association expression with its TypeSourceInfo, |
| /// bundled together in GenericSelectionExpr::(Const)Association. |
| Association getAssociation(unsigned I) { |
| assert(I < getNumAssocs() && |
| "Out-of-range index in GenericSelectionExpr::getAssociation!"); |
| return Association( |
| cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]), |
| getTrailingObjects<TypeSourceInfo *>()[I], |
| !isResultDependent() && (getResultIndex() == I)); |
| } |
| ConstAssociation getAssociation(unsigned I) const { |
| assert(I < getNumAssocs() && |
| "Out-of-range index in GenericSelectionExpr::getAssociation!"); |
| return ConstAssociation( |
| cast<Expr>(getTrailingObjects<Stmt *>()[AssocExprStartIndex + I]), |
| getTrailingObjects<TypeSourceInfo *>()[I], |
| !isResultDependent() && (getResultIndex() == I)); |
| } |
| |
| association_range associations() { |
| AssociationIterator Begin(getTrailingObjects<Stmt *>() + |
| AssocExprStartIndex, |
| getTrailingObjects<TypeSourceInfo *>(), |
| /*Offset=*/0, ResultIndex); |
| AssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs, |
| /*Offset=*/NumAssocs, ResultIndex); |
| return llvm::make_range(Begin, End); |
| } |
| |
| const_association_range associations() const { |
| ConstAssociationIterator Begin(getTrailingObjects<Stmt *>() + |
| AssocExprStartIndex, |
| getTrailingObjects<TypeSourceInfo *>(), |
| /*Offset=*/0, ResultIndex); |
| ConstAssociationIterator End(Begin.E + NumAssocs, Begin.TSI + NumAssocs, |
| /*Offset=*/NumAssocs, ResultIndex); |
| return llvm::make_range(Begin, End); |
| } |
| |
| SourceLocation getGenericLoc() const { |
| return GenericSelectionExprBits.GenericLoc; |
| } |
| SourceLocation getDefaultLoc() const { return DefaultLoc; } |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| SourceLocation getBeginLoc() const { return getGenericLoc(); } |
| SourceLocation getEndLoc() const { return getRParenLoc(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == GenericSelectionExprClass; |
| } |
| |
| child_range children() { |
| return child_range(getTrailingObjects<Stmt *>(), |
| getTrailingObjects<Stmt *>() + |
| numTrailingObjects(OverloadToken<Stmt *>())); |
| } |
| const_child_range children() const { |
| return const_child_range(getTrailingObjects<Stmt *>(), |
| getTrailingObjects<Stmt *>() + |
| numTrailingObjects(OverloadToken<Stmt *>())); |
| } |
| }; |
| |
| //===----------------------------------------------------------------------===// |
| // Clang Extensions |
| //===----------------------------------------------------------------------===// |
| |
| /// ExtVectorElementExpr - This represents access to specific elements of a |
| /// vector, and may occur on the left hand side or right hand side. For example |
| /// the following is legal: "V.xy = V.zw" if V is a 4 element extended vector. |
| /// |
| /// Note that the base may have either vector or pointer to vector type, just |
| /// like a struct field reference. |
| /// |
| class ExtVectorElementExpr : public Expr { |
| Stmt *Base; |
| IdentifierInfo *Accessor; |
| SourceLocation AccessorLoc; |
| public: |
| ExtVectorElementExpr(QualType ty, ExprValueKind VK, Expr *base, |
| IdentifierInfo &accessor, SourceLocation loc) |
| : Expr(ExtVectorElementExprClass, ty, VK, |
| (VK == VK_RValue ? OK_Ordinary : OK_VectorComponent), |
| base->isTypeDependent(), base->isValueDependent(), |
| base->isInstantiationDependent(), |
| base->containsUnexpandedParameterPack()), |
| Base(base), Accessor(&accessor), AccessorLoc(loc) {} |
| |
| /// Build an empty vector element expression. |
| explicit ExtVectorElementExpr(EmptyShell Empty) |
| : Expr(ExtVectorElementExprClass, Empty) { } |
| |
| const Expr *getBase() const { return cast<Expr>(Base); } |
| Expr *getBase() { return cast<Expr>(Base); } |
| void setBase(Expr *E) { Base = E; } |
| |
| IdentifierInfo &getAccessor() const { return *Accessor; } |
| void setAccessor(IdentifierInfo *II) { Accessor = II; } |
| |
| SourceLocation getAccessorLoc() const { return AccessorLoc; } |
| void setAccessorLoc(SourceLocation L) { AccessorLoc = L; } |
| |
| /// getNumElements - Get the number of components being selected. |
| unsigned getNumElements() const; |
| |
| /// containsDuplicateElements - Return true if any element access is |
| /// repeated. |
| bool containsDuplicateElements() const; |
| |
| /// getEncodedElementAccess - Encode the elements accessed into an llvm |
| /// aggregate Constant of ConstantInt(s). |
| void getEncodedElementAccess(SmallVectorImpl<uint32_t> &Elts) const; |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return getBase()->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { return AccessorLoc; } |
| |
| /// isArrow - Return true if the base expression is a pointer to vector, |
| /// return false if the base expression is a vector. |
| bool isArrow() const; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == ExtVectorElementExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&Base, &Base+1); } |
| const_child_range children() const { |
| return const_child_range(&Base, &Base + 1); |
| } |
| }; |
| |
| /// BlockExpr - Adaptor class for mixing a BlockDecl with expressions. |
| /// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } |
| class BlockExpr : public Expr { |
| protected: |
| BlockDecl *TheBlock; |
| public: |
| BlockExpr(BlockDecl *BD, QualType ty) |
| : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary, |
| ty->isDependentType(), ty->isDependentType(), |
| ty->isInstantiationDependentType() || BD->isDependentContext(), |
| false), |
| TheBlock(BD) {} |
| |
| /// Build an empty block expression. |
| explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { } |
| |
| const BlockDecl *getBlockDecl() const { return TheBlock; } |
| BlockDecl *getBlockDecl() { return TheBlock; } |
| void setBlockDecl(BlockDecl *BD) { TheBlock = BD; } |
| |
| // Convenience functions for probing the underlying BlockDecl. |
| SourceLocation getCaretLocation() const; |
| const Stmt *getBody() const; |
| Stmt *getBody(); |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return getCaretLocation(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return getBody()->getEndLoc(); |
| } |
| |
| /// getFunctionType - Return the underlying function type for this block. |
| const FunctionProtoType *getFunctionType() const; |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == BlockExprClass; |
| } |
| |
| // 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()); |
| } |
| }; |
| |
| /// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2] |
| /// This AST node provides support for reinterpreting a type to another |
| /// type of the same size. |
| class AsTypeExpr : public Expr { |
| private: |
| Stmt *SrcExpr; |
| SourceLocation BuiltinLoc, RParenLoc; |
| |
| friend class ASTReader; |
| friend class ASTStmtReader; |
| explicit AsTypeExpr(EmptyShell Empty) : Expr(AsTypeExprClass, Empty) {} |
| |
| public: |
| AsTypeExpr(Expr* SrcExpr, QualType DstType, |
| ExprValueKind VK, ExprObjectKind OK, |
| SourceLocation BuiltinLoc, SourceLocation RParenLoc) |
| : Expr(AsTypeExprClass, DstType, VK, OK, |
| DstType->isDependentType(), |
| DstType->isDependentType() || SrcExpr->isValueDependent(), |
| (DstType->isInstantiationDependentType() || |
| SrcExpr->isInstantiationDependent()), |
| (DstType->containsUnexpandedParameterPack() || |
| SrcExpr->containsUnexpandedParameterPack())), |
| SrcExpr(SrcExpr), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} |
| |
| /// getSrcExpr - Return the Expr to be converted. |
| Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); } |
| |
| /// getBuiltinLoc - Return the location of the __builtin_astype token. |
| SourceLocation getBuiltinLoc() const { return BuiltinLoc; } |
| |
| /// getRParenLoc - Return the location of final right parenthesis. |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == AsTypeExprClass; |
| } |
| |
| // Iterators |
| child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } |
| const_child_range children() const { |
| return const_child_range(&SrcExpr, &SrcExpr + 1); |
| } |
| }; |
| |
| /// PseudoObjectExpr - An expression which accesses a pseudo-object |
| /// l-value. A pseudo-object is an abstract object, accesses to which |
| /// are translated to calls. The pseudo-object expression has a |
| /// syntactic form, which shows how the expression was actually |
| /// written in the source code, and a semantic form, which is a series |
| /// of expressions to be executed in order which detail how the |
| /// operation is actually evaluated. Optionally, one of the semantic |
| /// forms may also provide a result value for the expression. |
| /// |
| /// If any of the semantic-form expressions is an OpaqueValueExpr, |
| /// that OVE is required to have a source expression, and it is bound |
| /// to the result of that source expression. Such OVEs may appear |
| /// only in subsequent semantic-form expressions and as |
| /// sub-expressions of the syntactic form. |
| /// |
| /// PseudoObjectExpr should be used only when an operation can be |
| /// usefully described in terms of fairly simple rewrite rules on |
| /// objects and functions that are meant to be used by end-developers. |
| /// For example, under the Itanium ABI, dynamic casts are implemented |
| /// as a call to a runtime function called __dynamic_cast; using this |
| /// class to describe that would be inappropriate because that call is |
| /// not really part of the user-visible semantics, and instead the |
| /// cast is properly reflected in the AST and IR-generation has been |
| /// taught to generate the call as necessary. In contrast, an |
| /// Objective-C property access is semantically defined to be |
| /// equivalent to a particular message send, and this is very much |
| /// part of the user model. The name of this class encourages this |
| /// modelling design. |
| class PseudoObjectExpr final |
| : public Expr, |
| private llvm::TrailingObjects<PseudoObjectExpr, Expr *> { |
| // PseudoObjectExprBits.NumSubExprs - The number of sub-expressions. |
| // Always at least two, because the first sub-expression is the |
| // syntactic form. |
| |
| // PseudoObjectExprBits.ResultIndex - The index of the |
| // sub-expression holding the result. 0 means the result is void, |
| // which is unambiguous because it's the index of the syntactic |
| // form. Note that this is therefore 1 higher than the value passed |
| // in to Create, which is an index within the semantic forms. |
| // Note also that ASTStmtWriter assumes this encoding. |
| |
| Expr **getSubExprsBuffer() { return getTrailingObjects<Expr *>(); } |
| const Expr * const *getSubExprsBuffer() const { |
| return getTrailingObjects<Expr *>(); |
| } |
| |
| PseudoObjectExpr(QualType type, ExprValueKind VK, |
| Expr *syntactic, ArrayRef<Expr*> semantic, |
| unsigned resultIndex); |
| |
| PseudoObjectExpr(EmptyShell shell, unsigned numSemanticExprs); |
| |
| unsigned getNumSubExprs() const { |
| return PseudoObjectExprBits.NumSubExprs; |
| } |
| |
| public: |
| /// NoResult - A value for the result index indicating that there is |
| /// no semantic result. |
| enum : unsigned { NoResult = ~0U }; |
| |
| static PseudoObjectExpr *Create(const ASTContext &Context, Expr *syntactic, |
| ArrayRef<Expr*> semantic, |
| unsigned resultIndex); |
| |
| static PseudoObjectExpr *Create(const ASTContext &Context, EmptyShell shell, |
| unsigned numSemanticExprs); |
| |
| /// Return the syntactic form of this expression, i.e. the |
| /// expression it actually looks like. Likely to be expressed in |
| /// terms of OpaqueValueExprs bound in the semantic form. |
| Expr *getSyntacticForm() { return getSubExprsBuffer()[0]; } |
| const Expr *getSyntacticForm() const { return getSubExprsBuffer()[0]; } |
| |
| /// Return the index of the result-bearing expression into the semantics |
| /// expressions, or PseudoObjectExpr::NoResult if there is none. |
| unsigned getResultExprIndex() const { |
| if (PseudoObjectExprBits.ResultIndex == 0) return NoResult; |
| return PseudoObjectExprBits.ResultIndex - 1; |
| } |
| |
| /// Return the result-bearing expression, or null if there is none. |
| Expr *getResultExpr() { |
| if (PseudoObjectExprBits.ResultIndex == 0) |
| return nullptr; |
| return getSubExprsBuffer()[PseudoObjectExprBits.ResultIndex]; |
| } |
| const Expr *getResultExpr() const { |
| return const_cast<PseudoObjectExpr*>(this)->getResultExpr(); |
| } |
| |
| unsigned getNumSemanticExprs() const { return getNumSubExprs() - 1; } |
| |
| typedef Expr * const *semantics_iterator; |
| typedef const Expr * const *const_semantics_iterator; |
| semantics_iterator semantics_begin() { |
| return getSubExprsBuffer() + 1; |
| } |
| const_semantics_iterator semantics_begin() const { |
| return getSubExprsBuffer() + 1; |
| } |
| semantics_iterator semantics_end() { |
| return getSubExprsBuffer() + getNumSubExprs(); |
| } |
| const_semantics_iterator semantics_end() const { |
| return getSubExprsBuffer() + getNumSubExprs(); |
| } |
| |
| llvm::iterator_range<semantics_iterator> semantics() { |
| return llvm::make_range(semantics_begin(), semantics_end()); |
| } |
| llvm::iterator_range<const_semantics_iterator> semantics() const { |
| return llvm::make_range(semantics_begin(), semantics_end()); |
| } |
| |
| Expr *getSemanticExpr(unsigned index) { |
| assert(index + 1 < getNumSubExprs()); |
| return getSubExprsBuffer()[index + 1]; |
| } |
| const Expr *getSemanticExpr(unsigned index) const { |
| return const_cast<PseudoObjectExpr*>(this)->getSemanticExpr(index); |
| } |
| |
| SourceLocation getExprLoc() const LLVM_READONLY { |
| return getSyntacticForm()->getExprLoc(); |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { |
| return getSyntacticForm()->getBeginLoc(); |
| } |
| SourceLocation getEndLoc() const LLVM_READONLY { |
| return getSyntacticForm()->getEndLoc(); |
| } |
| |
| child_range children() { |
| const_child_range CCR = |
| const_cast<const PseudoObjectExpr *>(this)->children(); |
| return child_range(cast_away_const(CCR.begin()), |
| cast_away_const(CCR.end())); |
| } |
| const_child_range children() const { |
| Stmt *const *cs = const_cast<Stmt *const *>( |
| reinterpret_cast<const Stmt *const *>(getSubExprsBuffer())); |
| return const_child_range(cs, cs + getNumSubExprs()); |
| } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == PseudoObjectExprClass; |
| } |
| |
| friend TrailingObjects; |
| friend class ASTStmtReader; |
| }; |
| |
| /// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, |
| /// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the |
| /// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>, |
| /// and corresponding __opencl_atomic_* for OpenCL 2.0. |
| /// All of these instructions take one primary pointer, at least one memory |
| /// order. The instructions for which getScopeModel returns non-null value |
| /// take one synch scope. |
| class AtomicExpr : public Expr { |
| public: |
| enum AtomicOp { |
| #define BUILTIN(ID, TYPE, ATTRS) |
| #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) AO ## ID, |
| #include "clang/Basic/Builtins.def" |
| // Avoid trailing comma |
| BI_First = 0 |
| }; |
| |
| private: |
| /// Location of sub-expressions. |
| /// The location of Scope sub-expression is NumSubExprs - 1, which is |
| /// not fixed, therefore is not defined in enum. |
| enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR }; |
| Stmt *SubExprs[END_EXPR + 1]; |
| unsigned NumSubExprs; |
| SourceLocation BuiltinLoc, RParenLoc; |
| AtomicOp Op; |
| |
| friend class ASTStmtReader; |
| public: |
| AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t, |
| AtomicOp op, SourceLocation RP); |
| |
| /// Determine the number of arguments the specified atomic builtin |
| /// should have. |
| static unsigned getNumSubExprs(AtomicOp Op); |
| |
| /// Build an empty AtomicExpr. |
| explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { } |
| |
| Expr *getPtr() const { |
| return cast<Expr>(SubExprs[PTR]); |
| } |
| Expr *getOrder() const { |
| return cast<Expr>(SubExprs[ORDER]); |
| } |
| Expr *getScope() const { |
| assert(getScopeModel() && "No scope"); |
| return cast<Expr>(SubExprs[NumSubExprs - 1]); |
| } |
| Expr *getVal1() const { |
| if (Op == AO__c11_atomic_init || Op == AO__opencl_atomic_init) |
| return cast<Expr>(SubExprs[ORDER]); |
| assert(NumSubExprs > VAL1); |
| return cast<Expr>(SubExprs[VAL1]); |
| } |
| Expr *getOrderFail() const { |
| assert(NumSubExprs > ORDER_FAIL); |
| return cast<Expr>(SubExprs[ORDER_FAIL]); |
| } |
| Expr *getVal2() const { |
| if (Op == AO__atomic_exchange) |
| return cast<Expr>(SubExprs[ORDER_FAIL]); |
| assert(NumSubExprs > VAL2); |
| return cast<Expr>(SubExprs[VAL2]); |
| } |
| Expr *getWeak() const { |
| assert(NumSubExprs > WEAK); |
| return cast<Expr>(SubExprs[WEAK]); |
| } |
| QualType getValueType() const; |
| |
| AtomicOp getOp() const { return Op; } |
| unsigned getNumSubExprs() const { return NumSubExprs; } |
| |
| Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); } |
| const Expr * const *getSubExprs() const { |
| return reinterpret_cast<Expr * const *>(SubExprs); |
| } |
| |
| bool isVolatile() const { |
| return getPtr()->getType()->getPointeeType().isVolatileQualified(); |
| } |
| |
| bool isCmpXChg() const { |
| return getOp() == AO__c11_atomic_compare_exchange_strong || |
| getOp() == AO__c11_atomic_compare_exchange_weak || |
| getOp() == AO__opencl_atomic_compare_exchange_strong || |
| getOp() == AO__opencl_atomic_compare_exchange_weak || |
| getOp() == AO__atomic_compare_exchange || |
| getOp() == AO__atomic_compare_exchange_n; |
| } |
| |
| bool isOpenCL() const { |
| return getOp() >= AO__opencl_atomic_init && |
| getOp() <= AO__opencl_atomic_fetch_max; |
| } |
| |
| SourceLocation getBuiltinLoc() const { return BuiltinLoc; } |
| SourceLocation getRParenLoc() const { return RParenLoc; } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return BuiltinLoc; } |
| SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == AtomicExprClass; |
| } |
| |
| // Iterators |
| child_range children() { |
| return child_range(SubExprs, SubExprs+NumSubExprs); |
| } |
| const_child_range children() const { |
| return const_child_range(SubExprs, SubExprs + NumSubExprs); |
| } |
| |
| /// Get atomic scope model for the atomic op code. |
| /// \return empty atomic scope model if the atomic op code does not have |
| /// scope operand. |
| static std::unique_ptr<AtomicScopeModel> getScopeModel(AtomicOp Op) { |
| auto Kind = |
| (Op >= AO__opencl_atomic_load && Op <= AO__opencl_atomic_fetch_max) |
| ? AtomicScopeModelKind::OpenCL |
| : AtomicScopeModelKind::None; |
| return AtomicScopeModel::create(Kind); |
| } |
| |
| /// Get atomic scope model. |
| /// \return empty atomic scope model if this atomic expression does not have |
| /// scope operand. |
| std::unique_ptr<AtomicScopeModel> getScopeModel() const { |
| return getScopeModel(getOp()); |
| } |
| }; |
| |
| /// TypoExpr - Internal placeholder for expressions where typo correction |
| /// still needs to be performed and/or an error diagnostic emitted. |
| class TypoExpr : public Expr { |
| public: |
| TypoExpr(QualType T) |
| : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary, |
| /*isTypeDependent*/ true, |
| /*isValueDependent*/ true, |
| /*isInstantiationDependent*/ true, |
| /*containsUnexpandedParameterPack*/ false) { |
| assert(T->isDependentType() && "TypoExpr given a non-dependent type"); |
| } |
| |
| 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()); |
| } |
| |
| SourceLocation getBeginLoc() const LLVM_READONLY { return SourceLocation(); } |
| SourceLocation getEndLoc() const LLVM_READONLY { return SourceLocation(); } |
| |
| static bool classof(const Stmt *T) { |
| return T->getStmtClass() == TypoExprClass; |
| } |
| |
| }; |
| } // end namespace clang |
| |
| #endif // LLVM_CLANG_AST_EXPR_H |