From 128e1d722d6a685ec6be49e5f11739ba9a76f9a8 Mon Sep 17 00:00:00 2001 From: jason Date: Wed, 19 May 1999 10:44:22 +0000 Subject: [PATCH] Implement anonymous structs. * cp-tree.h (ANON_AGGR_TYPE_P): Rename from ANON_UNION_TYPE_P. * class.c, decl.c, decl2.c, init.c, pt.c, search.c, typeck.c: Adjust. * class.c (finish_struct_1): Remove redundant check for anon struct. * decl.c (fixup_anonymous_aggr): Renamed from fixup_anonymous_union. (check_tag_decl): Check for anonymous struct here. * decl2.c (build_anon_union_vars): Catch anon struct at file scope. * init.c (sort_member_init, emit_base_init): Handle getting fields as well as names in current_member_init_list. (perform_member_init): Handle getting an anon aggr. * method.c (do_build_assign_ref): Don't descend into anon aggrs. (do_build_copy_constructor): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@27027 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 15 ++++++++++++++ gcc/cp/class.c | 9 +++------ gcc/cp/cp-tree.h | 20 +++++++++---------- gcc/cp/decl.c | 17 +++++++++------- gcc/cp/decl2.c | 13 +++++++++---- gcc/cp/init.c | 59 ++++++++++++++++++++++++++++---------------------------- gcc/cp/method.c | 31 +++++++---------------------- gcc/cp/pt.c | 4 ++-- gcc/cp/search.c | 8 ++++---- gcc/cp/typeck.c | 6 +++--- 10 files changed, 91 insertions(+), 91 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d3d297a..63f4158 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +1999-05-19 Jason Merrill + + Implement anonymous structs. + * cp-tree.h (ANON_AGGR_TYPE_P): Rename from ANON_UNION_TYPE_P. + * class.c, decl.c, decl2.c, init.c, pt.c, search.c, typeck.c: Adjust. + * class.c (finish_struct_1): Remove redundant check for anon struct. + * decl.c (fixup_anonymous_aggr): Renamed from fixup_anonymous_union. + (check_tag_decl): Check for anonymous struct here. + * decl2.c (build_anon_union_vars): Catch anon struct at file scope. + * init.c (sort_member_init, emit_base_init): Handle getting fields + as well as names in current_member_init_list. + (perform_member_init): Handle getting an anon aggr. + * method.c (do_build_assign_ref): Don't descend into anon aggrs. + (do_build_copy_constructor): Likewise. + 1999-05-19 Mark Mitchell * tree.c (cp_build_qualified_type): Don't allow qualified function diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 00f9d32..94c891e 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1337,7 +1337,7 @@ delete_duplicate_fields_1 (field, fields) tree prev = 0; if (DECL_NAME (field) == 0) { - if (TREE_CODE (TREE_TYPE (field)) != UNION_TYPE) + if (! ANON_AGGR_TYPE_P (TREE_TYPE (field))) return fields; for (x = TYPE_FIELDS (TREE_TYPE (field)); x; x = TREE_CHAIN (x)) @@ -1350,7 +1350,7 @@ delete_duplicate_fields_1 (field, fields) { if (DECL_NAME (x) == 0) { - if (TREE_CODE (TREE_TYPE (x)) != UNION_TYPE) + if (! ANON_AGGR_TYPE_P (TREE_TYPE (x))) continue; TYPE_FIELDS (TREE_TYPE (x)) = delete_duplicate_fields_1 (field, TYPE_FIELDS (TREE_TYPE (x))); @@ -2953,7 +2953,7 @@ finish_struct_anon (t) continue; if (DECL_NAME (field) == NULL_TREE - && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + && ANON_AGGR_TYPE_P (TREE_TYPE (field))) { tree* uelt = &TYPE_FIELDS (TREE_TYPE (field)); for (; *uelt; uelt = &TREE_CHAIN (*uelt)) @@ -3135,9 +3135,6 @@ finish_struct_1 (t, warn_anon) int has_pointers = 0; tree inline_friends; - if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) - pedwarn ("anonymous class type not used to declare any objects"); - if (TYPE_SIZE (t)) { if (IS_AGGR_TYPE (t)) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 2498089..8524788 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -696,7 +696,7 @@ struct lang_type unsigned const_needs_init : 1; unsigned ref_needs_init : 1; unsigned has_const_assign_ref : 1; - unsigned anon_union : 1; + unsigned anon_aggr : 1; unsigned has_nonpublic_ctor : 2; unsigned has_nonpublic_assign_ref : 2; @@ -1764,16 +1764,14 @@ extern int flag_new_for_scope; Just used to communicate formatting information to dbxout.c. */ #define DECL_OPERATOR(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.operator_attr) -#define ANON_UNION_P(NODE) (DECL_NAME (NODE) == 0) - -/* Nonzero if TYPE is an anonymous union type. We have to use a flag for - this because "A union for which objects or pointers are declared is not - an anonymous union" [class.union]. */ -#define ANON_UNION_TYPE_P(NODE) \ +/* Nonzero if TYPE is an anonymous union or struct type. We have to use a + flag for this because "A union for which objects or pointers are + declared is not an anonymous union" [class.union]. */ +#define ANON_AGGR_TYPE_P(NODE) \ (TYPE_LANG_SPECIFIC (NODE) \ - && TYPE_LANG_SPECIFIC (NODE)->type_flags.anon_union) -#define SET_ANON_UNION_TYPE_P(NODE) \ - (TYPE_LANG_SPECIFIC (NODE)->type_flags.anon_union = 1) + && TYPE_LANG_SPECIFIC (NODE)->type_flags.anon_aggr) +#define SET_ANON_AGGR_TYPE_P(NODE) \ + (TYPE_LANG_SPECIFIC (NODE)->type_flags.anon_aggr = 1) #define UNKNOWN_TYPE LANG_TYPE @@ -2879,7 +2877,7 @@ extern int in_function_p PROTO((void)); extern void replace_defarg PROTO((tree, tree)); extern void print_other_binding_stack PROTO((struct binding_level *)); extern void revert_static_member_fn PROTO((tree*, tree*, tree*)); -extern void fixup_anonymous_union PROTO((tree)); +extern void fixup_anonymous_aggr PROTO((tree)); extern int check_static_variable_definition PROTO((tree, tree)); extern void push_local_binding PROTO((tree, tree, int)); extern int push_class_binding PROTO((tree, tree)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 05a0340..ebb15d1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4338,7 +4338,7 @@ pushdecl_class_level (x) if (TREE_CODE (x) == TYPE_DECL) set_identifier_type_value (name, TREE_TYPE (x)); } - else if (ANON_UNION_TYPE_P (TREE_TYPE (x))) + else if (ANON_AGGR_TYPE_P (TREE_TYPE (x))) { tree f; @@ -7011,7 +7011,7 @@ define_function (name, type, function_code, pfn, library_name) union type.) */ void -fixup_anonymous_union (t) +fixup_anonymous_aggr (t) tree t; { tree *q; @@ -7098,12 +7098,15 @@ check_tag_decl (declspecs) /* Check for an anonymous union. We're careful accessing TYPE_IDENTIFIER because some built-in types, like pointer-to-member types, do not have TYPE_NAME. */ - else if (t && TREE_CODE (t) == UNION_TYPE + else if (t && IS_AGGR_TYPE_CODE (TREE_CODE (t)) && TYPE_NAME (t) && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) { /* Anonymous unions are objects, so they can have specifiers. */; - SET_ANON_UNION_TYPE_P (t); + SET_ANON_AGGR_TYPE_P (t); + + if (TREE_CODE (t) != UNION_TYPE && pedantic && ! in_system_header) + pedwarn ("ISO C++ prohibits anonymous structs"); } else if (ob_modifier) @@ -7149,9 +7152,9 @@ shadow_tag (declspecs) union { ... } ; because there is no declarator after the union, the parser sends that declaration here. */ - if (t && ANON_UNION_TYPE_P (t)) + if (t && ANON_AGGR_TYPE_P (t)) { - fixup_anonymous_union (t); + fixup_anonymous_aggr (t); if (TYPE_FIELDS (t)) { @@ -10053,7 +10056,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) /* Static anonymous unions are dealt with here. */ if (staticp && decl_context == TYPENAME && TREE_CODE (declspecs) == TREE_LIST - && ANON_UNION_TYPE_P (TREE_VALUE (declspecs))) + && ANON_AGGR_TYPE_P (TREE_VALUE (declspecs))) decl_context = FIELD; /* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual' diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index bb24014..9b9f4d6 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -887,10 +887,10 @@ grok_x_components (specs) /* The only case where we need to do anything additional here is an anonymous union field, e.g.: `struct S { union { int i; }; };'. */ - if (t == NULL_TREE || !ANON_UNION_TYPE_P (t)) + if (t == NULL_TREE || !ANON_AGGR_TYPE_P (t)) return; - fixup_anonymous_union (t); + fixup_anonymous_aggr (t); finish_member_declaration (build_lang_field_decl (FIELD_DECL, NULL_TREE, t)); @@ -2152,6 +2152,11 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p) tree main_decl = NULL_TREE; tree field; + /* Rather than write the code to handle the non-union case, + just give an error. */ + if (TREE_CODE (type) != UNION_TYPE) + error ("anonymous struct not inside named type"); + for (field = TYPE_FIELDS (type); field != NULL_TREE; field = TREE_CHAIN (field)) @@ -2173,7 +2178,7 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p) cp_pedwarn_at ("protected member `%#D' in anonymous union", field); if (DECL_NAME (field) == NULL_TREE - && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + && ANON_AGGR_TYPE_P (TREE_TYPE (field))) { decl = build_anon_union_vars (field, elems, static_p, external_p); if (!decl) @@ -2205,7 +2210,7 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p) TREE_ASM_WRITTEN (decl) = 1; if (DECL_NAME (field) == NULL_TREE - && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + && ANON_AGGR_TYPE_P (TREE_TYPE (field))) /* The remainder of the processing was already done in the recursive call. */ continue; diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 7fb2030..1bbc51e 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -154,16 +154,25 @@ perform_member_init (member, name, init, explicit) expand_start_target_temps (); - if (TYPE_NEEDS_CONSTRUCTING (type) - || (init && TYPE_HAS_CONSTRUCTOR (type))) + decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit); + + /* Deal with this here, as we will get confused if we try to call the + assignment op for an anonymous union. This can happen in a + synthesized copy constructor. */ + if (ANON_AGGR_TYPE_P (type)) + { + init = build (INIT_EXPR, type, decl, TREE_VALUE (init)); + TREE_SIDE_EFFECTS (init) = 1; + expand_expr_stmt (init); + } + else if (TYPE_NEEDS_CONSTRUCTING (type) + || (init && TYPE_HAS_CONSTRUCTOR (type))) { /* Since `init' is already a TREE_LIST on the current_member_init_list, only build it into one if we aren't already a list. */ if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST) init = build_expr_list (NULL_TREE, init); - decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit); - if (explicit && TREE_CODE (type) == ARRAY_TYPE && init != NULL_TREE @@ -186,7 +195,7 @@ perform_member_init (member, name, init, explicit) /* default-initialization. */ if (AGGREGATE_TYPE_P (type)) init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); - else if (TREE_CODE (type) == REFERENCE_TYPE) + else if (TREE_CODE (type) == REFERENCE_TYPE) { cp_error ("default-initialization of `%#D', which has reference type", member); @@ -216,8 +225,6 @@ perform_member_init (member, name, init, explicit) current_member_init_list. */ if (init || explicit) { - decl = build_component_ref (current_class_ref, name, NULL_TREE, - explicit); expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); } } @@ -275,16 +282,13 @@ sort_member_init (t) continue; name = TREE_PURPOSE (x); -#if 0 - /* This happens in templates, since the IDENTIFIER is replaced - with the COMPONENT_REF in tsubst_expr. */ - field = (TREE_CODE (name) == COMPONENT_REF - ? TREE_OPERAND (name, 1) : IDENTIFIER_CLASS_VALUE (name)); -#else - /* Let's find out when this happens. */ - my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 348); - field = IDENTIFIER_CLASS_VALUE (name); -#endif + if (TREE_CODE (name) == IDENTIFIER_NODE) + field = IDENTIFIER_CLASS_VALUE (name); + else + { + my_friendly_assert (TREE_CODE (name) == FIELD_DECL, 348); + field = name; + } /* If one member shadows another, get the outermost one. */ if (TREE_CODE (field) == TREE_LIST) @@ -635,15 +639,8 @@ emit_base_init (t, immediately) init = TREE_VALUE (mem_init_list); from_init_list = 1; -#if 0 - if (TREE_CODE (name) == COMPONENT_REF) - name = DECL_NAME (TREE_OPERAND (name, 1)); -#else - /* Also see if it's ever a COMPONENT_REF here. If it is, we - need to do `expand_assignment (name, init, 0, 0);' and - a continue. */ - my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 349); -#endif + my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE + || TREE_CODE (name) == FIELD_DECL, 349); } else { @@ -672,9 +669,11 @@ emit_base_init (t, immediately) { name = TREE_PURPOSE (mem_init_list); init = TREE_VALUE (mem_init_list); - /* XXX: this may need the COMPONENT_REF operand 0 check if - it turns out we actually get them. */ - field = IDENTIFIER_CLASS_VALUE (name); + + if (TREE_CODE (name) == IDENTIFIER_NODE) + field = IDENTIFIER_CLASS_VALUE (name); + else + field = name; /* If one member shadows another, get the outermost one. */ if (TREE_CODE (field) == TREE_LIST) @@ -831,7 +830,7 @@ initializing_context (field) /* Anonymous union members can be initialized in the first enclosing non-anonymous union context. */ - while (t && ANON_UNION_TYPE_P (t)) + while (t && ANON_AGGR_TYPE_P (t)) t = TYPE_CONTEXT (t); return t; } diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 39f7f04..4870169 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -2282,18 +2282,10 @@ do_build_copy_constructor (fndecl) continue; } else if ((t = TREE_TYPE (field)) != NULL_TREE - && ANON_UNION_TYPE_P (t) + && ANON_AGGR_TYPE_P (t) && TYPE_FIELDS (t) != NULL_TREE) - { - do - { - init = build (COMPONENT_REF, t, init, field); - field = largest_union_member (t); - } - while ((t = TREE_TYPE (field)) != NULL_TREE - && ANON_UNION_TYPE_P (t) - && TYPE_FIELDS (t) != NULL_TREE); - } + /* Just use the field; anonymous types can't have + nontrivial copy ctors or assignment ops. */; else continue; @@ -2301,7 +2293,7 @@ do_build_copy_constructor (fndecl) init = build_tree_list (NULL_TREE, init); current_member_init_list - = tree_cons (DECL_NAME (field), init, current_member_init_list); + = tree_cons (field, init, current_member_init_list); } current_member_init_list = nreverse (current_member_init_list); current_base_init_list = nreverse (current_base_init_list); @@ -2390,19 +2382,10 @@ do_build_assign_ref (fndecl) continue; } else if ((t = TREE_TYPE (field)) != NULL_TREE - && ANON_UNION_TYPE_P (t) + && ANON_AGGR_TYPE_P (t) && TYPE_FIELDS (t) != NULL_TREE) - { - do - { - comp = build (COMPONENT_REF, t, comp, field); - init = build (COMPONENT_REF, t, init, field); - field = largest_union_member (t); - } - while ((t = TREE_TYPE (field)) != NULL_TREE - && ANON_UNION_TYPE_P (t) - && TYPE_FIELDS (t) != NULL_TREE); - } + /* Just use the field; anonymous types can't have + nontrivial copy ctors or assignment ops. */; else continue; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 59543ca..6c316518 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4884,8 +4884,8 @@ instantiate_class_template (type) TYPE_PACKED (type) = TYPE_PACKED (pattern); TYPE_ALIGN (type) = TYPE_ALIGN (pattern); TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray */ - if (ANON_UNION_TYPE_P (pattern)) - SET_ANON_UNION_TYPE_P (type); + if (ANON_AGGR_TYPE_P (pattern)) + SET_ANON_AGGR_TYPE_P (type); /* We must copy the arguments to the permanent obstack since during the tsubst'ing below they may wind up in the diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 1213358..906aa13 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -534,7 +534,7 @@ lookup_field_1 (type, name) #endif /* GATHER_STATISTICS */ my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (field)) == 'd', 0); if (DECL_NAME (field) == NULL_TREE - && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + && ANON_AGGR_TYPE_P (TREE_TYPE (field))) { tree temp = lookup_field_1 (TREE_TYPE (field), name); if (temp) @@ -610,7 +610,7 @@ context_for_name_lookup (decl) declared. */ tree context = DECL_REAL_CONTEXT (decl); - while (TYPE_P (context) && ANON_UNION_TYPE_P (context)) + while (TYPE_P (context) && ANON_AGGR_TYPE_P (context)) context = TYPE_CONTEXT (context); if (!context) context = global_namespace; @@ -2927,7 +2927,7 @@ dfs_push_decls (binfo, data) && TREE_CODE (fields) != USING_DECL) setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0); else if (TREE_CODE (fields) == FIELD_DECL - && ANON_UNION_TYPE_P (TREE_TYPE (fields))) + && ANON_AGGR_TYPE_P (TREE_TYPE (fields))) dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data); method_vec = (CLASS_TYPE_P (type) @@ -3001,7 +3001,7 @@ dfs_unuse_fields (binfo, data) TREE_USED (fields) = 0; if (DECL_NAME (fields) == NULL_TREE - && TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE) + && ANON_AGGR_TYPE_P (TREE_TYPE (fields))) unuse_fields (TREE_TYPE (fields)); } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index a6d08be..6ca5adc 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2006,7 +2006,7 @@ lookup_anon_field (t, type) /* Otherwise, it could be nested, search harder. */ if (DECL_NAME (field) == NULL_TREE - && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) + && ANON_AGGR_TYPE_P (TREE_TYPE (field))) { tree subfield = lookup_anon_field (TREE_TYPE (field), type); if (subfield) @@ -2216,7 +2216,7 @@ build_component_ref (datum, component, basetype_path, protect) tree context = DECL_FIELD_CONTEXT (field); tree base = context; while (!same_type_p (base, basetype) && TYPE_NAME (base) - && ANON_UNION_TYPE_P (base)) + && ANON_AGGR_TYPE_P (base)) { base = TYPE_CONTEXT (base); } @@ -2246,7 +2246,7 @@ build_component_ref (datum, component, basetype_path, protect) basetype = base; /* Handle things from anon unions here... */ - if (TYPE_NAME (context) && ANON_UNION_TYPE_P (context)) + if (TYPE_NAME (context) && ANON_AGGR_TYPE_P (context)) { tree subfield = lookup_anon_field (basetype, context); tree subdatum = build_component_ref (datum, subfield, -- 2.7.4