diff options
Diffstat (limited to 'include/clang/AST/Decl.h')
-rw-r--r-- | include/clang/AST/Decl.h | 852 |
1 files changed, 542 insertions, 310 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index a02a2ce..11696db 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -22,6 +22,7 @@ #include "clang/Basic/Linkage.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" +#include "llvm/Support/Compiler.h" namespace clang { class CXXTemporary; @@ -40,7 +41,8 @@ class DependentFunctionTemplateSpecializationInfo; class TypeLoc; class UnresolvedSetImpl; class LabelStmt; - +class Module; + /// \brief A container of type source information. /// /// A client can read the relevant info using TypeLoc wrappers, e.g: @@ -66,6 +68,7 @@ public: /// TranslationUnitDecl - The top declaration context. class TranslationUnitDecl : public Decl, public DeclContext { + virtual void anchor(); ASTContext &Ctx; /// The (most recently entered) anonymous namespace for this @@ -98,11 +101,15 @@ public: /// NamedDecl - This represents a decl with a name. Many decls have names such /// as ObjCMethodDecl, but not @class, etc. class NamedDecl : public Decl { + virtual void anchor(); /// Name - The name of this declaration, which is typically a normal /// identifier but may also be a special kind of name (C++ /// constructor, Objective-C selector, etc.) DeclarationName Name; +private: + NamedDecl *getUnderlyingDeclImpl(); + protected: NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) : Decl(DK, DC, L), Name(N) { } @@ -182,15 +189,11 @@ public: /// \brief Determine whether this declaration has linkage. bool hasLinkage() const; - /// \brief Whether this declaration was marked as being private to the - /// module in which it was defined. - bool isModulePrivate() const { return ModulePrivate; } + using Decl::isModulePrivate; + using Decl::setModulePrivate; - /// \brief Specify whether this declaration was marked as being private - /// to the module in which it was defined. - void setModulePrivate(bool MP = true) { - ModulePrivate = MP; - } + /// \brief Determine whether this declaration is hidden from name lookup. + bool isHidden() const { return Hidden; } /// \brief Determine whether this declaration is a C++ class member. bool isCXXClassMember() const { @@ -206,8 +209,8 @@ public: return DC->isRecord(); } - /// \brief Given that this declaration is a C++ class member, - /// determine whether it's an instance member of its class. + /// \brief Determine whether the given declaration is an instance member of + /// a C++ class. bool isCXXInstanceMember() const; class LinkageInfo { @@ -249,26 +252,52 @@ public: setLinkage(minLinkage(linkage(), L)); } void mergeLinkage(LinkageInfo Other) { - setLinkage(minLinkage(linkage(), Other.linkage())); + mergeLinkage(Other.linkage()); } - void mergeVisibility(Visibility V) { - setVisibility(minVisibility(visibility(), V)); - } - void mergeVisibility(Visibility V, bool E) { + // Merge the visibility V giving preference to explicit ones. + // This is used, for example, when merging the visibility of a class + // down to one of its members. If the member has no explicit visibility, + // the class visibility wins. + void mergeVisibility(Visibility V, bool E = false) { + // If one has explicit visibility and the other doesn't, keep the + // explicit one. + if (visibilityExplicit() && !E) + return; + if (!visibilityExplicit() && E) + setVisibility(V, E); + + // If both are explicit or both are implicit, keep the minimum. setVisibility(minVisibility(visibility(), V), visibilityExplicit() || E); } + // Merge the visibility V, keeping the most restrictive one. + // This is used for cases like merging the visibility of a template + // argument to an instantiation. If we already have a hidden class, + // no argument should give it default visibility. + void mergeVisibilityWithMin(Visibility V, bool E = false) { + // Never increase the visibility + if (visibility() < V) + return; + + // If this visibility is explicit, keep it. + if (visibilityExplicit() && !E) + return; + setVisibility(V, E); + } void mergeVisibility(LinkageInfo Other) { mergeVisibility(Other.visibility(), Other.visibilityExplicit()); } + void mergeVisibilityWithMin(LinkageInfo Other) { + mergeVisibilityWithMin(Other.visibility(), Other.visibilityExplicit()); + } void merge(LinkageInfo Other) { mergeLinkage(Other); mergeVisibility(Other); } - void merge(std::pair<Linkage,Visibility> LV) { - mergeLinkage(LV.first); - mergeVisibility(LV.second); + void mergeWithMin(LinkageInfo Other) { + mergeLinkage(Other); + mergeVisibilityWithMin(Other); } friend LinkageInfo merge(LinkageInfo L, LinkageInfo R) { @@ -281,7 +310,9 @@ public: Linkage getLinkage() const; /// \brief Determines the visibility of this entity. - Visibility getVisibility() const { return getLinkageAndVisibility().visibility(); } + Visibility getVisibility() const { + return getLinkageAndVisibility().visibility(); + } /// \brief Determines the linkage and visibility of this entity. LinkageInfo getLinkageAndVisibility() const; @@ -291,12 +322,19 @@ public: llvm::Optional<Visibility> getExplicitVisibility() const; /// \brief Clear the linkage cache in response to a change - /// to the declaration. + /// to the declaration. void ClearLinkageCache(); /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. - NamedDecl *getUnderlyingDecl(); + NamedDecl *getUnderlyingDecl() { + // Fast-path the common case. + if (this->getKind() != UsingShadow && + this->getKind() != ObjCCompatibleAlias) + return this; + + return getUnderlyingDeclImpl(); + } const NamedDecl *getUnderlyingDecl() const { return const_cast<NamedDecl*>(this)->getUnderlyingDecl(); } @@ -317,6 +355,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) { /// location of the statement. For GNU local labels (__label__), the decl /// location is where the __label__ is. class LabelDecl : public NamedDecl { + virtual void anchor(); LabelStmt *TheStmt; /// LocStart - For normal labels, this is the same as the main declaration /// label, i.e., the location of the identifier; for GNU local labels, @@ -333,14 +372,15 @@ public: static LabelDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, SourceLocation GnuLabelL); - + static LabelDecl *CreateDeserialized(ASTContext &C, unsigned ID); + LabelStmt *getStmt() const { return TheStmt; } void setStmt(LabelStmt *T) { TheStmt = T; } bool isGnuLocal() const { return LocStart != getLocation(); } void setLocStart(SourceLocation L) { LocStart = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LocStart, getLocation()); } @@ -349,10 +389,12 @@ public: static bool classof(const LabelDecl *D) { return true; } static bool classofKind(Kind K) { return K == Label; } }; - + /// NamespaceDecl - Represent a C++ namespace. -class NamespaceDecl : public NamedDecl, public DeclContext { - bool IsInline : 1; +class NamespaceDecl : public NamedDecl, public DeclContext, + public Redeclarable<NamespaceDecl> +{ + virtual void anchor(); /// LocStart - The starting location of the source range, pointing /// to either the namespace or the inline keyword. @@ -360,41 +402,40 @@ class NamespaceDecl : public NamedDecl, public DeclContext { /// RBraceLoc - The ending location of the source range. SourceLocation RBraceLoc; - // For extended namespace definitions: - // - // namespace A { int x; } - // namespace A { int y; } - // - // there will be one NamespaceDecl for each declaration. - // NextNamespace points to the next extended declaration. - // OrigNamespace points to the original namespace declaration. - // OrigNamespace of the first namespace decl points to its anonymous namespace - LazyDeclPtr NextNamespace; - - /// \brief A pointer to either the original namespace definition for - /// this namespace (if the boolean value is false) or the anonymous - /// namespace that lives just inside this namespace (if the boolean - /// value is true). - /// - /// We can combine these two notions because the anonymous namespace - /// must only be stored in one of the namespace declarations (so all - /// of the namespace declarations can find it). We therefore choose - /// the original namespace declaration, since all of the namespace - /// declarations have a link directly to it; the original namespace - /// declaration itself only needs to know that it is the original - /// namespace declaration (which the boolean indicates). - llvm::PointerIntPair<NamespaceDecl *, 1, bool> OrigOrAnonNamespace; - - NamespaceDecl(DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id) - : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), - IsInline(false), LocStart(StartLoc), RBraceLoc(), - NextNamespace(), OrigOrAnonNamespace(0, true) { } + /// \brief A pointer to either the anonymous namespace that lives just inside + /// this namespace or to the first namespace in the chain (the latter case + /// only when this is not the first in the chain), along with a + /// boolean value indicating whether this is an inline namespace. + llvm::PointerIntPair<NamespaceDecl *, 1, bool> AnonOrFirstNamespaceAndInline; + NamespaceDecl(DeclContext *DC, bool Inline, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + NamespaceDecl *PrevDecl); + + typedef Redeclarable<NamespaceDecl> redeclarable_base; + virtual NamespaceDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } + virtual NamespaceDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual NamespaceDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } + public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id); + bool Inline, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + NamespaceDecl *PrevDecl); + + static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + typedef redeclarable_base::redecl_iterator redecl_iterator; + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; /// \brief Returns true if this is an anonymous namespace declaration. /// @@ -411,67 +452,60 @@ public: /// \brief Returns true if this is an inline namespace declaration. bool isInline() const { - return IsInline; + return AnonOrFirstNamespaceAndInline.getInt(); } /// \brief Set whether this is an inline namespace declaration. void setInline(bool Inline) { - IsInline = Inline; + AnonOrFirstNamespaceAndInline.setInt(Inline); } - /// \brief Return the next extended namespace declaration or null if there - /// is none. - NamespaceDecl *getNextNamespace(); - const NamespaceDecl *getNextNamespace() const { - return const_cast<NamespaceDecl *>(this)->getNextNamespace(); - } + /// \brief Get the original (first) namespace declaration. + NamespaceDecl *getOriginalNamespace() { + if (isFirstDeclaration()) + return this; - /// \brief Set the next extended namespace declaration. - void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; } + return AnonOrFirstNamespaceAndInline.getPointer(); + } /// \brief Get the original (first) namespace declaration. - NamespaceDecl *getOriginalNamespace() const { - if (OrigOrAnonNamespace.getInt()) - return const_cast<NamespaceDecl *>(this); + const NamespaceDecl *getOriginalNamespace() const { + if (isFirstDeclaration()) + return this; - return OrigOrAnonNamespace.getPointer(); + return AnonOrFirstNamespaceAndInline.getPointer(); } /// \brief Return true if this declaration is an original (first) declaration /// of the namespace. This is false for non-original (subsequent) namespace /// declarations and anonymous namespaces. bool isOriginalNamespace() const { - return getOriginalNamespace() == this; - } - - /// \brief Set the original (first) namespace declaration. - void setOriginalNamespace(NamespaceDecl *ND) { - if (ND != this) { - OrigOrAnonNamespace.setPointer(ND); - OrigOrAnonNamespace.setInt(false); - } + return isFirstDeclaration(); } + /// \brief Retrieve the anonymous namespace nested inside this namespace, + /// if any. NamespaceDecl *getAnonymousNamespace() const { - return getOriginalNamespace()->OrigOrAnonNamespace.getPointer(); + return getOriginalNamespace()->AnonOrFirstNamespaceAndInline.getPointer(); } void setAnonymousNamespace(NamespaceDecl *D) { - assert(!D || D->isAnonymousNamespace()); - assert(!D || D->getParent()->getRedeclContext() == this); - getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D); + getOriginalNamespace()->AnonOrFirstNamespaceAndInline.setPointer(D); } - virtual NamespaceDecl *getCanonicalDecl() { return getOriginalNamespace(); } - const NamespaceDecl *getCanonicalDecl() const { - return getOriginalNamespace(); + /// Retrieves the canonical declaration of this namespace. + NamespaceDecl *getCanonicalDecl() { + return getOriginalNamespace(); } - - virtual SourceRange getSourceRange() const { + const NamespaceDecl *getCanonicalDecl() const { + return getOriginalNamespace(); + } + + virtual SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(LocStart, RBraceLoc); } - SourceLocation getLocStart() const { return LocStart; } + SourceLocation getLocStart() const LLVM_READONLY { return LocStart; } SourceLocation getRBraceLoc() const { return RBraceLoc; } void setLocStart(SourceLocation L) { LocStart = L; } void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } @@ -486,7 +520,7 @@ public: static NamespaceDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC)); } - + friend class ASTDeclReader; friend class ASTDeclWriter; }; @@ -495,6 +529,7 @@ public: /// an lvalue) a function (in which case it is a function designator) or /// an enum constant. class ValueDecl : public NamedDecl { + virtual void anchor(); QualType DeclType; protected: @@ -505,6 +540,12 @@ public: QualType getType() const { return DeclType; } void setType(QualType newType) { DeclType = newType; } + /// \brief Determine whether this symbol is weakly-imported, + /// or declared with the weak or weak-ref attr. + bool isWeak() const { + return hasAttr<WeakAttr>() || hasAttr<WeakRefAttr>() || isWeakImported(); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ValueDecl *D) { return true; } @@ -537,7 +578,7 @@ struct QualifierInfo { void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, TemplateParameterList **TPLists); - + private: // Copy constructor and copy assignment are disabled. QualifierInfo(const QualifierInfo&); @@ -592,7 +633,10 @@ public: /// range taking into account any outer template declarations. SourceLocation getOuterLocStart() const; - virtual SourceRange getSourceRange() const; + virtual SourceRange getSourceRange() const LLVM_READONLY; + SourceLocation getLocStart() const LLVM_READONLY { + return getOuterLocStart(); + } /// \brief Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. @@ -600,15 +644,15 @@ public: return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() : 0; } - - /// \brief Retrieve the nested-name-specifier (with source-location - /// information) that qualifies the name of this declaration, if it was + + /// \brief Retrieve the nested-name-specifier (with source-location + /// information) that qualifies the name of this declaration, if it was /// present in the source. NestedNameSpecifierLoc getQualifierLoc() const { return hasExtInfo() ? getExtInfo()->QualifierLoc : NestedNameSpecifierLoc(); } - + void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc); unsigned getNumTemplateParameterLists() const { @@ -655,8 +699,9 @@ struct EvaluatedStmt { /// integral constant expression. bool CheckingICE : 1; - /// \brief Whether this statement is an integral constant - /// expression. Only valid if CheckedICE is true. + /// \brief Whether this statement is an integral constant expression, + /// or in C++11, whether the statement is a constant expression. Only + /// valid if CheckedICE is true. bool IsICE : 1; Stmt *Value; @@ -675,6 +720,13 @@ public: /// It is illegal to call this function with SC == None. static const char *getStorageClassSpecifierString(StorageClass SC); + /// \brief Initialization styles. + enum InitializationStyle { + CInit, ///< C-style initialization with assignment + CallInit, ///< Call-style initialization (C++98) + ListInit ///< Direct list-initialization (C++11) + }; + protected: /// \brief Placeholder type used in Init to denote an unparsed C++ default /// argument. @@ -700,14 +752,15 @@ private: unsigned SClass : 3; unsigned SClassAsWritten : 3; unsigned ThreadSpecified : 1; - unsigned HasCXXDirectInit : 1; + unsigned InitStyle : 2; /// \brief Whether this variable is the exception variable in a C++ catch /// or an Objective-C @catch statement. unsigned ExceptionVar : 1; - + /// \brief Whether this local variable could be allocated in the return - /// slot of its function, enabling the named return value optimization (NRVO). + /// slot of its function, enabling the named return value optimization + /// (NRVO). unsigned NRVOVariable : 1; /// \brief Whether this variable is the for-range-declaration in a C++0x @@ -721,14 +774,14 @@ private: /// \brief Whether this variable is (C++0x) constexpr. unsigned IsConstexpr : 1; }; - enum { NumVarDeclBits = 13 }; + enum { NumVarDeclBits = 14 }; friend class ASTDeclReader; friend class StmtIteratorBase; - + protected: enum { NumParameterIndexBits = 8 }; - + class ParmVarDeclBitfields { friend class ParmVarDecl; friend class ASTDeclReader; @@ -749,7 +802,7 @@ protected: /// Otherwise, the number of function parameter scopes enclosing /// the function parameter scope in which this parameter was /// declared. - unsigned ScopeDepthOrObjCQuals : 8; + unsigned ScopeDepthOrObjCQuals : 7; /// The number of parameters preceding this parameter in the /// function parameter scope in which it was declared. @@ -777,22 +830,28 @@ protected: typedef Redeclarable<VarDecl> redeclarable_base; virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + virtual VarDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual VarDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } public: typedef redeclarable_base::redecl_iterator redecl_iterator; - redecl_iterator redecls_begin() const { - return redeclarable_base::redecls_begin(); - } - redecl_iterator redecls_end() const { - return redeclarable_base::redecls_end(); - } + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten); - virtual SourceRange getSourceRange() const; + static VarDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + virtual SourceRange getSourceRange() const LLVM_READONLY; StorageClass getStorageClass() const { return (StorageClass) VarDeclBits.SClass; @@ -823,12 +882,12 @@ public: return getStorageClass() >= SC_Auto; } - /// isStaticLocal - Returns true if a variable with function scope is a + /// isStaticLocal - Returns true if a variable with function scope is a /// static local variable. bool isStaticLocal() const { return getStorageClass() == SC_Static && !isFileVarDecl(); } - + /// hasExternStorage - Returns true if a variable has extern or /// __private_extern__ storage. bool hasExternalStorage() const { @@ -896,11 +955,17 @@ public: /// \brief Check whether this declaration is a definition. If this could be /// a tentative definition (in C), don't check whether there's an overriding /// definition. - DefinitionKind isThisDeclarationADefinition() const; + DefinitionKind isThisDeclarationADefinition(ASTContext &) const; + DefinitionKind isThisDeclarationADefinition() const { + return isThisDeclarationADefinition(getASTContext()); + } /// \brief Check whether this variable is defined in this /// translation unit. - DefinitionKind hasDefinition() const; + DefinitionKind hasDefinition(ASTContext &) const; + DefinitionKind hasDefinition() const { + return hasDefinition(getASTContext()); + } /// \brief Get the tentative definition that acts as the real definition in /// a TU. Returns null if there is a proper definition available. @@ -914,26 +979,32 @@ public: bool isTentativeDefinitionNow() const; /// \brief Get the real (not just tentative) definition for this declaration. - VarDecl *getDefinition(); + VarDecl *getDefinition(ASTContext &); + const VarDecl *getDefinition(ASTContext &C) const { + return const_cast<VarDecl*>(this)->getDefinition(C); + } + VarDecl *getDefinition() { + return getDefinition(getASTContext()); + } const VarDecl *getDefinition() const { return const_cast<VarDecl*>(this)->getDefinition(); } - /// \brief Determine whether this is or was instantiated from an out-of-line + /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a static data member. virtual bool isOutOfLine() const; /// \brief If this is a static data member, find its out-of-line definition. VarDecl *getOutOfLineDefinition(); - + /// isFileVarDecl - Returns true for file scoped variable declaration. bool isFileVarDecl() const { if (getKind() != Decl::Var) return false; - + if (getDeclContext()->getRedeclContext()->isFileContext()) return true; - + if (isStaticDataMember()) return true; @@ -996,7 +1067,7 @@ public: void setInit(Expr *I); /// \brief Determine whether this variable is a reference that - /// extends the lifetime of its temporary initializer. + /// extends the lifetime of its temporary initializer. /// /// A reference extends the lifetime of its temporary initializer if /// it's initializer is an rvalue that would normally go out of scope @@ -1009,41 +1080,21 @@ public: /// \endcode bool extendsLifetimeOfTemporary() const; - EvaluatedStmt *EnsureEvaluatedStmt() const { - EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); - if (!Eval) { - Stmt *S = Init.get<Stmt *>(); - Eval = new (getASTContext()) EvaluatedStmt; - Eval->Value = S; - Init = Eval; - } - return Eval; - } - - /// \brief Check whether we are in the process of checking whether the - /// initializer can be evaluated. - bool isEvaluatingValue() const { - if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) - return Eval->IsEvaluating; - - return false; - } + /// \brief Determine whether this variable's value can be used in a + /// constant expression, according to the relevant language standard. + /// This only checks properties of the declaration, and does not check + /// whether the initializer is in fact a constant expression. + bool isUsableInConstantExpressions(ASTContext &C) const; - /// \brief Note that we now are checking whether the initializer can be - /// evaluated. - void setEvaluatingValue() const { - EvaluatedStmt *Eval = EnsureEvaluatedStmt(); - Eval->IsEvaluating = true; - } + EvaluatedStmt *ensureEvaluatedStmt() const; - /// \brief Note that constant evaluation has computed the given - /// value for this variable's initializer. - void setEvaluatedValue(const APValue &Value) const { - EvaluatedStmt *Eval = EnsureEvaluatedStmt(); - Eval->IsEvaluating = false; - Eval->WasEvaluated = true; - Eval->Evaluated = Value; - } + /// \brief Attempt to evaluate the value of the initializer attached to this + /// declaration, and produce notes explaining why it cannot be evaluated or is + /// not a constant expression. Returns a pointer to the value if evaluation + /// succeeded, 0 otherwise. + APValue *evaluateValue() const; + APValue *evaluateValue( + llvm::SmallVectorImpl<PartialDiagnosticAt> &Notes) const; /// \brief Return the already-evaluated value of this variable's /// initializer, or NULL if the value is not yet known. Returns pointer @@ -1065,8 +1116,9 @@ public: return false; } - /// \brief Determines whether the initializer is an integral - /// constant expression. + /// \brief Determines whether the initializer is an integral constant + /// expression, or in C++11, whether the initializer is a constant + /// expression. /// /// \pre isInitKnownICE() bool isInitICE() const { @@ -1075,41 +1127,31 @@ public: return Init.get<EvaluatedStmt *>()->IsICE; } - /// \brief Check whether we are in the process of checking the initializer - /// is an integral constant expression. - bool isCheckingICE() const { - if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) - return Eval->CheckingICE; - - return false; - } + /// \brief Determine whether the value of the initializer attached to this + /// declaration is an integral constant expression. + bool checkInitIsICE() const; - /// \brief Note that we now are checking whether the initializer is an - /// integral constant expression. - void setCheckingICE() const { - EvaluatedStmt *Eval = EnsureEvaluatedStmt(); - Eval->CheckingICE = true; + void setInitStyle(InitializationStyle Style) { + VarDeclBits.InitStyle = Style; } - /// \brief Note that we now know whether the initializer is an - /// integral constant expression. - void setInitKnownICE(bool IsICE) const { - EvaluatedStmt *Eval = EnsureEvaluatedStmt(); - Eval->CheckingICE = false; - Eval->CheckedICE = true; - Eval->IsICE = IsICE; + /// \brief The style of initialization for this declaration. + /// + /// C-style initialization is "int x = 1;". Call-style initialization is + /// a C++98 direct-initializer, e.g. "int x(1);". The Init expression will be + /// the expression inside the parens or a "ClassType(a,b,c)" class constructor + /// expression for class types. List-style initialization is C++11 syntax, + /// e.g. "int x{1};". Clients can distinguish between different forms of + /// initialization by checking this value. In particular, "int x = {1};" is + /// C-style, "int x({1})" is call-style, and "int x{1};" is list-style; the + /// Init expression in all three cases is an InitListExpr. + InitializationStyle getInitStyle() const { + return static_cast<InitializationStyle>(VarDeclBits.InitStyle); } - void setCXXDirectInitializer(bool T) { VarDeclBits.HasCXXDirectInit = T; } - - /// hasCXXDirectInitializer - If true, the initializer was a direct - /// initializer, e.g: "int x(1);". The Init expression will be the expression - /// inside the parens or a "ClassType(a,b,c)" class constructor expression for - /// class types. Clients can distinguish between "int x(1);" and "int x=1;" - /// by checking hasCXXDirectInitializer. - /// - bool hasCXXDirectInitializer() const { - return VarDeclBits.HasCXXDirectInit; + /// \brief Whether the initializer is a direct-initializer (list or call). + bool isDirectInit() const { + return getInitStyle() != CInit; } /// \brief Determine whether this variable is the exception variable in a @@ -1118,7 +1160,7 @@ public: return VarDeclBits.ExceptionVar; } void setExceptionVariable(bool EV) { VarDeclBits.ExceptionVar = EV; } - + /// \brief Determine whether this local variable can be used with the named /// return value optimization (NRVO). /// @@ -1143,7 +1185,7 @@ public: /// Generally such variables are also 'const' for safety. bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; } void setARCPseudoStrong(bool ps) { VarDeclBits.ARCPseudoStrong = ps; } - + /// Whether this variable is (C++0x) constexpr. bool isConstexpr() const { return VarDeclBits.IsConstexpr; } void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; } @@ -1153,15 +1195,15 @@ public: /// from which it was instantiated. VarDecl *getInstantiatedFromStaticDataMember() const; - /// \brief If this variable is a static data member, determine what kind of + /// \brief If this variable is a static data member, determine what kind of /// template specialization or instantiation this is. TemplateSpecializationKind getTemplateSpecializationKind() const; - + /// \brief If this variable is an instantiation of a static data member of a /// class template specialization, retrieves the member specialization /// information. MemberSpecializationInfo *getMemberSpecializationInfo() const; - + /// \brief For a static data member that was instantiated from a static /// data member of a class template, set the template specialiation kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK, @@ -1174,11 +1216,14 @@ public: }; class ImplicitParamDecl : public VarDecl { + virtual void anchor(); public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T); + static ImplicitParamDecl *CreateDeserialized(ASTContext &C, unsigned ID); + ImplicitParamDecl(DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType Type) : VarDecl(ImplicitParam, DC, IdLoc, IdLoc, Id, Type, @@ -1218,8 +1263,10 @@ public: StorageClass S, StorageClass SCAsWritten, Expr *DefArg); - virtual SourceRange getSourceRange() const; + static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID); + virtual SourceRange getSourceRange() const LLVM_READONLY; + void setObjCMethodScopeInfo(unsigned parameterIndex) { ParmVarDeclBits.IsObjCMethodParam = true; setParameterIndex(parameterIndex); @@ -1229,7 +1276,8 @@ public: assert(!ParmVarDeclBits.IsObjCMethodParam); ParmVarDeclBits.ScopeDepthOrObjCQuals = scopeDepth; - assert(ParmVarDeclBits.ScopeDepthOrObjCQuals == scopeDepth && "truncation!"); + assert(ParmVarDeclBits.ScopeDepthOrObjCQuals == scopeDepth + && "truncation!"); setParameterIndex(parameterIndex); } @@ -1276,20 +1324,14 @@ public: const Expr *getDefaultArg() const { return const_cast<ParmVarDecl *>(this)->getDefaultArg(); } - + void setDefaultArg(Expr *defarg) { Init = reinterpret_cast<Stmt *>(defarg); } - unsigned getNumDefaultArgTemporaries() const; - CXXTemporary *getDefaultArgTemporary(unsigned i); - const CXXTemporary *getDefaultArgTemporary(unsigned i) const { - return const_cast<ParmVarDecl *>(this)->getDefaultArgTemporary(i); - } - /// \brief Retrieve the source range that covers the entire default /// argument. - SourceRange getDefaultArgRange() const; + SourceRange getDefaultArgRange() const; void setUninstantiatedDefaultArg(Expr *arg) { Init = reinterpret_cast<UninstantiatedDefaultArgument *>(arg); } @@ -1351,7 +1393,7 @@ public: /// \brief Determine whether this parameter is actually a function /// parameter pack. bool isParameterPack() const; - + /// setOwningFunction - Sets the function declaration that owns this /// ParmVarDecl. Since ParmVarDecls are often created before the /// FunctionDecls that own them, this routine is required to update @@ -1362,7 +1404,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ParmVarDecl *D) { return true; } static bool classofKind(Kind K) { return K == ParmVar; } - + private: enum { ParameterIndexSentinel = (1 << NumParameterIndexBits) - 1 }; @@ -1371,7 +1413,7 @@ private: setParameterIndexLarge(parameterIndex); return; } - + ParmVarDeclBits.ParameterIndex = parameterIndex; assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!"); } @@ -1379,7 +1421,7 @@ private: unsigned d = ParmVarDeclBits.ParameterIndex; return d == ParameterIndexSentinel ? getParameterIndexLarge() : d; } - + void setParameterIndexLarge(unsigned parameterIndex); unsigned getParameterIndexLarge() const; }; @@ -1394,7 +1436,7 @@ private: /// FunctionDecl (e.g., the translation unit); this FunctionDecl /// contains all of the information known about the function. Other, /// previous declarations of the function are available via the -/// getPreviousDeclaration() chain. +/// getPreviousDecl() chain. class FunctionDecl : public DeclaratorDecl, public DeclContext, public Redeclarable<FunctionDecl> { public: @@ -1415,6 +1457,11 @@ private: /// no formals. ParmVarDecl **ParamInfo; + /// DeclsInPrototypeScope - Array of pointers to NamedDecls for + /// decls defined in the function prototype that are not parameters. E.g. + /// 'enum Y' in 'void f(enum Y {AA} x) {}'. + llvm::ArrayRef<NamedDecl*> DeclsInPrototypeScope; + LazyDeclStmtPtr Body; // FIXME: This can be packed into the bitfields in Decl. @@ -1456,7 +1503,7 @@ private: /// FunctionTemplateSpecializationInfo, which contains information about /// the template being specialized and the template arguments involved in /// that specialization. - llvm::PointerUnion4<FunctionTemplateDecl *, + llvm::PointerUnion4<FunctionTemplateDecl *, MemberSpecializationInfo *, FunctionTemplateSpecializationInfo *, DependentFunctionTemplateSpecializationInfo *> @@ -1486,7 +1533,7 @@ private: /// \param TemplateArgsAsWritten location info of template arguments. /// /// \param PointOfInstantiation point at which the function template - /// specialization was first instantiated. + /// specialization was first instantiated. void setFunctionTemplateSpecialization(ASTContext &C, FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, @@ -1524,15 +1571,19 @@ protected: typedef Redeclarable<FunctionDecl> redeclarable_base; virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + virtual FunctionDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual FunctionDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } public: typedef redeclarable_base::redecl_iterator redecl_iterator; - redecl_iterator redecls_begin() const { - return redeclarable_base::redecls_begin(); - } - redecl_iterator redecls_end() const { - return redeclarable_base::redecls_end(); - } + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, @@ -1560,6 +1611,8 @@ public: bool hasWrittenPrototype = true, bool isConstexprSpecified = false); + static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID); + DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } @@ -1570,7 +1623,7 @@ public: void setRangeEnd(SourceLocation E) { EndRangeLoc = E; } - virtual SourceRange getSourceRange() const; + virtual SourceRange getSourceRange() const LLVM_READONLY; /// \brief Returns true if the function has a body (definition). The /// function body might be in any of the (re-)declarations of this @@ -1656,7 +1709,7 @@ public: void setTrivial(bool IT) { IsTrivial = IT; } /// Whether this function is defaulted per C++0x. Only valid for - /// special member functions. + /// special member functions. bool isDefaulted() const { return IsDefaulted; } void setDefaulted(bool D = true) { IsDefaulted = D; } @@ -1774,6 +1827,11 @@ public: setParams(getASTContext(), NewParamInfo); } + const llvm::ArrayRef<NamedDecl*> &getDeclsInPrototypeScope() const { + return DeclsInPrototypeScope; + } + void setDeclsInPrototypeScope(llvm::ArrayRef<NamedDecl *> NewDecls); + /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of /// function parameters, if some of the parameters have default @@ -1783,12 +1841,12 @@ public: QualType getResultType() const { return getType()->getAs<FunctionType>()->getResultType(); } - + /// \brief Determine the type of an expression that calls this function. QualType getCallResultType() const { return getType()->getAs<FunctionType>()->getCallResultType(getASTContext()); } - + StorageClass getStorageClass() const { return StorageClass(SClass); } void setStorageClass(StorageClass SC); @@ -1799,10 +1857,10 @@ public: /// \brief Determine whether the "inline" keyword was specified for this /// function. bool isInlineSpecified() const { return IsInlineSpecified; } - + /// Set whether the "inline" keyword was specified for this function. - void setInlineSpecified(bool I) { - IsInlineSpecified = I; + void setInlineSpecified(bool I) { + IsInlineSpecified = I; IsInline = I; } @@ -1819,7 +1877,7 @@ public: bool isInlineDefinitionExternallyVisible() const; bool doesDeclarationForceExternallyVisibleDefinition() const; - + /// isOverloadedOperator - Whether this function declaration /// represents an C++ overloaded operator, e.g., "operator+". bool isOverloadedOperator() const { @@ -1852,7 +1910,7 @@ public: /// X<int>::A is required, it will be instantiated from the /// declaration returned by getInstantiatedFromMemberFunction(). FunctionDecl *getInstantiatedFromMemberFunction() const; - + /// \brief What kind of templated function this is. TemplatedKind getTemplatedKind() const; @@ -1860,7 +1918,7 @@ public: /// class template specialization, retrieves the member specialization /// information. MemberSpecializationInfo *getMemberSpecializationInfo() const; - + /// \brief Specify that this record is an instantiation of the /// member function FD. void setInstantiationOfMemberFunction(FunctionDecl *FD, @@ -1888,7 +1946,7 @@ public: TemplateOrSpecialization = Template; } - /// \brief Determine whether this function is a function template + /// \brief Determine whether this function is a function template /// specialization. bool isFunctionTemplateSpecialization() const { return getPrimaryTemplate() != 0; @@ -1899,7 +1957,7 @@ public: FunctionDecl *getClassScopeSpecializationPattern() const; /// \brief If this function is actually a function template specialization, - /// retrieve information about this function template specialization. + /// retrieve information about this function template specialization. /// Otherwise, returns NULL. FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const { return TemplateOrSpecialization. @@ -1910,7 +1968,11 @@ public: /// specialization or a member of a class template specialization that can /// be implicitly instantiated. bool isImplicitlyInstantiable() const; - + + /// \brief Determines if the given function was instantiated from a + /// function template. + bool isTemplateInstantiation() const; + /// \brief Retrieve the function declaration from which this function could /// be instantiated, if it is an instantiation (rather than a non-template /// or a specialization, for example). @@ -1958,7 +2020,7 @@ public: /// \param TemplateArgsAsWritten location info of template arguments. /// /// \param PointOfInstantiation point at which the function template - /// specialization was first instantiated. + /// specialization was first instantiated. void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, void *InsertPos, @@ -1994,15 +2056,21 @@ public: /// \brief Retrieve the (first) point of instantiation of a function template /// specialization or a member of a class template specialization. /// - /// \returns the first point of instantiation, if this function was - /// instantiated from a template; otherwise, returns an invalid source + /// \returns the first point of instantiation, if this function was + /// instantiated from a template; otherwise, returns an invalid source /// location. SourceLocation getPointOfInstantiation() const; - - /// \brief Determine whether this is or was instantiated from an out-of-line + + /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a member function. virtual bool isOutOfLine() const; - + + /// \brief Identify a memory copying or setting function. + /// If the given function is a memory copy or setting function, returns + /// the corresponding Builtin ID. If the function is not a memory function, + /// returns 0. + unsigned getMemoryFunctionKind() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FunctionDecl *D) { return true; } @@ -2056,6 +2124,8 @@ public: TypeSourceInfo *TInfo, Expr *BW, bool Mutable, bool HasInit); + static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); + /// getFieldIndex - Returns the index of this field within its record, /// as appropriate for passing to ASTRecordLayout::getFieldOffset. unsigned getFieldIndex() const; @@ -2108,7 +2178,8 @@ public: Expr *getInClassInitializer() const { return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() : 0; } - /// setInClassInitializer - Set the C++0x in-class initializer for this member. + /// setInClassInitializer - Set the C++0x in-class initializer for this + /// member. void setInClassInitializer(Expr *Init); /// removeInClassInitializer - Remove the C++0x in-class initializer from this /// member. @@ -2128,7 +2199,7 @@ public: return cast<RecordDecl>(getDeclContext()); } - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2155,7 +2226,8 @@ public: SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, const llvm::APSInt &V); - + static EnumConstantDecl *CreateDeserialized(ASTContext &C, unsigned ID); + const Expr *getInitExpr() const { return (const Expr*) Init; } Expr *getInitExpr() { return (Expr*) Init; } const llvm::APSInt &getInitVal() const { return Val; } @@ -2163,8 +2235,8 @@ public: void setInitExpr(Expr *E) { Init = (Stmt*) E; } void setInitVal(const llvm::APSInt &V) { Val = V; } - SourceRange getSourceRange() const; - + SourceRange getSourceRange() const LLVM_READONLY; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const EnumConstantDecl *D) { return true; } @@ -2177,6 +2249,7 @@ public: /// field injected from an anonymous union/struct into the parent scope. /// IndirectFieldDecl are always implicit. class IndirectFieldDecl : public ValueDecl { + virtual void anchor(); NamedDecl **Chaining; unsigned ChainingSize; @@ -2189,6 +2262,8 @@ public: static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, NamedDecl **CH, unsigned CHS); + + static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); typedef NamedDecl * const *chain_iterator; chain_iterator chain_begin() const { return Chaining; } @@ -2216,6 +2291,7 @@ public: /// TypeDecl - Represents a declaration of a type. /// class TypeDecl : public NamedDecl { + virtual void anchor(); /// TypeForDecl - This indicates the Type object that represents /// this TypeDecl. It is a cache maintained by /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and @@ -2228,6 +2304,7 @@ class TypeDecl : public NamedDecl { friend class TagDecl; friend class TemplateTypeParmDecl; friend class TagType; + friend class ASTReader; protected: TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -2239,9 +2316,9 @@ public: const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) { TypeForDecl = TD; } - SourceLocation getLocStart() const { return LocStart; } + SourceLocation getLocStart() const LLVM_READONLY { return LocStart; } void setLocStart(SourceLocation L) { LocStart = L; } - virtual SourceRange getSourceRange() const { + virtual SourceRange getSourceRange() const LLVM_READONLY { if (LocStart.isValid()) return SourceRange(LocStart, getLocation()); else @@ -2257,6 +2334,7 @@ public: /// Base class for declarations which introduce a typedef-name. class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> { + virtual void anchor(); /// UnderlyingType - This is the type the typedef is set to. TypeSourceInfo *TInfo; @@ -2270,15 +2348,19 @@ protected: virtual TypedefNameDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + virtual TypedefNameDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual TypedefNameDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } public: typedef redeclarable_base::redecl_iterator redecl_iterator; - redecl_iterator redecls_begin() const { - return redeclarable_base::redecls_begin(); - } - redecl_iterator redecls_end() const { - return redeclarable_base::redecls_end(); - } + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; TypeSourceInfo *getTypeSourceInfo() const { return TInfo; @@ -2318,8 +2400,9 @@ public: static TypedefDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo); - - SourceRange getSourceRange() const; + static TypedefDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceRange getSourceRange() const LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2338,8 +2421,9 @@ public: static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo); + static TypeAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); - SourceRange getSourceRange() const; + SourceRange getSourceRange() const LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2364,15 +2448,17 @@ private: /// a definition until the definition has been fully processed. bool IsCompleteDefinition : 1; +protected: /// IsBeingDefined - True if this is currently being defined. bool IsBeingDefined : 1; +private: /// IsEmbeddedInDeclarator - True if this tag declaration is /// "embedded" (i.e., defined or declared for the very first time) /// in the syntax of a declarator. bool IsEmbeddedInDeclarator : 1; - /// /brief True if this tag is free standing, e.g. "struct foo;". + /// \brief True if this tag is free standing, e.g. "struct foo;". bool IsFreeStanding : 1; protected: @@ -2381,7 +2467,7 @@ protected: unsigned NumNegativeBits : 8; /// IsScoped - True if this tag declaration is a scoped enumeration. Only - /// possible in C++0x mode. + /// possible in C++11 mode. bool IsScoped : 1; /// IsScopedUsingClassTag - If this tag declaration is a scoped enum, /// then this is true if the scoped enum was declared using the class @@ -2390,7 +2476,7 @@ protected: bool IsScopedUsingClassTag : 1; /// IsFixed - True if this is an enumeration with fixed underlying type. Only - /// possible in C++0x mode. + /// possible in C++11 or Microsoft extensions mode. bool IsFixed : 1; private: @@ -2431,20 +2517,24 @@ protected: typedef Redeclarable<TagDecl> redeclarable_base; virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + virtual TagDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual TagDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } /// @brief Completes the definition of this tag declaration. /// /// This is a helper function for derived classes. - void completeDefinition(); - + void completeDefinition(); + public: typedef redeclarable_base::redecl_iterator redecl_iterator; - redecl_iterator redecls_begin() const { - return redeclarable_base::redecls_begin(); - } - redecl_iterator redecls_end() const { - return redeclarable_base::redecls_end(); - } + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; SourceLocation getRBraceLoc() const { return RBraceLoc; } void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } @@ -2456,7 +2546,7 @@ public: /// getOuterLocStart - Return SourceLocation representing start of source /// range taking into account any outer template declarations. SourceLocation getOuterLocStart() const; - virtual SourceRange getSourceRange() const; + virtual SourceRange getSourceRange() const LLVM_READONLY; virtual TagDecl* getCanonicalDecl(); const TagDecl* getCanonicalDecl() const { @@ -2532,7 +2622,8 @@ public: bool isEnum() const { return getTagKind() == TTK_Enum; } TypedefNameDecl *getTypedefNameForAnonDecl() const { - return hasExtInfo() ? 0 : TypedefNameDeclOrQualifier.get<TypedefNameDecl*>(); + return hasExtInfo() ? 0 : + TypedefNameDeclOrQualifier.get<TypedefNameDecl*>(); } void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); @@ -2543,15 +2634,15 @@ public: return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() : 0; } - - /// \brief Retrieve the nested-name-specifier (with source-location - /// information) that qualifies the name of this declaration, if it was + + /// \brief Retrieve the nested-name-specifier (with source-location + /// information) that qualifies the name of this declaration, if it was /// present in the source. NestedNameSpecifierLoc getQualifierLoc() const { return hasExtInfo() ? getExtInfo()->QualifierLoc : NestedNameSpecifierLoc(); } - + void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc); unsigned getNumTemplateParameterLists() const { @@ -2580,9 +2671,11 @@ public: friend class ASTDeclWriter; }; -/// EnumDecl - Represents an enum. As an extension, we allow forward-declared -/// enums. +/// EnumDecl - Represents an enum. In C++11, enums can be forward-declared +/// with a fixed underlying type, and in C we allow them to be forward-declared +/// with no underlying type as an extension. class EnumDecl : public TagDecl { + virtual void anchor(); /// IntegerType - This represent the integer type that the enum corresponds /// to for code generation purposes. Note that the enumerator constants may /// have a different type than this does. @@ -2606,23 +2699,16 @@ class EnumDecl : public TagDecl { /// in C++) are of the enum type instead. QualType PromotionType; - /// \brief If the enumeration was instantiated from an enumeration - /// within a class or function template, this pointer refers to the - /// enumeration declared within the template. - EnumDecl *InstantiatedFrom; - - // The number of positive and negative bits required by the - // enumerators are stored in the SubclassBits field. - enum { - NumBitsWidth = 8, - NumBitsMask = (1 << NumBitsWidth) - 1 - }; + /// \brief If this enumeration is an instantiation of a member enumeration + /// of a class template specialization, this is the member specialization + /// information. + MemberSpecializationInfo *SpecializationInfo; EnumDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl, bool Scoped, bool ScopedUsingClassTag, bool Fixed) : TagDecl(Enum, TTK_Enum, DC, IdLoc, Id, PrevDecl, StartLoc), - InstantiatedFrom(0) { + SpecializationInfo(0) { assert(Scoped || !ScopedUsingClassTag); IntegerType = (const Type*)0; NumNegativeBits = 0; @@ -2631,6 +2717,9 @@ class EnumDecl : public TagDecl { IsScopedUsingClassTag = ScopedUsingClassTag; IsFixed = Fixed; } + + void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, + TemplateSpecializationKind TSK); public: EnumDecl *getCanonicalDecl() { return cast<EnumDecl>(TagDecl::getCanonicalDecl()); @@ -2639,11 +2728,22 @@ public: return cast<EnumDecl>(TagDecl::getCanonicalDecl()); } - const EnumDecl *getPreviousDeclaration() const { - return cast_or_null<EnumDecl>(TagDecl::getPreviousDeclaration()); + const EnumDecl *getPreviousDecl() const { + return cast_or_null<EnumDecl>(TagDecl::getPreviousDecl()); } - EnumDecl *getPreviousDeclaration() { - return cast_or_null<EnumDecl>(TagDecl::getPreviousDeclaration()); + EnumDecl *getPreviousDecl() { + return cast_or_null<EnumDecl>(TagDecl::getPreviousDecl()); + } + + const EnumDecl *getMostRecentDecl() const { + return cast<EnumDecl>(TagDecl::getMostRecentDecl()); + } + EnumDecl *getMostRecentDecl() { + return cast<EnumDecl>(TagDecl::getMostRecentDecl()); + } + + EnumDecl *getDefinition() const { + return cast_or_null<EnumDecl>(TagDecl::getDefinition()); } static EnumDecl *Create(ASTContext &C, DeclContext *DC, @@ -2651,7 +2751,7 @@ public: IdentifierInfo *Id, EnumDecl *PrevDecl, bool IsScoped, bool IsScopedUsingClassTag, bool IsFixed); - static EnumDecl *Create(ASTContext &C, EmptyShell Empty); + static EnumDecl *CreateDeserialized(ASTContext &C, unsigned ID); /// completeDefinition - When created, the EnumDecl corresponds to a /// forward-declared enum. This method is used to mark the @@ -2668,14 +2768,14 @@ public: typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator; enumerator_iterator enumerator_begin() const { - const EnumDecl *E = cast_or_null<EnumDecl>(getDefinition()); + const EnumDecl *E = getDefinition(); if (!E) E = this; return enumerator_iterator(E->decls_begin()); } enumerator_iterator enumerator_end() const { - const EnumDecl *E = cast_or_null<EnumDecl>(getDefinition()); + const EnumDecl *E = getDefinition(); if (!E) E = this; return enumerator_iterator(E->decls_end()); @@ -2723,7 +2823,7 @@ public: /// \brief Returns the width in bits required to store all the /// negative enumerators of this enum. These widths include /// the rightmost leading 1; that is: - /// + /// /// MOST NEGATIVE ENUMERATOR PATTERN NUM NEGATIVE BITS /// ------------------------ ------- ----------------- /// -1 1111111 1 @@ -2760,11 +2860,31 @@ public: /// \brief Returns the enumeration (declared within the template) /// from which this enumeration type was instantiated, or NULL if /// this enumeration was not instantiated from any template. - EnumDecl *getInstantiatedFromMemberEnum() const { - return InstantiatedFrom; + EnumDecl *getInstantiatedFromMemberEnum() const; + + /// \brief If this enumeration is a member of a specialization of a + /// templated class, determine what kind of template specialization + /// or instantiation this is. + TemplateSpecializationKind getTemplateSpecializationKind() const; + + /// \brief For an enumeration member that was instantiated from a member + /// enumeration of a templated class, set the template specialiation kind. + void setTemplateSpecializationKind(TemplateSpecializationKind TSK, + SourceLocation PointOfInstantiation = SourceLocation()); + + /// \brief If this enumeration is an instantiation of a member enumeration of + /// a class template specialization, retrieves the member specialization + /// information. + MemberSpecializationInfo *getMemberSpecializationInfo() const { + return SpecializationInfo; } - void setInstantiationOfMemberEnum(EnumDecl *IF) { InstantiatedFrom = IF; } + /// \brief Specify that this enumeration is an instantiation of the + /// member enumeration ED. + void setInstantiationOfMemberEnum(EnumDecl *ED, + TemplateSpecializationKind TSK) { + setInstantiationOfMemberEnum(getASTContext(), ED, TSK); + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const EnumDecl *D) { return true; } @@ -2791,7 +2911,7 @@ class RecordDecl : public TagDecl { bool AnonymousStructOrUnion : 1; /// HasObjectMember - This is true if this struct has at least one member - /// containing an object. + /// containing an Objective-C object pointer type. bool HasObjectMember : 1; /// \brief Whether the field declarations of this record have been loaded @@ -2810,13 +2930,20 @@ public: static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl* PrevDecl = 0); - static RecordDecl *Create(const ASTContext &C, EmptyShell Empty); + static RecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); - const RecordDecl *getPreviousDeclaration() const { - return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration()); + const RecordDecl *getPreviousDecl() const { + return cast_or_null<RecordDecl>(TagDecl::getPreviousDecl()); } - RecordDecl *getPreviousDeclaration() { - return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration()); + RecordDecl *getPreviousDecl() { + return cast_or_null<RecordDecl>(TagDecl::getPreviousDecl()); + } + + const RecordDecl *getMostRecentDecl() const { + return cast<RecordDecl>(TagDecl::getMostRecentDecl()); + } + RecordDecl *getMostRecentDecl() { + return cast<RecordDecl>(TagDecl::getMostRecentDecl()); } bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } @@ -2902,6 +3029,7 @@ private: }; class FileScopeAsmDecl : public Decl { + virtual void anchor(); StringLiteral *AsmString; SourceLocation RParenLoc; FileScopeAsmDecl(DeclContext *DC, StringLiteral *asmstring, @@ -2912,10 +3040,12 @@ public: StringLiteral *Str, SourceLocation AsmLoc, SourceLocation RParenLoc); + static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, unsigned ID); + SourceLocation getAsmLoc() const { return getLocation(); } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceRange getSourceRange() const { + SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getAsmLoc(), getRParenLoc()); } @@ -2976,6 +3106,8 @@ private: // FIXME: This can be packed into the bitfields in Decl. bool IsVariadic : 1; bool CapturesCXXThis : 1; + bool BlockMissingReturnType : 1; + bool IsConversionFromLambda : 1; /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal /// parameters of this function. This is null if a prototype or if there are /// no formals. @@ -2992,12 +3124,14 @@ protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) : Decl(Block, DC, CaretLoc), DeclContext(Block), IsVariadic(false), CapturesCXXThis(false), + BlockMissingReturnType(true), IsConversionFromLambda(false), ParamInfo(0), NumParams(0), Body(0), SignatureAsWritten(0), Captures(0), NumCaptures(0) {} public: - static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); - + static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); + static BlockDecl *CreateDeserialized(ASTContext &C, unsigned ID); + SourceLocation getCaretLocation() const { return getLocation(); } bool isVariadic() const { return IsVariadic; } @@ -3049,6 +3183,11 @@ public: capture_const_iterator capture_end() const { return Captures + NumCaptures; } bool capturesCXXThis() const { return CapturesCXXThis; } + bool blockMissingReturnType() const { return BlockMissingReturnType; } + void setBlockMissingReturnType(bool val) { BlockMissingReturnType = val; } + + bool isConversionFromLambda() const { return IsConversionFromLambda; } + void setIsConversionFromLambda(bool val) { IsConversionFromLambda = val; } bool capturesVariable(const VarDecl *var) const; @@ -3057,8 +3196,8 @@ public: const Capture *end, bool capturesCXXThis); - virtual SourceRange getSourceRange() const; - + virtual SourceRange getSourceRange() const LLVM_READONLY; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const BlockDecl *D) { return true; } @@ -3071,6 +3210,75 @@ public: } }; +/// \brief Describes a module import declaration, which makes the contents +/// of the named module visible in the current translation unit. +/// +/// An import declaration imports the named module (or submodule). For example: +/// \code +/// @__experimental_modules_import std.vector; +/// \endcode +/// +/// Import declarations can also be implicitly generated from #include/#import +/// directives. +class ImportDecl : public Decl { + /// \brief The imported module, along with a bit that indicates whether + /// we have source-location information for each identifier in the module + /// name. + /// + /// When the bit is false, we only have a single source location for the + /// end of the import declaration. + llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete; + + /// \brief The next import in the list of imports local to the translation + /// unit being parsed (not loaded from an AST file). + ImportDecl *NextLocalImport; + + friend class ASTReader; + friend class ASTDeclReader; + friend class ASTContext; + + ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, + ArrayRef<SourceLocation> IdentifierLocs); + + ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported, + SourceLocation EndLoc); + + ImportDecl(EmptyShell Empty) : Decl(Import, Empty), NextLocalImport() { } + +public: + /// \brief Create a new module import declaration. + static ImportDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, Module *Imported, + ArrayRef<SourceLocation> IdentifierLocs); + + /// \brief Create a new module import declaration for an implicitly-generated + /// import. + static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, Module *Imported, + SourceLocation EndLoc); + + /// \brief Create a new, deserialized module import declaration. + static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumLocations); + + /// \brief Retrieve the module that was imported by the import declaration. + Module *getImportedModule() const { return ImportedAndComplete.getPointer(); } + + /// \brief Retrieves the locations of each of the identifiers that make up + /// the complete module name in the import declaration. + /// + /// This will return an empty array if the locations of the individual + /// identifiers aren't available. + ArrayRef<SourceLocation> getIdentifierLocs() const; + + virtual SourceRange getSourceRange() const LLVM_READONLY; + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const ImportDecl *D) { return true; } + static bool classofKind(Kind K) { return K == Import; } +}; + + /// Insertion operator for diagnostics. This allows sending NamedDecl's /// into a diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, @@ -3079,6 +3287,12 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, DiagnosticsEngine::ak_nameddecl); return DB; } +inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + const NamedDecl* ND) { + PD.AddTaggedVal(reinterpret_cast<intptr_t>(ND), + DiagnosticsEngine::ak_nameddecl); + return PD; +} template<typename decl_type> void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) { @@ -3086,26 +3300,44 @@ void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) { // and Redeclarable to be defined. decl_type *First; - + if (PrevDecl) { // Point to previous. Make sure that this is actually the most recent // redeclaration, or we can build invalid chains. If the most recent // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. - RedeclLink = PreviousDeclLink(llvm::cast<decl_type>( - PrevDecl->getMostRecentDeclaration())); + RedeclLink = PreviousDeclLink( + llvm::cast<decl_type>(PrevDecl->getMostRecentDecl())); First = PrevDecl->getFirstDeclaration(); assert(First->RedeclLink.NextIsLatest() && "Expected first"); } else { // Make this first. First = static_cast<decl_type*>(this); } - + // First one will point to this one as latest. First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this))) ND->ClearLinkageCache(); } +// Inline function definitions. + +/// \brief Check if the given decl is complete. +/// +/// We use this function to break a cycle between the inline definitions in +/// Type.h and Decl.h. +inline bool IsEnumDeclComplete(EnumDecl *ED) { + return ED->isComplete(); +} + +/// \brief Check if the given decl is scoped. +/// +/// We use this function to break a cycle between the inline definitions in +/// Type.h and Decl.h. +inline bool IsEnumDeclScoped(EnumDecl *ED) { + return ED->isScoped(); +} + } // end namespace clang #endif |