diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -61,6 +61,15 @@ 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 --- a/clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp +++ b/clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp @@ -11,6 +11,17 @@ //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32> auto i2 = reinterpret_cast(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(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(i4); diff --git a/clang/test/SemaCXX/reinterpret-cast.cpp b/clang/test/SemaCXX/reinterpret-cast.cpp --- a/clang/test/SemaCXX/reinterpret-cast.cpp +++ b/clang/test/SemaCXX/reinterpret-cast.cpp @@ -25,6 +25,9 @@ const int structure::*psi = 0; (void)reinterpret_cast(psi); + const int ci = 0; + (void)reinterpret_cast(i); + structure s; (void)reinterpret_cast(s); // expected-error {{reinterpret_cast from 'structure' to 'structure' is not allowed}} @@ -68,6 +71,16 @@ (void)reinterpret_cast(ip); // Valid: T*** -> T2 const* const* const* (void)reinterpret_cast(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(i); + // Valid: T* -> T* (top level const is ignored) + (void)reinterpret_cast(ip); } void fnptrs() diff --git a/clang/test/SemaCXX/warn-reinterpret-base-class.cpp b/clang/test/SemaCXX/warn-reinterpret-base-class.cpp --- a/clang/test/SemaCXX/warn-reinterpret-base-class.cpp +++ b/clang/test/SemaCXX/warn-reinterpret-base-class.cpp @@ -298,7 +298,7 @@ #endif (void)reinterpret_cast(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(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 --- a/clang/test/SemaOpenCLCXX/addrspace_cast.clcpp +++ b/clang/test/SemaOpenCLCXX/addrspace_cast.clcpp @@ -22,7 +22,7 @@ void test_temp(__global int *par) { T *var1 = addrspace_cast(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(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int' is not allowed}} + T var3 = addrspace_cast(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 --- a/clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp +++ b/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(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(i2); + // Testing reinterpret_cast with address spaces. + __private short s; + auto s2 = reinterpret_cast<__private short>(s); + auto s3 = reinterpret_cast(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;