1 // RUN: %clang_cc1 -emit-llvm -O2 -optzns -o - -triple=i386-pc-win32 2>/dev/null %s | FileCheck %s 2 // REQUIRES: asserts 3 4 struct S { char a; }; 5 struct V { virtual void f(){} }; 6 struct A : virtual V {}; 7 struct B : S, virtual V {}; 8 struct T {}; 9 10 T* test0() { return dynamic_cast<T*>((B*)0); } 11 // CHECK: define noalias %struct.T* @"\01?test0@@YAPAUT@@XZ"() #0 { 12 // CHECK-NEXT: entry: 13 // CHECK-NEXT: ret %struct.T* null 14 // CHECK-NEXT: } 15 16 T* test1(V* x) { return &dynamic_cast<T&>(*x); } 17 // CHECK: define %struct.T* @"\01?test1@@YAPAUT@@PAUV@@@Z"(%struct.V* %x) #1 { 18 // CHECK-NEXT: entry: 19 // CHECK-NEXT: %0 = bitcast %struct.V* %x to i8* 20 // CHECK-NEXT: %1 = tail call i8* @__RTDynamicCast(i8* %0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32 1) #2 21 // CHECK-NEXT: %2 = bitcast i8* %1 to %struct.T* 22 // CHECK-NEXT: ret %struct.T* %2 23 // CHECK-NEXT: } 24 25 T* test2(A* x) { return &dynamic_cast<T&>(*x); } 26 // CHECK: define %struct.T* @"\01?test2@@YAPAUT@@PAUA@@@Z"(%struct.A* %x) #1 { 27 // CHECK-NEXT: entry: 28 // CHECK-NEXT: %0 = bitcast %struct.A* %x to i8* 29 // CHECK-NEXT: %1 = bitcast %struct.A* %x to i8** 30 // CHECK-NEXT: %vbtable = load i8** %1, align 4 31 // CHECK-NEXT: %2 = getelementptr inbounds i8* %vbtable, i32 4 32 // CHECK-NEXT: %3 = bitcast i8* %2 to i32* 33 // CHECK-NEXT: %vbase_offs = load i32* %3, align 4 34 // CHECK-NEXT: %4 = getelementptr inbounds i8* %0, i32 %vbase_offs 35 // CHECK-NEXT: %5 = tail call i8* @__RTDynamicCast(i8* %4, i32 %vbase_offs, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32 1) #2 36 // CHECK-NEXT: %6 = bitcast i8* %5 to %struct.T* 37 // CHECK-NEXT: ret %struct.T* %6 38 // CHECK-NEXT: } 39 40 T* test3(B* x) { return &dynamic_cast<T&>(*x); } 41 // CHECK: define %struct.T* @"\01?test3@@YAPAUT@@PAUB@@@Z"(%struct.B* %x) #1 { 42 // CHECK-NEXT: entry: 43 // CHECK-NEXT: %0 = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 44 // CHECK-NEXT: %vbptr = getelementptr inbounds i8* %0, i32 4 45 // CHECK-NEXT: %1 = bitcast i8* %vbptr to i8** 46 // CHECK-NEXT: %vbtable = load i8** %1, align 4 47 // CHECK-NEXT: %2 = getelementptr inbounds i8* %vbtable, i32 4 48 // CHECK-NEXT: %3 = bitcast i8* %2 to i32* 49 // CHECK-NEXT: %vbase_offs = load i32* %3, align 4 50 // CHECK-NEXT: %4 = add nsw i32 %vbase_offs, 4 51 // CHECK-NEXT: %5 = getelementptr inbounds i8* %0, i32 %4 52 // CHECK-NEXT: %6 = tail call i8* @__RTDynamicCast(i8* %5, i32 %4, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32 1) #2 53 // CHECK-NEXT: %7 = bitcast i8* %6 to %struct.T* 54 // CHECK-NEXT: ret %struct.T* %7 55 // CHECK-NEXT: } 56 57 T* test4(V* x) { return dynamic_cast<T*>(x); } 58 // CHECK: define %struct.T* @"\01?test4@@YAPAUT@@PAUV@@@Z"(%struct.V* %x) #1 { 59 // CHECK-NEXT: entry: 60 // CHECK-NEXT: %0 = bitcast %struct.V* %x to i8* 61 // CHECK-NEXT: %1 = tail call i8* @__RTDynamicCast(i8* %0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUV@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32 0) #2 62 // CHECK-NEXT: %2 = bitcast i8* %1 to %struct.T* 63 // CHECK-NEXT: ret %struct.T* %2 64 // CHECK-NEXT: } 65 66 T* test5(A* x) { return dynamic_cast<T*>(x); } 67 // CHECK: define %struct.T* @"\01?test5@@YAPAUT@@PAUA@@@Z"(%struct.A* %x) #1 { 68 // CHECK-NEXT: entry: 69 // CHECK-NEXT: %0 = icmp eq %struct.A* %x, null 70 // CHECK-NEXT: br i1 %0, label %dynamic_cast.call, label %dynamic_cast.valid 71 // CHECK: dynamic_cast.valid: ; preds = %entry 72 // CHECK-NEXT: %1 = bitcast %struct.A* %x to i8* 73 // CHECK-NEXT: %2 = bitcast %struct.A* %x to i8** 74 // CHECK-NEXT: %vbtable = load i8** %2, align 4 75 // CHECK-NEXT: %3 = getelementptr inbounds i8* %vbtable, i32 4 76 // CHECK-NEXT: %4 = bitcast i8* %3 to i32* 77 // CHECK-NEXT: %vbase_offs = load i32* %4, align 4 78 // CHECK-NEXT: %5 = getelementptr inbounds i8* %1, i32 %vbase_offs 79 // CHECK-NEXT: %6 = tail call i8* @__RTDynamicCast(i8* %5, i32 %vbase_offs, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32 0) #2 80 // CHECK-NEXT: %phitmp = bitcast i8* %6 to %struct.T* 81 // CHECK-NEXT: br label %dynamic_cast.call 82 // CHECK: dynamic_cast.call: ; preds = %dynamic_cast.valid, %entry 83 // CHECK-NEXT: %7 = phi %struct.T* [ %phitmp, %dynamic_cast.valid ], [ null, %entry ] 84 // CHECK-NEXT: ret %struct.T* %7 85 // CHECK-NEXT: } 86 87 T* test6(B* x) { return dynamic_cast<T*>(x); } 88 // CHECK: define %struct.T* @"\01?test6@@YAPAUT@@PAUB@@@Z"(%struct.B* %x) #1 { 89 // CHECK-NEXT: entry: 90 // CHECK-NEXT: %0 = icmp eq %struct.B* %x, null 91 // CHECK-NEXT: br i1 %0, label %dynamic_cast.call, label %dynamic_cast.valid 92 // CHECK: dynamic_cast.valid: ; preds = %entry 93 // CHECK-NEXT: %1 = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 94 // CHECK-NEXT: %vbptr = getelementptr inbounds i8* %1, i32 4 95 // CHECK-NEXT: %2 = bitcast i8* %vbptr to i8** 96 // CHECK-NEXT: %vbtable = load i8** %2, align 4 97 // CHECK-NEXT: %3 = getelementptr inbounds i8* %vbtable, i32 4 98 // CHECK-NEXT: %4 = bitcast i8* %3 to i32* 99 // CHECK-NEXT: %vbase_offs = load i32* %4, align 4 100 // CHECK-NEXT: %5 = add nsw i32 %vbase_offs, 4 101 // CHECK-NEXT: %6 = getelementptr inbounds i8* %1, i32 %5 102 // CHECK-NEXT: %7 = tail call i8* @__RTDynamicCast(i8* %6, i32 %5, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32 0) #2 103 // CHECK-NEXT: %phitmp = bitcast i8* %7 to %struct.T* 104 // CHECK-NEXT: br label %dynamic_cast.call 105 // CHECK: dynamic_cast.call: ; preds = %dynamic_cast.valid, %entry 106 // CHECK-NEXT: %8 = phi %struct.T* [ %phitmp, %dynamic_cast.valid ], [ null, %entry ] 107 // CHECK-NEXT: ret %struct.T* %8 108 // CHECK-NEXT: } 109 110 void* test7(V* x) { return dynamic_cast<void*>(x); } 111 // CHECK: define i8* @"\01?test7@@YAPAXPAUV@@@Z"(%struct.V* %x) #1 { 112 // CHECK-NEXT: entry: 113 // CHECK-NEXT: %0 = bitcast %struct.V* %x to i8* 114 // CHECK-NEXT: %1 = tail call i8* @__RTCastToVoid(i8* %0) #2 115 // CHECK-NEXT: ret i8* %1 116 // CHECK-NEXT: } 117 118 void* test8(A* x) { return dynamic_cast<void*>(x); } 119 // CHECK: define i8* @"\01?test8@@YAPAXPAUA@@@Z"(%struct.A* %x) #1 { 120 // CHECK-NEXT: entry: 121 // CHECK-NEXT: %0 = icmp eq %struct.A* %x, null 122 // CHECK-NEXT: br i1 %0, label %dynamic_cast.call, label %dynamic_cast.valid 123 // CHECK: dynamic_cast.valid: ; preds = %entry 124 // CHECK-NEXT: %1 = bitcast %struct.A* %x to i8* 125 // CHECK-NEXT: %2 = bitcast %struct.A* %x to i8** 126 // CHECK-NEXT: %vbtable = load i8** %2, align 4 127 // CHECK-NEXT: %3 = getelementptr inbounds i8* %vbtable, i32 4 128 // CHECK-NEXT: %4 = bitcast i8* %3 to i32* 129 // CHECK-NEXT: %vbase_offs = load i32* %4, align 4 130 // CHECK-NEXT: %5 = getelementptr inbounds i8* %1, i32 %vbase_offs 131 // CHECK-NEXT: %6 = tail call i8* @__RTCastToVoid(i8* %5) #2 132 // CHECK-NEXT: br label %dynamic_cast.call 133 // CHECK: dynamic_cast.call: ; preds = %dynamic_cast.valid, %entry 134 // CHECK-NEXT: %7 = phi i8* [ %6, %dynamic_cast.valid ], [ null, %entry ] 135 // CHECK-NEXT: ret i8* %7 136 // CHECK-NEXT: } 137 138 void* test9(B* x) { return dynamic_cast<void*>(x); } 139 // CHECK: define i8* @"\01?test9@@YAPAXPAUB@@@Z"(%struct.B* %x) #1 { 140 // CHECK-NEXT: entry: 141 // CHECK-NEXT: %0 = icmp eq %struct.B* %x, null 142 // CHECK-NEXT: br i1 %0, label %dynamic_cast.call, label %dynamic_cast.valid 143 // CHECK: dynamic_cast.valid: ; preds = %entry 144 // CHECK-NEXT: %1 = getelementptr inbounds %struct.B* %x, i32 0, i32 0, i32 0 145 // CHECK-NEXT: %vbptr = getelementptr inbounds i8* %1, i32 4 146 // CHECK-NEXT: %2 = bitcast i8* %vbptr to i8** 147 // CHECK-NEXT: %vbtable = load i8** %2, align 4 148 // CHECK-NEXT: %3 = getelementptr inbounds i8* %vbtable, i32 4 149 // CHECK-NEXT: %4 = bitcast i8* %3 to i32* 150 // CHECK-NEXT: %vbase_offs = load i32* %4, align 4 151 // CHECK-NEXT: %5 = add nsw i32 %vbase_offs, 4 152 // CHECK-NEXT: %6 = getelementptr inbounds i8* %1, i32 %5 153 // CHECK-NEXT: %7 = tail call i8* @__RTCastToVoid(i8* %6) #2 154 // CHECK-NEXT: br label %dynamic_cast.call 155 // CHECK: dynamic_cast.call: ; preds = %dynamic_cast.valid, %entry 156 // CHECK-NEXT: %8 = phi i8* [ %7, %dynamic_cast.valid ], [ null, %entry ] 157 // CHECK-NEXT: ret i8* %8 158 // CHECK-NEXT: } 159