On 8/11/25 2:39 AM, Jakub Jelinek wrote:
On Wed, Aug 06, 2025 at 10:18:54PM -0700, Jason Merrill wrote:
On 7/28/25 3:03 AM, Jakub Jelinek wrote:
That makes sense from the specification, but also seems like an unnecessary
restriction, would be worth raising with the committee.
https://cplusplus.github.io/CWG/issues/3048.html
Looks good, thanks.
Also please factor this code out of cp_convert_range_for rather than
duplicating it.
Not sure if it is worth or how to do it. The range_temp case in
cp_convert_range_for is conditional:
if (range_decl == error_mark_node || range_expr == error_mark_node)
/* If an error happened previously do nothing or else a lot of
unhelpful errors would be issued. */
begin_expr = end_expr = iter_type = error_mark_node;
else
{
tree range_temp;
if (VAR_P (range_expr)
&& array_of_runtime_bound_p (TREE_TYPE (range_expr)))
/* Can't bind a reference to an array of runtime bound. */
range_temp = range_expr;
else
and the common part with the iterating expansion stmt lowering only starts
in this else block, while the begin/end cases are unconditional.
Furthermore, while some stmts are the same, others are different,
diff -U30 -pb of the blocks gives:
@@ -1,30 +1,42 @@
- range_temp = build_range_temp (range_expr);
+ tree range_temp, begin_expr, end_expr, iter_type, end;
+ range_temp = build_range_temp (expansion_init);
+ /* Depending on CWG3044 resolution, we might want to remove
+ these 3 sets of TREE_STATIC (on range_temp, begin and end).
+ Although it can only be done when P2686R4 is fully implemented. */
+ TREE_STATIC (range_temp) = 1;
+ TREE_PUBLIC (range_temp) = 0;
+ DECL_COMMON (range_temp) = 0;
+ DECL_INTERFACE_KNOWN (range_temp) = 1;
+ DECL_DECLARED_CONSTEXPR_P (range_temp) = 1;
+ TREE_READONLY (range_temp) = 1;
pushdecl (range_temp);
- cp_finish_decl (range_temp, range_expr,
+ cp_finish_decl (range_temp, expansion_init,
/*is_constant_init*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING);
range_temp = convert_from_reference (range_temp);
- }
iter_type = cp_perform_range_for_lookup (range_temp, &begin_expr,
&end_expr);
- }
- /* The new for initialization statement. */
- begin = build_decl (input_location, VAR_DECL, for_begin__identifier,
- iter_type);
+ begin = build_decl (loc, VAR_DECL, for_begin__identifier, iter_type);
TREE_USED (begin) = 1;
DECL_ARTIFICIAL (begin) = 1;
+ TREE_STATIC (begin) = 1;
+ DECL_DECLARED_CONSTEXPR_P (begin) = 1;
+ TREE_READONLY (begin) = 1;
pushdecl (begin);
cp_finish_decl (begin, begin_expr,
/*is_constant_init*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING);
if (cxx_dialect >= cxx17)
iter_type = cv_unqualified (TREE_TYPE (end_expr));
- end = build_decl (input_location, VAR_DECL, for_end__identifier, iter_type);
+ end = build_decl (loc, VAR_DECL, for_end__identifier, iter_type);
TREE_USED (end) = 1;
DECL_ARTIFICIAL (end) = 1;
+ TREE_STATIC (end) = 1;
+ DECL_DECLARED_CONSTEXPR_P (end) = 1;
+ TREE_READONLY (end) = 1;
pushdecl (end);
cp_finish_decl (end, end_expr,
/*is_constant_init*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING);
That doesn't look very different to me.
So, to factor this out it would need to be a function
with tons of arguments and extra bool argument whether it is
cp_convert_range_for or finish_expansion_stmt (in the latter
case do that TREE_STATIC (maybe only temporarily depending on the CWG
resolution) and the other two and somehow deal with the initial
conditionals for the cp_convert_range_for case.
I figure the initial conditionals can stay in cp_convert_range_for.
I can try to do it if you really think it is desirable.
Please, it still seems reasonable to me.
--- gcc/cp/decl2.cc.jj 2025-07-19 21:05:56.681592433 +0200
+++ gcc/cp/decl2.cc 2025-07-22 08:58:19.574836765 +0200
@@ -6240,6 +6240,8 @@ decl_dependent_p (tree decl)
if (LAMBDA_FUNCTION_P (decl)
&& dependent_type_p (DECL_CONTEXT (decl)))
return true;
+ if (in_expansion_stmt && decl == current_function_decl)
+ return true;
This seems wrong; an expansion statement doesn't make the enclosing function
dependent. What needed this change?
Without that I'm getting tons of errors on
expansion-stmt{1,10,11,12,13,14,17}.C tests.
expansion-stmt1.C:58:12: error: use of ‘g’ before deduction of ‘auto’
58 | r += g.a + g.b + g.c;
| ^
etc. In this case, g is the for-range-declaration (but it could be
even auto within the expansion stmt body); and it obviously affects solely
the cases where expansion stmt is not present in a template.
Ah, I was forgetting the decl = CP_DECL_CONTEXT (decl) earlier in the
function, it makes more sense that way. I'd still prefer to limit this
change to the case where the original argument is the variable, and not
affect the case where the original argument is the function.
Jason