forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			212 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| // 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 { %struct.TestClass*, %struct.Foo* }
 | |
|   // CHECK-1: [[INNER:@.+]] = {{.+}} global double
 | |
| 
 | |
|   // CHECK-1: define {{.*}} void @_ZN9TestClass10MemberFuncEv
 | |
|   // CHECK-1:   alloca %struct.anon
 | |
|   // CHECK-1:   getelementptr inbounds %[[Capture]], %[[Capture]]* %{{[^,]*}}, i32 0, i32 0
 | |
|   // CHECK-1:   getelementptr inbounds %[[Capture]], %[[Capture]]* %{{[^,]*}}, i32 0, i32 1
 | |
|   // CHECK-1:   store %struct.Foo* %f, %struct.Foo**
 | |
|   // 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]], %[[Capture]]* {{[^,]*}}, i32 0, i32 0
 | |
| // CHECK-1:   call {{.*}}i32 @__cxa_guard_acquire(
 | |
| // CHECK-1:   store double %{{.+}}, double* [[INNER]],
 | |
| // CHECK-1:   call {{.*}}void @__cxa_guard_release(
 | |
| // CHECK-1:   getelementptr inbounds %struct.TestClass, %struct.TestClass* {{[^,]*}}, i32 0, i32 0
 | |
| // CHECK-1:   getelementptr inbounds %[[Capture]], %[[Capture]]* {{[^,]*}}, 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]+]](%[[Capture:.*]]*
 | |
|   //
 | |
|   // CHECK-2: define internal {{.*}}void @[[HelperName]]
 | |
|   // CHECK-2:   getelementptr inbounds %[[Capture]], %[[Capture]]*
 | |
|   // CHECK-2:   load i32*, i32**
 | |
|   // CHECK-2:   load i32, i32*
 | |
| }
 | |
| 
 | |
| void test3(int x) {
 | |
|   #pragma clang __debug captured
 | |
|   {
 | |
|     x = [=]() { return x + 1; } ();
 | |
|   }
 | |
|   x = [=]() { return x + 1; }();
 | |
| 
 | |
|   // CHECK-3: %[[Capture:struct\.anon[\.0-9]*]] = type { i32* }
 | |
| 
 | |
|   // CHECK-3-LABEL: 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-LABEL: 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 {{(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)
 |