nrvo.cpp revision f5d8f466c3eebaffc51468812bdcbe7f0fe4891a
1// RUN: %clang_cc1 -emit-llvm -O1 -o - %s | FileCheck %s
2// RUN: %clang_cc1 -emit-llvm -O1 -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s
3
4// Test code generation for the named return value optimization.
5class X {
6public:
7  X();
8  X(const X&);
9  ~X();
10};
11
12// CHECK: define void @_Z5test0v
13// CHECK-EH: define void @_Z5test0v
14X test0() {
15  X x;
16  // CHECK:          call void @_ZN1XC1Ev
17  // CHECK-NEXT:     ret void
18
19  // CHECK-EH:       call void @_ZN1XC1Ev
20  // CHECK-EH-NEXT:  ret void
21  return x;
22}
23
24// CHECK: define void @_Z5test1b(
25// CHECK-EH: define void @_Z5test1b(
26X test1(bool B) {
27  // CHECK:      tail call void @_ZN1XC1Ev
28  // CHECK-NEXT: ret void
29  X x;
30  if (B)
31    return (x);
32  return x;
33  // CHECK-EH:      tail call void @_ZN1XC1Ev
34  // CHECK-EH-NEXT: ret void
35}
36
37// CHECK: define void @_Z5test2b
38// CHECK-EH: define void @_Z5test2b
39X 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 void @_ZN1XC1Ev
49  // CHECK-NEXT: call void @_ZN1XC1Ev
50  // CHECK: call void @_ZN1XC1ERKS_
51  // CHECK: call void @_ZN1XC1ERKS_
52  // CHECK: call void @_ZN1XD1Ev
53  // CHECK: call void @_ZN1XD1Ev
54  // CHECK: ret void
55
56  // The block ordering in the -fexceptions IR is unfortunate.
57
58  // CHECK-EH:      call void @_ZN1XC1Ev
59  // CHECK-EH-NEXT: invoke void @_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 void @_ZN1XC1ERKS_
68  // -> %cleanup, %lpad1
69
70  // %lpad: landing pad for ctor of 'y', dtor of 'y'
71  // CHECK-EH:      call i8* @llvm.eh.exception()
72  // CHECK-EH: call i32 (i8*, i8*, ...)* @llvm.eh.selector
73  // CHECK-EH-NEXT: br label
74  // -> %eh.cleanup
75
76  // %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
77  // CHECK-EH: invoke void @_ZN1XD1Ev
78  // -> %eh.cleanup, %terminate.lpad
79
80  // %if.end: returning 'y'
81  // CHECK-EH: invoke void @_ZN1XC1ERKS_
82  // -> %cleanup, %lpad1
83
84  // %cleanup: normal cleanup for 'y'
85  // CHECK-EH: invoke void @_ZN1XD1Ev
86  // -> %invoke.cont11, %lpad
87
88  // %invoke.cont11: normal cleanup for 'x'
89  // CHECK-EH:      call void @_ZN1XD1Ev
90  // CHECK-EH-NEXT: ret void
91
92  // %eh.cleanup:  EH cleanup for 'x'
93  // CHECK-EH: invoke void @_ZN1XD1Ev
94  // -> %invoke.cont17, %terminate.lpad
95
96  // %invoke.cont17: rethrow block for %eh.cleanup.
97  // This really should be elsewhere in the function.
98  // CHECK-EH:      call void @_Unwind_Resume_or_Rethrow
99  // CHECK-EH-NEXT: unreachable
100
101  // %terminate.lpad: terminate landing pad.
102  // CHECK-EH:      call i8* @llvm.eh.exception()
103  // CHECK-EH-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector
104  // CHECK-EH-NEXT: call void @_ZSt9terminatev()
105  // CHECK-EH-NEXT: unreachable
106
107}
108
109X test3(bool B) {
110  // FIXME: We don't manage to apply NRVO here, although we could.
111  {
112    X y;
113    return y;
114  }
115  X x;
116  return x;
117}
118
119extern "C" void exit(int) throw();
120
121// CHECK: define void @_Z5test4b
122X test4(bool B) {
123  {
124    // CHECK: tail call void @_ZN1XC1Ev
125    X x;
126    // CHECK: br i1
127    if (B)
128      return x;
129  }
130  // CHECK: tail call void @_ZN1XD1Ev
131  // CHECK: tail call void @exit(i32 1)
132  exit(1);
133}
134
135// CHECK-EH: define void @_Z5test5
136void may_throw();
137X test5() {
138  try {
139    may_throw();
140  } catch (X x) {
141    // CHECK-EH: invoke void @_ZN1XC1ERKS_
142    // CHECK-EH: call void @__cxa_end_catch()
143    // CHECK-EH: ret void
144    return x;
145  }
146}
147