129 lines
4.2 KiB
Diff
129 lines
4.2 KiB
Diff
commit 20e9d78543493f2f6aeef19af4cea54696247fc8
|
|
Author: Richard Biener <rguenther@suse.de>
|
|
Date: Tue Jan 14 08:43:32 2020 +0100
|
|
|
|
PR middle-end/93246 - missing alias subsets
|
|
|
|
Starting with the introduction of TYPE_TYPELESS_STORAGE the situation
|
|
of having a alias-set zero aggregate field became more common which
|
|
prevents recording alias-sets of fields of said aggregate as subset
|
|
of the outer aggregate. component_uses_parent_alias_set_from in the
|
|
past fended off some of the issues with that but the alias oracles
|
|
use of the alias set of the base of an access path never appropriately
|
|
handled it.
|
|
|
|
The following makes it so that alias-sets of fields of alias-set zero
|
|
aggregate fields are still recorded as subset of the container.
|
|
|
|
2020-01-14 Richard Biener <rguenther@suse.de>
|
|
|
|
PR middle-end/93246
|
|
* alias.c (record_component_aliases): Take superset to record
|
|
into, recurse for alias-set zero fields.
|
|
(record_component_aliases): New oveerload wrapping around the above.
|
|
|
|
* g++.dg/torture/pr93246.C: New testcase.
|
|
|
|
diff --git a/gcc/alias.c b/gcc/alias.c
|
|
index b64e3ea264d..053c3494e79 100644
|
|
--- a/gcc/alias.c
|
|
+++ b/gcc/alias.c
|
|
@@ -1186,15 +1186,14 @@ record_alias_subset (alias_set_type superset, alias_set_type subset)
|
|
}
|
|
}
|
|
|
|
-/* Record that component types of TYPE, if any, are part of that type for
|
|
+/* Record that component types of TYPE, if any, are part of SUPERSET for
|
|
aliasing purposes. For record types, we only record component types
|
|
for fields that are not marked non-addressable. For array types, we
|
|
only record the component type if it is not marked non-aliased. */
|
|
|
|
void
|
|
-record_component_aliases (tree type)
|
|
+record_component_aliases (tree type, alias_set_type superset)
|
|
{
|
|
- alias_set_type superset = get_alias_set (type);
|
|
tree field;
|
|
|
|
if (superset == 0)
|
|
@@ -1244,7 +1243,21 @@ record_component_aliases (tree type)
|
|
== get_alias_set (TREE_TYPE (field)));
|
|
}
|
|
|
|
- record_alias_subset (superset, get_alias_set (t));
|
|
+ alias_set_type set = get_alias_set (t);
|
|
+ record_alias_subset (superset, set);
|
|
+ /* If the field has alias-set zero make sure to still record
|
|
+ any componets of it. This makes sure that for
|
|
+ struct A {
|
|
+ struct B {
|
|
+ int i;
|
|
+ char c[4];
|
|
+ } b;
|
|
+ };
|
|
+ in C++ even though 'B' has alias-set zero because
|
|
+ TYPE_TYPELESS_STORAGE is set, 'A' has the alias-set of
|
|
+ 'int' as subset. */
|
|
+ if (set == 0)
|
|
+ record_component_aliases (t, superset);
|
|
}
|
|
break;
|
|
|
|
@@ -1260,6 +1273,19 @@ record_component_aliases (tree type)
|
|
}
|
|
}
|
|
|
|
+/* Record that component types of TYPE, if any, are part of that type for
|
|
+ aliasing purposes. For record types, we only record component types
|
|
+ for fields that are not marked non-addressable. For array types, we
|
|
+ only record the component type if it is not marked non-aliased. */
|
|
+
|
|
+void
|
|
+record_component_aliases (tree type)
|
|
+{
|
|
+ alias_set_type superset = get_alias_set (type);
|
|
+ record_component_aliases (type, superset);
|
|
+}
|
|
+
|
|
+
|
|
/* Allocate an alias set for use in storing and reading from the varargs
|
|
spill area. */
|
|
|
|
diff --git a/gcc/testsuite/g++.dg/torture/pr93246.C b/gcc/testsuite/g++.dg/torture/pr93246.C
|
|
new file mode 100644
|
|
index 00000000000..4c523443175
|
|
--- /dev/null
|
|
+++ b/gcc/testsuite/g++.dg/torture/pr93246.C
|
|
@@ -0,0 +1,31 @@
|
|
+// { dg-do run }
|
|
+// { dg-additional-options "-fstrict-aliasing" }
|
|
+
|
|
+template <typename = void> struct Optional {
|
|
+ auto is_present() const { const bool &p = inner.present; return p; }
|
|
+ auto set_present() { if (not is_present()) inner.present = true; }
|
|
+ struct InnerType {
|
|
+ bool present = false;
|
|
+ char padding[1] = {0};
|
|
+ };
|
|
+ using inner_t = InnerType;
|
|
+ inner_t inner = {};
|
|
+};
|
|
+
|
|
+template <typename WrappedType> struct Wrapper {
|
|
+ auto operator-> () { return value; }
|
|
+ WrappedType *value;
|
|
+};
|
|
+
|
|
+void __attribute__((noinline,noclone)) foo(Optional<>& x) { __asm__ volatile ("":::"memory"); }
|
|
+
|
|
+int main()
|
|
+{
|
|
+ Optional<> buf{};
|
|
+ foo(buf);
|
|
+ Wrapper<Optional<>> wo = {&buf};
|
|
+ wo->set_present();
|
|
+ auto x = wo->is_present();
|
|
+ if (!x)
|
|
+ __builtin_abort ();
|
|
+}
|