olestrohm created this revision.
olestrohm added reviewers: Anastasia, svenvh.
olestrohm added a project: clang.
Herald added subscribers: ldrumm, yaxunl.
olestrohm requested review of this revision.
Herald added a subscriber: cfe-commits.

This fixes two issues with reinterpret_cast in C++ for OpenCL and adds tests to 
make sure they both pass without errors, and generate the correct code.

Reinterpret_cast can only convert a type to itself if it is an integral type 
(or pointer or reference or vectors), so I didn't include any exceptions for 
opencl types.
Not even float can be converted to itself, so I don't think it makes sense to 
allow this for any opencl types unlesss you think some of them fit the integral 
restriction.

Fixes: https://bugs.llvm.org/show_bug.cgi?id=47977 and 
https://bugs.llvm.org/show_bug.cgi?id=49221


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D101519

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaCast.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp

Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===================================================================
--- /dev/null
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+
+kernel void foo() {
+  long x;
+  auto x2 = reinterpret_cast<int2>(x);
+  int2 y;
+  auto y2 = reinterpret_cast<long>(y);
+  auto y3 = reinterpret_cast<int>(y); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
+
+  __private int i;
+  auto i2 = reinterpret_cast<__private int>(i);
+  auto i3 = reinterpret_cast<decltype(i)>(i);
+
+  reserve_id_t z;
+  auto z2 = reinterpret_cast<reserve_id_t>(z); // expected-error{{reinterpret_cast from 'reserve_id_t' to 'reserve_id_t' is not allowed}}
+}
Index: clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
@@ -0,0 +1,15 @@
+//RUN: %clang_cc1 %s -triple spir -emit-llvm -O0 -o - | FileCheck %s
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+
+//CHECK-LABEL: define{{.*}} spir_func void @_Z3barPU3AS1Dv2_i
+void bar(global int2 *vec) {
+  //CHECK: load i32, i32* %x, align 4
+  //CHECK: store i32 %{{[0-9]+}}, i32* %y, align 4
+  int x;
+  auto y = reinterpret_cast<__private int>(x);
+  //CHECK: bitcast <2 x i32> %{{[0-9]+}} to i64
+  auto lv = reinterpret_cast<long>(vec[0]);
+  //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32>
+  auto vec0 = reinterpret_cast<int2>(lv);
+}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -7358,6 +7358,25 @@
          matSrcType->getNumColumns() == matDestType->getNumColumns();
 }
 
+bool Sema::areVectorTypesSameSize(QualType srcTy, QualType destTy) {
+  assert(destTy->isVectorType() || srcTy->isVectorType());
+
+  uint64_t srcLen, destLen;
+  QualType srcEltTy, destEltTy;
+  if (!breakDownVectorType(srcTy, srcLen, srcEltTy))
+    return false;
+  if (!breakDownVectorType(destTy, destLen, destEltTy))
+    return false;
+
+  // ASTContext::getTypeSize will return the size rounded up to a
+  // power of 2, so instead of using that, we need to use the raw
+  // element size multiplied by the element count.
+  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
+  uint64_t destEltSize = Context.getTypeSize(destEltTy);
+
+  return (srcLen * srcEltSize == destLen * destEltSize);
+}
+
 /// Are the two types lax-compatible vector types?  That is, given
 /// that one of them is a vector, do they have equal storage sizes,
 /// where the storage size is the number of elements times the element
@@ -7376,18 +7395,7 @@
   if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
   if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
 
-  uint64_t srcLen, destLen;
-  QualType srcEltTy, destEltTy;
-  if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
-  if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
-
-  // ASTContext::getTypeSize will return the size rounded up to a
-  // power of 2, so instead of using that, we need to use the raw
-  // element size multiplied by the element count.
-  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
-  uint64_t destEltSize = Context.getTypeSize(destEltTy);
-
-  return (srcLen * srcEltSize == destLen * destEltSize);
+  return areVectorTypesSameSize(srcTy, destTy);
 }
 
 /// Is this a legal conversion between two types, one of which is
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2328,6 +2328,15 @@
       return TC_Success;
     }
 
+    if (Self.LangOpts.OpenCL && !CStyle) {
+      if (DestType->isExtVectorType() || SrcType->isExtVectorType()) {
+        if (Self.areVectorTypesSameSize(SrcType, DestType)) {
+          Kind = CK_BitCast;
+          return TC_Success;
+        }
+      }
+    }
+
     // Otherwise, pick a reasonable diagnostic.
     if (!destIsVector)
       msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
@@ -2339,7 +2348,10 @@
     return TC_Failed;
   }
 
-  if (SrcType == DestType) {
+  if (SrcType == DestType ||
+      (Self.LangOpts.OpenCL &&
+        Self.Context.removeAddrSpaceQualType(SrcType) ==
+          Self.Context.removeAddrSpaceQualType(DestType))) {
     // C++ 5.2.10p2 has a note that mentions that, subject to all other
     // restrictions, a cast to the same type is allowed so long as it does not
     // cast away constness. In C++98, the intent was not entirely clear here,
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -11662,6 +11662,7 @@
 
   bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy);
 
+  bool areVectorTypesSameSize(QualType srcType, QualType destType);
   bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
   bool isLaxVectorConversion(QualType srcType, QualType destType);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to