[PATCH] Partial specialization after class template instantiation.

Anton Bikineev ant.bikineev at gmail.com
Fri Apr 10 13:23:02 PDT 2015


Applied some comments


http://reviews.llvm.org/D5744

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaTemplate.cpp
  test/SemaTemplate/class-template-spec.cpp

Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -3392,6 +3392,8 @@
 def note_specialized_decl : Note<"attempt to specialize declaration here">;
 def err_specialization_after_instantiation : Error<
   "explicit specialization of %0 after instantiation">;
+def err_partial_spec_after_instantiation : Error<
+  "partial specialization of %0 after instantiation">;
 def note_instantiation_required_here : Note<
   "%select{implicit|explicit}0 instantiation first required here">;
 def err_template_spec_friend : Error<
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -6217,6 +6217,38 @@
     CanonType = Context.getTypeDeclType(Specialization);
   }
 
+  // C++ [temp.class.spec]p1:
+  //   A partial specialization shall be declared before the first use of a class
+  //   template specialization that would make use of partial specialization as
+  //   the result of an implicit or explicit instantiation in every translation
+  //   unit in which such a use occurs; no diagnostic is required.
+  if (isPartialSpecialization && !PrevDecl) {
+    auto *ThisPartialSpec =
+        cast<ClassTemplatePartialSpecializationDecl>(Specialization);
+    for (const auto &S : ClassTemplate->specializations()) {
+      TemplateDeductionInfo Info(KWLoc);
+      if (S->getSpecializationKind() != TSK_ExplicitSpecialization &&
+          S->hasDefinition() &&
+          !DeduceTemplateArguments(ThisPartialSpec, S->getTemplateArgs(), Info)) {
+        auto *InstantiatedFrom =
+            S->getInstantiatedFrom()
+                .dyn_cast<ClassTemplatePartialSpecializationDecl *>();
+        if (!InstantiatedFrom ||
+            getMoreSpecializedPartialSpecialization(
+                ThisPartialSpec, InstantiatedFrom, KWLoc) == ThisPartialSpec) {
+          SourceRange Range(TemplateNameLoc, RAngleLoc);
+          Diag(TemplateNameLoc, diag::err_partial_spec_after_instantiation)
+              << Context.getTypeDeclType(ThisPartialSpec) << Range;
+
+          Diag(S->getPointOfInstantiation(),
+               diag::note_instantiation_required_here)
+              << (S->getTemplateSpecializationKind() !=
+                  TSK_ImplicitInstantiation);
+        }
+      }
+    }
+  }
+
   // C++ [temp.expl.spec]p6:
   //   If a template, a member template or the member of a class template is
   //   explicitly specialized then that specialization shall be declared
Index: test/SemaTemplate/class-template-spec.cpp
===================================================================
--- test/SemaTemplate/class-template-spec.cpp
+++ test/SemaTemplate/class-template-spec.cpp
@@ -177,3 +177,16 @@
   > struct S;
   template<typename T> struct S<T> {}; // expected-error {{non-type template argument specializes a template parameter with dependent type 'T'}}
 }
+
+namespace PartialSpecAfterInstantiation {
+  template <typename T> struct A {};
+
+  A<int*> a; // expected-note {{implicit instantiation}}
+  template <typename T> struct A<T*> {}; // expected-error {{partial specialization}}
+
+  template struct A<int&>; // expected-note {{explicit instantiation}}
+  template <typename T> struct A<T&> {}; // expected-error {{partial specialization}}
+
+  A<const int*>* b; // that's fine
+  template <typename T> struct A<const T*> {};
+}

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D5744.23617.patch
Type: text/x-patch
Size: 3529 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150410/772d65cf/attachment.bin>


More information about the cfe-commits mailing list