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:
parent
f282747406
commit
e9b2c82318
|
@ -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>
|
Sun Nov 4 11:53:31 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
|
||||||
|
|
||||||
* config/sparc/sparc.c (sparc_emit_set_const32, GEN_HIGHINT64):
|
* config/sparc/sparc.c (sparc_emit_set_const32, GEN_HIGHINT64):
|
||||||
|
|
|
@ -55,7 +55,7 @@ static int comp_target_types PARAMS ((tree, tree));
|
||||||
static int function_types_compatible_p PARAMS ((tree, tree));
|
static int function_types_compatible_p PARAMS ((tree, tree));
|
||||||
static int type_lists_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 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 convert_arguments PARAMS ((tree, tree, tree, tree));
|
||||||
static tree pointer_int_sum PARAMS ((enum tree_code, tree, tree));
|
static tree pointer_int_sum PARAMS ((enum tree_code, tree, tree));
|
||||||
static tree pointer_diff PARAMS ((tree, tree));
|
static tree pointer_diff PARAMS ((tree, tree));
|
||||||
|
@ -990,17 +990,20 @@ default_conversion (exp)
|
||||||
return 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,
|
If the component name is not found, returns NULL_TREE. Otherwise,
|
||||||
store in *INDIRECT the component which directly contains
|
the return value is a TREE_LIST, with each TREE_VALUE a FIELD_DECL
|
||||||
that anonymous union. Otherwise, set *INDIRECT to 0. */
|
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
|
static tree
|
||||||
lookup_field (type, component, indirect)
|
lookup_field (decl, component)
|
||||||
tree type, component;
|
tree decl, component;
|
||||||
tree *indirect;
|
|
||||||
{
|
{
|
||||||
|
tree type = TREE_TYPE (decl);
|
||||||
tree field;
|
tree field;
|
||||||
|
|
||||||
/* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
|
/* 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. */
|
/* Step through all anon unions in linear fashion. */
|
||||||
while (DECL_NAME (field_array[bot]) == NULL_TREE)
|
while (DECL_NAME (field_array[bot]) == NULL_TREE)
|
||||||
{
|
{
|
||||||
tree anon = 0, junk;
|
|
||||||
|
|
||||||
field = field_array[bot++];
|
field = field_array[bot++];
|
||||||
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|
||||||
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
|
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
|
||||||
anon = lookup_field (TREE_TYPE (field), component, &junk);
|
|
||||||
|
|
||||||
if (anon != NULL_TREE)
|
|
||||||
{
|
{
|
||||||
*indirect = field;
|
tree anon = lookup_field (field, component);
|
||||||
return anon;
|
|
||||||
}
|
if (anon)
|
||||||
|
return tree_cons (NULL_TREE, field, anon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Entire record is only anon unions. */
|
/* Entire record is only anon unions. */
|
||||||
|
@ -1059,35 +1059,31 @@ lookup_field (type, component, indirect)
|
||||||
if (DECL_NAME (field_array[bot]) == component)
|
if (DECL_NAME (field_array[bot]) == component)
|
||||||
field = field_array[bot];
|
field = field_array[bot];
|
||||||
else if (DECL_NAME (field) != component)
|
else if (DECL_NAME (field) != component)
|
||||||
field = 0;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
|
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 = lookup_field (field, component);
|
||||||
tree anon = 0;
|
|
||||||
|
|
||||||
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
|
if (anon)
|
||||||
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
|
return tree_cons (NULL_TREE, field, anon);
|
||||||
anon = lookup_field (TREE_TYPE (field), component, &junk);
|
|
||||||
|
|
||||||
if (anon != NULL_TREE)
|
|
||||||
{
|
|
||||||
*indirect = field;
|
|
||||||
return anon;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DECL_NAME (field) == component)
|
if (DECL_NAME (field) == component)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (field == NULL_TREE)
|
||||||
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*indirect = NULL_TREE;
|
return tree_cons (NULL_TREE, field, NULL_TREE);
|
||||||
return field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make an expression to refer to the COMPONENT field of
|
/* 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)
|
if (code == RECORD_TYPE || code == UNION_TYPE)
|
||||||
{
|
{
|
||||||
tree indirect = 0;
|
|
||||||
|
|
||||||
if (!COMPLETE_TYPE_P (type))
|
if (!COMPLETE_TYPE_P (type))
|
||||||
{
|
{
|
||||||
incomplete_type_error (NULL_TREE, type);
|
incomplete_type_error (NULL_TREE, type);
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
field = lookup_field (type, component, &indirect);
|
field = lookup_field (datum, component);
|
||||||
|
|
||||||
if (!field)
|
if (!field)
|
||||||
{
|
{
|
||||||
|
@ -1143,29 +1137,27 @@ build_component_ref (datum, component)
|
||||||
IDENTIFIER_POINTER (component));
|
IDENTIFIER_POINTER (component));
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
if (TREE_TYPE (field) == error_mark_node)
|
|
||||||
return error_mark_node;
|
|
||||||
|
|
||||||
/* If FIELD was found buried within an anonymous union,
|
/* Chain the COMPONENT_REFs if necessary down to the FIELD.
|
||||||
make one COMPONENT_REF to get that anonymous union,
|
This might be better solved in future the way the C++ front
|
||||||
then fall thru to make a second COMPONENT_REF to get FIELD. */
|
end does it - by giving the anonymous entities each a
|
||||||
if (indirect != 0)
|
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);
|
tree subdatum = TREE_VALUE (field);
|
||||||
if (TREE_READONLY (datum) || TREE_READONLY (indirect))
|
|
||||||
|
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;
|
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;
|
TREE_THIS_VOLATILE (ref) = 1;
|
||||||
datum = ref;
|
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;
|
return ref;
|
||||||
}
|
}
|
||||||
else if (code != ERROR_MARK)
|
else if (code != ERROR_MARK)
|
||||||
|
|
|
@ -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>
|
2001-11-03 Geoffrey Keating <geoffk@redhat.com>
|
||||||
|
|
||||||
* g++.old-deja/g++.bugs/900227_01.C: short and pointer are the
|
* g++.old-deja/g++.bugs/900227_01.C: short and pointer are the
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue