// RUN: %clang_cc1 -std=c++1y -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s struct S { S(); S(S &&); ~S(); }; void f() { (void) [s(S{})] {}; } // CHECK-LABEL: define{{.*}} void @_Z1fv( // CHECK: call void @_ZN1SC1Ev( // CHECK: call void @"_ZZ1fvEN3$_0D1Ev"( // CHECK-LABEL: define internal void @"_ZZ1fvEN3$_0D1Ev"( // CHECK: @"_ZZ1fvEN3$_0D2Ev"( // D2 at end of file. void g() { [a(1), b(2)] { return a + b; } (); } // CHECK-LABEL: define{{.*}} void @_Z1gv( // CHECK: getelementptr inbounds {{.*}}, i32 0, i32 0 // CHECK: store i32 1, i32* // CHECK: getelementptr inbounds {{.*}}, i32 0, i32 1 // CHECK: store i32 2, i32* // CHECK: call i32 @"_ZZ1gvENK3$_1clEv"( // CHECK-LABEL: define internal i32 @"_ZZ1gvENK3$_1clEv"( // CHECK: getelementptr inbounds {{.*}}, i32 0, i32 0 // CHECK: load i32, i32* // CHECK: getelementptr inbounds {{.*}}, i32 0, i32 1 // CHECK: load i32, i32* // CHECK: add nsw i32 // CHECK-LABEL: define{{.*}} void @_Z18init_capture_dtorsv void init_capture_dtors() { // Ensure that init-captures are not treated as separate full-expressions. struct HasDtor { ~HasDtor() {} }; void some_function_call(); void other_function_call(); // CHECK: call {{.*}}some_function_call // CHECK: call {{.*}}HasDtorD ([x = (HasDtor(), 0)]{}, some_function_call()); // CHECK: call {{.*}}other_function_call other_function_call(); } int h(int a) { // CHECK-LABEL: define{{.*}} i32 @_Z1hi( // CHECK: %[[A_ADDR:.*]] = alloca i32, // CHECK: %[[OUTER:.*]] = alloca // CHECK: store i32 {{.*}}, i32* %[[A_ADDR]], // // Initialize init-capture 'b(a)' by reference. // CHECK: getelementptr inbounds {{.*}}, {{.*}}* %[[OUTER]], i32 0, i32 0 // CHECK: store i32* %[[A_ADDR]], i32** {{.*}}, // // Initialize init-capture 'c(a)' by copy. // CHECK: getelementptr inbounds {{.*}}, {{.*}}* %[[OUTER]], i32 0, i32 1 // CHECK: load i32, i32* %[[A_ADDR]], // CHECK: store i32 // // CHECK: call i32 @"_ZZ1hiENK3$_2clEv"({{.*}}* {{[^,]*}} %[[OUTER]]) return [&b(a), c(a)] { // CHECK-LABEL: define internal i32 @"_ZZ1hiENK3$_2clEv"( // CHECK: %[[OUTER_ADDR:.*]] = alloca // CHECK: %[[INNER:.*]] = alloca // CHECK: store {{.*}}, {{.*}}** %[[OUTER_ADDR]], // // Capture outer 'c' by reference. // CHECK: %[[OUTER:.*]] = load {{.*}}*, {{.*}}** %[[OUTER_ADDR]] // CHECK: getelementptr inbounds {{.*}}, {{.*}}* %[[INNER]], i32 0, i32 0 // CHECK-NEXT: getelementptr inbounds {{.*}}, {{.*}}* %[[OUTER]], i32 0, i32 1 // CHECK-NEXT: store i32* % // // Capture outer 'b' by copy. // CHECK: getelementptr inbounds {{.*}}, {{.*}}* %[[INNER]], i32 0, i32 1 // CHECK-NEXT: getelementptr inbounds {{.*}}, {{.*}}* %[[OUTER]], i32 0, i32 0 // CHECK-NEXT: load i32*, i32** % // CHECK-NEXT: load i32, i32* % // CHECK-NEXT: store i32 // // CHECK: call i32 @"_ZZZ1hiENK3$_2clEvENKUlvE_clEv"({{.*}}* {{[^,]*}} %[[INNER]]) return [=, &c] { // CHECK-LABEL: define internal void @"_ZZ1fvEN3$_0D2Ev"( // CHECK: call void @_ZN1SD1Ev( // CHECK-LABEL: define internal i32 @"_ZZZ1hiENK3$_2clEvENKUlvE_clEv"( // CHECK: %[[INNER_ADDR:.*]] = alloca // CHECK: store {{.*}}, {{.*}}** %[[INNER_ADDR]], // CHECK: %[[INNER:.*]] = load {{.*}}*, {{.*}}** %[[INNER_ADDR]] // // Load capture of 'b' // CHECK: getelementptr inbounds {{.*}}, {{.*}}* %[[INNER]], i32 0, i32 1 // CHECK: load i32, i32* % // // Load capture of 'c' // CHECK: getelementptr inbounds {{.*}}, {{.*}}* %[[INNER]], i32 0, i32 0 // CHECK: load i32*, i32** % // CHECK: load i32, i32* % // // CHECK: add nsw i32 return b + c; } (); } (); } // Ensure we can emit code for init-captures in global lambdas too. auto global_lambda = [a = 0] () mutable { return ++a; }; int get_incremented() { return global_lambda(); }