diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 26 |
2 files changed, 32 insertions, 21 deletions
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index c0754ba7902..fe16fc2df31 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1877,28 +1877,29 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, 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; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f384f56269a..61f361676d6 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5400,7 +5400,16 @@ static bool breakDownVectorType(QualType type, uint64_t &len, 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, QualType srcTy, QualType destTy) { // 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(SourceRange R, QualType DestTy, // 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) |