74 lines · cpp
1// dynamic_cast2// Ensure that dynamic casting works normally3 4// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O3 -o - -emit-llvm | FileCheck %s5 6// CHECK: define{{.*}} ptr @_Z6upcastP1B(ptr noundef readnone returned captures(ret: address, provenance) %b) local_unnamed_addr7// CHECK-NEXT: entry:8// CHECK-NEXT: ret ptr %b9// CHECK-NEXT: }10 11// CHECK: define{{.*}} ptr @_Z8downcastP1A(ptr noundef readonly %a) local_unnamed_addr12// CHECK-NEXT: entry:13// CHECK-NEXT: [[isnull:%[0-9]+]] = icmp eq ptr %a, null14// CHECK-NEXT: br i1 [[isnull]], label %[[dynamic_cast_end:[a-z0-9._]+]], label %[[dynamic_cast_notnull:[a-z0-9._]+]]15// CHECK: [[dynamic_cast_notnull]]:16// CHECK-NEXT: [[as_b:%[0-9]+]] = tail call ptr @__dynamic_cast(ptr nonnull %a, ptr nonnull @_ZTI1A, ptr nonnull @_ZTI1B, i64 0)17// CHECK-NEXT: br label %[[dynamic_cast_end]]18// CHECK: [[dynamic_cast_end]]:19// CHECK-NEXT: [[res:%[0-9]+]] = phi ptr [ [[as_b]], %[[dynamic_cast_notnull]] ], [ null, %entry ]20// CHECK-NEXT: ret ptr [[res]]21// CHECK-NEXT: }22 23// CHECK: declare ptr @__dynamic_cast(ptr, ptr, ptr, i64) local_unnamed_addr24 25// CHECK: define{{.*}} ptr @_Z8selfcastP1B(ptr noundef readnone returned captures(ret: address, provenance) %b) local_unnamed_addr26// CHECK-NEXT: entry27// CHECK-NEXT: ret ptr %b28// CHECK-NEXT: }29 30// CHECK: define{{.*}} ptr @_Z9void_castP1B(ptr noundef readonly captures(address_is_null, ret: address, provenance) %b) local_unnamed_addr31// CHECK-NEXT: entry:32// CHECK-NEXT: [[isnull:%[0-9]+]] = icmp eq ptr %b, null33// CHECK-NEXT: br i1 [[isnull]], label %[[dynamic_cast_end:[a-z0-9._]+]], label %[[dynamic_cast_notnull:[a-z0-9._]+]]34// CHECK: [[dynamic_cast_notnull]]:35// CHECK-DAG: [[vtable:%[a-z0-9]+]] = load ptr, ptr %b, align 836// CHECK-DAG: [[offset_ptr:%.+]] = getelementptr inbounds i8, ptr [[vtable]], i64 -837// CHECK-DAG: [[offset_to_top:%.+]] = load i32, ptr [[offset_ptr]], align 438// CHECK-DAG: [[offset_to_top2:%.+]] = sext i32 [[offset_to_top]] to i6439// CHECK-DAG: [[casted:%.+]] = getelementptr inbounds i8, ptr %b, i64 [[offset_to_top2]]40// CHECK-NEXT: br label %[[dynamic_cast_end]]41// CHECK: [[dynamic_cast_end]]:42// CHECK-NEXT: [[res:%[0-9]+]] = phi ptr [ [[casted]], %[[dynamic_cast_notnull]] ], [ null, %entry ]43// CHECK-NEXT: ret ptr [[res]]44// CHECK-NEXT: }45 46class A {47public:48 virtual void foo();49};50 51class B : public A {52public:53 void foo() override;54};55 56void A::foo() {}57void B::foo() {}58 59A *upcast(B *b) {60 return dynamic_cast<A *>(b);61}62 63B *downcast(A *a) {64 return dynamic_cast<B *>(a);65}66 67B *selfcast(B *b) {68 return dynamic_cast<B *>(b);69}70 71void *void_cast(B *b) {72 return dynamic_cast<void *>(b);73}74