pt.c (complete_template_args): Rewrite.
authorJason Merrill <jason@gcc.gnu.org>
Fri, 20 Mar 1998 10:44:06 +0000 (05:44 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 20 Mar 1998 10:44:06 +0000 (05:44 -0500)
* pt.c (complete_template_args): Rewrite.
(tsubst, FUNCTION_DECL): Use it.
* semantics.c (finish_asm_stmt): Fix combine strings. Call
c_expand_asm_operands () if output_operands, input_operands or
clobbers is not NULL_TREE.
* pt.c (complete_template_args): New function.
(get_bindings): Deal with specializations of function templates
with return type containing parameters from outer class
templates.
(tsubst, TEMPLATE_TEMPLATE_PARM): When reducing parameter level,
substitute arguments and compose a new type.

From-SVN: r18724

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/cp/semantics.c

index 5c41abc7b246eed2cf328d0490e13037ad0a56bb..6c7d567addde5068a91594c04e3114ccf38d626e 100644 (file)
@@ -1,3 +1,23 @@
+Fri Mar 20 10:42:07 1998  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * pt.c (complete_template_args): Rewrite.
+       (tsubst, FUNCTION_DECL): Use it.
+
+Fri Mar 20 08:12:43 1998  H.J. Lu  (hjl@gnu.org)
+
+       * semantics.c (finish_asm_stmt): Fix combine strings. Call
+       c_expand_asm_operands () if output_operands, input_operands or
+       clobbers is not NULL_TREE.
+
+Fri Mar 20 00:10:19 1998  Kriang Lerdsuwanakij  <lerdsuwa@scf.usc.edu>
+
+       * pt.c (complete_template_args): New function.
+       (get_bindings): Deal with specializations of function templates
+       with return type containing parameters from outer class 
+       templates.
+       (tsubst, TEMPLATE_TEMPLATE_PARM): When reducing parameter level,
+       substitute arguments and compose a new type.
+
 Thu Mar 19 19:01:48 1998  Mark Mitchell  <mmitchell@usa.net>
 
        * pt.c (tsubst): Clear DECL_PENDING_INLINE_INFO for new
index 6102bead6ca3deca7cdc0e30dc5145ed96c5a5d2..d372e11e3a1ffa48965296fd09da9279fbe0fc47 100644 (file)
@@ -81,6 +81,7 @@ static tree get_class_bindings PROTO((tree, tree, tree, tree));
 static tree coerce_template_parms PROTO((tree, tree, tree, int, int, int));
 static tree tsubst_enum        PROTO((tree, tree, tree *));
 static tree add_to_template_args PROTO((tree, tree));
+static tree complete_template_args PROTO((tree, tree, int));
 static int  type_unification_real PROTO((tree, tree *, tree, tree,
                                         int, int, int));
 static void note_template_header PROTO((int));
@@ -340,6 +341,103 @@ is_member_template (t)
   return 0;
 }
 
+/* Return a new template argument vector which contains all of ARGS
+   for all outer templates TYPE is contained in, but has as its 
+   innermost set of arguments the EXTRA_ARGS.  If UNBOUND_ONLY, we
+   are only interested in unbound template arguments, not arguments from
+   enclosing templates that have been instantiated already.  */
+
+static tree
+complete_template_args (tmpl, extra_args, unbound_only)
+     tree tmpl, extra_args;
+     int unbound_only;
+{
+  /* depth is the number of levels of enclosing args we're adding.  */
+  int depth, i;
+  tree args, new_args, spec_args = NULL_TREE;
+  
+  my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
+  my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0);
+
+  if (DECL_TEMPLATE_INFO (tmpl) && !unbound_only)
+    {
+      /* A specialization of a member template of a template class shows up
+        as a TEMPLATE_DECL with DECL_TEMPLATE_SPECIALIZATION set.
+        DECL_TI_ARGS is the specialization args, and DECL_TI_TEMPLATE
+        is the template being specialized.  */
+      if (DECL_TEMPLATE_SPECIALIZATION (tmpl))
+       {
+         spec_args = DECL_TI_ARGS (tmpl);
+         tmpl = DECL_TI_TEMPLATE (tmpl);
+       }
+
+      if (DECL_TEMPLATE_INFO (tmpl))
+       {
+         /* A partial instantiation of a member template shows up as a
+            TEMPLATE_DECL with DECL_TEMPLATE_INFO.  DECL_TI_ARGS is
+            all the bound template arguments.  */
+         args = DECL_TI_ARGS (tmpl);
+         if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
+           depth = 1;
+         else
+           depth = TREE_VEC_LENGTH (args);
+       }
+      else
+       /* If we are a specialization, we might have no previously bound
+          template args.  */
+       depth = 0;
+
+      new_args = make_tree_vec (depth + 1 + (!!spec_args));
+
+      if (depth == 1)
+       TREE_VEC_ELT (new_args, 0) = args;
+      else
+       for (i = 0; i < depth; ++i)
+         TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i);
+    }
+  else
+    {
+      tree type;
+      int skip;
+
+      /* For unbound args, we have to do more work.  We are getting bindings
+        for the innermost args from extra_args, so we start from our
+        context and work out until we've seen all the args.  We need to
+        do it this way to handle partial specialization.  */
+
+      depth = list_length (DECL_TEMPLATE_PARMS (tmpl)) - 1;
+      if (depth == 0)
+       return extra_args;
+
+      new_args = make_tree_vec (depth + 1);
+
+      if (! is_member_template (tmpl))
+       /* If this isn't a member template, extra_args is for the innermost
+          template class, so skip over it.  */
+       skip = 1;
+
+      type = DECL_REAL_CONTEXT (tmpl);
+      for (i = depth; i; type = TYPE_CONTEXT (type))
+       if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type)))
+         {
+           if (skip)
+             skip = 0;
+           else
+             {
+               --i;
+               TREE_VEC_ELT (new_args, i) = CLASSTYPE_TI_ARGS (type);
+             }
+         }
+    }
+
+  TREE_VEC_ELT (new_args, depth) = extra_args;
+
+  if (spec_args)
+    TREE_VEC_ELT (new_args, depth + 1) = spec_args;
+
+  return new_args;
+}
+
 /* Return a new template argument vector which contains all of ARGS,
    but has as its innermost set of arguments the EXTRA_ARGS.  */
 
