Clang Project

clang_source_code/test/CodeGenCXX/captured-statements.cpp
1// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm %s -o %t -debug-info-kind=limited
2// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-1
3// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-2
4// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-3
5// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-4
6// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-5
7// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-6
8// RUN: FileCheck %s -input-file=%t -check-prefix=CHECK-7
9
10struct Foo {
11  int x;
12  float y;
13  ~Foo() {}
14};
15
16struct TestClass {
17  int x;
18
19  TestClass() : x(0) {};
20  void MemberFunc() {
21    Foo f;
22    #pragma clang __debug captured
23    {
24      static double inner = x;
25      (void)inner;
26      f.y = x;
27    }
28  }
29};
30
31void test1() {
32  TestClass c;
33  c.MemberFunc();
34  // CHECK-1: %[[Capture:struct\.anon[\.0-9]*]] = type { %struct.TestClass*, %struct.Foo* }
35  // CHECK-1: [[INNER:@.+]] = {{.+}} global double
36
37  // CHECK-1: define {{.*}} void @_ZN9TestClass10MemberFuncEv
38  // CHECK-1:   alloca %struct.anon
39  // CHECK-1:   getelementptr inbounds %[[Capture]], %[[Capture]]* %{{[^,]*}}, i32 0, i32 0
40  // CHECK-1:   getelementptr inbounds %[[Capture]], %[[Capture]]* %{{[^,]*}}, i32 0, i32 1
41  // CHECK-1:   store %struct.Foo* %f, %struct.Foo**
42  // CHECK-1:   call void @[[HelperName:[\.A-Za-z0-9_]+]](%[[Capture]]*
43  // CHECK-1:   call {{.*}}FooD1Ev
44  // CHECK-1:   ret
45}
46
47// CHECK-1: define internal {{.*}}void @[[HelperName]]
48// CHECK-1:   getelementptr inbounds %[[Capture]], %[[Capture]]* {{[^,]*}}, i32 0, i32 0
49// CHECK-1:   call {{.*}}i32 @__cxa_guard_acquire(
50// CHECK-1:   store double %{{.+}}, double* [[INNER]],
51// CHECK-1:   call {{.*}}void @__cxa_guard_release(
52// CHECK-1:   getelementptr inbounds %struct.TestClass, %struct.TestClass* {{[^,]*}}, i32 0, i32 0
53// CHECK-1:   getelementptr inbounds %[[Capture]], %[[Capture]]* {{[^,]*}}, i32 0, i32 1
54
55void test2(int x) {
56  int y = [&]() {
57    #pragma clang __debug captured
58    {
59      x++;
60    }
61    return x;
62  }();
63
64  // CHECK-2-LABEL: define {{.*}}void @_Z5test2i
65  // CHECK-2:   call {{.*}} @[[Lambda:["$\w]+]]
66  //
67  // CHECK-2: define internal {{.*}} @[[Lambda]]
68  // CHECK-2:   call void @[[HelperName:["$_A-Za-z0-9]+]](%[[Capture:.*]]*
69  //
70  // CHECK-2: define internal {{.*}}void @[[HelperName]]
71  // CHECK-2:   getelementptr inbounds %[[Capture]], %[[Capture]]*
72  // CHECK-2:   load i32*, i32**
73  // CHECK-2:   load i32, i32*
74}
75
76void test3(int x) {
77  #pragma clang __debug captured
78  {
79    x = [=]() { return x + 1; } ();
80  }
81  x = [=]() { return x + 1; }();
82
83  // CHECK-3: %[[Capture:struct\.anon[\.0-9]*]] = type { i32* }
84
85  // CHECK-3-LABEL: define {{.*}}void @_Z5test3i
86  // CHECK-3:   store i32*
87  // CHECK-3:   call void @{{.*}}__captured_stmt
88  // CHECK-3:   ret void
89}
90
91void test4() {
92  #pragma clang __debug captured
93  {
94    Foo f;
95    f.x = 5;
96  }
97  // CHECK-4-LABEL: define {{.*}}void @_Z5test4v
98  // CHECK-4:   call void @[[HelperName:[\."$_A-Za-z0-9]+]](%[[Capture:.*]]*
99  // CHECK-4:   ret void
100  //
101  // CHECK-4: define internal {{.*}}void @[[HelperName]]
102  // CHECK-4:   store i32 5, i32*
103  // CHECK-4:   call {{.*}}FooD1Ev
104}
105
106template <typename T, int id>
107void touch(const T &) {}
108
109template <typename T, unsigned id>
110void template_capture_var() {
111  T x;
112  #pragma clang __debug captured
113  {
114    touch<T, id>(x);
115  }
116}
117
118template <typename T, int id>
119class Val {
120  T v;
121public:
122  void set() {
123    #pragma clang __debug captured
124    {
125      touch<T, id>(v);
126    }
127  }
128
129  template <typename U, int id2>
130  void foo(U u) {
131    #pragma clang __debug captured
132    {
133      touch<U, id + id2>(u);
134    }
135  }
136};
137
138void test_capture_var() {
139  // CHECK-5: define {{.*}} void @_Z20template_capture_varIiLj201EEvv
140  // CHECK-5-NOT: }
141  // CHECK-5: store i32*
142  // CHECK-5: call void @__captured_stmt
143  // CHECK-5-NEXT: ret void
144  template_capture_var<int, 201>();
145
146  // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3setEv
147  // CHECK-5-NOT: }
148  // CHECK-5: store %class.Val*
149  // CHECK-5: call void @__captured_stmt
150  // CHECK-5-NEXT: ret void
151  Val<float, 202> Obj;
152  Obj.set();
153
154  // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3fooIdLi203EEEvT_
155  // CHECK-5-NOT: }
156  // CHECK-5: store %class.Val*
157  // CHECK-5: store double
158  // CHECK-5: call void @__captured_stmt
159  // CHECK-5-NEXT: ret void
160  Obj.foo<double, 203>(1.0);
161}
162
163template <typename T>
164void template_capture_lambda() {
165  T x, y;
166  [=, &y]() {
167    #pragma clang __debug captured
168    {
169      y += x;
170    }
171  }();
172}
173
174void test_capture_lambda() {
175  // CHECK-6: define {{.*}} void @_ZZ23template_capture_lambdaIiEvvENKUlvE_clEv
176  // CHECK-6-NOT: }
177  // CHECK-6: store i32*
178  // CHECK-6: store i32*
179  // CHECK-6: call void @__captured_stmt
180  // CHECK-6-NEXT: ret void
181  template_capture_lambda<int>();
182}
183
184inline int test_captured_linkage() {
185  // CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr {{(dso_local )?}}global i32 0
186  int j;
187  #pragma clang __debug captured
188  {
189    static int i = 0;
190    j = ++i;
191  }
192  return j;
193}
194void call_test_captured_linkage() {
195  test_captured_linkage();
196}
197
198// CHECK-1-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
199// CHECK-1-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
200// CHECK-2-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
201// CHECK-2-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
202// CHECK-3-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
203// CHECK-3-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
204// CHECK-4-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
205// CHECK-4-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
206// CHECK-5-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
207// CHECK-5-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
208// CHECK-6-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
209// CHECK-6-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
210// CHECK-7-DAG: !DILocalVariable(name: "this", {{.*}}, flags: DIFlagArtificial | DIFlagObjectPointer)
211// CHECK-7-DAG: !DILocalVariable(name: "__context", {{.*}}, flags: DIFlagArtificial)
212