diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d0ecbdb7b72..3e1fa5d4ab0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2003-06-27 Mark Mitchell + + PR c++/10796 + * decl.c (finish_enum): Implement DR377. + + * decl.c (cp_finish_decl): Don't make variables with reference + type readonly while they are being initialized. + 2003-06-26 Mark Mitchell PR c++/11332 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b9c59af6cc7..66257c0d6c4 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8101,7 +8101,8 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags) ttype = target_type (type); if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl) - && TYPE_NEEDS_CONSTRUCTING (type)) + && (TYPE_NEEDS_CONSTRUCTING (type) + || TREE_CODE (type) == REFERENCE_TYPE)) { /* Currently, GNU C++ puts constants in text space, making them impossible to initialize. In the future, one would hope for @@ -13106,24 +13107,36 @@ finish_enum (tree enumtype) highprec = min_precision (maxnode, unsignedp); precision = MAX (lowprec, highprec); - /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'. */ - TYPE_SIZE (enumtype) = NULL_TREE; + /* DR 377 + + IF no integral type can represent all the enumerator values, the + enumeration is ill-formed. */ + if (precision > TYPE_PRECISION (long_long_integer_type_node)) + { + error ("no integral type can represent all of the enumerator values " + "for `%T'", enumtype); + precision = TYPE_PRECISION (long_long_integer_type_node); + } + + /* Compute the minium and maximum values for the type, the size of + the type, and so forth. */ TYPE_PRECISION (enumtype) = precision; + TYPE_SIZE (enumtype) = NULL_TREE; if (unsignedp) fixup_unsigned_type (enumtype); else fixup_signed_type (enumtype); - if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node))) - /* Use the width of the narrowest normal C type which is wide - enough. */ - TYPE_PRECISION (enumtype) = TYPE_PRECISION (c_common_type_for_size - (precision, 1)); - else - TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); - - TYPE_SIZE (enumtype) = NULL_TREE; - layout_type (enumtype); + /* We use "int" or "unsigned int" as the underlying type, unless all + the values will not fit or the user has requested that we try to + use shorter types where possible. */ + if (precision < TYPE_PRECISION (integer_type_node) + && !flag_short_enums) + { + TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); + TYPE_SIZE (enumtype) = NULL_TREE; + layout_type (enumtype); + } /* Fix up all variant types of this enum type. */ for (t = TYPE_MAIN_VARIANT (enumtype); t; t = TYPE_NEXT_VARIANT (t)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 930031bf95a..b407402ed3f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2003-06-27 Mark Mitchell + + PR c++/10796 + * g++.dg/init/enum1.C: New test. + 2003-06-27 Ulrich Weigand * gcc.dg/20030627-1.c: New test. diff --git a/gcc/testsuite/g++.dg/init/enum1.C b/gcc/testsuite/g++.dg/init/enum1.C new file mode 100644 index 00000000000..f74a5ad2b55 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/enum1.C @@ -0,0 +1,10 @@ +enum test { + acceptable = -1, + unacceptable = 0xffffffffffffffffLL +}; // { dg-error "" } + +enum test t = acceptable, u = unacceptable; + +int main() { + return 0; +}