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); 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/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/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(vec[0]); + //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32> + auto vec0 = reinterpret_cast(lv); +} 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(x); + int2 y; + auto y2 = reinterpret_cast(y); + auto y3 = reinterpret_cast(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(i); + + reserve_id_t z; + auto z2 = reinterpret_cast(z); // expected-error{{reinterpret_cast from 'reserve_id_t' to 'reserve_id_t' is not allowed}} +}