From: Douglas Gregor Date: Wed, 19 May 2010 03:21:00 +0000 (+0000) Subject: Implement C++ builtin operator candidates for vector types. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=26bcf67d0156e2aec6ea184f8c2fb6186ec7b1e3;p=clang Implement C++ builtin operator candidates for vector types. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104105 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8bc3d063b1..5e1f21b4c3 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -4929,7 +4929,13 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { if (const VectorType *RV = rhsType->getAs()) if (LV->getElementType() == RV->getElementType() && LV->getNumElements() == RV->getNumElements()) { - return lhsType->isExtVectorType() ? lhsType : rhsType; + if (lhsType->isExtVectorType()) { + ImpCastExprToType(rex, lhsType, CastExpr::CK_BitCast); + return lhsType; + } + + ImpCastExprToType(lex, rhsType, CastExpr::CK_BitCast); + return rhsType; } } } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 897ee66265..14042ea6ab 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -3774,6 +3774,10 @@ class BuiltinCandidateTypeSet { /// used in the built-in candidates. TypeSet EnumerationTypes; + /// \brief The set of vector types that will be used in the built-in + /// candidates. + TypeSet VectorTypes; + /// Sema - The semantic analysis instance where we are building the /// candidate type set. Sema &SemaRef; @@ -3815,6 +3819,9 @@ public: /// enumeration_end - Past the last enumeration type found; iterator enumeration_end() { return EnumerationTypes.end(); } + + iterator vector_begin() { return VectorTypes.begin(); } + iterator vector_end() { return VectorTypes.end(); } }; /// AddPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty to @@ -3947,6 +3954,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, return; } else if (Ty->isEnumeralType()) { EnumerationTypes.insert(Ty); + } else if (Ty->isVectorType()) { + VectorTypes.insert(Ty); } else if (AllowUserConversions) { if (const RecordType *TyRec = Ty->getAs()) { if (SemaRef.RequireCompleteType(Loc, Ty, 0)) { @@ -4111,21 +4120,14 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]); BuiltinCandidateTypeSet CandidateTypes(*this); - if (Op == OO_Less || Op == OO_Greater || Op == OO_LessEqual || - Op == OO_GreaterEqual || Op == OO_EqualEqual || Op == OO_ExclaimEqual || - Op == OO_Plus || (Op == OO_Minus && NumArgs == 2) || Op == OO_Equal || - Op == OO_PlusEqual || Op == OO_MinusEqual || Op == OO_Subscript || - Op == OO_ArrowStar || Op == OO_PlusPlus || Op == OO_MinusMinus || - (Op == OO_Star && NumArgs == 1) || Op == OO_Conditional) { - for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) - CandidateTypes.AddTypesConvertedFrom(Args[ArgIdx]->getType(), - OpLoc, - true, - (Op == OO_Exclaim || - Op == OO_AmpAmp || - Op == OO_PipePipe), - VisibleTypeConversionsQuals); - } + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) + CandidateTypes.AddTypesConvertedFrom(Args[ArgIdx]->getType(), + OpLoc, + true, + (Op == OO_Exclaim || + Op == OO_AmpAmp || + Op == OO_PipePipe), + VisibleTypeConversionsQuals); bool isComparison = false; switch (Op) { @@ -4289,6 +4291,14 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, QualType ArithTy = ArithmeticTypes[Arith]; AddBuiltinCandidate(ArithTy, &ArithTy, Args, 1, CandidateSet); } + + // Extension: We also add these operators for vector types. + for (BuiltinCandidateTypeSet::iterator Vec = CandidateTypes.vector_begin(), + VecEnd = CandidateTypes.vector_end(); + Vec != VecEnd; ++Vec) { + QualType VecTy = *Vec; + AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet); + } break; case OO_Tilde: @@ -4302,6 +4312,14 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, QualType IntTy = ArithmeticTypes[Int]; AddBuiltinCandidate(IntTy, &IntTy, Args, 1, CandidateSet); } + + // Extension: We also add this operator for vector types. + for (BuiltinCandidateTypeSet::iterator Vec = CandidateTypes.vector_begin(), + VecEnd = CandidateTypes.vector_end(); + Vec != VecEnd; ++Vec) { + QualType VecTy = *Vec; + AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet); + } break; case OO_New: @@ -4458,6 +4476,30 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); } } + + // Extension: Add the binary operators ==, !=, <, <=, >=, >, *, /, and the + // conditional operator for vector types. + for (BuiltinCandidateTypeSet::iterator Vec1 = CandidateTypes.vector_begin(), + Vec1End = CandidateTypes.vector_end(); + Vec1 != Vec1End; ++Vec1) + for (BuiltinCandidateTypeSet::iterator + Vec2 = CandidateTypes.vector_begin(), + Vec2End = CandidateTypes.vector_end(); + Vec2 != Vec2End; ++Vec2) { + QualType LandR[2] = { *Vec1, *Vec2 }; + QualType Result; + if (isComparison) + Result = Context.BoolTy; + else { + if ((*Vec1)->isExtVectorType() || !(*Vec2)->isExtVectorType()) + Result = *Vec1; + else + Result = *Vec2; + } + + AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); + } + break; case OO_Percent: @@ -4513,7 +4555,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, MemPtr != MemPtrEnd; ++MemPtr) AddBuiltinAssignmentOperatorCandidates(*this, *MemPtr, Args, 2, CandidateSet); - // Fall through. + + // Fall through. case OO_PlusEqual: case OO_MinusEqual: @@ -4588,6 +4631,30 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, } } } + + // Extension: Add the binary operators =, +=, -=, *=, /= for vector types. + for (BuiltinCandidateTypeSet::iterator Vec1 = CandidateTypes.vector_begin(), + Vec1End = CandidateTypes.vector_end(); + Vec1 != Vec1End; ++Vec1) + for (BuiltinCandidateTypeSet::iterator + Vec2 = CandidateTypes.vector_begin(), + Vec2End = CandidateTypes.vector_end(); + Vec2 != Vec2End; ++Vec2) { + QualType ParamTypes[2]; + ParamTypes[1] = *Vec2; + // Add this built-in operator as a candidate (VQ is empty). + ParamTypes[0] = Context.getLValueReferenceType(*Vec1); + AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/Op == OO_Equal); + + // Add this built-in operator as a candidate (VQ is 'volatile'). + if (VisibleTypeConversionsQuals.hasVolatile()) { + ParamTypes[0] = Context.getVolatileType(*Vec1); + ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]); + AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/Op == OO_Equal); + } + } break; case OO_PercentEqual: @@ -4683,7 +4750,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, ParamTypes[0] = ParamTypes[1]; ParamTypes[1] = *Ptr; AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); - } + } break; case OO_ArrowStar: diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp index e0fd1e770e..b548865553 100644 --- a/test/SemaCXX/vector.cpp +++ b/test/SemaCXX/vector.cpp @@ -101,16 +101,18 @@ void casts(longlong16 ll16, longlong16_e ll16e) { } template -struct convertible_to { +struct convertible_to { // expected-note 3 {{candidate function (the implicit copy assignment operator)}} operator T() const; }; -void test_implicit_conversions(char16 c16, longlong16 ll16, char16_e c16e, - longlong16_e ll16e, +void test_implicit_conversions(bool Cond, char16 c16, longlong16 ll16, + char16_e c16e, longlong16_e ll16e, convertible_to to_c16, convertible_to to_ll16, convertible_to to_c16e, - convertible_to to_ll16e) { + convertible_to to_ll16e, + convertible_to rto_c16, + convertible_to rto_c16e) { f0(to_c16); f0(to_ll16); f0(to_c16e); @@ -119,4 +121,68 @@ void test_implicit_conversions(char16 c16, longlong16 ll16, char16_e c16e, f2(to_ll16); f2(to_c16e); f2(to_ll16e); // expected-error{{no matching function}} + + (void)(c16 == c16e); + (void)(c16 == to_c16); + (void)+to_c16; + (void)-to_c16; + (void)~to_c16; + (void)(to_c16 == to_c16e); + (void)(to_c16 != to_c16e); + (void)(to_c16 < to_c16e); + (void)(to_c16 <= to_c16e); + (void)(to_c16 > to_c16e); + (void)(to_c16 >= to_c16e); + (void)(to_c16 + to_c16); + (void)(to_c16 - to_c16); + (void)(to_c16 * to_c16); + (void)(to_c16 / to_c16); + (void)(rto_c16 = to_c16); // expected-error{{no viable overloaded '='}} + (void)(rto_c16 += to_c16); + (void)(rto_c16 -= to_c16); + (void)(rto_c16 *= to_c16); + (void)(rto_c16 /= to_c16); + + (void)+to_c16e; + (void)-to_c16e; + (void)~to_c16e; + (void)(to_c16e == to_c16e); + (void)(to_c16e != to_c16e); + (void)(to_c16e < to_c16e); + (void)(to_c16e <= to_c16e); + (void)(to_c16e > to_c16e); + (void)(to_c16e >= to_c16e); + (void)(to_c16e + to_c16); + (void)(to_c16e - to_c16); + (void)(to_c16e * to_c16); + (void)(to_c16e / to_c16); + (void)(rto_c16e = to_c16); // expected-error{{no viable overloaded '='}} + (void)(rto_c16e += to_c16); + (void)(rto_c16e -= to_c16); + (void)(rto_c16e *= to_c16); + (void)(rto_c16e /= to_c16); + + (void)+to_c16; + (void)-to_c16; + (void)~to_c16; + (void)(to_c16 == to_c16e); + (void)(to_c16 != to_c16e); + (void)(to_c16 < to_c16e); + (void)(to_c16 <= to_c16e); + (void)(to_c16 > to_c16e); + (void)(to_c16 >= to_c16e); + (void)(to_c16 + to_c16e); + (void)(to_c16 - to_c16e); + (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)(Cond? to_c16 : to_c16e); + (void)(Cond? to_ll16e : to_ll16); + (void)(Cond? to_c16 : to_ll16); // expected-error{{can't convert between vector values of different size}} + (void)(Cond? to_c16e : to_ll16e); // expected-error{{can't convert between vector values of different size}} }