// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
// RUN: %clang_cc1 %s -x c++ -std=c++23  -triple x86_64-apple-darwin10 -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis  -o - | FileCheck --check-prefix=CHECK-NOAUTH %s
// RUN: %clang_cc1 %s -x c++ -std=c++23  -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-type-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis   -o - | FileCheck --check-prefix=CHECK-TYPEAUTH %s
// RUN: %clang_cc1 %s -x c++ -std=c++23  -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-address-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis  -o - | FileCheck --check-prefix=CHECK-ADDRESSAUTH %s
// RUN: %clang_cc1 %s -x c++ -std=c++23  -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-type-discrimination -fptrauth-vtable-pointer-address-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis  -o - | FileCheck --check-prefix=CHECK-BOTHAUTH %s
// FIXME: Assume load should not require -fstrict-vtable-pointers

namespace test1 {
struct A {
  A();
  virtual void bar();
};

struct B : A {
  B();
  virtual void foo();
};

struct Z : A {};
struct C : Z, B {
  C();
  virtual void wibble();
};

struct D : virtual A {
};

struct E : D, B {
};

template <class A, class B> struct same_type {
  static const bool value = false;
};

template <class A> struct same_type<A, A> {
  static const bool value = true;
};

// CHECK-NOAUTH-LABEL: define ptr @_ZN5test11aEPNS_1AE(
// CHECK-NOAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-NOAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA6:![0-9]+]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9:![0-9]+]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @_ZN5test11aEPNS_1AE(
// CHECK-TYPEAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-TYPEAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA6:![0-9]+]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9:![0-9]+]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = load volatile i8, ptr [[TMP3]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP3]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @_ZN5test11aEPNS_1AE(
// CHECK-ADDRESSAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-ADDRESSAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA6:![0-9]+]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9:![0-9]+]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 [[TMP1]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP4]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @_ZN5test11aEPNS_1AE(
// CHECK-BOTHAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-BOTHAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA6:![0-9]+]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9:![0-9]+]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP1]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = load volatile i8, ptr [[TMP5]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP5]]
//
const void *a(A *o) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(o)), const void*>::value);
  return __builtin_get_vtable_pointer(o);
}

// CHECK-NOAUTH-LABEL: define ptr @_ZN5test11bEPNS_1BE(
// CHECK-NOAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-NOAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA11:![0-9]+]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @_ZN5test11bEPNS_1BE(
// CHECK-TYPEAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-TYPEAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA11:![0-9]+]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = load volatile i8, ptr [[TMP3]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP3]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @_ZN5test11bEPNS_1BE(
// CHECK-ADDRESSAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-ADDRESSAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA11:![0-9]+]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 [[TMP1]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP4]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @_ZN5test11bEPNS_1BE(
// CHECK-BOTHAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-BOTHAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA11:![0-9]+]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP1]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = load volatile i8, ptr [[TMP5]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP5]]
//
const void *b(B *o) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(o)), const void*>::value);
  return __builtin_get_vtable_pointer(o);
}

// CHECK-NOAUTH-LABEL: define ptr @_ZN5test16b_as_AEPNS_1BE(
// CHECK-NOAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-NOAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @_ZN5test16b_as_AEPNS_1BE(
// CHECK-TYPEAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-TYPEAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = load volatile i8, ptr [[TMP3]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP3]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @_ZN5test16b_as_AEPNS_1BE(
// CHECK-ADDRESSAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-ADDRESSAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 [[TMP1]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP4]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @_ZN5test16b_as_AEPNS_1BE(
// CHECK-BOTHAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-BOTHAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA11]]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP1]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = load volatile i8, ptr [[TMP5]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP5]]
//
const void *b_as_A(B *o) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(o)), const void*>::value);
  return __builtin_get_vtable_pointer((A *)o);
}

// CHECK-NOAUTH-LABEL: define ptr @_ZN5test11cEPNS_1CE(
// CHECK-NOAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-NOAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13:![0-9]+]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @_ZN5test11cEPNS_1CE(
// CHECK-TYPEAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-TYPEAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13:![0-9]+]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = load volatile i8, ptr [[TMP3]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP3]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @_ZN5test11cEPNS_1CE(
// CHECK-ADDRESSAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-ADDRESSAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13:![0-9]+]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 [[TMP1]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP4]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @_ZN5test11cEPNS_1CE(
// CHECK-BOTHAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-BOTHAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13:![0-9]+]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP1]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = load volatile i8, ptr [[TMP5]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP5]]
//
const void *c(C *o) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(o)), const void*>::value);
  return __builtin_get_vtable_pointer(o);
}

// CHECK-NOAUTH-LABEL: define ptr @_ZN5test16c_as_ZEPNS_1CE(
// CHECK-NOAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-NOAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @_ZN5test16c_as_ZEPNS_1CE(
// CHECK-TYPEAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-TYPEAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = load volatile i8, ptr [[TMP3]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP3]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @_ZN5test16c_as_ZEPNS_1CE(
// CHECK-ADDRESSAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-ADDRESSAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 [[TMP1]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP4]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @_ZN5test16c_as_ZEPNS_1CE(
// CHECK-BOTHAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-BOTHAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP1]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = load volatile i8, ptr [[TMP5]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP5]]
//
const void *c_as_Z(C *o) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(o)), const void*>::value);
  return __builtin_get_vtable_pointer((Z *)o);
}

// CHECK-NOAUTH-LABEL: define ptr @_ZN5test16c_as_BEPNS_1CE(
// CHECK-NOAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-NOAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-NOAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-NOAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-NOAUTH:       [[CAST_NOTNULL]]:
// CHECK-NOAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
// CHECK-NOAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-NOAUTH:       [[CAST_END]]:
// CHECK-NOAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @_ZN5test16c_as_BEPNS_1CE(
// CHECK-TYPEAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-TYPEAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-TYPEAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-TYPEAUTH:       [[CAST_NOTNULL]]:
// CHECK-TYPEAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
// CHECK-TYPEAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-TYPEAUTH:       [[CAST_END]]:
// CHECK-TYPEAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP4]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @_ZN5test16c_as_BEPNS_1CE(
// CHECK-ADDRESSAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-ADDRESSAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-ADDRESSAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-ADDRESSAUTH:       [[CAST_NOTNULL]]:
// CHECK-ADDRESSAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
// CHECK-ADDRESSAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-ADDRESSAUTH:       [[CAST_END]]:
// CHECK-ADDRESSAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[CAST_RESULT]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP6:%.*]] = load volatile i8, ptr [[TMP5]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP5]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @_ZN5test16c_as_BEPNS_1CE(
// CHECK-BOTHAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-BOTHAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA13]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-BOTHAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-BOTHAUTH:       [[CAST_NOTNULL]]:
// CHECK-BOTHAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
// CHECK-BOTHAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-BOTHAUTH:       [[CAST_END]]:
// CHECK-BOTHAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[CAST_RESULT]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP2]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP4]], i32 2, i64 [[TMP3]])
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = inttoptr i64 [[TMP5]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP7:%.*]] = load volatile i8, ptr [[TMP6]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP6]]
//
const void *c_as_B(C *o) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(o)), const void*>::value);
  return __builtin_get_vtable_pointer((B *)o);
}

// CHECK-NOAUTH-LABEL: define ptr @_ZN5test11dEPNS_1DE(
// CHECK-NOAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-NOAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA15:![0-9]+]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @_ZN5test11dEPNS_1DE(
// CHECK-TYPEAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-TYPEAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA15:![0-9]+]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = load volatile i8, ptr [[TMP3]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP3]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @_ZN5test11dEPNS_1DE(
// CHECK-ADDRESSAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-ADDRESSAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA15:![0-9]+]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 [[TMP1]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP4]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @_ZN5test11dEPNS_1DE(
// CHECK-BOTHAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-BOTHAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA15:![0-9]+]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP1]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = load volatile i8, ptr [[TMP5]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP5]]
//
const void *d(D *o) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(o)), const void*>::value);
  return __builtin_get_vtable_pointer(o);
}

