Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -o - %s | FileCheck %s
      2 // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s
      3 
      4 // Test code generation for the named return value optimization.
      5 class X {
      6 public:
      7   X();
      8   X(const X&);
      9   ~X();
     10 };
     11 
     12 template<typename T> struct Y {
     13   Y();
     14   static Y f() {
     15     Y y;
     16     return y;
     17   }
     18 };
     19 
     20 // CHECK-LABEL: define void @_Z5test0v
     21 // CHECK-EH-LABEL: define void @_Z5test0v
     22 X test0() {
     23   X x;
     24   // CHECK:          call {{.*}} @_ZN1XC1Ev
     25   // CHECK-NEXT:     ret void
     26 
     27   // CHECK-EH:       call {{.*}} @_ZN1XC1Ev
     28   // CHECK-EH-NEXT:  ret void
     29   return x;
     30 }
     31 
     32 // CHECK-LABEL: define void @_Z5test1b(
     33 // CHECK-EH-LABEL: define void @_Z5test1b(
     34 X test1(bool B) {
     35   // CHECK:      tail call {{.*}} @_ZN1XC1Ev
     36   // CHECK-NEXT: ret void
     37   X x;
     38   if (B)
     39     return (x);
     40   return x;
     41   // CHECK-EH:      tail call {{.*}} @_ZN1XC1Ev
     42   // CHECK-EH-NEXT: ret void
     43 }
     44 
     45 // CHECK-LABEL: define void @_Z5test2b
     46 // CHECK-EH-LABEL: define void @_Z5test2b
     47 // CHECK-EH-SAME:  personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
     48 X test2(bool B) {
     49   // No NRVO.
     50 
     51   X x;
     52   X y;
     53   if (B)
     54     return y;
     55   return x;
     56 
     57   // CHECK: call {{.*}} @_ZN1XC1Ev
     58   // CHECK-NEXT: {{.*}} getelementptr inbounds %class.X, %class.X* %y, i32 0, i32 0
     59   // CHECK-NEXT: call void @llvm.lifetime.start
     60   // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev
     61   // CHECK: call {{.*}} @_ZN1XC1ERKS_
     62   // CHECK: call {{.*}} @_ZN1XC1ERKS_
     63   // CHECK: call {{.*}} @_ZN1XD1Ev
     64   // CHECK-NEXT: call void @llvm.lifetime.end
     65   // CHECK: call {{.*}} @_ZN1XD1Ev
     66   // CHECK-NEXT: call void @llvm.lifetime.end
     67   // CHECK: ret void
     68 
     69   // The block ordering in the -fexceptions IR is unfortunate.
     70 
     71   // CHECK-EH:      call void @llvm.lifetime.start
     72   // CHECK-EH-NEXT: call {{.*}} @_ZN1XC1Ev
     73   // CHECK-EH:      call void @llvm.lifetime.start
     74   // CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev
     75   // -> %invoke.cont, %lpad
     76 
     77   // %invoke.cont:
     78   // CHECK-EH:      br i1
     79   // -> %if.then, %if.end
     80 
     81   // %if.then: returning 'x'
     82   // CHECK-EH:      invoke {{.*}} @_ZN1XC1ERKS_
     83   // -> %cleanup, %lpad1
     84 
     85   // %lpad: landing pad for ctor of 'y', dtor of 'y'
     86   // CHECK-EH:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 }
     87   // CHECK-EH-NEXT:   cleanup
     88   // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
     89   // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
     90   // CHECK-EH-NEXT: br label
     91   // -> %eh.cleanup
     92 
     93   // %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
     94   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
     95   // -> %eh.cleanup, %terminate.lpad
     96 
     97   // %if.end: returning 'y'
     98   // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
     99   // -> %cleanup, %lpad1
    100 
    101   // %cleanup: normal cleanup for 'y'
    102   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
    103   // -> %invoke.cont11, %lpad
    104 
    105   // %invoke.cont11: normal cleanup for 'x'
    106   // CHECK-EH:      call void @llvm.lifetime.end
    107   // CHECK-EH-NEXT: call {{.*}} @_ZN1XD1Ev
    108   // CHECK-EH-NEXT: call void @llvm.lifetime.end
    109   // CHECK-EH-NEXT: ret void
    110 
    111   // %eh.cleanup:  EH cleanup for 'x'
    112   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
    113   // -> %invoke.cont17, %terminate.lpad
    114 
    115   // %invoke.cont17: rethrow block for %eh.cleanup.
    116   // This really should be elsewhere in the function.
    117   // CHECK-EH:      resume { i8*, i32 }
    118 
    119   // %terminate.lpad: terminate landing pad.
    120   // CHECK-EH:      [[T0:%.*]] = landingpad { i8*, i32 }
    121   // CHECK-EH-NEXT:   catch i8* null
    122   // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
    123   // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]]
    124   // CHECK-EH-NEXT: unreachable
    125 
    126 }
    127 
    128 // CHECK-LABEL: define void @_Z5test3b
    129 X test3(bool B) {
    130   // CHECK: tail call {{.*}} @_ZN1XC1Ev
    131   // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_
    132   // CHECK: call {{.*}} @_ZN1XC1Ev
    133   // CHECK: call {{.*}} @_ZN1XC1ERKS_
    134   if (B) {
    135     X y;
    136     return y;
    137   }
    138   // FIXME: we should NRVO this variable too.
    139   X x;
    140   return x;
    141 }
    142 
    143 extern "C" void exit(int) throw();
    144 
    145 // CHECK-LABEL: define void @_Z5test4b
    146 X test4(bool B) {
    147   {
    148     // CHECK: tail call {{.*}} @_ZN1XC1Ev
    149     X x;
    150     // CHECK: br i1
    151     if (B)
    152       return x;
    153   }
    154   // CHECK: tail call {{.*}} @_ZN1XD1Ev
    155   // CHECK: tail call void @exit(i32 1)
    156   exit(1);
    157 }
    158 
    159 #ifdef __EXCEPTIONS
    160 // CHECK-EH-LABEL: define void @_Z5test5
    161 void may_throw();
    162 X test5() {
    163   try {
    164     may_throw();
    165   } catch (X x) {
    166     // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
    167     // CHECK-EH: call void @__cxa_end_catch()
    168     // CHECK-EH: ret void
    169     return x;
    170   }
    171 }
    172 #endif
    173 
    174 // rdar://problem/10430868
    175 // CHECK-LABEL: define void @_Z5test6v
    176 X test6() {
    177   X a __attribute__((aligned(8)));
    178   return a;
    179   // CHECK:      [[A:%.*]] = alloca [[X:%.*]], align 8
    180   // CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds %class.X, %class.X* [[A]], i32 0, i32 0
    181   // CHECK-NEXT: call void @llvm.lifetime.start(i64 1, i8* [[PTR]])
    182   // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* nonnull [[A]])
    183   // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* nonnull dereferenceable({{[0-9]+}}) [[A]])
    184   // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* nonnull [[A]])
    185   // CHECK-NEXT: call void @llvm.lifetime.end(i64 1, i8* [[PTR]])
    186   // CHECK-NEXT: ret void
    187 }
    188 
    189 // CHECK-LABEL: define void @_Z5test7b
    190 X test7(bool b) {
    191   // CHECK: tail call {{.*}} @_ZN1XC1Ev
    192   // CHECK-NEXT: ret
    193   if (b) {
    194     X x;
    195     return x;
    196   }
    197   return X();
    198 }
    199 
    200 // CHECK-LABEL: define void @_Z5test8b
    201 X test8(bool b) {
    202   // CHECK: tail call {{.*}} @_ZN1XC1Ev
    203   // CHECK-NEXT: ret
    204   if (b) {
    205     X x;
    206     return x;
    207   } else {
    208     X y;
    209     return y;
    210   }
    211 }
    212 
    213 Y<int> test9() {
    214   Y<int>::f();
    215 }
    216 
    217 // CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv
    218 // CHECK: tail call {{.*}} @_ZN1YIiEC1Ev
    219 
    220 // CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind }
    221