@@ -2711,7 +2711,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
2711
2711
// These builtins restrict the element type to floating point
2712
2712
// types only, and take in two arguments.
2713
2713
case Builtin::BI__builtin_elementwise_pow: {
2714
- if (BuiltinElementwiseMath(TheCall))
2714
+ if (BuiltinElementwiseMath(TheCall, true ))
2715
2715
return ExprError();
2716
2716
2717
2717
QualType ArgTy = TheCall->getArg(0)->getType();
@@ -2727,7 +2727,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
2727
2727
// types only.
2728
2728
case Builtin::BI__builtin_elementwise_add_sat:
2729
2729
case Builtin::BI__builtin_elementwise_sub_sat: {
2730
- if (BuiltinElementwiseMath(TheCall))
2730
+ if (BuiltinElementwiseMath(TheCall, false ))
2731
2731
return ExprError();
2732
2732
2733
2733
const Expr *Arg = TheCall->getArg(0);
@@ -2747,7 +2747,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
2747
2747
2748
2748
case Builtin::BI__builtin_elementwise_min:
2749
2749
case Builtin::BI__builtin_elementwise_max:
2750
- if (BuiltinElementwiseMath(TheCall))
2750
+ if (BuiltinElementwiseMath(TheCall, false ))
2751
2751
return ExprError();
2752
2752
break;
2753
2753
@@ -14899,11 +14899,23 @@ void Sema::CheckAddressOfPackedMember(Expr *rhs) {
14899
14899
_2, _3, _4));
14900
14900
}
14901
14901
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
+
14902
14914
bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
14903
14915
if (checkArgCount(TheCall, 1))
14904
14916
return true;
14905
14917
14906
- ExprResult A = UsualUnaryConversions( TheCall->getArg(0));
14918
+ ExprResult A = BuiltinVectorMathConversions(*this, TheCall->getArg(0));
14907
14919
if (A.isInvalid())
14908
14920
return true;
14909
14921
@@ -14917,63 +14929,96 @@ bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
14917
14929
return false;
14918
14930
}
14919
14931
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 ;
14926
14938
}
14927
14939
14928
14940
bool Sema::BuiltinVectorToScalarMath(CallExpr *TheCall) {
14929
- QualType Res;
14930
- if (BuiltinVectorMath(TheCall, Res) )
14941
+ std::optional< QualType> Res = BuiltinVectorMath(TheCall) ;
14942
+ if (! Res)
14931
14943
return true;
14932
14944
14933
- if (auto *VecTy0 = Res->getAs<VectorType>())
14945
+ if (auto *VecTy0 = (* Res) ->getAs<VectorType>())
14934
14946
TheCall->setType(VecTy0->getElementType());
14935
14947
else
14936
- TheCall->setType(Res);
14948
+ TheCall->setType(* Res);
14937
14949
14938
14950
return false;
14939
14951
}
14940
14952
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) {
14942
14968
if (checkArgCount(TheCall, 2))
14943
- return true ;
14969
+ return std::nullopt ;
14944
14970
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;
14952
14974
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
+ }
14955
14983
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();
14960
14987
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
+ }
14963
14992
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;
14967
15004
}
14968
15005
14969
15006
bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall,
14970
15007
bool CheckForFloatArgs) {
14971
15008
if (checkArgCount(TheCall, 3))
14972
15009
return true;
14973
15010
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
+
14974
15018
Expr *Args[3];
14975
15019
for (int I = 0; I < 3; ++I) {
14976
- ExprResult Converted = UsualUnaryConversions(TheCall->getArg(I));
15020
+ ExprResult Converted =
15021
+ BuiltinVectorMathConversions(*this, TheCall->getArg(I));
14977
15022
if (Converted.isInvalid())
14978
15023
return true;
14979
15024
Args[I] = Converted.get();
@@ -15010,7 +15055,7 @@ bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall,
15010
15055
return false;
15011
15056
}
15012
15057
15013
- bool Sema::PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall) {
15058
+ bool Sema::PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall, bool FPOnly ) {
15014
15059
if (checkArgCount(TheCall, 1))
15015
15060
return true;
15016
15061
0 commit comments