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 // CHECK: define void @_Z5test0v
     13 // CHECK-EH: define void @_Z5test0v
     14 X test0() {
     15   X x;
     16   // CHECK:          call {{.*}} @_ZN1XC1Ev
     17   // CHECK-NEXT:     ret void
     18 
     19   // CHECK-EH:       call {{.*}} @_ZN1XC1Ev
     20   // CHECK-EH-NEXT:  ret void
     21   return x;
     22 }
     23 
     24 // CHECK: define void @_Z5test1b(
     25 // CHECK-EH: define void @_Z5test1b(
     26 X test1(bool B) {
     27   // CHECK:      tail call {{.*}} @_ZN1XC1Ev
     28   // CHECK-NEXT: ret void
     29   X x;
     30   if (B)
     31     return (x);
     32   return x;
     33   // CHECK-EH:      tail call {{.*}} @_ZN1XC1Ev
     34   // CHECK-EH-NEXT: ret void
     35 }
     36 
     37 // CHECK: define void @_Z5test2b
     38 // CHECK-EH: define void @_Z5test2b
     39 X test2(bool B) {
     40   // No NRVO.
     41 
     42   X x;
     43   X y;
     44   if (B)
     45     return y;
     46   return x;
     47 
     48   // CHECK: call {{.*}} @_ZN1XC1Ev
     49   // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev
     50   // CHECK: call {{.*}} @_ZN1XC1ERKS_
     51   // CHECK: call {{.*}} @_ZN1XC1ERKS_
     52   // CHECK: call {{.*}} @_ZN1XD1Ev
     53   // CHECK: call {{.*}} @_ZN1XD1Ev
     54   // CHECK: ret void
     55 
     56   // The block ordering in the -fexceptions IR is unfortunate.
     57 
     58   // CHECK-EH:      call {{.*}} @_ZN1XC1Ev
     59   // CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev
     60   // -> %invoke.cont, %lpad
     61 
     62   // %invoke.cont:
     63   // CHECK-EH:      br i1
     64   // -> %if.then, %if.end
     65 
     66   // %if.then: returning 'x'
     67   // CHECK-EH:      invoke {{.*}} @_ZN1XC1ERKS_
     68   // -> %cleanup, %lpad1
     69 
     70   // %lpad: landing pad for ctor of 'y', dtor of 'y'
     71   // CHECK-EH:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
     72   // CHECK-EH-NEXT:   cleanup
     73   // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
     74   // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
     75   // CHECK-EH-NEXT: br label
     76   // -> %eh.cleanup
     77 
     78   // %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
     79   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
     80   // -> %eh.cleanup, %terminate.lpad
     81 
     82   // %if.end: returning 'y'
     83   // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
     84   // -> %cleanup, %lpad1
     85 
     86   // %cleanup: normal cleanup for 'y'
     87   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
     88   // -> %invoke.cont11, %lpad
     89 
     90   // %invoke.cont11: normal cleanup for 'x'
     91   // CHECK-EH:      call {{.*}} @_ZN1XD1Ev
     92   // CHECK-EH-NEXT: ret void
     93 
     94   // %eh.cleanup:  EH cleanup for 'x'
     95   // CHECK-EH: invoke {{.*}} @_ZN1XD1Ev
     96   // -> %invoke.cont17, %terminate.lpad
     97 
     98   // %invoke.cont17: rethrow block for %eh.cleanup.
     99   // This really should be elsewhere in the function.
    100   // CHECK-EH:      resume { i8*, i32 }
    101 
    102   // %terminate.lpad: terminate landing pad.
    103   // CHECK-EH:      [[T0:%.*]] = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
    104   // CHECK-EH-NEXT:   catch i8* null
    105   // CHECK-EH-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
    106   // CHECK-EH-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]]
    107   // CHECK-EH-NEXT: unreachable
    108 
    109 }
    110 
    111 X test3(bool B) {
    112   // FIXME: We don't manage to apply NRVO here, although we could.
    113   {
    114     X y;
    115     return y;
    116   }
    117   X x;
    118   return x;
    119 }
    120 
    121 extern "C" void exit(int) throw();
    122 
    123 // CHECK: define void @_Z5test4b
    124 X test4(bool B) {
    125   {
    126     // CHECK: tail call {{.*}} @_ZN1XC1Ev
    127     X x;
    128     // CHECK: br i1
    129     if (B)
    130       return x;
    131   }
    132   // CHECK: tail call {{.*}} @_ZN1XD1Ev
    133   // CHECK: tail call void @exit(i32 1)
    134   exit(1);
    135 }
    136 
    137 #ifdef __EXCEPTIONS
    138 // CHECK-EH: define void @_Z5test5
    139 void may_throw();
    140 X test5() {
    141   try {
    142     may_throw();
    143   } catch (X x) {
    144     // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
    145     // CHECK-EH: call void @__cxa_end_catch()
    146     // CHECK-EH: ret void
    147     return x;
    148   }
    149 }
    150 #endif
    151 
    152 // rdar://problem/10430868
    153 // CHECK: define void @_Z5test6v
    154 X test6() {
    155   X a __attribute__((aligned(8)));
    156   return a;
    157   // CHECK:      [[A:%.*]] = alloca [[X:%.*]], align 8
    158   // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* [[A]])
    159   // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* [[A]])
    160   // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]])
    161   // CHECK-NEXT: ret void
    162 }
    163 
    164 // CHECK-EH: attributes [[NR_NUW]] = { noreturn nounwind }
    165