Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -8045,6 +8045,7 @@ // If there's an ext-vector type and a scalar, try to convert the scalar to // the vector element type and splat. + // FIXME: this should also work for regular vector types as supported in GCC. if (!RHSVecType && isa(LHSVecType)) { if (!tryVectorConvertAndSplat(*this, &RHS, RHSType, LHSVecType->getElementType(), LHSType)) @@ -8057,16 +8058,31 @@ return RHSType; } - // If we're allowing lax vector conversions, only the total (data) size needs - // to be the same. If one of the types is scalar, the result is always the - // vector type. Don't allow this if the scalar operand is an lvalue. + // FIXME: The code below also handles convertion between vectors and + // non-scalars, we should break this down into fine grained specific checks + // and emit proper diagnostics. QualType VecType = LHSVecType ? LHSType : RHSType; - QualType ScalarType = LHSVecType ? RHSType : LHSType; - ExprResult *ScalarExpr = LHSVecType ? &RHS : &LHS; - if (isLaxVectorConversion(ScalarType, VecType) && - !ScalarExpr->get()->isLValue()) { - *ScalarExpr = ImpCastExprToType(ScalarExpr->get(), VecType, CK_BitCast); - return VecType; + const VectorType *VT = LHSVecType ? LHSVecType : RHSVecType; + QualType OtherType = LHSVecType ? RHSType : LHSType; + ExprResult *OtherExpr = LHSVecType ? &RHS : &LHS; + if (isLaxVectorConversion(OtherType, VecType)) { + // If we're allowing lax vector conversions, only the total (data) size + // needs to be the same. For non compound assignment, if one of the types is + // scalar, the result is always the vector type. + if (!IsCompAssign) { + *OtherExpr = ImpCastExprToType(OtherExpr->get(), VecType, CK_BitCast); + return VecType; + // In a compound assignment, lhs += rhs, 'lhs' is a lvalue src, forbidding + // any implicit cast. Here, the 'rhs' should be implicit casted to 'lhs' + // type. Note that this is already done by non-compound assignments in + // CheckAssignmentConstraints. If it's a scalar type, only biscast for + // <1 x T> -> T. + } else if (OtherType->isExtVectorType() || + (OtherType->isScalarType() && VT->getNumElements() == 1)) { + ExprResult *RHSExpr = &RHS; + *RHSExpr = ImpCastExprToType(RHSExpr->get(), LHSType, CK_BitCast); + return LHSType; + } } // Okay, the expression is invalid. Index: test/Sema/vector-cast.c =================================================================== --- test/Sema/vector-cast.c +++ test/Sema/vector-cast.c @@ -53,14 +53,13 @@ float2 f2; double d, a, b, c; float64x2_t v = {0.0, 1.0}; - f2 += d; + // FIXME: These diagnostics are inaccurate: should complain that 'double' to vector 'float2' involves truncation + f2 += d; // expected-error {{cannot convert between vector values of different size ('float2' (vector of 2 'float' values) and 'double')}} + d += f2; // expected-error {{cannot convert between vector values of different size}} a = 3.0 + vget_low_f64(v); b = vget_low_f64(v) + 3.0; c = vget_low_f64(v); - // LAX conversions within compound assignments are not supported. - // FIXME: This diagnostic is inaccurate. - d += f2; // expected-error {{cannot convert between vector values of different size}} - c -= vget_low_f64(v); // expected-error {{cannot convert between vector values of different size}} + c -= vget_low_f64(v); // LAX conversions between scalar and vector types require same size and one element sized vectors. d = f2; // expected-error {{assigning to 'double' from incompatible type 'float2'}} d = d + f2; // expected-error {{assigning to 'double' from incompatible type 'float2'}}