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 X test2(bool B) {
     48   // No NRVO.
     49 
     50   X x;
     51   X y;
     52   if (B)
     53     return y;
     54   return x;
     55 
     56   // CHECK: call {{.*}} @_ZN1XC1Ev
     57   // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev
     58   // CHECK: call {{.*}} @_ZN1XC1ERKS_
     59   // CHECK: call {{.*}} @_ZN1XC1ERKS_
     60   // CHECK: call {{.*}} @_ZN1XD1Ev
     61   // CHECK: call {{.*}} @_ZN1XD1Ev
     62   // CHECK: ret void
     63 
     64   // The block ordering in the -fexceptions IR is unfortunate.
     65 
     66   // CHECK-EH:      call {{.*}} @_ZN1XC1Ev
     67   // CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev
     68   // -> %invoke.cont, %lpad
     69 
     70   // %invoke.cont:
     71   // CHECK-EH:      br i1
     72   // -> %if.then, %if.end
     73 
     74   // %if.then: returning 'x'
     75   // CHECK-EH:      invoke {{.*}} @_ZN1XC1ERKS_
     76   // -> %cleanup, %lpad1
     77 
     78   // %lpad: landing pad for ctor of 'y', dtor of 'y'
     79   // CHECK-EH:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
     80   // CHECK-EH-NEXT:   cleanup
     81   // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
     82   // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
     83   // CHECK-EH-NEXT: br label
     84   // -> %eh.cleanup
     85 
     86   // %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
     87   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
     88   // -> %eh.cleanup, %terminate.lpad
     89 
     90   // %if.end: returning 'y'
     91   // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
     92   // -> %cleanup, %lpad1
     93 
     94   // %cleanup: normal cleanup for 'y'
     95   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
     96   // -> %invoke.cont11, %lpad
     97 
     98   // %invoke.cont11: normal cleanup for 'x'
     99   // CHECK-EH:      call {{.*}} @_ZN1XD1Ev
    100   // CHECK-EH-NEXT: ret void
    101 
    102   // %eh.cleanup:  EH cleanup for 'x'
    103   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
    104   // -> %invoke.cont17, %terminate.lpad
    105 
    106   // %invoke.cont17: rethrow block for %eh.cleanup.
    107   // This really should be elsewhere in the function.
    108   // CHECK-EH:      resume { i8*, i32 }
    109 
    110   // %terminate.lpad: terminate landing pad.
    111   // CHECK-EH:      [[T0:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
    112   // CHECK-EH-NEXT:   catch i8* null
    113   // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
    114   // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]]
    115   // CHECK-EH-NEXT: unreachable
    116 
    117 }
    118 
    119 // CHECK-LABEL: define void @_Z5test3b
    120 X test3(bool B) {
    121   // CHECK: tail call {{.*}} @_ZN1XC1Ev
    122   // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_
    123   // CHECK: call {{.*}} @_ZN1XC1Ev
    124   // CHECK: call {{.*}} @_ZN1XC1ERKS_
    125   if (B) {
    126     X y;
    127     return y;
    128   }
    129   // FIXME: we should NRVO this variable too.
    130   X x;
    131   return x;
    132 }
    133 
    134 extern "C" void exit(int) throw();
    135 
    136 // CHECK-LABEL: define void @_Z5test4b
    137 X test4(bool B) {
    138   {
    139     // CHECK: tail call {{.*}} @_ZN1XC1Ev
    140     X x;
    141     // CHECK: br i1
    142     if (B)
    143       return x;
    144   }
    145   // CHECK: tail call {{.*}} @_ZN1XD1Ev
    146   // CHECK: tail call void @exit(i32 1)
    147   exit(1);
    148 }
    149 
    150 #ifdef __EXCEPTIONS
    151 // CHECK-EH-LABEL: define void @_Z5test5
    152 void may_throw();
    153 X test5() {
    154   try {
    155     may_throw();
    156   } catch (X x) {
    157     // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
    158     // CHECK-EH: call void @__cxa_end_catch()
    159     // CHECK-EH: ret void
    160     return x;
    161   }
    162 }
    163 #endif
    164 
    165 // rdar://problem/10430868
    166 // CHECK-LABEL: define void @_Z5test6v
    167 X test6() {
    168   X a __attribute__((aligned(8)));
    169   return a;
    170   // CHECK:      [[A:%.*]] = alloca [[X:%.*]], align 8
    171   // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* [[A]])
    172   // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* nonnull [[A]])
    173   // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]])
    174   // CHECK-NEXT: ret void
    175 }
    176 
    177 // CHECK-LABEL: define void @_Z5test7b
    178 X test7(bool b) {
    179   // CHECK: tail call {{.*}} @_ZN1XC1Ev
    180   // CHECK-NEXT: ret
    181   if (b) {
    182     X x;
    183     return x;
    184   }
    185   return X();
    186 }
    187 
    188 // CHECK-LABEL: define void @_Z5test8b
    189 X test8(bool b) {
    190   // CHECK: tail call {{.*}} @_ZN1XC1Ev
    191   // CHECK-NEXT: ret
    192   if (b) {
    193     X x;
    194     return x;
    195   } else {
    196     X y;
    197     return y;
    198   }
    199 }
    200 
    201 Y<int> test9() {
    202   Y<int>::f();
    203 }
    204 
    205 // CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv
    206 // CHECK: tail call {{.*}} @_ZN1YIiEC1Ev
    207 
    208 // CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind }
    209