decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it uses template parameters.
authorMark Mitchell <mark@markmitchell.com>
Tue, 4 Aug 1998 11:46:41 +0000 (11:46 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 4 Aug 1998 11:46:41 +0000 (11:46 +0000)
* decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it
uses template parameters.
* method.c (build_template_parm_names): Use the full set of
template arguments for tsubst'ing.
(build_overload_identifier): Pass the full set of template
arguments to build_template_parm_names, not just the
innermost_args.
* pt.c (TMPL_ARGS_DEPTH): Define using
TMPL_ARGS_HAVE_MULTIPLE_LEVELS, for clarity.
(NUM_TMPL_ARGS): New macro.
(add_outermost_template_args): Deal with the case where the outer
args will be completely discarded.
(coerce_template_parms): Use the full set of template arguments
for tsubst'ing.  Simplify.  Add some asserts.  Improve
error messages.
(lookup_template_class): Pass the full set of template arguments
to coerce_template_parms.
(tsubst): Add assertion.
(do_type_instantiation): Don't instantiate member template
classes.
* init.c (build_offset_ref): Deal with a TEMPLATE_ID_EXPR whose
name is a LOOKUP_EXPR, rather than an IDENTIFIER_NODE.

From-SVN: r21609

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/pt.c
gcc/testsuite/g++.old-deja/g++.pt/crash18.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/memclass16.C [new file with mode: 0644]

index 2d2e7dc6be6e8d5697ee06f9cf25d10218df07f8..12218d8ae80da7a3300f35c8f2e96a143693ac56 100644 (file)
@@ -1,3 +1,29 @@
+1998-08-04  Mark Mitchell  <mark@markmitchell.com>
+
+       * decl.c (pushtag): Don't mangle the name of a TYPE_DECL if it
+       uses template parameters.
+       * method.c (build_template_parm_names): Use the full set of
+       template arguments for tsubst'ing.
+       (build_overload_identifier): Pass the full set of template
+       arguments to build_template_parm_names, not just the
+       innermost_args. 
+       * pt.c (TMPL_ARGS_DEPTH): Define using
+       TMPL_ARGS_HAVE_MULTIPLE_LEVELS, for clarity.
+       (NUM_TMPL_ARGS): New macro.
+       (add_outermost_template_args): Deal with the case where the outer
+       args will be completely discarded.
+       (coerce_template_parms): Use the full set of template arguments
+       for tsubst'ing.  Simplify.  Add some asserts.  Improve
+       error messages.
+       (lookup_template_class): Pass the full set of template arguments
+       to coerce_template_parms.
+       (tsubst): Add assertion.
+       (do_type_instantiation): Don't instantiate member template
+       classes. 
+       
+       * init.c (build_offset_ref): Deal with a TEMPLATE_ID_EXPR whose
+       name is a LOOKUP_EXPR, rather than an IDENTIFIER_NODE.
+
 1998-08-03  Jason Merrill  <jason@yorick.cygnus.com>
 
        * method.c (set_mangled_name_for_decl): Change return type to void.
index 68419056fb792b4259b3b6105691a0a209d5bf5f..699170a0c9235ecf47245ee93e03e259d4ed6509 100644 (file)
@@ -2396,8 +2396,9 @@ pushtag (name, type, globalize)
 
              TYPE_CONTEXT (type) = DECL_CONTEXT (d);
              DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
-             DECL_ASSEMBLER_NAME (d)
-               = get_identifier (build_overload_name (type, 1, 1));
+             if (!uses_template_parms (type))
+               DECL_ASSEMBLER_NAME (d)
+                 = get_identifier (build_overload_name (type, 1, 1));
            }
         }
       if (b->parm_flag == 2)
index 5975320d31f2300a6ffae873fe4af3819f14a4d2..78b6c5d8cbadf3d7acd131981f6d0f0d860664cc 100644 (file)
@@ -1547,6 +1547,11 @@ build_offset_ref (type, name)
         part, we treat this just like a.f.  We do remember, however,
         the template-id that was used.  */
       name = TREE_OPERAND (orig_name, 0);
+
+      if (TREE_CODE (name) == LOOKUP_EXPR)
+       /* This can happen during tsubst'ing.  */
+       name = TREE_OPERAND (name, 0);
+
       my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
     }
 
