--- /dev/null
+// { dg-do run }
+// { dg-additional-options "-fstrict-aliasing" }
+
+#include <cassert>
+#include <memory>
+#include <string>
+
+class Base
+{
+public:
+ Base* previous = nullptr;
+ Base* next = nullptr;
+ Base* target = nullptr;
+};
+
+class Target : public Base
+{
+public:
+ __attribute__((always_inline)) ~Target()
+ {
+ while (this->next)
+ {
+ Base* n = this->next;
+
+ if (n->previous)
+ n->previous->next = n->next;
+ if (n->next)
+ n->next->previous = n->previous;
+ n->previous = nullptr;
+ n->next = nullptr;
+ n->target = nullptr;
+ }
+ }
+};
+
+template <typename T>
+class TargetWithData final : public Target
+{
+public:
+ TargetWithData(T data)
+ : data(data)
+ {}
+ T data;
+};
+
+void test()
+{
+ printf("test\n");
+ Base ptr;
+ {
+ auto data = std::make_unique<TargetWithData<std::string>>(std::string("asdf"));
+ ptr.target = &*data;
+ ptr.previous = &*data;
+ data->next = &ptr;
+
+ assert(ptr.target != nullptr);
+ }
+ assert(ptr.target == nullptr);
+}
+
+int main(int, char**)
+{
+ test();
+ return 0;
+}
unshare_expr (mem_base));
if (TYPE_ALIGN (ref_type) != ref_align)
ref_type = build_aligned_type (ref_type, ref_align);
- (*slot)->mem.ref
+ tree new_ref
= fold_build2 (MEM_REF, ref_type, tmp,
build_int_cst (ref_alias_type, mem_off));
if ((*slot)->mem.volatile_p)
- TREE_THIS_VOLATILE ((*slot)->mem.ref) = 1;
+ TREE_THIS_VOLATILE (new_ref) = 1;
+ (*slot)->mem.ref = new_ref;
+ /* Make sure the recorded base and offset are consistent
+ with the newly built ref. */
+ if (TREE_CODE (TREE_OPERAND (new_ref, 0)) == ADDR_EXPR)
+ ;
+ else
+ {
+ (*slot)->mem.base = new_ref;
+ (*slot)->mem.offset = 0;
+ }
gcc_checking_assert (TREE_CODE ((*slot)->mem.ref) == MEM_REF
&& is_gimple_mem_ref_addr
(TREE_OPERAND ((*slot)->mem.ref,