diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 9 | ||||
-rw-r--r-- | lib/Sema/SemaCXXCast.cpp | 26 | ||||
-rw-r--r-- | test/SemaCXX/vector-casts.cpp | 40 |
3 files changed, 75 insertions, 0 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 807a85560f..b14317eb08 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1518,6 +1518,15 @@ def ext_cast_fn_obj : Extension< "cast between pointer-to-function and pointer-to-object is an extension">; def err_bad_reinterpret_cast_small_int : Error< "cast from pointer to smaller type %2 loses information">; +def err_bad_cxx_cast_vector_to_scalar_different_size : Error< + "%select{||reinterpret_cast||C-style cast|}0 from vector %1 " + "to scalar %2 of different size">; +def err_bad_cxx_cast_scalar_to_vector_different_size : Error< + "%select{||reinterpret_cast||C-style cast|}0 from scalar %1 " + "to vector %2 of different size">; +def err_bad_cxx_cast_vector_to_vector_different_size : Error< + "%select{||reinterpret_cast||C-style cast|}0 from vector %1 " + "to vector %2 of different size">; def err_bad_lvalue_to_rvalue_cast : Error< "cannot cast from lvalue of type %1 to rvalue reference type %2; types are " "not compatible">; diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index dbd6c6fde5..f0ae9a1330 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -956,6 +956,32 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, return TC_Success; } + bool destIsVector = DestType->isVectorType(); + bool srcIsVector = SrcType->isVectorType(); + if (srcIsVector || destIsVector) { + bool srcIsScalar = SrcType->isIntegralType() && !SrcType->isEnumeralType(); + bool destIsScalar = + DestType->isIntegralType() && !DestType->isEnumeralType(); + + // Check if this is a cast between a vector and something else. + if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) && + !(srcIsVector && destIsVector)) + return TC_NotApplicable; + + // If both types have the same size, we can successfully cast. + if (Self.Context.getTypeSize(SrcType) == Self.Context.getTypeSize(DestType)) + return TC_Success; + + if (destIsScalar) + msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size; + else if (srcIsScalar) + msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size; + else + msg = diag::err_bad_cxx_cast_vector_to_vector_different_size; + + return TC_Failed; + } + bool destIsPtr = DestType->isPointerType(); bool srcIsPtr = SrcType->isPointerType(); if (!destIsPtr && !srcIsPtr) { diff --git a/test/SemaCXX/vector-casts.cpp b/test/SemaCXX/vector-casts.cpp new file mode 100644 index 0000000000..5b08043545 --- /dev/null +++ b/test/SemaCXX/vector-casts.cpp @@ -0,0 +1,40 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef int __v2si __attribute__((__vector_size__(8))); +typedef short __v4hi __attribute__((__vector_size__(8))); +typedef short __v8hi __attribute__((__vector_size__(16))); + +struct S { }; + +void f() { + __v2si v2si; + __v4hi v4hi; + __v8hi v8hi; + unsigned long long ll; + unsigned char c; + S s; + + (void)reinterpret_cast<__v2si>(v4hi); + (void)(__v2si)v4hi; + (void)reinterpret_cast<__v4hi>(v2si); + (void)(__v4hi)v2si; + (void)reinterpret_cast<unsigned long long>(v2si); + (void)(unsigned long long)v2si; + (void)reinterpret_cast<__v2si>(ll); + (void)(__v2si)(ll); + + (void)reinterpret_cast<S>(v2si); // expected-error {{reinterpret_cast from '__v2si' to 'struct S' is not allowed}} + (void)(S)v2si; // expected-error {{C-style cast from '__v2si' to 'struct S' is not allowed}} + (void)reinterpret_cast<__v2si>(s); // expected-error {{reinterpret_cast from 'struct S' to '__v2si' is not allowed}} + (void)(__v2si)s; // expected-error {{C-style cast from 'struct S' to '__v2si' is not allowed}} + + (void)reinterpret_cast<unsigned char>(v2si); // expected-error {{reinterpret_cast from vector '__v2si' to scalar 'unsigned char' of different size}} + (void)(unsigned char)v2si; // expected-error {{C-style cast from vector '__v2si' to scalar 'unsigned char' of different size}} + (void)reinterpret_cast<__v2si>(c); // expected-error {{reinterpret_cast from scalar 'unsigned char' to vector '__v2si' of different size}} + + (void)reinterpret_cast<__v8hi>(v4hi); // expected-error {{reinterpret_cast from vector '__v4hi' to vector '__v8hi' of different size}} + (void)(__v8hi)v4hi; // expected-error {{C-style cast from vector '__v4hi' to vector '__v8hi' of different size}} + (void)reinterpret_cast<__v4hi>(v8hi); // expected-error {{reinterpret_cast from vector '__v8hi' to vector '__v4hi' of different size}} + (void)(__v4hi)v8hi; // expected-error {{C-style cast from vector '__v8hi' to vector '__v4hi' of different size}} +} + + |