[cfe-commits] r89651 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaTemplate.cpp test/SemaTemplate/temp_explicit.cpp

Douglas Gregor dgregor at apple.com
Mon Nov 23 04:11:45 PST 2009


Author: dgregor
Date: Mon Nov 23 06:11:45 2009
New Revision: 89651

URL: http://llvm.org/viewvc/llvm-project?rev=89651&view=rev
Log:
Tolerate extraneous "template<>" headers better, downgrading the
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.


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaTemplate/temp_explicit.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=89651&r1=89650&r2=89651&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Nov 23 06:11:45 2009
@@ -1049,6 +1049,11 @@
 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">;

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=89651&r1=89650&r2=89651&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Nov 23 06:11:45 2009
@@ -1048,6 +1048,8 @@
   // 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 @@
           = 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 @@
   // 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;
     }
   }

Modified: cfe/trunk/test/SemaTemplate/temp_explicit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_explicit.cpp?rev=89651&r1=89650&r2=89651&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_explicit.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_explicit.cpp Mon Nov 23 06:11:45 2009
@@ -108,3 +108,20 @@
 };
 
 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>
+{};





More information about the cfe-commits mailing list