// 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<ExtVectorType>(LHSVecType)) {
if (!tryVectorConvertAndSplat(*this, &RHS, RHSType,
LHSVecType->getElementType(), LHSType))
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 bitcast for
+ // <1 x T> -> T. The result is also a vector type.
+ } else if (OtherType->isExtVectorType() ||
+ (OtherType->isScalarType() && VT->getNumElements() == 1)) {
+ ExprResult *RHSExpr = &RHS;
+ *RHSExpr = ImpCastExprToType(RHSExpr->get(), LHSType, CK_BitCast);
+ return VecType;
+ }
}
// Okay, the expression is invalid.
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'}}