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.
gcc/cp/ChangeLog:
* cp-tree.h (finish_id_expression): Adjust declaration.
* parser.cc (cp_parser_splice_expression): Don't defer access checking.
Don't pass context to finish_id_expression. Call finish_id_expression
with splice_p = true.
(cp_parser_primary_expression): Adjust the call to finish_id_expression.
(cp_parser_lambda_introducer): Likewise.
(cp_parser_decltype_expr): Likewise.
(cp_finish_omp_declare_variant): Likewise.
* pt.cc (tsubst_expr): Likewise.
* semantics.cc (finish_id_expression_1): New splice_p parameter.
For FIELD_DECLs and functions, call build_offset_ref when taking
the address when the entity was designated by a splice-expression.
Use nullptr. Allow a VAR_DECL in an assert.
(finish_id_expression): New splice_p parameter. Use it.
(omp_reduction_lookup): Adjust the call to finish_id_expression.
---
gcc/cp/cp-tree.h | 2 +-
gcc/cp/parser.cc | 21 +++++++--------------
gcc/cp/pt.cc | 1 +
gcc/cp/semantics.cc | 41 +++++++++++++++++++++++++++++------------
4 files changed, 38 insertions(+), 27 deletions(-)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fcad67a662c..99f4c2fc2e4 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8443,7 +8443,7 @@ extern tree process_outer_var_ref (tree,
tsubst_flags_t, bool force_use = false
extern cp_expr finish_id_expression (tree, tree, tree,
cp_id_kind *,
bool, bool, bool *,
- bool, bool, bool, bool,
+ bool, bool, bool, bool, bool,
const char **,
location_t);
extern tree finish_typeof (tree);
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 8c46b260fff..a7ad4876ac3 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -6395,18 +6395,8 @@ cp_parser_splice_expression (cp_parser *parser, bool
template_p,
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. */
- push_deferring_access_checks (dk_no_check);
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,
@@ -6414,11 +6404,11 @@ cp_parser_splice_expression (cp_parser *parser, bool
template_p,
/*done=*/true,
address_p,
template_arg_p,
+ /*splice_p=*/true,
&error_msg,
loc);
if (error_msg)
cp_parser_error (parser, error_msg);
- pop_deferring_access_checks ();
}
return t;
@@ -7174,6 +7164,7 @@ cp_parser_primary_expression (cp_parser *parser,
&parser->non_integral_constant_expression_p,
template_p, done, address_p,
template_arg_p,
+ /*splice_p=*/false,
&error_msg,
id_expression.get_location ()));
if (error_msg)
@@ -13177,6 +13168,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree
lambda_expr)
/*done=*/true,
/*address_p=*/false,
/*template_arg_p=*/false,
+ /*splice_p=*/false,
&error_msg,
capture_token->location);
@@ -19299,6 +19291,7 @@ cp_parser_decltype_expr (cp_parser *parser,
/*done=*/true,
/*address_p=*/false,
/*template_arg_p=*/false,
+ /*splice_p=*/false,
&error_msg,
id_expr_start_token->location));
@@ -53549,8 +53542,8 @@ cp_finish_omp_declare_variant (cp_parser *parser,
cp_token *pragma_tok,
= finish_id_expression (varid, variant, parser->scope,
&idk, false, true,
&parser->non_integral_constant_expression_p,
- template_p, true, false, false, &error_msg,
- varid.get_location ());
+ template_p, true, false, false, false,
+ &error_msg, varid.get_location ());
if (error_msg)
cp_parser_error (parser, error_msg);
}
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 7c6577b48ef..c510733d41b 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21185,6 +21185,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t
complain, tree in_decl)
/*done=*/true,
/*address_p=*/false,
/*template_arg_p=*/false,
+ /*splice_p=*/false,
&error_msg,
input_location);
if (error_msg)
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 236bc625c25..76b0ddb1b12 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -4735,6 +4735,7 @@ process_outer_var_ref (tree decl, tsubst_flags_t
complain, bool odr_use)
TEMPLATE_P is true iff the qualified-id was of the form
"A::template B". TEMPLATE_ARG_P is true iff this qualified name
appears as a template argument.
+ SPLICE_P is true if ID_EXPRESSION was designated by a splice-expression.
If an error occurs, and it is the kind of error that might cause
the parser to abort a tentative parse, *ERROR_MSG is filled in. It
@@ -4760,6 +4761,7 @@ finish_id_expression_1 (tree id_expression,
bool done,
bool address_p,
bool template_arg_p,
+ bool splice_p,
const char **error_msg,
location_t location)
{
@@ -5022,16 +5024,23 @@ finish_id_expression_1 (tree id_expression,
&& contract_class_ptr == current_class_ptr)
{
error ("%qD 'this' required when accessing a member within a "
- "constructor precondition or destructor postcondition "
- "contract check", decl);
- return error_mark_node;
+ "constructor precondition or destructor postcondition "
+ "contract check", decl);
+ return error_mark_node;
}
/* Since SCOPE is NULL here, this is an unqualified name.
Access checking has been performed during name lookup
already. Turn off checking to avoid duplicate errors. */
push_deferring_access_checks (dk_no_check);
- decl = finish_non_static_data_member (decl, NULL_TREE,
- /*qualifying_scope=*/NULL_TREE);
+
+ if (splice_p && address_p)
+ decl = build_offset_ref (DECL_CONTEXT (decl), decl,
+ /*address_p=*/true,
+ tf_warning_or_error);
+ else
+ decl
+ = finish_non_static_data_member (decl, NULL_TREE,
+ /*qualifying_scope=*/NULL_TREE);
pop_deferring_access_checks ();
}
else if (is_overloaded_fn (decl))
@@ -5041,6 +5050,11 @@ finish_id_expression_1 (tree id_expression,
concerned with (all member fns or all non-members). */
tree first_fn = get_first_fn (decl);
first_fn = STRIP_TEMPLATE (first_fn);
+ tree ctx = DECL_CONTEXT (first_fn);
+
+ if (splice_p && address_p)
+ return build_offset_ref (ctx, first_fn, /*address_p=*/true,
+ tf_warning_or_error);
if (!template_arg_p
&& (TREE_CODE (first_fn) == USING_DECL
@@ -5053,14 +5067,15 @@ finish_id_expression_1 (tree id_expression,
&& contract_class_ptr == current_class_ptr)
{
error ("%qD 'this' required when accessing a member within a "
- "constructor precondition or destructor postcondition "
- "contract check", decl);
+ "constructor precondition or destructor postcondition "
+ "contract check", decl);
return error_mark_node;
}
- decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0);
+ decl = maybe_dummy_object (ctx, nullptr);
return finish_class_member_access_expr (decl, id_expression,
/*template_p=*/false,
- tf_warning_or_error);
+ tf_warning_or_error,
+ splice_p);
}
decl = baselink_for_fns (decl);
@@ -5080,7 +5095,8 @@ 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
+ || (splice_p && VAR_P (decl)));
else
perform_or_defer_access_check (TYPE_BINFO (path),
decl, decl,
@@ -5114,6 +5130,7 @@ finish_id_expression (tree id_expression,
bool done,
bool address_p,
bool template_arg_p,
+ bool splice_p,
const char **error_msg,
location_t location)
{
@@ -5123,7 +5140,7 @@ finish_id_expression (tree id_expression,
allow_non_integral_constant_expression_p,
non_integral_constant_expression_p,
template_p, done, address_p, template_arg_p,
- error_msg, location);
+ splice_p, error_msg, location);
return result.maybe_add_location_wrapper ();
}
@@ -6744,7 +6761,7 @@ omp_reduction_lookup (location_t loc, tree id, tree type,
tree *baselinkp,
decl = error_mark_node;
id = finish_id_expression (id, decl, NULL_TREE, &idk, false, true,
&nonint_cst_expression_p, false, true, false,
- false, &error_msg, loc);
+ false, false, &error_msg, loc);
if (idk == CP_ID_KIND_UNQUALIFIED
&& identifier_p (id))
{
base-commit: 065a6ab3747fe9116643ac6754582bc195847bfc
--
2.53.0