[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