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

Submitted by Jason Merrill on July 16, 2010, 9:02 p.m.

Details

Message ID 4C40C8E3.2090505@redhat.com
State New
Headers show

Commit Message

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 hide | download patch | download mbox

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\\*>" }