// CHECK-NOAUTH-LABEL: define ptr @_ZN5test16d_as_AEPNS_1DE(
// CHECK-NOAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-NOAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-NOAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-NOAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-NOAUTH:       [[CAST_NOTNULL]]:
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[VTABLE]], i64 -32
// CHECK-NOAUTH-NEXT:    [[VBASE_OFFSET:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR]], align 8
// CHECK-NOAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[VBASE_OFFSET]]
// CHECK-NOAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-NOAUTH:       [[CAST_END]]:
// CHECK-NOAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-NOAUTH-NEXT:    [[VTABLE1:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE1]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @_ZN5test16d_as_AEPNS_1DE(
// CHECK-TYPEAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-TYPEAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-TYPEAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-TYPEAUTH:       [[CAST_NOTNULL]]:
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[TMP4]], i64 -32
// CHECK-TYPEAUTH-NEXT:    [[VBASE_OFFSET:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR]], align 8
// CHECK-TYPEAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[VBASE_OFFSET]]
// CHECK-TYPEAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-TYPEAUTH:       [[CAST_END]]:
// CHECK-TYPEAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE1:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP5:%.*]] = ptrtoint ptr [[VTABLE1]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP6:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP5]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP7:%.*]] = inttoptr i64 [[TMP6]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP8:%.*]] = load volatile i8, ptr [[TMP7]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP7]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @_ZN5test16d_as_AEPNS_1DE(
// CHECK-ADDRESSAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-ADDRESSAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-ADDRESSAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-ADDRESSAUTH:       [[CAST_NOTNULL]]:
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[TMP5]], i64 -32
// CHECK-ADDRESSAUTH-NEXT:    [[VBASE_OFFSET:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR]], align 8
// CHECK-ADDRESSAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[VBASE_OFFSET]]
// CHECK-ADDRESSAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-ADDRESSAUTH:       [[CAST_END]]:
// CHECK-ADDRESSAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE1:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP6:%.*]] = ptrtoint ptr [[CAST_RESULT]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP7:%.*]] = ptrtoint ptr [[VTABLE1]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP8:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP7]], i32 2, i64 [[TMP6]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP9:%.*]] = inttoptr i64 [[TMP8]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP10:%.*]] = load volatile i8, ptr [[TMP9]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP9]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @_ZN5test16d_as_AEPNS_1DE(
// CHECK-BOTHAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-BOTHAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA15]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-BOTHAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-BOTHAUTH:       [[CAST_NOTNULL]]:
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP2]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP4]], i32 2, i64 [[TMP3]])
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = inttoptr i64 [[TMP5]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[TMP6]], i64 -32
// CHECK-BOTHAUTH-NEXT:    [[VBASE_OFFSET:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR]], align 8
// CHECK-BOTHAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[VBASE_OFFSET]]
// CHECK-BOTHAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-BOTHAUTH:       [[CAST_END]]:
// CHECK-BOTHAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE1:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP7:%.*]] = ptrtoint ptr [[CAST_RESULT]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP8:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP7]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP9:%.*]] = ptrtoint ptr [[VTABLE1]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP10:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP9]], i32 2, i64 [[TMP8]])
// CHECK-BOTHAUTH-NEXT:    [[TMP11:%.*]] = inttoptr i64 [[TMP10]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP12:%.*]] = load volatile i8, ptr [[TMP11]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP11]]
//
const void *d_as_A(D *o) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(o)), const void*>::value);
  return __builtin_get_vtable_pointer((A *)o);
}

// CHECK-NOAUTH-LABEL: define ptr @_ZN5test11eEPNS_1EE(
// CHECK-NOAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-NOAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17:![0-9]+]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @_ZN5test11eEPNS_1EE(
// CHECK-TYPEAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-TYPEAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17:![0-9]+]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = load volatile i8, ptr [[TMP3]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP3]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @_ZN5test11eEPNS_1EE(
// CHECK-ADDRESSAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-ADDRESSAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17:![0-9]+]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 [[TMP1]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP4]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @_ZN5test11eEPNS_1EE(
// CHECK-BOTHAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-BOTHAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17:![0-9]+]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP1]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = load volatile i8, ptr [[TMP5]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP5]]
//
const void *e(E *o) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(o)), const void*>::value);
  return __builtin_get_vtable_pointer(o);
}

// CHECK-NOAUTH-LABEL: define ptr @_ZN5test16e_as_BEPNS_1EE(
// CHECK-NOAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-NOAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-NOAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-NOAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-NOAUTH:       [[CAST_NOTNULL]]:
// CHECK-NOAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
// CHECK-NOAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-NOAUTH:       [[CAST_END]]:
// CHECK-NOAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @_ZN5test16e_as_BEPNS_1EE(
// CHECK-TYPEAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-TYPEAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-TYPEAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-TYPEAUTH:       [[CAST_NOTNULL]]:
// CHECK-TYPEAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
// CHECK-TYPEAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-TYPEAUTH:       [[CAST_END]]:
// CHECK-TYPEAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP4]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @_ZN5test16e_as_BEPNS_1EE(
// CHECK-ADDRESSAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-ADDRESSAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-ADDRESSAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-ADDRESSAUTH:       [[CAST_NOTNULL]]:
// CHECK-ADDRESSAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
// CHECK-ADDRESSAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-ADDRESSAUTH:       [[CAST_END]]:
// CHECK-ADDRESSAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[CAST_RESULT]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP6:%.*]] = load volatile i8, ptr [[TMP5]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP5]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @_ZN5test16e_as_BEPNS_1EE(
// CHECK-BOTHAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-BOTHAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
// CHECK-BOTHAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-BOTHAUTH:       [[CAST_NOTNULL]]:
// CHECK-BOTHAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
// CHECK-BOTHAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-BOTHAUTH:       [[CAST_END]]:
// CHECK-BOTHAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[CAST_RESULT]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[CAST_RESULT]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP2]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP4]], i32 2, i64 [[TMP3]])
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = inttoptr i64 [[TMP5]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP7:%.*]] = load volatile i8, ptr [[TMP6]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP6]]
//
const void *e_as_B(E *o) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(o)), const void*>::value);
  return __builtin_get_vtable_pointer((B *)o);
}

// CHECK-NOAUTH-LABEL: define ptr @_ZN5test16e_as_DEPNS_1EE(
// CHECK-NOAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-NOAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @_ZN5test16e_as_DEPNS_1EE(
// CHECK-TYPEAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-TYPEAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = load volatile i8, ptr [[TMP3]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP3]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @_ZN5test16e_as_DEPNS_1EE(
// CHECK-ADDRESSAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-ADDRESSAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 [[TMP1]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP4]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @_ZN5test16e_as_DEPNS_1EE(
// CHECK-BOTHAUTH-SAME: ptr [[O:%.*]]) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-BOTHAUTH-NEXT:    [[O_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[O]], ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[O_ADDR]], align 8, !tbaa [[TBAA17]]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP1]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = load volatile i8, ptr [[TMP5]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP5]]
//
const void *e_as_D(E *o) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(o)), const void*>::value);
  return __builtin_get_vtable_pointer((D *)o);
}

// CHECK-NOAUTH-LABEL: define ptr @aArrayParameter(
// CHECK-NOAUTH-SAME: ptr [[AARRAY:%.*]]) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-NOAUTH-NEXT:    [[AARRAY_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NOAUTH-NEXT:    store ptr [[AARRAY]], ptr [[AARRAY_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AARRAY_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @aArrayParameter(
// CHECK-TYPEAUTH-SAME: ptr [[AARRAY:%.*]]) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-TYPEAUTH-NEXT:    [[AARRAY_ADDR:%.*]] = alloca ptr, align 8
// CHECK-TYPEAUTH-NEXT:    store ptr [[AARRAY]], ptr [[AARRAY_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AARRAY_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = load volatile i8, ptr [[TMP3]], align 8
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP3]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @aArrayParameter(
// CHECK-ADDRESSAUTH-SAME: ptr [[AARRAY:%.*]]) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-ADDRESSAUTH-NEXT:    [[AARRAY_ADDR:%.*]] = alloca ptr, align 8
// CHECK-ADDRESSAUTH-NEXT:    store ptr [[AARRAY]], ptr [[AARRAY_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AARRAY_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 [[TMP1]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP4]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @aArrayParameter(
// CHECK-BOTHAUTH-SAME: ptr [[AARRAY:%.*]]) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-BOTHAUTH-NEXT:    [[AARRAY_ADDR:%.*]] = alloca ptr, align 8
// CHECK-BOTHAUTH-NEXT:    store ptr [[AARRAY]], ptr [[AARRAY_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AARRAY_ADDR]], align 8, !tbaa [[TBAA6]]
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[TMP0]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP1]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = load volatile i8, ptr [[TMP5]], align 8
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP5]]
//
extern "C" const void *aArrayParameter(A aArray[]) {
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(aArray)), const void*>::value);
  return __builtin_get_vtable_pointer(aArray);
}

