diff options
Diffstat (limited to 'include/clang/AST/Expr.h')
-rw-r--r-- | include/clang/AST/Expr.h | 1157 |
1 files changed, 731 insertions, 426 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 1242f4e6c702c..558bd00ba978d 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -21,12 +21,13 @@ #include "clang/AST/OperationKinds.h" #include "clang/AST/ASTVector.h" #include "clang/AST/TemplateBase.h" -#include "clang/AST/UsuallyTinyPtrVector.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TypeTraits.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include <cctype> namespace clang { @@ -56,8 +57,8 @@ class Expr : public Stmt { protected: Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK, - bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack) - : Stmt(SC) + bool TD, bool VD, bool ID, bool ContainsUnexpandedParameterPack) + : Stmt(SC) { ExprBits.TypeDependent = TD; ExprBits.ValueDependent = VD; @@ -97,8 +98,8 @@ public: bool isValueDependent() const { return ExprBits.ValueDependent; } /// \brief Set whether this expression is value-dependent or not. - void setValueDependent(bool VD) { - ExprBits.ValueDependent = VD; + void setValueDependent(bool VD) { + ExprBits.ValueDependent = VD; if (VD) ExprBits.InstantiationDependent = true; } @@ -117,8 +118,8 @@ public: bool isTypeDependent() const { return ExprBits.TypeDependent; } /// \brief Set whether this expression is type-dependent or not. - void setTypeDependent(bool TD) { - ExprBits.TypeDependent = TD; + void setTypeDependent(bool TD) { + ExprBits.TypeDependent = TD; if (TD) ExprBits.InstantiationDependent = true; } @@ -140,12 +141,12 @@ public: /// } /// \endcode /// - bool isInstantiationDependent() const { - return ExprBits.InstantiationDependent; + bool isInstantiationDependent() const { + return ExprBits.InstantiationDependent; } - + /// \brief Set whether this expression is instantiation-dependent or not. - void setInstantiationDependent(bool ID) { + void setInstantiationDependent(bool ID) { ExprBits.InstantiationDependent = ID; } @@ -163,8 +164,8 @@ public: /// /// The expressions \c args and \c static_cast<Types&&>(args) both /// contain parameter packs. - bool containsUnexpandedParameterPack() const { - return ExprBits.ContainsUnexpandedParameterPack; + bool containsUnexpandedParameterPack() const { + return ExprBits.ContainsUnexpandedParameterPack; } /// \brief Set the bit that describes whether this expression @@ -175,7 +176,7 @@ public: /// getExprLoc - Return the preferred location for the arrow when diagnosing /// a problem with a generic expression. - SourceLocation getExprLoc() const; + 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 Loc and Ranges @@ -235,7 +236,6 @@ public: MLV_IncompleteType, MLV_ConstQualified, MLV_ArrayType, - MLV_NotBlockQualified, MLV_ReadonlyProperty, MLV_NoSetterProperty, MLV_MemberFunction, @@ -271,7 +271,6 @@ public: 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_NotBlockQualified, // Not captured in the closure CM_NoSetterProperty,// Implicit assignment to ObjC property without setter CM_ConstQualified, CM_ArrayType, @@ -302,12 +301,12 @@ public: bool isPRValue() const { return Kind >= CL_Function; } bool isRValue() const { return Kind >= CL_XValue; } bool isModifiable() const { return getModifiable() == CM_Modifiable; } - + /// \brief Create a simple, modifiably lvalue static Classification makeSimpleLValue() { return Classification(CL_LValue, CM_Modifiable); } - + }; /// \brief Classify - Classify this expression according to the C++0x /// expression taxonomy. @@ -390,54 +389,79 @@ public: /// \brief Returns whether this expression refers to a vector element. bool refersToVectorElement() const; - + + /// \brief Returns whether this expression has a placeholder type. + bool hasPlaceholderType() const { + return getType()->isPlaceholderType(); + } + + /// \brief Returns whether this expression has a specific placeholder type. + bool hasPlaceholderType(BuiltinType::Kind K) const { + assert(BuiltinType::isPlaceholderTypeKind(K)); + if (const BuiltinType *BT = dyn_cast<BuiltinType>(getType())) + return BT->getKind() == K; + return false; + } + /// isKnownToHaveBooleanValue - Return true if this is an integer expression /// that is known to return 0 or 1. This happens for _Bool/bool expressions /// but also int expressions which are produced by things like comparisons in /// C. bool isKnownToHaveBooleanValue() const; - + /// isIntegerConstantExpr - Return true if this expression is a valid integer /// constant expression, and, if so, return its value in Result. If not a /// valid i-c-e, return false and fill in Loc (if specified) with the location /// of the invalid expression. + /// + /// Note: This does not perform the implicit conversions required by C++11 + /// [expr.const]p5. bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, SourceLocation *Loc = 0, bool isEvaluated = true) const; - bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const { - llvm::APSInt X; - return isIntegerConstantExpr(X, Ctx, Loc); - } - /// isConstantInitializer - Returns true if this expression is a constant - /// initializer, which can be emitted at compile-time. - bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const; + bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const; - /// EvalResult is a struct with detailed info about an evaluated expression. - struct EvalResult { - /// Val - This is the value the expression can be folded to. - APValue Val; + /// isCXX98IntegralConstantExpr - Return true if this expression is an + /// integral constant expression in C++98. Can only be used in C++. + bool isCXX98IntegralConstantExpr(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(ASTContext &Ctx, APValue *Result = 0, + SourceLocation *Loc = 0) 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, + llvm::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. + bool isConstantInitializer(ASTContext &Ctx, bool ForRef) const; + /// EvalStatus is a struct with detailed info about an evaluation in progress. + struct EvalStatus { /// HasSideEffects - Whether the evaluated expression has side effects. /// For example, (f() && 0) can be folded, but it still has side effects. bool HasSideEffects; - /// Diag - If the expression is unfoldable, then Diag contains a note - /// diagnostic indicating why it's not foldable. DiagLoc indicates a caret - /// position for the error, and DiagExpr is the expression that caused - /// the error. - /// If the expression is foldable, but not an integer constant expression, - /// Diag contains a note diagnostic that describes why it isn't an integer - /// constant expression. If the expression *is* an integer constant - /// expression, then Diag will be zero. - unsigned Diag; - const Expr *DiagExpr; - SourceLocation DiagLoc; + /// 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. + llvm::SmallVectorImpl<PartialDiagnosticAt> *Diag; - EvalResult() : HasSideEffects(false), Diag(0), DiagExpr(0) {} + EvalStatus() : HasSideEffects(false), Diag(0) {} - // isGlobalLValue - Return true if the evaluated lvalue expression - // is global. - bool isGlobalLValue() const; // hasSideEffects - Return true if the evaluated expression has // side effects. bool hasSideEffects() const { @@ -445,11 +469,23 @@ public: } }; - /// Evaluate - Return true if this is a constant which we can fold using - /// any crazy technique (that has nothing to do with language standards) that - /// we want to. If this function returns true, it returns the folded constant - /// in Result. - bool Evaluate(EvalResult &Result, const ASTContext &Ctx) const; + /// EvalResult is a struct with detailed info about an evaluated expression. + struct EvalResult : EvalStatus { + /// Val - This is the value the expression can be folded to. + APValue Val; + + // isGlobalLValue - Return true if the evaluated lvalue expression + // is global. + bool isGlobalLValue() const; + }; + + /// EvaluateAsRValue - Return true if this is a constant which we can fold to + /// an rvalue using any crazy technique (that has nothing to do with language + /// standards) that we want to, even if the expression has side-effects. If + /// this function returns true, it returns the folded constant in Result. If + /// the expression is a glvalue, an lvalue-to-rvalue conversion will be + /// applied. + bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const; /// EvaluateAsBooleanCondition - Return true if this is a constant /// which we we can fold and convert to a boolean condition using @@ -457,30 +493,43 @@ public: /// side-effects. bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const; + enum SideEffectsKind { SE_NoSideEffects, SE_AllowSideEffects }; + /// EvaluateAsInt - Return true if this is a constant which we can fold and - /// convert to an integer using any crazy technique that we want to. - bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx) const; + /// convert to an integer, using any crazy technique that we want to. + bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, + SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; - /// isEvaluatable - Call Evaluate to see if this expression can be constant - /// folded, but discard the result. + /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be + /// constant folded without side-effects, but discard the result. bool isEvaluatable(const ASTContext &Ctx) const; /// HasSideEffects - This routine returns true for all those expressions - /// which must be evaluated each time and must not be optimized away + /// which must be evaluated each time and must not be optimized away /// or evaluated at compile time. Example is a function call, volatile /// variable read. bool HasSideEffects(const ASTContext &Ctx) const; + + /// \brief Determine whether this expression involves a call to any function + /// that is not trivial. + bool hasNonTrivialCall(ASTContext &Ctx); - /// EvaluateKnownConstInt - Call Evaluate and return the folded integer. This - /// must be called on an expression that constant folds to an integer. + /// 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) const; - /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue - /// with link time known address. + /// 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; - /// EvaluateAsLValue - Evaluate an expression to see if it's a lvalue. - bool EvaluateAsAnyLValue(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, + llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const; /// \brief Enumeration used to describe the kind of Null pointer constant /// returned from \c isNullPointerConstant(). @@ -503,16 +552,16 @@ public: enum NullPointerConstantValueDependence { /// \brief Specifies that the expression should never be value-dependent. NPC_NeverValueDependent = 0, - + /// \brief Specifies that a value-dependent expression of integral or /// dependent type should be considered a null pointer constant. NPC_ValueDependentIsNull, - + /// \brief Specifies that a value-dependent expression should be considered /// to never be a null pointer constant. NPC_ValueDependentIsNotNull }; - + /// isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to /// a Null pointer constant. The return value can further distinguish the /// kind of NULL pointer constant that was detected. @@ -544,60 +593,62 @@ public: /// IgnoreImpCasts - Skip past any implicit casts which might /// surround this expression. Only skips ImplicitCastExprs. - Expr *IgnoreImpCasts(); + Expr *IgnoreImpCasts() LLVM_READONLY; /// IgnoreImplicit - Skip past any implicit AST nodes which might /// surround this expression. - Expr *IgnoreImplicit() { return cast<Expr>(Stmt::IgnoreImplicit()); } + Expr *IgnoreImplicit() LLVM_READONLY { + return cast<Expr>(Stmt::IgnoreImplicit()); + } /// IgnoreParens - Ignore parentheses. If this Expr is a ParenExpr, return /// its subexpression. If that subexpression is also a ParenExpr, /// then this method recursively returns its subexpression, and so forth. /// Otherwise, the method returns the current Expr. - Expr *IgnoreParens(); + Expr *IgnoreParens() LLVM_READONLY; /// IgnoreParenCasts - Ignore parentheses and casts. Strip off any ParenExpr /// or CastExprs, returning their operand. - Expr *IgnoreParenCasts(); + Expr *IgnoreParenCasts() LLVM_READONLY; - /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off any - /// ParenExpr or ImplicitCastExprs, returning their operand. - Expr *IgnoreParenImpCasts(); + /// IgnoreParenImpCasts - Ignore parentheses and implicit casts. Strip off + /// any ParenExpr or ImplicitCastExprs, returning their operand. + Expr *IgnoreParenImpCasts() LLVM_READONLY; /// IgnoreConversionOperator - Ignore conversion operator. If this Expr is a /// call to a conversion operator, return the argument. - Expr *IgnoreConversionOperator(); + Expr *IgnoreConversionOperator() LLVM_READONLY; - const Expr *IgnoreConversionOperator() const { + const Expr *IgnoreConversionOperator() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreConversionOperator(); } - const Expr *IgnoreParenImpCasts() const { + const Expr *IgnoreParenImpCasts() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParenImpCasts(); } - + /// Ignore parentheses and lvalue casts. Strip off any ParenExpr and /// CastExprs that represent lvalue casts, returning their operand. - Expr *IgnoreParenLValueCasts(); - - const Expr *IgnoreParenLValueCasts() const { + Expr *IgnoreParenLValueCasts() LLVM_READONLY; + + const Expr *IgnoreParenLValueCasts() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParenLValueCasts(); } /// IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the /// value (including ptr->int casts of the same size). Strip off any /// ParenExpr or CastExprs, returning their operand. - Expr *IgnoreParenNoopCasts(ASTContext &Ctx); + Expr *IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY; /// \brief Determine whether this expression is a default function argument. /// /// Default arguments are implicitly generated in the abstract syntax tree - /// by semantic analysis for function calls, object constructions, etc. in + /// by semantic analysis for function calls, object constructions, etc. in /// C++. Default arguments are represented by \c CXXDefaultArgExpr nodes; /// this routine also looks through any implicit casts to determine whether /// the expression is a default argument. bool isDefaultArgument() const; - + /// \brief Determine whether the result of this expression is a /// temporary object of the given class type. bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const; @@ -605,21 +656,20 @@ public: /// \brief Whether this expression is an implicit reference to 'this' in C++. bool isImplicitCXXThis() const; - const Expr *IgnoreImpCasts() const { + const Expr *IgnoreImpCasts() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreImpCasts(); } - const Expr *IgnoreParens() const { + const Expr *IgnoreParens() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParens(); } - const Expr *IgnoreParenCasts() const { + const Expr *IgnoreParenCasts() const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParenCasts(); } - const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const { + const Expr *IgnoreParenNoopCasts(ASTContext &Ctx) const LLVM_READONLY { return const_cast<Expr*>(this)->IgnoreParenNoopCasts(Ctx); } - static bool hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs); - static bool hasAnyValueDependentArguments(Expr** Exprs, unsigned NumExprs); + static bool hasAnyTypeDependentArguments(llvm::ArrayRef<Expr *> Exprs); static bool classof(const Stmt *T) { return T->getStmtClass() >= firstExprConstant && @@ -642,15 +692,18 @@ class OpaqueValueExpr : public Expr { friend class ASTStmtReader; Expr *SourceExpr; SourceLocation Loc; - + public: - OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, - ExprObjectKind OK = OK_Ordinary) + OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, + ExprObjectKind OK = OK_Ordinary, + Expr *SourceExpr = 0) : Expr(OpaqueValueExprClass, T, VK, OK, - T->isDependentType(), T->isDependentType(), + T->isDependentType(), + T->isDependentType() || + (SourceExpr && SourceExpr->isValueDependent()), T->isInstantiationDependentType(), - false), - SourceExpr(0), Loc(Loc) { + false), + SourceExpr(SourceExpr), Loc(Loc) { } /// Given an expression which invokes a copy constructor --- i.e. a @@ -663,12 +716,12 @@ public: /// \brief Retrieve the location of this expression. SourceLocation getLocation() const { return Loc; } - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { if (SourceExpr) return SourceExpr->getSourceRange(); return Loc; } - SourceLocation getExprLoc() const { + SourceLocation getExprLoc() const LLVM_READONLY { if (SourceExpr) return SourceExpr->getExprLoc(); return Loc; } @@ -684,7 +737,6 @@ public: /// expression which binds the opaque value expression in the first /// place. Expr *getSourceExpr() const { return SourceExpr; } - void setSourceExpr(Expr *e) { SourceExpr = e; } static bool classof(const Stmt *T) { return T->getStmtClass() == OpaqueValueExprClass; @@ -709,9 +761,12 @@ public: /// 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.HasExplicitTemplateArgs: +/// DeclRefExprBits.HasTemplateKWAndArgsInfo: /// Specifies when this declaration reference expression has an explicit -/// C++ template argument list. +/// C++ template keyword and/or template argument list. +/// DeclRefExprBits.RefersToEnclosingLocal +/// Specifies when this declaration reference expression (validly) +/// refers to a local variable from a different function. class DeclRefExpr : public Expr { /// \brief The declaration that we are referencing. ValueDecl *D; @@ -753,8 +808,11 @@ class DeclRefExpr : public Expr { return const_cast<DeclRefExpr *>(this)->getInternalFoundDecl(); } - DeclRefExpr(NestedNameSpecifierLoc QualifierLoc, - ValueDecl *D, const DeclarationNameInfo &NameInfo, + DeclRefExpr(ASTContext &Ctx, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, + ValueDecl *D, bool refersToEnclosingLocal, + const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK); @@ -765,23 +823,27 @@ class DeclRefExpr : public Expr { /// \brief Computes the type- and value-dependence flags for this /// declaration reference expression. - void computeDependence(); + void computeDependence(ASTContext &C); public: - DeclRefExpr(ValueDecl *D, QualType T, ExprValueKind VK, SourceLocation L, + DeclRefExpr(ValueDecl *D, bool refersToEnclosingLocal, QualType T, + ExprValueKind VK, SourceLocation L, const DeclarationNameLoc &LocInfo = DeclarationNameLoc()) : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), D(D), Loc(L), DNLoc(LocInfo) { DeclRefExprBits.HasQualifier = 0; - DeclRefExprBits.HasExplicitTemplateArgs = 0; + DeclRefExprBits.HasTemplateKWAndArgsInfo = 0; DeclRefExprBits.HasFoundDecl = 0; DeclRefExprBits.HadMultipleCandidates = 0; - computeDependence(); + DeclRefExprBits.RefersToEnclosingLocal = refersToEnclosingLocal; + computeDependence(D->getASTContext()); } static DeclRefExpr *Create(ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool isEnclosingLocal, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD = 0, @@ -789,7 +851,9 @@ public: static DeclRefExpr *Create(ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool isEnclosingLocal, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, NamedDecl *FoundD = 0, @@ -799,7 +863,7 @@ public: static DeclRefExpr *CreateEmpty(ASTContext &Context, bool HasQualifier, bool HasFoundDecl, - bool HasExplicitTemplateArgs, + bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); ValueDecl *getDecl() { return D; } @@ -812,7 +876,9 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; /// \brief Determine whether this declaration reference was preceded by a /// C++ nested-name-specifier, e.g., \c N::foo. @@ -851,25 +917,65 @@ public: return hasFoundDecl() ? getInternalFoundDecl() : D; } - /// \brief Determines whether this declaration reference was followed by an - /// explict template argument list. - bool hasExplicitTemplateArgs() const { - return DeclRefExprBits.HasExplicitTemplateArgs; + bool hasTemplateKWAndArgsInfo() const { + return DeclRefExprBits.HasTemplateKWAndArgsInfo; } - /// \brief Retrieve the explicit template argument list that followed the - /// member template name. - ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(hasExplicitTemplateArgs()); + /// \brief Return the optional template keyword and arguments info. + ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { + if (!hasTemplateKWAndArgsInfo()) + return 0; + if (hasFoundDecl()) - return *reinterpret_cast<ASTTemplateArgumentListInfo *>( + return reinterpret_cast<ASTTemplateKWAndArgsInfo *>( &getInternalFoundDecl() + 1); if (hasQualifier()) - return *reinterpret_cast<ASTTemplateArgumentListInfo *>( + return reinterpret_cast<ASTTemplateKWAndArgsInfo *>( &getInternalQualifierLoc() + 1); - return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1); + return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1); + } + + /// \brief Return the optional template keyword and arguments info. + const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { + return const_cast<DeclRefExpr*>(this)->getTemplateKWAndArgsInfo(); + } + + /// \brief Retrieve the location of the template keyword preceding + /// this name, if any. + SourceLocation getTemplateKeywordLoc() const { + if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); + return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + } + + /// \brief Retrieve the location of the left angle bracket starting the + /// explicit template argument list following the name, if any. + SourceLocation getLAngleLoc() const { + if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); + return getTemplateKWAndArgsInfo()->LAngleLoc; + } + + /// \brief Retrieve the location of the right angle bracket ending the + /// explicit template argument list following the name, if any. + SourceLocation getRAngleLoc() const { + if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); + return getTemplateKWAndArgsInfo()->RAngleLoc; + } + + /// \brief Determines whether the name in this declaration reference + /// was preceded by the template keyword. + bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } + + /// \brief Determines whether this declaration reference was followed by an + /// explicit template argument list. + bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name. + ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { + assert(hasExplicitTemplateArgs()); + return *getTemplateKWAndArgsInfo(); } /// \brief Retrieve the explicit template argument list that followed the @@ -881,7 +987,7 @@ public: /// \brief Retrieves the optional explicit template arguments. /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. - const ASTTemplateArgumentListInfo *getExplicitTemplateArgsOpt() const { + const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; return &getExplicitTemplateArgs(); } @@ -893,15 +999,6 @@ public: getExplicitTemplateArgs().copyInto(List); } - /// \brief Retrieve the location of the left angle bracket following the - /// member name ('<'), if any. - SourceLocation getLAngleLoc() const { - if (!hasExplicitTemplateArgs()) - return SourceLocation(); - - return getExplicitTemplateArgs().LAngleLoc; - } - /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { @@ -920,15 +1017,6 @@ public: return getExplicitTemplateArgs().NumTemplateArgs; } - /// \brief Retrieve the location of the right angle bracket following the - /// template arguments ('>'). - SourceLocation getRAngleLoc() const { - if (!hasExplicitTemplateArgs()) - return SourceLocation(); - - return getExplicitTemplateArgs().RAngleLoc; - } - /// \brief Returns true if this expression refers to a function that /// was resolved from an overloaded set having size greater than 1. bool hadMultipleCandidates() const { @@ -941,6 +1029,12 @@ public: DeclRefExprBits.HadMultipleCandidates = V; } + /// Does this DeclRefExpr refer to a local declaration from an + /// enclosing function scope? + bool refersToEnclosingLocal() const { + return DeclRefExprBits.RefersToEnclosingLocal; + } + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass; } @@ -971,7 +1065,7 @@ private: public: PredefinedExpr(SourceLocation l, QualType type, IdentType IT) : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary, - type->isDependentType(), type->isDependentType(), + type->isDependentType(), type->isDependentType(), type->isInstantiationDependentType(), /*ContainsUnexpandedParameterPack=*/false), Loc(l), Type(IT) {} @@ -988,7 +1082,7 @@ public: static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); - SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } static bool classof(const Stmt *T) { return T->getStmtClass() == PredefinedExprClass; @@ -1008,11 +1102,11 @@ public: /// the APFloat/APInt values will never get freed. APNumericStorage uses /// ASTContext's allocator for memory allocation. class APNumericStorage { - unsigned BitWidth; 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; } @@ -1020,7 +1114,7 @@ class APNumericStorage { APNumericStorage& operator=(const APNumericStorage&); // do not implement protected: - APNumericStorage() : BitWidth(0), VAL(0) { } + APNumericStorage() : VAL(0), BitWidth(0) { } llvm::APInt getIntValue() const { unsigned NumWords = llvm::APInt::getNumWords(BitWidth); @@ -1032,22 +1126,23 @@ protected: void setIntValue(ASTContext &C, const llvm::APInt &Val); }; -class APIntStorage : public APNumericStorage { -public: - llvm::APInt getValue() const { return getIntValue(); } +class APIntStorage : private APNumericStorage { +public: + llvm::APInt getValue() const { return getIntValue(); } void setValue(ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); } }; -class APFloatStorage : public APNumericStorage { -public: - llvm::APFloat getValue() const { return llvm::APFloat(getIntValue()); } +class APFloatStorage : private APNumericStorage { +public: + llvm::APFloat getValue(bool IsIEEE) const { + return llvm::APFloat(getIntValue(), IsIEEE); + } void setValue(ASTContext &C, const llvm::APFloat &Val) { setIntValue(C, Val.bitcastToAPInt()); } }; -class IntegerLiteral : public Expr { - APIntStorage Num; +class IntegerLiteral : public Expr, public APIntStorage { SourceLocation Loc; /// \brief Construct an empty integer literal. @@ -1077,13 +1172,11 @@ public: /// \brief Returns a new empty integer literal. static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty); - llvm::APInt getValue() const { return Num.getValue(); } - SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } /// \brief Retrieve the location of the literal. SourceLocation getLocation() const { return Loc; } - void setValue(ASTContext &C, const llvm::APInt &Val) { Num.setValue(C, Val); } void setLocation(SourceLocation Location) { Loc = Location; } static bool classof(const Stmt *T) { @@ -1107,28 +1200,30 @@ public: private: unsigned Value; SourceLocation Loc; - unsigned Kind : 2; 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), Kind(kind) { + Value(value), Loc(l) { + CharacterLiteralBits.Kind = kind; } /// \brief Construct an empty character literal. CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { } SourceLocation getLocation() const { return Loc; } - CharacterKind getKind() const { return static_cast<CharacterKind>(Kind); } + CharacterKind getKind() const { + return static_cast<CharacterKind>(CharacterLiteralBits.Kind); + } - SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } unsigned getValue() const { return Value; } void setLocation(SourceLocation Location) { Loc = Location; } - void setKind(CharacterKind kind) { Kind = kind; } + void setKind(CharacterKind kind) { CharacterLiteralBits.Kind = kind; } void setValue(unsigned Val) { Value = Val; } static bool classof(const Stmt *T) { @@ -1140,35 +1235,41 @@ public: child_range children() { return child_range(); } }; -class FloatingLiteral : public Expr { - APFloatStorage Num; - bool IsExact : 1; +class FloatingLiteral : public Expr, private APFloatStorage { SourceLocation Loc; FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false, - false, false), - IsExact(isexact), Loc(L) { + false, false), Loc(L) { + FloatingLiteralBits.IsIEEE = + &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad; + FloatingLiteralBits.IsExact = isexact; setValue(C, V); } /// \brief Construct an empty floating-point literal. - explicit FloatingLiteral(EmptyShell Empty) - : Expr(FloatingLiteralClass, Empty), IsExact(false) { } + explicit FloatingLiteral(ASTContext &C, EmptyShell Empty) + : Expr(FloatingLiteralClass, Empty) { + FloatingLiteralBits.IsIEEE = + &C.getTargetInfo().getLongDoubleFormat() == &llvm::APFloat::IEEEquad; + FloatingLiteralBits.IsExact = false; + } public: static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L); static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty); - llvm::APFloat getValue() const { return Num.getValue(); } + llvm::APFloat getValue() const { + return APFloatStorage::getValue(FloatingLiteralBits.IsIEEE); + } void setValue(ASTContext &C, const llvm::APFloat &Val) { - Num.setValue(C, Val); + APFloatStorage::setValue(C, Val); } - bool isExact() const { return IsExact; } - void setExact(bool E) { IsExact = E; } + 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 @@ -1178,7 +1279,7 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - SourceRange getSourceRange() const { return SourceRange(Loc); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(Loc); } static bool classof(const Stmt *T) { return T->getStmtClass() == FloatingLiteralClass; @@ -1210,7 +1311,7 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - SourceRange getSourceRange() const { return Val->getSourceRange(); } + SourceRange getSourceRange() const LLVM_READONLY { return Val->getSourceRange(); } static bool classof(const Stmt *T) { return T->getStmtClass() == ImaginaryLiteralClass; } @@ -1249,17 +1350,24 @@ public: private: friend class ASTStmtReader; - const char *StrData; - unsigned ByteLength; - unsigned NumConcatenated; + union { + const char *asChar; + const uint16_t *asUInt16; + const uint32_t *asUInt32; + } StrData; + unsigned Length; + unsigned CharByteWidth : 4; unsigned Kind : 3; - bool IsPascal : 1; + unsigned IsPascal : 1; + unsigned NumConcatenated; SourceLocation TokLocs[1]; StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, VK_LValue, OK_Ordinary, false, false, false, false) {} + static int mapCharByteWidth(TargetInfo const &target,StringKind k); + public: /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. @@ -1278,15 +1386,46 @@ public: static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs); StringRef getString() const { - return StringRef(StrData, ByteLength); - } - - unsigned getByteLength() const { return ByteLength; } + assert(CharByteWidth==1 + && "This function is used in places that assume strings use char"); + return StringRef(StrData.asChar, getByteLength()); + } + + /// Allow clients that need the byte representation, such as ASTWriterStmt + /// ::VisitStringLiteral(), access. + StringRef getBytes() const { + // FIXME: StringRef may not be the right type to use as a result for this. + if (CharByteWidth == 1) + return StringRef(StrData.asChar, getByteLength()); + if (CharByteWidth == 4) + return StringRef(reinterpret_cast<const char*>(StrData.asUInt32), + getByteLength()); + assert(CharByteWidth == 2 && "unsupported CharByteWidth"); + return StringRef(reinterpret_cast<const char*>(StrData.asUInt16), + getByteLength()); + } + + uint32_t getCodeUnit(size_t i) const { + assert(i < Length && "out of bounds access"); + if (CharByteWidth == 1) + return static_cast<unsigned char>(StrData.asChar[i]); + if (CharByteWidth == 4) + return StrData.asUInt32[i]; + assert(CharByteWidth == 2 && "unsupported CharByteWidth"); + return StrData.asUInt16[i]; + } + + unsigned getByteLength() const { return CharByteWidth*Length; } + unsigned getLength() const { return Length; } + unsigned getCharByteWidth() const { return CharByteWidth; } /// \brief Sets the string data to the given string data. - void setString(ASTContext &C, StringRef Str); + void setString(ASTContext &C, StringRef Str, + StringKind Kind, bool IsPascal); StringKind getKind() const { return static_cast<StringKind>(Kind); } + + bool isAscii() const { return Kind == Ascii; } bool isWide() const { return Kind == Wide; } bool isUTF8() const { return Kind == UTF8; } @@ -1301,6 +1440,7 @@ public: return true; return false; } + /// getNumConcatenated - Get the number of string literal tokens that were /// concatenated in translation phase #6 to form this string literal. unsigned getNumConcatenated() const { return NumConcatenated; } @@ -1313,7 +1453,7 @@ public: assert(TokNum < NumConcatenated && "Invalid tok number"); TokLocs[TokNum] = L; } - + /// getLocationOfByte - Return a source location that points to the specified /// byte of this string literal. /// @@ -1329,7 +1469,7 @@ public: tokloc_iterator tokloc_begin() const { return TokLocs; } tokloc_iterator tokloc_end() const { return TokLocs+NumConcatenated; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(TokLocs[0], TokLocs[NumConcatenated-1]); } static bool classof(const Stmt *T) { @@ -1363,7 +1503,7 @@ public: Expr *getSubExpr() { return cast<Expr>(Val); } void setSubExpr(Expr *E) { Val = E; } - SourceRange getSourceRange() const { return SourceRange(L, R); } + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(L, R); } /// \brief Get the location of the left parentheses '('. SourceLocation getLParen() const { return L; } @@ -1408,7 +1548,7 @@ public: : Expr(UnaryOperatorClass, type, VK, OK, input->isTypeDependent() || type->isDependentType(), input->isValueDependent(), - (input->isInstantiationDependent() || + (input->isInstantiationDependent() || type->isInstantiationDependentType()), input->containsUnexpandedParameterPack()), Opc(opc), Loc(l), Val(input) {} @@ -1439,12 +1579,26 @@ public: 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 Opc == UO_PreInc || Opc == UO_PostInc; + 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 Opc <= UO_PreDec; + return isIncrementDecrementOp(getOpcode()); } + static bool isArithmeticOp(Opcode Op) { return Op >= UO_Plus && Op <= UO_LNot; } @@ -1462,13 +1616,13 @@ public: /// the given unary opcode. static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { if (isPostfix()) return SourceRange(Val->getLocStart(), Loc); else return SourceRange(Loc, Val->getLocEnd()); } - SourceLocation getExprLoc() const { return Loc; } + SourceLocation getExprLoc() const LLVM_READONLY { return Loc; } static bool classof(const Stmt *T) { return T->getStmtClass() == UnaryOperatorClass; @@ -1484,14 +1638,14 @@ public: /// @code /// struct S { /// float f; -/// double d; +/// 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). +/// we can represent and evaluate the expression @c offsetof(struct T, s[2].d). class OffsetOfExpr : public Expr { public: @@ -1513,48 +1667,48 @@ public: private: enum { MaskBits = 2, Mask = 0x03 }; - + /// \brief The source range that covers this part of the designator. SourceRange Range; - + /// \brief The data describing the designator, which comes in three /// different forms, depending on the lower two bits. - /// - An unsigned index into the array of Expr*'s stored after this node + /// - 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 + /// - A CXXBaseSpecifier*, for references that look at a field in a /// base class. uintptr_t Data; - + public: /// \brief Create an offsetof node that refers to an array element. - OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, + OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, SourceLocation RBracketLoc) : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) { } - + /// \brief Create an offsetof node that refers to a field. - OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, + OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc) - : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), + : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) { } - + /// \brief Create an offsetof node that refers to an identifier. OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name, SourceLocation NameLoc) - : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), + : Range(DotLoc.isValid()? DotLoc : NameLoc, NameLoc), Data(reinterpret_cast<uintptr_t>(Name) | Identifier) { } /// \brief Create an offsetof node that refers into a C++ base class. explicit OffsetOfNode(const CXXBaseSpecifier *Base) : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {} - + /// \brief Determine what kind of offsetof node this is. - Kind getKind() const { + Kind getKind() const { return static_cast<Kind>(Data & Mask); } - + /// \brief For an array element node, returns the index into the array /// of expressions. unsigned getArrayExprIndex() const { @@ -1567,28 +1721,28 @@ public: assert(getKind() == Field); return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask); } - + /// \brief For a field or identifier offsetof node, returns the name of /// the field. IdentifierInfo *getFieldName() const; - + /// \brief For a base class node, returns the base specifier. CXXBaseSpecifier *getBase() const { assert(getKind() == Base); - return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); + return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); } - + /// \brief Retrieve the source range that covers this offsetof node. /// /// For an array element node, the source range contains the locations of /// the square brackets. For a field or identifier node, the source range - /// contains the location of the period (if there is one) and the + /// contains the location of the period (if there is one) and the /// identifier. - SourceRange getSourceRange() const { return Range; } + SourceRange getSourceRange() const LLVM_READONLY { return Range; } }; private: - + SourceLocation OperatorLoc, RParenLoc; // Base type; TypeSourceInfo *TSInfo; @@ -1596,26 +1750,26 @@ private: unsigned NumComps; // Number of sub-expressions (i.e. array subscript expressions). unsigned NumExprs; - - OffsetOfExpr(ASTContext &C, QualType type, + + OffsetOfExpr(ASTContext &C, QualType type, SourceLocation OperatorLoc, TypeSourceInfo *tsi, - OffsetOfNode* compsPtr, unsigned numComps, + OffsetOfNode* compsPtr, unsigned numComps, Expr** exprsPtr, unsigned numExprs, SourceLocation RParenLoc); explicit OffsetOfExpr(unsigned numComps, unsigned numExprs) : Expr(OffsetOfExprClass, EmptyShell()), - TSInfo(0), NumComps(numComps), NumExprs(numExprs) {} + TSInfo(0), NumComps(numComps), NumExprs(numExprs) {} public: - - static OffsetOfExpr *Create(ASTContext &C, QualType type, - SourceLocation OperatorLoc, TypeSourceInfo *tsi, - OffsetOfNode* compsPtr, unsigned numComps, + + static OffsetOfExpr *Create(ASTContext &C, QualType type, + SourceLocation OperatorLoc, TypeSourceInfo *tsi, + OffsetOfNode* compsPtr, unsigned numComps, Expr** exprsPtr, unsigned numExprs, SourceLocation RParenLoc); - static OffsetOfExpr *CreateEmpty(ASTContext &C, + static OffsetOfExpr *CreateEmpty(ASTContext &C, unsigned NumComps, unsigned NumExprs); /// getOperatorLoc - Return the location of the operator. @@ -1625,14 +1779,14 @@ public: /// \brief Return the location of the right parentheses. SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation R) { RParenLoc = R; } - + TypeSourceInfo *getTypeSourceInfo() const { return TSInfo; } void setTypeSourceInfo(TypeSourceInfo *tsi) { TSInfo = tsi; } - + const OffsetOfNode &getComponent(unsigned Idx) const { assert(Idx < NumComps && "Subscript out of range"); return reinterpret_cast<const OffsetOfNode *> (this + 1)[Idx]; @@ -1642,7 +1796,7 @@ public: assert(Idx < NumComps && "Subscript out of range"); reinterpret_cast<OffsetOfNode *> (this + 1)[Idx] = ON; } - + unsigned getNumComponents() const { return NumComps; } @@ -1661,12 +1815,12 @@ public: reinterpret_cast<Expr **>( reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx] = E; } - + unsigned getNumExpressions() const { return NumExprs; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(OperatorLoc, RParenLoc); } @@ -1689,8 +1843,6 @@ public: /// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and /// vec_step (OpenCL 1.1 6.11.12). class UnaryExprOrTypeTraitExpr : public Expr { - unsigned Kind : 2; - bool isType : 1; // true if operand is a type, false if an expression union { TypeSourceInfo *Ty; Stmt *Ex; @@ -1707,7 +1859,9 @@ public: TInfo->getType()->isDependentType(), TInfo->getType()->isInstantiationDependentType(), TInfo->getType()->containsUnexpandedParameterPack()), - Kind(ExprKind), isType(true), OpLoc(op), RParenLoc(rp) { + OpLoc(op), RParenLoc(rp) { + UnaryExprOrTypeTraitExprBits.Kind = ExprKind; + UnaryExprOrTypeTraitExprBits.IsType = true; Argument.Ty = TInfo; } @@ -1720,7 +1874,9 @@ public: E->isTypeDependent(), E->isInstantiationDependent(), E->containsUnexpandedParameterPack()), - Kind(ExprKind), isType(false), OpLoc(op), RParenLoc(rp) { + OpLoc(op), RParenLoc(rp) { + UnaryExprOrTypeTraitExprBits.Kind = ExprKind; + UnaryExprOrTypeTraitExprBits.IsType = false; Argument.Ex = E; } @@ -1729,11 +1885,11 @@ public: : Expr(UnaryExprOrTypeTraitExprClass, Empty) { } UnaryExprOrTypeTrait getKind() const { - return static_cast<UnaryExprOrTypeTrait>(Kind); + return static_cast<UnaryExprOrTypeTrait>(UnaryExprOrTypeTraitExprBits.Kind); } - void setKind(UnaryExprOrTypeTrait K) { Kind = K; } + void setKind(UnaryExprOrTypeTrait K) { UnaryExprOrTypeTraitExprBits.Kind = K;} - bool isArgumentType() const { return isType; } + bool isArgumentType() const { return UnaryExprOrTypeTraitExprBits.IsType; } QualType getArgumentType() const { return getArgumentTypeInfo()->getType(); } @@ -1749,10 +1905,13 @@ public: return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr(); } - void setArgument(Expr *E) { Argument.Ex = E; isType = false; } + void setArgument(Expr *E) { + Argument.Ex = E; + UnaryExprOrTypeTraitExprBits.IsType = false; + } void setArgument(TypeSourceInfo *TInfo) { Argument.Ty = TInfo; - isType = true; + UnaryExprOrTypeTraitExprBits.IsType = true; } /// Gets the argument type, or the type of the argument expression, whichever @@ -1767,7 +1926,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(OpLoc, RParenLoc); } @@ -1842,14 +2001,14 @@ public: return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLHS()->getLocStart(), RBracketLoc); } SourceLocation getRBracketLoc() const { return RBracketLoc; } void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } - SourceLocation getExprLoc() const { return getBase()->getExprLoc(); } + SourceLocation getExprLoc() const LLVM_READONLY { return getBase()->getExprLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == ArraySubscriptExprClass; @@ -1927,7 +2086,10 @@ public: Expr **getArgs() { return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START); } - + const Expr *const *getArgs() const { + return const_cast<CallExpr*>(this)->getArgs(); + } + /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); @@ -1969,7 +2131,7 @@ public: /// isBuiltinCall - If this is a call to a builtin, return the builtin ID. If /// not, return 0. - unsigned isBuiltinCall(const ASTContext &Context) const; + unsigned isBuiltinCall() 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 @@ -1979,7 +2141,9 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() >= firstCallExprConstant && @@ -2016,13 +2180,13 @@ class MemberExpr : public Expr { /// In X.F, this is the decl referenced by F. ValueDecl *MemberDecl; - /// MemberLoc - This is the location of the member name. - SourceLocation MemberLoc; - /// 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; + /// IsArrow - True if this is "X->F", false if this is "X.F". bool IsArrow : 1; @@ -2032,12 +2196,14 @@ class MemberExpr : public Expr { /// structure is allocated immediately after the MemberExpr. bool HasQualifierOrFoundDecl : 1; - /// \brief True if this member expression specified a template argument list - /// explicitly, e.g., x->f<int>. When true, an ExplicitTemplateArgumentList - /// structure (and its TemplateArguments) are allocated immediately after - /// the MemberExpr or, if the member expression also has a qualifier, after - /// the MemberNameQualifier structure. - bool HasExplicitTemplateArgumentList : 1; + /// \brief True if this member expression specified a template keyword + /// and/or a template argument list explicitly, e.g., x->f<int>, + /// x->template f, x->template f<int>. + /// When true, an ASTTemplateKWAndArgsInfo structure and its + /// TemplateArguments (if any) are allocated immediately after + /// the MemberExpr or, if the member expression also has a qualifier, + /// after the MemberNameQualifier structure. + bool HasTemplateKWAndArgsInfo : 1; /// \brief True if this member expression refers to a method that /// was resolved from an overloaded set having size greater than 1. @@ -2059,13 +2225,13 @@ public: const DeclarationNameInfo &NameInfo, QualType ty, ExprValueKind VK, ExprObjectKind OK) : Expr(MemberExprClass, ty, VK, OK, - base->isTypeDependent(), + base->isTypeDependent(), base->isValueDependent(), base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), - Base(base), MemberDecl(memberdecl), MemberLoc(NameInfo.getLoc()), - MemberDNLoc(NameInfo.getInfo()), IsArrow(isarrow), - HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false), + Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()), + MemberLoc(NameInfo.getLoc()), IsArrow(isarrow), + HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) { assert(memberdecl->getDeclName() == NameInfo.getName()); } @@ -2073,7 +2239,7 @@ public: // 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 oeprators). + // for constructors, destructors and conversion operators). MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl, SourceLocation l, QualType ty, ExprValueKind VK, ExprObjectKind OK) @@ -2081,13 +2247,14 @@ public: base->isTypeDependent(), base->isValueDependent(), base->isInstantiationDependent(), base->containsUnexpandedParameterPack()), - Base(base), MemberDecl(memberdecl), MemberLoc(l), MemberDNLoc(), + Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l), IsArrow(isarrow), - HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false), + HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) {} static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, ValueDecl *memberdecl, DeclAccessPair founddecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *targs, @@ -2126,22 +2293,61 @@ public: return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier(); } - /// \brief If the member name was qualified, retrieves the + /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name, with source-location /// information. NestedNameSpecifierLoc getQualifierLoc() const { if (!hasQualifier()) return NestedNameSpecifierLoc(); - + return getMemberQualifier()->QualifierLoc; } - /// \brief Determines whether this member expression actually had a C++ - /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgs() const { - return HasExplicitTemplateArgumentList; + /// \brief Return the optional template keyword and arguments info. + ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() { + if (!HasTemplateKWAndArgsInfo) + return 0; + + if (!HasQualifierOrFoundDecl) + return reinterpret_cast<ASTTemplateKWAndArgsInfo *>(this + 1); + + return reinterpret_cast<ASTTemplateKWAndArgsInfo *>( + getMemberQualifier() + 1); + } + + /// \brief Return the optional template keyword and arguments info. + const ASTTemplateKWAndArgsInfo *getTemplateKWAndArgsInfo() const { + return const_cast<MemberExpr*>(this)->getTemplateKWAndArgsInfo(); + } + + /// \brief Retrieve the location of the template keyword preceding + /// the member name, if any. + SourceLocation getTemplateKeywordLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->getTemplateKeywordLoc(); + } + + /// \brief Retrieve the location of the left angle bracket starting the + /// explicit template argument list following the member name, if any. + SourceLocation getLAngleLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->LAngleLoc; + } + + /// \brief Retrieve the location of the right angle bracket ending the + /// explicit template argument list following the member name, if any. + SourceLocation getRAngleLoc() const { + if (!HasTemplateKWAndArgsInfo) return SourceLocation(); + return getTemplateKWAndArgsInfo()->RAngleLoc; } + /// Determines whether the member name was preceded by the template keyword. + bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } + + /// \brief Determines whether the member name was followed by an + /// explicit template argument list. + bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { @@ -2153,12 +2359,8 @@ public: /// follow the member template name. This must only be called on an /// expression with explicit template arguments. ASTTemplateArgumentListInfo &getExplicitTemplateArgs() { - assert(HasExplicitTemplateArgumentList); - if (!HasQualifierOrFoundDecl) - return *reinterpret_cast<ASTTemplateArgumentListInfo *>(this + 1); - - return *reinterpret_cast<ASTTemplateArgumentListInfo *>( - getMemberQualifier() + 1); + assert(hasExplicitTemplateArgs()); + return *getTemplateKWAndArgsInfo(); } /// \brief Retrieve the explicit template argument list that @@ -2175,20 +2377,11 @@ public: if (!hasExplicitTemplateArgs()) return 0; return &getExplicitTemplateArgs(); } - - /// \brief Retrieve the location of the left angle bracket following the - /// member name ('<'), if any. - SourceLocation getLAngleLoc() const { - if (!HasExplicitTemplateArgumentList) - return SourceLocation(); - - return getExplicitTemplateArgs().LAngleLoc; - } /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { - if (!HasExplicitTemplateArgumentList) + if (!hasExplicitTemplateArgs()) return 0; return getExplicitTemplateArgs().getTemplateArgs(); @@ -2197,21 +2390,12 @@ public: /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { - if (!HasExplicitTemplateArgumentList) + if (!hasExplicitTemplateArgs()) return 0; return getExplicitTemplateArgs().NumTemplateArgs; } - /// \brief Retrieve the location of the right angle bracket following the - /// template arguments ('>'). - SourceLocation getRAngleLoc() const { - if (!HasExplicitTemplateArgumentList) - return SourceLocation(); - - return getExplicitTemplateArgs().RAngleLoc; - } - /// \brief Retrieve the member declaration name info. DeclarationNameInfo getMemberNameInfo() const { return DeclarationNameInfo(MemberDecl->getDeclName(), @@ -2226,9 +2410,11 @@ public: SourceLocation getMemberLoc() const { return MemberLoc; } void setMemberLoc(SourceLocation L) { MemberLoc = L; } - SourceRange getSourceRange() const; - - SourceLocation getExprLoc() const { return MemberLoc; } + SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; + + SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; } /// \brief Determine whether the base of this explicit is implicit. bool isImplicitAccess() const { @@ -2269,19 +2455,19 @@ class CompoundLiteralExpr : public Expr { /// The type as written. This can be an incomplete array type, in /// which case the actual expression type will be different. - TypeSourceInfo *TInfo; + /// The int part of the pair stores whether this expr is file scope. + llvm::PointerIntPair<TypeSourceInfo *, 1, bool> TInfoAndScope; Stmt *Init; - bool FileScope; public: CompoundLiteralExpr(SourceLocation lparenloc, TypeSourceInfo *tinfo, QualType T, ExprValueKind VK, Expr *init, bool fileScope) : Expr(CompoundLiteralExprClass, T, VK, OK_Ordinary, - tinfo->getType()->isDependentType(), + tinfo->getType()->isDependentType(), init->isValueDependent(), (init->isInstantiationDependent() || tinfo->getType()->isInstantiationDependentType()), init->containsUnexpandedParameterPack()), - LParenLoc(lparenloc), TInfo(tinfo), Init(init), FileScope(fileScope) {} + LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {} /// \brief Construct an empty compound literal. explicit CompoundLiteralExpr(EmptyShell Empty) @@ -2291,16 +2477,20 @@ public: Expr *getInitializer() { return cast<Expr>(Init); } void setInitializer(Expr *E) { Init = E; } - bool isFileScope() const { return FileScope; } - void setFileScope(bool FS) { FileScope = FS; } + 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 TInfo; } - void setTypeSourceInfo(TypeSourceInfo* tinfo) { TInfo = tinfo; } + TypeSourceInfo *getTypeSourceInfo() const { + return TInfoAndScope.getPointer(); + } + void setTypeSourceInfo(TypeSourceInfo *tinfo) { + TInfoAndScope.setPointer(tinfo); + } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { // FIXME: Init should never be null. if (!Init) return SourceRange(); @@ -2352,7 +2542,7 @@ protected: // Cast expressions are value-dependent if the type is // dependent or if the subexpression is value-dependent. ty->isDependentType() || (op && op->isValueDependent()), - (ty->isInstantiationDependentType() || + (ty->isInstantiationDependentType() || (op && op->isInstantiationDependent())), (ty->containsUnexpandedParameterPack() || op->containsUnexpandedParameterPack())), @@ -2454,9 +2644,15 @@ public: static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return getSubExpr()->getSourceRange(); } + SourceLocation getLocStart() const LLVM_READONLY { + return getSubExpr()->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + return getSubExpr()->getLocEnd(); + } static bool classof(const Stmt *T) { return T->getStmtClass() == ImplicitCastExprClass; @@ -2551,7 +2747,7 @@ public: SourceLocation getRParenLoc() const { return RPLoc; } void setRParenLoc(SourceLocation L) { RPLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LPLoc, getSubExpr()->getSourceRange().getEnd()); } static bool classof(const Stmt *T) { @@ -2611,6 +2807,7 @@ public: explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { } + SourceLocation getExprLoc() const LLVM_READONLY { return OpLoc; } SourceLocation getOperatorLoc() const { return OpLoc; } void setOperatorLoc(SourceLocation L) { OpLoc = L; } @@ -2622,7 +2819,7 @@ public: Expr *getRHS() const { return cast<Expr>(SubExprs[RHS]); } void setRHS(Expr *E) { SubExprs[RHS] = E; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLHS()->getLocStart(), getRHS()->getLocEnd()); } @@ -2674,6 +2871,13 @@ public: 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; @@ -2842,11 +3046,11 @@ public: // 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]); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getCond()->getLocStart(), getRHS()->getLocEnd()); } static bool classof(const Stmt *T) { @@ -2895,8 +3099,7 @@ public: SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; - - OpaqueValue->setSourceExpr(common); + assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value"); } /// \brief Build an empty conditional operator. @@ -2928,8 +3131,8 @@ public: Expr *getFalseExpr() const { return cast<Expr>(SubExprs[RHS]); } - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getCommon()->getLocStart(), getFalseExpr()->getLocEnd()); } static bool classof(const Stmt *T) { @@ -2981,7 +3184,7 @@ public: SourceLocation getLabelLoc() const { return LabelLoc; } void setLabelLoc(SourceLocation L) { LabelLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(AmpAmpLoc, LabelLoc); } @@ -3023,7 +3226,7 @@ public: const CompoundStmt *getSubStmt() const { return cast<CompoundStmt>(SubStmt); } void setSubStmt(CompoundStmt *S) { SubStmt = S; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LParenLoc, RParenLoc); } @@ -3073,7 +3276,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -3088,7 +3291,7 @@ public: /// \brief 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!"); @@ -3168,7 +3371,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -3205,7 +3408,7 @@ public: SourceLocation getTokenLocation() const { return TokenLoc; } void setTokenLocation(SourceLocation L) { TokenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(TokenLoc); } static bool classof(const Stmt *T) { @@ -3251,7 +3454,7 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -3319,10 +3522,6 @@ class InitListExpr : public Expr { /// field within the union will be initialized. llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit; - /// Whether this initializer list originally had a GNU array-range - /// designator in it. This is a temporary marker used by CodeGen. - bool HadArrayRangeDesignator; - public: InitListExpr(ASTContext &C, SourceLocation lbraceloc, Expr **initexprs, unsigned numinits, @@ -3336,7 +3535,7 @@ public: /// \brief Retrieve the set of initializers. Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); } - + const Expr *getInit(unsigned Init) const { assert(Init < getNumInits() && "Initializer access out of range!"); return cast_or_null<Expr>(InitExprs[Init]); @@ -3383,6 +3582,10 @@ public: } void setArrayFiller(Expr *filler); + /// \brief Return true if this is an array initializer and its array "filler" + /// has been set. + bool hasArrayFiller() const { return getArrayFiller(); } + /// \brief If this initializes a union, specifies which field in the /// union to initialize. /// @@ -3417,12 +3620,21 @@ public: InitListExpr *getSyntacticForm() const { return SyntacticForm; } void setSyntacticForm(InitListExpr *Init) { SyntacticForm = Init; } - bool hadArrayRangeDesignator() const { return HadArrayRangeDesignator; } + bool hadArrayRangeDesignator() const { + return InitListExprBits.HadArrayRangeDesignator != 0; + } void sawArrayRangeDesignator(bool ARD = true) { - HadArrayRangeDesignator = ARD; + InitListExprBits.HadArrayRangeDesignator = ARD; + } + + bool initializesStdInitializerList() const { + return InitListExprBits.InitializesStdInitializerList != 0; + } + void setInitializesStdInitializerList(bool ISIL = true) { + InitListExprBits.InitializesStdInitializerList = ISIL; } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == InitListExprClass; @@ -3490,15 +3702,15 @@ private: /// The number of designators in this initializer expression. unsigned NumDesignators : 15; - /// \brief The designators in this designated initialization - /// expression. - Designator *Designators; - /// 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; + /// \brief The designators in this designated initialization + /// expression. + Designator *Designators; + DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumDesignators, const Designator *Designators, @@ -3508,7 +3720,7 @@ private: explicit DesignatedInitExpr(unsigned NumSubExprs) : Expr(DesignatedInitExprClass, EmptyShell()), - NumDesignators(0), Designators(0), NumSubExprs(NumSubExprs) { } + NumDesignators(0), NumSubExprs(NumSubExprs), Designators(0) { } public: /// A field designator, e.g., ".x". @@ -3658,7 +3870,7 @@ public: SourceLocation getEndLocation() const { return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc(); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getStartLocation(), getEndLocation()); } }; @@ -3707,7 +3919,7 @@ public: Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; } - void setDesignators(ASTContext &C, const Designator *Desigs, + void setDesignators(ASTContext &C, const Designator *Desigs, unsigned NumDesigs); Expr *getArrayIndex(const Designator& D); @@ -3760,7 +3972,7 @@ public: SourceRange getDesignatorsSourceRange() const; - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == DesignatedInitExprClass; @@ -3797,7 +4009,7 @@ public: } static bool classof(const ImplicitValueInitExpr *) { return true; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(); } @@ -3813,7 +4025,7 @@ class ParenListExpr : public Expr { public: ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, - unsigned numexprs, SourceLocation rparenloc, QualType T); + unsigned numexprs, SourceLocation rparenloc); /// \brief Build an empty paren list. explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } @@ -3835,7 +4047,7 @@ public: SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LParenLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -3853,9 +4065,9 @@ public: }; -/// \brief Represents a C1X generic selection. +/// \brief Represents a C11 generic selection. /// -/// A generic selection (C1X 6.5.1.1) contains an unevaluated controlling +/// 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). @@ -3950,7 +4162,7 @@ public: const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); } Expr *getResultExpr() { return getAssocExpr(getResultIndex()); } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(GenericLoc, RParenLoc); } static bool classof(const Stmt *T) { @@ -4016,7 +4228,7 @@ public: /// aggregate Constant of ConstantInt(s). void getEncodedElementAccess(SmallVectorImpl<unsigned> &Elts) const; - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getBase()->getLocStart(), AccessorLoc); } @@ -4042,9 +4254,8 @@ protected: public: BlockExpr(BlockDecl *BD, QualType ty) : Expr(BlockExprClass, ty, VK_RValue, OK_Ordinary, - ty->isDependentType(), false, - // FIXME: Check for instantiate-dependence in the statement? - ty->isInstantiationDependentType(), + ty->isDependentType(), ty->isDependentType(), + ty->isInstantiationDependentType() || BD->isDependentContext(), false), TheBlock(BD) {} @@ -4060,12 +4271,12 @@ public: const Stmt *getBody() const; Stmt *getBody(); - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getCaretLocation(), getBody()->getLocEnd()); } /// getFunctionType - Return the underlying function type for this block. - const FunctionType *getFunctionType() const; + const FunctionProtoType *getFunctionType() const; static bool classof(const Stmt *T) { return T->getStmtClass() == BlockExprClass; @@ -4076,46 +4287,6 @@ public: child_range children() { return child_range(); } }; -/// BlockDeclRefExpr - A reference to a local variable declared in an -/// enclosing scope. -class BlockDeclRefExpr : public Expr { - VarDecl *D; - SourceLocation Loc; - bool IsByRef : 1; - bool ConstQualAdded : 1; -public: - BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK, - SourceLocation l, bool ByRef, bool constAdded = false); - - // \brief Build an empty reference to a declared variable in a - // block. - explicit BlockDeclRefExpr(EmptyShell Empty) - : Expr(BlockDeclRefExprClass, Empty) { } - - VarDecl *getDecl() { return D; } - const VarDecl *getDecl() const { return D; } - void setDecl(VarDecl *VD) { D = VD; } - - SourceLocation getLocation() const { return Loc; } - void setLocation(SourceLocation L) { Loc = L; } - - SourceRange getSourceRange() const { return SourceRange(Loc); } - - bool isByRef() const { return IsByRef; } - void setByRef(bool BR) { IsByRef = BR; } - - bool isConstQualAdded() const { return ConstQualAdded; } - void setConstQualAdded(bool C) { ConstQualAdded = C; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == BlockDeclRefExprClass; - } - static bool classof(const BlockDeclRefExpr *) { return true; } - - // Iterators - child_range children() { return child_range(); } -}; - /// 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. @@ -4127,12 +4298,12 @@ private: 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, + : Expr(AsTypeExprClass, DstType, VK, OK, DstType->isDependentType(), DstType->isDependentType() || SrcExpr->isValueDependent(), (DstType->isInstantiationDependentType() || @@ -4140,7 +4311,7 @@ public: (DstType->containsUnexpandedParameterPack() || SrcExpr->containsUnexpandedParameterPack())), SrcExpr(SrcExpr), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} - + /// getSrcExpr - Return the Expr to be converted. Expr *getSrcExpr() const { return cast<Expr>(SrcExpr); } @@ -4149,83 +4320,218 @@ public: /// getRParenLoc - Return the location of final right parenthesis. SourceLocation getRParenLoc() const { return RParenLoc; } - - SourceRange getSourceRange() const { + + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BuiltinLoc, RParenLoc); } - + static bool classof(const Stmt *T) { - return T->getStmtClass() == AsTypeExprClass; + return T->getStmtClass() == AsTypeExprClass; } static bool classof(const AsTypeExpr *) { return true; } - + // Iterators child_range children() { return 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 : public 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 reinterpret_cast<Expr**>(this + 1); } + const Expr * const *getSubExprsBuffer() const { + return reinterpret_cast<const Expr * const *>(this + 1); + } + + friend class ASTStmtReader; + + 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 { NoResult = ~0U }; + + static PseudoObjectExpr *Create(ASTContext &Context, Expr *syntactic, + ArrayRef<Expr*> semantic, + unsigned resultIndex); + + static PseudoObjectExpr *Create(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 0; + 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(); + } + 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(); + } + SourceRange getSourceRange() const LLVM_READONLY { + return getSyntacticForm()->getSourceRange(); + } + + child_range children() { + Stmt **cs = reinterpret_cast<Stmt**>(getSubExprsBuffer()); + return child_range(cs, cs + getNumSubExprs()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == PseudoObjectExprClass; + } + static bool classof(const PseudoObjectExpr *) { return true; } +}; + /// AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, /// __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the -/// similarly-named C++0x instructions. All of these instructions take one -/// primary pointer and at least one memory order. +/// similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>. +/// All of these instructions take one primary pointer and at least one memory +/// order. class AtomicExpr : public Expr { public: - enum AtomicOp { Load, Store, CmpXchgStrong, CmpXchgWeak, Xchg, - Add, Sub, And, Or, Xor }; + 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: - enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, END_EXPR }; + enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR }; Stmt* SubExprs[END_EXPR]; unsigned NumSubExprs; SourceLocation BuiltinLoc, RParenLoc; AtomicOp Op; + friend class ASTStmtReader; + public: AtomicExpr(SourceLocation BLoc, Expr **args, unsigned nexpr, QualType t, AtomicOp op, SourceLocation RP); + /// \brief Determine the number of arguments the specified atomic builtin + /// should have. + static unsigned getNumSubExprs(AtomicOp Op); + /// \brief Build an empty AtomicExpr. explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { } Expr *getPtr() const { return cast<Expr>(SubExprs[PTR]); } - void setPtr(Expr *E) { - SubExprs[PTR] = E; - } Expr *getOrder() const { return cast<Expr>(SubExprs[ORDER]); } - void setOrder(Expr *E) { - SubExprs[ORDER] = E; - } Expr *getVal1() const { - assert(NumSubExprs >= 3); + if (Op == AO__c11_atomic_init) + return cast<Expr>(SubExprs[ORDER]); + assert(NumSubExprs > VAL1); return cast<Expr>(SubExprs[VAL1]); } - void setVal1(Expr *E) { - assert(NumSubExprs >= 3); - SubExprs[VAL1] = E; - } Expr *getOrderFail() const { - assert(NumSubExprs == 5); + assert(NumSubExprs > ORDER_FAIL); return cast<Expr>(SubExprs[ORDER_FAIL]); } - void setOrderFail(Expr *E) { - assert(NumSubExprs == 5); - SubExprs[ORDER_FAIL] = E; - } Expr *getVal2() const { - assert(NumSubExprs == 5); + if (Op == AO__atomic_exchange) + return cast<Expr>(SubExprs[ORDER_FAIL]); + assert(NumSubExprs > VAL2); return cast<Expr>(SubExprs[VAL2]); } - void setVal2(Expr *E) { - assert(NumSubExprs == 5); - SubExprs[VAL2] = E; + Expr *getWeak() const { + assert(NumSubExprs > WEAK); + return cast<Expr>(SubExprs[WEAK]); } AtomicOp getOp() const { return Op; } - void setOp(AtomicOp op) { Op = op; } unsigned getNumSubExprs() { return NumSubExprs; } - void setNumSubExprs(unsigned num) { NumSubExprs = num; } Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); } @@ -4234,17 +4540,16 @@ public: } bool isCmpXChg() const { - return getOp() == AtomicExpr::CmpXchgStrong || - getOp() == AtomicExpr::CmpXchgWeak; + return getOp() == AO__c11_atomic_compare_exchange_strong || + getOp() == AO__c11_atomic_compare_exchange_weak || + getOp() == AO__atomic_compare_exchange || + getOp() == AO__atomic_compare_exchange_n; } SourceLocation getBuiltinLoc() const { return BuiltinLoc; } - void setBuiltinLoc(SourceLocation L) { BuiltinLoc = L; } - SourceLocation getRParenLoc() const { return RParenLoc; } - void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(BuiltinLoc, RParenLoc); } static bool classof(const Stmt *T) { |