[clang] 85255a0 - [C++][Sema] Ignore top-level qualifiers in casts

Ole Strohm via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 5 04:28:32 PDT 2021


Author: Ole Strohm
Date: 2021-07-05T12:22:08+01:00
New Revision: 85255a04e5729c03214c51177aa885c055f3e242

URL: https://github.com/llvm/llvm-project/commit/85255a04e5729c03214c51177aa885c055f3e242
DIFF: https://github.com/llvm/llvm-project/commit/85255a04e5729c03214c51177aa885c055f3e242.diff

LOG: [C++][Sema] Ignore top-level qualifiers in casts

Ignore top-level qualifiers in casts, which fixes issues in reinterpret_cast.

This rule comes from [expr.type]/8.2.2 which explains that casting to a
pr-qualified type should actually cast to the unqualified type. In C++
this is only done for types that aren't classes or arrays.

Fixes: PR49221

Reviewed By: Anastasia

Differential Revision: https://reviews.llvm.org/D102689

Added: 
    

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 1e2113b58f81..869e414c7095 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -61,6 +61,15 @@ namespace {
         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();

diff  --git a/clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp b/clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
index 430223f337b7..3771e1b1e090 100644
--- a/clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
+++ b/clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
@@ -11,6 +11,17 @@ void bar(global int2 *in) {
   //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);

diff  --git a/clang/test/SemaCXX/reinterpret-cast.cpp b/clang/test/SemaCXX/reinterpret-cast.cpp
index 6cc46d8b0d9f..6a4bc9166544 100644
--- a/clang/test/SemaCXX/reinterpret-cast.cpp
+++ b/clang/test/SemaCXX/reinterpret-cast.cpp
@@ -25,6 +25,9 @@ void self_conversion()
   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 constness()
   (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()

diff  --git a/clang/test/SemaCXX/warn-reinterpret-base-class.cpp b/clang/test/SemaCXX/warn-reinterpret-base-class.cpp
index d73b4872117f..55bc777ce2e0 100644
--- a/clang/test/SemaCXX/warn-reinterpret-base-class.cpp
+++ b/clang/test/SemaCXX/warn-reinterpret-base-class.cpp
@@ -298,7 +298,7 @@ void 
diff erent_subobject_downcast(E *e, F *f, A *a) {
 #endif
   (void)reinterpret_cast<H *>(a);
 
-  // expected-warning at +2 {{'reinterpret_cast' to class 'L' (aka 'const F *volatile') from its base at non-zero offset 'E *' behaves 
diff erently from 'static_cast'}}
+  // expected-warning at +2 {{'reinterpret_cast' to class 'K' (aka 'const F *') from its base at non-zero offset 'E *' behaves 
diff erently from 'static_cast'}}
   // expected-note at +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"

diff  --git a/clang/test/SemaOpenCLCXX/addrspace_cast.clcpp b/clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
index 37cf1bc1d296..bbe6b4495ff0 100644
--- a/clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
+++ b/clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
@@ -22,7 +22,7 @@ template <class T>
 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() {

diff  --git a/clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp b/clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
index 0e3d74e5bc2d..862f49bf024e 100644
--- a/clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
+++ b/clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -4,6 +4,11 @@ typedef int int2 __attribute__((ext_vector_type(2)));
 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 @@ kernel void foo() {
   auto i2_to_i = reinterpret_cast<int>(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of 
diff erent 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;


        


More information about the cfe-commits mailing list