@@ -2711,7 +2711,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
27112711 // These builtins restrict the element type to floating point
27122712 // types only, and take in two arguments.
27132713 case Builtin::BI__builtin_elementwise_pow: {
2714- if (BuiltinElementwiseMath(TheCall))
2714+ if (BuiltinElementwiseMath(TheCall, true ))
27152715 return ExprError();
27162716
27172717 QualType ArgTy = TheCall->getArg(0)->getType();
@@ -2727,7 +2727,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
27272727 // types only.
27282728 case Builtin::BI__builtin_elementwise_add_sat:
27292729 case Builtin::BI__builtin_elementwise_sub_sat: {
2730- if (BuiltinElementwiseMath(TheCall))
2730+ if (BuiltinElementwiseMath(TheCall, false ))
27312731 return ExprError();
27322732
27332733 const Expr *Arg = TheCall->getArg(0);
@@ -2747,7 +2747,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
27472747
27482748 case Builtin::BI__builtin_elementwise_min:
27492749 case Builtin::BI__builtin_elementwise_max:
2750- if (BuiltinElementwiseMath(TheCall))
2750+ if (BuiltinElementwiseMath(TheCall, false ))
27512751 return ExprError();
27522752 break;
27532753
@@ -14899,11 +14899,23 @@ void Sema::CheckAddressOfPackedMember(Expr *rhs) {
1489914899 _2, _3, _4));
1490014900}
1490114901
14902+ // Performs a similar job to Sema::UsualUnaryConversions, but without any
14903+ // implicit promotion of integral/enumeration types.
14904+ static ExprResult BuiltinVectorMathConversions(Sema &S, Expr *E) {
14905+ // First, convert to an r-value.
14906+ ExprResult Res = S.DefaultFunctionArrayLvalueConversion(E);
14907+ if (Res.isInvalid())
14908+ return ExprError();
14909+
14910+ // Promote floating-point types.
14911+ return S.UsualUnaryFPConversions(Res.get());
14912+ }
14913+
1490214914bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
1490314915 if (checkArgCount(TheCall, 1))
1490414916 return true;
1490514917
14906- ExprResult A = UsualUnaryConversions( TheCall->getArg(0));
14918+ ExprResult A = BuiltinVectorMathConversions(*this, TheCall->getArg(0));
1490714919 if (A.isInvalid())
1490814920 return true;
1490914921
@@ -14917,63 +14929,96 @@ bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
1491714929 return false;
1491814930}
1491914931
14920- bool Sema::BuiltinElementwiseMath(CallExpr *TheCall) {
14921- QualType Res;
14922- if (BuiltinVectorMath(TheCall, Res))
14923- return true ;
14924- TheCall->setType(Res);
14925- return false ;
14932+ bool Sema::BuiltinElementwiseMath(CallExpr *TheCall, bool FPOnly ) {
14933+ if (auto Res = BuiltinVectorMath(TheCall, FPOnly); Res.has_value()) {
14934+ TheCall->setType(* Res);
14935+ return false ;
14936+ }
14937+ return true ;
1492614938}
1492714939
1492814940bool Sema::BuiltinVectorToScalarMath(CallExpr *TheCall) {
14929- QualType Res;
14930- if (BuiltinVectorMath(TheCall, Res) )
14941+ std::optional< QualType> Res = BuiltinVectorMath(TheCall) ;
14942+ if (! Res)
1493114943 return true;
1493214944
14933- if (auto *VecTy0 = Res->getAs<VectorType>())
14945+ if (auto *VecTy0 = (* Res) ->getAs<VectorType>())
1493414946 TheCall->setType(VecTy0->getElementType());
1493514947 else
14936- TheCall->setType(Res);
14948+ TheCall->setType(* Res);
1493714949
1493814950 return false;
1493914951}
1494014952
14941- bool Sema::BuiltinVectorMath(CallExpr *TheCall, QualType &Res) {
14953+ static bool checkBuiltinVectorMathMixedEnums(Sema &S, Expr *LHS, Expr *RHS,
14954+ SourceLocation Loc) {
14955+ QualType L = LHS->getEnumCoercedType(S.Context),
14956+ R = RHS->getEnumCoercedType(S.Context);
14957+ if (L->isUnscopedEnumerationType() && R->isUnscopedEnumerationType() &&
14958+ !S.Context.hasSameUnqualifiedType(L, R)) {
14959+ return S.Diag(Loc, diag::err_conv_mixed_enum_types_cxx26)
14960+ << LHS->getSourceRange() << RHS->getSourceRange()
14961+ << /*Arithmetic Between*/ 0 << L << R;
14962+ }
14963+ return false;
14964+ }
14965+
14966+ std::optional<QualType> Sema::BuiltinVectorMath(CallExpr *TheCall,
14967+ bool FPOnly) {
1494214968 if (checkArgCount(TheCall, 2))
14943- return true ;
14969+ return std::nullopt ;
1494414970
14945- ExprResult A = TheCall->getArg(0);
14946- ExprResult B = TheCall->getArg(1);
14947- // Do standard promotions between the two arguments, returning their common
14948- // type.
14949- Res = UsualArithmeticConversions(A, B, TheCall->getExprLoc(), ACK_Comparison);
14950- if (A.isInvalid() || B.isInvalid())
14951- return true;
14971+ if (checkBuiltinVectorMathMixedEnums(
14972+ *this, TheCall->getArg(0), TheCall->getArg(1), TheCall->getExprLoc()))
14973+ return std::nullopt;
1495214974
14953- QualType TyA = A.get()->getType();
14954- QualType TyB = B.get()->getType();
14975+ Expr *Args[2];
14976+ for (int I = 0; I < 2; ++I) {
14977+ ExprResult Converted =
14978+ BuiltinVectorMathConversions(*this, TheCall->getArg(I));
14979+ if (Converted.isInvalid())
14980+ return std::nullopt;
14981+ Args[I] = Converted.get();
14982+ }
1495514983
14956- if (Res.isNull() || TyA.getCanonicalType() != TyB.getCanonicalType())
14957- return Diag(A.get()->getBeginLoc(),
14958- diag::err_typecheck_call_different_arg_types)
14959- << TyA << TyB;
14984+ SourceLocation LocA = Args[0]->getBeginLoc();
14985+ QualType TyA = Args[0]->getType();
14986+ QualType TyB = Args[1]->getType();
1496014987
14961- if (checkMathBuiltinElementType(*this, A.get()->getBeginLoc(), TyA, 1))
14962- return true;
14988+ if (TyA.getCanonicalType() != TyB.getCanonicalType()) {
14989+ Diag(LocA, diag::err_typecheck_call_different_arg_types) << TyA << TyB;
14990+ return std::nullopt;
14991+ }
1496314992
14964- TheCall->setArg(0, A.get());
14965- TheCall->setArg(1, B.get());
14966- return false;
14993+ if (FPOnly) {
14994+ if (checkFPMathBuiltinElementType(*this, LocA, TyA, 1))
14995+ return std::nullopt;
14996+ } else {
14997+ if (checkMathBuiltinElementType(*this, LocA, TyA, 1))
14998+ return std::nullopt;
14999+ }
15000+
15001+ TheCall->setArg(0, Args[0]);
15002+ TheCall->setArg(1, Args[1]);
15003+ return TyA;
1496715004}
1496815005
1496915006bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall,
1497015007 bool CheckForFloatArgs) {
1497115008 if (checkArgCount(TheCall, 3))
1497215009 return true;
1497315010
15011+ SourceLocation Loc = TheCall->getExprLoc();
15012+ if (checkBuiltinVectorMathMixedEnums(*this, TheCall->getArg(0),
15013+ TheCall->getArg(1), Loc) ||
15014+ checkBuiltinVectorMathMixedEnums(*this, TheCall->getArg(1),
15015+ TheCall->getArg(2), Loc))
15016+ return true;
15017+
1497415018 Expr *Args[3];
1497515019 for (int I = 0; I < 3; ++I) {
14976- ExprResult Converted = UsualUnaryConversions(TheCall->getArg(I));
15020+ ExprResult Converted =
15021+ BuiltinVectorMathConversions(*this, TheCall->getArg(I));
1497715022 if (Converted.isInvalid())
1497815023 return true;
1497915024 Args[I] = Converted.get();
@@ -15010,7 +15055,7 @@ bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall,
1501015055 return false;
1501115056}
1501215057
15013- bool Sema::PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall) {
15058+ bool Sema::PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall, bool FPOnly ) {
1501415059 if (checkArgCount(TheCall, 1))
1501515060 return true;
1501615061
0 commit comments