aboutsummaryrefslogtreecommitdiff
path: root/gcc/alias.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/alias.cc')
-rw-r--r--gcc/alias.cc17
1 files changed, 16 insertions, 1 deletions
diff --git a/gcc/alias.cc b/gcc/alias.cc
index 7c1af1f..86d8f71 100644
--- a/gcc/alias.cc
+++ b/gcc/alias.cc
@@ -774,7 +774,22 @@ reference_alias_ptr_type_1 (tree *t)
&& (TYPE_MAIN_VARIANT (TREE_TYPE (inner))
!= TYPE_MAIN_VARIANT
(TREE_TYPE (TREE_TYPE (TREE_OPERAND (inner, 1))))))
- return TREE_TYPE (TREE_OPERAND (inner, 1));
+ {
+ tree alias_ptrtype = TREE_TYPE (TREE_OPERAND (inner, 1));
+ /* Unless we have the (aggregate) effective type of the access
+ somewhere on the access path. If we have for example
+ (&a->elts[i])->l.len exposed by abstraction we'd see
+ MEM <A> [(B *)a].elts[i].l.len and we can use the alias set
+ of 'len' when typeof (MEM <A> [(B *)a].elts[i]) == B for
+ example. See PR111715. */
+ tree inner = *t;
+ while (handled_component_p (inner)
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (inner))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (alias_ptrtype))))
+ inner = TREE_OPERAND (inner, 0);
+ if (TREE_CODE (inner) == MEM_REF)
+ return alias_ptrtype;
+ }
/* Otherwise, pick up the outermost object that we could have
a pointer to. */