OSDN Git Service

* cp-tree.h (finish_enum): Change prototype.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 26 Aug 1998 13:55:47 +0000 (13:55 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 26 Aug 1998 13:55:47 +0000 (13:55 +0000)
* decl.c (finish_enum): Use TYPE_VALUES, rather than taking a
VALUES parameter.  Don't try to compute mins/maxs if
processing_template_decl.
* parse.y (structsp): Use new calling sequence for finish_enum.
* pt.c (tsubst_enum): Likewise.  Take the new type as input.
(lookup_template_class): Remove unused variables.  Tweak.
Register enums on instantiation list before substituting
enumeration constants.
(tsubst_decl): Remove unused variables.
(regenerate_decl_from_template): Likewise.
* decl.c (duplicate_decls): Don't obliterate the
DECL_TEMPLATE_INFO for a template if we're not replacing it with
anything.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22004 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 78b6915..366f352 100644 (file)
@@ -1,5 +1,21 @@
 1998-08-26  Mark Mitchell  <mark@markmitchell.com>
 
+       * cp-tree.h (finish_enum): Change prototype.
+       * decl.c (finish_enum): Use TYPE_VALUES, rather than taking a
+       VALUES parameter.  Don't try to compute mins/maxs if
+       processing_template_decl. 
+       * parse.y (structsp): Use new calling sequence for finish_enum.
+       * pt.c (tsubst_enum): Likewise.  Take the new type as input.  
+       (lookup_template_class): Remove unused variables.  Tweak.
+       Register enums on instantiation list before substituting
+       enumeration constants.
+       (tsubst_decl): Remove unused variables.
+       (regenerate_decl_from_template): Likewise.
+       
+       * decl.c (duplicate_decls): Don't obliterate the
+       DECL_TEMPLATE_INFO for a template if we're not replacing it with
+       anything. 
+
        * lex.c (do_identifier): Fix typo in comment.
 
 Wed Aug 26 10:54:51 1998  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
index a22a5ad..bf91f83 100644 (file)
@@ -2562,7 +2562,7 @@ extern tree xref_tag                              PROTO((tree, tree, tree, int));
 extern tree xref_tag_from_type                 PROTO((tree, tree, int));
 extern void xref_basetypes                     PROTO((tree, tree, tree, tree));
 extern tree start_enum                         PROTO((tree));
-extern tree finish_enum                                PROTO((tree, tree));
+extern tree finish_enum                                PROTO((tree));
 extern tree build_enumerator                   PROTO((tree, tree));
 extern tree grok_enum_decls                    PROTO((tree));
 extern int start_function                      PROTO((tree, tree, tree, int));
index 0179eaf..995207d 100644 (file)
@@ -2982,7 +2982,8 @@ duplicate_decls (newdecl, olddecl)
        cp_error ("invalid redeclaration of %D", newdecl);
       TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
       DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
-      DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
+      if (DECL_TEMPLATE_INFO (newdecl))
+       DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
       DECL_TEMPLATE_SPECIALIZATIONS (olddecl) 
        = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
                   DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
@@ -11861,12 +11862,13 @@ start_enum (name)
    Returns ENUMTYPE.  */
 
 tree
-finish_enum (enumtype, values)
-     register tree enumtype, values;
+finish_enum (enumtype)
+     tree enumtype;
 {
   register tree minnode = NULL_TREE, maxnode = NULL_TREE;
   /* Calculate the maximum value of any enumerator in this type.  */
 
+  tree values = TYPE_VALUES (enumtype);
   if (values)
     {
       tree pair;
@@ -11899,12 +11901,15 @@ finish_enum (enumtype, values)
                  = build1 (NOP_EXPR, enumtype, value);
              TREE_TYPE (value) = enumtype;
 
-             if (!minnode)
-               minnode = maxnode = value;
-             else if (tree_int_cst_lt (maxnode, value))
-               maxnode = value;
-             else if (tree_int_cst_lt (value, minnode))
-               minnode = value;
+             if (!processing_template_decl)
+               {
+                 if (!minnode)
+                   minnode = maxnode = value;
+                 else if (tree_int_cst_lt (maxnode, value))
+                   maxnode = value;
+                 else if (tree_int_cst_lt (value, minnode))
+                   minnode = value;
+               }
            }
 
          /* In the list we're building up, we want the enumeration
index 9b45ea4..c9842f9 100644 (file)
@@ -2060,24 +2060,26 @@ structsp:
                { $<itype>3 = suspend_momentary ();
                  $<ttype>$ = start_enum ($2); }
          enumlist maybecomma_warn '}'
-               { $$.t = finish_enum ($<ttype>4, $5);
+               { TYPE_VALUES ($<ttype>4) = $5;
+                 $$.t = finish_enum ($<ttype>4);
                  $$.new_type_flag = 1;
                  resume_momentary ((int) $<itype>3);
                  check_for_missing_semicolon ($<ttype>4); }
        | ENUM identifier '{' '}'
-               { $$.t = finish_enum (start_enum ($2), NULL_TREE);
+               { $$.t = finish_enum (start_enum ($2));
                  $$.new_type_flag = 1;
                  check_for_missing_semicolon ($$.t); }
        | ENUM '{'
                { $<itype>2 = suspend_momentary ();
                  $<ttype>$ = start_enum (make_anon_name ()); }
          enumlist maybecomma_warn '}'
-               { $$.t = finish_enum ($<ttype>3, $4);
+                { TYPE_VALUES ($<ttype>3) = $4;
+                 $$.t = finish_enum ($<ttype>3);
                  resume_momentary ((int) $<itype>1);
                  check_for_missing_semicolon ($<ttype>3);
                  $$.new_type_flag = 1; }
        | ENUM '{' '}'
-               { $$.t = finish_enum (start_enum (make_anon_name()), NULL_TREE);
+               { $$.t = finish_enum (start_enum (make_anon_name()));
                  $$.new_type_flag = 1;
                  check_for_missing_semicolon ($$.t); }
        | ENUM identifier
index 3f9dccc..ddaf5fe 100644 (file)
@@ -85,7 +85,7 @@ static tree tsubst_expr_values PROTO((tree, tree));
 static int list_eq PROTO((tree, tree));
 static tree get_class_bindings PROTO((tree, tree, tree));
 static tree coerce_template_parms PROTO((tree, tree, tree, int, int));
-static tree tsubst_enum        PROTO((tree, tree));
+static void tsubst_enum        PROTO((tree, tree, tree));
 static tree add_to_template_args PROTO((tree, tree));
 static tree add_outermost_template_args PROTO((tree, tree));
 static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*,
@@ -3152,8 +3152,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
      int entering_scope;
 {
   tree template = NULL_TREE, parmlist;
-  char *mangled_name;
-  tree id, t;
+  tree t;
 
   if (TREE_CODE (d1) == IDENTIFIER_NODE)
     {
@@ -3242,11 +3241,14 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
     }
   else 
     {
+      extern tree current_local_enum;
       tree template_type = TREE_TYPE (template);
       tree type_decl;
       tree found = NULL_TREE;
       int arg_depth;
       int parm_depth;
+      int is_partial_instantiation;
+      tree prev_local_enum;
 
       template = most_general_template (template);
       parmlist = DECL_TEMPLATE_PARMS (template);
@@ -3398,13 +3400,20 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
         DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent.  */
       push_obstacks (&permanent_obstack, &permanent_obstack);
       
+      /* This type is a "partial instantiation" if any of the template
+        arguments still inolve template parameters.  */
+      is_partial_instantiation = uses_template_parms (arglist);
+
       /* Create the type.  */
       if (TREE_CODE (template_type) == ENUMERAL_TYPE)
        {
-         if (!uses_template_parms (arglist))
-           t = tsubst_enum (template_type, arglist);
+         if (!is_partial_instantiation)
+           {
+             prev_local_enum = current_local_enum;
+             t = start_enum (TYPE_IDENTIFIER (template_type));
+           }
          else
-           /* We don't want to call tsubst_enum for this type, since
+           /* We don't want to call start_enum for this type, since
               the values for the enumeration constants may involve
               template parameters.  And, no one should be interested
               in the enumeration constants for such a type.  */
@@ -3439,22 +3448,37 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
       else
        type_decl = TYPE_NAME (t);
 
-      /* We're done with the permanent obstack, now.  */
-      pop_obstacks ();
-
       /* Set up the template information.  */
       arglist = copy_to_permanent (arglist);
       SET_TYPE_TEMPLATE_INFO (t,
-                             perm_tree_cons (template, arglist, NULL_TREE));
-      DECL_TEMPLATE_INSTANTIATIONS (template) = perm_tree_cons
-       (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (template));
+                             tree_cons (template, arglist, NULL_TREE));
+      DECL_TEMPLATE_INSTANTIATIONS (template) 
+       = tree_cons (arglist, t, 
+                    DECL_TEMPLATE_INSTANTIATIONS (template));
+
+      if (TREE_CODE (t) == ENUMERAL_TYPE 
+         && !is_partial_instantiation)
+       {
+         /* Now that the type has been registered on the
+            instantiations list, we set up the enumerators.  Because
+            the enumeration constants may involve the enumeration
+            type itself, we make sure to register the type first, and
+            then create the constants.  That way, doing tsubst_expr
+            for the enumeration constants won't result in recursive
+            calls here; we'll find the instantiation and exit above.  */
+         tsubst_enum (template_type, t, arglist);
+         current_local_enum = prev_local_enum;
+       }
+
+      /* We're done with the permanent obstack, now.  */
+      pop_obstacks ();
 
       /* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO
         is set up.  */
       if (TREE_CODE (t) != ENUMERAL_TYPE)
        DECL_NAME (type_decl) = classtype_mangled_name (t);
       DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl);
-      if (! uses_template_parms (arglist))
+      if (!is_partial_instantiation)
        {
          DECL_ASSEMBLER_NAME (type_decl)
            = get_identifier (build_overload_name (t, 1, 1));
@@ -4708,8 +4732,6 @@ tsubst_decl (t, args, type, in_decl)
        /* We can get here when processing a member template function
           of a template class.  */
        tree decl = DECL_TEMPLATE_RESULT (t);
-       tree parms;
-       tree* new_parms;
        tree spec;
        int is_template_template_parm = DECL_TEMPLATE_TEMPLATE_PARM_P (t);
 
@@ -7781,7 +7803,6 @@ regenerate_decl_from_template (decl, tmpl)
      tree tmpl;
 {
   tree args;
-  tree save_ti;
   tree code_pattern;
   tree new_decl;
   tree gen_tmpl;
@@ -8172,17 +8193,17 @@ add_maybe_template (d, fns)
   DECL_MAYBE_TEMPLATE (d) = 1;
 }
 
-/* Instantiate an enumerated type.  */
+/* Instantiate an enumerated type.  TAG is the template type, NEWTAG
+   is the instantiation (which should have been created with
+   start_enum) and ARGS are the template arguments to use.  */
 
-static tree
-tsubst_enum (tag, args)
-     tree tag, args;
+static void
+tsubst_enum (tag, newtag, args)
+     tree tag;
+     tree newtag;
+     tree args;
 {
-  extern tree current_local_enum;
-  tree prev_local_enum = current_local_enum;
-
-  tree newtag = start_enum (TYPE_IDENTIFIER (tag));
-  tree e, values = NULL_TREE;
+  tree e;
 
   for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
     {
@@ -8194,21 +8215,22 @@ tsubst_enum (tag, args)
        {
          if (TREE_CODE (value) == NOP_EXPR)
            /* This is the special case where the value is really a
-          TEMPLATE_PARM_INDEX.  See finish_enum.  */
+              TEMPLATE_PARM_INDEX.  See finish_enum.  */
            value = TREE_OPERAND (value, 0);
          value = tsubst_expr (value, args, NULL_TREE);
        }
 
       elt = build_enumerator (TREE_PURPOSE (e), value);
-      TREE_CHAIN (elt) = values;
-      values = elt;
-    }
 
-  finish_enum (newtag, values);
-
-  current_local_enum = prev_local_enum;
+      /* We save the enumerators we have built so far in the
+        TYPE_VALUES so that if the enumeration constants for
+        subsequent enumerators involve those for previous ones,
+        tsubst_copy will be able to find them.  */
+      TREE_CHAIN (elt) = TYPE_VALUES (newtag);
+      TYPE_VALUES (newtag) = elt;
+    }
 
-  return newtag;
+  finish_enum (newtag);
 }
 
 /* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/enum8.C b/gcc/testsuite/g++.old-deja/g++.pt/enum8.C
new file mode 100644 (file)
index 0000000..e5cc58a
--- /dev/null
@@ -0,0 +1,18 @@
+// Build don't link:
+
+template <int I>
+void f();
+
+template <>
+void f<4>() {}
+
+template <class T>
+struct S
+{
+  enum E { a = 1, b = a + 3 };
+};
+
+int main()
+{
+  f<S<int>::b>();
+}