olestrohm updated this revision to Diff 350560.
olestrohm retitled this revision from "[C++4OpenCL] Allow address space 
conversion in reinterpret_cast" to "[C++] Ignore top-level qualifiers in casts".
olestrohm edited the summary of this revision.
olestrohm added a comment.

I've added a check in the constructor for CastOperator that removes qualifiers 
for non-class, non-array types.
I had to add a check for ObjectiveC, since they seem to use qualifiers for a 
lot of language features,
but maybe a better solution would be to remove specific qualifiers instead?

This actually didn't cause that many changes in behaviour or error messages, 
maybe because the other casts
already have checks for this, but there was one change in a C++ test that looks 
a little strange after this patch,
but maybe that's alright.

Hopefully this is makes sense, but do suggest changes to the approach if you 
think there is a better one.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102689/new/

https://reviews.llvm.org/D102689

Files:
  clang/lib/Sema/SemaCast.cpp
  clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
  clang/test/SemaCXX/reinterpret-cast.cpp
  clang/test/SemaCXX/warn-reinterpret-base-class.cpp
  clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp

Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===================================================================
--- clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -4,6 +4,11 @@
 typedef int int3 __attribute__((ext_vector_type(3)));
 typedef int int4 __attribute__((ext_vector_type(4)));
 
+struct X {};
+
+__global int g = 0;
+__global int *__global g_ptr = &g;
+
 kernel void foo() {
   // Testing conversions between vectors and vectors/scalars
   long l1;
@@ -13,6 +18,18 @@
   auto i2_to_i = reinterpret_cast<int>(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
   auto i2_to_i2 = reinterpret_cast<int2>(i2);
 
+  // Testing reinterpret_cast with address spaces.
+  __private short s;
+  auto s2 = reinterpret_cast<__private short>(s);
+  auto s3 = reinterpret_cast<decltype(s)>(s);
+  auto s4 = reinterpret_cast<__global short>(s);
+
+  __private X x;
+  auto x2 = reinterpret_cast<__private X>(x); // expected-error{{reinterpret_cast from '__private X' to '__private X' is not allowed}}
+
+  auto ptr = reinterpret_cast<__global int* __private>(g_ptr);
+  (void)reinterpret_cast<__private int* __private>(g_ptr); // expected-error{{reinterpret_cast from '__global int *' to '__private int *' is not allowed}}
+
   // Only integral types (and pointer/references) can be reinterpret casted to themselves.
   // Currently this does not include any opencl types.
   reserve_id_t r_id1;
Index: clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
===================================================================
--- clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
@@ -22,7 +22,7 @@
 void test_temp(__global int *par) {
   T *var1 = addrspace_cast<T *>(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int *' converts between mismatching address spaces}}
   __private T *var2 = addrspace_cast<__private T *>(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int *' converts between mismatching address spaces}}
-  T var3 = addrspace_cast<T>(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int' is not allowed}}
+  T var3 = addrspace_cast<T>(par); //expected-error{{addrspace_cast from '__global int *__private' to 'int' is not allowed}}
 }
 
 void bar() {
Index: clang/test/SemaCXX/warn-reinterpret-base-class.cpp
===================================================================
--- clang/test/SemaCXX/warn-reinterpret-base-class.cpp
+++ clang/test/SemaCXX/warn-reinterpret-base-class.cpp
@@ -298,7 +298,7 @@
 #endif
   (void)reinterpret_cast<H *>(a);
 
-  // expected-warning@+2 {{'reinterpret_cast' to class 'L' (aka 'const F *volatile') from its base at non-zero offset 'E *' behaves differently from 'static_cast'}}
+  // expected-warning@+2 {{'reinterpret_cast' to class 'K' (aka 'const F *') from its base at non-zero offset 'E *' behaves differently from 'static_cast'}}
   // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}}
   (void)reinterpret_cast<L>(e);
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast"
Index: clang/test/SemaCXX/reinterpret-cast.cpp
===================================================================
--- clang/test/SemaCXX/reinterpret-cast.cpp
+++ clang/test/SemaCXX/reinterpret-cast.cpp
@@ -25,6 +25,9 @@
   const int structure::*psi = 0;
   (void)reinterpret_cast<const int structure::*>(psi);
 
+  const int ci = 0;
+  (void)reinterpret_cast<const int>(i);
+
   structure s;
   (void)reinterpret_cast<structure>(s); // expected-error {{reinterpret_cast from 'structure' to 'structure' is not allowed}}
 
@@ -68,6 +71,16 @@
   (void)reinterpret_cast<int const*>(ip);
   // Valid: T*** -> T2 const* const* const*
   (void)reinterpret_cast<int const* const* const*>(ipppc);
+
+  // C++ [expr.type]/8.2.2:
+  //   If a pr-value initially has the type cv-T, where T is a
+  //   cv-unqualified non-class, non-array type, the type of the
+  //   expression is adjusted to T prior to any further analysis.
+  int i = 0;
+  // Valid: T -> T (top level const is ignored)
+  (void)reinterpret_cast<const int>(i);
+  // Valid: T* -> T* (top level const is ignored)
+  (void)reinterpret_cast<int *const>(ip);
 }
 
 void fnptrs()
Index: clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
===================================================================
--- clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
+++ clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
@@ -11,6 +11,17 @@
   //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32>
   auto i2 = reinterpret_cast<int2>(l);
 
+  __private short s1;
+  // CHECK: %{{[0-9]+}} = load i16, i16* %s1, align 2
+  // CHECK-NEXT: store i16 %{{[0-9]+}}, i16* %s2, align 2
+  auto s2 = reinterpret_cast<__private short>(s1);
+  // CHECK: %{{[0-9]+}} = load i16, i16* %s1, align 2
+  // CHECK-NEXT: store i16 %{{[0-9]+}}, i16* %s3, align 2
+  auto s3 = reinterpret_cast<decltype(s1)>(s1);
+  // CHECK: %{{[0-9]+}} = load i16, i16* %s1, align 2
+  // CHECK-NEXT: store i16 %{{[0-9]+}}, i16* %s4, align 2
+  auto s4 = reinterpret_cast<__global short>(s1);
+
   int4 i4;
   //CHECK: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64>
   auto l2 = reinterpret_cast<long2>(i4);
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -61,6 +61,14 @@
         ValueKind(Expr::getValueKindForType(destType)),
         Kind(CK_Dependent), IsARCUnbridgedCast(false) {
 
+      // C++ [expr.type]/8.2.2:
+      //   If a pr-value initially has the type cv-T, where T is a
+      //   cv-unqualified non-class, non-array type, the type of the
+      //   expression is adjusted to T prior to any further analysis.
+      if (!S.Context.getLangOpts().ObjC && !DestType->isRecordType() && !DestType->isArrayType()) {
+        DestType = DestType.getUnqualifiedType();
+      }
+
       if (const BuiltinType *placeholder =
             src.get()->getType()->getAsPlaceholderType()) {
         PlaceholderKind = placeholder->getKind();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to