decl2.c (finish_anon_union): Generalize error messages to handle anonymous structures.
* decl2.c (finish_anon_union): Generalize error messages to handle anonymous structures. * init.c (perform_member_init): Remove `name' parameter. (build_field_list): New function. (sort_member_init): Handle anonymous union initialization order correctly. Check for multiple initializations of the same union. (emit_base_init): Don't look up fields by name here. (expand_member_init): Record the result of name lookup for future reference. * typeck.c (build_component_ref): Fix formatting. From-SVN: r33963
This commit is contained in:
parent
2c0b35cb89
commit
ff9f1a5d55
@ -1,3 +1,16 @@
|
|||||||
|
2000-05-17 Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
|
* decl2.c (finish_anon_union): Generalize error messages to handle
|
||||||
|
anonymous structures.
|
||||||
|
* init.c (perform_member_init): Remove `name' parameter.
|
||||||
|
(build_field_list): New function.
|
||||||
|
(sort_member_init): Handle anonymous union initialization order
|
||||||
|
correctly. Check for multiple initializations of the same union.
|
||||||
|
(emit_base_init): Don't look up fields by name here.
|
||||||
|
(expand_member_init): Record the result of name lookup for future
|
||||||
|
reference.
|
||||||
|
* typeck.c (build_component_ref): Fix formatting.
|
||||||
|
|
||||||
Wed May 17 17:27:44 2000 Andrew Cagney <cagney@b1.cygnus.com>
|
Wed May 17 17:27:44 2000 Andrew Cagney <cagney@b1.cygnus.com>
|
||||||
|
|
||||||
* decl.c (pop_label): Replace warn_unused with warn_unused_label.
|
* decl.c (pop_label): Replace warn_unused with warn_unused_label.
|
||||||
|
@ -2172,7 +2172,7 @@ finish_anon_union (anon_union_decl)
|
|||||||
|
|
||||||
if (public_p)
|
if (public_p)
|
||||||
{
|
{
|
||||||
error ("global anonymous unions must be declared static");
|
error ("namespace-scope anonymous aggregates must be static");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2182,7 +2182,7 @@ finish_anon_union (anon_union_decl)
|
|||||||
|
|
||||||
if (main_decl == NULL_TREE)
|
if (main_decl == NULL_TREE)
|
||||||
{
|
{
|
||||||
warning ("anonymous union with no members");
|
warning ("anonymous aggregate with no members");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
300
gcc/cp/init.c
300
gcc/cp/init.c
@ -39,7 +39,7 @@ static void construct_virtual_bases PARAMS ((tree, tree, tree, tree, tree));
|
|||||||
static void expand_aggr_init_1 PARAMS ((tree, tree, tree, tree, int));
|
static void expand_aggr_init_1 PARAMS ((tree, tree, tree, tree, int));
|
||||||
static void expand_default_init PARAMS ((tree, tree, tree, tree, int));
|
static void expand_default_init PARAMS ((tree, tree, tree, tree, int));
|
||||||
static tree build_vec_delete_1 PARAMS ((tree, tree, tree, tree, int));
|
static tree build_vec_delete_1 PARAMS ((tree, tree, tree, tree, int));
|
||||||
static void perform_member_init PARAMS ((tree, tree, tree, int));
|
static void perform_member_init PARAMS ((tree, tree, int));
|
||||||
static void sort_base_init PARAMS ((tree, tree *, tree *));
|
static void sort_base_init PARAMS ((tree, tree *, tree *));
|
||||||
static tree build_builtin_delete_call PARAMS ((tree));
|
static tree build_builtin_delete_call PARAMS ((tree));
|
||||||
static int member_init_ok_or_else PARAMS ((tree, tree, const char *));
|
static int member_init_ok_or_else PARAMS ((tree, tree, const char *));
|
||||||
@ -52,6 +52,7 @@ static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
|
|||||||
static tree build_new_1 PARAMS ((tree));
|
static tree build_new_1 PARAMS ((tree));
|
||||||
static tree get_cookie_size PARAMS ((tree));
|
static tree get_cookie_size PARAMS ((tree));
|
||||||
static tree build_dtor_call PARAMS ((tree, tree, int));
|
static tree build_dtor_call PARAMS ((tree, tree, int));
|
||||||
|
static tree build_field_list PARAMS ((tree, tree, int *));
|
||||||
|
|
||||||
/* Set up local variable for this file. MUST BE CALLED AFTER
|
/* Set up local variable for this file. MUST BE CALLED AFTER
|
||||||
INIT_DECL_PROCESSING. */
|
INIT_DECL_PROCESSING. */
|
||||||
@ -175,14 +176,14 @@ initialize_vtbl_ptrs (type, addr)
|
|||||||
/* Subroutine of emit_base_init. */
|
/* Subroutine of emit_base_init. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
perform_member_init (member, name, init, explicit)
|
perform_member_init (member, init, explicit)
|
||||||
tree member, name, init;
|
tree member, init;
|
||||||
int explicit;
|
int explicit;
|
||||||
{
|
{
|
||||||
tree decl;
|
tree decl;
|
||||||
tree type = TREE_TYPE (member);
|
tree type = TREE_TYPE (member);
|
||||||
|
|
||||||
decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
|
decl = build_component_ref (current_class_ref, member, NULL_TREE, explicit);
|
||||||
|
|
||||||
if (decl == error_mark_node)
|
if (decl == error_mark_node)
|
||||||
return;
|
return;
|
||||||
@ -191,10 +192,13 @@ perform_member_init (member, name, init, explicit)
|
|||||||
assignment op for an anonymous union. This can happen in a
|
assignment op for an anonymous union. This can happen in a
|
||||||
synthesized copy constructor. */
|
synthesized copy constructor. */
|
||||||
if (ANON_AGGR_TYPE_P (type))
|
if (ANON_AGGR_TYPE_P (type))
|
||||||
|
{
|
||||||
|
if (init)
|
||||||
{
|
{
|
||||||
init = build (INIT_EXPR, type, decl, TREE_VALUE (init));
|
init = build (INIT_EXPR, type, decl, TREE_VALUE (init));
|
||||||
finish_expr_stmt (init);
|
finish_expr_stmt (init);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (TYPE_NEEDS_CONSTRUCTING (type)
|
else if (TYPE_NEEDS_CONSTRUCTING (type)
|
||||||
|| (init && TYPE_HAS_CONSTRUCTOR (type)))
|
|| (init && TYPE_HAS_CONSTRUCTOR (type)))
|
||||||
{
|
{
|
||||||
@ -268,7 +272,7 @@ perform_member_init (member, name, init, explicit)
|
|||||||
{
|
{
|
||||||
tree expr;
|
tree expr;
|
||||||
|
|
||||||
expr = build_component_ref (current_class_ref, name, NULL_TREE,
|
expr = build_component_ref (current_class_ref, member, NULL_TREE,
|
||||||
explicit);
|
explicit);
|
||||||
expr = build_delete (type, expr, integer_zero_node,
|
expr = build_delete (type, expr, integer_zero_node,
|
||||||
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
|
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
|
||||||
@ -278,91 +282,198 @@ perform_member_init (member, name, init, explicit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns a TREE_LIST containing (as the TREE_PURPOSE of each node) all
|
||||||
|
the FIELD_DECLs on the TYPE_FIELDS list for T, in reverse order. */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
build_field_list (t, list, uses_unions_p)
|
||||||
|
tree t;
|
||||||
|
tree list;
|
||||||
|
int *uses_unions_p;
|
||||||
|
{
|
||||||
|
tree fields;
|
||||||
|
|
||||||
|
/* Note whether or not T is a union. */
|
||||||
|
if (TREE_CODE (t) == UNION_TYPE)
|
||||||
|
*uses_unions_p = 1;
|
||||||
|
|
||||||
|
for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
|
||||||
|
{
|
||||||
|
/* Skip CONST_DECLs for enumeration constants and so forth. */
|
||||||
|
if (TREE_CODE (fields) != FIELD_DECL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Keep track of whether or not any fields are unions. */
|
||||||
|
if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
|
||||||
|
*uses_unions_p = 1;
|
||||||
|
|
||||||
|
/* For an anonymous struct or union, we must recursively
|
||||||
|
consider the fields of the anonymous type. They can be
|
||||||
|
directly initialized from the constructor. */
|
||||||
|
if (ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
|
||||||
|
{
|
||||||
|
/* Add this field itself. Synthesized copy constructors
|
||||||
|
initialize the entire aggregate. */
|
||||||
|
list = tree_cons (fields, NULL_TREE, list);
|
||||||
|
/* And now add the fields in the anonymous aggregate. */
|
||||||
|
list = build_field_list (TREE_TYPE (fields), list,
|
||||||
|
uses_unions_p);
|
||||||
|
}
|
||||||
|
/* Add this field. */
|
||||||
|
else if (DECL_NAME (fields))
|
||||||
|
list = tree_cons (fields, NULL_TREE, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/* Subroutine of emit_member_init. */
|
/* Subroutine of emit_member_init. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
sort_member_init (t)
|
sort_member_init (t)
|
||||||
tree t;
|
tree t;
|
||||||
{
|
{
|
||||||
tree x, member, name, field;
|
tree init_list;
|
||||||
tree init_list = NULL_TREE;
|
tree last_field;
|
||||||
int last_pos = 0;
|
tree init;
|
||||||
tree last_field = NULL_TREE;
|
int uses_unions_p;
|
||||||
|
|
||||||
for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member))
|
/* Build up a list of the various fields, in sorted order. */
|
||||||
|
init_list = nreverse (build_field_list (t, NULL_TREE, &uses_unions_p));
|
||||||
|
|
||||||
|
/* Go through the explicit initializers, adding them to the
|
||||||
|
INIT_LIST. */
|
||||||
|
last_field = init_list;
|
||||||
|
for (init = current_member_init_list; init; init = TREE_CHAIN (init))
|
||||||
{
|
{
|
||||||
int pos;
|
tree f;
|
||||||
|
tree initialized_field;
|
||||||
|
|
||||||
/* member could be, for example, a CONST_DECL for an enumerated
|
initialized_field = TREE_PURPOSE (init);
|
||||||
tag; we don't want to try to initialize that, since it already
|
my_friendly_assert (TREE_CODE (initialized_field) == FIELD_DECL,
|
||||||
has a value. */
|
20000516);
|
||||||
if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (x = current_member_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)
|
/* If the explicit initializers are in sorted order, then the
|
||||||
{
|
INITIALIZED_FIELD will be for a field following the
|
||||||
/* If we cleared this out, then pay no attention to it. */
|
LAST_FIELD. */
|
||||||
if (TREE_PURPOSE (x) == NULL_TREE)
|
for (f = last_field; f; f = TREE_CHAIN (f))
|
||||||
continue;
|
if (TREE_PURPOSE (f) == initialized_field)
|
||||||
name = TREE_PURPOSE (x);
|
break;
|
||||||
|
|
||||||
if (TREE_CODE (name) == IDENTIFIER_NODE)
|
/* Give a warning, if appropriate. */
|
||||||
field = IDENTIFIER_CLASS_VALUE (name);
|
if (warn_reorder && !f)
|
||||||
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)
|
|
||||||
field = TREE_VALUE (field);
|
|
||||||
|
|
||||||
if (field == member)
|
|
||||||
{
|
|
||||||
if (warn_reorder)
|
|
||||||
{
|
|
||||||
if (pos < last_pos)
|
|
||||||
{
|
{
|
||||||
cp_warning_at ("member initializers for `%#D'", last_field);
|
cp_warning_at ("member initializers for `%#D'", last_field);
|
||||||
cp_warning_at (" and `%#D'", field);
|
cp_warning_at (" and `%#D'", initialized_field);
|
||||||
warning (" will be re-ordered to match declaration order");
|
warning (" will be re-ordered to match declaration order");
|
||||||
}
|
}
|
||||||
last_pos = pos;
|
|
||||||
last_field = field;
|
/* Look again, from the beginning of the list. We must find the
|
||||||
|
field on this loop. */
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
f = init_list;
|
||||||
|
while (TREE_PURPOSE (f) != initialized_field)
|
||||||
|
f = TREE_CHAIN (f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure we won't try to work on this init again. */
|
/* If there was already an explicit initializer for this field,
|
||||||
TREE_PURPOSE (x) = NULL_TREE;
|
issue an error. */
|
||||||
x = build_tree_list (name, TREE_VALUE (x));
|
if (TREE_TYPE (f))
|
||||||
goto got_it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we didn't find MEMBER in the list, create a dummy entry
|
|
||||||
so the two lists (INIT_LIST and the list of members) will be
|
|
||||||
symmetrical. */
|
|
||||||
x = build_tree_list (NULL_TREE, NULL_TREE);
|
|
||||||
got_it:
|
|
||||||
init_list = chainon (init_list, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initializers for base members go at the end. */
|
|
||||||
for (x = current_member_init_list ; x ; x = TREE_CHAIN (x))
|
|
||||||
{
|
|
||||||
name = TREE_PURPOSE (x);
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
if (purpose_member (name, init_list))
|
|
||||||
{
|
|
||||||
cp_error ("multiple initializations given for member `%D'",
|
cp_error ("multiple initializations given for member `%D'",
|
||||||
IDENTIFIER_CLASS_VALUE (name));
|
initialized_field);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Mark the field as explicitly initialized. */
|
||||||
|
TREE_TYPE (f) = error_mark_node;
|
||||||
|
/* And insert the initializer. */
|
||||||
|
TREE_VALUE (f) = TREE_VALUE (init);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remember the location of the last explicitly initialized
|
||||||
|
field. */
|
||||||
|
last_field = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* [class.base.init]
|
||||||
|
|
||||||
|
If a ctor-initializer specifies more than one mem-initializer for
|
||||||
|
multiple members of the same union (including members of
|
||||||
|
anonymous unions), the ctor-initializer is ill-formed. */
|
||||||
|
if (uses_unions_p)
|
||||||
|
{
|
||||||
|
last_field = NULL_TREE;
|
||||||
|
for (init = init_list; init; init = TREE_CHAIN (init))
|
||||||
|
{
|
||||||
|
tree field;
|
||||||
|
tree field_type;
|
||||||
|
int done;
|
||||||
|
|
||||||
|
/* Skip uninitialized members. */
|
||||||
|
if (!TREE_TYPE (init))
|
||||||
|
continue;
|
||||||
|
/* See if this field is a member of a union, or a member of a
|
||||||
|
structure contained in a union, etc. */
|
||||||
|
field = TREE_PURPOSE (init);
|
||||||
|
for (field_type = DECL_CONTEXT (field);
|
||||||
|
!same_type_p (field_type, t);
|
||||||
|
field_type = TYPE_CONTEXT (field_type))
|
||||||
|
if (TREE_CODE (field_type) == UNION_TYPE)
|
||||||
|
break;
|
||||||
|
/* If this field is not a member of a union, skip it. */
|
||||||
|
if (TREE_CODE (field_type) != UNION_TYPE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* It's only an error if we have two initializers for the same
|
||||||
|
union type. */
|
||||||
|
if (!last_field)
|
||||||
|
{
|
||||||
|
last_field = field;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_list = chainon (init_list,
|
/* See if LAST_FIELD and the field initialized by INIT are
|
||||||
build_tree_list (name, TREE_VALUE (x)));
|
members of the same union. If so, there's a problem,
|
||||||
TREE_PURPOSE (x) = NULL_TREE;
|
unless they're actually members of the same structure
|
||||||
|
which is itself a member of a union. For example, given:
|
||||||
|
|
||||||
|
union { struct { int i; int j; }; };
|
||||||
|
|
||||||
|
initializing both `i' and `j' makes sense. */
|
||||||
|
field_type = DECL_CONTEXT (field);
|
||||||
|
done = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
tree last_field_type;
|
||||||
|
|
||||||
|
last_field_type = DECL_CONTEXT (last_field);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (same_type_p (last_field_type, field_type))
|
||||||
|
{
|
||||||
|
if (TREE_CODE (field_type) == UNION_TYPE)
|
||||||
|
cp_error ("initializations for multiple members of `%T'",
|
||||||
|
last_field_type);
|
||||||
|
done = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (same_type_p (last_field_type, t))
|
||||||
|
break;
|
||||||
|
|
||||||
|
last_field_type = TYPE_CONTEXT (last_field_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we've reached the outermost class, then we're
|
||||||
|
done. */
|
||||||
|
if (same_type_p (field_type, t))
|
||||||
|
break;
|
||||||
|
|
||||||
|
field_type = TYPE_CONTEXT (field_type);
|
||||||
|
}
|
||||||
|
while (!done);
|
||||||
|
|
||||||
|
last_field = field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,32 +697,23 @@ emit_base_init (t)
|
|||||||
/* Initialize the vtable pointers for the class. */
|
/* Initialize the vtable pointers for the class. */
|
||||||
initialize_vtbl_ptrs (t, current_class_ptr);
|
initialize_vtbl_ptrs (t, current_class_ptr);
|
||||||
|
|
||||||
for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
|
while (mem_init_list)
|
||||||
{
|
{
|
||||||
tree init, name;
|
tree init;
|
||||||
|
tree member;
|
||||||
int from_init_list;
|
int from_init_list;
|
||||||
|
|
||||||
/* member could be, for example, a CONST_DECL for an enumerated
|
member = TREE_PURPOSE (mem_init_list);
|
||||||
tag; we don't want to try to initialize that, since it already
|
|
||||||
has a value. */
|
|
||||||
if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* See if we had a user-specified member initialization. */
|
/* See if we had a user-specified member initialization. */
|
||||||
if (TREE_PURPOSE (mem_init_list))
|
if (TREE_TYPE (mem_init_list))
|
||||||
{
|
{
|
||||||
name = TREE_PURPOSE (mem_init_list);
|
|
||||||
init = TREE_VALUE (mem_init_list);
|
init = TREE_VALUE (mem_init_list);
|
||||||
from_init_list = 1;
|
from_init_list = 1;
|
||||||
|
|
||||||
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE
|
|
||||||
|| TREE_CODE (name) == FIELD_DECL, 349);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
name = DECL_NAME (member);
|
|
||||||
init = DECL_INITIAL (member);
|
init = DECL_INITIAL (member);
|
||||||
|
|
||||||
from_init_list = 0;
|
from_init_list = 0;
|
||||||
|
|
||||||
/* Effective C++ rule 12. */
|
/* Effective C++ rule 12. */
|
||||||
@ -621,35 +723,7 @@ emit_base_init (t)
|
|||||||
cp_warning ("`%D' should be initialized in the member initialization list", member);
|
cp_warning ("`%D' should be initialized in the member initialization list", member);
|
||||||
}
|
}
|
||||||
|
|
||||||
perform_member_init (member, name, init, from_init_list);
|
perform_member_init (member, init, from_init_list);
|
||||||
mem_init_list = TREE_CHAIN (mem_init_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now initialize any members from our bases. */
|
|
||||||
while (mem_init_list)
|
|
||||||
{
|
|
||||||
tree name, init, field;
|
|
||||||
|
|
||||||
if (TREE_PURPOSE (mem_init_list))
|
|
||||||
{
|
|
||||||
name = TREE_PURPOSE (mem_init_list);
|
|
||||||
init = TREE_VALUE (mem_init_list);
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
field = TREE_VALUE (field);
|
|
||||||
if (decl_type_context (field) != current_class_type)
|
|
||||||
cp_error ("field `%D' not in immediate context", field);
|
|
||||||
}
|
|
||||||
|
|
||||||
perform_member_init (field, name, init, 1);
|
|
||||||
}
|
|
||||||
mem_init_list = TREE_CHAIN (mem_init_list);
|
mem_init_list = TREE_CHAIN (mem_init_list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -992,7 +1066,7 @@ expand_member_init (exp, name, init)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
member_init = build_tree_list (name, init);
|
member_init = build_tree_list (field, init);
|
||||||
current_member_init_list = chainon (current_member_init_list, member_init);
|
current_member_init_list = chainon (current_member_init_list, member_init);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2189,9 +2189,7 @@ build_component_ref (datum, component, basetype_path, protect)
|
|||||||
tree base = context;
|
tree base = context;
|
||||||
while (!same_type_p (base, basetype) && TYPE_NAME (base)
|
while (!same_type_p (base, basetype) && TYPE_NAME (base)
|
||||||
&& ANON_AGGR_TYPE_P (base))
|
&& ANON_AGGR_TYPE_P (base))
|
||||||
{
|
|
||||||
base = TYPE_CONTEXT (base);
|
base = TYPE_CONTEXT (base);
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle base classes here... */
|
/* Handle base classes here... */
|
||||||
if (base != basetype && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype))
|
if (base != basetype && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype))
|
||||||
|
23
gcc/testsuite/g++.old-deja/g++.other/union3.C
Normal file
23
gcc/testsuite/g++.old-deja/g++.other/union3.C
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
int j;
|
||||||
|
|
||||||
|
A ();
|
||||||
|
};
|
||||||
|
|
||||||
|
A::A ()
|
||||||
|
: i (1), j (i = 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
return a.i;
|
||||||
|
}
|
33
gcc/testsuite/g++.old-deja/g++.other/union4.C
Normal file
33
gcc/testsuite/g++.old-deja/g++.other/union4.C
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Build don't link:
|
||||||
|
// Origin: Mark Mitchell <mark@codesourcery.com>
|
||||||
|
// Special g++ Options:
|
||||||
|
|
||||||
|
union A
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
A () : i (3), j (2) {} // ERROR - multiple initializations
|
||||||
|
};
|
||||||
|
|
||||||
|
union B
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
union {
|
||||||
|
int j;
|
||||||
|
};
|
||||||
|
|
||||||
|
B () : i (3), j (2) {} // ERROR - multiple initializations
|
||||||
|
};
|
||||||
|
|
||||||
|
union C
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
C () : i (3), j (2) {}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user