forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			104 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
| // 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
 | |
| }
 |