diff options
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 65 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 2 | ||||
-rw-r--r-- | clang/test/Sema/arm-neon-types.c | 7 | ||||
-rw-r--r-- | clang/test/Sema/ext_vector_casts.c | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/vector.cpp | 8 |
6 files changed, 44 insertions, 43 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e03ade68113..7cb060dcdf8 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5559,7 +5559,8 @@ public: SourceLocation QuestionLoc); /// type checking for vector binary operators. - QualType CheckVectorOperands(SourceLocation l, ExprResult &lex, ExprResult &rex); + QualType CheckVectorOperands(ExprResult &lex, ExprResult &rex, + SourceLocation Loc, bool isCompAssign); QualType CheckVectorCompareOperands(ExprResult &lex, ExprResult &rx, SourceLocation l, bool isRel); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index a8e7348d41a..adc1331a9fb 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4372,7 +4372,7 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprR // Now check the two expressions. if (LHSTy->isVectorType() || RHSTy->isVectorType()) - return CheckVectorOperands(QuestionLoc, LHS, RHS); + return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false); // OpenCL: If the condition is a vector, and both operands are scalar, // attempt to implicity convert them to the vector type to act like the @@ -5470,7 +5470,8 @@ QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &lex, ExprResult & return QualType(); } -QualType Sema::CheckVectorOperands(SourceLocation Loc, ExprResult &lex, ExprResult &rex) { +QualType Sema::CheckVectorOperands(ExprResult &lex, ExprResult &rex, + SourceLocation Loc, bool isCompAssign) { // For conversion purposes, we ignore any qualifiers. // For example, "const float" and "float" are equivalent. QualType lhsType = @@ -5482,42 +5483,33 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, ExprResult &lex, ExprResu if (lhsType == rhsType) return lhsType; - // Handle the case of a vector & extvector type of the same size and element - // type. It would be nice if we only had one vector type someday. - if (getLangOptions().LaxVectorConversions) { - if (const VectorType *LV = lhsType->getAs<VectorType>()) { - if (const VectorType *RV = rhsType->getAs<VectorType>()) { - if (LV->getElementType() == RV->getElementType() && - LV->getNumElements() == RV->getNumElements()) { - if (lhsType->isExtVectorType()) { - rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast); - return lhsType; - } - - lex = ImpCastExprToType(lex.take(), rhsType, CK_BitCast); - return rhsType; - } else if (Context.getTypeSize(lhsType) ==Context.getTypeSize(rhsType)){ - // If we are allowing lax vector conversions, and LHS and RHS are both - // vectors, the total size only needs to be the same. This is a - // bitcast; no bits are changed but the result type is different. - rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast); - return lhsType; - } - } - } - } - // Handle the case of equivalent AltiVec and GCC vector types if (lhsType->isVectorType() && rhsType->isVectorType() && Context.areCompatibleVectorTypes(lhsType, rhsType)) { - lex = ImpCastExprToType(lex.take(), rhsType, CK_BitCast); + if (lhsType->isExtVectorType()) { + rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast); + return lhsType; + } + + if (!isCompAssign) + lex = ImpCastExprToType(lex.take(), rhsType, CK_BitCast); return rhsType; } + if (getLangOptions().LaxVectorConversions && + Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType)) { + // If we are allowing lax vector conversions, and LHS and RHS are both + // vectors, the total size only needs to be the same. This is a + // bitcast; no bits are changed but the result type is different. + // FIXME: Should we really be allowing this? + rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast); + 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()) { + if (rhsType->isExtVectorType() && !isCompAssign) { swapped = true; std::swap(rex, lex); std::swap(rhsType, lhsType); @@ -5550,6 +5542,7 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, ExprResult &lex, ExprResu } // Vectors of different size or scalar and non-ext-vector are errors. + if (swapped) std::swap(rex, lex); Diag(Loc, diag::err_typecheck_vector_not_convertable) << lex.get()->getType() << rex.get()->getType() << lex.get()->getSourceRange() << rex.get()->getSourceRange(); @@ -5559,7 +5552,7 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, ExprResult &lex, ExprResu QualType Sema::CheckMultiplyDivideOperands( ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign, bool isDiv) { if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) - return CheckVectorOperands(Loc, lex, rex); + return CheckVectorOperands(lex, rex, Loc, isCompAssign); QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign); if (lex.isInvalid() || rex.isInvalid()) @@ -5583,7 +5576,7 @@ QualType Sema::CheckRemainderOperands( if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { if (lex.get()->getType()->hasIntegerRepresentation() && rex.get()->getType()->hasIntegerRepresentation()) - return CheckVectorOperands(Loc, lex, rex); + return CheckVectorOperands(lex, rex, Loc, isCompAssign); return InvalidOperands(Loc, lex, rex); } @@ -5605,7 +5598,7 @@ QualType Sema::CheckRemainderOperands( QualType Sema::CheckAdditionOperands( // C99 6.5.6 ExprResult &lex, ExprResult &rex, SourceLocation Loc, QualType* CompLHSTy) { if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { - QualType compType = CheckVectorOperands(Loc, lex, rex); + QualType compType = CheckVectorOperands(lex, rex, Loc, CompLHSTy); if (CompLHSTy) *CompLHSTy = compType; return compType; } @@ -5690,7 +5683,7 @@ QualType Sema::CheckAdditionOperands( // C99 6.5.6 QualType Sema::CheckSubtractionOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc, QualType* CompLHSTy) { if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { - QualType compType = CheckVectorOperands(Loc, lex, rex); + QualType compType = CheckVectorOperands(lex, rex, Loc, CompLHSTy); if (CompLHSTy) *CompLHSTy = compType; return compType; } @@ -5913,7 +5906,7 @@ QualType Sema::CheckShiftOperands(ExprResult &lex, ExprResult &rex, SourceLocati // Vector shifts promote their scalar inputs to vector type. if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) - return CheckVectorOperands(Loc, lex, rex); + return CheckVectorOperands(lex, rex, Loc, isCompAssign); // Shifts don't perform usual arithmetic conversions, they just do integer // promotions on each operand. C99 6.5.7p3 @@ -6382,7 +6375,7 @@ QualType Sema::CheckVectorCompareOperands(ExprResult &lex, ExprResult &rex, bool isRelational) { // Check to make sure we're operating on vectors of the same type and width, // Allowing one side to be a scalar of element type. - QualType vType = CheckVectorOperands(Loc, lex, rex); + QualType vType = CheckVectorOperands(lex, rex, Loc, /*isCompAssign*/false); if (vType.isNull()) return vType; @@ -6437,7 +6430,7 @@ inline QualType Sema::CheckBitwiseOperands( if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { if (lex.get()->getType()->hasIntegerRepresentation() && rex.get()->getType()->hasIntegerRepresentation()) - return CheckVectorOperands(Loc, lex, rex); + return CheckVectorOperands(lex, rex, Loc, isCompAssign); return InvalidOperands(Loc, lex, rex); } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c796f12f088..0cd707e1f58 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3636,7 +3636,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex // Extension: conditional operator involving vector types. if (LTy->isVectorType() || RTy->isVectorType()) - return CheckVectorOperands(QuestionLoc, LHS, RHS); + return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false); // -- The second and third operands have arithmetic or enumeration type; // the usual arithmetic conversions are performed to bring them to a diff --git a/clang/test/Sema/arm-neon-types.c b/clang/test/Sema/arm-neon-types.c index 1e8c9bf051e..4be83da970b 100644 --- a/clang/test/Sema/arm-neon-types.c +++ b/clang/test/Sema/arm-neon-types.c @@ -18,3 +18,10 @@ float32x2_t test3(uint32x2_t x) { // removed when that is fixed. return vcvt_n_f32_u32(x, 0); // expected-error {{argument should be a value from 1 to 32}} expected-error {{incompatible result type}} } + +typedef signed int vSInt32 __attribute__((__vector_size__(16))); +int32x4_t test4(int32x4_t a, vSInt32 b) { + a += b; + b += a; + return b += a; +} diff --git a/clang/test/Sema/ext_vector_casts.c b/clang/test/Sema/ext_vector_casts.c index 75d41ca077e..848ec1f106f 100644 --- a/clang/test/Sema/ext_vector_casts.c +++ b/clang/test/Sema/ext_vector_casts.c @@ -37,7 +37,7 @@ static void test() { 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 += vec4; // expected-error {{can't convert between vector values of different size ('int4' and 'float4')}} ivec4 += (int4)vec4; ivec4 -= ivec4; ivec4 |= ivec4; diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp index 9ae2c82fc53..4d3d93974c1 100644 --- a/clang/test/SemaCXX/vector.cpp +++ b/clang/test/SemaCXX/vector.cpp @@ -176,10 +176,10 @@ void test_implicit_conversions(bool Cond, char16 c16, longlong16 ll16, (void)(to_c16 * to_c16e); (void)(to_c16 / to_c16e); (void)(rto_c16 = c16e); // expected-error{{no viable overloaded '='}} - (void)(rto_c16 += to_c16e); // expected-error{{expression is not assignable}} - (void)(rto_c16 -= to_c16e); // expected-error{{expression is not assignable}} - (void)(rto_c16 *= to_c16e); // expected-error{{expression is not assignable}} - (void)(rto_c16 /= to_c16e); // expected-error{{expression is not assignable}} + (void)(rto_c16 += to_c16e); + (void)(rto_c16 -= to_c16e); + (void)(rto_c16 *= to_c16e); + (void)(rto_c16 /= to_c16e); (void)(Cond? to_c16 : to_c16e); (void)(Cond? to_ll16e : to_ll16); |