• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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();
fY14   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
test0()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(
test1(bool B)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
test2(bool B)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
test3(bool B)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
test4(bool B)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();
test5()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
test6()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
test7(bool b)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
test8(bool b)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 
test9()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