index 69ba1b02ea903e3a89db2308effec2b2cc21f3e8..16ecbf2d7daf7e1b4ba5de1de486d1553541ab26 100644 (file)
@@ -862,13 +862,14 @@ build_template_parm_names (parmlist, arglist)
      tree arglist;
 {
   int i, nparms;
-  
+  tree inner_args = innermost_args (arglist);
+
   nparms = TREE_VEC_LENGTH (parmlist);
   icat (nparms);
   for (i = 0; i < nparms; i++)
     {
       tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
-      tree arg = TREE_VEC_ELT (arglist, i);
+      tree arg = TREE_VEC_ELT (inner_args, i);
       if (TREE_CODE (parm) == TYPE_DECL)
        {
          /* This parameter is a type.  */
@@ -919,9 +920,8 @@ build_overload_identifier (name)
     {
       /* NAME is the TYPE_DECL for a template specialization.  */
       tree template, parmlist, arglist, tname;
-      template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
-      arglist = innermost_args (TREE_VALUE (template));
-      template = TREE_PURPOSE (template);
+      template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (name));
+      arglist = CLASSTYPE_TI_ARGS (TREE_TYPE (name));
       tname = DECL_NAME (template);
       parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
       OB_PUTC ('t');
index 3906eb38d992f9113cd8afc4fbd4cc8f817ff26a..6775575cb596fcd2918db31d71ac118b907bd9c0 100644 (file)
@@ -135,19 +135,6 @@ static int template_class_depth_real PROTO((tree, int));
    only one level of arguments, but which is a TREE_VEC containing as
    its only entry the TREE_VEC for that level.  */
 
-/* The depth of a template argument vector.  When called directly by
-   the parser, we use a TREE_LIST rather than a TREE_VEC to represent
-   template arguments.  In fact, we may even see NULL_TREE if there
-   are no template arguments.  In both of those cases, there is only
-   one level of template arguments.  */
-#define TMPL_ARGS_DEPTH(NODE)                                  \
-  ((NODE != NULL_TREE                                          \
-    && TREE_CODE (NODE) == TREE_VEC                            \
-    && TREE_VEC_LENGTH (NODE) > 0                              \
-    && TREE_VEC_ELT (NODE, 0) != NULL_TREE                     \
-    && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC) ?       \
-   TREE_VEC_LENGTH (NODE) : 1)
-
 /* Non-zero if the template arguments is actually a vector of vectors,
    rather than just a vector.  */
 #define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
@@ -157,6 +144,14 @@ static int template_class_depth_real PROTO((tree, int));
    && TREE_VEC_ELT (NODE, 0) != NULL_TREE                      \
    && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC)
 
+/* The depth of a template argument vector.  When called directly by
+   the parser, we use a TREE_LIST rather than a TREE_VEC to represent
+   template arguments.  In fact, we may even see NULL_TREE if there
+   are no template arguments.  In both of those cases, there is only
+   one level of template arguments.  */
+#define TMPL_ARGS_DEPTH(NODE)                                  \
+  (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1)
+
 /* The LEVELth level of the template ARGS.  Note that template
    parameter levels are indexed from 1, not from 0.  */
 #define TMPL_ARGS_LEVEL(ARGS, LEVEL)           \
@@ -177,6 +172,13 @@ static int template_class_depth_real PROTO((tree, int));
 #define SET_TMPL_ARG(ARGS, LEVEL, IDX, VAL)                    \
   (TREE_VEC_ELT (TREE_VEC_ELT ((ARGS), (LEVEL) - 1), (IDX)) = (VAL))
 
+/* Given a single level of template arguments in NODE, return the
+   number of arguments.  */
+#define NUM_TMPL_ARGS(NODE)                            \
+  ((NODE) == NULL_TREE ? 0                             \
+   : (TREE_CODE (NODE) == TREE_VEC                     \
+      ? TREE_VEC_LENGTH (NODE) : list_length (NODE)))
+
 /* The number of levels of template parameters given by NODE.  */
 #define TMPL_PARMS_DEPTH(NODE) \
   (TREE_INT_CST_HIGH (TREE_PURPOSE (NODE)))
@@ -506,6 +508,16 @@ add_outermost_template_args (args, extra_args)
 {
   tree new_args;
 
+  /* If there are more levels of EXTRA_ARGS than there are ARGS,
+     something very fishy is going on.  */
+  my_friendly_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),
+                     0);
+
+  /* If *all* the new arguments will be the EXTRA_ARGS, just return
+     them.  */
+  if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH (extra_args))
+    return extra_args;
+
   /* For the moment, we make ARGS look like it contains fewer levels.  */
   TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args);
   
