On Tue, Dec 09, 2025 at 08:38:26PM +0800, Jason Merrill wrote:
> This suggests that we're doing the lookup in the context of "d.", which is
> wrong.  That is, we should reject
> 
> struct A { static int x; };
> int q = A().[:^^x:];  // error, no 'x' in scope
> 
> but the branch currently accepts this.  Under
> https://eel.is/c++draft/basic.lookup.qual#general-2 'x' is not a
> member-qualified name.

This is about parser->context->object_type.

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.

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 0d59f6ec5a5..4e10fec64e2 100644
--- 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.  */
+  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;
+
   /* Get the location of the ':]'.  */
   location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location;
 
@@ -6215,7 +6227,8 @@ cp_parser_splice_expression (cp_parser *parser, bool 
template_p,
   if (member_access_p)
     push_deferring_access_checks (dk_no_check);
 
-  cp_expr expr = cp_parser_splice_specifier (parser, template_p, &targs_p);
+  cp_expr expr = cp_parser_splice_specifier (parser, template_p,
+                                            member_access_p, &targs_p);
 
   if (member_access_p)
     pop_deferring_access_checks ();
@@ -6385,7 +6398,8 @@ cp_parser_splice_scope_specifier (cp_parser *parser, bool 
typename_p,
                                  bool template_p)
 {
   bool targs_p = false;
-  cp_expr scope = cp_parser_splice_specifier (parser, template_p, &targs_p);
+  cp_expr scope = cp_parser_splice_specifier (parser, template_p, false,
+                                             &targs_p);
   const location_t loc = scope.get_location ();
   if (TREE_CODE (scope) == TYPE_DECL)
     scope = TREE_TYPE (scope);
diff --git a/gcc/testsuite/g++.dg/reflect/member1.C 
b/gcc/testsuite/g++.dg/reflect/member1.C
index c64b39f0938..e9d9a64d0eb 100644
--- a/gcc/testsuite/g++.dg/reflect/member1.C
+++ b/gcc/testsuite/g++.dg/reflect/member1.C
@@ -95,5 +95,5 @@ f ()
   s.template [: ^^S::N :].t;  // { dg-error "reflection .S::N. not usable in a 
template splice" }
   S::template [: ^^S::N<int> :] e1;  // { dg-error "expected unqualified-id" }
   C<int>::template [: ^^S::N<int> :] e2;  // { dg-error "expected 
unqualified-id" }
-  s.template [: ^^var<int> :] = 1;  // { dg-error "reflection .S::var<int>. 
not usable in a template splice" }
+  s.template [: ^^S::var<int> :] = 1;  // { dg-error "reflection .S::var<int>. 
not usable in a template splice" }
 }
diff --git a/gcc/testsuite/g++.dg/reflect/splice3.C 
b/gcc/testsuite/g++.dg/reflect/splice3.C
new file mode 100644
index 00000000000..88434444a2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/splice3.C
@@ -0,0 +1,5 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+struct A { static int x; };
+int q = A ().[: ^^x :];  // { dg-error "'x' has not been declared" }


        Jakub

Reply via email to