Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -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       static double inner = x;
     25       (void)inner;
     26       f.y = x;
     27     }
     28   }
     29 };
     30 
     31 void 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 
     55 void 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 
     76 void test3(int x) {
     77   #pragma clang __debug captured
     78   {
     79     x = [=]() { return x + 1; } ();
     80   }
     81 
     82   // CHECK-3: %[[Capture:struct\.anon[\.0-9]*]] = type { i32* }
     83 
     84   // CHECK-3-LABEL: define {{.*}}void @_Z5test3i
     85   // CHECK-3:   store i32*
     86   // CHECK-3:   call void @{{.*}}__captured_stmt
     87   // CHECK-3:   ret void
     88 }
     89 
     90 void test4() {
     91   #pragma clang __debug captured
     92   {
     93     Foo f;
     94     f.x = 5;
     95   }
     96   // CHECK-4-LABEL: define {{.*}}void @_Z5test4v
     97   // CHECK-4:   call void @[[HelperName:[\."$_A-Za-z0-9]+]](%[[Capture:.*]]*
     98   // CHECK-4:   ret void
     99   //
    100   // CHECK-4: define internal {{.*}}void @[[HelperName]]
    101   // CHECK-4:   store i32 5, i32*
    102   // CHECK-4:   call {{.*}}FooD1Ev
    103 }
    104 
    105 template <typename T, int id>
    106 void touch(const T &) {}
    107 
    108 template <typename T, unsigned id>
    109 void template_capture_var() {
    110   T x;
    111   #pragma clang __debug captured
    112   {
    113     touch<T, id>(x);
    114   }
    115 }
    116 
    117 template <typename T, int id>
    118 class Val {
    119   T v;
    120 public:
    121   void set() {
    122     #pragma clang __debug captured
    123     {
    124       touch<T, id>(v);
    125     }
    126   }
    127 
    128   template <typename U, int id2>
    129   void foo(U u) {
    130     #pragma clang __debug captured
    131     {
    132       touch<U, id + id2>(u);
    133     }
    134   }
    135 };
    136 
    137 void test_capture_var() {
    138   // CHECK-5: define {{.*}} void @_Z20template_capture_varIiLj201EEvv
    139   // CHECK-5-NOT: }
    140   // CHECK-5: store i32*
    141   // CHECK-5: call void @__captured_stmt
    142   // CHECK-5-NEXT: ret void
    143   template_capture_var<int, 201>();
    144 
    145   // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3setEv
    146   // CHECK-5-NOT: }
    147   // CHECK-5: store %class.Val*
    148   // CHECK-5: call void @__captured_stmt
    149   // CHECK-5-NEXT: ret void
    150   Val<float, 202> Obj;
    151   Obj.set();
    152 
    153   // CHECK-5: define {{.*}} void @_ZN3ValIfLi202EE3fooIdLi203EEEvT_
    154   // CHECK-5-NOT: }
    155   // CHECK-5: store %class.Val*
    156   // CHECK-5: store double
    157   // CHECK-5: call void @__captured_stmt
    158   // CHECK-5-NEXT: ret void
    159   Obj.foo<double, 203>(1.0);
    160 }
    161 
    162 template <typename T>
    163 void template_capture_lambda() {
    164   T x, y;
    165   [=, &y]() {
    166     #pragma clang __debug captured
    167     {
    168       y += x;
    169     }
    170   }();
    171 }
    172 
    173 void test_capture_lambda() {
    174   // CHECK-6: define {{.*}} void @_ZZ23template_capture_lambdaIiEvvENKUlvE_clEv
    175   // CHECK-6-NOT: }
    176   // CHECK-6: store i32*
    177   // CHECK-6: store i32*
    178   // CHECK-6: call void @__captured_stmt
    179   // CHECK-6-NEXT: ret void
    180   template_capture_lambda<int>();
    181 }
    182 
    183 inline int test_captured_linkage() {
    184   // CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr global i32 0
    185   int j;
    186   #pragma clang __debug captured
    187   {
    188     static int i = 0;
    189     j = ++i;
    190   }
    191   return j;
    192 }
    193 void call_test_captured_linkage() {
    194   test_captured_linkage();
    195 }
    196