Hi,
this is essentially an RFC, I'm still fully analyzing the issue, but
since I already have something prima facie reasonable and passing the
testsuite I decided to send immediately out what I have, looking for
further feedback / help. As fully analyzed by Jakub in the audit trail,
for the testcase - it's important detail being the parentheses around x
in the for(int y = 0, yend = (x); y < yend; ++y) part of the lambda body
- we ICE in maybe_undo_parenthesized_ref when we hit the assert:
gcc_assert (TREE_CODE (t) == ADDR_EXPR
|| TREE_CODE (t) == STATIC_CAST_EXPR);
because in tsubst_copy_and_build for INDIRECT_REF we do:
- if (TREE_CODE (r) == INDIRECT_REF)
- REF_PARENTHESIZED_P (r) = REF_PARENTHESIZED_P (t);
+ if (REF_PARENTHESIZED_P (t))
+ r = force_paren_expr (r);
irrespective of the details of r beyond it being an INDIRECT_REF. Today
something I immediately noticed, beyond all the ideas provided by Jakub
in the trail, is that in all the other places in pt.c, besides maybe one
case in tsubst_qualified_id, where we adjust REF_PARENTHESIZED_P either
we use indeed force_paren_expr which is guaranteed to produce something
consistent with maybe_undo_parenthesized_ref, or we simply do things like:
if (TREE_CODE (r) == COMPONENT_REF)
REF_PARENTHESIZED_P (r) = REF_PARENTHESIZED_P (t);
where in fact force_paren_expr would simply handle a COMPONENT_REF in
the same way. Thus the idea of the draft patch. Jason, if you see
something deeper going on which you would rather prefer to handle
yourself, please let me know and I'll adjust the bug owner appropriately.
Thanks! Paolo.
////////////////////
Index: cp/pt.c
===================================================================
--- cp/pt.c (revision 257458)
+++ cp/pt.c (working copy)
@@ -17224,8 +17224,8 @@ tsubst_copy_and_build (tree t,
r = build_x_indirect_ref (input_location, r, RO_UNARY_STAR,
complain|decltype_flag);
- if (TREE_CODE (r) == INDIRECT_REF)
- REF_PARENTHESIZED_P (r) = REF_PARENTHESIZED_P (t);
+ if (REF_PARENTHESIZED_P (t))
+ r = force_paren_expr (r);
RETURN (r);
}
Index: testsuite/g++.dg/cpp0x/lambda/lambda-ice25.C
===================================================================
--- testsuite/g++.dg/cpp0x/lambda/lambda-ice25.C (nonexistent)
+++ testsuite/g++.dg/cpp0x/lambda/lambda-ice25.C (working copy)
@@ -0,0 +1,27 @@
+// PR c++/83204
+// { dg-do compile { target c++11 } }
+
+int rand();
+
+template<typename T>
+struct s
+{
+ int count() { return rand(); }
+};
+
+template<typename v>
+void f(s<v> a)
+{
+ int const x = a.count();
+ int r = 0;
+ auto l = [&](int& r)
+ {
+ for(int y = 0, yend = (x); y < yend; ++y)
+ {
+ r += y;
+ }
+ };
+ l(r);
+}
+
+template void f(s<float>);