[cfe-commits] r81801 - in /cfe/trunk: include/clang/AST/DeclBase.h include/clang/Parse/Action.h lib/Parse/ParseDeclCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.decls/temp.friend/p5.cpp
John McCall
rjmccall at apple.com
Mon Sep 14 14:59:20 PDT 2009
Author: rjmccall
Date: Mon Sep 14 16:59:20 2009
New Revision: 81801
URL: http://llvm.org/viewvc/llvm-project?rev=81801&view=rev
Log:
Skeletal support for friend class templates.
Added:
cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p5.cpp
Modified:
cfe/trunk/include/clang/AST/DeclBase.h
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=81801&r1=81800&r2=81801&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Mon Sep 14 16:59:20 2009
@@ -419,7 +419,8 @@
/// 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)
+ assert((OldNS == IDNS_Tag || OldNS == IDNS_Ordinary ||
+ OldNS == (IDNS_Tag | IDNS_Ordinary))
&& "unsupported namespace for undeclared friend");
if (!PreviouslyDeclared) IdentifierNamespace = 0;
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=81801&r1=81800&r2=81801&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Mon Sep 14 16:59:20 2009
@@ -1214,7 +1214,8 @@
/// ActOnFriendTypeDecl - Parsed a friend type declaration.
virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S,
- const DeclSpec &DS) {
+ const DeclSpec &DS,
+ bool IsTemplate) {
return DeclPtrTy();
}
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=81801&r1=81800&r2=81801&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Sep 14 16:59:20 2009
@@ -1015,11 +1015,8 @@
ConsumeToken();
if (DS.isFriendSpecified()) {
- // FIXME: Friend templates are ignored for now.
- if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
- return;
-
- Actions.ActOnFriendTypeDecl(CurScope, DS);
+ bool IsTemplate = TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate;
+ Actions.ActOnFriendTypeDecl(CurScope, DS, IsTemplate);
} else
Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=81801&r1=81800&r2=81801&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Sep 14 16:59:20 2009
@@ -2246,7 +2246,7 @@
ExprArg AssertExpr,
ExprArg AssertMessageExpr);
- DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS);
+ DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, bool IsTemplate);
DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition,
MultiTemplateParamsArg TemplateParams);
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=81801&r1=81800&r2=81801&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Sep 14 16:59:20 2009
@@ -4009,12 +4009,35 @@
}
Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,
- const DeclSpec &DS) {
+ const DeclSpec &DS,
+ bool IsTemplate) {
SourceLocation Loc = DS.getSourceRange().getBegin();
assert(DS.isFriendSpecified());
assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);
+ // Handle friend templates specially.
+ if (IsTemplate) {
+ Decl *D;
+ switch (DS.getTypeSpecType()) {
+ default:
+ // FIXME: implement this
+ assert(false && "unelaborated type templates are currently unimplemented!");
+ case DeclSpec::TST_class:
+ case DeclSpec::TST_union:
+ case DeclSpec::TST_struct:
+ D = (Decl*) DS.getTypeRep();
+ }
+
+ ClassTemplateDecl *Temp = cast<ClassTemplateDecl>(D);
+ FriendDecl *FD = FriendDecl::Create(Context, CurContext, Loc, Temp,
+ DS.getFriendSpecLoc());
+ FD->setAccess(AS_public);
+ CurContext->addDecl(FD);
+
+ return DeclPtrTy::make(FD);
+ }
+
// Try to convert the decl specifier to a type.
bool invalid = false;
QualType T = ConvertDeclSpecToType(DS, Loc, invalid);
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=81801&r1=81800&r2=81801&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Sep 14 16:59:20 2009
@@ -556,13 +556,8 @@
if (CheckTemplateDeclScope(S, TemplateParams))
return true;
- TagDecl::TagKind Kind;
- switch (TagSpec) {
- default: assert(0 && "Unknown tag type!");
- case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break;
- case DeclSpec::TST_union: Kind = TagDecl::TK_union; break;
- case DeclSpec::TST_class: Kind = TagDecl::TK_class; break;
- }
+ TagDecl::TagKind Kind = TagDecl::getTagKindForTypeSpec(TagSpec);
+ assert(Kind != TagDecl::TK_enum && "can't build template of enumerated type");
// There is no such thing as an unnamed class template.
if (!Name) {
@@ -657,6 +652,13 @@
// FIXME: If we had a scope specifier, we better have a previous template
// declaration!
+ // If this is a friend declaration of an undeclared template,
+ // create the template in the innermost namespace scope.
+ if (TUK == TUK_Friend && !PrevClassTemplate) {
+ while (!SemanticContext->isFileContext())
+ SemanticContext = SemanticContext->getParent();
+ }
+
CXXRecordDecl *NewClass =
CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name, KWLoc,
PrevClassTemplate?
@@ -678,7 +680,11 @@
(void)T;
// Set the access specifier.
- SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
+ if (TUK == TUK_Friend)
+ NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */
+ PrevClassTemplate != NULL);
+ else
+ SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
// Set the lexical context of these templates
NewClass->setLexicalDeclContext(CurContext);
@@ -690,7 +696,23 @@
if (Attr)
ProcessDeclAttributeList(S, NewClass, Attr);
- PushOnScopeChains(NewTemplate, S);
+ if (TUK != TUK_Friend)
+ PushOnScopeChains(NewTemplate, S);
+ else {
+ // We might be replacing an existing declaration in the lookup tables;
+ // if so, borrow its access specifier.
+ if (PrevClassTemplate)
+ NewTemplate->setAccess(PrevClassTemplate->getAccess());
+
+ // Friend templates are visible in fairly strange ways.
+ if (!CurContext->isDependentContext()) {
+ DeclContext *DC = SemanticContext->getLookupContext();
+ DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false);
+ if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+ PushOnScopeChains(NewTemplate, EnclosingScope,
+ /* AddToContext = */ false);
+ }
+ }
if (Invalid) {
NewTemplate->setInvalidDecl();
Added: cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p5.cpp?rev=81801&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p5.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p5.cpp Mon Sep 14 16:59:20 2009
@@ -0,0 +1,6 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+class A {
+ template <class T> friend class B;
+};
+
More information about the cfe-commits
mailing list