]> granicus.if.org Git - clang/commitdiff
When we parse something that looks like a templated friend tag but
authorDouglas Gregor <dgregor@apple.com>
Thu, 20 Oct 2011 15:58:54 +0000 (15:58 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 20 Oct 2011 15:58:54 +0000 (15:58 +0000)
actually just has an extraneous 'template<>' header, strip off the
'template<>' header and treat it as a normal friend tag. Fixes PR10660
/ <rdar://problem/9958322>.

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

lib/Sema/SemaDeclCXX.cpp
test/SemaTemplate/friend-template.cpp

index 951ea9ccfd9b9c49efe4b75dd1b328a2a1ef93e7..bb867ed33ec45221ac23648c963db51edddca423 100644 (file)
@@ -9746,8 +9746,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
 
   if (Invalid) return 0;
 
-  assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?");
-
   bool isAllExplicitSpecializations = true;
   for (unsigned I = TempParamLists.size(); I-- > 0; ) {
     if (TempParamLists.get()[I]->size()) {
@@ -9762,6 +9760,18 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
   // about the template header and build an appropriate non-templated
   // friend.  TODO: for source fidelity, remember the headers.
   if (isAllExplicitSpecializations) {
+    if (SS.isEmpty()) {
+      bool Owned = false;
+      bool IsDependent = false;
+      return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc,
+                      Attr, AS_public, 
+                      /*ModulePrivateLoc=*/SourceLocation(),
+                      MultiTemplateParamsArg(), Owned, IsDependent, 
+                      /*ScopedEnum=*/false,
+                      /*ScopedEnumUsesClassTag=*/false,
+                      /*UnderlyingType=*/TypeResult());          
+    }
+    
     NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
     ElaboratedTypeKeyword Keyword
       = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
@@ -9789,6 +9799,10 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
     CurContext->addDecl(Friend);
     return Friend;
   }
+  
+  assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?");
+  
+
 
   // Handle the case of a templated-scope friend class.  e.g.
   //   template <class T> class A<T>::B;
index d1284de35f188b45e6fc502eeeeffcef6a93aa7e..152df37d3db3f9eca1b254c18a75784a37c5be01 100644 (file)
@@ -224,3 +224,9 @@ namespace friend_type_template_no_tag {
   };
   template struct S<int>;
 }
+
+namespace PR10660 {
+  struct A {
+    template <> friend class B; // expected-error{{extraneous 'template<>' in declaration of class 'B'}}
+  };
+}