aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-08-28 07:59:38 +0000
committerJohn McCall <rjmccall@apple.com>2009-08-28 07:59:38 +0000
commit02cace78cf48cc26686bd5b07c78606abca13bcd (patch)
tree6a631652ec93156bd9ed8b2eafd457d8948a607a /include/clang
parent550b14b410eaed037c9b791806194e6cea1ebe90 (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.h45
-rw-r--r--include/clang/AST/DeclCXX.h91
-rw-r--r--include/clang/AST/DeclNodes.def3
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)