diff --git a/gcc/testsuite/g++.dg/torture/pr111019.C b/gcc/testsuite/g++.dg/torture/pr111019.C new file mode 100644 index 0000000000000000000000000000000000000000..ce21a311c96ef63e3949f584af9ef7f8f0d27ac8 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr111019.C @@ -0,0 +1,65 @@ +// { 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; +} diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc index 86ce6acb0231e7c03b07bf7307e54d9e56be750e..28813f11b99acb526982276ba2cb3557d7a12f62 100644 --- a/gcc/tree-ssa-loop-im.cc +++ b/gcc/tree-ssa-loop-im.cc @@ -1656,11 +1656,21 @@ gather_mem_refs_stmt (class loop *loop, gimple *stmt) 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,