On Fri, Feb 20, 2026 at 03:40:49PM +0900, Jason Merrill wrote:
On 2/20/26 1:14 AM, Marek Polacek wrote:
On Thu, Feb 19, 2026 at 11:07:56PM +0900, Jason Merrill wrote:
On 2/19/26 10:35 PM, Marek Polacek wrote:
On Thu, Feb 19, 2026 at 05:28:24PM +0900, Jason Merrill wrote:
On 2/12/26 12:29 AM, Marek Polacek wrote:
On Wed, Feb 11, 2026 at 05:02:40PM +0900, Jason Merrill wrote:
On 2/11/26 1:05 AM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
In <https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705175.html>
(bottom of the message) we discussed not passing ctx to finish_id_expression
so that we can get rid of the _deferring_access_checks calls. So the
cp_parser_splice_expression changes are what we want. In order to be
able to do that, I had to adjust finish_id_expression_1 so that things
like &[: ^^S::fn :] and &[: ^^S::mem :] keep working.
Would it make sense to call build_offset_ref in cp_parser_splice_expression?
I could do that, but then I'd also have to duplicate the calls to
push/pop_deferring_access_checks, and add checks around build_offset_ref
just like in the r16-7445 patch. But then I think I wouldn't have
to add the new splice_p parameter. Thought maybe we want to signal to
finish_class_member_access_expr that we're coming from a splice anyway.
But why? I would think that accessing a pre-determined member ought to work
the same whether or not it comes from a splice.
I don't think passing splice_p to finish_class_member_access_expr
currently does anything. But the note about various checks that
would have to be added around build_offset_ref still stands.
That still sounds more localized, and therefore better, than cluttering the
API with more splice_p parameters.
Ok, fair enough. How about this, then?
+ else if (VAR_P (t) && DECL_CLASS_SCOPE_P (t))
+ /* finish_id_expression doesn't handle these well:
+ constexpr auto r = ^^S::i;
+ auto a = [:r:]; */
This seems to be referring to this assert in finish_id_expression_1:
Yes, it was.
/* PATH can be null for using an enum of an unrelated
class; we checked its access in lookup_using_decl.
??? Should this case make a clone instead, like
handle_using_decl? */
gcc_assert (TREE_CODE (decl) == CONST_DECL);
How about, instead of a special case in cp_parser_splice_expression, adding
|| flag_reflection to the assert?
I can do that too:
dg.exp passed so far, ok for trunk?
-- >8 --
In <https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705175.html>
(bottom of the message) we discussed not passing ctx to finish_id_expression
so that we can get rid of the _deferring_access_checks calls.
We can avoid passing context to finish_id_expression but we can't
completely avoid the _deferring_access_checks calls, because for
address_p we need to call build_offset_ref which needs it.
gcc/cp/ChangeLog:
* parser.cc (cp_parser_splice_expression): For dependent splices return
earlier. Refactor. For address_p, build an OFFSET_REF. Don't pass
context to finish_id_expression.
* semantics.cc (finish_id_expression_1): Adjust an assert to also check
flag_reflection.
---
gcc/cp/parser.cc | 31 ++++++++++++++++---------------
gcc/cp/semantics.cc | 6 +++++-
2 files changed, 21 insertions(+), 16 deletions(-)
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 13b9b8f46b4..8fd3ed08673 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -6313,6 +6313,7 @@ cp_parser_splice_expression (cp_parser *parser, bool
template_p,
SET_SPLICE_EXPR_EXPRESSION_P (t);
SET_SPLICE_EXPR_MEMBER_ACCESS_P (t, member_access_p);
SET_SPLICE_EXPR_ADDRESS_P (t, address_p);
+ return t;
}
if (error_operand_p (t))
@@ -6358,6 +6359,8 @@ cp_parser_splice_expression (cp_parser *parser, bool
template_p,
/* Were 'template' present, this would be valid code, so keep going. */
missing_template_diag (loc, diagnostics::kind::pedwarn);
+ cp_unevaluated u;
+
/* When doing foo.[: bar :], cp_parser_postfix_dot_deref_expression wants
to see an identifier or a TEMPLATE_ID_EXPR, if we have something like
s.template [: ^^S::var :]<int> where S::var is a variable template. */
@@ -6377,24 +6380,23 @@ cp_parser_splice_expression (cp_parser *parser, bool
template_p,
|| TREE_CODE (t) == TREE_BINFO);
/* ??? We're not setting *idk here. */
}
- else
+ else if (address_p
+ && (BASELINK_P (t) || DECL_NONSTATIC_MEMBER_P (t)))
{
- /* We may have to instantiate; for instance, if we're dealing with
- a variable template. For &[: ^^S::x :], we have to create an
- OFFSET_REF. For a VAR_DECL, we need the convert_from_reference. */
- cp_unevaluated u;
/* CWG 3109 adjusted [class.protected] to say that checking access to
- protected non-static members is disabled for members designated by a
- splice-expression. */
+ protected non-static members is disabled for members designated by
+ a splice-expression. */
push_deferring_access_checks (dk_no_check);
+ tree type = (BASELINK_P (t)
+ ? BINFO_TYPE (BASELINK_ACCESS_BINFO (t))
+ : DECL_CONTEXT (t));
+ t = build_offset_ref (type, t, /*address_p=*/true, tf_warning_or_error);
+ pop_deferring_access_checks ();
+ }
+ else
+ {
const char *error_msg;
- /* We don't have the parser scope here, so figure out the context. In
- struct S { static constexpr int i = 42; };
- constexpr auto r = ^^S::i;
- int i = [: r :];
- we need to pass down 'S'. */
- tree ctx = DECL_P (t) ? DECL_CONTEXT (t) : NULL_TREE;
- t = finish_id_expression (t, t, ctx, idk,
+ t = finish_id_expression (t, t, NULL_TREE, idk,
/*integral_constant_expression_p=*/false,
/*allow_non_integral_constant_expr_p=*/true,
&parser->non_integral_constant_expression_p,
@@ -6406,7 +6408,6 @@ cp_parser_splice_expression (cp_parser *parser, bool
template_p,
loc);
if (error_msg)
cp_parser_error (parser, error_msg);
- pop_deferring_access_checks ();
}
return t;
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index fbf7c6d7596..4aa2f14b468 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -5086,7 +5086,11 @@ finish_id_expression_1 (tree id_expression,
??? Should this case make a clone instead, like
handle_using_decl? */
- gcc_assert (TREE_CODE (decl) == CONST_DECL);
+ gcc_assert (TREE_CODE (decl) == CONST_DECL
+ /* This is for:
+ constexpr auto r = ^^S::i;
+ auto a = [:r:]; */
+ || flag_reflection);
else
perform_or_defer_access_check (TYPE_BINFO (path),
decl, decl,
base-commit: 8d8725bedd2f7cd5a894b47b43022f6ec0fef2c0