// CHECK-NOAUTH-LABEL: define ptr @aArrayLocal(
// CHECK-NOAUTH-SAME: ) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-NOAUTH-NEXT:    [[ARRAY:%.*]] = alloca [1 x %"struct.test1::A"], align 8
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[ARRAY]]) #[[ATTR5:[0-9]+]]
// CHECK-NOAUTH-NEXT:    call void @_ZN5test11AC1Ev(ptr nonnull align 8 dereferenceable(8) [[ARRAY]])
// CHECK-NOAUTH-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %"struct.test1::A"], ptr [[ARRAY]], i64 0, i64 0
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[ARRAYDECAY]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[ARRAY]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    ret ptr [[VTABLE]]
//
// CHECK-TYPEAUTH-LABEL: define ptr @aArrayLocal(
// CHECK-TYPEAUTH-SAME: ) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-TYPEAUTH-NEXT:    [[ARRAY:%.*]] = alloca [1 x %"struct.test1::A"], align 8
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[ARRAY]]) #[[ATTR7:[0-9]+]]
// CHECK-TYPEAUTH-NEXT:    [[CALL:%.*]] = call ptr @_ZN5test11AC1Ev(ptr nonnull align 8 dereferenceable(8) [[ARRAY]])
// CHECK-TYPEAUTH-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %"struct.test1::A"], ptr [[ARRAY]], i64 0, i64 0
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[ARRAYDECAY]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP0]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = inttoptr i64 [[TMP1]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = load volatile i8, ptr [[TMP2]], align 8
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[ARRAY]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    ret ptr [[TMP2]]
//
// CHECK-ADDRESSAUTH-LABEL: define ptr @aArrayLocal(
// CHECK-ADDRESSAUTH-SAME: ) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-ADDRESSAUTH-NEXT:    [[ARRAY:%.*]] = alloca [1 x %"struct.test1::A"], align 8
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[ARRAY]]) #[[ATTR7:[0-9]+]]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL:%.*]] = call ptr @_ZN5test11AC1Ev(ptr nonnull align 8 dereferenceable(8) [[ARRAY]])
// CHECK-ADDRESSAUTH-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %"struct.test1::A"], ptr [[ARRAY]], i64 0, i64 0
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[ARRAYDECAY]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP1]], i32 2, i64 [[TMP0]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = load volatile i8, ptr [[TMP3]], align 8
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[ARRAY]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    ret ptr [[TMP3]]
//
// CHECK-BOTHAUTH-LABEL: define ptr @aArrayLocal(
// CHECK-BOTHAUTH-SAME: ) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*:]]
// CHECK-BOTHAUTH-NEXT:    [[ARRAY:%.*]] = alloca [1 x %"struct.test1::A"], align 8
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[ARRAY]]) #[[ATTR7:[0-9]+]]
// CHECK-BOTHAUTH-NEXT:    [[CALL:%.*]] = call ptr @_ZN5test11AC1Ev(ptr nonnull align 8 dereferenceable(8) [[ARRAY]])
// CHECK-BOTHAUTH-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %"struct.test1::A"], ptr [[ARRAY]], i64 0, i64 0
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[ARRAYDECAY]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP0]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 [[TMP1]])
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = load volatile i8, ptr [[TMP4]], align 8
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[ARRAY]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    ret ptr [[TMP4]]
//
extern "C" const void *aArrayLocal() {
  A array[] = { A() };
  static_assert(same_type<decltype(__builtin_get_vtable_pointer(array)), const void*>::value);
  return __builtin_get_vtable_pointer(array);
}

