re PR c/2820 (unnamed union inside unnamed struct changes rest of the struct)

PR c/2820
	* c-typeck.c (lookup_field): Rework to return a chain down to
	the looked-up field.
	(build_component_ref): Use the new lookup_field to handle
	nested anonymous entities correctly.

	* testsuite/gcc.c-torture/execute/anon-1.c: New test.

From-SVN: r46774
This commit is contained in:
Neil Booth 2001-11-04 17:54:57 +00:00 committed by Neil Booth
parent f282747406
commit e9b2c82318
4 changed files with 83 additions and 50 deletions

View File

@ -1,3 +1,11 @@
2001-11-04 Neil Booth <neil@cat.daikokuya.demon.co.uk>
PR c/2820
* c-typeck.c (lookup_field): Rework to return a chain down to
the looked-up field.
(build_component_ref): Use the new lookup_field to handle
nested anonymous entities correctly.
Sun Nov 4 11:53:31 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* config/sparc/sparc.c (sparc_emit_set_const32, GEN_HIGHINT64):

View File

@ -55,7 +55,7 @@ static int comp_target_types PARAMS ((tree, tree));
static int function_types_compatible_p PARAMS ((tree, tree));
static int type_lists_compatible_p PARAMS ((tree, tree));
static tree decl_constant_value_for_broken_optimization PARAMS ((tree));
static tree lookup_field PARAMS ((tree, tree, tree *));
static tree lookup_field PARAMS ((tree, tree));
static tree convert_arguments PARAMS ((tree, tree, tree, tree));
static tree pointer_int_sum PARAMS ((enum tree_code, tree, tree));
static tree pointer_diff PARAMS ((tree, tree));
@ -990,17 +990,20 @@ default_conversion (exp)
return exp;
}
/* Look up component name in the structure type definition.
/* Look up COMPONENT in a structure or union DECL.
If this component name is found indirectly within an anonymous union,
store in *INDIRECT the component which directly contains
that anonymous union. Otherwise, set *INDIRECT to 0. */
If the component name is not found, returns NULL_TREE. Otherwise,
the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
stepping down the chain to the component, which is in the last
TREE_VALUE of the list. Normally the list is of length one, but if
the component is embedded within (nested) anonymous structures or
unions, the list steps down the chain to the component. */
static tree
lookup_field (type, component, indirect)
tree type, component;
tree *indirect;
lookup_field (decl, component)
tree decl, component;
{
tree type = TREE_TYPE (decl);
tree field;
/* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
@ -1026,18 +1029,15 @@ lookup_field (type, component, indirect)
/* Step through all anon unions in linear fashion. */
while (DECL_NAME (field_array[bot]) == NULL_TREE)
{
tree anon = 0, junk;
field = field_array[bot++];
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
anon = lookup_field (TREE_TYPE (field), component, &junk);
if (anon != NULL_TREE)
{
*indirect = field;
return anon;
}
tree anon = lookup_field (field, component);
if (anon)
return tree_cons (NULL_TREE, field, anon);
}
}
/* Entire record is only anon unions. */
@ -1059,35 +1059,31 @@ lookup_field (type, component, indirect)
if (DECL_NAME (field_array[bot]) == component)
field = field_array[bot];
else if (DECL_NAME (field) != component)
field = 0;
return NULL_TREE;
}
else
{
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
if (DECL_NAME (field) == NULL_TREE)
if (DECL_NAME (field) == NULL_TREE
&& (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
{
tree junk;
tree anon = 0;
tree anon = lookup_field (field, component);
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
anon = lookup_field (TREE_TYPE (field), component, &junk);
if (anon != NULL_TREE)
{
*indirect = field;
return anon;
}
if (anon)
return tree_cons (NULL_TREE, field, anon);
}
if (DECL_NAME (field) == component)
break;
}
if (field == NULL_TREE)
return NULL_TREE;
}
*indirect = NULL_TREE;
return field;
return tree_cons (NULL_TREE, field, NULL_TREE);
}
/* Make an expression to refer to the COMPONENT field of
@ -1126,15 +1122,13 @@ build_component_ref (datum, component)
if (code == RECORD_TYPE || code == UNION_TYPE)
{
tree indirect = 0;
if (!COMPLETE_TYPE_P (type))
{
incomplete_type_error (NULL_TREE, type);
return error_mark_node;
}
field = lookup_field (type, component, &indirect);
field = lookup_field (datum, component);
if (!field)
{
@ -1143,29 +1137,27 @@ build_component_ref (datum, component)
IDENTIFIER_POINTER (component));
return error_mark_node;
}
if (TREE_TYPE (field) == error_mark_node)
return error_mark_node;
/* If FIELD was found buried within an anonymous union,
make one COMPONENT_REF to get that anonymous union,
then fall thru to make a second COMPONENT_REF to get FIELD. */
if (indirect != 0)
/* Chain the COMPONENT_REFs if necessary down to the FIELD.
This might be better solved in future the way the C++ front
end does it - by giving the anonymous entities each a
separate name and type, and then have build_component_ref
recursively call itself. We can't do that here. */
for (; field; field = TREE_CHAIN (field))
{
ref = build (COMPONENT_REF, TREE_TYPE (indirect), datum, indirect);
if (TREE_READONLY (datum) || TREE_READONLY (indirect))
tree subdatum = TREE_VALUE (field);
if (TREE_TYPE (subdatum) == error_mark_node)
return error_mark_node;
ref = build (COMPONENT_REF, TREE_TYPE (subdatum), datum, subdatum);
if (TREE_READONLY (datum) || TREE_READONLY (subdatum))
TREE_READONLY (ref) = 1;
if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (indirect))
if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum))
TREE_THIS_VOLATILE (ref) = 1;
datum = ref;
}
ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field);
if (TREE_READONLY (datum) || TREE_READONLY (field))
TREE_READONLY (ref) = 1;
if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
TREE_THIS_VOLATILE (ref) = 1;
return ref;
}
else if (code != ERROR_MARK)

View File

@ -1,3 +1,7 @@
2001-11-04 Neil Booth <neil@cat.daikokuya.demon.co.uk>
* gcc.c-torture/execute/anon-1.c: New test.
2001-11-03 Geoffrey Keating <geoffk@redhat.com>
* g++.old-deja/g++.bugs/900227_01.C: short and pointer are the

View File

@ -0,0 +1,29 @@
/* Copyright (C) 2001 Free Software Foundation, Inc. */
/* Source: Neil Booth, 4 Nov 2001, derived from PR 2820 - field lookup in
nested anonymous entities was broken. */
struct
{
int x;
struct
{
int a;
union
{
int b;
};
};
} foo;
int
main(int argc, char *argv[])
{
foo.b = 6;
foo.a = 5;
if (foo.b != 6)
abort ();
return 0;
}