@@ -3591,7 +3689,20 @@ tsubst (t, args, in_decl)
          {
          case TEMPLATE_TYPE_PARM:
          case TEMPLATE_TEMPLATE_PARM:
-           r = copy_node (t);
+
+           if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
+               && CLASSTYPE_TEMPLATE_INFO (t))
+             {
+               tree argvec = tsubst (CLASSTYPE_TI_ARGS (t),
+                                     args, in_decl);
+               r = lookup_template_class (TYPE_NAME (t), argvec, in_decl, 
+                                          DECL_CONTEXT (TYPE_NAME (t)));
+               r = cp_build_type_variant (r, TYPE_READONLY (t),
+                                          TYPE_VOLATILE (t));
+             }
+           else
+             r = copy_node (t);
+
            TEMPLATE_TYPE_PARM_INDEX (r)
              = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
                                            r, levels);
@@ -3804,21 +3915,8 @@ tsubst (t, args, in_decl)
            /* Start by getting the innermost args.  */
            argvec = tsubst (DECL_TI_ARGS (t), args, in_decl);
 
-           /* If tmpl is an instantiation of a member template, tack on
-              the args for the enclosing class.  NOTE: this will change
-              for member class templates.  The generalized procedure
-              is to grab the outer args, then tack on the current args,
-              then any specialized args.  */
-           if (DECL_TEMPLATE_INFO (tmpl) && DECL_TI_ARGS (tmpl))
-             {
-               if (!DECL_TEMPLATE_SPECIALIZATION (tmpl))
-                 argvec = add_to_template_args (DECL_TI_ARGS (tmpl), argvec);
-               else
-                 /* In this case, we are instantiating a
-                    specialization.  The innermost template args are
-                    already given by the specialization.  */
-                 argvec = add_to_template_args (argvec, DECL_TI_ARGS (tmpl));
-             }
+           if (DECL_TEMPLATE_INFO (tmpl))
+             argvec = complete_template_args (tmpl, argvec, 0);
 
            /* Do we already have this instantiation?  */
            spec = retrieve_specialization (tmpl, argvec);
@@ -5701,7 +5799,9 @@ get_bindings_real (fn, decl, explicit_args, check_rettype)
   if (check_rettype)
     {
       /* Check to see that the resulting return type is also OK.  */
-      tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)), targs, NULL_TREE);
+      tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)),
+                      complete_template_args (fn, targs, 1),
+                      NULL_TREE);
 
       if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1))
        return NULL_TREE;
index f30224669554a80a94761bcfa581db378905906f..79f503863141b4802e346b5ad03996381ed4ea64 100644 (file)
@@ -709,7 +709,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
      tree clobbers;
 {
   if (TREE_CHAIN (string))
-    combine_strings (string);
+    string = combine_strings (string);
 
   if (processing_template_decl)
     {
@@ -721,7 +721,8 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
   else
     {
       emit_line_note (input_filename, lineno);
-      if (output_operands != NULL_TREE)
+      if (output_operands != NULL_TREE || input_operands != NULL_TREE
+         || clobbers != NULL_TREE)
        {
          if (cv_qualifier != NULL_TREE
              && cv_qualifier != ridpointers[(int) RID_VOLATILE])