48 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			48 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			C++
		
	
	
	
| // Check that destructors of memcpy-able struct members are called properly
 | |
| // during stack unwinding after an exception.
 | |
| //
 | |
| // Check that destructor's argument (address of member to be destroyed) is
 | |
| // obtained by taking offset from struct, not by bitcasting pointers.
 | |
| //
 | |
| // RUN: %clang_cc1 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -O0 -fno-elide-constructors -emit-llvm %s -o - | FileCheck %s
 | |
| 
 | |
| struct ImplicitCopy {
 | |
|   int id;
 | |
|   ImplicitCopy() { id = 10; }
 | |
|   ~ImplicitCopy() { id = 20; }
 | |
| };
 | |
| 
 | |
| struct ThrowCopy {
 | |
|   int id;
 | |
|   ThrowCopy() { id = 15; }
 | |
|   ThrowCopy(const ThrowCopy &x) {
 | |
|     id = 25;
 | |
|     throw 1;
 | |
|   }
 | |
|   ~ThrowCopy() { id = 35; }
 | |
| };
 | |
| 
 | |
| struct Container {
 | |
|   int id;
 | |
|   ImplicitCopy o1;
 | |
|   ThrowCopy o2;
 | |
| 
 | |
|   Container() { id = 1000; }
 | |
|   ~Container() { id = 2000; }
 | |
| };
 | |
| 
 | |
| int main() {
 | |
|   try {
 | |
|     Container c1;
 | |
|     // CHECK-LABEL: main
 | |
|     // CHECK: %{{.+}} = getelementptr inbounds %struct.Container, %struct.Container* %{{.+}}, i32 0, i32 1
 | |
|     // CHECK-NOT: %{{.+}} = bitcast %struct.Container* %{{.+}} to %struct.ImplicitCopy*
 | |
|     Container c2(c1);
 | |
| 
 | |
|     return 2;
 | |
|   } catch (...) {
 | |
|     return 1;
 | |
|   }
 | |
|   return 0;
 | |
| }
 |