]> granicus.if.org Git - clang/commitdiff
Provide a special diagnostic for attempts to explicitly specialize
authorDouglas Gregor <dgregor@apple.com>
Tue, 13 Jul 2010 00:10:04 +0000 (00:10 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 13 Jul 2010 00:10:04 +0000 (00:10 +0000)
class templates within class scope (which is ill-formed), and recover
by dropping the explicit specialization entirely. Fixes the infinite
loop in PR7622.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaTemplate.cpp
test/SemaTemplate/explicit-instantiation.cpp

index 8fda370e058c9d2db7b10a2c27318be1b8a90617..abd11c74d37442e51bb16e60056958c56e916767 100644 (file)
@@ -1575,6 +1575,8 @@ def err_explicit_instantiation_nontemplate_type : Error<
     "explicit instantiation of non-templated type %0">;
 def note_nontemplate_decl_here : Note<
     "non-templated declaration is here">;
+def err_explicit_instantiation_in_class : Error<
+  "explicit instantiation of %0 in class scope">;
 def err_explicit_instantiation_out_of_scope : Error<
   "explicit instantiation of %0 not in a namespace enclosing %1">;
 def err_explicit_instantiation_must_be_global : Error<
index 31823c72eadac6984dfb9c6d4ae4c3e81c1c2fe4..7cc4317845097842d4d5cf8aa414b88f2ab930a2 100644 (file)
@@ -4549,13 +4549,21 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
 }
 
 /// \brief Check the scope of an explicit instantiation.
-static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
+///
+/// \returns true if a serious error occurs, false otherwise.
+static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
                                             SourceLocation InstLoc,
                                             bool WasQualifiedName) {
   DeclContext *ExpectedContext
     = D->getDeclContext()->getEnclosingNamespaceContext()->getLookupContext();
   DeclContext *CurContext = S.CurContext->getLookupContext();
   
+  if (CurContext->isRecord()) {
+    S.Diag(InstLoc, diag::err_explicit_instantiation_in_class)
+      << D;
+    return true;
+  }
+  
   // C++0x [temp.explicit]p2:
   //   An explicit instantiation shall appear in an enclosing namespace of its 
   //   template.
@@ -4576,7 +4584,7 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
                : diag::warn_explicit_instantiation_out_of_scope_0x)
         << D;
     S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
-    return;
+    return false;
   }
   
   // C++0x [temp.explicit]p2:
@@ -4585,10 +4593,10 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
   //   its template is declared or, if that namespace is inline (7.3.1), any
   //   namespace from its enclosing namespace set.
   if (WasQualifiedName)
-    return;
+    return false;
   
   if (CurContext->Equals(ExpectedContext))
-    return;
+    return false;
   
   S.Diag(InstLoc, 
          S.getLangOptions().CPlusPlus0x?
@@ -4596,6 +4604,7 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D,
            : diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x)
     << D << ExpectedContext;
   S.Diag(D->getLocation(), diag::note_explicit_instantiation_here);
+  return false;
 }
 
 /// \brief Determine whether the given scope specifier has a template-id in it.
@@ -4698,8 +4707,9 @@ Sema::ActOnExplicitInstantiation(Scope *S,
   //   namespace of its template. [...]
   //
   // This is C++ DR 275.
-  CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc,
-                                  SS.isSet());
+  if (CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc,
+                                      SS.isSet()))
+    return true;
   
   ClassTemplateSpecializationDecl *Specialization = 0;
 
index de51f0992baa3ae01bac2d8b922e75a36eb24328..3a1446e8dd6730ea1ec682acf2a5eab9897c49e3 100644 (file)
@@ -83,3 +83,16 @@ namespace explicit_instantiation_after_implicit_instantiation {
   void test1() { (void)&X0<1>::x; }
   template struct X0<1>;
 }
+
+namespace PR7622 { // expected-note{{to match this}}
+  template<typename,typename=int>
+  struct basic_streambuf;
+
+  // FIXME: Very poor recovery here.
+  template<typename,typename>
+  struct basic_streambuf{friend bob<>()}; // expected-error{{unknown type name 'bob'}} \
+  // expected-error{{ expected member name or ';' after declaration specifiers}}
+  template struct basic_streambuf<int>; // expected-error{{explicit instantiation of 'basic_streambuf' in class scope}}
+}  // expected-error{{expected ';' after struct}}
+  
+//expected-error{{expected '}'}}