diff options
| author | Anders Carlsson <andersca@mac.com> | 2009-09-16 19:19:43 +0000 |
|---|---|---|
| committer | Anders Carlsson <andersca@mac.com> | 2009-09-16 19:19:43 +0000 |
| commit | 570af5d426787c1c457946309163d5b0cba282dc (patch) | |
| tree | adb7955f35f023652bc4c757055d9b62ca746a94 /clang | |
| parent | e8d0150398fee132b3f9c36352f3b5ef85c019c8 (diff) | |
| download | bcm5719-llvm-570af5d426787c1c457946309163d5b0cba282dc.tar.gz bcm5719-llvm-570af5d426787c1c457946309163d5b0cba282dc.zip | |
Improve handling of vector casts in C++.
llvm-svn: 82072
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 9 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaCXXCast.cpp | 26 | ||||
| -rw-r--r-- | clang/test/SemaCXX/vector-casts.cpp | 40 |
3 files changed, 75 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 807a85560f3..b14317eb083 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index dbd6c6fde5c..f0ae9a13308 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/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/clang/test/SemaCXX/vector-casts.cpp b/clang/test/SemaCXX/vector-casts.cpp new file mode 100644 index 00000000000..5b08043545f --- /dev/null +++ b/clang/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}} +} + + |

