On 12/12/25 12:58 AM, Jakub Jelinek wrote:
On Thu, Dec 11, 2025 at 11:29:01PM +0700, Jason Merrill wrote:
same_type<decltype([: ^^S::i :]), int> s5b;
where it seems to be parsing [: ^^S::i :] tentatively, sets
parser->scope and parser->qualifying_scope to S during that
parsing and then when it is parsing it again sees that.
So guess the question is where to clear those 3 (e.g. whether
at the start of cp_parser_splice_expression and also at the end
of those?)
I think so.
and/or if there are some spots where it should be temporarily
and where it should be reset back.
I don't think so.
Marek is looking at these right now.
And then there is also parser->context->object_type, guess for that one
we should save it and restore it, so that it can be taken into account
for s.[: ^^S::foo :] <int> (); etc. parsing.
...
The following WIP patch fixes that.
The reason for saving/restoring rather than just clearing is so that
it can be used for the splice-specialization-specifier case later on
if the splice-specifier is non-dependent.
Why is this needed? The template arguments aren't member-qualified, e.g.
this is properly rejected:
struct A {
static const int i = 42;
template <int I> void f();
};
int main()
{
A().f<i>(); // error, no 'i' in scope
}
I wanted to make it behave similarly to the non-splice parsing and without
that lots of things in member18.C testcase (which I finally got to work
fully a few minutes ago) didn't work.
For A().f<i>(); *dot_deref* sets parser->context->object_type and then
cp_parser_template_id is called, it parses the f IDENTIFIER_NODE and because
parser->context->object_type is set, it looks it up in that type and
creates a BASELINK from that and only with that the rest of
cp_parser_template_id can DTRT and create the right TEMPLATE_ID_EXPR,
everything before finish_class_member_access_expr is called.
Now, for the splice-specialization-specifier case for member access,
we get an OVERLOAD for a function template, but without a BASELINK
cp_parser_template_id with the new expr argument added by Marek where
it doesn't parse the identifier before < but uses the splice expression
it doesn't DTRT.
So, what I'm now using is
https://forge.sourceware.org/marek/gcc/src/commit/ebd656a2ba860bf05e0ef3283acd4efb6621f4dc/gcc/cp/parser.cc#L6155
and add a BASELINK in that case.
Makes sense.
The relevant recent commits are
https://forge.sourceware.org/marek/gcc/commit/43b63499a56e507d1e646e5ba732e5db88bcfaa0
https://forge.sourceware.org/marek/gcc/commit/47efb49b8d32cf1fecadf28990f74d2deff0039c
https://forge.sourceware.org/marek/gcc/commit/d9d8a99731e44ca57944b03a30b66ed7450bd622
https://forge.sourceware.org/marek/gcc/commit/99aaea31a7e583946f541f1c09ce7d3daff4062c
https://forge.sourceware.org/marek/gcc/commit/a6a2829e25ec1bd4d57779785248ab9dca6e88ef
https://forge.sourceware.org/marek/gcc/commit/d1dff2d009b72047c768a383b28f748982b5f51a
https://forge.sourceware.org/marek/gcc/commit/33ceee24fb16bc3d4772e298536d31f3a103aed4
https://forge.sourceware.org/marek/gcc/commit/ebd656a2ba860bf05e0ef3283acd4efb6621f4dc
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -6102,6 +6102,7 @@ cp_parser_next_tokens_can_start_splice_scope_spec_p
(cp_parser *parser)
static cp_expr
cp_parser_splice_specifier (cp_parser *parser, bool template_p = false,
+ bool member_access_p = false,
bool *targs_p = nullptr)
{
/* Get the location of the '[:'. */
@@ -6120,11 +6121,22 @@ cp_parser_splice_specifier (cp_parser *parser, bool
template_p = false,
return error_mark_node;
}
+ /* For member_access_p, temporarily clear parser->context->object_type. */
Why conditional on member_access_p?
It could be done for non-member_access_p too, I just think it will
never be non-NULL otherwise.
Right, so adding the parm seems unnecessary.
Jason