]> granicus.if.org Git - clang/commitdiff
Detect efforts to declare a template member friend and explicitly ignore them.
authorJohn McCall <rjmccall@apple.com>
Fri, 20 Aug 2010 01:40:01 +0000 (01:40 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 20 Aug 2010 01:40:01 +0000 (01:40 +0000)
Avoids a crash.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111609 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaAccess.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplate.cpp
test/CXX/temp/temp.decls/temp.friend/p5.cpp

index 90d317722218e9534bff26709c3fd9895e295168..e2b7a7e061db31fe8acf8c769ed52e538df2719d 100644 (file)
@@ -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());
 
index 19580957832a594b2fa84b01fde26742e7e27a4a..1d633a9048073bec9d08ad411d3d0845e72b8905 100644 (file)
@@ -6538,6 +6538,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S,
   FrD->setAccess(AS_public);
   CurContext->addDecl(FrD);
 
+  if (ND->isInvalidDecl()) FrD->setInvalidDecl();
+
   return DeclPtrTy::make(ND);
 }
 
index 5cfacf78b577cc863309aa4b1fc605fe64b2672f..af852aa3406fa1259b384162e45e2937234c6013 100644 (file)
@@ -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];
index f23611bd505ed79049d3a6bfd2fd3aeabe7c82df..82c2b3169d4e255e576b349bd7af7f1e5a009df5 100644 (file)
@@ -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(); }
+  };
+}