1// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s 2 3struct A { 4 A(); 5 ~A(); 6 int a; 7}; 8 9A getA(); 10 11int TakesTwo(A a, A b); 12void HasEHCleanup() { 13 TakesTwo(getA(), getA()); 14} 15 16// With exceptions, we need to clean up at least one of these temporaries. 17// WIN32-LABEL: define void @"\01?HasEHCleanup@@YAXXZ"() {{.*}} { 18// WIN32: %[[base:.*]] = call i8* @llvm.stacksave() 19// If this call throws, we have to restore the stack. 20// WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) 21// If this call throws, we have to cleanup the first temporary. 22// WIN32: invoke void @"\01?getA@@YA?AUA@@XZ"(%struct.A* sret %{{.*}}) 23// If this call throws, we have to cleanup the stacksave. 24// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" 25// WIN32: call void @llvm.stackrestore(i8* %[[base]]) 26// WIN32: ret void 27// 28// There should be one dtor call for unwinding from the second getA. 29// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" 30// WIN32-NOT: @"\01??1A@@QAE@XZ" 31// WIN32: call void @llvm.stackrestore 32// WIN32: } 33 34void TakeRef(const A &a); 35int HasDeactivatedCleanups() { 36 return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())); 37} 38 39// WIN32-LABEL: define i32 @"\01?HasDeactivatedCleanups@@YAHXZ"() {{.*}} { 40// WIN32: %[[isactive:.*]] = alloca i1 41// WIN32: call i8* @llvm.stacksave() 42// WIN32: %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]] 43// WIN32: %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1 44// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 45// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" 46// 47// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %[[arg1]]) 48// WIN32: store i1 true, i1* %[[isactive]] 49// 50// WIN32: %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0 51// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 52// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" 53// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 54// WIN32: store i1 false, i1* %[[isactive]] 55// 56// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z"([[argmem_ty]]* inalloca %[[argmem]]) 57// WIN32: call void @llvm.stackrestore 58// Destroy the two const ref temporaries. 59// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" 60// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" 61// WIN32: ret i32 62// 63// Conditionally destroy arg1. 64// WIN32: %[[cond:.*]] = load i1* %[[isactive]] 65// WIN32: br i1 %[[cond]] 66// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %[[arg1]]) 67// WIN32: } 68 69// Test putting the cleanups inside a conditional. 70int CouldThrow(); 71int HasConditionalCleanup(bool cond) { 72 return (cond ? TakesTwo(A(), A()) : CouldThrow()); 73} 74 75// WIN32-LABEL: define i32 @"\01?HasConditionalCleanup@@YAH_N@Z"(i1 zeroext %{{.*}}) {{.*}} { 76// WIN32: store i1 false 77// WIN32: br i1 78// WIN32: call i8* @llvm.stacksave() 79// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}}) 80// WIN32: store i1 true 81// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %{{.*}}) 82// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" 83// WIN32: call void @llvm.stackrestore 84// 85// WIN32: call i32 @"\01?CouldThrow@@YAHXZ"() 86// 87// Only one dtor in the invoke for arg1 88// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ"({{.*}}) 89// WIN32-NOT: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" 90// WIN32: call void @llvm.stackrestore 91// WIN32: } 92 93// Now test both. 94int HasConditionalDeactivatedCleanups(bool cond) { 95 return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow()); 96} 97 98// WIN32-LABEL: define i32 @"\01?HasConditionalDeactivatedCleanups@@YAH_N@Z"{{.*}} { 99// WIN32: alloca i1 100// WIN32: %[[arg1_cond:.*]] = alloca i1 101// Start all four cleanups as deactivated. 102// WIN32: store i1 false 103// WIN32: store i1 false 104// WIN32: store i1 false 105// WIN32: store i1 false 106// WIN32: br i1 107// True condition. 108// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 109// WIN32: store i1 true 110// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" 111// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 112// WIN32: store i1 true, i1* %[[arg1_cond]] 113// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 114// WIN32: store i1 true 115// WIN32: invoke void @"\01?TakeRef@@YAXABUA@@@Z" 116// WIN32: invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ" 117// WIN32: store i1 true 118// WIN32: store i1 false, i1* %[[arg1_cond]] 119// WIN32: invoke i32 @"\01?TakesTwo@@YAHUA@@0@Z" 120// False condition. 121// WIN32: invoke i32 @"\01?CouldThrow@@YAHXZ"() 122// Two normal cleanups for TakeRef args. 123// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" 124// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" 125// WIN32: ret i32 126// 127// Somewhere in the landing pad soup, we conditionally destroy arg1. 128// WIN32: %[[isactive:.*]] = load i1* %[[arg1_cond]] 129// WIN32: br i1 %[[isactive]] 130// WIN32: invoke x86_thiscallcc void @"\01??1A@@QAE@XZ" 131// WIN32: } 132 133namespace crash_on_partial_destroy { 134struct A { 135 virtual ~A(); 136}; 137 138struct B : virtual A { 139 // Has an implicit destructor. 140}; 141 142struct C : B { 143 C(); 144}; 145 146void foo(); 147// We used to crash when emitting this. 148C::C() { foo(); } 149 150// Verify that we don't bother with a vbtable lookup when adjusting the this 151// pointer to call a base destructor from a constructor while unwinding. 152// WIN32-LABEL: define {{.*}} @"\01??0C@crash_on_partial_destroy@@QAE@XZ"{{.*}} { 153// WIN32: landingpad 154// 155// We shouldn't do any vbptr loads, just constant GEPs. 156// WIN32-NOT: load 157// WIN32: getelementptr i8* %{{.*}}, i32 4 158// WIN32-NOT: load 159// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"* 160// WIN32: invoke x86_thiscallcc void @"\01??1B@crash_on_partial_destroy@@UAE@XZ" 161// 162// WIN32-NOT: load 163// WIN32: bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8* 164// WIN32-NOT: load 165// WIN32: getelementptr inbounds i8* %{{.*}}, i64 4 166// WIN32-NOT: load 167// WIN32: bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"* 168// WIN32: invoke x86_thiscallcc void @"\01??1A@crash_on_partial_destroy@@UAE@XZ" 169// WIN32: } 170} 171