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