diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 39 | ||||
| -rw-r--r-- | clang/test/Sema/ext_vector_casts.c | 4 |
2 files changed, 41 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f4802792573..842e11b6d1e 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6612,6 +6612,42 @@ QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS, return QualType(); } +static bool areVectorOperandsLaxBitCastable(ASTContext &Ctx, + QualType LHSType, QualType RHSType){ + if (!Ctx.getLangOpts().LaxVectorConversions) + return false; + + unsigned LHSSize = Ctx.getTypeSize(LHSType); + unsigned RHSSize = Ctx.getTypeSize(RHSType); + if (LHSSize != RHSSize) + return false; + + // For a non-power-of-2 vector ASTContext::getTypeSize returns the size + // rounded to the next power-of-2, but the LLVM IR type that we create + // is considered to have num-of-elements*width-of-element width. + // Make sure such width is the same between the types, otherwise we may end + // up with an invalid bitcast. + unsigned LHSIRSize, RHSIRSize; + if (LHSType->isVectorType()) { + const VectorType *Vec = LHSType->getAs<VectorType>(); + LHSIRSize = Vec->getNumElements() * + Ctx.getTypeSize(Vec->getElementType()); + } else { + LHSIRSize = LHSSize; + } + if (RHSType->isVectorType()) { + const VectorType *Vec = RHSType->getAs<VectorType>(); + RHSIRSize = Vec->getNumElements() * + Ctx.getTypeSize(Vec->getElementType()); + } else { + RHSIRSize = RHSSize; + } + if (LHSIRSize != RHSIRSize) + return false; + + return true; +} + QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign) { if (!IsCompAssign) { @@ -6647,8 +6683,7 @@ QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, return RHSType; } - if (getLangOpts().LaxVectorConversions && - Context.getTypeSize(LHSType) == Context.getTypeSize(RHSType)) { + if (areVectorOperandsLaxBitCastable(Context, LHSType, RHSType)) { // If we are allowing lax vector conversions, and LHS and RHS are both // vectors, the total size only needs to be the same. This is a // bitcast; no bits are changed but the result type is different. diff --git a/clang/test/Sema/ext_vector_casts.c b/clang/test/Sema/ext_vector_casts.c index 66004b03ff8..64dcd64cbda 100644 --- a/clang/test/Sema/ext_vector_casts.c +++ b/clang/test/Sema/ext_vector_casts.c @@ -1,6 +1,7 @@ // RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -fsyntax-only -verify -fno-lax-vector-conversions %s typedef __attribute__(( ext_vector_type(2) )) float float2; +typedef __attribute__(( ext_vector_type(3) )) float float3; typedef __attribute__(( ext_vector_type(4) )) int int4; typedef __attribute__(( ext_vector_type(8) )) short short8; typedef __attribute__(( ext_vector_type(4) )) float float4; @@ -11,12 +12,15 @@ typedef size_t stride4 __attribute__((ext_vector_type(4))); static void test() { float2 vec2; + float3 vec3; float4 vec4, vec4_2; int4 ivec4; short8 ish8; t3 vec4_3; int *ptr; int i; + + vec3 += vec2; // expected-error {{can't convert between vector values of different size}} vec4 = 5.0f; vec4 = (float4)5.0f; |

