On 7/16/24 6:54 PM, Andi Kleen wrote:
On Tue, Jul 16, 2024 at 06:06:42PM -0400, Jason Merrill wrote:
On 7/16/24 5:55 PM, Andi Kleen wrote:
On Tue, Jul 16, 2024 at 12:52:31PM -0700, Andi Kleen wrote:
On Tue, Jul 16, 2024 at 02:51:13PM -0400, Jason Merrill wrote:
On 7/16/24 12:18 PM, Andi Kleen wrote:
On Tue, Jul 16, 2024 at 11:17:14AM -0400, Jason Merrill wrote:
On 7/16/24 11:15 AM, Andi Kleen wrote:
In the adjusted test it looks like the types of f and g match, so I wouldn't
expect an error.
Good point! Missing the forest for the trees.
Anyways are the C++ patches ok with this change?
I'm still looking for a test which does error because the types are
different.
Like this?
Where the called function returns C and the callee function does not.
In this case the attribute seems to get lost and it succeeds.
This somewhat hackish patch fixes it here, to handle the case
of a TARGET_EXPR where the CALL_EXPR is in the cleanup. extract_call
bails on that.
The CALL_EXPR in the cleanup is calling the destructor, that's not what
we're trying to tail-call.
I think the problem here is that the call to f<C> is represented with an
AGGR_INIT_EXPR instead of CALL_EXPR, so you need to handle the flag on that
tree_code as well.
Okay this seems to work
(I had to adjust the test case because it now correctly errors out
on passing the class at -O0)
Great. Does it also work in a non-template function?
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4bb3e9c4989b..5ec8102c1849 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4245,6 +4245,10 @@ templated_operator_saved_lookups (tree t)
#define AGGR_INIT_FROM_THUNK_P(NODE) \
(AGGR_INIT_EXPR_CHECK (NODE)->base.protected_flag)
+/* Nonzero means that the call was marked musttail. */
+#define AGGR_INIT_EXPR_MUST_TAIL(NODE) \
+ (AGGR_INIT_EXPR_CHECK (NODE)->base.static_flag)
+
/* AGGR_INIT_EXPR accessors. These are equivalent to the CALL_EXPR
accessors, except for AGGR_INIT_EXPR_SLOT (which takes the place of
CALL_EXPR_STATIC_CHAIN). */
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 3b914089a6e2..d668c5af6a23 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21124,6 +21124,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t
complain, tree in_decl)
CALL_EXPR_REVERSE_ARGS (call) = rev;
if (TREE_CODE (call) == CALL_EXPR)
CALL_EXPR_MUST_TAIL_CALL (call) = mtc;
+ else if (TREE_CODE (call) == AGGR_INIT_EXPR)
+ AGGR_INIT_EXPR_MUST_TAIL (call) = mtc;
}
if (warning_suppressed_p (t, OPT_Wpessimizing_move))
/* This also suppresses -Wredundant-move. */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index cd3df13772db..fb45974cd90f 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4979,6 +4979,7 @@ simplify_aggr_init_expr (tree *tp)
= CALL_EXPR_OPERATOR_SYNTAX (aggr_init_expr);
CALL_EXPR_ORDERED_ARGS (call_expr) = CALL_EXPR_ORDERED_ARGS
(aggr_init_expr);
CALL_EXPR_REVERSE_ARGS (call_expr) = CALL_EXPR_REVERSE_ARGS
(aggr_init_expr);
+ CALL_EXPR_MUST_TAIL_CALL (call_expr) = AGGR_INIT_EXPR_MUST_TAIL
(aggr_init_expr);
if (style == ctor)
{
diff --git a/gcc/testsuite/g++.dg/musttail10.C
b/gcc/testsuite/g++.dg/musttail10.C
index e454a6238a06..93ec32db160a 100644
--- a/gcc/testsuite/g++.dg/musttail10.C
+++ b/gcc/testsuite/g++.dg/musttail10.C
@@ -14,9 +14,11 @@ template <class T>
__attribute__((noinline, noclone, noipa))
T g2() { [[gnu::musttail]] return f<T>(); }
+#if __OPTIMIZE__ >= 1
template <class T>
__attribute__((noinline, noclone, noipa))
T g3() { [[gnu::musttail]] return f<T>(); }
+#endif
template <class T>
__attribute__((noinline, noclone, noipa))
@@ -28,12 +30,20 @@ class C
public:
C(double x) : x(x) {}
~C() { asm("":::"memory"); }
+ operator int() { return x; }
};
+template <class T>
+__attribute__((noinline, noclone, noipa))
+T g5() { [[gnu::musttail]] return f<C>(); } /* { dg-error "cannot tail-call" }
*/
+
int main()
{
g1<int>();
g2<double>();
+#if __OPTIMIZE__ >= 1
g3<C>();
+#endif
g4<int>();
+ g5<int>();
}