Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
      2 void *f();
      3 
      4 template <typename T> T* g() {
      5  if (T* t = f())
      6    return t;
      7 
      8  return 0;
      9 }
     10 
     11 void h() {
     12  void *a = g<void>();
     13 }
     14 
     15 struct X {
     16   X();
     17   X(const X&);
     18   ~X();
     19   operator bool();
     20 };
     21 
     22 struct Y {
     23   Y();
     24   ~Y();
     25 };
     26 
     27 X getX();
     28 
     29 // CHECK-LABEL: define void @_Z11if_destructi(
     30 void if_destruct(int z) {
     31   // Verify that the condition variable is destroyed at the end of the
     32   // "if" statement.
     33   // CHECK: call void @_ZN1XC1Ev
     34   // CHECK: call zeroext i1 @_ZN1XcvbEv
     35   if (X x = X()) {
     36     // CHECK: store i32 18
     37     z = 18;
     38   }
     39   // CHECK: call void @_ZN1XD1Ev
     40   // CHECK: store i32 17
     41   z = 17;
     42 
     43   // CHECK: call void @_ZN1XC1Ev
     44   if (X x = X())
     45     Y y;
     46   // CHECK: br
     47   // CHECK: call  void @_ZN1YC1Ev
     48   // CHECK: call  void @_ZN1YD1Ev
     49   // CHECK: br
     50   // CHECK: call  void @_ZN1XD1Ev
     51 
     52   // CHECK: call void @_Z4getXv
     53   // CHECK: call zeroext i1 @_ZN1XcvbEv
     54   // CHECK: call void @_ZN1XD1Ev
     55   // CHECK: br
     56   if (getX()) { }
     57 
     58   // CHECK: ret
     59 }
     60 
     61 struct ConvertibleToInt {
     62   ConvertibleToInt();
     63   ~ConvertibleToInt();
     64   operator int();
     65 };
     66 
     67 ConvertibleToInt getConvToInt();
     68 
     69 void switch_destruct(int z) {
     70   // CHECK: call void @_ZN16ConvertibleToIntC1Ev
     71   switch (ConvertibleToInt conv = ConvertibleToInt()) {
     72   case 0:
     73     break;
     74 
     75   default:
     76     // CHECK: store i32 19
     77     z = 19;
     78     break;
     79   }
     80   // CHECK: call void @_ZN16ConvertibleToIntD1Ev
     81   // CHECK: store i32 20
     82   z = 20;
     83 
     84   // CHECK: call void @_Z12getConvToIntv
     85   // CHECK: call i32 @_ZN16ConvertibleToIntcviEv
     86   // CHECK: call void @_ZN16ConvertibleToIntD1Ev
     87   switch(getConvToInt()) {
     88   case 0:
     89     break;
     90   }
     91   // CHECK: store i32 27
     92   z = 27;
     93   // CHECK: ret
     94 }
     95 
     96 int foo();
     97 
     98 // CHECK-LABEL: define void @_Z14while_destructi
     99 void while_destruct(int z) {
    100   // CHECK: [[Z:%.*]] = alloca i32
    101   // CHECK: [[CLEANUPDEST:%.*]] = alloca i32
    102   while (X x = X()) {
    103     // CHECK: call void @_ZN1XC1Ev
    104     // CHECK-NEXT: [[COND:%.*]] = call zeroext i1 @_ZN1XcvbEv
    105     // CHECK-NEXT: br i1 [[COND]]
    106 
    107     // Loop-exit staging block.
    108     // CHECK: store i32 3, i32* [[CLEANUPDEST]]
    109     // CHECK-NEXT: br
    110 
    111     // While body.
    112     // CHECK: store i32 21, i32* [[Z]]
    113     // CHECK: store i32 0, i32* [[CLEANUPDEST]]
    114     // CHECK-NEXT: br
    115     z = 21;
    116 
    117     // Cleanup.
    118     // CHECK: call void @_ZN1XD1Ev
    119     // CHECK-NEXT: [[DEST:%.*]] = load i32, i32* [[CLEANUPDEST]]
    120     // CHECK-NEXT: switch i32 [[DEST]]
    121   }
    122 
    123   // CHECK: store i32 22, i32* [[Z]]
    124   z = 22;
    125 
    126   // CHECK: call void @_Z4getXv
    127   // CHECK-NEXT: call zeroext i1 @_ZN1XcvbEv
    128   // CHECK-NEXT: call void @_ZN1XD1Ev
    129   // CHECK-NEXT: br
    130   while(getX()) { }
    131 
    132   // CHECK: store i32 25, i32* [[Z]]
    133   z = 25;
    134 
    135   // CHECK: ret
    136 }
    137 
    138 // CHECK-LABEL: define void @_Z12for_destructi(
    139 void for_destruct(int z) {
    140   // CHECK: [[Z:%.*]] = alloca i32
    141   // CHECK: [[CLEANUPDEST:%.*]] = alloca i32
    142   // CHECK: [[I:%.*]] = alloca i32
    143   // CHECK: call void @_ZN1YC1Ev
    144   // CHECK-NEXT: br
    145   // -> %for.cond
    146 
    147   for(Y y = Y(); X x = X(); ++z) {
    148     // %for.cond: The loop condition.
    149     // CHECK: call void @_ZN1XC1Ev
    150     // CHECK-NEXT: [[COND:%.*]] = call zeroext i1 @_ZN1XcvbEv(
    151     // CHECK-NEXT: br i1 [[COND]]
    152     // -> %for.body, %for.cond.cleanup
    153 
    154     // %for.cond.cleanup: Exit cleanup staging.
    155     // CHECK: store i32 2, i32* [[CLEANUPDEST]]
    156     // CHECK-NEXT: br
    157     // -> %cleanup
    158 
    159     // %for.body:
    160     // CHECK: store i32 23, i32* [[Z]]
    161     // CHECK-NEXT: br
    162     // -> %for.inc
    163     z = 23;
    164 
    165     // %for.inc:
    166     // CHECK: [[TMP:%.*]] = load i32, i32* [[Z]]
    167     // CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP]], 1
    168     // CHECK-NEXT: store i32 [[INC]], i32* [[Z]]
    169     // CHECK-NEXT: store i32 0, i32* [[CLEANUPDEST]]
    170     // CHECK-NEXT: br
    171     // -> %cleanup
    172 
    173     // %cleanup:  Destroys X.
    174     // CHECK: call void @_ZN1XD1Ev
    175     // CHECK-NEXT: [[YDESTTMP:%.*]] = load i32, i32* [[CLEANUPDEST]]
    176     // CHECK-NEXT: switch i32 [[YDESTTMP]]
    177     // 0 -> %cleanup.cont, default -> %cleanup1
    178 
    179     // %cleanup.cont:  (eliminable)
    180     // CHECK: br
    181     // -> %for.cond
    182 
    183     // %cleanup1: Destroys Y.
    184     // CHECK: call void @_ZN1YD1Ev(
    185     // CHECK-NEXT: br
    186     // -> %for.end
    187   }
    188 
    189   // %for.end:
    190   // CHECK: store i32 24
    191   z = 24;
    192 
    193   // CHECK-NEXT: store i32 0, i32* [[I]]
    194   // CHECK-NEXT: br
    195   // -> %for.cond6
    196 
    197   // %for.cond6:
    198   // CHECK: call void @_Z4getXv
    199   // CHECK-NEXT: call zeroext i1 @_ZN1XcvbEv
    200   // CHECK-NEXT: call void @_ZN1XD1Ev
    201   // CHECK-NEXT: br
    202   // -> %for.body10, %for.end16
    203 
    204   // %for.body10:
    205   // CHECK: br
    206   // -> %for.inc11
    207 
    208   // %for.inc11:
    209   // CHECK: call void @_Z4getXv
    210   // CHECK-NEXT: load i32, i32* [[I]]
    211   // CHECK-NEXT: add
    212   // CHECK-NEXT: store
    213   // CHECK-NEXT: call void @_ZN1XD1Ev
    214   // CHECK-NEXT: br
    215   // -> %for.cond6
    216   int i = 0;
    217   for(; getX(); getX(), ++i) { }
    218 
    219   // %for.end16
    220   // CHECK: store i32 26
    221   z = 26;
    222 
    223   // CHECK-NEXT: ret void
    224 }
    225 
    226 void do_destruct(int z) {
    227   // CHECK-LABEL: define void @_Z11do_destruct
    228   do {
    229     // CHECK: store i32 77
    230     z = 77;
    231     // CHECK: call void @_Z4getXv
    232     // CHECK: call zeroext i1 @_ZN1XcvbEv
    233     // CHECK: call void @_ZN1XD1Ev
    234     // CHECK: br
    235   } while (getX());
    236   // CHECK: store i32 99
    237   z = 99;
    238   // CHECK: ret
    239 }
    240 
    241 int f(X);
    242 
    243 template<typename T>
    244 int instantiated(T x) {
    245   int result;
    246 
    247   // CHECK: call void @_ZN1XC1ERKS_
    248   // CHECK: call i32 @_Z1f1X
    249   // CHECK: call void @_ZN1XD1Ev
    250   // CHECK: br
    251   // CHECK: store i32 2
    252   // CHECK: br
    253   // CHECK: store i32 3
    254   if (f(x)) { result = 2; } else { result = 3; }
    255 
    256   // CHECK: call void @_ZN1XC1ERKS_
    257   // CHECK: call i32 @_Z1f1X
    258   // CHECK: call void @_ZN1XD1Ev
    259   // CHECK: br
    260   // CHECK: store i32 4
    261   // CHECK: br
    262   while (f(x)) { result = 4; }
    263 
    264   // CHECK: call void @_ZN1XC1ERKS_
    265   // CHECK: call i32 @_Z1f1X
    266   // CHECK: call void @_ZN1XD1Ev
    267   // CHECK: br
    268   // CHECK: store i32 6
    269   // CHECK: br
    270   // CHECK: call void @_ZN1XC1ERKS_
    271   // CHECK: call i32 @_Z1f1X
    272   // CHECK: store i32 5
    273   // CHECK: call void @_ZN1XD1Ev
    274   // CHECK: br
    275   for (; f(x); f(x), result = 5) {
    276     result = 6;
    277   }
    278 
    279   // CHECK: call void @_ZN1XC1ERKS_
    280   // CHECK: call i32 @_Z1f1X
    281   // CHECK: call void @_ZN1XD1Ev
    282   // CHECK: switch i32
    283   // CHECK: store i32 7
    284   // CHECK: store i32 8
    285   switch (f(x)) {
    286   case 0:
    287     result = 7;
    288     break;
    289 
    290   case 1:
    291     result = 8;
    292   }
    293 
    294   // CHECK: store i32 9
    295   // CHECK: br
    296   // CHECK: call void @_ZN1XC1ERKS_
    297   // CHECK: call i32 @_Z1f1X
    298   // CHECK: call void @_ZN1XD1Ev
    299   // CHECK: br
    300   do {
    301     result = 9;
    302   } while (f(x));
    303 
    304   // CHECK: store i32 10
    305   // CHECK: call void @_ZN1XC1ERKS_
    306   // CHECK: call zeroext i1 @_ZN1XcvbEv
    307   // CHECK: call void @_ZN1XD1Ev
    308   // CHECK: br
    309   do {
    310     result = 10;
    311   } while (X(x));
    312 
    313   // CHECK: ret i32
    314   return result;
    315 }
    316 
    317 template int instantiated(X);
    318