diff options
author | dnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-11-08 00:01:38 +0000 |
---|---|---|
committer | dnovillo <dnovillo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-11-08 00:01:38 +0000 |
commit | f5ef996258725dd451733c21e2bba88c87019646 (patch) | |
tree | 06efa0a928d92fb0ec421d6bddae19cebfe2145b /gcc/tree-ssa-operands.c | |
parent | a7905afa00a185861ad143eea26089abd5dbb966 (diff) | |
download | gcc-f5ef996258725dd451733c21e2bba88c87019646.tar.gz |
PR 33870
* tree.h (struct tree_struct_field_tag): Add field in_nested_struct.
(SFT_IN_NESTED_STRUCT): Define.
* tree-dfa.c (dump_subvars_for): Show offset of each
sub-var.
* tree-flow.h (struct fieldoff): Add field in_nested_struct.
* tree-ssa-structalias.c (struct variable_info): Likewise.
(push_fields_onto_fieldstack): If OFFSET is positive,
set in_nested_struct.
(create_variable_info_for): Copy setting of
in_nested_struct from the field offset object.
(set_uids_in_ptset): Set SFT_IN_NESTED_STRUCT from the
variable info object.
* tree-ssa-operands.c (add_vars_for_offset): If VAR
belongs to a nested structure, adjust OFFSET by
SFT_OFFSET(VAR).
testsuite/ChangeLog
* gcc.c-torture/execute/pr33870.x: Remove.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@129976 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-operands.c')
-rw-r--r-- | gcc/tree-ssa-operands.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 9ce133d5eae..87eec7452b7 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -1397,8 +1397,48 @@ add_vars_for_offset (tree var, unsigned HOST_WIDE_INT offset, subvar_t sv; unsigned int i; - /* Adjust offset by the pointed-to location. */ - offset += SFT_OFFSET (var); + if (SFT_IN_NESTED_STRUCT (var)) + { + /* Since VAR is an SFT inside a nested structure, the OFFSET + computed by get_ref_base_and_extent is the offset from the + start of the immediately containing structure. However, to + find out what other SFTs are affected by this reference, we + need to know the offsets starting at the root structure in + the nesting hierarchy. + + For instance, given the following structure: + + struct X { + int a; + struct Y { + int b; + struct Z { + int c[3]; + } d; + } e; + } m; + + and the following address expression: + + p_1 = &m.e.d; + + This structure will receive 5 SFTs, namely 2 for fields 'a' + and 'b' and 3 for the array 'c' in struct Z. So, the + reference p_1->c[2] and m.e.d.c[2] access the exact same + memory location (ie, SFT.5). + + Now, alias analysis computed the points-to set for pointer + p_1 as { SFT.3 } because that is the first field that p_1 + actually points to. When the expression p_1->c[2] is + analyzed, get_ref_base_and_extent will return an offset of 96 + because we are accessing the third element of the array. But + the SFT we are looking for is actually at offset 160, + counting from the top of struct X. + + Therefore, we adjust OFFSET by the offset of VAR so that we + can get at all the fields starting at VAR. */ + offset += SFT_OFFSET (var); + } /* Add all subvars of var that overlap with the access. Binary search for the first relevant SFT. */ |