From: John McCall Date: Fri, 20 Aug 2010 01:40:01 +0000 (+0000) Subject: Detect efforts to declare a template member friend and explicitly ignore them. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=29c695b86199ce917fd59b875683960a1858342a;p=clang Detect efforts to declare a template member friend and explicitly ignore them. Avoids a crash. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111609 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 90d3177222..e2b7a7e061 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -514,6 +514,9 @@ static AccessResult MatchesFriend(Sema &S, static AccessResult MatchesFriend(Sema &S, const EffectiveContext &EC, FriendDecl *FriendD) { + if (FriendD->isInvalidDecl()) + return AR_accessible; + if (TypeSourceInfo *T = FriendD->getFriendType()) return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified()); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 1958095783..1d633a9048 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -6538,6 +6538,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S, FrD->setAccess(AS_public); CurContext->addDecl(FrD); + if (ND->isInvalidDecl()) FrD->setInvalidDecl(); + return DeclPtrTy::make(ND); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5cfacf78b5..af852aa340 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1365,8 +1365,12 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // If there were at least as many template-ids as there were template // parameter lists, then there are no template parameter lists remaining for // the declaration itself. - if (Idx >= NumParamLists) + if (Idx >= NumParamLists) { + // Silently drop template member friend declarations. + // TODO: implement these + if (IsFriend && NumParamLists) Invalid = true; return 0; + } // If there were too many template parameter lists, complain about that now. if (Idx != NumParamLists - 1) { @@ -1395,6 +1399,11 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, } } + // Silently drop template member template friend declarations. + // TODO: implement these + if (IsFriend && NumParamLists > 1) + Invalid = true; + // Return the last template parameter list, which corresponds to the // entity being declared. return ParamLists[NumParamLists - 1]; diff --git a/test/CXX/temp/temp.decls/temp.friend/p5.cpp b/test/CXX/temp/temp.decls/temp.friend/p5.cpp index f23611bd50..82c2b3169d 100644 --- a/test/CXX/temp/temp.decls/temp.friend/p5.cpp +++ b/test/CXX/temp/temp.decls/temp.friend/p5.cpp @@ -1,13 +1,58 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -template class A { - class Member { +namespace test0 { + template class A { + class Member {}; }; -}; -class B { - template friend class A::Member; -}; + class B { + template friend class A::Member; + }; + + A a; + B b; +} + +// rdar://problem/8204127 +namespace test1 { + template struct A; + + class C { + static void foo(); + template friend void A::f(); + }; -A a; -B b; + template struct A { + void f() { C::foo(); } + }; + + template struct A { + void f() { C::foo(); } + }; + + template <> struct A { + void f() { C::foo(); } + }; +} + +// FIXME: these should fail! +namespace test2 { + template struct A; + + class C { + static void foo(); + template friend void A::g(); + }; + + template struct A { + void f() { C::foo(); } + }; + + template struct A { + void f() { C::foo(); } + }; + + template <> struct A { + void f() { C::foo(); } + }; +}