Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -emit-llvm -O1 -o - %s | FileCheck %s
      2 // RUN: %clang_cc1 -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:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
    104   // CHECK-EH-NEXT:   catch i8* null
    105   // CHECK-EH-NEXT: call void @_ZSt9terminatev()
    106   // CHECK-EH-NEXT: unreachable
    107 
    108 }
    109 
    110 X test3(bool B) {
    111   // FIXME: We don't manage to apply NRVO here, although we could.
    112   {
    113     X y;
    114     return y;
    115   }
    116   X x;
    117   return x;
    118 }
    119 
    120 extern "C" void exit(int) throw();
    121 
    122 // CHECK: define void @_Z5test4b
    123 X test4(bool B) {
    124   {
    125     // CHECK: tail call {{.*}} @_ZN1XC1Ev
    126     X x;
    127     // CHECK: br i1
    128     if (B)
    129       return x;
    130   }
    131   // CHECK: tail call {{.*}} @_ZN1XD1Ev
    132   // CHECK: tail call void @exit(i32 1)
    133   exit(1);
    134 }
    135 
    136 #ifdef __EXCEPTIONS
    137 // CHECK-EH: define void @_Z5test5
    138 void may_throw();
    139 X test5() {
    140   try {
    141     may_throw();
    142   } catch (X x) {
    143     // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
    144     // CHECK-EH: call void @__cxa_end_catch()
    145     // CHECK-EH: ret void
    146     return x;
    147   }
    148 }
    149 #endif
    150 
    151 // rdar://problem/10430868
    152 // CHECK: define void @_Z5test6v
    153 X test6() {
    154   X a __attribute__((aligned(8)));
    155   return a;
    156   // CHECK:      [[A:%.*]] = alloca [[X:%.*]], align 8
    157   // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* [[A]])
    158   // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* [[A]])
    159   // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* [[A]])
    160   // CHECK-NEXT: ret void
    161 }
    162