Patchwork C++ PATCH for c++/32505 (missed error on partial specialization after instantiation)

login
register
mail settings
Submitter Jason Merrill
Date July 16, 2010, 9:02 p.m.
Message ID <4C40C8E3.2090505@redhat.com>
Download mbox | patch
Permalink /patch/59127/
State New
Headers show

Comments

Jason Merrill - July 16, 2010, 9:02 p.m.
While looking at another issue, I noticed that we weren't diagnosing 
this.  The standard says that no diagnostic is required, but it seems 
like it's something that users would really want us to catch.   So now 
we do.

Tested x86_64-pc-linux-gnu, applied to trunk.

Patch

commit 846bfa71c1aeb0758caf3841637a2450baec8715
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jul 16 16:14:33 2010 -0400

    	PR c++/32505
    	* pt.c (process_partial_specialization): Diagnose partial
    	specialization after instantiation.
    	(most_specialized_class): Add complain parm.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ef6e8e9..3259043 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -158,7 +158,7 @@  static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
 static void regenerate_decl_from_template (tree, tree);
-static tree most_specialized_class (tree, tree);
+static tree most_specialized_class (tree, tree, tsubst_flags_t);
 static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
 static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
@@ -3831,6 +3831,7 @@  process_partial_specialization (tree decl)
   tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs);
   tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
   tree inner_parms;
+  tree inst;
   int nargs = TREE_VEC_LENGTH (inner_args);
   int ntparms;
   int  i;
@@ -4045,6 +4046,22 @@  process_partial_specialization (tree decl)
     = tree_cons (specargs, inner_parms,
                  DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
   TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
+
+  for (inst = DECL_TEMPLATE_INSTANTIATIONS (maintmpl); inst;
+       inst = TREE_CHAIN (inst))
+    {
+      tree inst_type = TREE_VALUE (inst);
+      if (COMPLETE_TYPE_P (inst_type)
+	  && CLASSTYPE_IMPLICIT_INSTANTIATION (inst_type))
+	{
+	  tree spec = most_specialized_class (inst_type, maintmpl, tf_none);
+	  if (spec && TREE_TYPE (spec) == type)
+	    permerror (input_location,
+		       "partial specialization of %qT after instantiation "
+		       "of %qT", type, inst_type);
+	}
+    }
+
   return decl;
 }
 
@@ -7749,7 +7766,7 @@  instantiate_class_template (tree type)
 
   /* Determine what specialization of the original template to
      instantiate.  */
-  t = most_specialized_class (type, templ);
+  t = most_specialized_class (type, templ, tf_warning_or_error);
   if (t == error_mark_node)
     {
       TYPE_BEING_DEFINED (type) = 1;
@@ -15974,7 +15991,7 @@  most_general_template (tree decl)
    returned.  */
 
 static tree
-most_specialized_class (tree type, tree tmpl)
+most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
 {
   tree list = NULL_TREE;
   tree t;
@@ -16094,6 +16111,8 @@  most_specialized_class (tree type, tree tmpl)
     {
       const char *str;
       char *spaces = NULL;
+      if (!(complain & tf_error))
+	return error_mark_node;
       error ("ambiguous class template instantiation for %q#T", type);
       str = TREE_CHAIN (list) ? _("candidates are:") : _("candidate is:");
       for (t = list; t; t = TREE_CHAIN (t))
diff --git a/gcc/testsuite/g++.dg/template/partial8.C b/gcc/testsuite/g++.dg/template/partial8.C
new file mode 100644
index 0000000..4db7e18
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/partial8.C
@@ -0,0 +1,4 @@ 
+// PR c++/32505
+template <class T> struct A { };
+A<int*> a;
+template <class T> struct A<T*> { }; // { dg-error "A<int\\*>" }