diff options
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 75 | ||||
-rw-r--r-- | test/Sema/ext_vector_casts.c | 22 |
2 files changed, 68 insertions, 29 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 464ee939ff..6e11165106 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2940,9 +2940,13 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) { return false; } - // All scalar -> ext vector "c-style" casts are legal; the appropriate + // All non-pointer scalars can be cast to ExtVector type. The appropriate // conversion will take place first from scalar to elt type, and then // splat from elt type to vector. + if (SrcTy->isPointerType()) + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_vector_and_scalar) + << DestTy << SrcTy << R; return false; } @@ -3374,12 +3378,16 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { return IncompatibleObjCQualifiedId; } + // Allow scalar to ExtVector assignments, and assignments of an ExtVector type + // to the same ExtVector type. + if (lhsType->isExtVectorType()) { + if (rhsType->isExtVectorType()) + return lhsType == rhsType ? Compatible : Incompatible; + if (!rhsType->isVectorType() && rhsType->isArithmeticType()) + return Compatible; + } + if (lhsType->isVectorType() || rhsType->isVectorType()) { - // For ExtVector, allow vector splats; float -> <n x float> - if (const ExtVectorType *LV = lhsType->getAsExtVectorType()) - if (LV->getElementType() == rhsType) - return Compatible; - // 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. @@ -3606,32 +3614,41 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, } } - // If the lhs is an extended vector and the rhs is a scalar of the same type - // or a literal, promote the rhs to the vector type. - if (const ExtVectorType *V = lhsType->getAsExtVectorType()) { - QualType eltType = V->getElementType(); - - if ((eltType->getAsBuiltinType() == rhsType->getAsBuiltinType()) || - (eltType->isIntegerType() && isa<IntegerLiteral>(rex)) || - (eltType->isFloatingType() && isa<FloatingLiteral>(rex))) { - ImpCastExprToType(rex, lhsType); - return lhsType; - } + // Canonicalize the ExtVector to the LHS, remember if we swapped so we can + // swap back (so that we don't reverse the inputs to a subtract, for instance. + bool swapped = false; + if (rhsType->isExtVectorType()) { + swapped = true; + std::swap(rex, lex); + std::swap(rhsType, lhsType); } - - // If the rhs is an extended vector and the lhs is a scalar of the same type, - // promote the lhs to the vector type. - if (const ExtVectorType *V = rhsType->getAsExtVectorType()) { - QualType eltType = V->getElementType(); - - if ((eltType->getAsBuiltinType() == lhsType->getAsBuiltinType()) || - (eltType->isIntegerType() && isa<IntegerLiteral>(lex)) || - (eltType->isFloatingType() && isa<FloatingLiteral>(lex))) { - ImpCastExprToType(lex, rhsType); - return rhsType; + + // Handle the case of an ext vector and scalar + if (const ExtVectorType *LV = lhsType->getAsExtVectorType()) { + QualType EltTy = LV->getElementType(); + if (EltTy->isIntegralType() && rhsType->isIntegralType()) { + if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) { + ImpCastExprToType(rex, EltTy); + rex = new (Context) CStyleCastExpr(lhsType, rex, lhsType, + rex->getSourceRange().getBegin(), + rex->getSourceRange().getEnd()); + if (swapped) std::swap(rex, lex); + return lhsType; + } + } + if (EltTy->isRealFloatingType() && rhsType->isScalarType() && + rhsType->isRealFloatingType()) { + if (Context.getFloatingTypeOrder(EltTy, rhsType) >= 0) { + ImpCastExprToType(rex, EltTy); + rex = new (Context) CStyleCastExpr(lhsType, rex, lhsType, + rex->getSourceRange().getBegin(), + rex->getSourceRange().getEnd()); + if (swapped) std::swap(rex, lex); + return lhsType; + } } } - + // You cannot convert between vector values of different size. Diag(Loc, diag::err_typecheck_vector_not_convertable) << lex->getType() << rex->getType() diff --git a/test/Sema/ext_vector_casts.c b/test/Sema/ext_vector_casts.c index 8aa762ebcf..dbcd1c9b3a 100644 --- a/test/Sema/ext_vector_casts.c +++ b/test/Sema/ext_vector_casts.c @@ -2,6 +2,7 @@ typedef __attribute__(( ext_vector_type(2) )) float float2; typedef __attribute__(( ext_vector_type(4) )) int int4; +typedef __attribute__(( ext_vector_type(8) )) short short8; typedef __attribute__(( ext_vector_type(4) )) float float4; typedef float t3 __attribute__ ((vector_size (16))); @@ -9,8 +10,12 @@ static void test() { float2 vec2; float4 vec4, vec4_2; int4 ivec4; + short8 ish8; t3 vec4_3; + int *ptr; + int i; + vec4 = 5.0f; vec4 = (float4)5.0f; vec4 = (float4)5; vec4 = (float4)vec4_3; @@ -19,5 +24,22 @@ static void test() { ivec4 = (int4)5; ivec4 = (int4)vec4_3; + i = (int)ivec4; // expected-error {{invalid conversion between vector type 'int4' and integer type 'int' of different size}} + i = ivec4; // expected-error {{incompatible type assigning 'int4', expected 'int'}} + + ivec4 = (int4)ptr; // expected-error {{invalid conversion between vector type 'int4' and scalar type 'int *'}} + vec4 = (float4)vec2; // expected-error {{invalid conversion between ext-vector type 'float4' and 'float2'}} + + ish8 += 5; // expected-error {{can't convert between vector values of different size ('short8' and 'int')}} + ish8 += (short)5; + ivec4 *= 5; + vec4 /= 5.2f; + vec4 %= 4; // expected-error {{invalid operands to binary expression ('float4' and 'int')}} + ivec4 %= 4; + ivec4 += vec4; // expected-error {{can't convert between vector values of different size ('float4' and 'int4')}} + ivec4 += (int4)vec4; + ivec4 -= ivec4; + ivec4 |= ivec4; + ivec4 += ptr; // expected-error {{can't convert between vector values of different size ('int4' and 'int *')}} } |