When the C++ frontend clones a CTOR we do not copy ASM_EXPR constraints fully as walk_tree does not recurse to TREE_PURPOSE of TREE_LIST nodes. At this point doing that seems too dangerous so the following instead avoids gimplification of ASM_EXPRs to clobber the shared constraints and unshares it there, like it also unshares TREE_VALUE when it re-writes a "+" output constraint to separate "=" output and matching input constraint.
Bootstrapped and tested on x86_64-unknown-linux-gnu, OK? Thanks, Richard. PR middle-end/66279 * gimplify.cc (gimplify_asm_expr): Copy TREE_PURPOSE before rewriting it for "+" processing. * g++.dg/pr66279.C: New testcase. --- gcc/gimplify.cc | 1 + gcc/testsuite/g++.dg/pr66279.C | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 gcc/testsuite/g++.dg/pr66279.C diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc index 756cdea173f..160e7fc9df6 100644 --- a/gcc/gimplify.cc +++ b/gcc/gimplify.cc @@ -7810,6 +7810,7 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) /* Turn the in/out constraint into an output constraint. */ char *p = xstrdup (constraint); p[0] = '='; + TREE_PURPOSE (link) = unshare_expr (TREE_PURPOSE (link)); TREE_VALUE (TREE_PURPOSE (link)) = build_string (constraint_len, p); /* And add a matching input constraint. */ diff --git a/gcc/testsuite/g++.dg/pr66279.C b/gcc/testsuite/g++.dg/pr66279.C new file mode 100644 index 00000000000..c878044a83b --- /dev/null +++ b/gcc/testsuite/g++.dg/pr66279.C @@ -0,0 +1,23 @@ +// { dg-do run } + +struct A {}; + +struct B : public virtual A +{ + B(); +}; + +B::B() +{ + unsigned int x = 42; + + __asm__ __volatile__ ("" : "+r"(x)); + + if (x != 42) + __builtin_abort (); +} + +int main() +{ + B b; +} -- 2.43.0