Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -5230,8 +5230,28 @@ // If the argument doesn't match, perform a bitcast to coerce it. This // can happen due to trivial type mismatches. if (FirstIRArg < IRFuncTy->getNumParams() && - V->getType() != IRFuncTy->getParamType(FirstIRArg)) + V->getType() != IRFuncTy->getParamType(FirstIRArg)) { + auto VTy = V->getType(); + auto IRTy = IRFuncTy->getParamType(FirstIRArg); + + if (VTy->isPointerTy() && + VTy->getPointerAddressSpace() != IRTy->getPointerAddressSpace()) { + // In the case of targets that use a non-default address space for + // globals it is possible to get a mismatch between the AST address + // space of type_info formals and the IR type of type_info actuals. + auto Ty = info_it->type.getTypePtr()->getPointeeType(); + if (auto CD = Ty->getAsCXXRecordDecl()) { + if (CD->isInStdNamespace() && CD->getName() == "type_info") + V = Builder.CreateAddrSpaceCast(V, IRTy); + else + llvm_unreachable("Unexpected address space mismatch."); + } + } else { + // If the argument doesn't match, perform a bitcast to coerce it. + // This can happen due to trivial type mismatches. V = Builder.CreateBitCast(V, IRFuncTy->getParamType(FirstIRArg)); + } + } if (ArgHasMaybeUndefAttr) V = Builder.CreateFreeze(V); Index: clang/lib/CodeGen/CGExprCXX.cpp =================================================================== --- clang/lib/CodeGen/CGExprCXX.cpp +++ clang/lib/CodeGen/CGExprCXX.cpp @@ -2194,7 +2194,7 @@ } llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { - llvm::Type *PtrTy = llvm::PointerType::getUnqual(getLLVMContext()); + llvm::Type *PtrTy = CGM.GlobalsInt8PtrTy; if (E->isTypeOperand()) { llvm::Constant *TypeInfo = Index: clang/lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- clang/lib/CodeGen/ItaniumCXXABI.cpp +++ clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1444,8 +1444,8 @@ llvm::Type *StdTypeInfoPtrTy) { auto *ClassDecl = cast(SrcRecordTy->castAs()->getDecl()); - llvm::Value *Value = CGF.GetVTablePtr( - ThisPtr, llvm::PointerType::getUnqual(CGF.getLLVMContext()), ClassDecl); + llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy, + ClassDecl); if (CGM.getItaniumVTableContext().isRelativeLayout()) { // Load the type info. Index: clang/test/CodeGenCXX/typeid-cxx11-with-address-space.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/typeid-cxx11-with-address-space.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -std=c++11 -o - | FileCheck %s +#include + +namespace Test1 { + +struct Item { + const std::type_info &ti; + const char *name; + void *(*make)(); +}; + +template void *make_impl() { return new T; } +template constexpr Item item(const char *name) { + return { typeid(T), name, make_impl }; +} + +struct A { virtual ~A(); }; +struct B : virtual A {}; +struct C { int n; }; + +// CHECK: @_ZN5Test15itemsE ={{.*}} constant [4 x {{.*}}] [{{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr), {{.*}} @_ZN5Test19make_implINS_1AEEEPvv {{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11BE to ptr), {{.*}} @_ZN5Test19make_implINS_1BEEEPvv {{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11CE to ptr), {{.*}} @_ZN5Test19make_implINS_1CEEEPvv {{.*}} ptr addrspacecast (ptr addrspace(1) @_ZTIi to ptr), {{.*}} @_ZN5Test19make_implIiEEPvv }] +extern constexpr Item items[] = { + item("A"), item("B"), item("C"), item("int") +}; + +// CHECK: @_ZN5Test11xE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr), align 8 +constexpr auto &x = items[0].ti; + +// CHECK: @_ZN5Test11yE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11BE to ptr), align 8 +constexpr auto &y = typeid(B{}); + +} Index: clang/test/CodeGenCXX/typeid-with-address-space.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/typeid-with-address-space.cpp @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -fcxx-exceptions -fexceptions -o - | FileCheck %s +#include + +namespace Test1 { + +// PR7400 +struct A { virtual void f(); }; + +// CHECK: @_ZN5Test16int_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIi to ptr), align 8 +const std::type_info &int_ti = typeid(int); + +// CHECK: @_ZN5Test14A_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIN5Test11AE to ptr), align 8 +const std::type_info &A_ti = typeid(const volatile A &); + +volatile char c; + +// CHECK: @_ZN5Test14c_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIc to ptr), align 8 +const std::type_info &c_ti = typeid(c); + +extern const double &d; + +// CHECK: @_ZN5Test14d_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTId to ptr), align 8 +const std::type_info &d_ti = typeid(d); + +extern A &a; + +// CHECK: @_ZN5Test14a_tiE ={{.*}} global +const std::type_info &a_ti = typeid(a); + +// CHECK: @_ZN5Test18A10_c_tiE ={{.*}} constant ptr addrspacecast (ptr addrspace(1) @_ZTIA10_c to ptr), align 8 +const std::type_info &A10_c_ti = typeid(char const[10]); + +// CHECK-LABEL: define{{.*}} ptr @_ZN5Test11fEv +// CHECK-SAME: personality ptr @__gxx_personality_v0 +const char *f() { + try { + // CHECK: br i1 + // CHECK: invoke void @__cxa_bad_typeid() [[NR:#[0-9]+]] + return typeid(*static_cast(0)).name(); + } catch (...) { + // CHECK: landingpad { ptr, i32 } + // CHECK-NEXT: catch ptr null + } + + return 0; +} + +} + +// CHECK: attributes [[NR]] = { noreturn } Index: clang/test/CodeGenCXX/typeinfo =================================================================== --- clang/test/CodeGenCXX/typeinfo +++ clang/test/CodeGenCXX/typeinfo @@ -10,6 +10,14 @@ bool operator!=(const type_info& __arg) const { return !operator==(__arg); } + + bool before(const type_info& __arg) const { + return __name < __arg.__name; + } + + unsigned long hash_code() const { + return reinterpret_cast(__name); + } protected: const char *__name; }; Index: clang/test/CodeGenCXX/typeinfo-with-address-space.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/typeinfo-with-address-space.cpp @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -I%S %s -triple amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck %s -check-prefix=AS +// RUN: %clang_cc1 -I%S %s -triple x86_64-linux-gnu -emit-llvm -o - | FileCheck %s -check-prefix=NO-AS +#include + +class A { + virtual void f() = 0; +}; + +class B : A { + void f() override; +}; + +// AS: @_ZTISt9type_info = external addrspace(1) constant ptr addrspace(1) +// NO-AS: @_ZTISt9type_info = external constant ptr +// AS: @_ZTIi = external addrspace(1) constant ptr addrspace(1) +// NO-AS: @_ZTIi = external constant ptr +// AS: @_ZTVN10__cxxabiv117__class_type_infoE = external addrspace(1) global ptr addrspace(1) +// NO-AS: @_ZTVN10__cxxabiv117__class_type_infoE = external global ptr +// AS: @_ZTS1A = linkonce_odr addrspace(1) constant [3 x i8] c"1A\00", comdat, align 1 +// NO-AS: @_ZTS1A = linkonce_odr constant [3 x i8] c"1A\00", comdat, align 1 +// AS: @_ZTI1A = linkonce_odr addrspace(1) constant { ptr addrspace(1), ptr addrspace(1) } { ptr addrspace(1) getelementptr inbounds (ptr addrspace(1), ptr addrspace(1) @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr addrspace(1) @_ZTS1A }, comdat, align 8 +// NO-AS: @_ZTI1A = linkonce_odr constant { ptr, ptr } { ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), ptr @_ZTS1A }, comdat, align 8 +// AS: @_ZTIf = external addrspace(1) constant ptr addrspace(1) +// NO-AS: @_ZTIf = external constant ptr + +unsigned long Fn(B& b) { +// AS: %3 = addrspacecast ptr addrspace(1) %2 to ptr +// AS-NEXT: %call = call noundef zeroext i1 @_ZNKSt9type_infoeqERKS_(ptr {{.*}} addrspacecast (ptr addrspace(1) @_ZTISt9type_info to ptr), ptr {{.*}} %3) +// NO-AS: %call = call noundef zeroext i1 @_ZNKSt9type_infoeqERKS_(ptr {{.*}} @_ZTISt9type_info, ptr {{.*}} %2) + if (typeid(std::type_info) == typeid(b)) + return 42; +// AS: %7 = addrspacecast ptr addrspace(1) %6 to ptr +// AS-NEXT: %call2 = call noundef zeroext i1 @_ZNKSt9type_infoneERKS_(ptr {{.*}} addrspacecast (ptr addrspace(1) @_ZTIi to ptr), ptr {{.*}} %7) +// NO-AS: %call2 = call noundef zeroext i1 @_ZNKSt9type_infoneERKS_(ptr {{.*}} @_ZTIi, ptr {{.*}} %5) + if (typeid(int) != typeid(b)) + return 1712; +// AS: %11 = addrspacecast ptr addrspace(1) %10 to ptr +// AS-NEXT: %call7 = call noundef ptr @_ZNKSt9type_info4nameEv(ptr {{.*}} %11) +// NO-AS: %call7 = call noundef ptr @_ZNKSt9type_info4nameEv(ptr {{.*}} %8) + if (typeid(A).name() == typeid(b).name()) + return 0; +// AS: %15 = addrspacecast ptr addrspace(1) %14 to ptr +// AS-NEXT: %call11 = call noundef zeroext i1 @_ZNKSt9type_info6beforeERKS_(ptr {{.*}} %15, ptr {{.*}} addrspacecast (ptr addrspace(1) @_ZTIf to ptr)) +// NO-AS: %call11 = call noundef zeroext i1 @_ZNKSt9type_info6beforeERKS_(ptr {{.*}} %11, ptr {{.*}} @_ZTIf) + if (typeid(b).before(typeid(float))) + return 1; +// AS: %19 = addrspacecast ptr addrspace(1) %18 to ptr +// AS-NEXT: %call15 = call noundef i64 @_ZNKSt9type_info9hash_codeEv(ptr {{.*}} %19) +// NO-AS: %call15 = call noundef i64 @_ZNKSt9type_info9hash_codeEv(ptr {{.*}} %14) + return typeid(b).hash_code(); +}