128 lines · cpp
1// RUN: %clang_cc1 -I%S %s -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -std=c++11 -o - -O1 -disable-llvm-passes | FileCheck %s --implicit-check-not='call {{.*}} @__dynamic_cast'2struct Offset { virtual ~Offset(); };3struct A { virtual ~A(); };4struct B final : Offset, A { };5 6struct C { virtual ~C(); int c; };7struct D : A { int d; };8struct E : A { int e; };9struct F : virtual A { int f; };10struct G : virtual A { int g; };11struct H final : C, D, E, F, G { int h; };12struct H1 final: C, private D { int h1; };13 14// CHECK-LABEL: @_Z7inexactP1A15C *inexact(A *a) {16 // CHECK: call {{.*}} @__dynamic_cast17 return dynamic_cast<C*>(a);18}19 20// CHECK-LABEL: @_Z12exact_singleP1A21B *exact_single(A *a) {22 // CHECK: %[[PTR_NULL:.*]] = icmp eq ptr %[[PTR:.*]], null23 // CHECK: br i1 %[[PTR_NULL]], label %[[LABEL_FAILED:.*]], label %[[LABEL_NOTNULL:.*]]24 25 // CHECK: [[LABEL_NOTNULL]]:26 // CHECK: %[[VPTR:.*]] = load ptr, ptr %[[PTR]]27 // CHECK: %[[MATCH:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr @_ZTV1B, i32 0, i32 1, i32 2)28 // CHECK: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[PTR]], i64 -829 // CHECK: br i1 %[[MATCH]], label %[[LABEL_END:.*]], label %[[LABEL_FAILED]]30 31 // CHECK: [[LABEL_FAILED]]:32 // CHECK: br label %[[LABEL_END]]33 34 // CHECK: [[LABEL_END]]:35 // CHECK: phi ptr [ %[[RESULT]], %[[LABEL_NOTNULL]] ], [ null, %[[LABEL_FAILED]] ]36 return dynamic_cast<B*>(a);37}38 39// CHECK-LABEL: @_Z9exact_refR1A40B &exact_ref(A &a) {41 // CHECK: %[[PTR_NULL:.*]] = icmp eq ptr %[[PTR:.*]], null42 // CHECK: br i1 %[[PTR_NULL]], label %[[LABEL_FAILED:.*]], label %[[LABEL_NOTNULL:.*]]43 44 // CHECK: [[LABEL_NOTNULL]]:45 // CHECK: %[[VPTR:.*]] = load ptr, ptr %[[PTR]]46 // CHECK: %[[MATCH:.*]] = icmp eq ptr %[[VPTR]], getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [4 x ptr] }, ptr @_ZTV1B, i32 0, i32 1, i32 2)47 // CHECK: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[PTR]], i64 -848 // CHECK: br i1 %[[MATCH]], label %[[LABEL_END:.*]], label %[[LABEL_FAILED]]49 50 // CHECK: [[LABEL_FAILED]]:51 // CHECK: call {{.*}} @__cxa_bad_cast52 // CHECK: unreachable53 54 // CHECK: [[LABEL_END]]:55 // CHECK: ret ptr %[[RESULT]]56 return dynamic_cast<B&>(a);57}58 59// CHECK-LABEL: @_Z11exact_multiP1A60H *exact_multi(A *a) {61 // CHECK: %[[PTR_NULL:.*]] = icmp eq ptr %[[PTR:.*]], null62 // CHECK: br i1 %[[PTR_NULL]], label %[[LABEL_FAILED:.*]], label %[[LABEL_NOTNULL:.*]]63 64 // CHECK: [[LABEL_NOTNULL]]:65 // CHECK: %[[VPTR:.*]] = load ptr, ptr %[[PTR]]66 // CHECK: %[[OFFSET_TO_TOP_SLOT:.*]] = getelementptr inbounds i64, ptr %[[VPTR]], i64 -267 // CHECK: %[[OFFSET_TO_TOP:.*]] = load i64, ptr %[[OFFSET_TO_TOP_SLOT]]68 // CHECK: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[PTR]], i64 %[[OFFSET_TO_TOP]]69 // CHECK: %[[DERIVED_VPTR:.*]] = load ptr, ptr %[[RESULT]]70 // CHECK: %[[MATCH:.*]] = icmp eq ptr %[[DERIVED_VPTR]], getelementptr inbounds inrange(-24, 16) ({ [5 x ptr], [4 x ptr], [4 x ptr], [6 x ptr], [6 x ptr] }, ptr @_ZTV1H, i32 0, i32 0, i32 3)71 // CHECK: br i1 %[[MATCH]], label %[[LABEL_END:.*]], label %[[LABEL_FAILED]]72 73 // CHECK: [[LABEL_FAILED]]:74 // CHECK: br label %[[LABEL_END]]75 76 // CHECK: [[LABEL_END]]:77 // CHECK: phi ptr [ %[[RESULT]], %[[LABEL_NOTNULL]] ], [ null, %[[LABEL_FAILED]] ]78 return dynamic_cast<H*>(a);79}80 81// CHECK-LABEL: @_Z19exact_invalid_multiP1D82H1 *exact_invalid_multi(D* d) {83 // CHECK: entry:84 // CHECK-NEXT: %d.addr = alloca ptr85 // CHECK-NEXT: store ptr %d, ptr %d.addr86 // CHECK-NEXT: load ptr, ptr %d.addr87 // CHECK-NEXT: ret ptr null88 return dynamic_cast<H1*>(d);89}90 91// CHECK-LABEL: @_Z19exact_invalid_multiR1D92H1 &exact_invalid_multi(D& d) {93 // CHECK: entry:94 // CHECK-NEXT: %d.addr = alloca ptr95 // CHECK-NEXT: store ptr %d, ptr %d.addr96 // CHECK-NEXT: load ptr, ptr %d.addr97 // CHECK-NEXT: call void @__cxa_bad_cast()98 // CHECK-NEXT: unreachable99 // CHECK: dynamic_cast.unreachable:100 // CHECK-NEXT: ret ptr poison101 return dynamic_cast<H1&>(d);102}103 104namespace GH137518 {105 class base { virtual void fn() = 0; };106 class test final : base { virtual void fn() { } };107 test* new_test() { return new test(); }108 109 // CHECK-LABEL: @_ZN8GH1375184castEPNS_4baseE(110 test* cast(base* b) {111 // CHECK: entry:112 // CHECK-NEXT: %b.addr = alloca ptr113 // CHECK-NEXT: store ptr %b, ptr %b.addr114 // CHECK-NEXT: load ptr, ptr %b.addr115 // CHECK-NEXT: ret ptr null116 return dynamic_cast<test*>(b);117 }118}119 120namespace GH64088 {121 // Ensure we mark the B vtable as used here, because we're going to emit a122 // reference to it.123 // CHECK: define {{.*}} void @_ZN7GH640881BD0Ev(124 struct A { virtual ~A(); };125 struct B final : A { virtual ~B() = default; };126 B *cast(A *p) { return dynamic_cast<B*>(p); }127}128