Home | History | Annotate | Download | only in CodeGenCXX
      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 
     10 struct Foo {
     11   int x;
     12   float y;
     13   ~Foo() {}
     14 };
     15 
     16 struct 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 
     29 void 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 
     49 void 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 
     70 void 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 
     84 void 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 
     99 template <typename T, int id>
    100 void touch(const T &) {}
    101 
    102 template <typename T, unsigned id>
    103 void template_capture_var() {
    104   T x;
    105   #pragma clang __debug captured
    106   {
    107     touch<T, id>(x);
    108   }
    109 }
    110 
    111 template <typename T, int id>
    112 class Val {
    113   T v;
    114 public:
    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 
    131 void 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 
    156 template <typename T>
    157 void template_capture_lambda() {
    158   T x, y;
    159   [=, &y]() {
    160     #pragma clang __debug captured
    161     {
    162       y += x;
    163     }
    164   }();
    165 }
    166 
    167 void 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 
    177 inline 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 }
    187 void call_test_captured_linkage() {
    188   test_captured_linkage();
    189 }
    190