1 // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -Wno-error=return-type -o - %s | FileCheck --check-prefixes=CHECK,CHECK-COMMON %s 2 // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -std=c++11 -Wno-error=return-type -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 -Wno-error=return-type -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 -Wno-error=return-type -O -o - %s | FileCheck %s --check-prefixes=CHECK-NOSTRICT-OPT,CHECK-COMMON 6 7 // CHECK-COMMON-LABEL: @_Z9no_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 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 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 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 69 NonTrivialDefaultConstructor() { } 70 }; 71 72 // CHECK-NOSTRICT-LABEL: @_Z28nonTrivialDefaultConstructorv 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 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 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