cp-tree.h (build_enumerator): Take the enumeration type as a paramter.
authorMark Mitchell <mark@markmitchell.com>
Fri, 28 Aug 1998 15:43:58 +0000 (15:43 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 28 Aug 1998 15:43:58 +0000 (15:43 +0000)
* cp-tree.h (build_enumerator): Take the enumeration type as a
paramter.
* decl.c (finish_enum): Don't set the TREE_TYPE for the
enumeration constant values if we're processing_template_decls.
Don't set the type for the CONST_DECLs either; that's done in
build_enumerator. (
(build_enumerator): Take the enumeration type as a
paramter.
* lex.c (do_identifier): Don't resolve enumeration constants while
processing template declarations, even if they happen to be
TEMPLATE_PARM_INDEXs.
* parse.y (current_enum_type): New variable.
(primary): Don't allow statement-expression in local classes just
as we don't in global classes.
(structsp): Use current_enum_type.
(enum_list): Likewise.
* pt.c (tsubst_enum): Don't check for NOP_EXPRs introduced by
finish_enum; they no longer occur.

From-SVN: r22060

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

index 8e486ca37b01aacfd690301929157f16f2eaead2..4cfc4c63f99e70170076d7f84aa8d5a6f6246046 100644 (file)
@@ -1,5 +1,24 @@
 1998-08-28  Mark Mitchell  <mark@markmitchell.com>
 
+       * cp-tree.h (build_enumerator): Take the enumeration type as a
+       paramter. 
+       * decl.c (finish_enum): Don't set the TREE_TYPE for the
+       enumeration constant values if we're processing_template_decls.
+       Don't set the type for the CONST_DECLs either; that's done in
+       build_enumerator. (
+       (build_enumerator): Take the enumeration type as a
+       paramter. 
+       * lex.c (do_identifier): Don't resolve enumeration constants while
+       processing template declarations, even if they happen to be
+       TEMPLATE_PARM_INDEXs. 
+       * parse.y (current_enum_type): New variable.
+       (primary): Don't allow statement-expression in local classes just
+       as we don't in global classes.
+       (structsp): Use current_enum_type.
+       (enum_list): Likewise.
+       * pt.c (tsubst_enum): Don't check for NOP_EXPRs introduced by
+       finish_enum; they no longer occur.
+       
        * cp-tree.h (finish_base_specifier): New function.
        * parse.y (base_class): Use it.
        * semantics.c (finish_base_specifier): Define it.
index 8829b397fec6c6d29ec39086927066eff9595ea8..f7ce4f2714eb44367ffbfc2173a9338724b685ef 100644 (file)
@@ -2536,7 +2536,7 @@ 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));
-extern tree build_enumerator                   PROTO((tree, tree));
+extern tree build_enumerator                   PROTO((tree, tree, tree));
 extern tree grok_enum_decls                    PROTO((tree));
 extern int start_function                      PROTO((tree, tree, tree, int));
 extern void expand_start_early_try_stmts       PROTO((void));
index 2deeaa80b7ce2067630de091416f8c6ffa7e6cad..2d4fb1345674e753d17b1d3a9b5ccf257275b83a 100644 (file)
@@ -11883,34 +11883,32 @@ finish_enum (enumtype)
             constant.  */
          decl = TREE_VALUE (pair);
 
-         /* The type of the CONST_DECL is the type of the enumeration,
-            not an INTEGER_TYPE.  */
-         TREE_TYPE (decl) = enumtype;
-
          /* The DECL_INITIAL will be NULL if we are processing a
             template declaration and this enumeration constant had no
             explicit initializer.  */
          value = DECL_INITIAL (decl);
-         if (value)
-           {
-             /* Set the TREE_TYPE for the VALUE as well.  When
-                processing a template, however, we might have a
-                TEMPLATE_PARM_INDEX, and we should not change the
-                type of such a thing.  */
-             if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
-               DECL_INITIAL (decl) = value 
-                 = build1 (NOP_EXPR, enumtype, value);
+         if (value && !processing_template_decl)
+           {
+             /* Set the TREE_TYPE for the VALUE as well.  That's so
+                that when we call decl_constant_value we get an
+                entity of the right type (but with the constant
+                value).  Since we shouldn't ever call
+                decl_constant_value on a template type, there's no
+                reason to do that when processing_template_decl.
+                And, if the expression is something like a
+                TEMPLATE_PARM_INDEX or a CAST_EXPR doing so will
+                wreak havoc on the intended type of the expression.  
+
+                Of course, there's also no point in trying to compute
+                minimum or maximum values if we're in a template.  */
              TREE_TYPE (value) = enumtype;
 
-             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;
-               }
+             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
@@ -11985,14 +11983,15 @@ finish_enum (enumtype)
   return enumtype;
 }
 
-/* Build and install a CONST_DECL for one value of the
-   current enumeration type (one that was begun with start_enum).
-   Return a tree-list containing the name and its value.
+/* Build and install a CONST_DECL for an enumeration constant of the
+   enumeration type TYPE whose NAME and VALUE (if any) are provided.
    Assignment of sequential values by default is handled here.  */
 
 tree
-build_enumerator (name, value)
-     tree name, value;
+build_enumerator (name, value, type)
+     tree name;
+     tree value;
+     tree type;
 {
   tree decl, result;
   tree context;
@@ -12038,8 +12037,9 @@ build_enumerator (name, value)
 #endif
    }
 
- /* We have to always copy here; not all INTEGER_CSTs are unshared,
-    and there's no wedding ring. Look at size_int()...*/
+ /* We always have to copy here; not all INTEGER_CSTs are unshared.
+    Even in other cases, we will later (in finish_enum) be setting the
+    type of VALUE.  */
  if (value != NULL_TREE)
    value = copy_node (value);
 
@@ -12048,11 +12048,11 @@ build_enumerator (name, value)
  context = current_scope ();
  if (context && context == current_class_type)
    /* This enum declaration is local to the class.  */
-   decl = build_lang_field_decl (CONST_DECL, name, integer_type_node);
+   decl = build_lang_field_decl (CONST_DECL, name, type);
  else
    /* It's a global enum, or it's local to a function.  (Note local to
       a function could mean local to a class method.  */
-   decl = build_decl (CONST_DECL, name, integer_type_node);
+   decl = build_decl (CONST_DECL, name, type);
 
  DECL_CONTEXT (decl) = FROB_CONTEXT (context);
  DECL_INITIAL (decl) = value;
index acb172822cabd4452c1cd2b8165a1e92ae30fc5a..915b660337910efecc30125fed275883bd18ffa6 100644 (file)
@@ -2984,8 +2984,12 @@ do_identifier (token, parsing, args)
            cp_error ("enum `%D' is private", id);
          /* protected is OK, since it's an enum of `this'.  */
        }
