summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr22071.C14
-rw-r--r--gcc/tree-ssa-structalias.c42
3 files changed, 62 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 37b484df4bc..70be4195356 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2005-06-29 Daniel Berlin <dberlin@dberlin.org>
+
+ Fix PR tree-optimization/22071
+
+ * tree-ssa-structalias.c (offset_overlaps_with_access): New
+ function.
+ (get_constraint_for_component_ref): Use it.
+
2005-07-01 Andrew Pinski <pinskia@physics.uc.edu>
PR other/22264
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr22071.C b/gcc/testsuite/g++.dg/tree-ssa/pr22071.C
new file mode 100644
index 00000000000..719aed37450
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr22071.C
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* This code ends up taking the address of part of the structure that is padding,
+ and because there is no real field there, the structure alias analyzer would
+ abort. */
+struct empty_class {};
+struct class1 : empty_class
+{
+ class1() {}
+ empty_class value_;
+};
+struct lambda : class1 { };
+lambda _1;
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 61137aaa63d..06adb3ec602 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -1940,6 +1940,25 @@ bitpos_of_field (const tree fdecl)
}
+/* Return true if an access to [ACCESSPOS, ACCESSSIZE]
+ overlaps with a field at [FIELDPOS, FIELDSIZE] */
+
+static bool
+offset_overlaps_with_access (const unsigned HOST_WIDE_INT fieldpos,
+ const unsigned HOST_WIDE_INT fieldsize,
+ const unsigned HOST_WIDE_INT accesspos,
+ const unsigned HOST_WIDE_INT accesssize)
+{
+ if (fieldpos == accesspos && fieldsize == accesssize)
+ return true;
+ if (accesspos >= fieldpos && accesspos <= (fieldpos + fieldsize))
+ return true;
+ if (accesspos < fieldpos && (accesspos + accesssize > fieldpos))
+ return true;
+
+ return false;
+}
+
/* Given a COMPONENT_REF T, return the constraint_expr for it. */
static struct constraint_expr
@@ -2000,8 +2019,27 @@ get_constraint_for_component_ref (tree t)
we may have to do something cute here. */
if (result.offset < get_varinfo (result.var)->fullsize)
- result.var = first_vi_for_offset (get_varinfo (result.var),
- result.offset)->id;
+ {
+ /* It's also not true that the constraint will actually start at the
+ right offset, it may start in some padding. We only care about
+ setting the constraint to the first actual field it touches, so
+ walk to find it. */
+ varinfo_t curr;
+ for (curr = get_varinfo (result.var); curr; curr = curr->next)
+ {
+ if (offset_overlaps_with_access (curr->offset, curr->size,
+ result.offset, bitsize))
+ {
+ result.var = curr->id;
+ break;
+
+ }
+ }
+ /* assert that we found *some* field there. The user couldn't be
+ accessing *only* padding. */
+
+ gcc_assert (curr);
+ }
else
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Access to past the end of variable, ignoring\n");