diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -2481,7 +2481,11 @@ if (IsAddressSpaceConversion(SrcType, DestType)) { Kind = CK_AddressSpaceConversion; assert(SrcType->isPointerType() && DestType->isPointerType()); + // C++ 7.6.1.10: The reinterpret_cast operator is only forbidden from + // casting away constness or volatile qualifiers. We permit changing the + // the address space qualifier in C++ while OpenCL uses more strict rules. if (!CStyle && + (Self.getLangOpts().OpenCL || Self.getLangOpts().OpenCLCPlusPlus) && !DestType->getPointeeType().getQualifiers().isAddressSpaceSupersetOf( SrcType->getPointeeType().getQualifiers())) { SuccessResult = TC_Failed; diff --git a/clang/test/SemaCXX/address-space-conversion.cpp b/clang/test/SemaCXX/address-space-conversion.cpp --- a/clang/test/SemaCXX/address-space-conversion.cpp +++ b/clang/test/SemaCXX/address-space-conversion.cpp @@ -132,23 +132,23 @@ A_ptr ap, A_ptr_1 ap1, A_ptr_2 ap2, B_ptr bp, B_ptr_1 bp1, B_ptr_2 bp2, const void __attribute__((address_space(1))) * cvp1) { - // reinterpret_cast can't be used to cast to a different address space unless they are matching (i.e. overlapping). - (void)reinterpret_cast(ap1); // expected-error{{reinterpret_cast from 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') to 'A_ptr' (aka 'A *') is not allowed}} - (void)reinterpret_cast(ap2); // expected-error{{reinterpret_cast from 'A_ptr_2' (aka '__attribute__((address_space(2))) A *') to 'A_ptr' (aka 'A *') is not allowed}} + // reinterpret_cast can be used to cast to a different address space. + (void)reinterpret_cast(ap1); + (void)reinterpret_cast(ap2); (void)reinterpret_cast(bp); - (void)reinterpret_cast(bp1); // expected-error{{reinterpret_cast from 'B_ptr_1' (aka '__attribute__((address_space(1))) B *') to 'A_ptr' (aka 'A *') is not allowed}} - (void)reinterpret_cast(bp2); // expected-error{{reinterpret_cast from 'B_ptr_2' (aka '__attribute__((address_space(2))) B *') to 'A_ptr' (aka 'A *') is not allowed}} + (void)reinterpret_cast(bp1); + (void)reinterpret_cast(bp2); (void)reinterpret_cast(vp); - (void)reinterpret_cast(vp1); // expected-error{{reinterpret_cast from 'void_ptr_1' (aka '__attribute__((address_space(1))) void *') to 'A_ptr' (aka 'A *') is not allowed}} - (void)reinterpret_cast(vp2); // expected-error{{reinterpret_cast from 'void_ptr_2' (aka '__attribute__((address_space(2))) void *') to 'A_ptr' (aka 'A *') is not allowed}} - (void)reinterpret_cast(ap); // expected-error{{reinterpret_cast from 'A_ptr' (aka 'A *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} - (void)reinterpret_cast(ap2); // expected-error{{reinterpret_cast from 'A_ptr_2' (aka '__attribute__((address_space(2))) A *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} - (void)reinterpret_cast(bp); // expected-error{{reinterpret_cast from 'B_ptr' (aka 'B *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} + (void)reinterpret_cast(vp1); + (void)reinterpret_cast(vp2); + (void)reinterpret_cast(ap); + (void)reinterpret_cast(ap2); + (void)reinterpret_cast(bp); (void)reinterpret_cast(bp1); - (void)reinterpret_cast(bp2); // expected-error{{reinterpret_cast from 'B_ptr_2' (aka '__attribute__((address_space(2))) B *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} - (void)reinterpret_cast(vp); // expected-error{{reinterpret_cast from 'void_ptr' (aka 'void *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} + (void)reinterpret_cast(bp2); + (void)reinterpret_cast(vp); (void)reinterpret_cast(vp1); - (void)reinterpret_cast(vp2); // expected-error{{reinterpret_cast from 'void_ptr_2' (aka '__attribute__((address_space(2))) void *') to 'A_ptr_1' (aka '__attribute__((address_space(1))) A *') is not allowed}} + (void)reinterpret_cast(vp2); // ... but don't try to cast away constness! (void)reinterpret_cast(cvp1); // expected-error{{casts away qualifiers}}