Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2437,6 +2437,9 @@ "vector size not an integral multiple of component size">; def err_attribute_zero_size : Error<"zero vector size">; def err_attribute_size_too_large : Error<"vector size too large">; +def err_typecheck_vector_not_convertable_implict_truncation : Error< + "cannot convert between %select{scalar|vector}0 type %1 and vector type" + " %2 as implicit conversion would cause truncation">; def err_typecheck_vector_not_convertable : Error< "cannot convert between vector values of different size (%0 and %1)">; def err_typecheck_vector_not_convertable_non_scalar : Error< @@ -5746,6 +5749,9 @@ "cannot assign to class object (%0 invalid)">; def err_typecheck_invalid_operands : Error< "invalid operands to binary expression (%0 and %1)">; +def err_typecheck_logical_vector_expr_gnu_cpp_restrict : Error< + "logical expression with vector %select{type %1|types %1 and %2}0 is only" + " supported in C++">; def err_typecheck_sub_ptr_compatible : Error< "%diff{$ and $ are not pointers to compatible types|" "pointers to incompatible types}0,1">; Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -9208,6 +9208,8 @@ /// type checking binary operators (subroutines of CreateBuiltinBinOp). QualType InvalidOperands(SourceLocation Loc, ExprResult &LHS, ExprResult &RHS); + QualType InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS, + ExprResult &RHS); QualType CheckPointerToMemberOperands( // C++ 5.5 ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, SourceLocation OpLoc, bool isIndirect); Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -8014,6 +8014,31 @@ return QualType(); } +// Diagnose cases where a scalar was implicitly converted to a vector and +// blame the natural vector. If it cannot be determined, diagnose the error +// as invalid vector logical operands for non-C++ cases. +QualType Sema::InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS, + ExprResult &RHS) { + QualType LHSType = LHS.get()->IgnoreImpCasts()->getType(); + QualType RHSType = RHS.get()->IgnoreImpCasts()->getType(); + + bool LHSNatVec = LHSType->isVectorType(); + bool RHSNatVec = RHSType->isVectorType(); + + if (LHSNatVec != RHSNatVec) { + Expr * Vector = LHSNatVec ? LHS.get() : RHS.get(); + Diag(Loc, diag::err_typecheck_logical_vector_expr_gnu_cpp_restrict) + << 0 << Vector->getType() << Vector->getSourceRange(); + return QualType(); + } + + Diag(Loc, diag::err_typecheck_logical_vector_expr_gnu_cpp_restrict) + << 1 << LHSType << RHSType << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + + return QualType(); +} + /// Try to convert a value of non-vector type to a vector type by converting /// the type to the element type of the vector and then performing a splat. /// If the language is OpenCL, we only use conversions that promote scalar @@ -8061,6 +8086,162 @@ return false; } +/// Test if a (constant) integer Int can be casted to another integer type +/// IntTy without losing precision. +static bool canConvertIntToOtherIntTy(Sema &S, ExprResult *Int, + QualType OtherIntTy) { + QualType IntTy = Int->get()->getType().getUnqualifiedType(); + + // Reject cases where the value of the Int is unknown as that would + // possibly cause truncation, but accept cases where the scalar can be + // demoted without loss of precision. + llvm::APSInt Result; + bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context); + int Order = S.Context.getIntegerTypeOrder(OtherIntTy, IntTy); + bool IntSigned = IntTy->hasSignedIntegerRepresentation(); + bool OtherIntSigned = OtherIntTy->hasSignedIntegerRepresentation(); + + if (CstInt) { + // If the scalar is constant and is of a higher order and has more active + // bits that the vector element type, reject it. + unsigned NumBits = IntSigned + ? (Result.isNegative() ? Result.getMinSignedBits() + : Result.getActiveBits()) + : Result.getActiveBits(); + if (Order < 0 && S.Context.getIntWidth(OtherIntTy) < NumBits) + return true; + + // If the signedness of the scalar type and the vector element type + // differs and the number of bits is greater than that of the vector + // element reject it. + return (IntSigned != OtherIntSigned && + NumBits > S.Context.getIntWidth(OtherIntTy)); + } + + // Reject cases where the value of the scalar is not constant and it's + // order is greater than that of the vector element type. + return (Order < 0); +} + +/// Test if a (constant) integer Int can be casted to floating point type +/// FloatTy without losing precision. +static bool canConvertIntTyToFloatTy(Sema &S, ExprResult *Int, + QualType FloatTy) { + QualType IntTy = Int->get()->getType().getUnqualifiedType(); + + // Determine if the integer constant can be expressed as a floating point + // number of the appropiate type. + llvm::APSInt Result; + bool CstInt = Int->get()->EvaluateAsInt(Result, S.Context); + uint64_t Bits = 0; + if (CstInt) { + // Reject constants that would be truncated if they were converted to + // the floating point type. Test by simple to/from conversion. + // FIXME: Ideally the conversion to an APFloat and from an APFloat + // could be avoided if there was a convertFromAPInt method + // which could signal back if implicit truncation occurred. + llvm::APFloat Float(S.Context.getFloatTypeSemantics(FloatTy)); + Float.convertFromAPInt(Result, IntTy->hasSignedIntegerRepresentation(), + llvm::APFloat::rmTowardZero); + llvm::APSInt ConvertBack(S.Context.getIntWidth(IntTy), + !IntTy->hasSignedIntegerRepresentation()); + bool Ignored = false; + Float.convertToInteger(ConvertBack, llvm::APFloat::rmNearestTiesToEven, + &Ignored); + if (Result != ConvertBack) + return true; + } else { + // Reject types that cannot be fully encoded into the mantissa of + // the float. + Bits = S.Context.getTypeSize(IntTy); + unsigned FloatPrec = llvm::APFloat::semanticsPrecision( + S.Context.getFloatTypeSemantics(FloatTy)); + if (Bits > FloatPrec) + return true; + } + + return false; +} + +/// Attempt to convert and splat Scalar into a vector whose types matches +/// Vector following GCC conversion rules. The rule is that implicit +/// conversion can occur when Scalar can be casted to match Vector's element +/// type without causing truncation of Scalar. +static bool tryGCCVectorConvertAndSplat(Sema &S, ExprResult *Scalar, + ExprResult *Vector) { + QualType ScalarTy = Scalar->get()->getType().getUnqualifiedType(); + QualType VectorTy = Vector->get()->getType().getUnqualifiedType(); + const VectorType *VT = VectorTy->getAs(); + + assert(!isa(VT) && + "ExtVectorTypes should not be handled here!"); + + QualType VectorEltTy = VT->getElementType(); + + // Reject cases where the vector element type or the scalar element type are + // not integral or floating point types. + if (!VectorEltTy->isArithmeticType() || !ScalarTy->isArithmeticType()) + return true; + + // The conversion to apply to the scalar before splatting it, + // if necessary. + CastKind ScalarCast = CK_Invalid; + + // Accept cases where the vector elements are integers and the scalar is + // an integer. + // FIXME: Notionally if the scalar was a floating point value with a precise + // integral representation, we could cast it to an appropriate integer + // type and then perform the rest of the checks here. GCC will perform + // this conversion in some cases as determined by the input language. + // We should accept it on a language independent basis. + if (VectorEltTy->isIntegralType(S.Context) && + ScalarTy->isIntegralType(S.Context) && + S.Context.getIntegerTypeOrder(VectorEltTy, ScalarTy)) { + + if (canConvertIntToOtherIntTy(S, Scalar, VectorEltTy)) + return true; + + ScalarCast = CK_IntegralCast; + } else if (VectorEltTy->isRealFloatingType()) { + if (ScalarTy->isRealFloatingType()) { + + // Reject cases where the scalar type is not a constant and has a higher + // Order than the vector element type. + llvm::APFloat Result(0.0); + bool CstScalar = Scalar->get()->EvaluateAsFloat(Result, S.Context); + int Order = S.Context.getFloatingTypeOrder(VectorEltTy, ScalarTy); + if (!CstScalar && Order < 0) + return true; + + // If the scalar cannot be safely casted to the vector element type, + // reject it. + if (CstScalar) { + bool Truncated = false; + Result.convert(S.Context.getFloatTypeSemantics(VectorEltTy), + llvm::APFloat::rmNearestTiesToEven, &Truncated); + if (Truncated) + return true; + } + + ScalarCast = CK_FloatingCast; + } else if (ScalarTy->isIntegralType(S.Context)) { + if (canConvertIntTyToFloatTy(S, Scalar, VectorEltTy)) + return true; + + ScalarCast = CK_IntegralToFloating; + } else + return true; + } + + // Adjust scalar if desired. + if (Scalar) { + if (ScalarCast != CK_Invalid) + *Scalar = S.ImpCastExprToType(Scalar->get(), VectorEltTy, ScalarCast); + *Scalar = S.ImpCastExprToType(Scalar->get(), VectorTy, CK_VectorSplat); + } + return false; +} + QualType Sema::CheckVectorOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign, bool AllowBothBool, @@ -8129,19 +8310,29 @@ } } - // If there's an ext-vector type and a scalar, try to convert the scalar to + // If there's a 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)) - return LHSType; + if (!RHSVecType) { + if (isa(LHSVecType)) { + if (!tryVectorConvertAndSplat(*this, &RHS, RHSType, + LHSVecType->getElementType(), LHSType)) + return LHSType; + } else { + if (!tryGCCVectorConvertAndSplat(*this, &RHS, &LHS)) + return LHSType; + } } - if (!LHSVecType && isa(RHSVecType)) { - if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS), - LHSType, RHSVecType->getElementType(), - RHSType)) - return RHSType; + if (!LHSVecType) { + if (isa(RHSVecType)) { + if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS), + LHSType, RHSVecType->getElementType(), + RHSType)) + return RHSType; + } else { + if (LHS.get()->getValueKind() == VK_LValue || + !tryGCCVectorConvertAndSplat(*this, &LHS, &RHS)) + return RHSType; + } } // FIXME: The code below also handles conversion between vectors and @@ -8194,6 +8385,22 @@ return QualType(); } + + // If there is a vector type that is not a ExtVector and a scalar, we reach + // this point if scalar could not be converted to the vector's element type + // without truncation. + if ((RHSVecType && !isa(RHSVecType)) || + (LHSVecType && !isa(LHSVecType))) { + QualType Scalar = LHSVecType ? RHSType : LHSType; + QualType Vector = LHSVecType ? LHSType : RHSType; + unsigned ScalarOrVector = LHSVecType && RHSVecType ? 1 : 0; + Diag(Loc, + diag::err_typecheck_vector_not_convertable_implict_truncation) + << ScalarOrVector << Scalar << Vector; + + return QualType(); + } + // Otherwise, use the generic diagnostic. Diag(Loc, diag::err_typecheck_vector_not_convertable) << LHSType << RHSType @@ -9813,6 +10020,12 @@ if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion < 120 && vType->hasFloatingRepresentation()) return InvalidOperands(Loc, LHS, RHS); + // FIXME: The check for C++ here is for GCC compatibility. GCC rejects the + // usage of the logical operators && and || with vectors in C. This + // check could be notionally dropped. + if (!getLangOpts().CPlusPlus && + !(isa(vType->getAs()))) + return InvalidLogicalVectorOperands(Loc, LHS, RHS); return GetSignedVectorType(LHS.get()->getType()); } @@ -11756,6 +11969,8 @@ resultType = GetSignedVectorType(resultType); break; } else { + // FIXME: GCC's vector extension permits the usage of '!' with a vector + // type in C++. We should allow that here too. return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) << resultType << Input.get()->getSourceRange()); } Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -5317,6 +5317,15 @@ // C++11 [expr.cond]p1 // The first expression is contextually converted to bool. + // + // FIXME; GCC's vector extension permits the use of a?b:c where the type of + // a is that of a integer vector with the same number of elements and + // size as the vectors of b and c. If one of either b or c is a scalar + // it is implicitly converted to match the type of the vector. + // Otherwise the expression is ill-formed. If both b and c are scalars, + // then b and c are checked and converted to the type of a if possible. + // Unlike the OpenCL ?: operator, the expression is evaluated as + // (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]). if (!Cond.get()->isTypeDependent()) { ExprResult CondRes = CheckCXXBooleanCondition(Cond.get()); if (CondRes.isInvalid()) Index: test/Sema/vector-cast.c =================================================================== --- test/Sema/vector-cast.c +++ test/Sema/vector-cast.c @@ -53,9 +53,8 @@ float2 f2; double d, a, b, c; float64x2_t v = {0.0, 1.0}; - // 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}} + f2 += d; // expected-error {{cannot convert between scalar type 'double' and vector type 'float2' (vector of 2 'float' values) as implicit conversion would cause truncation}} + d += f2; // expected-error {{assigning to 'double' from incompatible type 'float2' (vector of 2 'float' values)}} a = 3.0 + vget_low_f64(v); b = vget_low_f64(v) + 3.0; c = vget_low_f64(v); Index: test/Sema/vector-gcc-compat.c =================================================================== --- /dev/null +++ test/Sema/vector-gcc-compat.c @@ -0,0 +1,330 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only -Weverything + +// Test the compatibility of clang's vector extensions with gcc's vector +// extensions for C. Notably &&, ||, ?: and ! are not available. +typedef long long v2i64 __attribute__((vector_size(16))); +typedef int v2i32 __attribute__((vector_size(8))); +typedef short v2i16 __attribute__((vector_size(4))); +typedef char v2i8 __attribute__((vector_size(2))); + +typedef unsigned long long v2u64 __attribute__((vector_size(16))); +typedef unsigned int v2u32 __attribute__((vector_size(8))); +typedef unsigned short v2u16 __attribute__((vector_size(4))); +typedef unsigned char v2u8 __attribute__((vector_size(2))); + +typedef float v4f32 __attribute__((vector_size(16))); +typedef double v2f64 __attribute__((vector_size(16))); +typedef double v4f64 __attribute__((vector_size(32))); +typedef int v4i32 __attribute((vector_size(16))); + +void arithmeticTest(void); +void logicTest(void); +void comparisonTest(void); +void floatTestSignedType(char a, short b, int c, long long d); +void floatTestUnsignedType(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); +void floatTestConstant(void); +void intTestType(char a, short b, int c, long long d); +void intTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); +void uintTestType(char a, short b, int c, long long d); +void uintTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); +void uintTestConstant(v2u64 v2u64_a, v2u32 v2u32_a, v2u16 v2u16_a, v2u8 v2u8_a); +void intTestConstant(v2i64 v2i64_a, v2i32 v2i32_a, v2i16 v2i16_a, v2i8 v2i8_a); + +void arithmeticTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; + v2i64 v2i64_r; + + v2i64_r = v2i64_a + 1; + v2i64_r = v2i64_a - 1; + v2i64_r = v2i64_a * 1; + v2i64_r = v2i64_a / 1; + v2i64_r = v2i64_a % 1; + + v2i64_r = 1 + v2i64_a; + v2i64_r = 1 - v2i64_a; + v2i64_r = 1 * v2i64_a; + v2i64_r = 1 / v2i64_a; + v2i64_r = 1 % v2i64_a; + + v2i64_a += 1; + v2i64_a -= 1; + v2i64_a *= 1; + v2i64_a /= 1; + v2i64_a %= 1; +} + +void comparisonTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; + v2i64 v2i64_r; + + v2i64_r = v2i64_a == 1; + v2i64_r = v2i64_a != 1; + v2i64_r = v2i64_a < 1; + v2i64_r = v2i64_a > 1; + v2i64_r = v2i64_a <= 1; + v2i64_r = v2i64_a >= 1; + + v2i64_r = 1 == v2i64_a; + v2i64_r = 1 != v2i64_a; + v2i64_r = 1 < v2i64_a; + v2i64_r = 1 > v2i64_a; + v2i64_r = 1 <= v2i64_a; + v2i64_r = 1 >= v2i64_a; +} + +void logicTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; + v2i64 v2i64_b = (v2i64){2, 1}; + v2i64 v2i64_c = (v2i64){3, 1}; + v2i64 v2i64_r; + + v2i64_r = !v2i64_a; // expected-error {{invalid argument type 'v2i64' (vector of 2 'long long' values) to unary expression}} + v2i64_r = ~v2i64_a; + + v2i64_r = v2i64_a ? v2i64_b : v2i64_c; // expected-error {{used type 'v2i64' (vector of 2 'long long' values) where arithmetic or pointer type is required}} + + v2i64_r = v2i64_a & 1; + v2i64_r = v2i64_a | 1; + v2i64_r = v2i64_a ^ 1; + + v2i64_r = 1 & v2i64_a; + v2i64_r = 1 | v2i64_a; + v2i64_r = 1 ^ v2i64_a; + + v2i64_a &= 1; + v2i64_a |= 1; + v2i64_a ^= 1; + + v2i64_r = v2i64_a && 1; // expected-error {{logical expression with vector type 'v2i64' (vector of 2 'long long' values) is only supported in C++}} + v2i64_r = v2i64_a || 1; // expected-error {{logical expression with vector type 'v2i64' (vector of 2 'long long' values) is only supported in C++}} + + v2i64_r = v2i64_a && v2i64_a; // expected-error {{logical expression with vector types 'v2i64' (vector of 2 'long long' values) and 'v2i64' is only supported in C++}} + v2i64_r = v2i64_a || v2i64_a; // expected-error {{logical expression with vector types 'v2i64' (vector of 2 'long long' values) and 'v2i64' is only supported in C++}} + + v2i64_r = v2i64_a << 1; + v2i64_r = v2i64_a >> 1; + + v2i64_r = 1 << v2i64_a; + v2i64_r = 1 >> v2i64_a; + + v2i64_a <<= 1; + v2i64_a >>= 1; +} + +// For operations with floating point types, we check that interger constants +// can be respresented, or failing that checking based on the integer types. +void floatTestConstant(void) { + // Test that constants added to floats must be expressible as floating point + // numbers. + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f32_a = v4f32_a + 1; + v4f32_a = v4f32_a + 0xFFFFFF; + v4f32_a = v4f32_a + (-1567563LL); + v4f32_a = v4f32_a + (16777208); + v4f32_a = v4f32_a + (16777219); // expected-error {{cannot convert between scalar type 'int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} +} + +void floatTestConstantComparison(void); +void doubleTestConstantComparison(void); + +void floatTestConstantComparison(void) { + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4i32 v4i32_r; + v4i32_r = v4f32_a > 0.4f; + v4i32_r = v4f32_a >= 0.4f; + v4i32_r = v4f32_a < 0.4f; + v4i32_r = v4f32_a <= 0.4f; + v4i32_r = v4f32_a == 0.4f; // expected-warning {{comparing floating point with == or != is unsafe}} + v4i32_r = v4f32_a != 0.4f; // expected-warning {{comparing floating point with == or != is unsafe}} +} + +void doubleTestConstantComparison(void) { + v2f64 v2f64_a = {0.4, 0.4}; + v2i64 v2i64_r; + v2i64_r = v2f64_a > 0.4; + v2i64_r = v2f64_a >= 0.4; + v2i64_r = v2f64_a < 0.4; + v2i64_r = v2f64_a <= 0.4; + v2i64_r = v2f64_a == 0.4; // expected-warning {{comparing floating point with == or != is unsafe}} + v2i64_r = v2f64_a != 0.4; // expected-warning {{comparing floating point with == or != is unsafe}} +} + +void floatTestUnsignedType(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f64 v4f64_b = {0.4, 0.4, 0.4, 0.4}; + + v4f32_a = v4f32_a + a; + v4f32_a = v4f32_a + b; + v4f32_a = v4f32_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + v4f32_a = v4f32_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + + v4f64_b = v4f64_b + a; + v4f64_b = v4f64_b + b; + v4f64_b = v4f64_b + c; + v4f64_b = v4f64_b + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v4f64' (vector of 4 'double' values) as implicit conversion would cause truncation}} +} + +void floatTestSignedType(char a, short b, int c, long long d) { + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f64 v4f64_b = {0.4, 0.4, 0.4, 0.4}; + + v4f32_a = v4f32_a + a; + v4f32_a = v4f32_a + b; + v4f32_a = v4f32_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + v4f32_a = v4f32_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + + v4f64_b = v4f64_b + a; + v4f64_b = v4f64_b + b; + v4f64_b = v4f64_b + c; + v4f64_b = v4f64_b + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v4f64' (vector of 4 'double' values) as implicit conversion would cause truncation}} +} + +void intTestType(char a, short b, int c, long long d) { + v2i64 v2i64_a = {1, 2}; + v2i32 v2i32_a = {1, 2}; + v2i16 v2i16_a = {1, 2}; + v2i8 v2i8_a = {1, 2}; + + v2i64_a = v2i64_a + d; + v2i64_a = v2i64_a + c; + v2i64_a = v2i64_a + b; + v2i64_a = v2i64_a + a; + + v2i32_a = v2i32_a + d; // expected-warning {{implicit conversion loses integer precision: 'long long' to 'v2i32' (vector of 2 'int' values)}} + v2i32_a = v2i32_a + c; + v2i32_a = v2i32_a + b; + v2i32_a = v2i32_a + a; + + v2i16_a = v2i16_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + c; // expected-warning {{implicit conversion loses integer precision: 'int' to 'v2i16' (vector of 2 'short' values)}} + v2i16_a = v2i16_a + b; + v2i16_a = v2i16_a + a; + + v2i8_a = v2i8_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + b; // expected-warning {{implicit conversion loses integer precision: 'short' to 'v2i8' (vector of 2 'char' values)}} + v2i8_a = v2i8_a + a; +} + +void intTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { + v2i64 v2i64_a = {1, 2}; + v2i32 v2i32_a = {1, 2}; + v2i16 v2i16_a = {1, 2}; + v2i8 v2i8_a = {1, 2}; + + v2i64_a = v2i64_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i64' (vector of 2 'long long' values) as implicit conversion would cause truncation}} + + v2i64_a = v2i64_a + c; + v2i64_a = v2i64_a + b; + v2i64_a = v2i64_a + a; + + v2i32_a = v2i32_a + d; // expected-warning {{implicit conversion loses integer precision: 'unsigned long long' to 'v2i32' (vector of 2 'int' values)}} + v2i32_a = v2i32_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2i32' (vector of 2 'int' values) as implicit conversion would cause truncation}} + v2i32_a = v2i32_a + b; + v2i32_a = v2i32_a + a; + + v2i16_a = v2i16_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + c; // expected-warning {{implicit conversion loses integer precision: 'unsigned int' to 'v2i16' (vector of 2 'short' values)}} + v2i16_a = v2i16_a + b; // expected-error {{cannot convert between scalar type 'unsigned short' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + a; + + v2i8_a = v2i8_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + b; // expected-warning {{implicit conversion loses integer precision: 'unsigned short' to 'v2i8' (vector of 2 'char' values)}} + v2i8_a = v2i8_a + a; // expected-error {{cannot convert between scalar type 'unsigned char' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} +} + +void uintTestType(char a, short b, int c, long long d) { + v2u64 v2u64_a = {1, 2}; + v2u32 v2u32_a = {1, 2}; + v2u16 v2u16_a = {1, 2}; + v2u8 v2u8_a = {1, 2}; + + v2u64_a = v2u64_a + d; // expected-warning {{implicit conversion changes signedness: 'long long' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + c; // expected-warning {{implicit conversion changes signedness: 'int' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u64' (vector of 2 'unsigned long long' values)}} + + v2u32_a = v2u32_a + d; // expected-warning {{implicit conversion loses integer precision: 'long long' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + c; // expected-warning {{implicit conversion changes signedness: 'int' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u32' (vector of 2 'unsigned int' values)}} + + v2u16_a = v2u16_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2u16' (vector of 2 'unsigned short' values) as implicit conversion would cause truncation}} + v2u16_a = v2u16_a + c; // expected-warning {{implicit conversion loses integer precision: 'int' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u16' (vector of 2 'unsigned short' values)}} + + v2u8_a = v2u8_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + b; // expected-warning {{implicit conversion loses integer precision: 'short' to 'v2u8' (vector of 2 'unsigned char' values)}} + v2u8_a = v2u8_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u8' (vector of 2 'unsigned char' values)}} +} + +void uintTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { + v2u64 v2u64_a = {1, 2}; + v2u32 v2u32_a = {1, 2}; + v2u16 v2u16_a = {1, 2}; + v2u8 v2u8_a = {1, 2}; + + v2u64_a = v2u64_a + d; + v2u64_a = v2u64_a + c; + v2u64_a = v2u64_a + b; + v2u64_a = v2u64_a + a; + + v2u32_a = v2u32_a + d; // expected-warning {{implicit conversion loses integer precision: 'unsigned long long' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + c; + v2u32_a = v2u32_a + b; + v2u32_a = v2u32_a + a; + + v2u16_a = v2u16_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2u16' (vector of 2 'unsigned short' values) as implicit conversion would cause truncation}} + v2u16_a = v2u16_a + c; // expected-warning {{implicit conversion loses integer precision: 'unsigned int' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + b; + v2u16_a = v2u16_a + a; + + v2u8_a = v2u8_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + b; // expected-warning {{implicit conversion loses integer precision: 'unsigned short' to 'v2u8' (vector of 2 'unsigned char' values)}} + v2u8_a = v2u8_a + a; +} + +void uintTestConstant(v2u64 v2u64_a, v2u32 v2u32_a, v2u16 v2u16_a, + v2u8 v2u8_a) { + v2u64_a = v2u64_a + 0xFFFFFFFFFFFFFFFF; + v2u32_a = v2u32_a + 0xFFFFFFFF; + v2u16_a = v2u16_a + 0xFFFF; + v2u8_a = v2u8_a + 0xFF; + + v2u32_a = v2u32_a + 0x1FFFFFFFF; // expected-warning {{implicit conversion from 'long' to 'v2u32' (vector of 2 'unsigned int' values) changes value from 8589934591 to 4294967295}} + v2u16_a = v2u16_a + 0x1FFFF; // expected-warning {{implicit conversion from 'int' to 'v2u16' (vector of 2 'unsigned short' values) changes value from 131071 to 65535}} + v2u8_a = v2u8_a + 0x1FF; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} +} + +void intTestConstant(v2i64 v2i64_a, v2i32 v2i32_a, v2i16 v2i16_a, v2i8 v2i8_a) { + // Legal upper bounds. + v2i64_a = v2i64_a + (long long)0x7FFFFFFFFFFFFFFF; + v2i32_a = v2i32_a + (int)0x7FFFFFFF; + v2i16_a = v2i16_a + (short)0x7FFF; + v2i8_a = v2i8_a + (char)0x7F; + + // Legal lower bounds. + v2i64_a = v2i64_a + (-9223372036854775807); + v2i32_a = v2i32_a + (-2147483648); + v2i16_a = v2i16_a + (-32768); + v2i8_a = v2i8_a + (-128); + + // One increment/decrement more than the type can hold + v2i32_a = v2i32_a + 2147483648; // expected-warning {{implicit conversion from 'long' to 'v2i32' (vector of 2 'int' values) changes value from 2147483648 to -2147483648}} + v2i16_a = v2i16_a + 32768; // expected-warning {{implicit conversion from 'int' to 'v2i16' (vector of 2 'short' values) changes value from 32768 to -32768}} + v2i8_a = v2i8_a + 128; // expected-warning {{implicit conversion from 'int' to 'v2i8' (vector of 2 'char' values) changes value from 128 to -128}} + + v2i32_a = v2i32_a + (-2147483649); // expected-warning {{implicit conversion from 'long' to 'v2i32' (vector of 2 'int' values) changes value from -2147483649 to 2147483647}} + v2i16_a = v2i16_a + (-32769); // expected-warning {{implicit conversion from 'int' to 'v2i16' (vector of 2 'short' values) changes value from -32769 to 32767}} + v2i8_a = v2i8_a + (-129); // expected-error {{cannot convert between scalar type 'int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} +} Index: test/Sema/vector-gcc-compat.cpp =================================================================== --- /dev/null +++ test/Sema/vector-gcc-compat.cpp @@ -0,0 +1,328 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only -Weverything -std=c++11 + +// Test the compatibility of clang++'s vector extensions with g++'s vector +// extensions. In comparison to the extensions available in C, the !, ?:, && and +// || operators work on vector types. + +typedef long long v2i64 __attribute__((vector_size(16))); // expected-warning {{'long long' is incompatible with C++98}} +typedef int v2i32 __attribute__((vector_size(8))); +typedef short v2i16 __attribute__((vector_size(4))); +typedef char v2i8 __attribute__((vector_size(2))); + +typedef unsigned long long v2u64 __attribute__((vector_size(16))); // expected-warning {{'long long' is incompatible with C++98}} +typedef unsigned int v2u32 __attribute__((vector_size(8))); +typedef unsigned short v2u16 __attribute__((vector_size(4))); +typedef unsigned char v2u8 __attribute__((vector_size(2))); + +typedef float v4f32 __attribute__((vector_size(16))); +typedef double v2f64 __attribute__((vector_size(16))); +typedef double v4f64 __attribute__((vector_size(32))); +typedef int v4i32 __attribute((vector_size(16))); + +void arithmeticTest(void); +void logicTest(void); +void comparisonTest(void); +void floatTestSignedType(char a, short b, int c, long long d); // expected-warning {{'long long' is incompatible with C++98}} +void floatTestUnsignedType(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); // expected-warning {{'long long' is incompatible with C++98}} +void floatTestConstant(void); +void intTestType(char a, short b, int c, long long d); // expected-warning {{'long long' is incompatible with C++98}} +void intTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); // expected-warning {{'long long' is incompatible with C++98}} +void uintTestType(char a, short b, int c, long long d); // expected-warning {{'long long' is incompatible with C++98}} +void uintTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d); // expected-warning {{'long long' is incompatible with C++98}} +void uintTestConstant(v2u64 v2u64_a, v2u32 v2u32_a, v2u16 v2u16_a, v2u8 v2u8_a); +void intTestConstant(v2i64 v2i64_a, v2i32 v2i32_a, v2i16 v2i16_a, v2i8 v2i8_a); + +void arithmeticTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; // expected-warning {{compound literals are a C99-specific feature}} + v2i64 v2i64_r; + + v2i64_r = v2i64_a + 1; + v2i64_r = v2i64_a - 1; + v2i64_r = v2i64_a * 1; + v2i64_r = v2i64_a / 1; + v2i64_r = v2i64_a % 1; + + v2i64_r = 1 + v2i64_a; + v2i64_r = 1 - v2i64_a; + v2i64_r = 1 * v2i64_a; + v2i64_r = 1 / v2i64_a; + v2i64_r = 1 % v2i64_a; + + v2i64_a += 1; + v2i64_a -= 1; + v2i64_a *= 1; + v2i64_a /= 1; + v2i64_a %= 1; +} + +void comparisonTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; // expected-warning {{compound literals are a C99-specific feature}} + v2i64 v2i64_r; + + v2i64_r = v2i64_a == 1; + v2i64_r = v2i64_a != 1; + v2i64_r = v2i64_a < 1; + v2i64_r = v2i64_a > 1; + v2i64_r = v2i64_a <= 1; + v2i64_r = v2i64_a >= 1; + + v2i64_r = 1 == v2i64_a; + v2i64_r = 1 != v2i64_a; + v2i64_r = 1 < v2i64_a; + v2i64_r = 1 > v2i64_a; + v2i64_r = 1 <= v2i64_a; + v2i64_r = 1 >= v2i64_a; +} + +void logicTest(void) { + v2i64 v2i64_a = (v2i64){0, 1}; // expected-warning {{compound literals are a C99-specific feature}} + v2i64 v2i64_b = (v2i64){2, 1}; // expected-warning {{compound literals are a C99-specific feature}} + v2i64 v2i64_c = (v2i64){3, 1}; // expected-warning {{compound literals are a C99-specific feature}} + v2i64 v2i64_r; + + v2i64_r = !v2i64_a; // expected-error {{invalid argument type 'v2i64' (vector of 2 'long long' values) to unary expression}} + v2i64_r = ~v2i64_a; + + v2i64_r = v2i64_a ? v2i64_b : v2i64_c; // expected-error {{value of type 'v2i64' (vector of 2 'long long' values) is not contextually convertible to 'bool'}} + + v2i64_r = v2i64_a & 1; + v2i64_r = v2i64_a | 1; + v2i64_r = v2i64_a ^ 1; + + v2i64_r = 1 & v2i64_a; + v2i64_r = 1 | v2i64_a; + v2i64_r = 1 ^ v2i64_a; + v2i64_a &= 1; + v2i64_a |= 1; + v2i64_a ^= 1; + + v2i64_r = v2i64_a && 1; + v2i64_r = v2i64_a || 1; + + v2i64_r = v2i64_a << 1; + v2i64_r = v2i64_a >> 1; + + v2i64_r = 1 << v2i64_a; + v2i64_r = 1 >> v2i64_a; + + v2i64_a <<= 1; + v2i64_a >>= 1; +} + +// For operations with floating point types, we check that interger constants +// can be respresented, or failing that checking based on the integer types. +void floatTestConstant(void) { + // Test that constants added to floats must be expressible as floating point + // numbers. + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f32_a = v4f32_a + 1; + v4f32_a = v4f32_a + 0xFFFFFF; + v4f32_a = v4f32_a + (-1567563LL); // expected-warning {{'long long' is incompatible with C++98}} + v4f32_a = v4f32_a + (16777208); + v4f32_a = v4f32_a + (16777219); // expected-error {{cannot convert between scalar type 'int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} +} + +void floatTestConstantComparison(void); +void doubleTestConstantComparison(void); + +void floatTestConstantComparison(void) { + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4i32 v4i32_r; + v4i32_r = v4f32_a > 0.4f; + v4i32_r = v4f32_a >= 0.4f; + v4i32_r = v4f32_a < 0.4f; + v4i32_r = v4f32_a <= 0.4f; + v4i32_r = v4f32_a == 0.4f; // expected-warning {{comparing floating point with == or != is unsafe}} + v4i32_r = v4f32_a != 0.4f; // expected-warning {{comparing floating point with == or != is unsafe}} +} + +void doubleTestConstantComparison(void) { + v2f64 v2f64_a = {0.4, 0.4}; + v2i64 v2i64_r; + v2i64_r = v2f64_a > 0.4; + v2i64_r = v2f64_a >= 0.4; + v2i64_r = v2f64_a < 0.4; + v2i64_r = v2f64_a <= 0.4; + v2i64_r = v2f64_a == 0.4; // expected-warning {{comparing floating point with == or != is unsafe}} + v2i64_r = v2f64_a != 0.4; // expected-warning {{comparing floating point with == or != is unsafe}} +} + +void floatTestUnsignedType(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f64 v4f64_b = {0.4, 0.4, 0.4, 0.4}; + + v4f32_a = v4f32_a + a; + v4f32_a = v4f32_a + b; + v4f32_a = v4f32_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + v4f32_a = v4f32_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + + v4f64_b = v4f64_b + a; + v4f64_b = v4f64_b + b; + v4f64_b = v4f64_b + c; + v4f64_b = v4f64_b + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v4f64' (vector of 4 'double' values) as implicit conversion would cause truncation}} +} + +void floatTestSignedType(char a, short b, int c, long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v4f32 v4f32_a = {0.4f, 0.4f, 0.4f, 0.4f}; + v4f64 v4f64_b = {0.4, 0.4, 0.4, 0.4}; + + v4f32_a = v4f32_a + a; + v4f32_a = v4f32_a + b; + v4f32_a = v4f32_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + v4f32_a = v4f32_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v4f32' (vector of 4 'float' values) as implicit conversion would cause truncation}} + + v4f64_b = v4f64_b + a; + v4f64_b = v4f64_b + b; + v4f64_b = v4f64_b + c; + v4f64_b = v4f64_b + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v4f64' (vector of 4 'double' values) as implicit conversion would cause truncation}} +} + +void intTestType(char a, short b, int c, long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v2i64 v2i64_a = {1, 2}; + v2i32 v2i32_a = {1, 2}; + v2i16 v2i16_a = {1, 2}; + v2i8 v2i8_a = {1, 2}; + + v2i64_a = v2i64_a + d; + v2i64_a = v2i64_a + c; + v2i64_a = v2i64_a + b; + v2i64_a = v2i64_a + a; + + v2i32_a = v2i32_a + d; // expected-warning {{implicit conversion loses integer precision: 'long long' to 'v2i32' (vector of 2 'int' values)}} + v2i32_a = v2i32_a + c; + v2i32_a = v2i32_a + b; + v2i32_a = v2i32_a + a; + + v2i16_a = v2i16_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + c; // expected-warning {{implicit conversion loses integer precision: 'int' to 'v2i16' (vector of 2 'short' values)}} + v2i16_a = v2i16_a + b; + v2i16_a = v2i16_a + a; + + v2i8_a = v2i8_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + b; // expected-warning {{implicit conversion loses integer precision: 'short' to 'v2i8' (vector of 2 'char' values)}} + v2i8_a = v2i8_a + a; +} + +void intTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v2i64 v2i64_a = {1, 2}; + v2i32 v2i32_a = {1, 2}; + v2i16 v2i16_a = {1, 2}; + v2i8 v2i8_a = {1, 2}; + + v2i64_a = v2i64_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i64' (vector of 2 'long long' values) as implicit conversion would cause truncation}} + + v2i64_a = v2i64_a + c; + v2i64_a = v2i64_a + b; + v2i64_a = v2i64_a + a; + + v2i32_a = v2i32_a + d; // expected-warning {{implicit conversion loses integer precision: 'unsigned long long' to 'v2i32' (vector of 2 'int' values)}} + v2i32_a = v2i32_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2i32' (vector of 2 'int' values) as implicit conversion would cause truncation}} + v2i32_a = v2i32_a + b; + v2i32_a = v2i32_a + a; + + v2i16_a = v2i16_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + c; // expected-warning {{implicit conversion loses integer precision: 'unsigned int' to 'v2i16' (vector of 2 'short' values)}} + v2i16_a = v2i16_a + b; // expected-error {{cannot convert between scalar type 'unsigned short' and vector type 'v2i16' (vector of 2 'short' values) as implicit conversion would cause truncation}} + v2i16_a = v2i16_a + a; + + v2i8_a = v2i8_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} + v2i8_a = v2i8_a + b; // expected-warning {{implicit conversion loses integer precision: 'unsigned short' to 'v2i8' (vector of 2 'char' values)}} + v2i8_a = v2i8_a + a; // expected-error {{cannot convert between scalar type 'unsigned char' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} +} + +void uintTestType(char a, short b, int c, long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v2u64 v2u64_a = {1, 2}; + v2u32 v2u32_a = {1, 2}; + v2u16 v2u16_a = {1, 2}; + v2u8 v2u8_a = {1, 2}; + + v2u64_a = v2u64_a + d; // expected-warning {{implicit conversion changes signedness: 'long long' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + c; // expected-warning {{implicit conversion changes signedness: 'int' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u64' (vector of 2 'unsigned long long' values)}} + v2u64_a = v2u64_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u64' (vector of 2 'unsigned long long' values)}} + + v2u32_a = v2u32_a + d; // expected-warning {{implicit conversion loses integer precision: 'long long' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + c; // expected-warning {{implicit conversion changes signedness: 'int' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u32' (vector of 2 'unsigned int' values)}} + + v2u16_a = v2u16_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2u16' (vector of 2 'unsigned short' values) as implicit conversion would cause truncation}} + v2u16_a = v2u16_a + c; // expected-warning {{implicit conversion loses integer precision: 'int' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + b; // expected-warning {{implicit conversion changes signedness: 'short' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u16' (vector of 2 'unsigned short' values)}} + + v2u8_a = v2u8_a + d; // expected-error {{cannot convert between scalar type 'long long' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + c; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + b; // expected-warning {{implicit conversion loses integer precision: 'short' to 'v2u8' (vector of 2 'unsigned char' values)}} + v2u8_a = v2u8_a + a; // expected-warning {{implicit conversion changes signedness: 'char' to 'v2u8' (vector of 2 'unsigned char' values)}} +} + +void uintTestTypeUnsigned(unsigned char a, unsigned short b, unsigned int c, + unsigned long long d) { // expected-warning {{'long long' is incompatible with C++98}} + v2u64 v2u64_a = {1, 2}; + v2u32 v2u32_a = {1, 2}; + v2u16 v2u16_a = {1, 2}; + v2u8 v2u8_a = {1, 2}; + + v2u64_a = v2u64_a + d; + v2u64_a = v2u64_a + c; + v2u64_a = v2u64_a + b; + v2u64_a = v2u64_a + a; + + v2u32_a = v2u32_a + d; // expected-warning {{implicit conversion loses integer precision: 'unsigned long long' to 'v2u32' (vector of 2 'unsigned int' values)}} + v2u32_a = v2u32_a + c; + v2u32_a = v2u32_a + b; + v2u32_a = v2u32_a + a; + + v2u16_a = v2u16_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2u16' (vector of 2 'unsigned short' values) as implicit conversion would cause truncation}} + v2u16_a = v2u16_a + c; // expected-warning {{implicit conversion loses integer precision: 'unsigned int' to 'v2u16' (vector of 2 'unsigned short' values)}} + v2u16_a = v2u16_a + b; + v2u16_a = v2u16_a + a; + + v2u8_a = v2u8_a + d; // expected-error {{cannot convert between scalar type 'unsigned long long' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + c; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} + v2u8_a = v2u8_a + b; // expected-warning {{implicit conversion loses integer precision: 'unsigned short' to 'v2u8' (vector of 2 'unsigned char' values)}} + v2u8_a = v2u8_a + a; +} + +void uintTestConstant(v2u64 v2u64_a, v2u32 v2u32_a, v2u16 v2u16_a, + v2u8 v2u8_a) { + v2u64_a = v2u64_a + 0xFFFFFFFFFFFFFFFF; + v2u32_a = v2u32_a + 0xFFFFFFFF; + v2u16_a = v2u16_a + 0xFFFF; + v2u8_a = v2u8_a + 0xFF; + + v2u32_a = v2u32_a + 0x1FFFFFFFF; // expected-warning {{implicit conversion from 'long' to 'v2u32' (vector of 2 'unsigned int' values) changes value from 8589934591 to 4294967295}} + v2u16_a = v2u16_a + 0x1FFFF; // expected-warning {{implicit conversion from 'int' to 'v2u16' (vector of 2 'unsigned short' values) changes value from 131071 to 65535}} + v2u8_a = v2u8_a + 0x1FF; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2u8' (vector of 2 'unsigned char' values) as implicit conversion would cause truncation}} +} + +void intTestConstant(v2i64 v2i64_a, v2i32 v2i32_a, v2i16 v2i16_a, v2i8 v2i8_a) { + // Legal upper bounds. + v2i64_a = v2i64_a + static_cast(0x7FFFFFFFFFFFFFFF); // expected-warning {{'long long' is incompatible with C++98}} + v2i32_a = v2i32_a + static_cast(0x7FFFFFFF); + v2i16_a = v2i16_a + static_cast(0x7FFF); + v2i8_a = v2i8_a + static_cast(0x7F); + + // Legal lower bounds. + v2i64_a = v2i64_a + (-9223372036854775807); + v2i32_a = v2i32_a + (-2147483648); + v2i16_a = v2i16_a + (-32768); + v2i8_a = v2i8_a + (-128); + + // One increment/decrement more than the type can hold + v2i32_a = v2i32_a + 2147483648; // expected-warning {{implicit conversion from 'long' to 'v2i32' (vector of 2 'int' values) changes value from 2147483648 to -2147483648}} + v2i16_a = v2i16_a + 32768; // expected-warning {{implicit conversion from 'int' to 'v2i16' (vector of 2 'short' values) changes value from 32768 to -32768}} + v2i8_a = v2i8_a + 128; // expected-warning {{implicit conversion from 'int' to 'v2i8' (vector of 2 'char' values) changes value from 128 to -128}} + + v2i32_a = v2i32_a + (-2147483649); // expected-warning {{implicit conversion from 'long' to 'v2i32' (vector of 2 'int' values) changes value from -2147483649 to 2147483647}} + v2i16_a = v2i16_a + (-32769); // expected-warning {{implicit conversion from 'int' to 'v2i16' (vector of 2 'short' values) changes value from -32769 to 32767}} + v2i8_a = v2i8_a + (-129); // expected-error {{cannot convert between scalar type 'int' and vector type 'v2i8' (vector of 2 'char' values) as implicit conversion would cause truncation}} +} Index: test/Sema/vector-ops.c =================================================================== --- test/Sema/vector-ops.c +++ test/Sema/vector-ops.c @@ -13,11 +13,11 @@ (void)(~v2fa); // expected-error{{invalid argument type 'v2f' (vector of 2 'float' values) to unary}} // Comparison operators - v2ua = (v2ua==v2sa); // expected-warning{{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2ua = (v2ua==v2sa); // expected-warning{{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values}} v2sa = (v2ua==v2sa); // Arrays - int array1[v2ua]; // expected-error{{size of array has non-integer type 'v2u' (vector of 2 'unsigned int' values)}} + int array1[v2ua]; // expected-error{{size of array has non-integer type 'v2u' (vector of 2 'unsigned int' values}} int array2[17]; // FIXME: error message below needs type! (void)(array2[v2ua]); // expected-error{{array subscript is not an integer}} @@ -28,108 +28,108 @@ } void testLogicalVecVec(v2u v2ua, v2s v2sa, v2f v2fa) { - // Logical operators - v2ua = v2ua && v2ua; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2ua = v2ua || v2ua; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2ua = v2ua && v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} + v2ua = v2ua || v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} - v2ua = v2sa && v2ua; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2ua = v2sa || v2ua; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2ua = v2sa && v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} + v2ua = v2sa || v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} - v2ua = v2ua && v2fa; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2ua = v2ua || v2fa; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2ua = v2ua && v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} + v2ua = v2ua || v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} - v2ua = v2sa && v2fa; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2ua = v2sa || v2fa; // expected-warning {{incompatible vector types assigning to 'v2u' (vector of 2 'unsigned int' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2ua = v2sa && v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} + v2ua = v2sa || v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} - v2sa = v2sa && v2sa; - v2sa = v2sa || v2sa; + v2sa = v2sa && v2sa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2s'}} + v2sa = v2sa || v2sa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2s'}} - v2sa = v2ua && v2ua; - v2sa = v2ua || v2ua; + v2sa = v2ua && v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} + v2sa = v2ua || v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} - v2sa = v2sa && v2ua; - v2sa = v2sa || v2ua; + v2sa = v2sa && v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} + v2sa = v2sa || v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} - v2sa = v2sa && v2fa; - v2sa = v2sa || v2fa; + v2sa = v2sa && v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} + v2sa = v2sa || v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} - v2sa = v2ua && v2fa; - v2sa = v2ua || v2fa; + v2sa = v2ua && v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} + v2sa = v2ua || v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} - v2fa = v2fa && v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2fa || v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2fa && v2fa; // expected-error {{logical expression with vector types 'v2f' (vector of 2 'float' values) and 'v2f'}} + v2fa = v2fa || v2fa; // expected-error {{logical expression with vector types 'v2f' (vector of 2 'float' values) and 'v2f'}} - v2fa = v2sa && v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2sa || v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2sa && v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} + v2fa = v2sa || v2fa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2f' (vector of 2 'float' values)}} - v2fa = v2ua && v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2ua || v2fa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2ua && v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} + v2fa = v2ua || v2fa; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2f' (vector of 2 'float' values)}} - v2fa = v2ua && v2ua; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2ua || v2ua; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2ua && v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} + v2fa = v2ua || v2ua; // expected-error {{logical expression with vector types 'v2u' (vector of 2 'unsigned int' values) and 'v2u'}} - v2fa = v2sa && v2sa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2sa || v2sa; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2sa && v2sa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2s'}} + v2fa = v2sa || v2sa; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2s'}} - v2fa = v2sa && v2ua; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} - v2fa = v2sa || v2ua; // expected-warning {{incompatible vector types assigning to 'v2f' (vector of 2 'float' values) from '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} + v2fa = v2sa && v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} + v2fa = v2sa || v2ua; // expected-error {{logical expression with vector types 'v2s' (vector of 2 'int' values) and 'v2u' (vector of 2 'unsigned int' values)}} } void testLogicalVecScalar(v2u v2ua, v2s v2sa, v2f v2fa) { - unsigned u1; - v2ua = v2ua && u1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} - v2ua = v2ua || u1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} + v2ua = v2ua && u1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} + v2ua = v2ua || u1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} - v2sa = v2sa && u1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} - v2sa = v2sa || u1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} + v2sa = v2sa && u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2s' (vector of 2 'int' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} + v2sa = v2sa || u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2s' (vector of 2 'int' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} - v2ua = v2sa && u1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} - v2ua = v2sa || u1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} - v2sa = v2ua && u1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} - v2sa = v2ua || u1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'unsigned int')}} + v2ua = v2sa && u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2s' (vector of 2 'int' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} + v2ua = v2sa || u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2s' (vector of 2 'int' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'unsigned int')}} + v2sa = v2ua && u1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} + v2sa = v2ua || u1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} - v2ua = v2fa && u1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} - v2ua = v2fa || u1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} + v2ua = v2fa && u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} + v2ua = v2fa || u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} - v2sa = v2fa && u1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} - v2sa = v2fa || u1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'unsigned int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} + v2sa = v2fa && u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} + v2sa = v2fa || u1; // expected-error {{cannot convert between scalar type 'unsigned int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'unsigned int')}} int s1; - v2ua = v2ua && s1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'int')}} - v2ua = v2ua || s1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'int')}} + v2ua = v2ua && s1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} + v2ua = v2ua || s1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} - v2sa = v2sa && s1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'int')}} - v2sa = v2sa || s1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'int')}} + v2sa = v2sa && s1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) is only supported in C++}} + v2sa = v2sa || s1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) is only supported in C++}} - v2ua = v2sa && s1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'int')}} - v2ua = v2sa || s1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'int')}} - v2sa = v2ua && s1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'int')}} - v2sa = v2ua || s1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'int')}} + v2ua = v2sa && s1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) is only supported in C++}} + v2ua = v2sa || s1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) is only supported in C++}} - v2ua = v2fa && s1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int')}} - v2ua = v2fa || s1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int')}} + v2sa = v2ua && s1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} + v2sa = v2ua || s1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} - v2sa = v2fa && s1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int')}} - v2sa = v2fa || s1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'int')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int')}} + v2ua = v2fa && s1; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int'}} + v2ua = v2fa || s1; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int'}} + + v2sa = v2fa && s1; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int'}} + v2sa = v2fa || s1; // expected-error {{cannot convert between scalar type 'int' and vector type 'v2f' (vector of 2 'float' values) as implicit conversion would cause truncation}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'int'}} float f1; - v2ua = v2ua && f1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'float')}} - v2ua = v2ua || f1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'float')}} + v2ua = v2ua && f1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} + v2ua = v2ua || f1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} + + v2sa = v2sa && f1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) is only supported in C++}} + v2sa = v2sa || f1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) is only supported in C++}} - v2sa = v2sa && f1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'float')}} - v2sa = v2sa || f1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'float')}} + v2ua = v2sa && f1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) is only supported in C++}} + v2ua = v2sa || f1; // expected-error {{logical expression with vector type 'v2s' (vector of 2 'int' values) is only supported in C++}} - v2ua = v2sa && f1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'float')}} - v2ua = v2sa || f1; // expected-error {{cannot convert between vector values of different size ('v2s' (vector of 2 'int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2s' (vector of 2 'int' values) and 'float')}} - v2sa = v2ua && f1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'float')}} - v2sa = v2ua || f1; // expected-error {{cannot convert between vector values of different size ('v2u' (vector of 2 'unsigned int' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2u' (vector of 2 'unsigned int' values) and 'float')}} + v2sa = v2ua && f1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} + v2sa = v2ua || f1; // expected-error {{logical expression with vector type 'v2u' (vector of 2 'unsigned int' values) is only supported in C++}} - v2ua = v2fa && f1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'float')}} - v2ua = v2fa || f1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'float')}} + v2ua = v2fa && f1; // expected-error {{logical expression with vector type 'v2f' (vector of 2 'float' values) is only supported in C++}} + v2ua = v2fa || f1; // expected-error {{logical expression with vector type 'v2f' (vector of 2 'float' values) is only supported in C++}} - v2sa = v2fa && f1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'float')}} - v2sa = v2fa || f1; // expected-error {{cannot convert between vector values of different size ('v2f' (vector of 2 'float' values) and 'float')}} expected-error {{invalid operands to binary expression ('v2f' (vector of 2 'float' values) and 'float')}} + v2sa = v2fa && f1; // expected-error {{logical expression with vector type 'v2f' (vector of 2 'float' values) is only supported in C++}} + v2sa = v2fa || f1; // expected-error {{logical expression with vector type 'v2f' (vector of 2 'float' values) is only supported in C++}} } Index: test/Sema/zvector.c =================================================================== --- test/Sema/zvector.c +++ test/Sema/zvector.c @@ -326,14 +326,14 @@ bc = bc + sc2; // expected-error {{incompatible type}} bc = sc + bc2; // expected-error {{incompatible type}} - sc = sc + sc_scalar; // expected-error {{cannot convert}} - sc = sc + uc_scalar; // expected-error {{cannot convert}} - sc = sc_scalar + sc; // expected-error {{cannot convert}} - sc = uc_scalar + sc; // expected-error {{cannot convert}} - uc = uc + sc_scalar; // expected-error {{cannot convert}} - uc = uc + uc_scalar; // expected-error {{cannot convert}} - uc = sc_scalar + uc; // expected-error {{cannot convert}} - uc = uc_scalar + uc; // expected-error {{cannot convert}} + sc = sc + sc_scalar; + sc = sc + uc_scalar; // expected-error {{cannot convert between scalar type 'unsigned char' and vector type '__vector signed char' (vector of 16 'signed char' values) as implicit conversion would cause truncation}} + sc = sc_scalar + sc; + sc = uc_scalar + sc; // expected-error {{cannot convert between scalar type 'unsigned char' and vector type '__vector signed char' (vector of 16 'signed char' values) as implicit conversion would cause truncation}} + uc = uc + sc_scalar; // expected-error {{implicit conversion changes signedness: 'signed char' to '__vector unsigned char' (vector of 16 'unsigned char' values)}} + uc = uc + uc_scalar; + uc = sc_scalar + uc; // expected-error {{implicit conversion changes signedness: 'signed char' to '__vector unsigned char' (vector of 16 'unsigned char' values)}} + uc = uc_scalar + uc; ss = ss + ss2; us = us + us2; @@ -368,10 +368,10 @@ sc += sl2; // expected-error {{cannot convert}} sc += fd2; // expected-error {{cannot convert}} - sc += sc_scalar; // expected-error {{cannot convert}} - sc += uc_scalar; // expected-error {{cannot convert}} - uc += sc_scalar; // expected-error {{cannot convert}} - uc += uc_scalar; // expected-error {{cannot convert}} + sc += sc_scalar; + sc += uc_scalar; // expected-error {{cannot convert between scalar type 'unsigned char' and vector type '__vector signed char' (vector of 16 'signed char' values) as implicit conversion would cause truncation}} + uc += sc_scalar; // expected-error {{implicit conversion changes signedness: 'signed char' to '__vector unsigned char' (vector of 16 'unsigned char' values)}} + uc += uc_scalar; ss += ss2; us += us2; Index: test/SemaCXX/vector-no-lax.cpp =================================================================== --- test/SemaCXX/vector-no-lax.cpp +++ test/SemaCXX/vector-no-lax.cpp @@ -4,6 +4,6 @@ vSInt32 foo (vUInt32 a) { vSInt32 b = { 0, 0, 0, 0 }; - b += a; // expected-error{{cannot convert between vector values}} + b += a; // expected-error{{cannot convert between vector type 'vUInt32' (vector of 4 'unsigned int' values) and vector type 'vSInt32' (vector of 4 'int' values) as implicit conversion would cause truncation}} return b; }