This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Thanks for your report. The bug actually had nothing to do with function-at-a-time mode; it was a latent bug triggered by some other work. Here's the fix, which consists largely of an indentation fix-up and some simplifications to the code. (It's nice to see that often, now, C++ bugs are fixed by removing code rather than adding it...) -- Mark Mitchell mark@codesourcery.com CodeSourcery, LLC http://www.codesourcery.com 1999-11-10 Mark Mitchell <mark@codesourcery.com> * cp-tree.h (build_enumerator): Change prototype. * decl.c (enum_next_value): Remove. (enum_overflow): Likewise. (init_decl_processing): Don't register enum_next_value as a root. (start_enum): Clear TYPE_VALUES for a redefined enum. (finish_enum): Reset the type of enumeration constants. (build_enumerator): Fix indentation. Don't copy CONST_DECLs when we don't need to. Maintain the TYPE_VALUES list and look there for the previously defined enumeration constant. Let enumeration constants have the type of their values until the enumeration type is complete. * parse.y (enumlist_opt, enumlist, enumerator): Don't return a value. (structsp): Adjust. * parse.c: Regenerated. * pt.c (tsubst_enum): Adjust according to build_enumerator changes. Index: g++.pt/enum13.C =================================================================== RCS file: enum13.C diff -N enum13.C *** /dev/null Tue May 5 13:32:27 1998 --- enum13.C Wed Nov 10 13:37:51 1999 *************** *** 0 **** --- 1,9 ---- + // Build don't link: + // Origin: Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr> + + template <typename T> + struct foo { + enum { A = 4 >= 4, B = (1 ? true : A) }; + }; + + foo<int> bar; Index: cp-tree.h =================================================================== RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v retrieving revision 1.343 diff -c -p -r1.343 cp-tree.h *** cp-tree.h 1999/11/09 08:15:07 1.343 --- cp-tree.h 1999/11/10 21:33:18 *************** extern tree xref_tag_from_type PROTO(( *** 3466,3472 **** 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, tree)); extern int start_function PROTO((tree, tree, tree, int)); extern void expand_start_early_try_stmts PROTO((void)); extern void store_parm_decls PROTO((void)); --- 3466,3472 ---- extern void xref_basetypes PROTO((tree, tree, tree, tree)); extern tree start_enum PROTO((tree)); extern tree finish_enum PROTO((tree)); ! extern void build_enumerator PROTO((tree, tree, tree)); extern int start_function PROTO((tree, tree, tree, int)); extern void expand_start_early_try_stmts PROTO((void)); extern void store_parm_decls PROTO((void)); Index: decl.c =================================================================== RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v retrieving revision 1.497 diff -c -p -r1.497 decl.c *** decl.c 1999/11/09 08:15:07 1.497 --- decl.c 1999/11/10 21:33:30 *************** tree static_aggregates; *** 288,302 **** tree integer_two_node, integer_three_node; - /* While defining an enum type, this is 1 plus the last enumerator - constant value. */ - - static tree enum_next_value; - - /* Nonzero means that there was overflow computing enum_next_value. */ - - static int enum_overflow; - /* Parsing a function declarator leaves here a chain of structure and enum types declared in the parmlist. */ --- 288,293 ---- *************** init_decl_processing () *** 6357,6363 **** ggc_add_tree_root (&static_dtors, 1); ggc_add_tree_root (&lastiddecl, 1); - ggc_add_tree_root (&enum_next_value, 1); ggc_add_tree_root (&last_function_parm_tags, 1); ggc_add_tree_root (¤t_function_return_value, 1); ggc_add_tree_root (¤t_function_parms, 1); --- 6348,6353 ---- *************** start_enum (name) *** 12381,12386 **** --- 12371,12378 ---- { cp_error ("multiple definition of `%#T'", enumtype); cp_error_at ("previous definition here", enumtype); + /* Clear out TYPE_VALUES, and start again. */ + TYPE_VALUES (enumtype) = NULL_TREE; } else { *************** start_enum (name) *** 12391,12400 **** if (current_class_type) TREE_ADDRESSABLE (b->tags) = 1; - /* We don't copy this value because build_enumerator needs to do it. */ - enum_next_value = integer_zero_node; - enum_overflow = 0; - GNU_xref_decl (current_function_decl, enumtype); return enumtype; } --- 12383,12388 ---- *************** finish_enum (enumtype) *** 12425,12430 **** --- 12413,12426 ---- constant. */ decl = TREE_VALUE (pair); + /* [dcl.enum] + + Following the closing brace of an enum-specifier, each + enumerator has the type of its enumeration. Prior to the + closing brace, the type of each enumerator is the type of + its initializing value. */ + 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. */ *************** finish_enum (enumtype) *** 12530,12630 **** } /* 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, type) tree name; tree value; ! tree type; { ! tree decl, result; tree context; /* Remove no-op casts from the value. */ if (value) STRIP_TYPE_NOPS (value); ! if (! processing_template_decl) ! { ! /* Validate and default VALUE. */ ! if (value != NULL_TREE) ! { ! if (TREE_READONLY_DECL_P (value)) ! value = decl_constant_value (value); ! ! if (TREE_CODE (value) == INTEGER_CST) ! { ! value = default_conversion (value); ! constant_expression_warning (value); ! } ! else ! { ! cp_error ("enumerator value for `%D' not integer constant", name); ! value = NULL_TREE; ! } ! } ! /* Default based on previous value. */ ! if (value == NULL_TREE && ! processing_template_decl) ! { ! value = enum_next_value; ! if (enum_overflow) ! cp_error ("overflow in enumeration values at `%D'", name); ! } ! ! /* Remove no-op casts from the value. */ ! if (value) ! STRIP_TYPE_NOPS (value); #if 0 ! /* To fix MAX_VAL enum consts. (bkoz) */ ! TREE_TYPE (value) = integer_type_node; #endif ! } ! /* 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); /* C++ associates enums with global, function, or class declarations. */ ! ! context = current_scope (); ! if (context && context == current_class_type) ! /* This enum declaration is local to the class. */ ! decl = build_lang_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, type); ! DECL_CONTEXT (decl) = FROB_CONTEXT (context); ! DECL_INITIAL (decl) = value; ! TREE_READONLY (decl) = 1; ! if (context && context == current_class_type) ! /* In something like `struct S { enum E { i = 7 }; };' we put `i' on the TYPE_FIELDS list for `S'. (That's so that you can say things like `S::i' later.) */ ! finish_member_declaration (decl); ! else ! { ! pushdecl (decl); ! GNU_xref_decl (current_function_decl, decl); ! } ! ! if (! processing_template_decl) ! { ! /* Set basis for default for next value. */ ! enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value, ! integer_one_node, PLUS_EXPR); ! enum_overflow = tree_int_cst_lt (enum_next_value, value); ! } ! result = tree_cons (name, decl, NULL_TREE); ! return result; } --- 12526,12656 ---- } /* Build and install a CONST_DECL for an enumeration constant of the ! enumeration type ENUMTYPE whose NAME and VALUE (if any) are provided. Assignment of sequential values by default is handled here. */ ! void ! build_enumerator (name, value, enumtype) tree name; tree value; ! tree enumtype; { ! tree decl; tree context; + tree type; + tree values; /* Remove no-op casts from the value. */ if (value) STRIP_TYPE_NOPS (value); ! if (! processing_template_decl) ! { ! /* Validate and default VALUE. */ ! if (value != NULL_TREE) ! { ! if (TREE_READONLY_DECL_P (value)) ! value = decl_constant_value (value); ! if (TREE_CODE (value) == INTEGER_CST) ! { ! value = default_conversion (value); ! constant_expression_warning (value); ! } ! else ! { ! cp_error ("enumerator value for `%D' not integer constant", name); ! value = NULL_TREE; ! } ! } ! ! /* Default based on previous value. */ ! if (value == NULL_TREE && ! processing_template_decl) ! { ! tree prev_value; ! ! if (TYPE_VALUES (enumtype)) ! { ! /* The next value is the previous value ... */ ! prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype))); ! /* ... plus one. */ ! value = build_binary_op_nodefault (PLUS_EXPR, ! prev_value, ! integer_one_node, ! PLUS_EXPR); ! ! if (tree_int_cst_lt (value, prev_value)) ! cp_error ("overflow in enumeration values at `%D'", name); ! } ! else ! value = integer_zero_node; ! } ! ! /* Remove no-op casts from the value. */ ! if (value) ! STRIP_TYPE_NOPS (value); #if 0 ! /* To fix MAX_VAL enum consts. (bkoz) */ ! TREE_TYPE (value) = integer_type_node; #endif ! } ! /* 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. But, we don't need to make a copy if this ! VALUE is one of the enumeration constants for this same ! enumeration type. */ ! for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values)) ! if (TREE_VALUE (values) == value) ! break; ! /* If we didn't break out of the loop, then we do need a copy. */ ! if (!values && value) ! value = copy_node (value); /* C++ associates enums with global, function, or class declarations. */ ! context = current_scope (); ! ! /* Build the actual enumeration constant. Note that the enumeration ! constants have the type of their initializers until the ! enumeration is complete: ! ! [ dcl.enum ] ! ! Following the closing brace of an enum-specifier, each enumer- ! ator has the type of its enumeration. Prior to the closing ! brace, the type of each enumerator is the type of its ! initializing value. ! ! In finish_enum we will reset the type. Of course, if we're ! processing a template, there may be no value. */ ! type = value ? TREE_TYPE (value) : NULL_TREE; ! ! if (context && context == current_class_type) ! /* This enum declaration is local to the class. We need the full ! lang_decl so that we can record DECL_CLASS_CONTEXT, for example. */ ! decl = build_lang_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, type); ! DECL_CONTEXT (decl) = FROB_CONTEXT (context); ! DECL_INITIAL (decl) = value; ! TREE_READONLY (decl) = 1; ! if (context && context == current_class_type) ! /* In something like `struct S { enum E { i = 7 }; };' we put `i' on the TYPE_FIELDS list for `S'. (That's so that you can say things like `S::i' later.) */ ! finish_member_declaration (decl); ! else ! { ! pushdecl (decl); ! GNU_xref_decl (current_function_decl, decl); ! } ! /* Add this enumeration constant to the list for this type. */ ! TYPE_VALUES (enumtype) = tree_cons (name, decl, TYPE_VALUES (enumtype)); } Index: parse.y =================================================================== RCS file: /cvs/gcc/egcs/gcc/cp/parse.y,v retrieving revision 1.154 diff -c -p -r1.154 parse.y *** parse.y 1999/11/07 22:21:28 1.154 --- parse.y 1999/11/10 21:33:37 *************** empty_parms () *** 215,221 **** %type <ttype> component_declarator component_declarator0 %type <ttype> notype_component_declarator notype_component_declarator0 %type <ttype> after_type_component_declarator after_type_component_declarator0 - %type <ttype> enumlist_opt enumlist enumerator %type <ttype> absdcl cv_qualifiers %type <ttype> direct_abstract_declarator conversion_declarator %type <ttype> new_declarator direct_new_declarator --- 215,220 ---- *************** structsp: *** 2066,2073 **** { $<ttype>$ = current_enum_type; current_enum_type = start_enum ($2); } enumlist_opt '}' ! { TYPE_VALUES (current_enum_type) = $5; ! $$.t = finish_enum (current_enum_type); $$.new_type_flag = 1; current_enum_type = $<ttype>4; check_for_missing_semicolon ($$.t); } --- 2065,2071 ---- { $<ttype>$ = current_enum_type; current_enum_type = start_enum ($2); } enumlist_opt '}' ! { $$.t = finish_enum (current_enum_type); $$.new_type_flag = 1; current_enum_type = $<ttype>4; check_for_missing_semicolon ($$.t); } *************** structsp: *** 2075,2082 **** { $<ttype>$ = current_enum_type; current_enum_type = start_enum (make_anon_name ()); } enumlist_opt '}' ! { TYPE_VALUES (current_enum_type) = $4; ! $$.t = finish_enum (current_enum_type); $$.new_type_flag = 1; current_enum_type = $<ttype>3; check_for_missing_semicolon ($$.t); } --- 2073,2079 ---- { $<ttype>$ = current_enum_type; current_enum_type = start_enum (make_anon_name ()); } enumlist_opt '}' ! { $$.t = finish_enum (current_enum_type); $$.new_type_flag = 1; current_enum_type = $<ttype>3; check_for_missing_semicolon ($$.t); } *************** notype_component_declarator: *** 2582,2588 **** enumlist_opt: enumlist maybecomma_warn | maybecomma_warn - { $$ = NULL_TREE; } ; /* We chain the enumerators in reverse order. --- 2579,2584 ---- *************** enumlist_opt: *** 2592,2605 **** enumlist: enumerator | enumlist ',' enumerator - { TREE_CHAIN ($3) = $$; $$ = $3; } ; enumerator: identifier ! { $$ = build_enumerator ($$, NULL_TREE, current_enum_type); } | identifier '=' expr_no_commas ! { $$ = build_enumerator ($$, $3, current_enum_type); } ; /* ANSI new-type-id (5.3.4) */ --- 2588,2600 ---- enumlist: enumerator | enumlist ',' enumerator ; enumerator: identifier ! { build_enumerator ($1, NULL_TREE, current_enum_type); } | identifier '=' expr_no_commas ! { build_enumerator ($1, $3, current_enum_type); } ; /* ANSI new-type-id (5.3.4) */ Index: pt.c =================================================================== RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v retrieving revision 1.379 diff -c -p -r1.379 pt.c *** pt.c 1999/11/07 22:21:29 1.379 --- pt.c 1999/11/10 21:33:42 *************** tsubst_enum (tag, newtag, args) *** 9755,9762 **** for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e)) { tree value; ! tree elt; ! /* Note that in a template enum, the TREE_VALUE is the CONST_DECL, not the corresponding INTEGER_CST. */ value = tsubst_expr (DECL_INITIAL (TREE_VALUE (e)), --- 9755,9761 ---- for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e)) { tree value; ! /* Note that in a template enum, the TREE_VALUE is the CONST_DECL, not the corresponding INTEGER_CST. */ value = tsubst_expr (DECL_INITIAL (TREE_VALUE (e)), *************** tsubst_enum (tag, newtag, args) *** 9767,9780 **** set_current_access_from_decl (TREE_VALUE (e)); /* Actually build the enumerator itself. */ ! elt = build_enumerator (TREE_PURPOSE (e), value, newtag); ! ! /* 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; } finish_enum (newtag); --- 9766,9772 ---- set_current_access_from_decl (TREE_VALUE (e)); /* Actually build the enumerator itself. */ ! build_enumerator (TREE_PURPOSE (e), value, newtag); } finish_enum (newtag);
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |