1 // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -o - %s | FileCheck --check-prefixes=CHECK,CHECK-COMMON %s
2 // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -O -o - %s | FileCheck %s --check-prefixes=CHECK-OPT,CHECK-COMMON
3 // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -fno-strict-return -o - %s | FileCheck %s --check-prefixes=CHECK-NOSTRICT,CHECK-COMMON
4 // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -fno-strict-return -Wno-return-type -o - %s | FileCheck %s --check-prefixes=CHECK-NOSTRICT,CHECK-COMMON
5 // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -fno-strict-return -O -o - %s | FileCheck %s --check-prefixes=CHECK-NOSTRICT-OPT,CHECK-COMMON
6
7 // CHECK-COMMON-LABEL: @_Z9no_return
no_return()8 int no_return() {
9 // CHECK: call void @llvm.trap
10 // CHECK-NEXT: unreachable
11
12 // CHECK-OPT-NOT: call void @llvm.trap
13 // CHECK-OPT: unreachable
14
15 // -fno-strict-return should not emit trap + unreachable but it should return
16 // an undefined value instead.
17
18 // CHECK-NOSTRICT: alloca
19 // CHECK-NOSTRICT-NEXT: load
20 // CHECK-NOSTRICT-NEXT: ret i32
21 // CHECK-NOSTRICT-NEXT: }
22
23 // CHECK-NOSTRICT-OPT: ret i32 undef
24 }
25
26 enum Enum {
27 A, B
28 };
29
30 // CHECK-COMMON-LABEL: @_Z27returnNotViableDontOptimize4Enum
returnNotViableDontOptimize(Enum e)31 int returnNotViableDontOptimize(Enum e) {
32 switch (e) {
33 case A: return 1;
34 case B: return 2;
35 }
36 // Undefined behaviour optimization shouldn't be used when -fno-strict-return
37 // is turned on, even if all the enum cases are covered in this function.
38
39 // CHECK-NOSTRICT-NOT: call void @llvm.trap
40 // CHECK-NOSTRICT-NOT: unreachable
41 }
42
43 struct Trivial {
44 int x;
45 };
46
47 // CHECK-NOSTRICT-LABEL: @_Z7trivialv
trivial()48 Trivial trivial() {
49 // This function returns a trivial record so -fno-strict-return should avoid
50 // the undefined behaviour optimization.
51
52 // CHECK-NOSTRICT-NOT: call void @llvm.trap
53 // CHECK-NOSTRICT-NOT: unreachable
54 }
55
56 struct NonTrivialCopy {
57 NonTrivialCopy(const NonTrivialCopy &);
58 };
59
60 // CHECK-NOSTRICT-LABEL: @_Z14nonTrivialCopyv
nonTrivialCopy()61 NonTrivialCopy nonTrivialCopy() {
62 // CHECK-NOSTRICT-NOT: call void @llvm.trap
63 // CHECK-NOSTRICT-NOT: unreachable
64 }
65
66 struct NonTrivialDefaultConstructor {
67 int x;
68
NonTrivialDefaultConstructorNonTrivialDefaultConstructor69 NonTrivialDefaultConstructor() { }
70 };
71
72 // CHECK-NOSTRICT-LABEL: @_Z28nonTrivialDefaultConstructorv
nonTrivialDefaultConstructor()73 NonTrivialDefaultConstructor nonTrivialDefaultConstructor() {
74 // CHECK-NOSTRICT-NOT: call void @llvm.trap
75 // CHECK-NOSTRICT-NOT: unreachable
76 }
77
78 // Functions that return records with non-trivial destructors should always use
79 // the -fstrict-return optimization.
80
81 struct NonTrivialDestructor {
82 ~NonTrivialDestructor();
83 };
84
85 // CHECK-NOSTRICT-LABEL: @_Z20nonTrivialDestructorv
nonTrivialDestructor()86 NonTrivialDestructor nonTrivialDestructor() {
87 // CHECK-NOSTRICT: call void @llvm.trap
88 // CHECK-NOSTRICT-NEXT: unreachable
89 }
90
91 // The behavior for lambdas should be identical to functions.
92 // CHECK-COMMON-LABEL: @_Z10lambdaTestv
lambdaTest()93 void lambdaTest() {
94 auto lambda1 = []() -> int {
95 };
96 lambda1();
97
98 // CHECK: call void @llvm.trap
99 // CHECK-NEXT: unreachable
100
101 // CHECK-NOSTRICT-NOT: call void @llvm.trap
102 // CHECK-NOSTRICT-NOT: unreachable
103 }
104