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


Reply via email to