On 6/25/26 12:51 PM, Jakub Jelinek wrote:
On Thu, Jun 25, 2026 at 12:03:22PM -0400, Jason Merrill wrote:
Why include the implicit by-ref capture of d when its ordering is still
unspecified (and not tested)? It doesn't hurt, but could use a comment.
Comment added (and added also two lambdas without any implicit captures).
This test should probably also check order of initialization of by-ref
init-capture.
Added too.
Tested on x86_64-linux again.
OK.
2026-06-25 Jakub Jelinek <[email protected]>
PR c++/125832
* g++.dg/cpp29/lambda-order1.C: New test.
* g++.dg/cpp29/lambda-order2.C: New test.
--- gcc/testsuite/g++.dg/cpp29/lambda-order1.C.jj 2026-06-25
18:16:21.477309766 +0200
+++ gcc/testsuite/g++.dg/cpp29/lambda-order1.C 2026-06-25 18:39:32.584004559
+0200
@@ -0,0 +1,80 @@
+// P3847R1 - Lexical order for lambdas
+// { dg-do run { target c++14 } }
+
+int e;
+
+int
+foo (int x)
+{
+ if (x != e)
+ __builtin_abort ();
+ ++e;
+ return x;
+}
+
+int &
+bar (int x)
+{
+ if (x != e)
+ __builtin_abort ();
+ ++e;
+ return e;
+}
+
+int
+main ()
+{
+ int a = 1;
+ long b = 2;
+ double c = 3;
+ short d = 4;
+ foo (0);
+ auto f = [&, a0 = foo (1), a, a1 = foo (2),
+ b0 = foo (3), b, b1 = foo (4),
+ c0 = foo (5), c, c1 = foo (6)] () {
+ if (&a0 >= &a
+ || &a >= &a1
+ || (const void *) &a1 >= (const void *) &b0
+ || (const void *) &b0 >= (const void *) &b
+ /* d is captured implicitly, the ordering for
+ the d member vs. the explicitly captured
+ ones is still unspecified by C++, but part
+ of the Itanium ABI. Just test that it doesn't
+ change the order of the explicit captures. */
+ || d != 4
+ || (const void *) &b >= (const void *) &b1
+ || (const void *) &b1 >= (const void *) &c0
+ || (const void *) &c0 >= (const void *) &c
+ || (const void *) &c >= (const void *) &c1)
+ __builtin_abort ();
+ };
+ foo (7);
+ f ();
+ foo (8);
+ f ();
+ foo (9);
+ auto g = [=, &a0 = bar (10), &a, &a1 = bar (11),
+ &b0 = bar (12), &b, &b1 = bar (13),
+ &c0 = bar (14), &c, &c1 = bar (15)] () {
+ return a0 + a + a1 + b0 + b + b1 + c0 + c + c1;
+ };
+ foo (16);
+ g ();
+ foo (17);
+ auto h = [&, a0 = foo (18), a, a1 = foo (19),
+ b0 = foo (20), b, b1 = foo (21),
+ c0 = foo (22), c, c1 = foo (23)] () {
+ if (&a0 >= &a
+ || &a >= &a1
+ || (const void *) &a1 >= (const void *) &b0
+ || (const void *) &b0 >= (const void *) &b
+ || (const void *) &b >= (const void *) &b1
+ || (const void *) &b1 >= (const void *) &c0
+ || (const void *) &c0 >= (const void *) &c
+ || (const void *) &c >= (const void *) &c1)
+ __builtin_abort ();
+ };
+ foo (24);
+ h ();
+ foo (25);
+}
--- gcc/testsuite/g++.dg/cpp29/lambda-order2.C.jj 2026-06-25
18:16:21.477425501 +0200
+++ gcc/testsuite/g++.dg/cpp29/lambda-order2.C 2026-06-25 18:22:19.319621208
+0200
@@ -0,0 +1,24 @@
+// P3847R1 - Lexical order for lambdas
+// { dg-do run { target c++11 } }
+
+int
+main ()
+{
+ int a = 1;
+ long b = 2;
+ double c = 3;
+ short d = 4;
+ auto f = [&, a, b, c] () {
+ if ((const void *) &a >= (const void *) &b
+ /* d is captured implicitly, the ordering for
+ the d member vs. the explicitly captured
+ ones is still unspecified by C++, but part
+ of the Itanium ABI. Just test that it doesn't
+ change the order of the explicit captures. */
+ || d != 4
+ || (const void *) &b >= (const void *) &c)
+ __builtin_abort ();
+ };
+ f ();
+ f ();
+}
Jakub