diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Sema/SemaAccess.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 11 | ||||
| -rw-r--r-- | clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp | 61 |
4 files changed, 68 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 90d31772221..e2b7a7e061d 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/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/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 19580957832..1d633a90480 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/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/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 5cfacf78b57..af852aa3406 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/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/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp index f23611bd505..82c2b3169d4 100644 --- a/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp +++ b/clang/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(); } + }; +} |

