diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4237,14 +4237,21 @@ } // Defer address space conversion to the third conversion. + // FIXME: If PerformImplicitConversion did not try to pass the final + // destination type to every conversion function in here, this would not + // be necessary since the address space conversion would be handled as + // a qualification conversion instead. QualType FromPteeType = From->getType()->getPointeeType(); QualType ToPteeType = ToType->getPointeeType(); QualType NewToType = ToType; if (!FromPteeType.isNull() && !ToPteeType.isNull() && FromPteeType.getAddressSpace() != ToPteeType.getAddressSpace()) { - NewToType = Context.removeAddrSpaceQualType(ToPteeType); - NewToType = Context.getAddrSpaceQualType(NewToType, - FromPteeType.getAddressSpace()); + NewToType = + Context.removeAddrSpaceQualType(ToPteeType.getCanonicalType()); + if (FromPteeType.getAddressSpace() != LangAS::Default) + NewToType = Context.getAddrSpaceQualType( + NewToType, FromPteeType.getAddressSpace()); + if (ToType->isObjCObjectPointerType()) NewToType = Context.getObjCObjectPointerType(NewToType); else if (ToType->isBlockPointerType()) diff --git a/clang/test/CodeGenCXX/address-space-cast.cpp b/clang/test/CodeGenCXX/address-space-cast.cpp --- a/clang/test/CodeGenCXX/address-space-cast.cpp +++ b/clang/test/CodeGenCXX/address-space-cast.cpp @@ -6,6 +6,16 @@ void func_pvoid(__private__ void *x); void func_pint(__private__ int *x); +class Base { +}; + +class Derived : public Base { +}; + +void fn(Derived *p) { + __private__ Base *b = (__private__ Base *)p; +} + void test_cast(char *gen_char_ptr, void *gen_void_ptr, int *gen_int_ptr) { // CHECK: %[[cast:.*]] = addrspacecast i8* %{{.*}} to i8 addrspace(5)* // CHECK-NEXT: store i8 addrspace(5)* %[[cast]]