// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o %t // 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 { f.y = x; } } }; void test1() { TestClass c; c.MemberFunc(); // CHECK-1: %[[Capture:struct\.anon[\.0-9]*]] = type { %struct.Foo*, %struct.TestClass* } // CHECK-1: define {{.*}} void @_ZN9TestClass10MemberFuncEv // CHECK-1: alloca %struct.anon // CHECK-1: getelementptr inbounds %[[Capture]]* %{{[^,]*}}, i32 0, i32 0 // CHECK-1: store %struct.Foo* %f, %struct.Foo** // CHECK-1: getelementptr inbounds %[[Capture]]* %{{[^,]*}}, i32 0, i32 1 // CHECK-1: call void @[[HelperName:[A-Za-z0-9_]+]](%[[Capture]]* // CHECK-1: call {{.*}}FooD1Ev // CHECK-1: ret } // CHECK-1: define internal void @[[HelperName]] // CHECK-1: getelementptr inbounds %[[Capture]]* {{[^,]*}}, i32 0, i32 1 // CHECK-1: getelementptr inbounds %struct.TestClass* {{[^,]*}}, i32 0, i32 0 // CHECK-1: getelementptr inbounds %[[Capture]]* {{[^,]*}}, i32 0, i32 0 void test2(int x) { int y = [&]() { #pragma clang __debug captured { x++; } return x; }(); // CHECK-2: define void @_Z5test2i // CHECK-2: call {{.*}} @[[Lambda:["$\w]+]] // // CHECK-2: define internal {{.*}} @[[Lambda]] // CHECK-2: call void @[[HelperName:["$_A-Za-z0-9]+]](%[[Capture:.*]]* // // CHECK-2: define internal void @[[HelperName]] // CHECK-2: getelementptr inbounds %[[Capture]]* // CHECK-2: load i32** // CHECK-2: load i32* } void test3(int x) { #pragma clang __debug captured { x = [=]() { return x + 1; } (); } // CHECK-3: %[[Capture:struct\.anon[\.0-9]*]] = type { i32* } // CHECK-3: define void @_Z5test3i // CHECK-3: store i32* // CHECK-3: call void @{{.*}}__captured_stmt // CHECK-3: ret void } void test4() { #pragma clang __debug captured { Foo f; f.x = 5; } // CHECK-4: define void @_Z5test4v // CHECK-4: call void @[[HelperName:["$_A-Za-z0-9]+]](%[[Capture:.*]]* // CHECK-4: ret void // // CHECK-4: define internal void @[[HelperName]] // CHECK-4: store i32 5, i32* // 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 i32* // 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 %class.Val* // 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 %class.Val* // 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 i32* // CHECK-6: store i32* // 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 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(); }