diff options
author | John McCall <rjmccall@apple.com> | 2010-08-20 01:40:01 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-08-20 01:40:01 +0000 |
commit | 29c695b86199ce917fd59b875683960a1858342a (patch) | |
tree | 5738de2342a8ffcdede6ec1c4c85b692b98ad02c | |
parent | 59b6dca7e5160d6f2aff42b1cf077d1cbd64e330 (diff) |
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
-rw-r--r-- | lib/Sema/SemaAccess.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 11 | ||||
-rw-r--r-- | test/CXX/temp/temp.decls/temp.friend/p5.cpp | 61 |
4 files changed, 68 insertions, 9 deletions
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 T> class A { - class Member { +namespace test0 { + template <class T> class A { + class Member {}; }; -}; -class B { - template <class T> friend class A<T>::Member; -}; + class B { + template <class T> friend class A<T>::Member; + }; + + A<int> a; + B b; +} + +// rdar://problem/8204127 +namespace test1 { + template <class T> struct A; + + class C { + static void foo(); + template <class T> friend void A<T>::f(); + }; -A<int> a; -B b; + template <class T> struct A { + void f() { C::foo(); } + }; + + template <class T> struct A<T*> { + void f() { C::foo(); } + }; + + template <> struct A<char> { + void f() { C::foo(); } + }; +} + +// FIXME: these should fail! +namespace test2 { + template <class T> struct A; + + class C { + static void foo(); + template <class T> friend void A<T>::g(); + }; + + template <class T> struct A { + void f() { C::foo(); } + }; + + template <class T> struct A<T*> { + void f() { C::foo(); } + }; + + template <> struct A<char> { + void f() { C::foo(); } + }; +} |