]> gcc.gnu.org Git - gcc.git/commitdiff
cp-tree.h (hash_tree_cons_simple): New macro.
authorMark Mitchell <mark@markmitchell.com>
Fri, 4 Sep 1998 11:31:30 +0000 (11:31 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 4 Sep 1998 11:31:30 +0000 (11:31 +0000)
* cp-tree.h (hash_tree_cons_simple): New macro.
* pt.c (tsubst_arg_types): New function.  Use hash_tree_cons.
(coerce_template_parms): Use make_temp_vec, instead of
make_tree_vec.  Document this behavior.
(lookup_template_class): Likewise.
(tsubst, cases METHOD_TYPE, FUNCTION_TYPE): Use tsubst_arg_types.
Remove dead code (and add ssertion to check its deadness).  Fix
bug w.r.t. exception specifications.

From-SVN: r22233

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/testsuite/g++.old-deja/g++.eh/tmpl1.C [new file with mode: 0644]

index 656af650508fe986371622c157ed449c769294de..1138e872fb7da7a67ee28dc10edb5223c7e5e4ec 100644 (file)
@@ -1,3 +1,14 @@
+1998-09-04  Mark Mitchell  <mark@markmitchell.com>
+
+       * cp-tree.h (hash_tree_cons_simple): New macro.
+       * pt.c (tsubst_arg_types): New function.  Use hash_tree_cons.
+       (coerce_template_parms): Use make_temp_vec, instead of
+       make_tree_vec.  Document this behavior.
+       (lookup_template_class): Likewise.
+       (tsubst, cases METHOD_TYPE, FUNCTION_TYPE): Use tsubst_arg_types.  
+       Remove dead code (and add ssertion to check its deadness).  Fix
+       bug w.r.t. exception specifications.
+
 1998-09-03  Jason Merrill  <jason@yorick.cygnus.com>
 
        * decl2.c (import_export_vtable): Always make artificials comdat.
index ebd0686db2c3218461e3d09e28d93fb1cb954083..8bf6c5c86216ff2d3f3ee36ef9bebb9a1411ca6d 100644 (file)
@@ -3040,6 +3040,8 @@ extern void push_expression_obstack               PROTO((void));
 #define build_scratch_list build_expr_list
 #define make_scratch_vec make_temp_vec
 #define push_scratch_obstack push_expression_obstack
+#define hash_tree_cons_simple(PURPOSE, VALUE, CHAIN) \
+  hash_tree_cons (0, 0, 0, (PURPOSE), (VALUE), (CHAIN))
 
 /* in typeck.c */
 extern tree condition_conversion               PROTO((tree));
index d2251e8282fd8af3a257d07a60db0a8f37d64b84..b27621b89d0206a34f993a84834b6e39edfe1f4b 100644 (file)
@@ -126,6 +126,7 @@ static void set_mangled_name_for_template_decl PROTO((tree));
 static int template_class_depth_real PROTO((tree, int));
 static tree tsubst_aggr_type PROTO((tree, tree, tree, int));
 static tree tsubst_decl PROTO((tree, tree, tree, tree));
+static tree tsubst_arg_types PROTO((tree, tree, tree));
 
 /* We use TREE_VECs to hold template arguments.  If there is only one
    level of template arguments, then the TREE_VEC contains the
@@ -2802,7 +2803,10 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
    If REQUIRE_ALL_ARGUMENTS is non-zero, all arguments must be
    provided in ARGLIST, or else trailing parameters must have default
    values.  If REQUIRE_ALL_ARGUMENTS is zero, we will attempt argument
-   deduction for any unspecified trailing arguments.  */
+   deduction for any unspecified trailing arguments.  
+
+   The resulting TREE_VEC is allocated on a temporary obstack, and
+   must be explicitly copied if it will be permanent.  */
    
 static tree
 coerce_template_parms (parms, args, in_decl,
@@ -2839,7 +2843,7 @@ coerce_template_parms (parms, args, in_decl,
       return error_mark_node;
     }
 
-  new_inner_args = make_tree_vec (nparms);
+  new_inner_args = make_temp_vec (nparms);
   new_args = add_outermost_template_args (args, new_inner_args);
   for (i = 0; i < nparms; i++)
     {
@@ -3300,7 +3304,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
          int i;
          int saved_depth = TMPL_ARGS_DEPTH (arglist);
 
-         tree bound_args = make_tree_vec (parm_depth);
+         tree bound_args = make_temp_vec (parm_depth);
          
          for (i = saved_depth,
                 t = DECL_TEMPLATE_PARMS (template); 
@@ -5191,6 +5195,38 @@ tsubst_decl (t, args, type, in_decl)
 }
 
 
+/* Substitue into the ARG_TYPES of a function type.  */
+
+tree
+tsubst_arg_types (arg_types, args, in_decl)
+     tree arg_types;
+     tree args;
+     tree in_decl;
+{
+  tree remaining_arg_types;
+  tree result;
+  tree type;
+
+  if (!arg_types || arg_types == void_list_node)
+    return arg_types;
+  
+  remaining_arg_types = tsubst_arg_types (TREE_CHAIN (arg_types),
+                                         args, in_decl);
+
+  /* We use TYPE_MAIN_VARIANT is because top-level qualifiers don't
+     matter on function types.  */
+  type = TYPE_MAIN_VARIANT (type_decays_to 
+                           (tsubst (TREE_VALUE (arg_types),
+                                    args, in_decl)));
+
+  /* Note that we do not substitute into default arguments here.  The
+     standard mandates that they be instantiated only when needed,
+     which is done in build_over_call.  */
+  return hash_tree_cons_simple (TREE_PURPOSE (arg_types), type,
+                               remaining_arg_types);
+                        
+}
+
 /* Take the tree structure T and replace template parameters used therein
    with the argument vector ARGS.  IN_DECL is an associated decl for
    diagnostics.
@@ -5495,83 +5531,31 @@ tsubst (t, args, in_decl)
     case FUNCTION_TYPE:
     case METHOD_TYPE:
       {
-       tree values = TYPE_ARG_TYPES (t);
-       tree context = TYPE_CONTEXT (t);
-       tree raises = TYPE_RAISES_EXCEPTIONS (t);
+       tree arg_types;
+       tree raises;
        tree fntype;
 
-       /* Don't bother recursing if we know it won't change anything.  */
-       if (values != void_list_node)
-         {
-           /* This should probably be rewritten to use hash_tree_cons for
-               the memory savings.  */
-           tree first = NULL_TREE;
-           tree last = NULL_TREE;
-
-           for (; values && values != void_list_node;
-                values = TREE_CHAIN (values))
-             {
-               tree value = TYPE_MAIN_VARIANT (type_decays_to
-                 (tsubst (TREE_VALUE (values), args, in_decl)));
-               /* Don't instantiate default args unless they are used.
-                  Handle it in build_over_call instead.  */
-               tree purpose = TREE_PURPOSE (values);
-               tree x = build_tree_list (purpose, value);
-
-               if (first)
-                 TREE_CHAIN (last) = x;
-               else
-                 first = x;
-               last = x;
-             }
-
-           if (values == void_list_node)
-             TREE_CHAIN (last) = void_list_node;
-
-           values = first;
-         }
-       if (context)
-         context = tsubst (context, args, in_decl);
-       /* Could also optimize cases where return value and
-          values have common elements (e.g., T min(const &T, const T&).  */
-
-       /* If the above parameters haven't changed, just return the type.  */
-       if (type == TREE_TYPE (t)
-           && values == TYPE_VALUES (t)
-           && context == TYPE_CONTEXT (t))
-         return t;
+       /* The TYPE_CONTEXT is not used for function/method types.  */
+       my_friendly_assert (TYPE_CONTEXT (t) == NULL_TREE, 0);
+       
+       /* Substitue the argument types.  */
+       arg_types = tsubst_arg_types (TYPE_ARG_TYPES (t), args, in_decl);
 
        /* Construct a new type node and return it.  */
-       if (TREE_CODE (t) == FUNCTION_TYPE
-           && context == NULL_TREE)
-         {
-           fntype = build_function_type (type, values);
-         }
-       else if (context == NULL_TREE)
-         {
-           tree base = tsubst (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))),
-                               args, in_decl);
-           fntype = build_cplus_method_type (base, type,
-                                             TREE_CHAIN (values));
-         }
-       else
-         {
-           fntype = make_node (TREE_CODE (t));
-           TREE_TYPE (fntype) = type;
-           TYPE_CONTEXT (fntype) = FROB_CONTEXT (context);
-           TYPE_VALUES (fntype) = values;
-           TYPE_SIZE (fntype) = TYPE_SIZE (t);
-           TYPE_ALIGN (fntype) = TYPE_ALIGN (t);
-           TYPE_MODE (fntype) = TYPE_MODE (t);
-           if (TYPE_METHOD_BASETYPE (t))
-             TYPE_METHOD_BASETYPE (fntype) = tsubst (TYPE_METHOD_BASETYPE (t),
-                                                     args, in_decl);
-           /* Need to generate hash value.  */
-           my_friendly_abort (84);
-         }
+       if (TREE_CODE (t) == FUNCTION_TYPE)
+         fntype = build_function_type (type, arg_types);
+       else 
+         fntype 
+           = build_cplus_method_type (TREE_TYPE (TREE_VALUE (arg_types)),
+                                      type,
+                                      TREE_CHAIN (arg_types));
+
        fntype = build_type_variant (fntype,
                                     TYPE_READONLY (t),
                                     TYPE_VOLATILE (t));
+
+       /* Substitue the exception specification. */
+       raises = TYPE_RAISES_EXCEPTIONS (t);
        if (raises)
          {
            raises = tsubst (raises, args, in_decl);
diff --git a/gcc/testsuite/g++.old-deja/g++.eh/tmpl1.C b/gcc/testsuite/g++.old-deja/g++.eh/tmpl1.C
new file mode 100644 (file)
index 0000000..cdbd6e1
--- /dev/null
@@ -0,0 +1,15 @@
+template <class T>
+void f() throw (T)
+{
+  throw 7;
+}
+
+
+int main()
+{
+  try {
+    f<int>();
+  } catch (...) {
+    return 0;
+  }
+}
This page took 0.103048 seconds and 5 git commands to generate.