forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			149 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %clang_cc1 -emit-llvm -O1 -o - %s | FileCheck %s
 | |
| // RUN: %clang_cc1 -emit-llvm -O1 -fcxx-exceptions -fexceptions -o - %s | FileCheck --check-prefix=CHECK-EH %s
 | |
| 
 | |
| // Test code generation for the named return value optimization.
 | |
| class X {
 | |
| public:
 | |
|   X();
 | |
|   X(const X&);
 | |
|   ~X();
 | |
| };
 | |
| 
 | |
| // CHECK: define void @_Z5test0v
 | |
| // CHECK-EH: define void @_Z5test0v
 | |
| X test0() {
 | |
|   X x;
 | |
|   // CHECK:          call void @_ZN1XC1Ev
 | |
|   // CHECK-NEXT:     ret void
 | |
| 
 | |
|   // CHECK-EH:       call void @_ZN1XC1Ev
 | |
|   // CHECK-EH-NEXT:  ret void
 | |
|   return x;
 | |
| }
 | |
| 
 | |
| // CHECK: define void @_Z5test1b(
 | |
| // CHECK-EH: define void @_Z5test1b(
 | |
| X test1(bool B) {
 | |
|   // CHECK:      tail call void @_ZN1XC1Ev
 | |
|   // CHECK-NEXT: ret void
 | |
|   X x;
 | |
|   if (B)
 | |
|     return (x);
 | |
|   return x;
 | |
|   // CHECK-EH:      tail call void @_ZN1XC1Ev
 | |
|   // CHECK-EH-NEXT: ret void
 | |
| }
 | |
| 
 | |
| // CHECK: define void @_Z5test2b
 | |
| // CHECK-EH: define void @_Z5test2b
 | |
| X test2(bool B) {
 | |
|   // No NRVO.
 | |
| 
 | |
|   X x;
 | |
|   X y;
 | |
|   if (B)
 | |
|     return y;
 | |
|   return x;
 | |
| 
 | |
|   // CHECK: call void @_ZN1XC1Ev
 | |
|   // CHECK-NEXT: call void @_ZN1XC1Ev
 | |
|   // CHECK: call void @_ZN1XC1ERKS_
 | |
|   // CHECK: call void @_ZN1XC1ERKS_
 | |
|   // CHECK: call void @_ZN1XD1Ev
 | |
|   // CHECK: call void @_ZN1XD1Ev
 | |
|   // CHECK: ret void
 | |
| 
 | |
|   // The block ordering in the -fexceptions IR is unfortunate.
 | |
| 
 | |
|   // CHECK-EH:      call void @_ZN1XC1Ev
 | |
|   // CHECK-EH-NEXT: invoke void @_ZN1XC1Ev
 | |
|   // -> %invoke.cont, %lpad
 | |
| 
 | |
|   // %invoke.cont:
 | |
|   // CHECK-EH:      br i1
 | |
|   // -> %if.then, %if.end
 | |
| 
 | |
|   // %if.then: returning 'x'
 | |
|   // CHECK-EH:      invoke void @_ZN1XC1ERKS_
 | |
|   // -> %cleanup, %lpad1
 | |
| 
 | |
|   // %lpad: landing pad for ctor of 'y', dtor of 'y'
 | |
|   // CHECK-EH:      call i8* @llvm.eh.exception()
 | |
|   // CHECK-EH: call i32 (i8*, i8*, ...)* @llvm.eh.selector
 | |
|   // CHECK-EH-NEXT: br label
 | |
|   // -> %eh.cleanup
 | |
| 
 | |
|   // %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
 | |
|   // CHECK-EH: invoke void @_ZN1XD1Ev
 | |
|   // -> %eh.cleanup, %terminate.lpad
 | |
| 
 | |
|   // %if.end: returning 'y'
 | |
|   // CHECK-EH: invoke void @_ZN1XC1ERKS_
 | |
|   // -> %cleanup, %lpad1
 | |
| 
 | |
|   // %cleanup: normal cleanup for 'y'
 | |
|   // CHECK-EH: invoke void @_ZN1XD1Ev
 | |
|   // -> %invoke.cont11, %lpad
 | |
| 
 | |
|   // %invoke.cont11: normal cleanup for 'x'
 | |
|   // CHECK-EH:      call void @_ZN1XD1Ev
 | |
|   // CHECK-EH-NEXT: ret void
 | |
| 
 | |
|   // %eh.cleanup:  EH cleanup for 'x'
 | |
|   // CHECK-EH: invoke void @_ZN1XD1Ev
 | |
|   // -> %invoke.cont17, %terminate.lpad
 | |
| 
 | |
|   // %invoke.cont17: rethrow block for %eh.cleanup.
 | |
|   // This really should be elsewhere in the function.
 | |
|   // CHECK-EH:      call void @_Unwind_Resume_or_Rethrow
 | |
|   // CHECK-EH-NEXT: unreachable
 | |
| 
 | |
|   // %terminate.lpad: terminate landing pad.
 | |
|   // CHECK-EH:      call i8* @llvm.eh.exception()
 | |
|   // CHECK-EH-NEXT: call i32 (i8*, i8*, ...)* @llvm.eh.selector
 | |
|   // CHECK-EH-NEXT: call void @_ZSt9terminatev()
 | |
|   // CHECK-EH-NEXT: unreachable
 | |
| 
 | |
| }
 | |
| 
 | |
| X test3(bool B) {
 | |
|   // FIXME: We don't manage to apply NRVO here, although we could.
 | |
|   {
 | |
|     X y;
 | |
|     return y;
 | |
|   }
 | |
|   X x;
 | |
|   return x;
 | |
| }
 | |
| 
 | |
| extern "C" void exit(int) throw();
 | |
| 
 | |
| // CHECK: define void @_Z5test4b
 | |
| X test4(bool B) {
 | |
|   {
 | |
|     // CHECK: tail call void @_ZN1XC1Ev
 | |
|     X x;
 | |
|     // CHECK: br i1
 | |
|     if (B)
 | |
|       return x;
 | |
|   }
 | |
|   // CHECK: tail call void @_ZN1XD1Ev
 | |
|   // CHECK: tail call void @exit(i32 1)
 | |
|   exit(1);
 | |
| }
 | |
| 
 | |
| #ifdef __EXCEPTIONS
 | |
| // CHECK-EH: define void @_Z5test5
 | |
| void may_throw();
 | |
| X test5() {
 | |
|   try {
 | |
|     may_throw();
 | |
|   } catch (X x) {
 | |
|     // CHECK-EH: invoke void @_ZN1XC1ERKS_
 | |
|     // CHECK-EH: call void @__cxa_end_catch()
 | |
|     // CHECK-EH: ret void
 | |
|     return x;
 | |
|   }
 | |
| }
 | |
| #endif
 |