@@ -2545,15 +2557,11 @@ coerce_template_parms (parms, arglist, in_decl,
      int require_all_arguments;
 {
   int nparms, nargs, i, lost = 0;
-  tree vec = NULL_TREE;
-
-  if (arglist == NULL_TREE)
-    nargs = 0;
-  else if (TREE_CODE (arglist) == TREE_VEC)
-    nargs = TREE_VEC_LENGTH (arglist);
-  else
-    nargs = list_length (arglist);
+  tree inner_args;
+  tree vec;
 
+  inner_args = innermost_args (arglist);
+  nargs = NUM_TMPL_ARGS (inner_args);
   nparms = TREE_VEC_LENGTH (parms);
 
   if (nargs > nparms
@@ -2563,22 +2571,42 @@ coerce_template_parms (parms, arglist, in_decl,
     {
       if (complain) 
        {
-         error ("incorrect number of parameters (%d, should be %d)",
-                nargs, nparms);
+         cp_error ("wrong number of template arguments (%d, should be %d)",
+                   nargs, nparms);
          
          if (in_decl)
-           cp_error_at ("in template expansion for decl `%D'",
-                        in_decl);
+           cp_error_at ("provided for `%D'", in_decl);
        }
 
       return error_mark_node;
     }
 
-  if (arglist && TREE_CODE (arglist) == TREE_VEC && nargs == nparms)
-    vec = copy_node (arglist);
+  /* Create in VEC the appropriate innermost arguments, and reset
+     ARGLIST to contain the complete set of arguments.  */
+  if (inner_args && TREE_CODE (inner_args) == TREE_VEC && nargs == nparms)
+    {
+      /* If we already have all the arguments, we can just use them.
+        This is an optimization over the code in the `else' branch
+        below, and should be functionally identicial.  */
+      vec = copy_node (inner_args);
+      arglist = add_outermost_template_args (arglist, vec);
+    }
   else
     {
+      /* If we don't already have all the arguments we must get what
+        we can from default template arguments.  The tricky bit is
+        that previous arguments can influence the default values,
+        e.g.:  
+
+          template <class T, class U = T> void foo();
+
+        If we see `foo<int>' we have to come up with an {int, int}
+        vector.  */
+
+      tree new_arglist;
+
       vec = make_tree_vec (nparms);
+      new_arglist = add_outermost_template_args (arglist, vec);
 
       for (i = 0; i < nparms; i++)
        {
@@ -2597,23 +2625,33 @@ coerce_template_parms (parms, arglist, in_decl,
            }
          else if (i < nargs)
            {
-             arg = TREE_VEC_ELT (arglist, i);
+             arg = TREE_VEC_ELT (inner_args, i);
              if (arg == error_mark_node)
                lost++;
            }
+         /* If no template argument was supplied, look for a default
+            value.  */
          else if (TREE_PURPOSE (parm) == NULL_TREE)
            {
+             /* There was no default value.  */
              my_friendly_assert (!require_all_arguments, 0);
              break;
            }
          else if (TREE_CODE (TREE_VALUE (parm)) == TYPE_DECL)
-           arg = tsubst (TREE_PURPOSE (parm), vec, in_decl);
+           arg = tsubst (TREE_PURPOSE (parm), new_arglist, in_decl);
          else
-           arg = tsubst_expr (TREE_PURPOSE (parm), vec, in_decl);
+           arg = tsubst_expr (TREE_PURPOSE (parm), new_arglist, in_decl);
 
          TREE_VEC_ELT (vec, i) = arg;
        }
+
+      /* We've left ARGLIST intact up to this point, in order to allow
+        iteration through it in the case that it was a TREE_LIST, but
+        from here on it should contain the full set of template
+        arguments.  */
+      arglist = new_arglist;
     }
+
   for (i = 0; i < nparms; i++)
     {
       tree arg = TREE_VEC_ELT (vec, i);
@@ -2772,7 +2810,7 @@ coerce_template_parms (parms, arglist, in_decl,
        }
       else
        {
-         tree t = tsubst (TREE_TYPE (parm), vec, in_decl);
+         tree t = tsubst (TREE_TYPE (parm), arglist, in_decl);
 
          if (processing_template_decl)
            arg = maybe_fold_nontype_arg (arg);
@@ -3205,17 +3243,29 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
        {
          /* We have multiple levels of arguments to coerce, at once.  */
          int i;
+         int saved_depth = TMPL_ARGS_DEPTH (arglist);
 
          tree bound_args = make_tree_vec (parm_depth);
          
-         for (i = TREE_VEC_LENGTH (arglist) - 1, 
+         for (i = saved_depth,
                 t = DECL_TEMPLATE_PARMS (template); 
-              i >= 0 && t != NULL_TREE;
+              i > 0 && t != NULL_TREE;
               --i, t = TREE_CHAIN (t))
-           TREE_VEC_ELT (bound_args, i) =
-             coerce_template_parms (TREE_VALUE (t),
-                                    TREE_VEC_ELT (arglist, i),
-                                    template, 1, 1);
+           {
+             tree a = coerce_template_parms (TREE_VALUE (t),
+                                             arglist, template, 1, 1);
+             SET_TMPL_ARGS_LEVEL (bound_args, i, a);
+
+             /* We temporarily reduce the length of the ARGLIST so
+                that coerce_template_parms will see only the arguments
+                corresponding to the template parameters it is
+                examining.  */
+             TREE_VEC_LENGTH (arglist)--;
+           }
+
+         /* Restore the ARGLIST to its full size.  */
+         TREE_VEC_LENGTH (arglist) = saved_depth;
+
          arglist = bound_args;
        }
       else
@@ -4647,9 +4697,13 @@ tsubst (t, args, in_decl)
            if (arg != NULL_TREE)
              {
                if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-                 return cp_build_type_variant
-                   (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
-                    TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
+                 {
+                   my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg))
+                                       == 't', 0);
+                   return cp_build_type_variant
+                     (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
+                      TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
+                 }
                else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
                  {
                    if (CLASSTYPE_TEMPLATE_INFO (t))
@@ -7392,8 +7446,22 @@ do_type_instantiation (t, storage)
            instantiate_decl (tmp);
        }
 
+    /* In contrast to implicit instantiation, where only the
+       declarations, and not the definitions, of members are
+       instantiated, we have here:
+
+         [temp.explicit]
+
+        The explicit instantiation of a class template specialization
+        implies the instantiation of all of its members not
+        previously explicitly specialized in the translation unit
+        containing the explicit instantiation.  
+
+       Of course, we can't instantiate member template classes, since
+       we don't have any arguments for them.  */
     for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
-      if (IS_AGGR_TYPE (TREE_VALUE (tmp)))
+      if (IS_AGGR_TYPE (TREE_VALUE (tmp))
+         && !uses_template_parms (CLASSTYPE_TI_ARGS (TREE_VALUE (tmp))))
        do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage);
   }
 }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash18.C b/gcc/testsuite/g++.old-deja/g++.pt/crash18.C
new file mode 100644 (file)
index 0000000..b12c702
--- /dev/null
@@ -0,0 +1,23 @@
+// Build don't run:
+
+template<class T>
+class foo {
+  T deft;
+
+  template<class U> int priv (U u, T t) { return u - t; }
+public:
+  foo (T t) : deft (t) {}
+
+  template<class U> int pub (U u) {
+    int (foo::*fn) (U, T);
+    fn = &foo<T>::template priv<U>;
+    return (this->*fn) (u, deft);
+  }
+};
+
+int
+main ()
+{
+  foo<long> fff (5);
+  return fff.pub (3);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memclass16.C b/gcc/testsuite/g++.old-deja/g++.pt/memclass16.C
new file mode 100644 (file)
index 0000000..e8e5643
--- /dev/null
@@ -0,0 +1,13 @@
+// Build don't link:
+
+template <class Q>
+class A {
+public:
+        typedef enum { X, Y } B;
+        template <B c> class Traits{ };
+};
+
+
+template class A<int>;
+template class A<double>::Traits<A<double>::X>;