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;

Reply via email to