ebevhan created this revision. ebevhan added reviewers: svenvh, rjmccall. Herald added a project: clang. Herald added a subscriber: cfe-commits.
When performing a pointer conversion as the second conversion in an SCS where the conversion is a derived-to-base and the address space of the type wants to change, we need to defer the address space conversion until the third step since we must perform two ImplicitCasts at once otherwise. We do this by repacking the destination type we give to CheckPointerConversion with the source address space. However, this repacking does not take sugar into account, so if the address spaces in question are hidden behind nodes like AttributedType or MacroQualifiedType, it won't work properly. Also, if the source AS is Default, getAddrSpaceQualType fails, since it cannot apply a Default AS. Use the canonical destination type to ensure that we strip any sugar that would get in the way. I'm unsure if this is currently broken upstream without other patches to exploit the behavior, but the fix seems to work for the use case in D62574 <https://reviews.llvm.org/D62574>. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D83325 Files: clang/lib/Sema/SemaExprCXX.cpp clang/test/CodeGenCXX/address-space-cast.cpp Index: clang/test/CodeGenCXX/address-space-cast.cpp =================================================================== --- clang/test/CodeGenCXX/address-space-cast.cpp +++ 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]] Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ 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())
Index: clang/test/CodeGenCXX/address-space-cast.cpp =================================================================== --- clang/test/CodeGenCXX/address-space-cast.cpp +++ 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]] Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ 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())
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits