diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/class.c | 364 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.ext/anon2.C | 14 |
4 files changed, 224 insertions, 167 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index fcf01dd6984..228da449145 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +1999-11-03 Mark Mitchell <mark@codesourcery.com> + + * class.c (check_bitfield_decl): New function, split out from + finish_stuct_1. + (check_field_decl): Likewise. Recursively examine members of + anonymous structs. + (finish_struct_1): Use them. + * cp-tree.h (ANON_UNION_TYPE_P): New macro. + 1999-11-02 Mark Mitchell <mark@codesourcery.com> * decl.c (grokfndecl): Remove dead code. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 793e5fc2333..d7f0775a6d9 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -122,6 +122,8 @@ static tree build_vtable_entry_for_fn PROTO((tree, tree)); static tree build_vtbl_initializer PROTO((tree)); static int count_fields PROTO((tree)); static int add_fields_to_vec PROTO((tree, tree, int)); +static void check_bitfield_decl PROTO((tree)); +static void check_field_decl PROTO((tree, tree, int *, int *, int *, int *)); /* Variables shared between class.c and call.c. */ @@ -3156,6 +3158,194 @@ add_fields_to_vec (fields, field_vec, idx) return idx; } +/* FIELD is a bit-field. We are finishing the processing for its + enclosing type. Issue any appropriate messages and set appropriate + flags. */ + +static void +check_bitfield_decl (field) + tree field; +{ + tree type = TREE_TYPE (field); + + /* Invalid bit-field size done by grokfield. */ + /* Detect invalid bit-field type. Simply checking if TYPE is + integral is insufficient, as that is the array core of the field + type. If TREE_TYPE (field) is integral, then TYPE must be the same. */ + if (DECL_INITIAL (field) + && ! INTEGRAL_TYPE_P (TREE_TYPE (field))) + { + cp_error_at ("bit-field `%#D' with non-integral type", field); + DECL_INITIAL (field) = NULL; + } + + /* Detect and ignore out of range field width. */ + if (DECL_INITIAL (field)) + { + tree w = DECL_INITIAL (field); + register int width = 0; + + /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */ + STRIP_NOPS (w); + + /* detect invalid field size. */ + if (TREE_CODE (w) == CONST_DECL) + w = DECL_INITIAL (w); + else if (TREE_READONLY_DECL_P (w)) + w = decl_constant_value (w); + + if (TREE_CODE (w) != INTEGER_CST) + { + cp_error_at ("bit-field `%D' width not an integer constant", + field); + DECL_INITIAL (field) = NULL_TREE; + } + else if (width = TREE_INT_CST_LOW (w), + width < 0) + { + DECL_INITIAL (field) = NULL; + cp_error_at ("negative width in bit-field `%D'", field); + } + else if (width == 0 && DECL_NAME (field) != 0) + { + DECL_INITIAL (field) = NULL; + cp_error_at ("zero width for bit-field `%D'", field); + } + else if (width + > TYPE_PRECISION (long_long_unsigned_type_node)) + { + /* The backend will dump if you try to use something too + big; avoid that. */ + DECL_INITIAL (field) = NULL; + sorry ("bit-fields larger than %d bits", + TYPE_PRECISION (long_long_unsigned_type_node)); + cp_error_at (" in declaration of `%D'", field); + } + else if (width > TYPE_PRECISION (type) + && TREE_CODE (type) != ENUMERAL_TYPE + && TREE_CODE (type) != BOOLEAN_TYPE) + cp_warning_at ("width of `%D' exceeds its type", field); + else if (TREE_CODE (type) == ENUMERAL_TYPE + && ((min_precision (TYPE_MIN_VALUE (type), + TREE_UNSIGNED (type)) > width) + || (min_precision (TYPE_MAX_VALUE (type), + TREE_UNSIGNED (type)) > width))) + cp_warning_at ("`%D' is too small to hold all values of `%#T'", + field, type); + + if (DECL_INITIAL (field)) + { + DECL_INITIAL (field) = NULL_TREE; + DECL_FIELD_SIZE (field) = width; + DECL_BIT_FIELD (field) = 1; + + if (width == 0) + { +#ifdef EMPTY_FIELD_BOUNDARY + DECL_ALIGN (field) = MAX (DECL_ALIGN (field), + EMPTY_FIELD_BOUNDARY); +#endif +#ifdef PCC_BITFIELD_TYPE_MATTERS + if (PCC_BITFIELD_TYPE_MATTERS) + DECL_ALIGN (field) = MAX (DECL_ALIGN (field), + TYPE_ALIGN (type)); +#endif + } + } + } + else + /* Non-bit-fields are aligned for their type. */ + DECL_ALIGN (field) = MAX (DECL_ALIGN (field), TYPE_ALIGN (type)); +} + +/* FIELD is a non bit-field. We are finishing the processing for its + enclosing type T. Issue any appropriate messages and set appropriate + flags. */ + +static void +check_field_decl (field, t, cant_have_const_ctor, + cant_have_default_ctor, no_const_asn_ref, + any_default_members) + tree field; + tree t; + int *cant_have_const_ctor; + int *cant_have_default_ctor; + int *no_const_asn_ref; + int *any_default_members; +{ + tree type = strip_array_types (TREE_TYPE (field)); + + /* An anonymous union cannot contain any fields which would change + the settings of CANT_HAVE_CONST_CTOR and friends. */ + if (ANON_UNION_TYPE_P (type)) + ; + /* And, we don't set TYPE_HAS_CONST_INIT_REF, etc., for anonymous + structs. So, we recurse through their fields here. */ + else if (ANON_AGGR_TYPE_P (type)) + { + tree fields; + + for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) + if (TREE_CODE (field) == FIELD_DECL && !DECL_C_BIT_FIELD (field)) + check_field_decl (fields, t, cant_have_const_ctor, + cant_have_default_ctor, no_const_asn_ref, + any_default_members); + } + /* Check members with class type for constructors, destructors, + etc. */ + else if (CLASS_TYPE_P (type)) + { + /* Never let anything with uninheritable virtuals + make it through without complaint. */ + abstract_virtuals_error (field, type); + + if (TREE_CODE (t) == UNION_TYPE) + { + if (TYPE_NEEDS_CONSTRUCTING (type)) + cp_error_at ("member `%#D' with constructor not allowed in union", + field); + if (TYPE_NEEDS_DESTRUCTOR (type)) + cp_error_at ("member `%#D' with destructor not allowed in union", + field); + if (TYPE_HAS_COMPLEX_ASSIGN_REF (type)) + cp_error_at ("member `%#D' with copy assignment operator not allowed in union", + field); + } + else + { + TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type); + TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type); + TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type); + TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type); + } + + if (!TYPE_HAS_CONST_INIT_REF (type)) + *cant_have_const_ctor = 1; + + if (!TYPE_HAS_CONST_ASSIGN_REF (type)) + *no_const_asn_ref = 1; + + if (TYPE_HAS_CONSTRUCTOR (type) + && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) + *cant_have_default_ctor = 1; + } + if (DECL_INITIAL (field) != NULL_TREE) + { + /* `build_class_init_list' does not recognize + non-FIELD_DECLs. */ + if (TREE_CODE (t) == UNION_TYPE && any_default_members != 0) + cp_error_at ("multiple fields in union `%T' initialized"); + *any_default_members = 1; + } + + /* Non-bit-fields are aligned for their type, except packed fields + which require only BITS_PER_UNIT alignment. */ + DECL_ALIGN (field) = MAX (DECL_ALIGN (field), + (DECL_PACKED (field) + ? BITS_PER_UNIT + : TYPE_ALIGN (TREE_TYPE (field)))); +}; + /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration (or C++ class declaration). @@ -3188,7 +3378,6 @@ finish_struct_1 (t) tree t; { int old; - enum tree_code code = TREE_CODE (t); tree fields = TYPE_FIELDS (t); tree x, last_x, method_vec; int has_virtual; @@ -3447,8 +3636,7 @@ finish_struct_1 (t) } } - while (TREE_CODE (type) == ARRAY_TYPE) - type = TREE_TYPE (type); + type = strip_array_types (type); if (TREE_CODE (type) == POINTER_TYPE) has_pointers = 1; @@ -3500,171 +3688,13 @@ finish_struct_1 (t) /* We set DECL_C_BIT_FIELD in grokbitfield. If the type and width are valid, we'll also set DECL_BIT_FIELD. */ if (DECL_C_BIT_FIELD (x)) - { - /* Invalid bit-field size done by grokfield. */ - /* Detect invalid bit-field type. Simply checking if TYPE is - integral is insufficient, as that is the array core of the - field type. If TREE_TYPE (x) is integral, then TYPE must be - the same. */ - if (DECL_INITIAL (x) - && ! INTEGRAL_TYPE_P (TREE_TYPE (x))) - { - cp_error_at ("bit-field `%#D' with non-integral type", x); - DECL_INITIAL (x) = NULL; - } - - /* Detect and ignore out of range field width. */ - if (DECL_INITIAL (x)) - { - tree w = DECL_INITIAL (x); - register int width = 0; - - /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */ - STRIP_NOPS (w); - - /* detect invalid field size. */ - if (TREE_CODE (w) == CONST_DECL) - w = DECL_INITIAL (w); - else if (TREE_READONLY_DECL_P (w)) - w = decl_constant_value (w); - - if (TREE_CODE (w) != INTEGER_CST) - { - cp_error_at ("bit-field `%D' width not an integer constant", - x); - DECL_INITIAL (x) = NULL_TREE; - } - else if (width = TREE_INT_CST_LOW (w), - width < 0) - { - DECL_INITIAL (x) = NULL; - cp_error_at ("negative width in bit-field `%D'", x); - } - else if (width == 0 && DECL_NAME (x) != 0) - { - DECL_INITIAL (x) = NULL; - cp_error_at ("zero width for bit-field `%D'", x); - } - else if (width - > TYPE_PRECISION (long_long_unsigned_type_node)) - { - /* The backend will dump if you try to use something - too big; avoid that. */ - DECL_INITIAL (x) = NULL; - sorry ("bit-fields larger than %d bits", - TYPE_PRECISION (long_long_unsigned_type_node)); - cp_error_at (" in declaration of `%D'", x); - } - else if (width > TYPE_PRECISION (type) - && TREE_CODE (type) != ENUMERAL_TYPE - && TREE_CODE (type) != BOOLEAN_TYPE) - { - cp_warning_at ("width of `%D' exceeds its type", x); - } - else if (TREE_CODE (type) == ENUMERAL_TYPE - && ((min_precision (TYPE_MIN_VALUE (type), - TREE_UNSIGNED (type)) > width) - || (min_precision (TYPE_MAX_VALUE (type), - TREE_UNSIGNED (type)) > width))) - { - cp_warning_at ("`%D' is too small to hold all values of `%#T'", - x, type); - } - - if (DECL_INITIAL (x)) - { - DECL_INITIAL (x) = NULL_TREE; - DECL_FIELD_SIZE (x) = width; - DECL_BIT_FIELD (x) = 1; - - if (width == 0) - { -#ifdef EMPTY_FIELD_BOUNDARY - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), - EMPTY_FIELD_BOUNDARY); -#endif -#ifdef PCC_BITFIELD_TYPE_MATTERS - if (PCC_BITFIELD_TYPE_MATTERS) - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), - TYPE_ALIGN (type)); -#endif - } - } - } - else - /* Non-bit-fields are aligned for their type. */ - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), TYPE_ALIGN (type)); - } + check_bitfield_decl (x); else - { - if (CLASS_TYPE_P (type) && ! ANON_AGGR_TYPE_P (type)) - { - /* Never let anything with uninheritable virtuals - make it through without complaint. */ - abstract_virtuals_error (x, type); - - if (code == UNION_TYPE) - { - const char *fie = NULL; - if (TYPE_NEEDS_CONSTRUCTING (type)) - fie = "constructor"; - else if (TYPE_NEEDS_DESTRUCTOR (type)) - fie = "destructor"; - else if (TYPE_HAS_COMPLEX_ASSIGN_REF (type)) - fie = "copy assignment operator"; - if (fie) - cp_error_at ("member `%#D' with %s not allowed in union", x, - fie); - } - else - { - TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type); - TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type); - TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type); - TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type); - } - - if (!TYPE_HAS_CONST_INIT_REF (type)) - cant_have_const_ctor = 1; - - if (!TYPE_HAS_CONST_ASSIGN_REF (type)) - no_const_asn_ref = 1; - - if (TYPE_HAS_CONSTRUCTOR (type) - && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) - { - cant_have_default_ctor = 1; -#if 0 - /* This is wrong for aggregates. */ - if (! TYPE_HAS_CONSTRUCTOR (t)) - { - if (DECL_NAME (x)) - cp_pedwarn_at ("member `%#D' with only non-default constructor", x); - else - cp_pedwarn_at ("member with only non-default constructor", x); - cp_pedwarn_at ("in class without a constructor", - x); - } -#endif - } - } - if (DECL_INITIAL (x) != NULL_TREE) - { - /* `build_class_init_list' does not recognize - non-FIELD_DECLs. */ - if (code == UNION_TYPE && any_default_members != 0) - cp_error_at ("multiple fields in union `%T' initialized"); - any_default_members = 1; - } - - { - unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT - : TYPE_ALIGN (TREE_TYPE (x))); - /* Non-bit-fields are aligned for their type, except packed - fields which require only BITS_PER_UNIT alignment. */ - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), min_align); - } - } + check_field_decl (x, t, + &cant_have_const_ctor, + &cant_have_default_ctor, + &no_const_asn_ref, + &any_default_members); } /* If this type has any constant members which did not come diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b79242bb196..882ca04c222 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2321,6 +2321,10 @@ extern int flag_new_for_scope; #define SET_ANON_AGGR_TYPE_P(NODE) \ (TYPE_LANG_SPECIFIC (NODE)->anon_aggr = 1) +/* Nonzero if TYPE is an anonymous union type. */ +#define ANON_UNION_TYPE_P(NODE) \ + (TREE_CODE (NODE) == UNION_TYPE && ANON_AGGR_TYPE_P (NODE)) + /* For a VAR_DECL that is an anonymous union, these are the various sub-variables that make up the anonymous union. */ #define DECL_ANON_UNION_ELEMS(NODE) DECL_ARGUMENTS ((NODE)) diff --git a/gcc/testsuite/g++.old-deja/g++.ext/anon2.C b/gcc/testsuite/g++.old-deja/g++.ext/anon2.C new file mode 100644 index 00000000000..587427ab209 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.ext/anon2.C @@ -0,0 +1,14 @@ +// Build don't link: +// Special g++ Options: + +struct S +{ + S (); +}; + +union U { + struct { + S s; // ERROR - struct with constructor in union + }; +}; + |