r243069 - Fix the equal-vector-size rule for reinterpret_casts in C++
John McCall
rjmccall at apple.com
Thu Jul 23 16:54:08 PDT 2015
Author: rjmccall
Date: Thu Jul 23 18:54:07 2015
New Revision: 243069
URL: http://llvm.org/viewvc/llvm-project?rev=243069&view=rev
Log:
Fix the equal-vector-size rule for reinterpret_casts in C++
to consider the storage size of the vector instead of its
sizeof. In other words, ban <3 x int> to <4 x int> casts,
which produced invalid IR anyway.
Also, attempt to be a little more rigorous, or at least
explicit, about when enums are allowed in these casts.
rdar://21901132
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaCast.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/test/Sema/vector-cast.c
cfe/trunk/test/SemaCXX/vector-casts.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=243069&r1=243068&r2=243069&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Jul 23 18:54:07 2015
@@ -8375,6 +8375,7 @@ public:
QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS,
SourceLocation Loc);
+ bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
bool isLaxVectorConversion(QualType srcType, QualType destType);
/// type checking declaration initializers (C99 6.7.8)
Modified: cfe/trunk/lib/Sema/SemaCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=243069&r1=243068&r2=243069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCast.cpp Thu Jul 23 18:54:07 2015
@@ -1877,28 +1877,29 @@ static TryCastResult TryReinterpretCast(
return TC_Success;
}
+ // Allow reinterpret_casts between vectors of the same size and
+ // between vectors and integers of the same size.
bool destIsVector = DestType->isVectorType();
bool srcIsVector = SrcType->isVectorType();
if (srcIsVector || destIsVector) {
- // FIXME: Should this also apply to floating point types?
- bool srcIsScalar = SrcType->isIntegralType(Self.Context);
- bool destIsScalar = DestType->isIntegralType(Self.Context);
-
- // Check if this is a cast between a vector and something else.
- if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) &&
- !(srcIsVector && destIsVector))
+ // The non-vector type, if any, must have integral type. This is
+ // the same rule that C vector casts use; note, however, that enum
+ // types are not integral in C++.
+ if ((!destIsVector && !DestType->isIntegralType(Self.Context)) ||
+ (!srcIsVector && !SrcType->isIntegralType(Self.Context)))
return TC_NotApplicable;
- // If both types have the same size, we can successfully cast.
- if (Self.Context.getTypeSize(SrcType)
- == Self.Context.getTypeSize(DestType)) {
+ // The size we want to consider is eltCount * eltSize.
+ // That's exactly what the lax-conversion rules will check.
+ if (Self.areLaxCompatibleVectorTypes(SrcType, DestType)) {
Kind = CK_BitCast;
return TC_Success;
}
-
- if (destIsScalar)
+
+ // Otherwise, pick a reasonable diagnostic.
+ if (!destIsVector)
msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
- else if (srcIsScalar)
+ else if (!srcIsVector)
msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size;
else
msg = diag::err_bad_cxx_cast_vector_to_vector_different_size;
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=243069&r1=243068&r2=243069&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Jul 23 18:54:07 2015
@@ -5400,7 +5400,16 @@ static bool breakDownVectorType(QualType
return true;
}
-static bool VectorTypesMatch(Sema &S, QualType srcTy, QualType destTy) {
+/// 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
+/// size?
+///
+/// This will also return false if either of the types is neither a
+/// vector nor a real type.
+bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) {
+ assert(destTy->isVectorType() || srcTy->isVectorType());
+
uint64_t srcLen, destLen;
QualType srcElt, destElt;
if (!breakDownVectorType(srcTy, srcLen, srcElt)) return false;
@@ -5409,27 +5418,28 @@ static bool VectorTypesMatch(Sema &S, Qu
// 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 = S.Context.getTypeSize(srcElt);
- uint64_t destEltSize = S.Context.getTypeSize(destElt);
+ uint64_t srcEltSize = Context.getTypeSize(srcElt);
+ uint64_t destEltSize = Context.getTypeSize(destElt);
return (srcLen * srcEltSize == destLen * destEltSize);
}
-/// Is this a legal conversion between two known vector types?
+/// Is this a legal conversion between two types, one of which is
+/// known to be a vector type?
bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) {
assert(destTy->isVectorType() || srcTy->isVectorType());
if (!Context.getLangOpts().LaxVectorConversions)
return false;
- return VectorTypesMatch(*this, srcTy, destTy);
+ return areLaxCompatibleVectorTypes(srcTy, destTy);
}
bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty,
CastKind &Kind) {
assert(VectorTy->isVectorType() && "Not a vector type!");
- if (Ty->isVectorType() || Ty->isIntegerType()) {
- if (!VectorTypesMatch(*this, Ty, VectorTy))
+ if (Ty->isVectorType() || Ty->isIntegralType(Context)) {
+ if (!areLaxCompatibleVectorTypes(Ty, VectorTy))
return Diag(R.getBegin(),
Ty->isVectorType() ?
diag::err_invalid_conversion_between_vectors :
@@ -5455,7 +5465,7 @@ ExprResult Sema::CheckExtVectorCast(Sour
// In OpenCL, casts between vectors of different types are not allowed.
// (See OpenCL 6.2).
if (SrcTy->isVectorType()) {
- if (!VectorTypesMatch(*this, SrcTy, DestTy)
+ if (!areLaxCompatibleVectorTypes(SrcTy, DestTy)
|| (getLangOpts().OpenCL &&
(DestTy.getCanonicalType() != SrcTy.getCanonicalType()))) {
Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
Modified: cfe/trunk/test/Sema/vector-cast.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/vector-cast.c?rev=243069&r1=243068&r2=243069&view=diff
==============================================================================
--- cfe/trunk/test/Sema/vector-cast.c (original)
+++ cfe/trunk/test/Sema/vector-cast.c Thu Jul 23 18:54:07 2015
@@ -3,12 +3,20 @@
typedef long long t1 __attribute__ ((vector_size (8)));
typedef char t2 __attribute__ ((vector_size (16)));
typedef float t3 __attribute__ ((vector_size (16)));
+typedef short s2 __attribute__ ((vector_size(4)));
+
+typedef enum { Evalue = 0x10000 } E;
void f()
{
t1 v1;
t2 v2;
t3 v3;
+ s2 v4;
+ E e;
+
+ e = (E)v4;
+ v4 = (s2)e;
v2 = (t2)v1; // expected-error {{invalid conversion between vector type \
't2' (vector of 16 'char' values) and 't1' (vector of 1 'long long' value) of different size}}
Modified: cfe/trunk/test/SemaCXX/vector-casts.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/vector-casts.cpp?rev=243069&r1=243068&r2=243069&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/vector-casts.cpp (original)
+++ cfe/trunk/test/SemaCXX/vector-casts.cpp Thu Jul 23 18:54:07 2015
@@ -1,18 +1,22 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown -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)));
typedef short __v3hi __attribute__((__ext_vector_type__(3)));
-struct S { }; // expected-note 2 {{candidate constructor}}
+struct S { }; // expected-note 3 {{candidate constructor}}
+
+enum E : long long { Evalue };
void f() {
__v2si v2si;
+ __v3hi v3hi;
__v4hi v4hi;
__v8hi v8hi;
unsigned long long ll;
unsigned char c;
S s;
+ E e;
(void)reinterpret_cast<__v2si>(v4hi);
(void)(__v2si)v4hi;
@@ -23,6 +27,11 @@ void f() {
(void)reinterpret_cast<__v2si>(ll);
(void)(__v2si)(ll);
+ (void)(E)v2si; // expected-error {{C-style cast from '__v2si' (vector of 2 'int' values) to 'E' is not allowed}}
+ (void)(__v2si)e; // expected-error {{C-style cast from 'E' to '__v2si' (vector of 2 'int' values)}}
+ (void)reinterpret_cast<E>(v2si); // expected-error {{reinterpret_cast from '__v2si' (vector of 2 'int' values) to 'E' is not allowed}}
+ (void)reinterpret_cast<__v2si>(e); // expected-error {{reinterpret_cast from 'E' to '__v2si' (vector of 2 'int' values)}}
+
(void)reinterpret_cast<S>(v2si); // expected-error {{reinterpret_cast from '__v2si' (vector of 2 'int' values) to 'S' is not allowed}}
(void)(S)v2si; // expected-error {{no matching conversion for C-style cast from '__v2si' (vector of 2 'int' values) to 'S'}}
(void)reinterpret_cast<__v2si>(s); // expected-error {{reinterpret_cast from 'S' to '__v2si' (vector of 2 'int' values) is not allowed}}
@@ -36,6 +45,15 @@ void f() {
(void)(__v8hi)v4hi; // expected-error {{C-style cast from vector '__v4hi' (vector of 4 'short' values) to vector '__v8hi' (vector of 8 'short' values) of different size}}
(void)reinterpret_cast<__v4hi>(v8hi); // expected-error {{reinterpret_cast from vector '__v8hi' (vector of 8 'short' values) to vector '__v4hi' (vector of 4 'short' values) of different size}}
(void)(__v4hi)v8hi; // expected-error {{C-style cast from vector '__v8hi' (vector of 8 'short' values) to vector '__v4hi' (vector of 4 'short' values) of different size}}
+
+ (void)(__v3hi)v4hi; // expected-error {{C-style cast from vector '__v4hi' (vector of 4 'short' values) to vector '__v3hi' (vector of 3 'short' values) of different size}}
+ (void)(__v3hi)v2si; // expected-error {{C-style cast from vector '__v2si' (vector of 2 'int' values) to vector '__v3hi' (vector of 3 'short' values) of different size}}
+ (void)(__v4hi)v3hi; // expected-error {{C-style cast from vector '__v3hi' (vector of 3 'short' values) to vector '__v4hi' (vector of 4 'short' values) of different size}}
+ (void)(__v2si)v3hi; // expected-error {{C-style cast from vector '__v3hi' (vector of 3 'short' values) to vector '__v2si' (vector of 2 'int' values) of different size}}
+ (void)reinterpret_cast<__v3hi>(v4hi); // expected-error {{reinterpret_cast from vector '__v4hi' (vector of 4 'short' values) to vector '__v3hi' (vector of 3 'short' values) of different size}}
+ (void)reinterpret_cast<__v3hi>(v2si); // expected-error {{reinterpret_cast from vector '__v2si' (vector of 2 'int' values) to vector '__v3hi' (vector of 3 'short' values) of different size}}
+ (void)reinterpret_cast<__v4hi>(v3hi); // expected-error {{reinterpret_cast from vector '__v3hi' (vector of 3 'short' values) to vector '__v4hi' (vector of 4 'short' values) of different size}}
+ (void)reinterpret_cast<__v2si>(v3hi); // expected-error {{reinterpret_cast from vector '__v3hi' (vector of 3 'short' values) to vector '__v2si' (vector of 2 'int' values) of different size}}
}
struct testvec {
More information about the cfe-commits
mailing list