diff options
Diffstat (limited to 'include/clang/AST/DeclBase.h')
-rw-r--r-- | include/clang/AST/DeclBase.h | 163 |
1 files changed, 126 insertions, 37 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 754facf..26eea64 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -16,6 +16,7 @@ #include "clang/AST/AttrIterator.h" #include "clang/AST/DeclarationName.h" +#include "clang/Basic/Linkage.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/Compiler.h" @@ -31,6 +32,7 @@ class DeclarationName; class DependentDiagnostic; class EnumDecl; class FunctionDecl; +class LinkageComputer; class LinkageSpecDecl; class Module; class NamedDecl; @@ -157,7 +159,12 @@ public: /// This declaration is a C++ operator declared in a non-class /// context. All such operators are also in IDNS_Ordinary. /// C++ lexical operator lookup looks for these. - IDNS_NonMemberOperator = 0x0400 + IDNS_NonMemberOperator = 0x0400, + + /// This declaration is a function-local extern declaration of a + /// variable or function. This may also be IDNS_Ordinary if it + /// has been declared outside any function. + IDNS_LocalExtern = 0x0800 }; /// ObjCDeclQualifier - 'Qualifiers' written next to the return and @@ -284,19 +291,16 @@ protected: /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. unsigned IdentifierNamespace : 12; - /// \brief Whether the \c CachedLinkage field is active. - /// - /// 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; + /// \brief If 0, we have not computed the linkage of this declaration. + /// Otherwise, it is the linkage + 1. + mutable unsigned CacheValidAndLinkage : 3; friend class ASTDeclWriter; friend class ASTDeclReader; friend class ASTReader; + friend class LinkageComputer; + + template<typename decl_type> friend class Redeclarable; private: void CheckAccessDeclContext() const; @@ -309,7 +313,7 @@ protected: HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), FromASTFile(0), Hidden(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - HasCachedLinkage(0) + CacheValidAndLinkage(0) { if (StatisticsEnabled) add(DK); } @@ -319,7 +323,7 @@ protected: HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), FromASTFile(0), Hidden(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - HasCachedLinkage(0) + CacheValidAndLinkage(0) { if (StatisticsEnabled) add(DK); } @@ -341,6 +345,18 @@ protected: /// \brief Update a potentially out-of-date declaration. void updateOutOfDate(IdentifierInfo &II) const; + Linkage getCachedLinkage() const { + return Linkage(CacheValidAndLinkage - 1); + } + + void setCachedLinkage(Linkage L) const { + CacheValidAndLinkage = L + 1; + } + + bool hasCachedLinkage() const { + return CacheValidAndLinkage; + } + public: /// \brief Source range that this declaration covers. @@ -419,7 +435,6 @@ public: return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs()); } const AttrVec &getAttrs() const; - void swapAttrs(Decl *D); void dropAttrs(); void addAttr(Attr *A) { @@ -490,7 +505,16 @@ public: /// whether the function is used. bool isUsed(bool CheckUsedAttr = true) const; - void setUsed(bool U = true) { Used = U; } + /// \brief Set whether the declaration is used, in the sense of odr-use. + /// + /// This should only be used immediately after creating a declaration. + void setIsUsed() { Used = true; } + + /// \brief Mark the declaration used, in the sense of odr-use. + /// + /// This notifies any mutation listeners in addition to setting a bit + /// indicating the declaration is used. + void markUsed(ASTContext &C); /// \brief Whether this declaration was referenced. bool isReferenced() const; @@ -513,13 +537,13 @@ public: NextInContextAndBits.setInt(Bits); } -protected: /// \brief Whether this declaration was marked as being private to the /// module in which it was defined. - bool isModulePrivate() const { + bool isModulePrivate() const { return NextInContextAndBits.getInt() & ModulePrivateFlag; } - + +protected: /// \brief Specify whether this declaration was marked as being private /// to the module in which it was defined. void setModulePrivate(bool MP = true) { @@ -761,7 +785,12 @@ public: const Decl *getPreviousDecl() const { return const_cast<Decl *>(this)->getPreviousDeclImpl(); } - + + /// \brief True if this is the first declaration in its redeclaration chain. + bool isFirstDecl() const { + return getPreviousDecl() == 0; + } + /// \brief Retrieve the most recent declaration that declares the same entity /// as this declaration (which may be this declaration). Decl *getMostRecentDecl() { return getMostRecentDeclImpl(); } @@ -777,8 +806,10 @@ public: /// top-level Stmt* of that body. Otherwise this method returns null. virtual Stmt* getBody() const { return 0; } - /// \brief Returns true if this Decl represents a declaration for a body of + /// \brief Returns true if this \c Decl represents a declaration for a body of /// code, such as a function or method definition. + /// Note that \c hasBody can also return true if any redeclaration of this + /// \c Decl represents a declaration for a body of code. virtual bool hasBody() const { return getBody() != 0; } /// getBodyRBrace - Gets the right brace of the body, if a body exists. @@ -808,37 +839,71 @@ public: bool isFunctionOrFunctionTemplate() const; /// \brief Changes the namespace of this declaration to reflect that it's + /// a function-local extern declaration. + /// + /// These declarations appear in the lexical context of the extern + /// declaration, but in the semantic context of the enclosing namespace + /// scope. + void setLocalExternDecl() { + assert((IdentifierNamespace == IDNS_Ordinary || + IdentifierNamespace == IDNS_OrdinaryFriend) && + "namespace is not ordinary"); + + Decl *Prev = getPreviousDecl(); + IdentifierNamespace &= ~IDNS_Ordinary; + + IdentifierNamespace |= IDNS_LocalExtern; + if (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary) + IdentifierNamespace |= IDNS_Ordinary; + } + + /// \brief Determine whether this is a block-scope declaration with linkage. + /// This will either be a local variable declaration declared 'extern', or a + /// local function declaration. + bool isLocalExternDecl() { + return IdentifierNamespace & IDNS_LocalExtern; + } + + /// \brief Changes the namespace of this declaration to reflect that it's /// the object of a friend declaration. /// /// These declarations appear in the lexical context of the friending /// class, but in the semantic context of the actual entity. This property /// applies only to a specific decl object; other redeclarations of the /// same entity may not (and probably don't) share this property. - void setObjectOfFriendDecl(bool PreviouslyDeclared) { + void setObjectOfFriendDecl(bool PerformFriendInjection = false) { unsigned OldNS = IdentifierNamespace; assert((OldNS & (IDNS_Tag | IDNS_Ordinary | - IDNS_TagFriend | IDNS_OrdinaryFriend)) && + IDNS_TagFriend | IDNS_OrdinaryFriend | + IDNS_LocalExtern)) && "namespace includes neither ordinary nor tag"); assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type | - IDNS_TagFriend | IDNS_OrdinaryFriend)) && + IDNS_TagFriend | IDNS_OrdinaryFriend | + IDNS_LocalExtern)) && "namespace includes other than ordinary or tag"); - IdentifierNamespace = 0; + Decl *Prev = getPreviousDecl(); + IdentifierNamespace &= ~(IDNS_Ordinary | IDNS_Tag | IDNS_Type); + if (OldNS & (IDNS_Tag | IDNS_TagFriend)) { IdentifierNamespace |= IDNS_TagFriend; - if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type; + if (PerformFriendInjection || + (Prev && Prev->getIdentifierNamespace() & IDNS_Tag)) + IdentifierNamespace |= IDNS_Tag | IDNS_Type; } - if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) { + if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend | IDNS_LocalExtern)) { IdentifierNamespace |= IDNS_OrdinaryFriend; - if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary; + if (PerformFriendInjection || + (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary)) + IdentifierNamespace |= IDNS_Ordinary; } } enum FriendObjectKind { - FOK_None, // not a friend object - FOK_Declared, // a friend of a previously-declared entity - FOK_Undeclared // a friend of a previously-undeclared entity + FOK_None, ///< Not a friend object. + FOK_Declared, ///< A friend of a previously-declared entity. + FOK_Undeclared ///< A friend of a previously-undeclared entity. }; /// \brief Determines whether this declaration is the object of a @@ -846,11 +911,11 @@ public: /// /// There is currently no direct way to find the associated FriendDecl. FriendObjectKind getFriendObjectKind() const { - unsigned mask - = (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend)); + unsigned mask = + (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend)); if (!mask) return FOK_None; - return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? - FOK_Declared : FOK_Undeclared); + return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? FOK_Declared + : FOK_Undeclared); } /// Specifies that this declaration is a C++ overloaded non-member. @@ -877,9 +942,6 @@ public: // Same as dump(), but forces color printing. LLVM_ATTRIBUTE_USED void dumpColor() const; void dump(raw_ostream &Out) const; - // Debuggers don't usually respect default arguments. - LLVM_ATTRIBUTE_USED void dumpXML() const; - void dumpXML(raw_ostream &OS) const; private: void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx); @@ -974,6 +1036,7 @@ protected: mutable Decl *LastDecl; friend class ExternalASTSource; + friend class ASTDeclReader; friend class ASTWriter; /// \brief Build up a chain of declarations. @@ -1096,6 +1159,14 @@ public: /// C++0x scoped enums), and C++ linkage specifications. bool isTransparentContext() const; + /// \brief Determines whether this context or some of its ancestors is a + /// linkage specification context that specifies C linkage. + bool isExternCContext() const; + + /// \brief Determines whether this context or some of its ancestors is a + /// linkage specification context that specifies C++ linkage. + bool isExternCXXContext() const; + /// \brief Determine whether this declaration context is equivalent /// to the declaration context DC. bool Equals(const DeclContext *DC) const { @@ -1429,12 +1500,20 @@ public: return const_cast<DeclContext*>(this)->lookup(Name); } + /// \brief Find the declarations with the given name that are visible + /// within this context; don't attempt to retrieve anything from an + /// external source. + lookup_result noload_lookup(DeclarationName Name); + /// \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 /// usual relationship between a DeclContext and the external source. /// See the ASTImporter for the (few, but important) use cases. + /// + /// FIXME: This is very inefficient; replace uses of it with uses of + /// noload_lookup. void localUncachedLookup(DeclarationName Name, SmallVectorImpl<NamedDecl *> &Results); @@ -1458,10 +1537,16 @@ public: /// of looking up every possible name. class all_lookups_iterator; + /// \brief Iterators over all possible lookups within this context. all_lookups_iterator lookups_begin() const; - all_lookups_iterator lookups_end() const; + /// \brief Iterators over all possible lookups within this context that are + /// currently loaded; don't attempt to retrieve anything from an external + /// source. + all_lookups_iterator noload_lookups_begin() const; + all_lookups_iterator noload_lookups_end() const; + /// udir_iterator - Iterates through the using-directives stored /// within this context. typedef UsingDirectiveDecl * const * udir_iterator; @@ -1532,6 +1617,8 @@ public: static bool classof(const DeclContext *D) { return true; } LLVM_ATTRIBUTE_USED void dumpDeclContext() const; + LLVM_ATTRIBUTE_USED void dumpLookups() const; + LLVM_ATTRIBUTE_USED void dumpLookups(llvm::raw_ostream &OS) const; private: void reconcileExternalVisibleStorage(); @@ -1548,6 +1635,8 @@ private: friend class DependentDiagnostic; StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; + template<decl_iterator (DeclContext::*Begin)() const, + decl_iterator (DeclContext::*End)() const> void buildLookupImpl(DeclContext *DCtx); void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, bool Rediscoverable); |