|  | // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm %s -o %t -debug-info-kind=limited | 
|  | // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-1 | 
|  | // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2 | 
|  | // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-3 | 
|  | // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-4 | 
|  | // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-5 | 
|  | // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-6 | 
|  | // RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-7 | 
|  |  | 
|  | struct Foo { | 
|  | int x; | 
|  | float y; | 
|  | ~Foo() {} | 
|  | }; | 
|  |  | 
|  | struct TestClass { | 
|  | int x; | 
|  |  | 
|  | TestClass() : x(0) {}; | 
|  | void MemberFunc() { | 
|  | Foo f; | 
|  | #pragma clang __debug captured | 
|  | { | 
|  | static double inner = x; | 
|  | (void)inner; | 
|  | f.y = x; | 
|  | } | 
|  | } | 
|  | }; | 
|  |  | 
|  | void test1() { | 
|  | TestClass c; | 
|  | c.MemberFunc(); | 
|  | // CHECK-1: %[[Capture:struct\.anon[\.0-9]*]] = type { ptr, ptr } | 
|  | // CHECK-1: [[INNER:@.+]] = {{.+}} global double | 
|  |  | 
|  | // CHECK-1: define {{.*}} void @_ZN9TestClass10MemberFuncEv | 
|  | // CHECK-1:   alloca %struct.anon | 
|  | // CHECK-1:   getelementptr inbounds nuw %[[Capture]], ptr %{{[^,]*}}, i32 0, i32 0 | 
|  | // CHECK-1:   getelementptr inbounds nuw %[[Capture]], ptr %{{[^,]*}}, i32 0, i32 1 | 
|  | // CHECK-1:   store ptr %f, ptr | 
|  | // CHECK-1:   call void @[[HelperName:[\.A-Za-z0-9_]+]](ptr | 
|  | // CHECK-1:   call {{.*}}FooD1Ev | 
|  | // CHECK-1:   ret | 
|  | } | 
|  |  | 
|  | // CHECK-1: define internal {{.*}}void @[[HelperName]] | 
|  | // CHECK-1:   getelementptr inbounds nuw %[[Capture]], ptr {{[^,]*}}, i32 0, i32 0 | 
|  | // CHECK-1:   call {{.*}}i32 @__cxa_guard_acquire( | 
|  | // CHECK-1:   store double %{{.+}}, ptr [[INNER]], | 
|  | // CHECK-1:   call {{.*}}void @__cxa_guard_release( | 
|  | // CHECK-1:   getelementptr inbounds nuw %struct.TestClass, ptr {{[^,]*}}, i32 0, i32 0 | 
|  | // CHECK-1:   getelementptr inbounds nuw %[[Capture]], ptr {{[^,]*}}, i32 0, i32 1 | 
|  |  | 
|  | void test2(int x) { | 
|  | int y = [&]() { | 
|  | #pragma clang __debug captured | 
|  | { | 
|  | x++; | 
|  | } | 
|  | return x; | 
|  | }(); | 
|  |  | 
|  | // CHECK-2-LABEL: define {{.*}}void @_Z5test2i | 
|  | // CHECK-2:   call {{.*}} @[[Lambda:["$\w]+]] | 
|  | // | 
|  | // CHECK-2: define internal {{.*}} @[[Lambda]] | 
|  | // CHECK-2:   call void @[[HelperName:["$_A-Za-z0-9]+]](ptr | 
|  | // | 
|  | // CHECK-2: define internal {{.*}}void @[[HelperName]] | 
|  | // CHECK-2:   getelementptr inbounds nuw %[[Capture:.*]], ptr | 
|  | // CHECK-2:   load ptr, ptr | 
|  | // CHECK-2:   load i32, ptr | 
|  | } | 
|  |  | 
|  | void test3(int x) { | 
|  | #pragma clang __debug captured | 
|  | { | 
|  | x = [=]() { return x + 1; } (); | 
|  | } | 
|  | x = [=]() { return x + 1; }(); | 
|  |  | 
|  | // CHECK-3: %[[Capture:struct\.anon[\.0-9]*]] = type { ptr } | 
|  |  | 
|  | // CHECK-3-LABEL: define {{.*}}void @_Z5test3i | 
|  | // CHECK-3:   store ptr | 
|  | // CHECK-3:   call void @{{.*}}__captured_stmt | 
|  | // CHECK-3:   ret void | 
|  | } | 
|  |  | 
|  | void test4() { | 
|  | #pragma clang __debug captured | 
|  | { | 
|  | Foo f; | 
|  | f.x = 5; | 
|  | } | 
|  | // CHECK-4-LABEL: define {{.*}}void @_Z5test4v | 
|  | // CHECK-4:   call void @[[HelperName:[\."$_A-Za-z0-9]+]](ptr | 
|  | // CHECK-4:   ret void | 
|  | // | 
|  | // CHECK-4: define internal {{.*}}void @[[HelperName]] | 
|  | // CHECK-4:   store i32 5, ptr | 
|  | // CHECK-4:   call {{.*}}FooD1Ev | 
|  | } | 
|  |  | 
|  | template <typename T, int id> | 
|  | void touch(const T &) {} | 
|  |  | 
|  | template <typename T, unsigned id> | 
|  | void template_capture_var() { | 
|  | T x; | 
|  | #pragma clang __debug captured | 
|  | { | 
|  | touch<T, id>(x); | 
|  | } | 
|  | } | 
|  |  | 
|  | template <typename T, int id> | 
|  | class Val { | 
|  | T v; | 
|  | public: | 
|  | void set() { | 
|  | #pragma clang __debug captured | 
|  | { | 
|  | touch<T, id>(v); | 
|  | } | 
|  | } | 
|  |  | 
|  | template <typename U, int id2> | 
|  | void foo(U u) { | 
|  | #pragma clang __debug captured | 
|  | { | 
|  | touch<U, id + id2>(u); | 
|  | } | 
|  | } | 
|  | }; | 
|  |  | 
|  | void test_capture_var() { | 
|  | // CHECK-5: define {{.*}} void @_Z20template_capture_varIiLj201EEvv | 
|  | // CHECK-5-NOT: } | 
|  | // CHECK-5: store ptr | 
|  | // CHECK-5: call void @__captured_stmt | 
|  | // CHECK-5-NEXT: ret void | 
|  | template_capture_var<int, 201>(); | 
|  |  | 
|  | // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3setEv | 
|  | // CHECK-5-NOT: } | 
|  | // CHECK-5: store ptr | 
|  | // CHECK-5: call void @__captured_stmt | 
|  | // CHECK-5-NEXT: ret void | 
|  | Val<float, 202> Obj; | 
|  | Obj.set(); | 
|  |  | 
|  | // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3fooIdLi203EEEvT_ | 
|  | // CHECK-5-NOT: } | 
|  | // CHECK-5: store ptr | 
|  | // CHECK-5: store double | 
|  | // CHECK-5: call void @__captured_stmt | 
|  | // CHECK-5-NEXT: ret void | 
|  | Obj.foo<double, 203>(1.0); | 
|  | } | 
|  |  | 
|  | template <typename T> | 
|  | void template_capture_lambda() { | 
|  | T x, y; | 
|  | [=, &y]() { | 
|  | #pragma clang __debug captured | 
|  | { | 
|  | y += x; | 
|  | } | 
|  | }(); | 
|  | } | 
|  |  | 
|  | void test_capture_lambda() { | 
|  | // CHECK-6: define {{.*}} void @_ZZ23template_capture_lambdaIiEvvENKUlvE_clEv | 
|  | // CHECK-6-NOT: } | 
|  | // CHECK-6: store ptr | 
|  | // CHECK-6: store ptr | 
|  | // CHECK-6: call void @__captured_stmt | 
|  | // CHECK-6-NEXT: ret void | 
|  | template_capture_lambda<int>(); | 
|  | } | 
|  |  | 
|  | inline int test_captured_linkage() { | 
|  | // CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr {{(dso_local )?}}global i32 0 | 
|  | int j; | 
|  | #pragma clang __debug captured | 
|  | { | 
|  | static int i = 0; | 
|  | j = ++i; | 
|  | } | 
|  | return j; | 
|  | } | 
|  | void call_test_captured_linkage() { | 
|  | test_captured_linkage(); | 
|  | } | 
|  |  | 
|  | // CHECK-1-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) | 
|  | // CHECK-1-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) | 
|  | // CHECK-2-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) | 
|  | // CHECK-2-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) | 
|  | // CHECK-3-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) | 
|  | // CHECK-3-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) | 
|  | // CHECK-4-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) | 
|  | // CHECK-4-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) | 
|  | // CHECK-5-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) | 
|  | // CHECK-5-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) | 
|  | // CHECK-6-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) | 
|  | // CHECK-6-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) | 
|  | // CHECK-7-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer) | 
|  | // CHECK-7-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial) |