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