diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -9024,6 +9024,30 @@ S.AddBuiltinCandidate(LandR, Args, CandidateSet); } } + + // Extension: Add the binary bitwise operators for vector types + if (!CandidateTypes[0].vector_types().empty() && + !CandidateTypes[1].vector_types().empty()) { + // If both candidates have vector types, then add them pairwise... + for (QualType Vec1Ty : CandidateTypes[0].vector_types()) { + for (QualType Vec2Ty : CandidateTypes[1].vector_types()) { + QualType LandR[2] = {Vec1Ty, Vec2Ty}; + S.AddBuiltinCandidate(LandR, Args, CandidateSet); + } + } + } else { + // ...but if only one side has vector candidates, use that set of + // vector candidates pairwise for both sides of the operator + // (allowing splatting the scalar to a vector). + for (unsigned Candidate = 0; Candidate < 2; ++Candidate) { + for (QualType Vec1Ty : CandidateTypes[Candidate].vector_types()) { + for (QualType Vec2Ty : CandidateTypes[Candidate].vector_types()) { + QualType LandR[2] = {Vec1Ty, Vec2Ty}; + S.AddBuiltinCandidate(LandR, Args, CandidateSet); + } + } + } + } } // C++ [over.built]p20: @@ -9250,6 +9274,25 @@ }); } } + + // Extension: Add the binary operators %=, <<=, >>=, &=, ^=, |= for vector types. + for (QualType Vec1Ty : CandidateTypes[0].vector_types()) + for (QualType Vec2Ty : CandidateTypes[0].vector_types()) { + QualType ParamTypes[2]; + ParamTypes[1] = Vec2Ty; + // Add this built-in operator as a candidate (VQ is empty). + ParamTypes[0] = S.Context.getLValueReferenceType(Vec1Ty); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, + /*IsAssignmentOperator=*/false); + + // Add this built-in operator as a candidate (VQ is 'volatile'). + if (VisibleTypeConversionsQuals.hasVolatile()) { + ParamTypes[0] = S.Context.getVolatileType(Vec1Ty); + ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); + S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet, + /*IsAssignmentOperator=*/false); + } + } } // C++ [over.operator]p23: diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp --- a/clang/test/SemaCXX/vector.cpp +++ b/clang/test/SemaCXX/vector.cpp @@ -726,11 +726,10 @@ (void)(ea | v2ua); // expected-error{{cannot convert between vector values of different size}} (void)(v2ua ^ ea); // expected-error{{cannot convert between vector values of different size}} (void)(ea ^ v2ua); // expected-error{{cannot convert between vector values of different size}} - // FIXME: Vector/scalar shifts cause an assertion failure - // (void)(v2ua << ea); - // (void)(ea << v2ua); - // (void)(v2ua >> ea); - // (void)(ea >> v2ua); + (void)(v2ua << ea); + (void)(ea << v2ua); + (void)(v2ua >> ea); + (void)(ea >> v2ua); v2ua += ea; // expected-error{{cannot convert between vector values of different size}} v2ua -= ea; // expected-error{{cannot convert between vector values of different size}} @@ -740,9 +739,8 @@ v2ua &= ea; // expected-error{{cannot convert between vector values of different size}} v2ua |= ea; // expected-error{{cannot convert between vector values of different size}} v2ua ^= ea; // expected-error{{cannot convert between vector values of different size}} - // FIXME: Vector/scalar shifts cause an assertion failure - // v2ua >>= ea; - // v2ua <<= ea; + v2ua >>= ea; + v2ua <<= ea; ea += v2ua; // expected-error{{cannot convert between vector values of different size}} ea -= v2ua; // expected-error{{cannot convert between vector values of different size}} @@ -752,9 +750,8 @@ ea &= v2ua; // expected-error{{cannot convert between vector values of different size}} ea |= v2ua; // expected-error{{cannot convert between vector values of different size}} ea ^= v2ua; // expected-error{{cannot convert between vector values of different size}} - // FIXME: Vector/scalar shifts cause an assertion failure - // ea >>= v2ua; // not-expected-error{{assigning to 'enum Enum' from incompatible type 'v2u'}} - // ea <<= v2ua; // not-expected-error{{assigning to 'enum Enum' from incompatible type 'v2u'}} + ea >>= v2ua; // expected-error{{assigning to 'Enum' from incompatible type 'v2u'}} + ea <<= v2ua; // expected-error{{assigning to 'Enum' from incompatible type 'v2u'}} } #if __cplusplus >= 201103L // C++11 or later