diff options
author | John McCall <rjmccall@apple.com> | 2009-08-28 07:59:38 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-08-28 07:59:38 +0000 |
commit | 02cace78cf48cc26686bd5b07c78606abca13bcd (patch) | |
tree | 6a631652ec93156bd9ed8b2eafd457d8948a607a /include/clang | |
parent | 550b14b410eaed037c9b791806194e6cea1ebe90 (diff) |
Omnibus friend decl refactoring. Instead of cloning AST classes for friend
declarations of same, introduce a single AST class and add appropriate bits
(encoded in the namespace) for whether a decl is "real" or not. Much hackery
about previously-declared / not-previously-declared, but it's essentially
mandated by the standard that friends alter lookup, and this is at least
fairly non-intrusive.
Refactor the Sema methods specific to friends for cleaner flow and less nesting.
Incidentally solve a few bugs, but I remain confident that we can put them back.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80353 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang')
-rw-r--r-- | include/clang/AST/DeclBase.h | 45 | ||||
-rw-r--r-- | include/clang/AST/DeclCXX.h | 91 | ||||
-rw-r--r-- | include/clang/AST/DeclNodes.def | 3 |
3 files changed, 81 insertions, 58 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index e43f15d79a..9aea17bd1b 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -79,7 +79,9 @@ public: /// namespaces, labels, tags, members and ordinary /// identifiers. These are meant as bitmasks, so that searches in /// C++ can look into the "tag" namespace during ordinary lookup. We - /// use additional namespaces for Objective-C entities. + /// use additional namespaces for Objective-C entities. We also + /// put C++ friend declarations (of previously-undeclared entities) in + /// shadow namespaces. enum IdentifierNamespace { IDNS_Label = 0x1, IDNS_Tag = 0x2, @@ -88,7 +90,8 @@ public: IDNS_ObjCProtocol = 0x10, IDNS_ObjCImplementation = 0x20, IDNS_ObjCCategoryImpl = 0x40, - IDNS_Friend = 0x80 + IDNS_OrdinaryFriend = 0x80, + IDNS_TagFriend = 0x100 }; /// ObjCDeclQualifier - Qualifier used on types in method declarations @@ -164,7 +167,7 @@ private: protected: /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. - unsigned IdentifierNamespace : 8; + unsigned IdentifierNamespace : 16; private: #ifndef NDEBUG @@ -406,6 +409,42 @@ public: /// \brief Whether this declaration is a function or function template. bool isFunctionOrFunctionTemplate() const; + + /// \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) { + unsigned OldNS = IdentifierNamespace; + assert((OldNS == IDNS_Tag || OldNS == IDNS_Ordinary) + && "unsupported namespace for undeclared friend"); + if (!PreviouslyDeclared) IdentifierNamespace = 0; + + if (OldNS == IDNS_Tag) + IdentifierNamespace |= IDNS_TagFriend; + else + IdentifierNamespace |= IDNS_OrdinaryFriend; + } + + 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 + }; + + /// \brief Determines whether this declaration is the object of a + /// friend declaration and, if so, what kind. + /// + /// There is currently no direct way to find the associated FriendDecl. + FriendObjectKind getFriendObjectKind() const { + unsigned mask + = (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend)); + if (!mask) return FOK_None; + return (mask & (IDNS_Tag | IDNS_Ordinary) ? FOK_Declared : FOK_Undeclared); + } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *) { return true; } diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 2d16557d95..45e85c0a49 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -1280,83 +1280,68 @@ public: static bool classof(const CXXConversionDecl *D) { return true; } }; -/// FriendFunctionDecl - Represents the declaration (and possibly -/// the definition) of a friend function. For example: +/// FriendDecl - Represents the declaration of a friend entity, +/// which can be a function, a type, or a templated function or type. +// For example: /// /// @code -/// class A { -/// friend int foo(int); +/// template <typename T> class A { +/// friend int foo(T); +/// friend class B; +/// friend T; // only in C++0x +/// template <typename U> friend class C; +/// template <typename U> friend A& operator+=(A&, const U&) { ... } /// }; /// @endcode -class FriendFunctionDecl : public FunctionDecl { - // Location of the 'friend' specifier. - const SourceLocation FriendLoc; - - FriendFunctionDecl(DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, DeclaratorInfo *DInfo, - bool isInline, SourceLocation FriendL) - : FunctionDecl(FriendFunction, DC, L, N, T, DInfo, None, isInline), - FriendLoc(FriendL) - {} - +/// +/// The semantic context of a friend decl is its declaring class. +class FriendDecl : public Decl { public: - static FriendFunctionDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, DeclarationName N, - QualType T, DeclaratorInfo *DInfo, - bool isInline, SourceLocation FriendL); - - SourceLocation getFriendLoc() const { - return FriendLoc; - } + typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion; - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == FriendFunction; - } - static bool classof(const FriendFunctionDecl *D) { return true; } -}; - -/// FriendClassDecl - Represents the declaration of a friend class. -/// For example: -/// -/// @code -/// class X { -/// friend class Y; -/// }; -/// @endcode -class FriendClassDecl : public Decl { - // The friended type. In C++0x, this can be an arbitrary type, - // which we simply ignore if it's not a record type. - QualType FriendType; +private: + // The declaration that's a friend of this class. + FriendUnion Friend; // Location of the 'friend' specifier. SourceLocation FriendLoc; - FriendClassDecl(DeclContext *DC, SourceLocation L, - QualType T, SourceLocation FriendL) - : Decl(FriendClass, DC, L), - FriendType(T), + FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend, + SourceLocation FriendL) + : Decl(Decl::Friend, DC, L), + Friend(Friend), FriendLoc(FriendL) {} public: - static FriendClassDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, QualType T, - SourceLocation FriendL); + static FriendDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, FriendUnion Friend_, + SourceLocation FriendL); + + /// If this friend declaration names an (untemplated but + /// possibly dependent) type, return the type; otherwise + /// return null. This is used only for C++0x's unelaborated + /// friend type declarations. + Type *getFriendType() const { + return Friend.dyn_cast<Type*>(); + } - QualType getFriendType() const { - return FriendType; + /// If this friend declaration doesn't name an unelaborated + /// type, return the inner declaration. + NamedDecl *getFriendDecl() const { + return Friend.dyn_cast<NamedDecl*>(); } + /// Retrieves the location of the 'friend' keyword. SourceLocation getFriendLoc() const { return FriendLoc; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { - return D->getKind() == FriendClass; + return D->getKind() == Decl::Friend; } - static bool classof(const FriendClassDecl *D) { return true; } + static bool classof(const FriendDecl *D) { return true; } }; /// LinkageSpecDecl - This represents a linkage specification. For example: diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def index 996d042d14..61df9d052f 100644 --- a/include/clang/AST/DeclNodes.def +++ b/include/clang/AST/DeclNodes.def @@ -93,7 +93,6 @@ ABSTRACT_DECL(Named, Decl) DECL(EnumConstant, ValueDecl) ABSTRACT_DECL(Declarator, NamedDecl) DECL(Function, ValueDecl) - DECL(FriendFunction, FunctionDecl) DECL(CXXMethod, FunctionDecl) DECL(CXXConstructor, CXXMethodDecl) DECL(CXXDestructor, CXXMethodDecl) @@ -127,7 +126,7 @@ DECL(ObjCPropertyImpl, Decl) DECL(ObjCForwardProtocol, Decl) DECL(ObjCClass, Decl) DECL(FileScopeAsm, Decl) -DECL(FriendClass, Decl) +DECL(Friend, Decl) DECL(StaticAssert, Decl) LAST_DECL(Block, Decl) |