[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