pt.c (process_partial_specialization): Build a TEMPLATE_DECL for a partial specializa...
authorJason Merrill <jason@redhat.com>
Thu, 20 Jun 2013 18:33:02 +0000 (14:33 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 20 Jun 2013 18:33:02 +0000 (14:33 -0400)
* pt.c (process_partial_specialization): Build a TEMPLATE_DECL for
a partial specialization.
(tsubst_decl): Don't clobber CLASSTYPE_TI_TEMPLATE of a partial
specialization.
(most_specialized_class): Adjust.

From-SVN: r200263

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c

index 7c7a17f8a45505747680c9a7343e3642f421ce2b..a7df33b562cf2bece27d9c3162012f88ce033756 100644 (file)
@@ -1,5 +1,11 @@
 2013-06-20  Jason Merrill  <jason@redhat.com>
 
+       * pt.c (process_partial_specialization): Build a TEMPLATE_DECL for
+       a partial specialization.
+       (tsubst_decl): Don't clobber CLASSTYPE_TI_TEMPLATE of a partial
+       specialization.
+       (most_specialized_class): Adjust.
+
        * cp-tree.h (DECL_TEMPLATE_PARMS, DECL_TEMPLATE_RESULT)
        (DECL_TEMPLATE_INSTANTIATIONS, DECL_TEMPLATE_SPECIALIZATIONS): Use
        TEMPLATE_DECL_CHECK.
index 41ef24d455bc3dfab45d57783f4874862d7cb669..9fc4aeb13652afdc768f1e33d47a3e44328887f2 100644 (file)
@@ -3727,11 +3727,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
    specializations of this template.  (Full specializations are not
    recorded on this list.)  The TREE_PURPOSE holds the arguments used
    in the partial specialization (e.g., for `template <class T> struct
-   S<T*, int>' this will be `T*'.)  The arguments will also include
-   any outer template arguments.  The TREE_VALUE holds the innermost
-   template parameters for the specialization (e.g., `T' in the
-   example above.)  The TREE_TYPE is the _TYPE node for the partial
-   specialization.
+   S<T*, int>' this will be `T*, int'.)  The arguments will also include
+   any outer template arguments.  The TREE_VALUE holds the TEMPLATE_DECL
+   for the partial specialization.  The TREE_TYPE is the _TYPE node for
+   the partial specialization.
 
    This list is not used for other templates.  */
 #define DECL_TEMPLATE_SPECIALIZATIONS(NODE)     \
@@ -3801,9 +3800,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define SET_DECL_SELF_REFERENCE_P(NODE) \
   (DECL_LANG_FLAG_4 (NODE) = 1)
 
-/* A `primary' template is one that has its own template header.  A
-   member function of a class template is a template, but not primary.
-   A member template is primary.  Friend templates are primary, too.  */
+/* A `primary' template is one that has its own template header and is not
+   a partial specialization.  A member function of a class template is a
+   template, but not primary.  A member template is primary.  Friend
+   templates are primary, too.  */
 
 /* Returns the primary template corresponding to these parameters.  */
 #define DECL_PRIMARY_TEMPLATE(NODE) \
index 517f05b3f42144bd528a76d0d8904e143dad29be..97efdc99b1a86255a1cf185f33e84e853450dd59 100644 (file)
@@ -4246,8 +4246,16 @@ process_partial_specialization (tree decl)
   /* We should only get here once.  */
   gcc_assert (!COMPLETE_TYPE_P (type));
 
+  tree tmpl = build_template_decl (decl, current_template_parms,
+                                  DECL_MEMBER_TEMPLATE_P (maintmpl));
+  TREE_TYPE (tmpl) = type;
+  DECL_TEMPLATE_RESULT (tmpl) = decl;
+  SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
+  DECL_TEMPLATE_INFO (tmpl) = build_template_info (maintmpl, specargs);
+  DECL_PRIMARY_TEMPLATE (tmpl) = maintmpl;
+
   DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
-    = tree_cons (specargs, inner_parms,
+    = tree_cons (specargs, tmpl,
                  DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
   TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
 
@@ -10058,7 +10066,10 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
              RETURN (error_mark_node);
 
            TREE_TYPE (r) = new_type;
-           CLASSTYPE_TI_TEMPLATE (new_type) = r;
+           /* For a partial specialization, we need to keep pointing to
+              the primary template.  */
+           if (!DECL_TEMPLATE_SPECIALIZATION (t))
+             CLASSTYPE_TI_TEMPLATE (new_type) = r;
            DECL_TEMPLATE_RESULT (r) = TYPE_MAIN_DECL (new_type);
            DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
            DECL_CONTEXT (r) = TYPE_CONTEXT (new_type);
@@ -18080,7 +18091,8 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
     {
       tree partial_spec_args;
       tree spec_args;
-      tree parms = TREE_VALUE (t);
+      tree spec_tmpl = TREE_VALUE (t);
+      tree orig_parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl);
 
       partial_spec_args = CLASSTYPE_TI_ARGS (TREE_TYPE (t));
 
@@ -18088,24 +18100,14 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
 
       if (outer_args)
        {
-         int i;
-
          /* Discard the outer levels of args, and then substitute in the
             template args from the enclosing class.  */
          partial_spec_args = INNERMOST_TEMPLATE_ARGS (partial_spec_args);
          partial_spec_args = tsubst_template_args
            (partial_spec_args, outer_args, tf_none, NULL_TREE);
 
-         /* PARMS already refers to just the innermost parms, but the
-            template parms in partial_spec_args had their levels lowered
-            by tsubst, so we need to do the same for the parm list.  We
-            can't just tsubst the TREE_VEC itself, as tsubst wants to
-            treat a TREE_VEC as an argument vector.  */
-         parms = copy_node (parms);
-         for (i = TREE_VEC_LENGTH (parms) - 1; i >= 0; --i)
-           TREE_VEC_ELT (parms, i) =
-             tsubst (TREE_VEC_ELT (parms, i), outer_args, tf_none, NULL_TREE);
-
+         /* And the same for the partial specialization TEMPLATE_DECL.  */
+         spec_tmpl = tsubst (spec_tmpl, outer_args, tf_none, NULL_TREE);
        }
 
       partial_spec_args =
@@ -18120,7 +18122,10 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
 
       if (partial_spec_args == error_mark_node)
        return error_mark_node;
+      if (spec_tmpl == error_mark_node)
+       return error_mark_node;
 
+      tree parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl);
       spec_args = get_class_bindings (tmpl, parms,
                                      partial_spec_args,
                                      args);
@@ -18128,7 +18133,7 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain)
        {
          if (outer_args)
            spec_args = add_to_template_args (outer_args, spec_args);
-         list = tree_cons (spec_args, TREE_VALUE (t), list);
+         list = tree_cons (spec_args, orig_parms, list);
          TREE_TYPE (list) = TREE_TYPE (t);
        }
     }