// CHECK-NOAUTH-LABEL: define void @_ZN5test14testEv(
// CHECK-NOAUTH-SAME: ) #[[ATTR0]] {
// CHECK-NOAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-NOAUTH-NEXT:    [[AINSTANCE:%.*]] = alloca %"struct.test1::A", align 8
// CHECK-NOAUTH-NEXT:    [[BINSTANCE:%.*]] = alloca %"struct.test1::B", align 8
// CHECK-NOAUTH-NEXT:    [[CINSTANCE:%.*]] = alloca %"struct.test1::C", align 8
// CHECK-NOAUTH-NEXT:    [[DINSTANCE:%.*]] = alloca %"struct.test1::D", align 8
// CHECK-NOAUTH-NEXT:    [[EINSTANCE:%.*]] = alloca %"struct.test1::E", align 8
// CHECK-NOAUTH-NEXT:    [[EARRAY:%.*]] = alloca [1 x %"struct.test1::E"], align 16
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[AINSTANCE]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    call void @_ZN5test11AC1Ev(ptr nonnull align 8 dereferenceable(8) [[AINSTANCE]])
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[BINSTANCE]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    call void @_ZN5test11BC1Ev(ptr nonnull align 8 dereferenceable(8) [[BINSTANCE]])
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[CINSTANCE]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    call void @_ZN5test11CC1Ev(ptr nonnull align 8 dereferenceable(16) [[CINSTANCE]])
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[DINSTANCE]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    call void @_ZN5test11DC1Ev(ptr nonnull align 8 dereferenceable(8) [[DINSTANCE]])
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[EINSTANCE]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    call void @_ZN5test11EC1Ev(ptr nonnull align 8 dereferenceable(16) [[EINSTANCE]])
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[EARRAY]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    call void @llvm.memset.p0.i64(ptr align 16 [[EARRAY]], i8 0, i64 16, i1 false)
// CHECK-NOAUTH-NEXT:    call void @_ZN5test11EC1Ev(ptr nonnull align 8 dereferenceable(16) [[EARRAY]])
// CHECK-NOAUTH-NEXT:    [[CALL:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[AINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[CALL1:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[BINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[TMP0:%.*]] = icmp eq ptr [[CINSTANCE]], null
// CHECK-NOAUTH-NEXT:    br i1 [[TMP0]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-NOAUTH:       [[CAST_NOTNULL]]:
// CHECK-NOAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CINSTANCE]], i64 8
// CHECK-NOAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-NOAUTH:       [[CAST_END]]:
// CHECK-NOAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-NOAUTH-NEXT:    [[CALL2:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT]])
// CHECK-NOAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[DINSTANCE]], null
// CHECK-NOAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END5:.*]], label %[[CAST_NOTNULL3:.*]]
// CHECK-NOAUTH:       [[CAST_NOTNULL3]]:
// CHECK-NOAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[DINSTANCE]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[VTABLE]], i64 -32
// CHECK-NOAUTH-NEXT:    [[VBASE_OFFSET:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR]], align 8
// CHECK-NOAUTH-NEXT:    [[ADD_PTR4:%.*]] = getelementptr inbounds i8, ptr [[DINSTANCE]], i64 [[VBASE_OFFSET]]
// CHECK-NOAUTH-NEXT:    br label %[[CAST_END5]]
// CHECK-NOAUTH:       [[CAST_END5]]:
// CHECK-NOAUTH-NEXT:    [[CAST_RESULT6:%.*]] = phi ptr [ [[ADD_PTR4]], %[[CAST_NOTNULL3]] ], [ null, %[[CAST_END]] ]
// CHECK-NOAUTH-NEXT:    [[CALL7:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT6]])
// CHECK-NOAUTH-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-NOAUTH-NEXT:    br i1 [[TMP2]], label %[[CAST_END13:.*]], label %[[CAST_NOTNULL8:.*]]
// CHECK-NOAUTH:       [[CAST_NOTNULL8]]:
// CHECK-NOAUTH-NEXT:    [[VTABLE9:%.*]] = load ptr, ptr [[EINSTANCE]], align 8, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    [[VBASE_OFFSET_PTR10:%.*]] = getelementptr i8, ptr [[VTABLE9]], i64 -32
// CHECK-NOAUTH-NEXT:    [[VBASE_OFFSET11:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR10]], align 8
// CHECK-NOAUTH-NEXT:    [[ADD_PTR12:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 [[VBASE_OFFSET11]]
// CHECK-NOAUTH-NEXT:    br label %[[CAST_END13]]
// CHECK-NOAUTH:       [[CAST_END13]]:
// CHECK-NOAUTH-NEXT:    [[CAST_RESULT14:%.*]] = phi ptr [ [[ADD_PTR12]], %[[CAST_NOTNULL8]] ], [ null, %[[CAST_END5]] ]
// CHECK-NOAUTH-NEXT:    [[CALL15:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT14]])
// CHECK-NOAUTH-NEXT:    [[TMP3:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-NOAUTH-NEXT:    br i1 [[TMP3]], label %[[CAST_END18:.*]], label %[[CAST_NOTNULL16:.*]]
// CHECK-NOAUTH:       [[CAST_NOTNULL16]]:
// CHECK-NOAUTH-NEXT:    [[ADD_PTR17:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 8
// CHECK-NOAUTH-NEXT:    br label %[[CAST_END18]]
// CHECK-NOAUTH:       [[CAST_END18]]:
// CHECK-NOAUTH-NEXT:    [[CAST_RESULT19:%.*]] = phi ptr [ [[ADD_PTR17]], %[[CAST_NOTNULL16]] ], [ null, %[[CAST_END13]] ]
// CHECK-NOAUTH-NEXT:    [[CALL20:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT19]])
// CHECK-NOAUTH-NEXT:    [[CALL21:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[BINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[CINSTANCE]], null
// CHECK-NOAUTH-NEXT:    br i1 [[TMP4]], label %[[CAST_END24:.*]], label %[[CAST_NOTNULL22:.*]]
// CHECK-NOAUTH:       [[CAST_NOTNULL22]]:
// CHECK-NOAUTH-NEXT:    [[ADD_PTR23:%.*]] = getelementptr inbounds i8, ptr [[CINSTANCE]], i64 8
// CHECK-NOAUTH-NEXT:    br label %[[CAST_END24]]
// CHECK-NOAUTH:       [[CAST_END24]]:
// CHECK-NOAUTH-NEXT:    [[CAST_RESULT25:%.*]] = phi ptr [ [[ADD_PTR23]], %[[CAST_NOTNULL22]] ], [ null, %[[CAST_END18]] ]
// CHECK-NOAUTH-NEXT:    [[CALL26:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[CAST_RESULT25]])
// CHECK-NOAUTH-NEXT:    [[TMP5:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-NOAUTH-NEXT:    br i1 [[TMP5]], label %[[CAST_END29:.*]], label %[[CAST_NOTNULL27:.*]]
// CHECK-NOAUTH:       [[CAST_NOTNULL27]]:
// CHECK-NOAUTH-NEXT:    [[ADD_PTR28:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 8
// CHECK-NOAUTH-NEXT:    br label %[[CAST_END29]]
// CHECK-NOAUTH:       [[CAST_END29]]:
// CHECK-NOAUTH-NEXT:    [[CAST_RESULT30:%.*]] = phi ptr [ [[ADD_PTR28]], %[[CAST_NOTNULL27]] ], [ null, %[[CAST_END24]] ]
// CHECK-NOAUTH-NEXT:    [[CALL31:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[CAST_RESULT30]])
// CHECK-NOAUTH-NEXT:    [[CALL32:%.*]] = call ptr @_ZN5test16b_as_AEPNS_1BE(ptr [[BINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[CALL33:%.*]] = call ptr @_ZN5test11cEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[CALL34:%.*]] = call ptr @_ZN5test16c_as_ZEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[CALL35:%.*]] = call ptr @_ZN5test16c_as_BEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[CALL36:%.*]] = call ptr @_ZN5test11dEPNS_1DE(ptr [[DINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[CALL37:%.*]] = call ptr @_ZN5test11dEPNS_1DE(ptr [[EINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[CALL38:%.*]] = call ptr @_ZN5test16d_as_AEPNS_1DE(ptr [[DINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[CALL39:%.*]] = call ptr @_ZN5test16d_as_AEPNS_1DE(ptr [[EINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[CALL40:%.*]] = call ptr @_ZN5test11eEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[CALL41:%.*]] = call ptr @_ZN5test16e_as_BEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[CALL42:%.*]] = call ptr @_ZN5test16e_as_DEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-NOAUTH-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %"struct.test1::E"], ptr [[EARRAY]], i64 0, i64 0
// CHECK-NOAUTH-NEXT:    [[VTABLE43:%.*]] = load ptr, ptr [[ARRAYDECAY]], align 16, !tbaa [[TBAA9]]
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[EARRAY]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[EINSTANCE]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[DINSTANCE]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[CINSTANCE]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[BINSTANCE]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[AINSTANCE]]) #[[ATTR5]]
// CHECK-NOAUTH-NEXT:    ret void
//
// CHECK-TYPEAUTH-LABEL: define void @_ZN5test14testEv(
// CHECK-TYPEAUTH-SAME: ) #[[ATTR0]] {
// CHECK-TYPEAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-TYPEAUTH-NEXT:    [[AINSTANCE:%.*]] = alloca %"struct.test1::A", align 8
// CHECK-TYPEAUTH-NEXT:    [[BINSTANCE:%.*]] = alloca %"struct.test1::B", align 8
// CHECK-TYPEAUTH-NEXT:    [[CINSTANCE:%.*]] = alloca %"struct.test1::C", align 8
// CHECK-TYPEAUTH-NEXT:    [[DINSTANCE:%.*]] = alloca %"struct.test1::D", align 8
// CHECK-TYPEAUTH-NEXT:    [[EINSTANCE:%.*]] = alloca %"struct.test1::E", align 8
// CHECK-TYPEAUTH-NEXT:    [[EARRAY:%.*]] = alloca [1 x %"struct.test1::E"], align 8
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[AINSTANCE]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    [[CALL:%.*]] = call ptr @_ZN5test11AC1Ev(ptr nonnull align 8 dereferenceable(8) [[AINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[BINSTANCE]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    [[CALL1:%.*]] = call ptr @_ZN5test11BC1Ev(ptr nonnull align 8 dereferenceable(8) [[BINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[CINSTANCE]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    [[CALL2:%.*]] = call ptr @_ZN5test11CC1Ev(ptr nonnull align 8 dereferenceable(16) [[CINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[DINSTANCE]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    [[CALL3:%.*]] = call ptr @_ZN5test11DC1Ev(ptr nonnull align 8 dereferenceable(8) [[DINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[EINSTANCE]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    [[CALL4:%.*]] = call ptr @_ZN5test11EC1Ev(ptr nonnull align 8 dereferenceable(16) [[EINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[EARRAY]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[EARRAY]], i8 0, i64 16, i1 false)
// CHECK-TYPEAUTH-NEXT:    [[CALL5:%.*]] = call ptr @_ZN5test11EC1Ev(ptr nonnull align 8 dereferenceable(16) [[EARRAY]])
// CHECK-TYPEAUTH-NEXT:    [[CALL6:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[AINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[CALL7:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[BINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[TMP0:%.*]] = icmp eq ptr [[CINSTANCE]], null
// CHECK-TYPEAUTH-NEXT:    br i1 [[TMP0]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-TYPEAUTH:       [[CAST_NOTNULL]]:
// CHECK-TYPEAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CINSTANCE]], i64 8
// CHECK-TYPEAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-TYPEAUTH:       [[CAST_END]]:
// CHECK-TYPEAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-TYPEAUTH-NEXT:    [[CALL8:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT]])
// CHECK-TYPEAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[DINSTANCE]], null
// CHECK-TYPEAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END11:.*]], label %[[CAST_NOTNULL9:.*]]
// CHECK-TYPEAUTH:       [[CAST_NOTNULL9]]:
// CHECK-TYPEAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[DINSTANCE]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP2]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[TMP4]], i64 -32
// CHECK-TYPEAUTH-NEXT:    [[VBASE_OFFSET:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR]], align 8
// CHECK-TYPEAUTH-NEXT:    [[ADD_PTR10:%.*]] = getelementptr inbounds i8, ptr [[DINSTANCE]], i64 [[VBASE_OFFSET]]
// CHECK-TYPEAUTH-NEXT:    br label %[[CAST_END11]]
// CHECK-TYPEAUTH:       [[CAST_END11]]:
// CHECK-TYPEAUTH-NEXT:    [[CAST_RESULT12:%.*]] = phi ptr [ [[ADD_PTR10]], %[[CAST_NOTNULL9]] ], [ null, %[[CAST_END]] ]
// CHECK-TYPEAUTH-NEXT:    [[CALL13:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT12]])
// CHECK-TYPEAUTH-NEXT:    [[TMP5:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-TYPEAUTH-NEXT:    br i1 [[TMP5]], label %[[CAST_END19:.*]], label %[[CAST_NOTNULL14:.*]]
// CHECK-TYPEAUTH:       [[CAST_NOTNULL14]]:
// CHECK-TYPEAUTH-NEXT:    [[VTABLE15:%.*]] = load ptr, ptr [[EINSTANCE]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP6:%.*]] = ptrtoint ptr [[VTABLE15]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP7:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP6]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP8:%.*]] = inttoptr i64 [[TMP7]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[VBASE_OFFSET_PTR16:%.*]] = getelementptr i8, ptr [[TMP8]], i64 -32
// CHECK-TYPEAUTH-NEXT:    [[VBASE_OFFSET17:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR16]], align 8
// CHECK-TYPEAUTH-NEXT:    [[ADD_PTR18:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 [[VBASE_OFFSET17]]
// CHECK-TYPEAUTH-NEXT:    br label %[[CAST_END19]]
// CHECK-TYPEAUTH:       [[CAST_END19]]:
// CHECK-TYPEAUTH-NEXT:    [[CAST_RESULT20:%.*]] = phi ptr [ [[ADD_PTR18]], %[[CAST_NOTNULL14]] ], [ null, %[[CAST_END11]] ]
// CHECK-TYPEAUTH-NEXT:    [[CALL21:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT20]])
// CHECK-TYPEAUTH-NEXT:    [[TMP9:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-TYPEAUTH-NEXT:    br i1 [[TMP9]], label %[[CAST_END24:.*]], label %[[CAST_NOTNULL22:.*]]
// CHECK-TYPEAUTH:       [[CAST_NOTNULL22]]:
// CHECK-TYPEAUTH-NEXT:    [[ADD_PTR23:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 8
// CHECK-TYPEAUTH-NEXT:    br label %[[CAST_END24]]
// CHECK-TYPEAUTH:       [[CAST_END24]]:
// CHECK-TYPEAUTH-NEXT:    [[CAST_RESULT25:%.*]] = phi ptr [ [[ADD_PTR23]], %[[CAST_NOTNULL22]] ], [ null, %[[CAST_END19]] ]
// CHECK-TYPEAUTH-NEXT:    [[CALL26:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT25]])
// CHECK-TYPEAUTH-NEXT:    [[CALL27:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[BINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[TMP10:%.*]] = icmp eq ptr [[CINSTANCE]], null
// CHECK-TYPEAUTH-NEXT:    br i1 [[TMP10]], label %[[CAST_END30:.*]], label %[[CAST_NOTNULL28:.*]]
// CHECK-TYPEAUTH:       [[CAST_NOTNULL28]]:
// CHECK-TYPEAUTH-NEXT:    [[ADD_PTR29:%.*]] = getelementptr inbounds i8, ptr [[CINSTANCE]], i64 8
// CHECK-TYPEAUTH-NEXT:    br label %[[CAST_END30]]
// CHECK-TYPEAUTH:       [[CAST_END30]]:
// CHECK-TYPEAUTH-NEXT:    [[CAST_RESULT31:%.*]] = phi ptr [ [[ADD_PTR29]], %[[CAST_NOTNULL28]] ], [ null, %[[CAST_END24]] ]
// CHECK-TYPEAUTH-NEXT:    [[CALL32:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[CAST_RESULT31]])
// CHECK-TYPEAUTH-NEXT:    [[TMP11:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-TYPEAUTH-NEXT:    br i1 [[TMP11]], label %[[CAST_END35:.*]], label %[[CAST_NOTNULL33:.*]]
// CHECK-TYPEAUTH:       [[CAST_NOTNULL33]]:
// CHECK-TYPEAUTH-NEXT:    [[ADD_PTR34:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 8
// CHECK-TYPEAUTH-NEXT:    br label %[[CAST_END35]]
// CHECK-TYPEAUTH:       [[CAST_END35]]:
// CHECK-TYPEAUTH-NEXT:    [[CAST_RESULT36:%.*]] = phi ptr [ [[ADD_PTR34]], %[[CAST_NOTNULL33]] ], [ null, %[[CAST_END30]] ]
// CHECK-TYPEAUTH-NEXT:    [[CALL37:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[CAST_RESULT36]])
// CHECK-TYPEAUTH-NEXT:    [[CALL38:%.*]] = call ptr @_ZN5test16b_as_AEPNS_1BE(ptr [[BINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[CALL39:%.*]] = call ptr @_ZN5test11cEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[CALL40:%.*]] = call ptr @_ZN5test16c_as_ZEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[CALL41:%.*]] = call ptr @_ZN5test16c_as_BEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[CALL42:%.*]] = call ptr @_ZN5test11dEPNS_1DE(ptr [[DINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[CALL43:%.*]] = call ptr @_ZN5test11dEPNS_1DE(ptr [[EINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[CALL44:%.*]] = call ptr @_ZN5test16d_as_AEPNS_1DE(ptr [[DINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[CALL45:%.*]] = call ptr @_ZN5test16d_as_AEPNS_1DE(ptr [[EINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[CALL46:%.*]] = call ptr @_ZN5test11eEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[CALL47:%.*]] = call ptr @_ZN5test16e_as_BEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[CALL48:%.*]] = call ptr @_ZN5test16e_as_DEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-TYPEAUTH-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %"struct.test1::E"], ptr [[EARRAY]], i64 0, i64 0
// CHECK-TYPEAUTH-NEXT:    [[VTABLE49:%.*]] = load ptr, ptr [[ARRAYDECAY]], align 8, !tbaa [[TBAA9]]
// CHECK-TYPEAUTH-NEXT:    [[TMP12:%.*]] = ptrtoint ptr [[VTABLE49]] to i64
// CHECK-TYPEAUTH-NEXT:    [[TMP13:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP12]], i32 2, i64 48388)
// CHECK-TYPEAUTH-NEXT:    [[TMP14:%.*]] = inttoptr i64 [[TMP13]] to ptr
// CHECK-TYPEAUTH-NEXT:    [[TMP15:%.*]] = load volatile i8, ptr [[TMP14]], align 8
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[EARRAY]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[EINSTANCE]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[DINSTANCE]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[CINSTANCE]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[BINSTANCE]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[AINSTANCE]]) #[[ATTR7]]
// CHECK-TYPEAUTH-NEXT:    ret void
//
// CHECK-ADDRESSAUTH-LABEL: define void @_ZN5test14testEv(
// CHECK-ADDRESSAUTH-SAME: ) #[[ATTR0]] {
// CHECK-ADDRESSAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-ADDRESSAUTH-NEXT:    [[AINSTANCE:%.*]] = alloca %"struct.test1::A", align 8
// CHECK-ADDRESSAUTH-NEXT:    [[BINSTANCE:%.*]] = alloca %"struct.test1::B", align 8
// CHECK-ADDRESSAUTH-NEXT:    [[CINSTANCE:%.*]] = alloca %"struct.test1::C", align 8
// CHECK-ADDRESSAUTH-NEXT:    [[DINSTANCE:%.*]] = alloca %"struct.test1::D", align 8
// CHECK-ADDRESSAUTH-NEXT:    [[EINSTANCE:%.*]] = alloca %"struct.test1::E", align 8
// CHECK-ADDRESSAUTH-NEXT:    [[EARRAY:%.*]] = alloca [1 x %"struct.test1::E"], align 8
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[AINSTANCE]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL:%.*]] = call ptr @_ZN5test11AC1Ev(ptr nonnull align 8 dereferenceable(8) [[AINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[BINSTANCE]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL1:%.*]] = call ptr @_ZN5test11BC1Ev(ptr nonnull align 8 dereferenceable(8) [[BINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[CINSTANCE]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL2:%.*]] = call ptr @_ZN5test11CC1Ev(ptr nonnull align 8 dereferenceable(16) [[CINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[DINSTANCE]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL3:%.*]] = call ptr @_ZN5test11DC1Ev(ptr nonnull align 8 dereferenceable(8) [[DINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[EINSTANCE]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL4:%.*]] = call ptr @_ZN5test11EC1Ev(ptr nonnull align 8 dereferenceable(16) [[EINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[EARRAY]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[EARRAY]], i8 0, i64 16, i1 false)
// CHECK-ADDRESSAUTH-NEXT:    [[CALL5:%.*]] = call ptr @_ZN5test11EC1Ev(ptr nonnull align 8 dereferenceable(16) [[EARRAY]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL6:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[AINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL7:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[BINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP0:%.*]] = icmp eq ptr [[CINSTANCE]], null
// CHECK-ADDRESSAUTH-NEXT:    br i1 [[TMP0]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-ADDRESSAUTH:       [[CAST_NOTNULL]]:
// CHECK-ADDRESSAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CINSTANCE]], i64 8
// CHECK-ADDRESSAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-ADDRESSAUTH:       [[CAST_END]]:
// CHECK-ADDRESSAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL8:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[DINSTANCE]], null
// CHECK-ADDRESSAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END11:.*]], label %[[CAST_NOTNULL9:.*]]
// CHECK-ADDRESSAUTH:       [[CAST_NOTNULL9]]:
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[DINSTANCE]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[DINSTANCE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP3]], i32 2, i64 [[TMP2]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[TMP5]], i64 -32
// CHECK-ADDRESSAUTH-NEXT:    [[VBASE_OFFSET:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR]], align 8
// CHECK-ADDRESSAUTH-NEXT:    [[ADD_PTR10:%.*]] = getelementptr inbounds i8, ptr [[DINSTANCE]], i64 [[VBASE_OFFSET]]
// CHECK-ADDRESSAUTH-NEXT:    br label %[[CAST_END11]]
// CHECK-ADDRESSAUTH:       [[CAST_END11]]:
// CHECK-ADDRESSAUTH-NEXT:    [[CAST_RESULT12:%.*]] = phi ptr [ [[ADD_PTR10]], %[[CAST_NOTNULL9]] ], [ null, %[[CAST_END]] ]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL13:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT12]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP6:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-ADDRESSAUTH-NEXT:    br i1 [[TMP6]], label %[[CAST_END19:.*]], label %[[CAST_NOTNULL14:.*]]
// CHECK-ADDRESSAUTH:       [[CAST_NOTNULL14]]:
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE15:%.*]] = load ptr, ptr [[EINSTANCE]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP7:%.*]] = ptrtoint ptr [[EINSTANCE]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP8:%.*]] = ptrtoint ptr [[VTABLE15]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP9:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP8]], i32 2, i64 [[TMP7]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP10:%.*]] = inttoptr i64 [[TMP9]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[VBASE_OFFSET_PTR16:%.*]] = getelementptr i8, ptr [[TMP10]], i64 -32
// CHECK-ADDRESSAUTH-NEXT:    [[VBASE_OFFSET17:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR16]], align 8
// CHECK-ADDRESSAUTH-NEXT:    [[ADD_PTR18:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 [[VBASE_OFFSET17]]
// CHECK-ADDRESSAUTH-NEXT:    br label %[[CAST_END19]]
// CHECK-ADDRESSAUTH:       [[CAST_END19]]:
// CHECK-ADDRESSAUTH-NEXT:    [[CAST_RESULT20:%.*]] = phi ptr [ [[ADD_PTR18]], %[[CAST_NOTNULL14]] ], [ null, %[[CAST_END11]] ]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL21:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT20]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP11:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-ADDRESSAUTH-NEXT:    br i1 [[TMP11]], label %[[CAST_END24:.*]], label %[[CAST_NOTNULL22:.*]]
// CHECK-ADDRESSAUTH:       [[CAST_NOTNULL22]]:
// CHECK-ADDRESSAUTH-NEXT:    [[ADD_PTR23:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 8
// CHECK-ADDRESSAUTH-NEXT:    br label %[[CAST_END24]]
// CHECK-ADDRESSAUTH:       [[CAST_END24]]:
// CHECK-ADDRESSAUTH-NEXT:    [[CAST_RESULT25:%.*]] = phi ptr [ [[ADD_PTR23]], %[[CAST_NOTNULL22]] ], [ null, %[[CAST_END19]] ]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL26:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT25]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL27:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[BINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP12:%.*]] = icmp eq ptr [[CINSTANCE]], null
// CHECK-ADDRESSAUTH-NEXT:    br i1 [[TMP12]], label %[[CAST_END30:.*]], label %[[CAST_NOTNULL28:.*]]
// CHECK-ADDRESSAUTH:       [[CAST_NOTNULL28]]:
// CHECK-ADDRESSAUTH-NEXT:    [[ADD_PTR29:%.*]] = getelementptr inbounds i8, ptr [[CINSTANCE]], i64 8
// CHECK-ADDRESSAUTH-NEXT:    br label %[[CAST_END30]]
// CHECK-ADDRESSAUTH:       [[CAST_END30]]:
// CHECK-ADDRESSAUTH-NEXT:    [[CAST_RESULT31:%.*]] = phi ptr [ [[ADD_PTR29]], %[[CAST_NOTNULL28]] ], [ null, %[[CAST_END24]] ]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL32:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[CAST_RESULT31]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP13:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-ADDRESSAUTH-NEXT:    br i1 [[TMP13]], label %[[CAST_END35:.*]], label %[[CAST_NOTNULL33:.*]]
// CHECK-ADDRESSAUTH:       [[CAST_NOTNULL33]]:
// CHECK-ADDRESSAUTH-NEXT:    [[ADD_PTR34:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 8
// CHECK-ADDRESSAUTH-NEXT:    br label %[[CAST_END35]]
// CHECK-ADDRESSAUTH:       [[CAST_END35]]:
// CHECK-ADDRESSAUTH-NEXT:    [[CAST_RESULT36:%.*]] = phi ptr [ [[ADD_PTR34]], %[[CAST_NOTNULL33]] ], [ null, %[[CAST_END30]] ]
// CHECK-ADDRESSAUTH-NEXT:    [[CALL37:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[CAST_RESULT36]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL38:%.*]] = call ptr @_ZN5test16b_as_AEPNS_1BE(ptr [[BINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL39:%.*]] = call ptr @_ZN5test11cEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL40:%.*]] = call ptr @_ZN5test16c_as_ZEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL41:%.*]] = call ptr @_ZN5test16c_as_BEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL42:%.*]] = call ptr @_ZN5test11dEPNS_1DE(ptr [[DINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL43:%.*]] = call ptr @_ZN5test11dEPNS_1DE(ptr [[EINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL44:%.*]] = call ptr @_ZN5test16d_as_AEPNS_1DE(ptr [[DINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL45:%.*]] = call ptr @_ZN5test16d_as_AEPNS_1DE(ptr [[EINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL46:%.*]] = call ptr @_ZN5test11eEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL47:%.*]] = call ptr @_ZN5test16e_as_BEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[CALL48:%.*]] = call ptr @_ZN5test16e_as_DEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-ADDRESSAUTH-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %"struct.test1::E"], ptr [[EARRAY]], i64 0, i64 0
// CHECK-ADDRESSAUTH-NEXT:    [[VTABLE49:%.*]] = load ptr, ptr [[ARRAYDECAY]], align 8, !tbaa [[TBAA9]]
// CHECK-ADDRESSAUTH-NEXT:    [[TMP14:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP15:%.*]] = ptrtoint ptr [[VTABLE49]] to i64
// CHECK-ADDRESSAUTH-NEXT:    [[TMP16:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP15]], i32 2, i64 [[TMP14]])
// CHECK-ADDRESSAUTH-NEXT:    [[TMP17:%.*]] = inttoptr i64 [[TMP16]] to ptr
// CHECK-ADDRESSAUTH-NEXT:    [[TMP18:%.*]] = load volatile i8, ptr [[TMP17]], align 8
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[EARRAY]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[EINSTANCE]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[DINSTANCE]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[CINSTANCE]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[BINSTANCE]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[AINSTANCE]]) #[[ATTR7]]
// CHECK-ADDRESSAUTH-NEXT:    ret void
//
// CHECK-BOTHAUTH-LABEL: define void @_ZN5test14testEv(
// CHECK-BOTHAUTH-SAME: ) #[[ATTR0]] {
// CHECK-BOTHAUTH-NEXT:  [[ENTRY:.*]]:
// CHECK-BOTHAUTH-NEXT:    [[AINSTANCE:%.*]] = alloca %"struct.test1::A", align 8
// CHECK-BOTHAUTH-NEXT:    [[BINSTANCE:%.*]] = alloca %"struct.test1::B", align 8
// CHECK-BOTHAUTH-NEXT:    [[CINSTANCE:%.*]] = alloca %"struct.test1::C", align 8
// CHECK-BOTHAUTH-NEXT:    [[DINSTANCE:%.*]] = alloca %"struct.test1::D", align 8
// CHECK-BOTHAUTH-NEXT:    [[EINSTANCE:%.*]] = alloca %"struct.test1::E", align 8
// CHECK-BOTHAUTH-NEXT:    [[EARRAY:%.*]] = alloca [1 x %"struct.test1::E"], align 8
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[AINSTANCE]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    [[CALL:%.*]] = call ptr @_ZN5test11AC1Ev(ptr nonnull align 8 dereferenceable(8) [[AINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[BINSTANCE]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    [[CALL1:%.*]] = call ptr @_ZN5test11BC1Ev(ptr nonnull align 8 dereferenceable(8) [[BINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[CINSTANCE]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    [[CALL2:%.*]] = call ptr @_ZN5test11CC1Ev(ptr nonnull align 8 dereferenceable(16) [[CINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[DINSTANCE]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    [[CALL3:%.*]] = call ptr @_ZN5test11DC1Ev(ptr nonnull align 8 dereferenceable(8) [[DINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[EINSTANCE]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    [[CALL4:%.*]] = call ptr @_ZN5test11EC1Ev(ptr nonnull align 8 dereferenceable(16) [[EINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.start.p0(ptr [[EARRAY]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[EARRAY]], i8 0, i64 16, i1 false)
// CHECK-BOTHAUTH-NEXT:    [[CALL5:%.*]] = call ptr @_ZN5test11EC1Ev(ptr nonnull align 8 dereferenceable(16) [[EARRAY]])
// CHECK-BOTHAUTH-NEXT:    [[CALL6:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[AINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[CALL7:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[BINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[TMP0:%.*]] = icmp eq ptr [[CINSTANCE]], null
// CHECK-BOTHAUTH-NEXT:    br i1 [[TMP0]], label %[[CAST_END:.*]], label %[[CAST_NOTNULL:.*]]
// CHECK-BOTHAUTH:       [[CAST_NOTNULL]]:
// CHECK-BOTHAUTH-NEXT:    [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CINSTANCE]], i64 8
// CHECK-BOTHAUTH-NEXT:    br label %[[CAST_END]]
// CHECK-BOTHAUTH:       [[CAST_END]]:
// CHECK-BOTHAUTH-NEXT:    [[CAST_RESULT:%.*]] = phi ptr [ [[ADD_PTR]], %[[CAST_NOTNULL]] ], [ null, %[[ENTRY]] ]
// CHECK-BOTHAUTH-NEXT:    [[CALL8:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT]])
// CHECK-BOTHAUTH-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[DINSTANCE]], null
// CHECK-BOTHAUTH-NEXT:    br i1 [[TMP1]], label %[[CAST_END11:.*]], label %[[CAST_NOTNULL9:.*]]
// CHECK-BOTHAUTH:       [[CAST_NOTNULL9]]:
// CHECK-BOTHAUTH-NEXT:    [[VTABLE:%.*]] = load ptr, ptr [[DINSTANCE]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[DINSTANCE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP3:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP2]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP4:%.*]] = ptrtoint ptr [[VTABLE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP5:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP4]], i32 2, i64 [[TMP3]])
// CHECK-BOTHAUTH-NEXT:    [[TMP6:%.*]] = inttoptr i64 [[TMP5]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[VBASE_OFFSET_PTR:%.*]] = getelementptr i8, ptr [[TMP6]], i64 -32
// CHECK-BOTHAUTH-NEXT:    [[VBASE_OFFSET:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR]], align 8
// CHECK-BOTHAUTH-NEXT:    [[ADD_PTR10:%.*]] = getelementptr inbounds i8, ptr [[DINSTANCE]], i64 [[VBASE_OFFSET]]
// CHECK-BOTHAUTH-NEXT:    br label %[[CAST_END11]]
// CHECK-BOTHAUTH:       [[CAST_END11]]:
// CHECK-BOTHAUTH-NEXT:    [[CAST_RESULT12:%.*]] = phi ptr [ [[ADD_PTR10]], %[[CAST_NOTNULL9]] ], [ null, %[[CAST_END]] ]
// CHECK-BOTHAUTH-NEXT:    [[CALL13:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT12]])
// CHECK-BOTHAUTH-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-BOTHAUTH-NEXT:    br i1 [[TMP7]], label %[[CAST_END19:.*]], label %[[CAST_NOTNULL14:.*]]
// CHECK-BOTHAUTH:       [[CAST_NOTNULL14]]:
// CHECK-BOTHAUTH-NEXT:    [[VTABLE15:%.*]] = load ptr, ptr [[EINSTANCE]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP8:%.*]] = ptrtoint ptr [[EINSTANCE]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP9:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP8]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP10:%.*]] = ptrtoint ptr [[VTABLE15]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP11:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP10]], i32 2, i64 [[TMP9]])
// CHECK-BOTHAUTH-NEXT:    [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[VBASE_OFFSET_PTR16:%.*]] = getelementptr i8, ptr [[TMP12]], i64 -32
// CHECK-BOTHAUTH-NEXT:    [[VBASE_OFFSET17:%.*]] = load i64, ptr [[VBASE_OFFSET_PTR16]], align 8
// CHECK-BOTHAUTH-NEXT:    [[ADD_PTR18:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 [[VBASE_OFFSET17]]
// CHECK-BOTHAUTH-NEXT:    br label %[[CAST_END19]]
// CHECK-BOTHAUTH:       [[CAST_END19]]:
// CHECK-BOTHAUTH-NEXT:    [[CAST_RESULT20:%.*]] = phi ptr [ [[ADD_PTR18]], %[[CAST_NOTNULL14]] ], [ null, %[[CAST_END11]] ]
// CHECK-BOTHAUTH-NEXT:    [[CALL21:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT20]])
// CHECK-BOTHAUTH-NEXT:    [[TMP13:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-BOTHAUTH-NEXT:    br i1 [[TMP13]], label %[[CAST_END24:.*]], label %[[CAST_NOTNULL22:.*]]
// CHECK-BOTHAUTH:       [[CAST_NOTNULL22]]:
// CHECK-BOTHAUTH-NEXT:    [[ADD_PTR23:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 8
// CHECK-BOTHAUTH-NEXT:    br label %[[CAST_END24]]
// CHECK-BOTHAUTH:       [[CAST_END24]]:
// CHECK-BOTHAUTH-NEXT:    [[CAST_RESULT25:%.*]] = phi ptr [ [[ADD_PTR23]], %[[CAST_NOTNULL22]] ], [ null, %[[CAST_END19]] ]
// CHECK-BOTHAUTH-NEXT:    [[CALL26:%.*]] = call ptr @_ZN5test11aEPNS_1AE(ptr [[CAST_RESULT25]])
// CHECK-BOTHAUTH-NEXT:    [[CALL27:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[BINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[TMP14:%.*]] = icmp eq ptr [[CINSTANCE]], null
// CHECK-BOTHAUTH-NEXT:    br i1 [[TMP14]], label %[[CAST_END30:.*]], label %[[CAST_NOTNULL28:.*]]
// CHECK-BOTHAUTH:       [[CAST_NOTNULL28]]:
// CHECK-BOTHAUTH-NEXT:    [[ADD_PTR29:%.*]] = getelementptr inbounds i8, ptr [[CINSTANCE]], i64 8
// CHECK-BOTHAUTH-NEXT:    br label %[[CAST_END30]]
// CHECK-BOTHAUTH:       [[CAST_END30]]:
// CHECK-BOTHAUTH-NEXT:    [[CAST_RESULT31:%.*]] = phi ptr [ [[ADD_PTR29]], %[[CAST_NOTNULL28]] ], [ null, %[[CAST_END24]] ]
// CHECK-BOTHAUTH-NEXT:    [[CALL32:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[CAST_RESULT31]])
// CHECK-BOTHAUTH-NEXT:    [[TMP15:%.*]] = icmp eq ptr [[EINSTANCE]], null
// CHECK-BOTHAUTH-NEXT:    br i1 [[TMP15]], label %[[CAST_END35:.*]], label %[[CAST_NOTNULL33:.*]]
// CHECK-BOTHAUTH:       [[CAST_NOTNULL33]]:
// CHECK-BOTHAUTH-NEXT:    [[ADD_PTR34:%.*]] = getelementptr inbounds i8, ptr [[EINSTANCE]], i64 8
// CHECK-BOTHAUTH-NEXT:    br label %[[CAST_END35]]
// CHECK-BOTHAUTH:       [[CAST_END35]]:
// CHECK-BOTHAUTH-NEXT:    [[CAST_RESULT36:%.*]] = phi ptr [ [[ADD_PTR34]], %[[CAST_NOTNULL33]] ], [ null, %[[CAST_END30]] ]
// CHECK-BOTHAUTH-NEXT:    [[CALL37:%.*]] = call ptr @_ZN5test11bEPNS_1BE(ptr [[CAST_RESULT36]])
// CHECK-BOTHAUTH-NEXT:    [[CALL38:%.*]] = call ptr @_ZN5test16b_as_AEPNS_1BE(ptr [[BINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[CALL39:%.*]] = call ptr @_ZN5test11cEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[CALL40:%.*]] = call ptr @_ZN5test16c_as_ZEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[CALL41:%.*]] = call ptr @_ZN5test16c_as_BEPNS_1CE(ptr [[CINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[CALL42:%.*]] = call ptr @_ZN5test11dEPNS_1DE(ptr [[DINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[CALL43:%.*]] = call ptr @_ZN5test11dEPNS_1DE(ptr [[EINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[CALL44:%.*]] = call ptr @_ZN5test16d_as_AEPNS_1DE(ptr [[DINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[CALL45:%.*]] = call ptr @_ZN5test16d_as_AEPNS_1DE(ptr [[EINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[CALL46:%.*]] = call ptr @_ZN5test11eEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[CALL47:%.*]] = call ptr @_ZN5test16e_as_BEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[CALL48:%.*]] = call ptr @_ZN5test16e_as_DEPNS_1EE(ptr [[EINSTANCE]])
// CHECK-BOTHAUTH-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %"struct.test1::E"], ptr [[EARRAY]], i64 0, i64 0
// CHECK-BOTHAUTH-NEXT:    [[VTABLE49:%.*]] = load ptr, ptr [[ARRAYDECAY]], align 8, !tbaa [[TBAA9]]
// CHECK-BOTHAUTH-NEXT:    [[TMP16:%.*]] = ptrtoint ptr [[ARRAYDECAY]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP17:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[TMP16]], i64 48388)
// CHECK-BOTHAUTH-NEXT:    [[TMP18:%.*]] = ptrtoint ptr [[VTABLE49]] to i64
// CHECK-BOTHAUTH-NEXT:    [[TMP19:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[TMP18]], i32 2, i64 [[TMP17]])
// CHECK-BOTHAUTH-NEXT:    [[TMP20:%.*]] = inttoptr i64 [[TMP19]] to ptr
// CHECK-BOTHAUTH-NEXT:    [[TMP21:%.*]] = load volatile i8, ptr [[TMP20]], align 8
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[EARRAY]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[EINSTANCE]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[DINSTANCE]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[CINSTANCE]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[BINSTANCE]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    call void @llvm.lifetime.end.p0(ptr [[AINSTANCE]]) #[[ATTR7]]
// CHECK-BOTHAUTH-NEXT:    ret void
//
void test() {
  A aInstance;
  B bInstance;
  C cInstance;
  D dInstance;
  E eInstance;
  E eArray[] = { E() };
  a(&aInstance);
  a(&bInstance);
  a((B *)&cInstance);
  a(&dInstance);
  a((D *)&eInstance);
  a((B *)&eInstance);
  b(&bInstance);
  b(&cInstance);
  b(&eInstance);
  b_as_A(&bInstance);
  c(&cInstance);
  c_as_Z(&cInstance);
  c_as_B(&cInstance);
  d(&dInstance);
  d(&eInstance);
  d_as_A(&dInstance);
  d_as_A(&eInstance);
  e(&eInstance);
  e_as_B(&eInstance);
  e_as_D(&eInstance);
  (void)__builtin_get_vtable_pointer(eArray);
}
} // namespace test1
//.
// CHECK-NOAUTH: [[META4:![0-9]+]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// CHECK-NOAUTH: [[META5]] = !{!"Simple C++ TBAA"}
// CHECK-NOAUTH: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
// CHECK-NOAUTH: [[META7]] = !{!"p1 _ZTSN5test11AE", [[META8:![0-9]+]], i64 0}
// CHECK-NOAUTH: [[META8]] = !{!"any pointer", [[META4]], i64 0}
// CHECK-NOAUTH: [[TBAA9]] = !{[[META10:![0-9]+]], [[META10]], i64 0}
// CHECK-NOAUTH: [[META10]] = !{!"vtable pointer", [[META5]], i64 0}
// CHECK-NOAUTH: [[TBAA11]] = !{[[META12:![0-9]+]], [[META12]], i64 0}
// CHECK-NOAUTH: [[META12]] = !{!"p1 _ZTSN5test11BE", [[META8]], i64 0}
// CHECK-NOAUTH: [[TBAA13]] = !{[[META14:![0-9]+]], [[META14]], i64 0}
// CHECK-NOAUTH: [[META14]] = !{!"p1 _ZTSN5test11CE", [[META8]], i64 0}
// CHECK-NOAUTH: [[TBAA15]] = !{[[META16:![0-9]+]], [[META16]], i64 0}
// CHECK-NOAUTH: [[META16]] = !{!"p1 _ZTSN5test11DE", [[META8]], i64 0}
// CHECK-NOAUTH: [[TBAA17]] = !{[[META18:![0-9]+]], [[META18]], i64 0}
// CHECK-NOAUTH: [[META18]] = !{!"p1 _ZTSN5test11EE", [[META8]], i64 0}
//.
// CHECK-TYPEAUTH: [[META4:![0-9]+]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// CHECK-TYPEAUTH: [[META5]] = !{!"Simple C++ TBAA"}
// CHECK-TYPEAUTH: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
// CHECK-TYPEAUTH: [[META7]] = !{!"p1 _ZTSN5test11AE", [[META8:![0-9]+]], i64 0}
// CHECK-TYPEAUTH: [[META8]] = !{!"any pointer", [[META4]], i64 0}
// CHECK-TYPEAUTH: [[TBAA9]] = !{[[META10:![0-9]+]], [[META10]], i64 0}
// CHECK-TYPEAUTH: [[META10]] = !{!"vtable pointer", [[META5]], i64 0}
// CHECK-TYPEAUTH: [[TBAA11]] = !{[[META12:![0-9]+]], [[META12]], i64 0}
// CHECK-TYPEAUTH: [[META12]] = !{!"p1 _ZTSN5test11BE", [[META8]], i64 0}
// CHECK-TYPEAUTH: [[TBAA13]] = !{[[META14:![0-9]+]], [[META14]], i64 0}
// CHECK-TYPEAUTH: [[META14]] = !{!"p1 _ZTSN5test11CE", [[META8]], i64 0}
// CHECK-TYPEAUTH: [[TBAA15]] = !{[[META16:![0-9]+]], [[META16]], i64 0}
// CHECK-TYPEAUTH: [[META16]] = !{!"p1 _ZTSN5test11DE", [[META8]], i64 0}
// CHECK-TYPEAUTH: [[TBAA17]] = !{[[META18:![0-9]+]], [[META18]], i64 0}
// CHECK-TYPEAUTH: [[META18]] = !{!"p1 _ZTSN5test11EE", [[META8]], i64 0}
//.
// CHECK-ADDRESSAUTH: [[META4:![0-9]+]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// CHECK-ADDRESSAUTH: [[META5]] = !{!"Simple C++ TBAA"}
// CHECK-ADDRESSAUTH: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
// CHECK-ADDRESSAUTH: [[META7]] = !{!"p1 _ZTSN5test11AE", [[META8:![0-9]+]], i64 0}
// CHECK-ADDRESSAUTH: [[META8]] = !{!"any pointer", [[META4]], i64 0}
// CHECK-ADDRESSAUTH: [[TBAA9]] = !{[[META10:![0-9]+]], [[META10]], i64 0}
// CHECK-ADDRESSAUTH: [[META10]] = !{!"vtable pointer", [[META5]], i64 0}
// CHECK-ADDRESSAUTH: [[TBAA11]] = !{[[META12:![0-9]+]], [[META12]], i64 0}
// CHECK-ADDRESSAUTH: [[META12]] = !{!"p1 _ZTSN5test11BE", [[META8]], i64 0}
// CHECK-ADDRESSAUTH: [[TBAA13]] = !{[[META14:![0-9]+]], [[META14]], i64 0}
// CHECK-ADDRESSAUTH: [[META14]] = !{!"p1 _ZTSN5test11CE", [[META8]], i64 0}
// CHECK-ADDRESSAUTH: [[TBAA15]] = !{[[META16:![0-9]+]], [[META16]], i64 0}
// CHECK-ADDRESSAUTH: [[META16]] = !{!"p1 _ZTSN5test11DE", [[META8]], i64 0}
// CHECK-ADDRESSAUTH: [[TBAA17]] = !{[[META18:![0-9]+]], [[META18]], i64 0}
// CHECK-ADDRESSAUTH: [[META18]] = !{!"p1 _ZTSN5test11EE", [[META8]], i64 0}
//.
// CHECK-BOTHAUTH: [[META4:![0-9]+]] = !{!"omnipotent char", [[META5:![0-9]+]], i64 0}
// CHECK-BOTHAUTH: [[META5]] = !{!"Simple C++ TBAA"}
// CHECK-BOTHAUTH: [[TBAA6]] = !{[[META7:![0-9]+]], [[META7]], i64 0}
// CHECK-BOTHAUTH: [[META7]] = !{!"p1 _ZTSN5test11AE", [[META8:![0-9]+]], i64 0}
// CHECK-BOTHAUTH: [[META8]] = !{!"any pointer", [[META4]], i64 0}
// CHECK-BOTHAUTH: [[TBAA9]] = !{[[META10:![0-9]+]], [[META10]], i64 0}
// CHECK-BOTHAUTH: [[META10]] = !{!"vtable pointer", [[META5]], i64 0}
// CHECK-BOTHAUTH: [[TBAA11]] = !{[[META12:![0-9]+]], [[META12]], i64 0}
// CHECK-BOTHAUTH: [[META12]] = !{!"p1 _ZTSN5test11BE", [[META8]], i64 0}
// CHECK-BOTHAUTH: [[TBAA13]] = !{[[META14:![0-9]+]], [[META14]], i64 0}
// CHECK-BOTHAUTH: [[META14]] = !{!"p1 _ZTSN5test11CE", [[META8]], i64 0}
// CHECK-BOTHAUTH: [[TBAA15]] = !{[[META16:![0-9]+]], [[META16]], i64 0}
// CHECK-BOTHAUTH: [[META16]] = !{!"p1 _ZTSN5test11DE", [[META8]], i64 0}
// CHECK-BOTHAUTH: [[TBAA17]] = !{[[META18:![0-9]+]], [[META18]], i64 0}
// CHECK-BOTHAUTH: [[META18]] = !{!"p1 _ZTSN5test11EE", [[META8]], i64 0}
//.
