@@ -14649,11 +14649,23 @@ void Sema::CheckAddressOfPackedMember(Expr *rhs) {
1464914649 _2, _3, _4));
1465014650}
1465114651
14652+ // Performs a similar job to Sema::UsualUnaryConversions, but without any
14653+ // implicit promotion of integral/enumeration types.
14654+ static ExprResult BuiltinVectorMathConversions(Sema &S, Expr *E) {
14655+ // First, convert to an r-value.
14656+ ExprResult Res = S.DefaultFunctionArrayLvalueConversion(E);
14657+ if (Res.isInvalid())
14658+ return ExprError();
14659+
14660+ // Promote floating-point types.
14661+ return S.UsualUnaryFPConversions(Res.get());
14662+ }
14663+
1465214664bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
1465314665 if (checkArgCount(TheCall, 1))
1465414666 return true;
1465514667
14656- ExprResult A = UsualUnaryConversions( TheCall->getArg(0));
14668+ ExprResult A = BuiltinVectorMathConversions(*this, TheCall->getArg(0));
1465714669 if (A.isInvalid())
1465814670 return true;
1465914671
@@ -14668,67 +14680,95 @@ bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
1466814680}
1466914681
1467014682bool Sema::BuiltinElementwiseMath(CallExpr *TheCall, bool FPOnly) {
14671- QualType Res;
14672- if (BuiltinVectorMath(TheCall, Res, FPOnly))
14673- return true ;
14674- TheCall->setType(Res);
14675- return false ;
14683+ if (auto Res = BuiltinVectorMath(TheCall, FPOnly); Res.has_value()) {
14684+ TheCall->setType(* Res);
14685+ return false ;
14686+ }
14687+ return true ;
1467614688}
1467714689
1467814690bool Sema::BuiltinVectorToScalarMath(CallExpr *TheCall) {
14679- QualType Res;
14680- if (BuiltinVectorMath(TheCall, Res) )
14691+ std::optional< QualType> Res = BuiltinVectorMath(TheCall) ;
14692+ if (! Res)
1468114693 return true;
1468214694
14683- if (auto *VecTy0 = Res->getAs<VectorType>())
14695+ if (auto *VecTy0 = (* Res) ->getAs<VectorType>())
1468414696 TheCall->setType(VecTy0->getElementType());
1468514697 else
14686- TheCall->setType(Res);
14698+ TheCall->setType(* Res);
1468714699
1468814700 return false;
1468914701}
1469014702
14691- bool Sema::BuiltinVectorMath(CallExpr *TheCall, QualType &Res, bool FPOnly) {
14703+ static bool checkBuiltinVectorMathMixedEnums(Sema &S, Expr *LHS, Expr *RHS,
14704+ SourceLocation Loc) {
14705+ QualType L = LHS->getEnumCoercedType(S.Context),
14706+ R = RHS->getEnumCoercedType(S.Context);
14707+ if (L->isUnscopedEnumerationType() && R->isUnscopedEnumerationType() &&
14708+ !S.Context.hasSameUnqualifiedType(L, R)) {
14709+ return S.Diag(Loc, diag::err_conv_mixed_enum_types_cxx26)
14710+ << LHS->getSourceRange() << RHS->getSourceRange()
14711+ << /*Arithmetic Between*/ 0 << L << R;
14712+ }
14713+ return false;
14714+ }
14715+
14716+ std::optional<QualType> Sema::BuiltinVectorMath(CallExpr *TheCall,
14717+ bool FPOnly) {
1469214718 if (checkArgCount(TheCall, 2))
14693- return true ;
14719+ return std::nullopt ;
1469414720
14695- ExprResult A = TheCall->getArg(0);
14696- ExprResult B = TheCall->getArg(1);
14697- // Do standard promotions between the two arguments, returning their common
14698- // type.
14699- Res = UsualArithmeticConversions(A, B, TheCall->getExprLoc(), ACK_Comparison);
14700- if (A.isInvalid() || B.isInvalid())
14701- return true;
14721+ if (checkBuiltinVectorMathMixedEnums(
14722+ *this, TheCall->getArg(0), TheCall->getArg(1), TheCall->getExprLoc()))
14723+ return std::nullopt;
1470214724
14703- QualType TyA = A.get()->getType();
14704- QualType TyB = B.get()->getType();
14725+ Expr *Args[2];
14726+ for (int I = 0; I < 2; ++I) {
14727+ ExprResult Converted =
14728+ BuiltinVectorMathConversions(*this, TheCall->getArg(I));
14729+ if (Converted.isInvalid())
14730+ return std::nullopt;
14731+ Args[I] = Converted.get();
14732+ }
1470514733
14706- if (Res.isNull() || TyA.getCanonicalType() != TyB.getCanonicalType())
14707- return Diag(A.get()->getBeginLoc(),
14708- diag::err_typecheck_call_different_arg_types)
14709- << TyA << TyB;
14734+ SourceLocation LocA = Args[0]->getBeginLoc();
14735+ QualType TyA = Args[0]->getType();
14736+ QualType TyB = Args[1]->getType();
14737+
14738+ if (TyA.getCanonicalType() != TyB.getCanonicalType()) {
14739+ Diag(LocA, diag::err_typecheck_call_different_arg_types) << TyA << TyB;
14740+ return std::nullopt;
14741+ }
1471014742
1471114743 if (FPOnly) {
14712- if (checkFPMathBuiltinElementType(*this, A.get()->getBeginLoc() , TyA, 1))
14713- return true ;
14744+ if (checkFPMathBuiltinElementType(*this, LocA , TyA, 1))
14745+ return std::nullopt ;
1471414746 } else {
14715- if (checkMathBuiltinElementType(*this, A.get()->getBeginLoc() , TyA, 1))
14716- return true ;
14747+ if (checkMathBuiltinElementType(*this, LocA , TyA, 1))
14748+ return std::nullopt ;
1471714749 }
1471814750
14719- TheCall->setArg(0, A.get() );
14720- TheCall->setArg(1, B.get() );
14721- return false ;
14751+ TheCall->setArg(0, Args[0] );
14752+ TheCall->setArg(1, Args[1] );
14753+ return TyA ;
1472214754}
1472314755
1472414756bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall,
1472514757 bool CheckForFloatArgs) {
1472614758 if (checkArgCount(TheCall, 3))
1472714759 return true;
1472814760
14761+ SourceLocation Loc = TheCall->getExprLoc();
14762+ if (checkBuiltinVectorMathMixedEnums(*this, TheCall->getArg(0),
14763+ TheCall->getArg(1), Loc) ||
14764+ checkBuiltinVectorMathMixedEnums(*this, TheCall->getArg(1),
14765+ TheCall->getArg(2), Loc))
14766+ return true;
14767+
1472914768 Expr *Args[3];
1473014769 for (int I = 0; I < 3; ++I) {
14731- ExprResult Converted = UsualUnaryConversions(TheCall->getArg(I));
14770+ ExprResult Converted =
14771+ BuiltinVectorMathConversions(*this, TheCall->getArg(I));
1473214772 if (Converted.isInvalid())
1473314773 return true;
1473414774 Args[I] = Converted.get();
0 commit comments