aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenCXX/return.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenCXX/return.cpp')
-rw-r--r--test/CodeGenCXX/return.cpp99
1 files changed, 95 insertions, 4 deletions
diff --git a/test/CodeGenCXX/return.cpp b/test/CodeGenCXX/return.cpp
index 5c1cfdaeed75..584c2921c1e7 100644
--- a/test/CodeGenCXX/return.cpp
+++ b/test/CodeGenCXX/return.cpp
@@ -1,12 +1,103 @@
-// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
-// RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -O -o - %s | FileCheck %s --check-prefix=CHECK-OPT
+// 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: @_Z9no_return
-// CHECK-OPT: @_Z9no_return
+// 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
}