@@ -1968,26 +1968,40 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
19681968// Check if \p Ty is a valid type for the elementwise math builtins. If it is
19691969// not a valid type, emit an error message and return true. Otherwise return
19701970// false.
1971- static bool checkMathBuiltinElementType(Sema &S, SourceLocation Loc,
1972- QualType ArgTy, int ArgIndex) {
1973- if (!ArgTy->getAs<VectorType>() &&
1974- !ConstantMatrixType::isValidElementType(ArgTy)) {
1975- return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1976- << ArgIndex << /* vector, integer or float ty*/ 0 << ArgTy;
1977- }
1978-
1979- return false;
1980- }
1981-
1982- static bool checkFPMathBuiltinElementType(Sema &S, SourceLocation Loc,
1983- QualType ArgTy, int ArgIndex) {
1971+ static bool
1972+ checkMathBuiltinElementType(Sema &S, SourceLocation Loc, QualType ArgTy,
1973+ Sema::EltwiseBuiltinArgTyRestriction ArgTyRestr,
1974+ int ArgOrdinal) {
19841975 QualType EltTy = ArgTy;
19851976 if (auto *VecTy = EltTy->getAs<VectorType>())
19861977 EltTy = VecTy->getElementType();
19871978
1988- if (!EltTy->isRealFloatingType()) {
1989- return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1990- << ArgIndex << /* vector or float ty*/ 5 << ArgTy;
1979+ switch (ArgTyRestr) {
1980+ case Sema::EltwiseBuiltinArgTyRestriction::None:
1981+ if (!ArgTy->getAs<VectorType>() &&
1982+ !ConstantMatrixType::isValidElementType(ArgTy)) {
1983+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1984+ << ArgOrdinal << /* vector, integer or float ty*/ 0 << ArgTy;
1985+ }
1986+ break;
1987+ case Sema::EltwiseBuiltinArgTyRestriction::FloatTy:
1988+ if (!EltTy->isRealFloatingType()) {
1989+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1990+ << ArgOrdinal << /* vector or float ty*/ 5 << ArgTy;
1991+ }
1992+ break;
1993+ case Sema::EltwiseBuiltinArgTyRestriction::IntegerTy:
1994+ if (!EltTy->isIntegerType()) {
1995+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1996+ << ArgOrdinal << /* vector or int ty*/ 10 << ArgTy;
1997+ }
1998+ break;
1999+ case Sema::EltwiseBuiltinArgTyRestriction::SignedIntOrFloatTy:
2000+ if (EltTy->isUnsignedIntegerType()) {
2001+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
2002+ << 1 << /* signed integer or float ty*/ 3 << ArgTy;
2003+ }
2004+ break;
19912005 }
19922006
19932007 return false;
@@ -2694,23 +2708,11 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
26942708
26952709 // __builtin_elementwise_abs restricts the element type to signed integers or
26962710 // floating point types only.
2697- case Builtin::BI__builtin_elementwise_abs: {
2698- if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
2711+ case Builtin::BI__builtin_elementwise_abs:
2712+ if (PrepareBuiltinElementwiseMathOneArgCall(
2713+ TheCall, EltwiseBuiltinArgTyRestriction::SignedIntOrFloatTy))
26992714 return ExprError();
2700-
2701- QualType ArgTy = TheCall->getArg(0)->getType();
2702- QualType EltTy = ArgTy;
2703-
2704- if (auto *VecTy = EltTy->getAs<VectorType>())
2705- EltTy = VecTy->getElementType();
2706- if (EltTy->isUnsignedIntegerType()) {
2707- Diag(TheCall->getArg(0)->getBeginLoc(),
2708- diag::err_builtin_invalid_arg_type)
2709- << 1 << /* signed integer or float ty*/ 3 << ArgTy;
2710- return ExprError();
2711- }
27122715 break;
2713- }
27142716
27152717 // These builtins restrict the element type to floating point
27162718 // types only.
@@ -2736,81 +2738,46 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
27362738 case Builtin::BI__builtin_elementwise_tan:
27372739 case Builtin::BI__builtin_elementwise_tanh:
27382740 case Builtin::BI__builtin_elementwise_trunc:
2739- case Builtin::BI__builtin_elementwise_canonicalize: {
2740- if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
2741- return ExprError();
2742-
2743- QualType ArgTy = TheCall->getArg(0)->getType();
2744- if (checkFPMathBuiltinElementType(*this, TheCall->getArg(0)->getBeginLoc(),
2745- ArgTy, 1))
2741+ case Builtin::BI__builtin_elementwise_canonicalize:
2742+ if (PrepareBuiltinElementwiseMathOneArgCall(
2743+ TheCall, EltwiseBuiltinArgTyRestriction::FloatTy))
27462744 return ExprError();
27472745 break;
2748- }
2749- case Builtin::BI__builtin_elementwise_fma: {
2746+ case Builtin::BI__builtin_elementwise_fma:
27502747 if (BuiltinElementwiseTernaryMath(TheCall))
27512748 return ExprError();
27522749 break;
2753- }
27542750
27552751 // These builtins restrict the element type to floating point
27562752 // types only, and take in two arguments.
27572753 case Builtin::BI__builtin_elementwise_minimum:
27582754 case Builtin::BI__builtin_elementwise_maximum:
27592755 case Builtin::BI__builtin_elementwise_atan2:
27602756 case Builtin::BI__builtin_elementwise_fmod:
2761- case Builtin::BI__builtin_elementwise_pow: {
2762- if (BuiltinElementwiseMath(TheCall, /*FPOnly=*/true))
2757+ case Builtin::BI__builtin_elementwise_pow:
2758+ if (BuiltinElementwiseMath(TheCall,
2759+ EltwiseBuiltinArgTyRestriction::FloatTy))
27632760 return ExprError();
27642761 break;
2765- }
2766-
27672762 // These builtins restrict the element type to integer
27682763 // types only.
27692764 case Builtin::BI__builtin_elementwise_add_sat:
2770- case Builtin::BI__builtin_elementwise_sub_sat: {
2771- if (BuiltinElementwiseMath(TheCall))
2772- return ExprError();
2773-
2774- const Expr *Arg = TheCall->getArg(0);
2775- QualType ArgTy = Arg->getType();
2776- QualType EltTy = ArgTy;
2777-
2778- if (auto *VecTy = EltTy->getAs<VectorType>())
2779- EltTy = VecTy->getElementType();
2780-
2781- if (!EltTy->isIntegerType()) {
2782- Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
2783- << 1 << /* integer ty */ 6 << ArgTy;
2765+ case Builtin::BI__builtin_elementwise_sub_sat:
2766+ if (BuiltinElementwiseMath(TheCall,
2767+ EltwiseBuiltinArgTyRestriction::IntegerTy))
27842768 return ExprError();
2785- }
27862769 break;
2787- }
2788-
27892770 case Builtin::BI__builtin_elementwise_min:
27902771 case Builtin::BI__builtin_elementwise_max:
27912772 if (BuiltinElementwiseMath(TheCall))
27922773 return ExprError();
27932774 break;
27942775 case Builtin::BI__builtin_elementwise_popcount:
2795- case Builtin::BI__builtin_elementwise_bitreverse: {
2796- if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
2797- return ExprError();
2798-
2799- const Expr *Arg = TheCall->getArg(0);
2800- QualType ArgTy = Arg->getType();
2801- QualType EltTy = ArgTy;
2802-
2803- if (auto *VecTy = EltTy->getAs<VectorType>())
2804- EltTy = VecTy->getElementType();
2805-
2806- if (!EltTy->isIntegerType()) {
2807- Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
2808- << 1 << /* integer ty */ 6 << ArgTy;
2776+ case Builtin::BI__builtin_elementwise_bitreverse:
2777+ if (PrepareBuiltinElementwiseMathOneArgCall(
2778+ TheCall, EltwiseBuiltinArgTyRestriction::IntegerTy))
28092779 return ExprError();
2810- }
28112780 break;
2812- }
2813-
28142781 case Builtin::BI__builtin_elementwise_copysign: {
28152782 if (checkArgCount(TheCall, 2))
28162783 return ExprError();
@@ -2822,10 +2789,12 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
28222789
28232790 QualType MagnitudeTy = Magnitude.get()->getType();
28242791 QualType SignTy = Sign.get()->getType();
2825- if (checkFPMathBuiltinElementType(*this, TheCall->getArg(0)->getBeginLoc(),
2826- MagnitudeTy, 1) ||
2827- checkFPMathBuiltinElementType(*this, TheCall->getArg(1)->getBeginLoc(),
2828- SignTy, 2)) {
2792+ if (checkMathBuiltinElementType(
2793+ *this, TheCall->getArg(0)->getBeginLoc(), MagnitudeTy,
2794+ EltwiseBuiltinArgTyRestriction::FloatTy, 1) ||
2795+ checkMathBuiltinElementType(
2796+ *this, TheCall->getArg(1)->getBeginLoc(), SignTy,
2797+ EltwiseBuiltinArgTyRestriction::FloatTy, 2)) {
28292798 return ExprError();
28302799 }
28312800
@@ -14661,7 +14630,8 @@ static ExprResult BuiltinVectorMathConversions(Sema &S, Expr *E) {
1466114630 return S.UsualUnaryFPConversions(Res.get());
1466214631}
1466314632
14664- bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
14633+ bool Sema::PrepareBuiltinElementwiseMathOneArgCall(
14634+ CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr) {
1466514635 if (checkArgCount(TheCall, 1))
1466614636 return true;
1466714637
@@ -14672,15 +14642,17 @@ bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
1467214642 TheCall->setArg(0, A.get());
1467314643 QualType TyA = A.get()->getType();
1467414644
14675- if (checkMathBuiltinElementType(*this, A.get()->getBeginLoc(), TyA, 1))
14645+ if (checkMathBuiltinElementType(*this, A.get()->getBeginLoc(), TyA,
14646+ ArgTyRestr, 1))
1467614647 return true;
1467714648
1467814649 TheCall->setType(TyA);
1467914650 return false;
1468014651}
1468114652
14682- bool Sema::BuiltinElementwiseMath(CallExpr *TheCall, bool FPOnly) {
14683- if (auto Res = BuiltinVectorMath(TheCall, FPOnly); Res.has_value()) {
14653+ bool Sema::BuiltinElementwiseMath(CallExpr *TheCall,
14654+ EltwiseBuiltinArgTyRestriction ArgTyRestr) {
14655+ if (auto Res = BuiltinVectorMath(TheCall, ArgTyRestr); Res.has_value()) {
1468414656 TheCall->setType(*Res);
1468514657 return false;
1468614658 }
@@ -14713,8 +14685,9 @@ static bool checkBuiltinVectorMathMixedEnums(Sema &S, Expr *LHS, Expr *RHS,
1471314685 return false;
1471414686}
1471514687
14716- std::optional<QualType> Sema::BuiltinVectorMath(CallExpr *TheCall,
14717- bool FPOnly) {
14688+ std::optional<QualType>
14689+ Sema::BuiltinVectorMath(CallExpr *TheCall,
14690+ EltwiseBuiltinArgTyRestriction ArgTyRestr) {
1471814691 if (checkArgCount(TheCall, 2))
1471914692 return std::nullopt;
1472014693
@@ -14735,26 +14708,21 @@ std::optional<QualType> Sema::BuiltinVectorMath(CallExpr *TheCall,
1473514708 QualType TyA = Args[0]->getType();
1473614709 QualType TyB = Args[1]->getType();
1473714710
14711+ if (checkMathBuiltinElementType(*this, LocA, TyA, ArgTyRestr, 1))
14712+ return std::nullopt;
14713+
1473814714 if (TyA.getCanonicalType() != TyB.getCanonicalType()) {
1473914715 Diag(LocA, diag::err_typecheck_call_different_arg_types) << TyA << TyB;
1474014716 return std::nullopt;
1474114717 }
1474214718
14743- if (FPOnly) {
14744- if (checkFPMathBuiltinElementType(*this, LocA, TyA, 1))
14745- return std::nullopt;
14746- } else {
14747- if (checkMathBuiltinElementType(*this, LocA, TyA, 1))
14748- return std::nullopt;
14749- }
14750-
1475114719 TheCall->setArg(0, Args[0]);
1475214720 TheCall->setArg(1, Args[1]);
1475314721 return TyA;
1475414722}
1475514723
14756- bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall,
14757- bool CheckForFloatArgs ) {
14724+ bool Sema::BuiltinElementwiseTernaryMath(
14725+ CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr ) {
1475814726 if (checkArgCount(TheCall, 3))
1475914727 return true;
1476014728
@@ -14774,20 +14742,11 @@ bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall,
1477414742 Args[I] = Converted.get();
1477514743 }
1477614744
14777- if (CheckForFloatArgs) {
14778- int ArgOrdinal = 1;
14779- for (Expr *Arg : Args) {
14780- if (checkFPMathBuiltinElementType(*this, Arg->getBeginLoc(),
14781- Arg->getType(), ArgOrdinal++))
14782- return true;
14783- }
14784- } else {
14785- int ArgOrdinal = 1;
14786- for (Expr *Arg : Args) {
14787- if (checkMathBuiltinElementType(*this, Arg->getBeginLoc(), Arg->getType(),
14788- ArgOrdinal++))
14789- return true;
14790- }
14745+ int ArgOrdinal = 1;
14746+ for (Expr *Arg : Args) {
14747+ if (checkMathBuiltinElementType(*this, Arg->getBeginLoc(), Arg->getType(),
14748+ ArgTyRestr, ArgOrdinal++))
14749+ return true;
1479114750 }
1479214751
1479314752 for (int I = 1; I < 3; ++I) {
0 commit comments