Clang Project

clang_source_code/test/CodeGenCXX/return.cpp
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
8int 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
26enum Enum {
27  A, B
28};
29
30// CHECK-COMMON-LABEL: @_Z27returnNotViableDontOptimize4Enum
31int 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
43struct Trivial {
44  int x;
45};
46
47// CHECK-NOSTRICT-LABEL: @_Z7trivialv
48Trivial 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
56struct NonTrivialCopy {
57  NonTrivialCopy(const NonTrivialCopy &);
58};
59
60// CHECK-NOSTRICT-LABEL: @_Z14nonTrivialCopyv
61NonTrivialCopy nonTrivialCopy() {
62  // CHECK-NOSTRICT-NOT: call void @llvm.trap
63  // CHECK-NOSTRICT-NOT: unreachable
64}
65
66struct NonTrivialDefaultConstructor {
67  int x;
68
69  NonTrivialDefaultConstructor() { }
70};
71
72// CHECK-NOSTRICT-LABEL: @_Z28nonTrivialDefaultConstructorv
73NonTrivialDefaultConstructor 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
81struct NonTrivialDestructor {
82  ~NonTrivialDestructor();
83};
84
85// CHECK-NOSTRICT-LABEL: @_Z20nonTrivialDestructorv
86NonTrivialDestructor 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
93void 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