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. 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
