|  | // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -Wno-return-stack-address -emit-cir %s -o %t.cir | 
|  | // RUN: FileCheck --input-file=%t.cir %s | 
|  |  | 
|  | void fn() { | 
|  | auto a = [](){}; | 
|  | a(); | 
|  | } | 
|  |  | 
|  | //      CHECK: !ty_anon2E2_ = !cir.struct<class "anon.2" {!cir.int<u, 8>}> | 
|  | //  CHECK-DAG: module | 
|  |  | 
|  | //      CHECK: cir.func lambda internal private @_ZZ2fnvENK3$_0clEv{{.*}}) extra | 
|  |  | 
|  | //      CHECK:   cir.func @_Z2fnv() | 
|  | // CHECK-NEXT:     %0 = cir.alloca !ty_anon2E2_, !cir.ptr<!ty_anon2E2_>, ["a"] | 
|  | //      CHECK:   cir.call @_ZZ2fnvENK3$_0clEv | 
|  |  | 
|  | void l0() { | 
|  | int i; | 
|  | auto a = [&](){ i = i + 1; }; | 
|  | a(); | 
|  | } | 
|  |  | 
|  | // CHECK: cir.func lambda internal private @_ZZ2l0vENK3$_0clEv({{.*}}) extra | 
|  |  | 
|  | // CHECK: %0 = cir.alloca !cir.ptr<!ty_anon2E4_>, !cir.ptr<!cir.ptr<!ty_anon2E4_>>, ["this", init] {alignment = 8 : i64} | 
|  | // CHECK: cir.store %arg0, %0 : !cir.ptr<!ty_anon2E4_>, !cir.ptr<!cir.ptr<!ty_anon2E4_>> | 
|  | // CHECK: %1 = cir.load %0 : !cir.ptr<!cir.ptr<!ty_anon2E4_>>, !cir.ptr<!ty_anon2E4_> | 
|  | // CHECK: %2 = cir.get_member %1[0] {name = "i"} : !cir.ptr<!ty_anon2E4_> -> !cir.ptr<!cir.ptr<!s32i>> | 
|  | // CHECK: %3 = cir.load %2 : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> | 
|  | // CHECK: %4 = cir.load %3 : !cir.ptr<!s32i>, !s32i | 
|  | // CHECK: %5 = cir.const #cir.int<1> : !s32i | 
|  | // CHECK: %6 = cir.binop(add, %4, %5) nsw : !s32i | 
|  | // CHECK: %7 = cir.get_member %1[0] {name = "i"} : !cir.ptr<!ty_anon2E4_> -> !cir.ptr<!cir.ptr<!s32i>> | 
|  | // CHECK: %8 = cir.load %7 : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i> | 
|  | // CHECK: cir.store %6, %8 : !s32i, !cir.ptr<!s32i> | 
|  |  | 
|  | // CHECK: cir.func @_Z2l0v() | 
|  |  | 
|  | auto g() { | 
|  | int i = 12; | 
|  | return [&] { | 
|  | i += 100; | 
|  | return i; | 
|  | }; | 
|  | } | 
|  |  | 
|  | // CHECK: cir.func @_Z1gv() -> !ty_anon2E6_ | 
|  | // CHECK: %0 = cir.alloca !ty_anon2E6_, !cir.ptr<!ty_anon2E6_>, ["__retval"] {alignment = 8 : i64} | 
|  | // CHECK: %1 = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64} | 
|  | // CHECK: %2 = cir.const #cir.int<12> : !s32i | 
|  | // CHECK: cir.store %2, %1 : !s32i, !cir.ptr<!s32i> | 
|  | // CHECK: %3 = cir.get_member %0[0] {name = "i"} : !cir.ptr<!ty_anon2E6_> -> !cir.ptr<!cir.ptr<!s32i>> | 
|  | // CHECK: cir.store %1, %3 : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> | 
|  | // CHECK: %4 = cir.load %0 : !cir.ptr<!ty_anon2E6_>, !ty_anon2E6_ | 
|  | // CHECK: cir.return %4 : !ty_anon2E6_ | 
|  |  | 
|  | auto g2() { | 
|  | int i = 12; | 
|  | auto lam = [&] { | 
|  | i += 100; | 
|  | return i; | 
|  | }; | 
|  | return lam; | 
|  | } | 
|  |  | 
|  | // Should be same as above because of NRVO | 
|  | // CHECK: cir.func @_Z2g2v() -> !ty_anon2E8_ | 
|  | // CHECK-NEXT: %0 = cir.alloca !ty_anon2E8_, !cir.ptr<!ty_anon2E8_>, ["__retval", init] {alignment = 8 : i64} | 
|  | // CHECK-NEXT: %1 = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64} | 
|  | // CHECK-NEXT: %2 = cir.const #cir.int<12> : !s32i | 
|  | // CHECK-NEXT: cir.store %2, %1 : !s32i, !cir.ptr<!s32i> | 
|  | // CHECK-NEXT: %3 = cir.get_member %0[0] {name = "i"} : !cir.ptr<!ty_anon2E8_> -> !cir.ptr<!cir.ptr<!s32i>> | 
|  | // CHECK-NEXT: cir.store %1, %3 : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> | 
|  | // CHECK-NEXT: %4 = cir.load %0 : !cir.ptr<!ty_anon2E8_>, !ty_anon2E8_ | 
|  | // CHECK-NEXT: cir.return %4 : !ty_anon2E8_ | 
|  |  | 
|  | int f() { | 
|  | return g2()(); | 
|  | } | 
|  |  | 
|  | //      CHECK: cir.func @_Z1fv() -> !s32i | 
|  | // CHECK-NEXT:   %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64} | 
|  | // CHECK-NEXT:   cir.scope { | 
|  | // CHECK-NEXT:     %2 = cir.alloca !ty_anon2E8_, !cir.ptr<!ty_anon2E8_>, ["ref.tmp0"] {alignment = 8 : i64} | 
|  | // CHECK-NEXT:     %3 = cir.call @_Z2g2v() : () -> !ty_anon2E8_ | 
|  | // CHECK-NEXT:     cir.store %3, %2 : !ty_anon2E8_, !cir.ptr<!ty_anon2E8_> | 
|  | // CHECK-NEXT:     %4 = cir.call @_ZZ2g2vENK3$_0clEv(%2) : (!cir.ptr<!ty_anon2E8_>) -> !s32i | 
|  | // CHECK-NEXT:     cir.store %4, %0 : !s32i, !cir.ptr<!s32i> | 
|  | // CHECK-NEXT:   } | 
|  | // CHECK-NEXT:   %1 = cir.load %0 : !cir.ptr<!s32i>, !s32i | 
|  | // CHECK-NEXT:   cir.return %1 : !s32i | 
|  | // CHECK-NEXT: } | 
|  |  | 
|  | int g3() { | 
|  | auto* fn = +[](int const& i) -> int { return i; }; | 
|  | auto task = fn(3); | 
|  | return task; | 
|  | } | 
|  |  | 
|  | // lambda operator() | 
|  | // CHECK: cir.func lambda internal private @_ZZ2g3vENK3$_0clERKi{{.*}}!s32i extra | 
|  |  | 
|  | // lambda __invoke() | 
|  | // CHECK:   cir.func internal private @_ZZ2g3vEN3$_08__invokeERKi | 
|  |  | 
|  | // lambda operator int (*)(int const&)() | 
|  | // CHECK:   cir.func internal private @_ZZ2g3vENK3$_0cvPFiRKiEEv | 
|  |  | 
|  | // CHECK: cir.func @_Z2g3v() -> !s32i | 
|  | // CHECK:     %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64} | 
|  | // CHECK:     %1 = cir.alloca !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>, !cir.ptr<!cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>>, ["fn", init] {alignment = 8 : i64} | 
|  | // CHECK:     %2 = cir.alloca !s32i, !cir.ptr<!s32i>, ["task", init] {alignment = 4 : i64} | 
|  |  | 
|  | // 1. Use `operator int (*)(int const&)()` to retrieve the fnptr to `__invoke()`. | 
|  | // CHECK:     %3 = cir.scope { | 
|  | // CHECK:       %7 = cir.alloca !ty_anon2E11_, !cir.ptr<!ty_anon2E11_>, ["ref.tmp0"] {alignment = 1 : i64} | 
|  | // CHECK:       %8 = cir.call @_ZZ2g3vENK3$_0cvPFiRKiEEv(%7) : (!cir.ptr<!ty_anon2E11_>) -> !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>> | 
|  | // CHECK:       %9 = cir.unary(plus, %8) : !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>, !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>> | 
|  | // CHECK:       cir.yield %9 : !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>> | 
|  | // CHECK:     } | 
|  |  | 
|  | // 2. Load ptr to `__invoke()`. | 
|  | // CHECK:     cir.store %3, %1 : !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>, !cir.ptr<!cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>> | 
|  | // CHECK:     %4 = cir.scope { | 
|  | // CHECK:       %7 = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp1", init] {alignment = 4 : i64} | 
|  | // CHECK:       %8 = cir.load %1 : !cir.ptr<!cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>>, !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>> | 
|  | // CHECK:       %9 = cir.const #cir.int<3> : !s32i | 
|  | // CHECK:       cir.store %9, %7 : !s32i, !cir.ptr<!s32i> | 
|  |  | 
|  | // 3. Call `__invoke()`, which effectively executes `operator()`. | 
|  | // CHECK:       %10 = cir.call %8(%7) : (!cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>, !cir.ptr<!s32i>) -> !s32i | 
|  | // CHECK:       cir.yield %10 : !s32i | 
|  | // CHECK:     } | 
|  |  | 
|  | // CHECK:   } |