Hi Jason,
On Mon, May 06, 2024 at 11:02:20PM -0400, Jason Merrill wrote:
> > @@ -30189,7 +30207,7 @@ cp_parser_std_attribute (cp_parser *parser, tree
> > attr_ns)
> > /* Maybe we don't expect to see any arguments for this attribute. */
> > const attribute_spec *as
> > = lookup_attribute_spec (TREE_PURPOSE (attribute));
> > - if (as && as->max_length == 0)
> > + if ((as && as->max_length == 0) || is_attribute_p ("musttail",
> > attr_id))
>
> I'd prefer to add an attribute to the table, rather than special-case it
> here; apart from consistency, it seems likely that someone will later want
> to apply it to a function.
Just to clarify. I can add it to the table, but it would be a nop there
for now because the table is not used for statement attributes by
the current parser.
>
> You need a template testcase; I expect it doesn't work in templates with the
> current patch. It's probably enough to copy it in tsubst_expr where we
> currently propagate CALL_EXPR_OPERATOR_SYNTAX.
I tried it with the appended test case, everything seems to work without
changes.
Does it cover the cases you were concerned about?
>
> You also need a testcase where the function returns a class; in that case
> the call will often appear as AGGR_INIT_EXPR rather than CALL_EXPR, so
> you'll need to handle that as well. And see the places that copy flags like
> CALL_EXPR_OPERATOR_SYNTAX between CALL_EXPR and AGGR_INIT_EXPR.
Dito.
-Andi
/* { dg-do compile { target { tail_call } } } */
/* { dg-options "-O2" } */
/* { dg-additional-options "-fdelayed-branch" { target sparc*-*-* } } */
class Foo {
public:
int a, b;
Foo(int a, int b) : a(a), b(b) {}
};
Foo __attribute__((noinline,noclone,noipa))
callee (int i)
{
return Foo(i, i+1);
}
Foo __attribute__((noinline,noclone,noipa))
caller (int i)
{
[[gnu::musttail]] return callee (i + 1);
}
template<typename T>
T __attribute__((noinline,noclone,noipa)) foo (T i)
{
return i + 1;
}
int
caller2 (int k)
{
[[gnu::musttail]] return foo<int>(1);
}
template<typename T>
T caller3 (T v)
{
[[gnu::musttail]] return foo<T>(v);
}
int call3(int i)
{
[[gnu::musttail]] return caller3<int>(i + 1);
}
class Bar {
int a;
public:
Bar(int a) : a(a) {}
Bar operator+(Bar o) { return Bar(a + o.a); }
};
Bar
caller3 (Bar k)
{
[[gnu::musttail]] return caller3<Bar>(Bar(99));
}