On 2/6/26 4:44 AM, Marek Polacek wrote:
On Tue, Feb 03, 2026 at 12:13:41AM +0800, Jason Merrill wrote:
On 2/2/26 2:43 AM, Marek Polacek wrote:
On Fri, Jan 30, 2026 at 10:55:43AM +0800, Jason Merrill wrote:
On 1/30/26 8:36 AM, Marek Polacek wrote:
On Thu, Jan 29, 2026 at 07:32:03PM +0800, Jason Merrill wrote:
On 1/28/26 11:49 PM, Marek Polacek wrote:
On Wed, Jan 28, 2026 at 11:21:53AM +0800, Jason Merrill wrote:
On 1/28/26 10:50 AM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
This patch fixes the problem that when cp_parser_splice_specifier sees
:]<, it always thinks it's a template-id. Consequently, this should compile
but does not:
int i;
constexpr auto r = ^^i;
bool b = [:r:] < 42;
because we think that a template argument list follows the splice.
Fixed by using the new cp_parser_next_token_starts_template_argument_list_p
which checks that we see the whole <...>.
But this turned out to be more complicated when I considered
splice-specialization-specifiers in a template-argument-list. With this
patch we reject
S<[:r:] < 43> s;
but I think that's fine given the footnote in [temp.names]: "A > that
encloses [...] the template-arguments of a subsequent template-id or
splice-specialization-specifier, is considered nested for the purpose
of this description." (We can't just check !in_template_argument_list_p
because [:x:]<> can be valid in a template argument list.)
I think that's wrong under https://eel.is/c++draft/temp.names#3.1 since the
splice is not in a type-only context and is not preceded by template or
typename.
We should accept the above and not assume that the < starts a
template-argument-list. It would still be helpful to check whether it could
do so for -Wmissing-template-keyword.
Ah, fixed (by checking template_p and typename_p). We don't emit
a -Wmissing-template-keyword warning but currently we say:
note: add 'template' to denote a template
although this may change if we downgrade the error to a pedwarn.
I think that cp_parser_skip_entire_template_parameter_list has a bug
because it doesn't correctly handle >> in a template argument list;
see the xfail in parse3.C.
Sounds right.
We have to make sure that in a template argument list we don't eat
both > because the second > isn't spurious. I gave it a few minutes
but my quick fix didn't work, so I'm leaving it for later.
I also realized that my code to detect unparenthesized splice
expressions as template arguments is wrong. [expr.prim.splice] says that
constexpr auto i = e<[:^^h:]>;
is ill-formed, but I think "S<[:r:] >= 1>" is fine.
Agreed, the normative citation is https://eel.is/c++draft/temp#names-6
Cool, I've added that reference to a comment in the patch.
So I moved the
checking to cp_parser_template_argument while making sure that we
only complain when the splice-expression is the whole template-argument.
Sounds good.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
This patch fixes the problem that when cp_parser_splice_specifier sees
:]<, it always thinks it's a template-id. Consequently, this should compile
but does not:
int i;
constexpr auto r = ^^i;
bool b = [:r:] < 42;
because we think that a template argument list follows the splice.
Fixed by using the new cp_parser_next_token_starts_template_argument_list_p
which checks that we see the whole <...>.
But this turned out to be more complicated when I considered
splice-specialization-specifiers in a template-argument-list. We should
accept the following given [temp.names]/3:
S<[:r:] < 43> s;
To that effect, I'm checking !in_template_argument_list_p along with
I don't think that's valid either, unfortunately; even outside of a template
argument list
[:r:] < 42 > 0
seems to be well-formed (though pathological) code.
Oh well. How about if I parse the template-id tentatively, and only
consider the [:r:] < 42 > as a splice-specialization-specifier when
the parsing worked out?
This patch still breaks
Sorry :(
using info = decltype(^^::);
template <info R>
bool f()
{
return [: R :]<42>0;
}
int i;
int main()
{
f<^^i>();
}
We must only consider it a splice-specialization-specifier as specified by
[temp.names]/3.1; otherwise we should only -Wmissing-template-keyword. And
I think we should share that warning code with cp_parser_id_expression.
Well, I suppose we could also treat it as a (ill-formed)
splice-specialization-specifier if 'expr' is known to be a template at that
point, but not if it's dependent as above, and of course not if it's a
non-template.
I've tried to do the latter.
Ah, I wasn't thinking of them as alternatives; the latter was a refinement
of the former (an addition to [temp.names]/3.1). That is, template_p ||
typename_p || TREE_CODE (expr) == TEMPLATE_DECL.
Done.
I don't think using _next_token_starts_ here is appropriate for this case;
[temp.names] says if we have template or typename and see < it's a
template-id regardless of what follows, and I expect we can give better
syntax errors if we go ahead with that.
I went back to cp_parser_nth_token_starts_template_argument_list_p.
Once again, I think that's wrong; see below.
The -Wmissing-template-keyword suggestion was to avoid regressing diagnostic
quality on e.g. crash6.C. You could also give that warning at the point of
cp_parser_simulate_error in this patch. Without that I don't see the point
of doing the tentative parse at all, as we're just going to throw away the
result.
I tried to give warnings for dependent_splice_p with missing_template_diag,
but then we suggest adding 'template' where doing so would make the code
ill-formed, so I removed that. And so the crash6.C change remains.
I hope that's okay.
Yes, that's OK.
And _next_token_starts_ seems redundant with tentative parsing in the
missing "template" case; either one or the other seems sufficient to detect
a possible template-id, both is excessive.
I still think it would be good to share the warning code between here and
_id_expression, since they're doing the exact same thing.
I think I should be able to use missing_template_diag in
cp_parser_splice_expression instead of the error. But that can
hopefully wait for a different patch.
Agreed.
So, how about this version? Thanks,
@@ -6169,8 +6173,18 @@ cp_parser_splice_specifier (cp_parser *parser, bool
template_p = false,
/* Get the reflected operand. */
expr = splice (expr);
- /* If the next token is a '<', it's a splice-specialization-specifier. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+ /* If the next token is a <, it could be a splice-specialization-specifier.
+ But we need to handle "[:r:] < 42" where the < doesn't start a template
+ argument list. [temp.names]/3: A < is interpreted as the delimiter of
+ a template-argument-list if either
+ -- it follows a splice-specifier that either
+ -- appears in a type-only context or
+ -- is preceded by template or typename. */
+ if (cp_parser_nth_token_starts_template_argument_list_p (parser, 1)
This line should not change.
+ /* As a courtesy to the user, if there is a < after a template
+ name, parse the construct as an s-s-s and warn about the missing
+ 'template'; it can't be anything else. */
+ && (template_p || typename_p || TREE_CODE (expr) == TEMPLATE_DECL))
Adding this line is enough.
Jason