diff options
Diffstat (limited to 'include/clang/AST/DeclBase.h')
-rw-r--r-- | include/clang/AST/DeclBase.h | 354 |
1 files changed, 262 insertions, 92 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 9f29411..4c675aed 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -17,8 +17,9 @@ #include "clang/AST/Attr.h" #include "clang/AST/Type.h" #include "clang/Basic/Specifiers.h" -#include "llvm/Support/PrettyStackTrace.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/PrettyStackTrace.h" namespace clang { class DeclContext; @@ -98,7 +99,7 @@ public: /// identifiers. C++ describes lookup completely differently: /// certain lookups merely "ignore" certain kinds of declarations, /// usually based on whether the declaration is of a type, etc. - /// + /// /// These are meant as bitmasks, so that searches in /// C++ can look into the "tag" namespace during ordinary lookup. /// @@ -180,12 +181,28 @@ public: OBJC_TQ_Oneway = 0x20 }; -private: - /// NextDeclInContext - The next declaration within the same lexical +protected: + // Enumeration values used in the bits stored in NextInContextAndBits. + enum { + /// \brief Whether this declaration is a top-level declaration (function, + /// global variable, etc.) that is lexically inside an objc container + /// definition. + TopLevelDeclInObjCContainerFlag = 0x01, + + /// \brief Whether this declaration is private to the module in which it was + /// defined. + ModulePrivateFlag = 0x02 + }; + + /// \brief The next declaration within the same lexical /// DeclContext. These pointers form the linked list that is /// traversed via DeclContext's decls_begin()/decls_end(). - Decl *NextDeclInContext; + /// + /// The extra two bits are used for the TopLevelDeclInObjCContainer and + /// ModulePrivate bits. + llvm::PointerIntPair<Decl *, 2, unsigned> NextInContextAndBits; +private: friend class DeclContext; struct MultipleDC { @@ -243,7 +260,10 @@ private: /// evaluated context or not, e.g. functions used in uninstantiated templates /// are regarded as "referenced" but not "used". unsigned Referenced : 1; - + + /// \brief Whether statistic collection is enabled. + static bool StatisticsEnabled; + protected: /// Access - Used by C++ decls for the access specifier. // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum @@ -252,14 +272,12 @@ protected: /// \brief Whether this declaration was loaded from an AST file. unsigned FromASTFile : 1; - - /// ChangedAfterLoad - if this declaration has changed since being loaded - unsigned ChangedAfterLoad : 1; - - /// \brief Whether this declaration is private to the module in which it was - /// defined. - unsigned ModulePrivate : 1; + /// \brief Whether this declaration is hidden from normal name lookup, e.g., + /// because it is was loaded from an AST file is either module-private or + /// because its submodule has not been made visible. + unsigned Hidden : 1; + /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. unsigned IdentifierNamespace : 12; @@ -267,14 +285,15 @@ protected: /// /// This field is only valid for NamedDecls subclasses. mutable unsigned HasCachedLinkage : 1; - + /// \brief If \c HasCachedLinkage, the linkage of this declaration. /// /// This field is only valid for NamedDecls subclasses. mutable unsigned CachedLinkage : 2; - + friend class ASTDeclWriter; friend class ASTDeclReader; + friend class ASTReader; private: void CheckAccessDeclContext() const; @@ -282,38 +301,52 @@ private: protected: Decl(Kind DK, DeclContext *DC, SourceLocation L) - : NextDeclInContext(0), DeclCtx(DC), + : NextInContextAndBits(), DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), Referenced(false), - Access(AS_none), FromASTFile(0), ChangedAfterLoad(false), - ModulePrivate(0), + Access(AS_none), FromASTFile(0), Hidden(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - HasCachedLinkage(0) + HasCachedLinkage(0) { - if (Decl::CollectingStats()) add(DK); + if (StatisticsEnabled) add(DK); } Decl(Kind DK, EmptyShell Empty) - : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0), + : NextInContextAndBits(), DeclKind(DK), InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), Referenced(false), - Access(AS_none), FromASTFile(0), ChangedAfterLoad(false), - ModulePrivate(0), + Access(AS_none), FromASTFile(0), Hidden(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), HasCachedLinkage(0) { - if (Decl::CollectingStats()) add(DK); + if (StatisticsEnabled) add(DK); } virtual ~Decl(); + /// \brief Allocate memory for a deserialized declaration. + /// + /// This routine must be used to allocate memory for any declaration that is + /// deserialized from a module file. + /// + /// \param Context The context in which we will allocate memory. + /// \param ID The global ID of the deserialized declaration. + /// \param Size The size of the allocated object. + static void *AllocateDeserializedDecl(const ASTContext &Context, + unsigned ID, + unsigned Size); + public: /// \brief Source range that this declaration covers. - virtual SourceRange getSourceRange() const { + virtual SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLocation(), getLocation()); } - SourceLocation getLocStart() const { return getSourceRange().getBegin(); } - SourceLocation getLocEnd() const { return getSourceRange().getEnd(); } + SourceLocation getLocStart() const LLVM_READONLY { + return getSourceRange().getBegin(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + return getSourceRange().getEnd(); + } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } @@ -321,8 +354,8 @@ public: Kind getKind() const { return static_cast<Kind>(DeclKind); } const char *getDeclKindName() const; - Decl *getNextDeclInContext() { return NextDeclInContext; } - const Decl *getNextDeclInContext() const { return NextDeclInContext; } + Decl *getNextDeclInContext() { return NextInContextAndBits.getPointer(); } + const Decl *getNextDeclInContext() const {return NextInContextAndBits.getPointer();} DeclContext *getDeclContext() { if (isInSemaDC()) @@ -347,7 +380,7 @@ public: bool isInAnonymousNamespace() const; - ASTContext &getASTContext() const; + ASTContext &getASTContext() const LLVM_READONLY; void setAccess(AccessSpecifier AS) { Access = AS; @@ -364,7 +397,9 @@ public: } bool hasAttrs() const { return HasAttrs; } - void setAttrs(const AttrVec& Attrs); + void setAttrs(const AttrVec& Attrs) { + return setAttrsImpl(Attrs, getASTContext()); + } AttrVec &getAttrs() { return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs()); } @@ -389,11 +424,11 @@ public: attr_iterator attr_end() const { return hasAttrs() ? getAttrs().end() : 0; } - + template <typename T> void dropAttr() { if (!HasAttrs) return; - + AttrVec &Attrs = getAttrs(); for (unsigned i = 0, e = Attrs.size(); i != e; /* in loop */) { if (isa<T>(Attrs[i])) { @@ -406,7 +441,7 @@ public: if (Attrs.empty()) HasAttrs = false; } - + template <typename T> specific_attr_iterator<T> specific_attr_begin() const { return specific_attr_iterator<T>(attr_begin()); @@ -455,6 +490,48 @@ public: void setReferenced(bool R = true) { Referenced = R; } + /// \brief Whether this declaration is a top-level declaration (function, + /// global variable, etc.) that is lexically inside an objc container + /// definition. + bool isTopLevelDeclInObjCContainer() const { + return NextInContextAndBits.getInt() & TopLevelDeclInObjCContainerFlag; + } + + void setTopLevelDeclInObjCContainer(bool V = true) { + unsigned Bits = NextInContextAndBits.getInt(); + if (V) + Bits |= TopLevelDeclInObjCContainerFlag; + else + Bits &= ~TopLevelDeclInObjCContainerFlag; + NextInContextAndBits.setInt(Bits); + } + +protected: + /// \brief Whether this declaration was marked as being private to the + /// module in which it was defined. + bool isModulePrivate() const { + return NextInContextAndBits.getInt() & ModulePrivateFlag; + } + + /// \brief Specify whether this declaration was marked as being private + /// to the module in which it was defined. + void setModulePrivate(bool MP = true) { + unsigned Bits = NextInContextAndBits.getInt(); + if (MP) + Bits |= ModulePrivateFlag; + else + Bits &= ~ModulePrivateFlag; + NextInContextAndBits.setInt(Bits); + } + + /// \brief Set the owning module ID. + void setOwningModuleID(unsigned ID) { + assert(isFromASTFile() && "Only works on a deserialized declaration"); + *((unsigned*)this - 2) = ID; + } + +public: + /// \brief Determine the availability of the given declaration. /// /// This routine will determine the most restrictive availability of @@ -504,20 +581,24 @@ public: /// \brief Determine whether this declaration came from an AST file (such as /// a precompiled header or module) rather than having been parsed. bool isFromASTFile() const { return FromASTFile; } - - /// \brief Query whether this declaration was changed in a significant way - /// since being loaded from an AST file. - /// - /// In an epic violation of layering, what is "significant" is entirely - /// up to the serialization system, but implemented in AST and Sema. - bool isChangedSinceDeserialization() const { return ChangedAfterLoad; } - /// \brief Mark this declaration as having changed since deserialization, or - /// reset the flag. - void setChangedSinceDeserialization(bool Changed) { - ChangedAfterLoad = Changed; + /// \brief Retrieve the global declaration ID associated with this + /// declaration, which specifies where in the + unsigned getGlobalID() const { + if (isFromASTFile()) + return *((const unsigned*)this - 1); + return 0; } - + + /// \brief Retrieve the global ID of the module that owns this particular + /// declaration. + unsigned getOwningModuleID() const { + if (isFromASTFile()) + return *((const unsigned*)this - 2); + + return 0; + } + unsigned getIdentifierNamespace() const { return IdentifierNamespace; } @@ -587,7 +668,7 @@ public: /// \brief Whether this particular Decl is a canonical one. bool isCanonicalDecl() const { return getCanonicalDecl() == this; } - + protected: /// \brief Returns the next redeclaration or itself if this is the only decl. /// @@ -595,6 +676,14 @@ protected: /// Decl::redecl_iterator can iterate over them. virtual Decl *getNextRedeclaration() { return this; } + /// \brief Implementation of getPreviousDecl(), to be overridden by any + /// subclass that has a redeclaration chain. + virtual Decl *getPreviousDeclImpl() { return 0; } + + /// \brief Implementation of getMostRecentDecl(), to be overridden by any + /// subclass that has a redeclaration chain. + virtual Decl *getMostRecentDeclImpl() { return this; } + public: /// \brief Iterates through all the redeclarations of the same decl. class redecl_iterator { @@ -645,6 +734,26 @@ public: } redecl_iterator redecls_end() const { return redecl_iterator(); } + /// \brief Retrieve the previous declaration that declares the same entity + /// as this declaration, or NULL if there is no previous declaration. + Decl *getPreviousDecl() { return getPreviousDeclImpl(); } + + /// \brief Retrieve the most recent declaration that declares the same entity + /// as this declaration, or NULL if there is no previous declaration. + const Decl *getPreviousDecl() const { + return const_cast<Decl *>(this)->getPreviousDeclImpl(); + } + + /// \brief Retrieve the most recent declaration that declares the same entity + /// as this declaration (which may be this declaration). + Decl *getMostRecentDecl() { return getMostRecentDeclImpl(); } + + /// \brief Retrieve the most recent declaration that declares the same entity + /// as this declaration (which may be this declaration). + const Decl *getMostRecentDecl() const { + return const_cast<Decl *>(this)->getMostRecentDeclImpl(); + } + /// getBody - If this Decl represents a declaration for a body of code, /// such as a function or method definition, this method returns the /// top-level Stmt* of that body. Otherwise this method returns null. @@ -660,7 +769,7 @@ public: // global temp stats (until we have a per-module visitor) static void add(Kind k); - static bool CollectingStats(bool Enable = false); + static void EnableStatistics(); static void PrintStats(); /// isTemplateParameter - Determines whether this declaration is a @@ -673,7 +782,7 @@ public: /// \brief Whether this declaration is a parameter pack. bool isParameterPack() const; - + /// \brief returns true if this declaration is a template bool isTemplateDecl() const; @@ -722,7 +831,7 @@ public: unsigned mask = (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend)); if (!mask) return FOK_None; - return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? + return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? FOK_Declared : FOK_Undeclared); } @@ -747,17 +856,31 @@ public: static void printGroup(Decl** Begin, unsigned NumDecls, raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); - void dump() const; - void dumpXML() const; + LLVM_ATTRIBUTE_USED void dump() const; + LLVM_ATTRIBUTE_USED void dumpXML() const; void dumpXML(raw_ostream &OS) const; private: const Attr *getAttrsImpl() const; + void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx); + void setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, + ASTContext &Ctx); protected: ASTMutationListener *getASTMutationListener() const; }; +/// \brief Determine whether two declarations declare the same entity. +inline bool declaresSameEntity(const Decl *D1, const Decl *D2) { + if (!D1 || !D2) + return false; + + if (D1 == D2) + return true; + + return D1->getCanonicalDecl() == D2->getCanonicalDecl(); +} + /// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when /// doing something to a specific decl. class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry { @@ -826,8 +949,11 @@ class DeclContext { /// \brief Pointer to the data structure used to lookup declarations /// within this context (or a DependentStoredDeclsMap if this is a - /// dependent context). - mutable StoredDeclsMap *LookupPtr; + /// dependent context), and a bool indicating whether we have lazily + /// omitted any declarations from the map. We maintain the invariant + /// that, if the map contains an entry for a DeclarationName, then it + /// contains all relevant entries for that name. + mutable llvm::PointerIntPair<StoredDeclsMap*, 1, bool> LookupPtr; protected: /// FirstDecl - The first declaration stored within this declaration @@ -841,16 +967,17 @@ protected: mutable Decl *LastDecl; friend class ExternalASTSource; + friend class ASTWriter; /// \brief Build up a chain of declarations. /// /// \returns the first/last pair of declarations. static std::pair<Decl *, Decl *> - BuildDeclChain(const SmallVectorImpl<Decl*> &Decls, bool FieldsAlreadyLoaded); + BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded); DeclContext(Decl::Kind K) : DeclKind(K), ExternalLexicalStorage(false), - ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), + ExternalVisibleStorage(false), LookupPtr(0, false), FirstDecl(0), LastDecl(0) { } public: @@ -886,11 +1013,11 @@ public: } DeclContext *getLookupParent(); - + const DeclContext *getLookupParent() const { return const_cast<DeclContext*>(this)->getLookupParent(); } - + ASTContext &getParentASTContext() const { return cast<Decl>(this)->getASTContext(); } @@ -974,6 +1101,14 @@ public: /// declaration context DC. bool Encloses(const DeclContext *DC) const; + /// \brief Find the nearest non-closure ancestor of this context, + /// i.e. the innermost semantic parent of this context which is not + /// a closure. A context may be its own non-closure ancestor. + DeclContext *getNonClosureAncestor(); + const DeclContext *getNonClosureAncestor() const { + return const_cast<DeclContext*>(this)->getNonClosureAncestor(); + } + /// getPrimaryContext - There may be many different /// declarations of the same entity (including forward declarations /// of classes, multiple definitions of namespaces, etc.), each with @@ -1007,24 +1142,30 @@ public: /// inline, its enclosing namespace, recursively. bool InEnclosingNamespaceSetOf(const DeclContext *NS) const; - /// getNextContext - If this is a DeclContext that may have other - /// DeclContexts that are semantically connected but syntactically - /// different, such as C++ namespaces, this routine retrieves the - /// next DeclContext in the link. Iteration through the chain of - /// DeclContexts should begin at the primary DeclContext and - /// continue until this function returns NULL. For example, given: - /// @code + /// \\brief Collects all of the declaration contexts that are semantically + /// connected to this declaration context. + /// + /// For declaration contexts that have multiple semantically connected but + /// syntactically distinct contexts, such as C++ namespaces, this routine + /// retrieves the complete set of such declaration contexts in source order. + /// For example, given: + /// + /// \code /// namespace N { /// int x; /// } /// namespace N { /// int y; /// } - /// @endcode - /// The first occurrence of namespace N will be the primary - /// DeclContext. Its getNextContext will return the second - /// occurrence of namespace N. - DeclContext *getNextContext(); + /// \endcode + /// + /// The \c Contexts parameter will contain both definitions of N. + /// + /// \param Contexts Will be cleared and set to the set of declaration + /// contexts that are semanticaly connected to this declaration context, + /// in source order, including this context (which may be the only result, + /// for non-namespace contexts). + void collectAllContexts(llvm::SmallVectorImpl<DeclContext *> &Contexts); /// decl_iterator - Iterates through the declarations stored /// within this context. @@ -1133,13 +1274,13 @@ public: return tmp; } - friend bool - operator==(const specific_decl_iterator& x, const specific_decl_iterator& y) { + friend bool operator==(const specific_decl_iterator& x, + const specific_decl_iterator& y) { return x.Current == y.Current; } - friend bool - operator!=(const specific_decl_iterator& x, const specific_decl_iterator& y) { + friend bool operator!=(const specific_decl_iterator& x, + const specific_decl_iterator& y) { return x.Current != y.Current; } }; @@ -1207,13 +1348,13 @@ public: return tmp; } - friend bool - operator==(const filtered_decl_iterator& x, const filtered_decl_iterator& y) { + friend bool operator==(const filtered_decl_iterator& x, + const filtered_decl_iterator& y) { return x.Current == y.Current; } - friend bool - operator!=(const filtered_decl_iterator& x, const filtered_decl_iterator& y) { + friend bool operator!=(const filtered_decl_iterator& x, + const filtered_decl_iterator& y) { return x.Current != y.Current; } }; @@ -1232,6 +1373,16 @@ public: /// semantic context via makeDeclVisibleInContext. void addDecl(Decl *D); + /// @brief Add the declaration D into this context, but suppress + /// searches for external declarations with the same name. + /// + /// Although analogous in function to addDecl, this removes an + /// important check. This is only useful if the Decl is being + /// added in response to an external search; in all other cases, + /// addDecl() is the right function to use. + /// See the ASTImporter for use cases. + void addDeclInternal(Decl *D); + /// @brief Add the declaration D to this context without modifying /// any lookup tables. /// @@ -1265,12 +1416,12 @@ public: /// \brief A simplistic name lookup mechanism that performs name lookup /// into this declaration context without consulting the external source. /// - /// This function should almost never be used, because it subverts the + /// This function should almost never be used, because it subverts the /// usual relationship between a DeclContext and the external source. /// See the ASTImporter for the (few, but important) use cases. - void localUncachedLookup(DeclarationName Name, + void localUncachedLookup(DeclarationName Name, llvm::SmallVectorImpl<NamedDecl *> &Results); - + /// @brief Makes a declaration visible within this context. /// /// This routine makes the declaration D visible to name lookup @@ -1285,11 +1436,15 @@ public: /// visible from this context, as determined by /// NamedDecl::declarationReplaces, the previous declaration will be /// replaced with D. - /// - /// @param Recoverable true if it's okay to not add this decl to - /// the lookup tables because it can be easily recovered by walking - /// the declaration chains. - void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true); + void makeDeclVisibleInContext(NamedDecl *D); + + /// all_lookups_iterator - An iterator that provides a view over the results + /// of looking up every possible name. + class all_lookups_iterator; + + all_lookups_iterator lookups_begin() const; + + all_lookups_iterator lookups_end() const; /// udir_iterator - Iterates through the using-directives stored /// within this context. @@ -1315,7 +1470,11 @@ public: // Low-level accessors /// \brief Retrieve the internal representation of the lookup structure. - StoredDeclsMap* getLookupPtr() const { return LookupPtr; } + /// This may omit some names if we are lazily building the structure. + StoredDeclsMap *getLookupPtr() const { return LookupPtr.getPointer(); } + + /// \brief Ensure the lookup structure is fully-built and return it. + StoredDeclsMap *buildLookup(); /// \brief Whether this DeclContext has external storage containing /// additional declarations that are lexically in this context. @@ -1340,9 +1499,10 @@ public: /// \brief Determine whether the given declaration is stored in the list of /// declarations lexically within this context. bool isDeclInLexicalTraversal(const Decl *D) const { - return D && (D->NextDeclInContext || D == FirstDecl || D == LastDecl); + return D && (D->NextInContextAndBits.getPointer() || D == FirstDecl || + D == LastDecl); } - + static bool classof(const Decl *D); static bool classof(const DeclContext *D) { return true; } #define DECL(NAME, BASE) @@ -1350,16 +1510,26 @@ public: static bool classof(const NAME##Decl *D) { return true; } #include "clang/AST/DeclNodes.inc" - void dumpDeclContext() const; + LLVM_ATTRIBUTE_USED void dumpDeclContext() const; private: void LoadLexicalDeclsFromExternalStorage() const; + /// @brief Makes a declaration visible within this context, but + /// suppresses searches for external declarations with the same + /// name. + /// + /// Analogous to makeDeclVisibleInContext, but for the exclusive + /// use of addDeclInternal(). + void makeDeclVisibleInContextInternal(NamedDecl *D); + friend class DependentDiagnostic; StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; - void buildLookup(DeclContext *DCtx); - void makeDeclVisibleInContextImpl(NamedDecl *D); + void buildLookupImpl(DeclContext *DCtx); + void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, + bool Rediscoverable); + void makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal); }; inline bool Decl::isTemplateParameter() const { |