-      if (! processing_template_decl
-         || (DECL_INITIAL (id)
+      if (!processing_template_decl
+         /* Don't resolve enumeration constants while processing
+            template declarations, unless they're for global
+            enumerations and therefore cannot involve template
+            parameters.  */
+         || (!DECL_CONTEXT (id)
              && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
        id = DECL_INITIAL (id);
     }
index 3aca19f4cf40ecee5ef33b0be2f330b46aa5c773..6c66a55717a88fcd2a6e8ca2ce9b8a51a12333c8 100644 (file)
@@ -290,9 +290,13 @@ static tree current_declspecs;
    a declspec list have been updated.  */
 static tree prefix_attributes;
 
-/* When defining an aggregate, this is the most recent one being defined.  */
+/* When defining an aggregate, this is the kind of the most recent one
+   being defined.  (For example, this might be class_type_node.)  */
 static tree current_aggr;
 
+/* When defining an enumeration, this is the type of the enumeration.  */
+static tree current_enum_type;
+
 /* Tell yyparse how to print a token's value, if yydebug is set.  */
 
 #define YYPRINT(FILE,YYCHAR,YYLVAL) yyprint(FILE,YYCHAR,YYLVAL)
@@ -1373,7 +1377,8 @@ primary:
        | '(' error ')'
                { $$ = error_mark_node; }
        | '('
-               { if (current_function_decl == 0)
+               { tree scope = current_scope ();
+                 if (!scope || TREE_CODE (scope) != FUNCTION_DECL)
                    {
                      error ("braced-group within expression allowed only inside a function");
                      YYERROR;
@@ -2058,26 +2063,30 @@ pending_defargs:
 structsp:
          ENUM identifier '{'
                { $<itype>3 = suspend_momentary ();
-                 $<ttype>$ = start_enum ($2); }
+                 $<ttype>$ = current_enum_type;
+                 current_enum_type = start_enum ($2); }
          enumlist maybecomma_warn '}'
-               { TYPE_VALUES ($<ttype>4) = $5;
-                 $$.t = finish_enum ($<ttype>4);
+               { TYPE_VALUES (current_enum_type) = $5;
+                 $$.t = finish_enum (current_enum_type);
                  $$.new_type_flag = 1;
+                 current_enum_type = $<ttype>4;
                  resume_momentary ((int) $<itype>3);
-                 check_for_missing_semicolon ($<ttype>4); }
+                 check_for_missing_semicolon ($$.t); }
        | ENUM identifier '{' '}'
                { $$.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 ()); }
+                 $<ttype>$ = current_enum_type;
+                 current_enum_type = start_enum (make_anon_name ()); }
          enumlist maybecomma_warn '}'
-                { TYPE_VALUES ($<ttype>3) = $4;
-                 $$.t = finish_enum ($<ttype>3);
+                { TYPE_VALUES (current_enum_type) = $4;
+                 $$.t = finish_enum (current_enum_type);
+                 $$.new_type_flag = 1;
+                 current_enum_type = $<ttype>4;
                  resume_momentary ((int) $<itype>1);
-                 check_for_missing_semicolon ($<ttype>3);
-                 $$.new_type_flag = 1; }
+                 check_for_missing_semicolon ($$.t); }
        | ENUM '{' '}'
                { $$.t = finish_enum (start_enum (make_anon_name()));
                  $$.new_type_flag = 1;
@@ -2585,9 +2594,9 @@ enumlist:
 
 enumerator:
          identifier
-               { $$ = build_enumerator ($$, NULL_TREE); }
+               { $$ = build_enumerator ($$, NULL_TREE, current_enum_type); }
        | identifier '=' expr_no_commas
-               { $$ = build_enumerator ($$, $3); }
+               { $$ = build_enumerator ($$, $3, current_enum_type); }
        ;
 
 /* ANSI new-type-id (5.3.4) */
index b0b89c4c3d337d11f5ae63b78e36326723a14bc8..d86eea8f53ebb988cfb6270de912522e38e25363 100644 (file)
@@ -8210,20 +8210,11 @@ tsubst_enum (tag, newtag, args)
 
   for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
     {
-      tree value;
-      tree elt;
-
-      value = TREE_VALUE (e);
-      if (value)
-       {
-         if (TREE_CODE (value) == NOP_EXPR)
-           /* This is the special case where the value is really a
-              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 elt
+       = build_enumerator (TREE_PURPOSE (e), 
+                           tsubst_expr (TREE_VALUE (e), args,
+                                        NULL_TREE),
+                           newtag); 
 
       /* We save the enumerators we have built so far in the
         TYPE_VALUES so that if the enumeration constants for
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/enum10.C b/gcc/testsuite/g++.old-deja/g++.pt/enum10.C
new file mode 100644 (file)
index 0000000..713c11c
--- /dev/null
@@ -0,0 +1,12 @@
+// Build don't link:
+
+template <class T> 
+struct S {
+  enum E { a = (int) T::b };
+};
+
+struct S2 {
+  enum E2 { b };
+};
+
+template class S<S2>;