[PATCH] D151087: [Clang] Permit address space casts with 'reinterpret_cast' in C++
Joseph Huber via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon May 22 06:00:42 PDT 2023
jhuber6 created this revision.
jhuber6 added reviewers: rjmccall, ebevhan, jdoerfert, JonChesterfield, aaron.ballman.
Herald added subscribers: arichardson, Anastasia.
Herald added a project: All.
jhuber6 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Previously, D58346 <https://reviews.llvm.org/D58346> changed the rules to not permit address space casts
in C++. The cited reason was that `reinterpret_cast` is not allowed to
remove qualifiers, however the standard only explicitly says that
`const` and `volatile` qualifiers cannot be removed, see
http://eel.is/c++draft/expr.reinterpret.cast#7. The current behaviour is
suboptimal as it means there is no way in C++ to change address spaces
and we need to rely on unsafe C style casts that aren't permitted by
many styles. This patch changes the handling to only apply to OpenCL.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D151087
Files:
clang/lib/Sema/SemaCast.cpp
clang/test/SemaCXX/address-space-conversion.cpp
Index: clang/test/SemaCXX/address-space-conversion.cpp
===================================================================
--- clang/test/SemaCXX/address-space-conversion.cpp
+++ 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<A_ptr>(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<A_ptr>(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<A_ptr>(ap1);
+ (void)reinterpret_cast<A_ptr>(ap2);
(void)reinterpret_cast<A_ptr>(bp);
- (void)reinterpret_cast<A_ptr>(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<A_ptr>(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<A_ptr>(bp1);
+ (void)reinterpret_cast<A_ptr>(bp2);
(void)reinterpret_cast<A_ptr>(vp);
- (void)reinterpret_cast<A_ptr>(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<A_ptr>(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<A_ptr_1>(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<A_ptr_1>(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<A_ptr_1>(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<A_ptr>(vp1);
+ (void)reinterpret_cast<A_ptr>(vp2);
+ (void)reinterpret_cast<A_ptr_1>(ap);
+ (void)reinterpret_cast<A_ptr_1>(ap2);
+ (void)reinterpret_cast<A_ptr_1>(bp);
(void)reinterpret_cast<A_ptr_1>(bp1);
- (void)reinterpret_cast<A_ptr_1>(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<A_ptr_1>(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<A_ptr_1>(bp2);
+ (void)reinterpret_cast<A_ptr_1>(vp);
(void)reinterpret_cast<A_ptr_1>(vp1);
- (void)reinterpret_cast<A_ptr_1>(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<A_ptr_1>(vp2);
// ... but don't try to cast away constness!
(void)reinterpret_cast<A_ptr_2>(cvp1); // expected-error{{casts away qualifiers}}
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ 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;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D151087.524263.patch
Type: text/x-patch
Size: 4536 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230522/656730d1/attachment.bin>
More information about the cfe-commits
mailing list