104 lines · cpp
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 %s2// 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-COMMON3// 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-COMMON4// 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-COMMON5// 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-COMMON6 7// CHECK-COMMON-LABEL: @_Z9no_return8int no_return() {9 // CHECK: call void @llvm.trap10 // CHECK-NEXT: unreachable11 12 // CHECK-OPT-NOT: call void @llvm.trap13 // CHECK-OPT: unreachable14 15 // -fno-strict-return should not emit trap + unreachable but it should return16 // an undefined value instead.17 18 // CHECK-NOSTRICT: alloca19 // CHECK-NOSTRICT-NEXT: load20 // CHECK-NOSTRICT-NEXT: ret i3221 // CHECK-NOSTRICT-NEXT: }22 23 // CHECK-NOSTRICT-OPT: ret i32 undef24}25 26enum Enum {27 A, B28};29 30// CHECK-COMMON-LABEL: @_Z27returnNotViableDontOptimize4Enum31int 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-return37 // is turned on, even if all the enum cases are covered in this function.38 39 // CHECK-NOSTRICT-NOT: call void @llvm.trap40 // CHECK-NOSTRICT-NOT: unreachable41}42 43struct Trivial {44 int x;45};46 47// CHECK-NOSTRICT-LABEL: @_Z7trivialv48Trivial trivial() {49 // This function returns a trivial record so -fno-strict-return should avoid50 // the undefined behaviour optimization.51 52 // CHECK-NOSTRICT-NOT: call void @llvm.trap53 // CHECK-NOSTRICT-NOT: unreachable54}55 56struct NonTrivialCopy {57 NonTrivialCopy(const NonTrivialCopy &);58};59 60// CHECK-NOSTRICT-LABEL: @_Z14nonTrivialCopyv61NonTrivialCopy nonTrivialCopy() {62 // CHECK-NOSTRICT-NOT: call void @llvm.trap63 // CHECK-NOSTRICT-NOT: unreachable64}65 66struct NonTrivialDefaultConstructor {67 int x;68 69 NonTrivialDefaultConstructor() { }70};71 72// CHECK-NOSTRICT-LABEL: @_Z28nonTrivialDefaultConstructorv73NonTrivialDefaultConstructor nonTrivialDefaultConstructor() {74 // CHECK-NOSTRICT-NOT: call void @llvm.trap75 // CHECK-NOSTRICT-NOT: unreachable76}77 78// Functions that return records with non-trivial destructors should always use79// the -fstrict-return optimization.80 81struct NonTrivialDestructor {82 ~NonTrivialDestructor();83};84 85// CHECK-NOSTRICT-LABEL: @_Z20nonTrivialDestructorv86NonTrivialDestructor nonTrivialDestructor() {87 // CHECK-NOSTRICT: call void @llvm.trap88 // CHECK-NOSTRICT-NEXT: unreachable89}90 91// The behavior for lambdas should be identical to functions.92// CHECK-COMMON-LABEL: @_Z10lambdaTestv93void lambdaTest() {94 auto lambda1 = []() -> int {95 };96 lambda1();97 98 // CHECK: call void @llvm.trap99 // CHECK-NEXT: unreachable100 101 // CHECK-NOSTRICT-NOT: call void @llvm.trap102 // CHECK-NOSTRICT-NOT: unreachable103}104