[cfe-commits] r78719 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/AST/DeclNodes.def lib/AST/DeclBase.cpp lib/AST/DeclCXX.cpp lib/Sema/SemaDeclCXX.cpp
John McCall
rjmccall at apple.com
Tue Aug 11 14:13:22 PDT 2009
Author: rjmccall
Date: Tue Aug 11 16:13:21 2009
New Revision: 78719
URL: http://llvm.org/viewvc/llvm-project?rev=78719&view=rev
Log:
Add a FriendClassDecl type for holding declarations of friend types in
the AST, and create such declarations.
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/AST/DeclNodes.def
cfe/trunk/lib/AST/DeclBase.cpp
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=78719&r1=78718&r2=78719&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Aug 11 16:13:21 2009
@@ -1273,6 +1273,42 @@
static bool classof(const FriendFunctionDecl *D) { return true; }
};
+/// FriendClassDecl - Represents the declaration of a friend class.
+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.
+ const QualType FriendType;
+
+ // Location of the 'friend' specifier.
+ const SourceLocation FriendLoc;
+
+ FriendClassDecl(DeclContext *DC, SourceLocation L,
+ QualType T, SourceLocation FriendL)
+ : Decl(FriendClass, DC, L),
+ FriendType(T),
+ FriendLoc(FriendL)
+ {}
+
+public:
+ static FriendClassDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, QualType T,
+ SourceLocation FriendL);
+
+ QualType getFriendType() const {
+ return FriendType;
+ }
+
+ SourceLocation getFriendLoc() const {
+ return FriendLoc;
+ }
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == FriendClass;
+ }
+ static bool classof(const FriendClassDecl *D) { return true; }
+};
+
/// LinkageSpecDecl - This represents a linkage specification. For example:
/// extern "C" void foo();
///
Modified: cfe/trunk/include/clang/AST/DeclNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclNodes.def?rev=78719&r1=78718&r2=78719&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclNodes.def (original)
+++ cfe/trunk/include/clang/AST/DeclNodes.def Tue Aug 11 16:13:21 2009
@@ -125,6 +125,7 @@
DECL(ObjCForwardProtocol, Decl)
DECL(ObjCClass, Decl)
DECL(FileScopeAsm, Decl)
+DECL(FriendClass, Decl)
DECL(StaticAssert, Decl)
LAST_DECL(Block, Decl)
Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=78719&r1=78718&r2=78719&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Tue Aug 11 16:13:21 2009
@@ -199,6 +199,7 @@
case ObjCCompatibleAlias:
return IDNS_Ordinary;
+ case FriendClass:
case FriendFunction:
return IDNS_Friend;
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=78719&r1=78718&r2=78719&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Aug 11 16:13:21 2009
@@ -743,14 +743,20 @@
return !isa<OverloadedFunctionDecl>(D) || Iter == Other.Iter;
}
-FriendFunctionDecl *FriendFunctionDecl::Create(ASTContext &C,DeclContext *DC,
+FriendFunctionDecl *FriendFunctionDecl::Create(ASTContext &C,
+ DeclContext *DC,
SourceLocation L,
DeclarationName N, QualType T,
bool isInline,
SourceLocation FriendL) {
return new (C) FriendFunctionDecl(DC, L, N, T, isInline, FriendL);
}
-
+
+FriendClassDecl *FriendClassDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, QualType T,
+ SourceLocation FriendL) {
+ return new (C) FriendClassDecl(DC, L, T, FriendL);
+}
LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
DeclContext *DC,
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=78719&r1=78718&r2=78719&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Aug 11 16:13:21 2009
@@ -3320,68 +3320,98 @@
assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
// If there's no declarator, then this can only be a friend class
- // declaration (or else it's just invalid).
+ // declaration (or else it's just syntactically invalid).
if (!D) {
+ SourceLocation Loc = DS.getSourceRange().getBegin();
- // C++ [class.friend]p2:
- // An elaborated-type-specifier shall be used in a friend declaration
- // for a class.*
- // * The class-key of the elaborated-type-specifier is required.
- CXXRecordDecl *RD = 0;
-
- switch (DS.getTypeSpecType()) {
- case DeclSpec::TST_class:
- case DeclSpec::TST_struct:
- case DeclSpec::TST_union:
- RD = dyn_cast_or_null<CXXRecordDecl>(static_cast<Decl*>(DS.getTypeRep()));
- if (!RD) return DeclPtrTy();
- break;
-
- case DeclSpec::TST_typename:
- if (const RecordType *RT =
- ((const Type*) DS.getTypeRep())->getAs<RecordType>())
- RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- // fallthrough
- default:
- if (RD) {
- Diag(DS.getFriendSpecLoc(), diag::err_unelaborated_friend_type)
- << (RD->isUnion())
- << CodeModificationHint::CreateInsertion(DS.getTypeSpecTypeLoc(),
- RD->isUnion() ? " union" : " class");
- return DeclPtrTy::make(RD);
+ QualType T;
+ DeclContext *DC;
+
+ // In C++0x, we just accept any old type.
+ if (getLangOptions().CPlusPlus0x) {
+ bool invalid = false;
+ QualType T = ConvertDeclSpecToType(DS, Loc, invalid);
+ if (invalid)
+ return DeclPtrTy();
+
+ // The semantic context in which to create the decl. If it's not
+ // a record decl (or we don't yet know if it is), create it in the
+ // current context.
+ DC = CurContext;
+ if (const RecordType *RT = T->getAs<RecordType>())
+ DC = RT->getDecl()->getDeclContext();
+
+ // The C++98 rules are somewhat more complex.
+ } else {
+ // C++ [class.friend]p2:
+ // An elaborated-type-specifier shall be used in a friend declaration
+ // for a class.*
+ // * The class-key of the elaborated-type-specifier is required.
+ CXXRecordDecl *RD = 0;
+
+ switch (DS.getTypeSpecType()) {
+ case DeclSpec::TST_class:
+ case DeclSpec::TST_struct:
+ case DeclSpec::TST_union:
+ RD = dyn_cast_or_null<CXXRecordDecl>((Decl*) DS.getTypeRep());
+ if (!RD) return DeclPtrTy();
+ break;
+
+ case DeclSpec::TST_typename:
+ if (const RecordType *RT =
+ ((const Type*) DS.getTypeRep())->getAs<RecordType>())
+ RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
+ // fallthrough
+ default:
+ if (RD) {
+ Diag(DS.getFriendSpecLoc(), diag::err_unelaborated_friend_type)
+ << (RD->isUnion())
+ << CodeModificationHint::CreateInsertion(DS.getTypeSpecTypeLoc(),
+ RD->isUnion() ? " union" : " class");
+ return DeclPtrTy::make(RD);
+ }
+
+ Diag(DS.getFriendSpecLoc(), diag::err_unexpected_friend)
+ << DS.getSourceRange();
+ return DeclPtrTy();
}
- Diag(DS.getFriendSpecLoc(), diag::err_unexpected_friend)
- << DS.getSourceRange();
- return DeclPtrTy();
+ // The record declaration we get from friend declarations is not
+ // canonicalized; see ActOnTag.
+ assert(RD);
+
+ // C++ [class.friend]p2: A class shall not be defined inside
+ // a friend declaration.
+ if (RD->isDefinition())
+ Diag(DS.getFriendSpecLoc(), diag::err_friend_decl_defines_class)
+ << RD->getSourceRange();
+
+ // C++98 [class.friend]p1: A friend of a class is a function
+ // or class that is not a member of the class . . .
+ // But that's a silly restriction which nobody implements for
+ // inner classes, and C++0x removes it anyway, so we only report
+ // this (as a warning) if we're being pedantic.
+ //
+ // Also, definitions currently get treated in a way that causes
+ // this error, so only report it if we didn't see a definition.
+ else if (RD->getDeclContext() == CurContext &&
+ !getLangOptions().CPlusPlus0x)
+ Diag(DS.getFriendSpecLoc(), diag::ext_friend_inner_class);
+
+ T = QualType(RD->getTypeForDecl(), 0);
+ DC = RD->getDeclContext();
}
- // The record declaration we get from friend declarations is not
- // canonicalized; see ActOnTag.
- assert(RD);
-
- // C++ [class.friend]p2: A class shall not be defined inside
- // a friend declaration.
- if (RD->isDefinition())
- Diag(DS.getFriendSpecLoc(), diag::err_friend_decl_defines_class)
- << RD->getSourceRange();
-
- // C++98 [class.friend]p1: A friend of a class is a function
- // or class that is not a member of the class . . .
- // But that's a silly restriction which nobody implements for
- // inner classes, and C++0x removes it anyway, so we only report
- // this
- // But no-one implements it that way, and C++0x removes this
- // restriction, so we only report it (as a warning) if we're being
- // pedantic. Ideally this would real -pedantic mode
- //
- // Also, definitions currently get treated in a way that causes
- // this error, so only report it if we didn't see a definition.
- else if (RD->getDeclContext() == CurContext &&
- !getLangOptions().CPlusPlus0x)
- Diag(DS.getFriendSpecLoc(), diag::ext_friend_inner_class);
+ FriendClassDecl *FCD = FriendClassDecl::Create(Context, DC, Loc, T,
+ DS.getFriendSpecLoc());
+ FCD->setLexicalDeclContext(CurContext);
+
+ if (CurContext->isDependentContext())
+ CurContext->addHiddenDecl(FCD);
+ else
+ CurContext->addDecl(FCD);
- return DeclPtrTy::make(RD);
+ return DeclPtrTy::make(FCD);
}
// We have a declarator.
More information about the cfe-commits
mailing list