On Thu, Dec 11, 2025 at 05:58:43PM +0100, 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.
How about this patch, then?
Note that I still can't remove push_deferring_access_checks in
cp_parser_splice_expression. But I could remove some other code.
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index b675ca23f1a..661f4b0e4f4 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -6120,21 +6120,19 @@ 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. */
- tree save_object_type = NULL_TREE;
- if (member_access_p)
- {
- save_object_type = parser->context->object_type;
- parser->context->object_type = NULL_TREE;
- }
-
- tree expr = cp_parser_constant_expression (parser,
- /*allow_non_constant_p=*/false,
- /*non_constant_p=*/nullptr,
- /*strict_p=*/true);
-
- if (member_access_p)
- parser->context->object_type = save_object_type;
+ tree expr;
+ {
+ /* Temporarily clear parser->context->object_type. E.g.,
+ struct A { static int x; };
+ int q = A ().[: ^^x :];
+ should be an error -- x is not a member-qualified name and isn't
+ in scope. */
+ auto ot = make_temp_override (parser->context->object_type, NULL_TREE);
+ expr = cp_parser_constant_expression (parser,
+ /*allow_non_constant_p=*/false,
+ /*non_constant_p=*/nullptr,
+ /*strict_p=*/true);
+ }
/* Get the location of the ':]'. */
location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -6244,17 +6242,19 @@ cp_parser_splice_expression (cp_parser *parser, bool
template_p,
{
bool targs_p = false;
- /* [class.access.base]/5: A member m is accessible at the point R when
- designated in class N if
- -- m is designated by a splice-expression */
- if (member_access_p)
- push_deferring_access_checks (dk_no_check);
+ /* E.g., [: X::x :] is a separate lookup and we shouldn't take into
+ account any previous scopes. */
+ parser->scope = NULL_TREE;
+ parser->object_scope = NULL_TREE;
+ parser->qualifying_scope = NULL_TREE;
cp_expr expr = cp_parser_splice_specifier (parser, template_p,
member_access_p, &targs_p);
- if (member_access_p)
- pop_deferring_access_checks ();
+ /* And don't leave the scopes set, either. */
+ parser->scope = NULL_TREE;
+ parser->object_scope = NULL_TREE;
+ parser->qualifying_scope = NULL_TREE;
const location_t loc = expr.get_location ();
tree t = expr.get_value ();
@@ -9686,8 +9686,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
[:^^B::fn:]() // do not disable virtual dispatch
[:^^B:]::fn() // disable virtual dispatch
- so we check SPLICE_P. */
- if (parser->scope && !splice_p)
+ In the former, parser->scope has been cleared when we get here. */
+ if (parser->scope)
*idk = CP_ID_KIND_QUALIFIED;
/* If the name is a template-id that names a type, we will get a
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 3d160b9c84b..1e88bf57aa5 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -3532,11 +3532,6 @@ finish_class_member_access_expr (cp_expr object, tree
name, bool template_p,
return error_mark_node;
}
- /* For OBJECT.[:S::fn:] the BASELINK can be inside a SCOPE_REF.
- This happens, but, until Reflection, not for a class member access. */
- if (TREE_CODE (name) == SCOPE_REF && BASELINK_P (TREE_OPERAND (name, 1)))
- name = TREE_OPERAND (name, 1);
-
if (BASELINK_P (name))
/* A member function that has already been looked up. */
member = name;