]> granicus.if.org Git - clang/commitdiff
Tolerate extraneous "template<>" headers better, downgrading the
authorDouglas Gregor <dgregor@apple.com>
Mon, 23 Nov 2009 12:11:45 +0000 (12:11 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 23 Nov 2009 12:11:45 +0000 (12:11 +0000)
complaint to a warning and providing a helpful node in the case where
the "template<>" header is redundant because the corresponding
template-id refers to an explicit specialization. C++0x might still
change this behavior, and existing practice is all over the place on
the number of "template<>" headers actually needed.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaTemplate.cpp
test/SemaTemplate/temp_explicit.cpp

index 7ca011986b6be8277210a3a627c203026f9a87ef..399cf37cca1e61b877bc3f0e9c0c7ab3797f0cbd 100644 (file)
@@ -1049,6 +1049,11 @@ def err_template_param_list_matches_nontemplate : Error<
 def err_template_spec_extra_headers : Error<
   "extraneous template parameter list in template specialization or "
   "out-of-line template definition">;
+def warn_template_spec_extra_headers : Warning<
+  "extraneous template parameter list in template specialization">;
+def note_explicit_template_spec_does_not_need_header : Note<
+  "'template<>' header not required for explicitly-specialized class %0 "
+  "declared here">;
 def err_template_qualified_declarator_no_match : Error<
   "nested name specifier '%0' for declaration does not refer into a class, "
   "class template or class template partial specialization">;
index 096289fa35d8e48b7996b45b6be925de754a6dec..bfdf17afaee56ea9e9ce15218c2d3f0aca8d6555 100644 (file)
@@ -1048,6 +1048,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
   // template-ids will match up with the template parameter lists.
   llvm::SmallVector<const TemplateSpecializationType *, 4>
     TemplateIdsInSpecifier;
+  llvm::SmallVector<ClassTemplateSpecializationDecl *, 4>
+    ExplicitSpecializationsInSpecifier;
   for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
        NNS; NNS = NNS->getPrefix()) {
     if (const TemplateSpecializationType *SpecType
@@ -1061,10 +1063,10 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
           = cast<ClassTemplateSpecializationDecl>(Record->getDecl());
         // If the nested name specifier refers to an explicit specialization,
         // we don't need a template<> header.
-        // FIXME: revisit this approach once we cope with specializations
-        // properly.
-        if (SpecDecl->getSpecializationKind() == TSK_ExplicitSpecialization)
+        if (SpecDecl->getSpecializationKind() == TSK_ExplicitSpecialization) {
+          ExplicitSpecializationsInSpecifier.push_back(SpecDecl);
           continue;
+        }
       }
 
       TemplateIdsInSpecifier.push_back(SpecType);
@@ -1145,10 +1147,20 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
   // If there were too many template parameter lists, complain about that now.
   if (Idx != NumParamLists - 1) {
     while (Idx < NumParamLists - 1) {
+      bool isExplicitSpecHeader = ParamLists[Idx]->size() == 0;
       Diag(ParamLists[Idx]->getTemplateLoc(),
-           diag::err_template_spec_extra_headers)
+           isExplicitSpecHeader? diag::warn_template_spec_extra_headers
+                               : diag::err_template_spec_extra_headers)
         << SourceRange(ParamLists[Idx]->getTemplateLoc(),
                        ParamLists[Idx]->getRAngleLoc());
+
+      if (isExplicitSpecHeader && !ExplicitSpecializationsInSpecifier.empty()) {
+        Diag(ExplicitSpecializationsInSpecifier.back()->getLocation(),
+             diag::note_explicit_template_spec_does_not_need_header)
+          << ExplicitSpecializationsInSpecifier.back();
+        ExplicitSpecializationsInSpecifier.pop_back();
+      }
+        
       ++Idx;
     }
   }
index 9c824d6f414562e424b548f5a97979636edd469a..ae409aff662baaf5216686853ae38d2ef3e8f63b 100644 (file)
@@ -108,3 +108,20 @@ struct X6 {
 };
 
 template struct X6::Inner; // expected-error{{non-templated}}
+
+// PR5559
+template <typename T>
+struct Foo;
+
+template <>
+struct Foo<int> // expected-note{{header not required for explicitly-specialized}}
+{
+    template <typename U>
+    struct Bar
+    {};
+};
+
+template <> // expected-warning{{extraneous template parameter list}}
+template <>
+struct Foo<int>::Bar<void>
+{};