On Mon, Jul 15, 2024 at 06:57:57PM -0400, Jason Merrill wrote: > On 7/8/24 12:56 PM, Andi Kleen wrote: > > diff --git a/gcc/testsuite/g++.dg/musttail10.C > > b/gcc/testsuite/g++.dg/musttail10.C > > new file mode 100644 > > index 000000000000..9b7043b8a306 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/musttail10.C > > @@ -0,0 +1,34 @@ > > +/* { dg-do compile { target { tail_call } } } */ > > +/* { dg-options "-std=gnu++11" } */ > > +/* { dg-additional-options "-fdelayed-branch" { target sparc*-*-* } } */ > > + > > +int f(); > > + > > +double h() { [[gnu::musttail]] return f(); } /* { dg-error "cannot > > tail-call" } */ > > + > > +template <class T> > > +__attribute__((noinline, noclone, noipa)) > > +T g1() { [[gnu::musttail]] return f(); } /* { dg-error "target is not > > able" "" { target powerpc*-*-* } } */ > > + > > +template <class T> > > +__attribute__((noinline, noclone, noipa)) > > +T g2() { [[gnu::musttail]] return f(); } /* { dg-error "cannot tail-call" > > } */ > > + > > +template <class T> > > +__attribute__((noinline, noclone, noipa)) > > +T g3() { [[gnu::musttail]] return f(); } /* { dg-error "cannot tail-call" > > } */ > > + > > +class C > > +{ > > + double x; > > +public: > > + C(double x) : x(x) {} > > + ~C() { asm("":::"memory"); } > > +}; > > + > > +int main() > > +{ > > + g1<int>(); > > + g2<double>(); > > + g3<C>(); > > +} > > I had asked for this test to check the case where the function called with > [[musttail]] returns a non-trivially-copyable class; the test now includes > such a class, but all the [[musttail]] calls are still to a function that > returns int.
Thanks Jason. I fixed the test case, but now the musttail gets lost, no error for g2/g3. That means the flag is still lost somewhere. Does something outside tsubst need changes too? Right now tsubst has only this: @@ -21113,12 +21113,17 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) bool op = CALL_EXPR_OPERATOR_SYNTAX (t); bool ord = CALL_EXPR_ORDERED_ARGS (t); bool rev = CALL_EXPR_REVERSE_ARGS (t); - if (op || ord || rev) + bool mtc = false; + if (TREE_CODE (t) == CALL_EXPR) + mtc = CALL_EXPR_MUST_TAIL_CALL (t); + if (op || ord || rev || mtc) if (tree call = extract_call_expr (ret)) { CALL_EXPR_OPERATOR_SYNTAX (call) = op; CALL_EXPR_ORDERED_ARGS (call) = ord; CALL_EXPR_REVERSE_ARGS (call) = rev; + if (TREE_CODE (call) == CALL_EXPR) + CALL_EXPR_MUST_TAIL_CALL (call) = mtc; } if (warning_suppressed_p (t, OPT_Wpessimizing_move)) /* This also suppresses -Wredundant-move. */ Fixed test case: template <class T> T f(); double h() { [[gnu::musttail]] return f<int>(); } /* { dg-error "cannot tail-call" } */ template <class T> __attribute__((noinline, noclone, noipa)) T g1() { [[gnu::musttail]] return f<T>(); } /* { dg-error "target is not able" "" { target powerpc*-*-* } } */ template <class T> __attribute__((noinline, noclone, noipa)) T g2() { [[gnu::musttail]] return f<T>(); } /* { dg-error "cannot tail-call" } */ template <class T> __attribute__((noinline, noclone, noipa)) T g3() { [[gnu::musttail]] return f<T>(); } /* { dg-error "cannot tail-call" } */ class C { double x; public: C(double x) : x(x) {} ~C() { asm("":::"memory"); } }; int main() { g1<int>(); g2<double>(); g3<C>(); }