@@ -1970,26 +1970,40 @@ bool Sema::CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
19701970// Check if \p Ty is a valid type for the elementwise math builtins. If it is
19711971// not a valid type, emit an error message and return true. Otherwise return
19721972// false.
1973- static bool checkMathBuiltinElementType(Sema &S, SourceLocation Loc,
1974- QualType ArgTy, int ArgIndex) {
1975- if (!ArgTy->getAs<VectorType>() &&
1976- !ConstantMatrixType::isValidElementType(ArgTy)) {
1977- return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1978- << ArgIndex << /* vector, integer or float ty*/ 0 << ArgTy;
1979- }
1980-
1981- return false;
1982- }
1983-
1984- static bool checkFPMathBuiltinElementType(Sema &S, SourceLocation Loc,
1985- QualType ArgTy, int ArgIndex) {
1973+ static bool
1974+ checkMathBuiltinElementType(Sema &S, SourceLocation Loc, QualType ArgTy,
1975+ Sema::EltwiseBuiltinArgTyRestriction ArgTyRestr,
1976+ int ArgOrdinal) {
19861977 QualType EltTy = ArgTy;
19871978 if (auto *VecTy = EltTy->getAs<VectorType>())
19881979 EltTy = VecTy->getElementType();
19891980
1990- if (!EltTy->isRealFloatingType()) {
1991- return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1992- << ArgIndex << /* vector or float ty*/ 5 << ArgTy;
1981+ switch (ArgTyRestr) {
1982+ case Sema::EltwiseBuiltinArgTyRestriction::None:
1983+ if (!ArgTy->getAs<VectorType>() &&
1984+ !ConstantMatrixType::isValidElementType(ArgTy)) {
1985+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1986+ << ArgOrdinal << /* vector, integer or float ty*/ 0 << ArgTy;
1987+ }
1988+ break;
1989+ case Sema::EltwiseBuiltinArgTyRestriction::FloatTy:
1990+ if (!EltTy->isRealFloatingType()) {
1991+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1992+ << ArgOrdinal << /* vector or float ty*/ 5 << ArgTy;
1993+ }
1994+ break;
1995+ case Sema::EltwiseBuiltinArgTyRestriction::IntegerTy:
1996+ if (!EltTy->isIntegerType()) {
1997+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
1998+ << ArgOrdinal << /* vector or int ty*/ 10 << ArgTy;
1999+ }
2000+ break;
2001+ case Sema::EltwiseBuiltinArgTyRestriction::SignedIntOrFloatTy:
2002+ if (EltTy->isUnsignedIntegerType()) {
2003+ return S.Diag(Loc, diag::err_builtin_invalid_arg_type)
2004+ << 1 << /* signed integer or float ty*/ 3 << ArgTy;
2005+ }
2006+ break;
19932007 }
19942008
19952009 return false;
@@ -2695,23 +2709,11 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
26952709
26962710 // __builtin_elementwise_abs restricts the element type to signed integers or
26972711 // floating point types only.
2698- case Builtin::BI__builtin_elementwise_abs: {
2699- if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
2712+ case Builtin::BI__builtin_elementwise_abs:
2713+ if (PrepareBuiltinElementwiseMathOneArgCall(
2714+ TheCall, EltwiseBuiltinArgTyRestriction::SignedIntOrFloatTy))
27002715 return ExprError();
2701-
2702- QualType ArgTy = TheCall->getArg(0)->getType();
2703- QualType EltTy = ArgTy;
2704-
2705- if (auto *VecTy = EltTy->getAs<VectorType>())
2706- EltTy = VecTy->getElementType();
2707- if (EltTy->isUnsignedIntegerType()) {
2708- Diag(TheCall->getArg(0)->getBeginLoc(),
2709- diag::err_builtin_invalid_arg_type)
2710- << 1 << /* signed integer or float ty*/ 3 << ArgTy;
2711- return ExprError();
2712- }
27132716 break;
2714- }
27152717
27162718 // These builtins restrict the element type to floating point
27172719 // types only.
@@ -2737,81 +2739,46 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
27372739 case Builtin::BI__builtin_elementwise_tan:
27382740 case Builtin::BI__builtin_elementwise_tanh:
27392741 case Builtin::BI__builtin_elementwise_trunc:
2740- case Builtin::BI__builtin_elementwise_canonicalize: {
2741- if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
2742- return ExprError();
2743-
2744- QualType ArgTy = TheCall->getArg(0)->getType();
2745- if (checkFPMathBuiltinElementType(*this, TheCall->getArg(0)->getBeginLoc(),
2746- ArgTy, 1))
2742+ case Builtin::BI__builtin_elementwise_canonicalize:
2743+ if (PrepareBuiltinElementwiseMathOneArgCall(
2744+ TheCall, EltwiseBuiltinArgTyRestriction::FloatTy))
27472745 return ExprError();
27482746 break;
2749- }
2750- case Builtin::BI__builtin_elementwise_fma: {
2747+ case Builtin::BI__builtin_elementwise_fma:
27512748 if (BuiltinElementwiseTernaryMath(TheCall))
27522749 return ExprError();
27532750 break;
2754- }
27552751
27562752 // These builtins restrict the element type to floating point
27572753 // types only, and take in two arguments.
27582754 case Builtin::BI__builtin_elementwise_minimum:
27592755 case Builtin::BI__builtin_elementwise_maximum:
27602756 case Builtin::BI__builtin_elementwise_atan2:
27612757 case Builtin::BI__builtin_elementwise_fmod:
2762- case Builtin::BI__builtin_elementwise_pow: {
2763- if (BuiltinElementwiseMath(TheCall, /*FPOnly=*/true))
2758+ case Builtin::BI__builtin_elementwise_pow:
2759+ if (BuiltinElementwiseMath(TheCall,
2760+ EltwiseBuiltinArgTyRestriction::FloatTy))
27642761 return ExprError();
27652762 break;
2766- }
2767-
27682763 // These builtins restrict the element type to integer
27692764 // types only.
27702765 case Builtin::BI__builtin_elementwise_add_sat:
2771- case Builtin::BI__builtin_elementwise_sub_sat: {
2772- if (BuiltinElementwiseMath(TheCall))
2773- return ExprError();
2774-
2775- const Expr *Arg = TheCall->getArg(0);
2776- QualType ArgTy = Arg->getType();
2777- QualType EltTy = ArgTy;
2778-
2779- if (auto *VecTy = EltTy->getAs<VectorType>())
2780- EltTy = VecTy->getElementType();
2781-
2782- if (!EltTy->isIntegerType()) {
2783- Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
2784- << 1 << /* integer ty */ 6 << ArgTy;
2766+ case Builtin::BI__builtin_elementwise_sub_sat:
2767+ if (BuiltinElementwiseMath(TheCall,
2768+ EltwiseBuiltinArgTyRestriction::IntegerTy))
27852769 return ExprError();
2786- }
27872770 break;
2788- }
2789-
27902771 case Builtin::BI__builtin_elementwise_min:
27912772 case Builtin::BI__builtin_elementwise_max:
27922773 if (BuiltinElementwiseMath(TheCall))
27932774 return ExprError();
27942775 break;
27952776 case Builtin::BI__builtin_elementwise_popcount:
2796- case Builtin::BI__builtin_elementwise_bitreverse: {
2797- if (PrepareBuiltinElementwiseMathOneArgCall(TheCall))
2798- return ExprError();
2799-
2800- const Expr *Arg = TheCall->getArg(0);
2801- QualType ArgTy = Arg->getType();
2802- QualType EltTy = ArgTy;
2803-
2804- if (auto *VecTy = EltTy->getAs<VectorType>())
2805- EltTy = VecTy->getElementType();
2806-
2807- if (!EltTy->isIntegerType()) {
2808- Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
2809- << 1 << /* integer ty */ 6 << ArgTy;
2777+ case Builtin::BI__builtin_elementwise_bitreverse:
2778+ if (PrepareBuiltinElementwiseMathOneArgCall(
2779+ TheCall, EltwiseBuiltinArgTyRestriction::IntegerTy))
28102780 return ExprError();
2811- }
28122781 break;
2813- }
2814-
28152782 case Builtin::BI__builtin_elementwise_copysign: {
28162783 if (checkArgCount(TheCall, 2))
28172784 return ExprError();
@@ -2823,10 +2790,12 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
28232790
28242791 QualType MagnitudeTy = Magnitude.get()->getType();
28252792 QualType SignTy = Sign.get()->getType();
2826- if (checkFPMathBuiltinElementType(*this, TheCall->getArg(0)->getBeginLoc(),
2827- MagnitudeTy, 1) ||
2828- checkFPMathBuiltinElementType(*this, TheCall->getArg(1)->getBeginLoc(),
2829- SignTy, 2)) {
2793+ if (checkMathBuiltinElementType(
2794+ *this, TheCall->getArg(0)->getBeginLoc(), MagnitudeTy,
2795+ EltwiseBuiltinArgTyRestriction::FloatTy, 1) ||
2796+ checkMathBuiltinElementType(
2797+ *this, TheCall->getArg(1)->getBeginLoc(), SignTy,
2798+ EltwiseBuiltinArgTyRestriction::FloatTy, 2)) {
28302799 return ExprError();
28312800 }
28322801
@@ -14666,7 +14635,8 @@ static ExprResult BuiltinVectorMathConversions(Sema &S, Expr *E) {
1466614635 return S.UsualUnaryFPConversions(Res.get());
1466714636}
1466814637
14669- bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
14638+ bool Sema::PrepareBuiltinElementwiseMathOneArgCall(
14639+ CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr) {
1467014640 if (checkArgCount(TheCall, 1))
1467114641 return true;
1467214642
@@ -14677,15 +14647,17 @@ bool Sema::PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall) {
1467714647 TheCall->setArg(0, A.get());
1467814648 QualType TyA = A.get()->getType();
1467914649
14680- if (checkMathBuiltinElementType(*this, A.get()->getBeginLoc(), TyA, 1))
14650+ if (checkMathBuiltinElementType(*this, A.get()->getBeginLoc(), TyA,
14651+ ArgTyRestr, 1))
1468114652 return true;
1468214653
1468314654 TheCall->setType(TyA);
1468414655 return false;
1468514656}
1468614657
14687- bool Sema::BuiltinElementwiseMath(CallExpr *TheCall, bool FPOnly) {
14688- if (auto Res = BuiltinVectorMath(TheCall, FPOnly); Res.has_value()) {
14658+ bool Sema::BuiltinElementwiseMath(CallExpr *TheCall,
14659+ EltwiseBuiltinArgTyRestriction ArgTyRestr) {
14660+ if (auto Res = BuiltinVectorMath(TheCall, ArgTyRestr); Res.has_value()) {
1468914661 TheCall->setType(*Res);
1469014662 return false;
1469114663 }
@@ -14718,8 +14690,9 @@ static bool checkBuiltinVectorMathMixedEnums(Sema &S, Expr *LHS, Expr *RHS,
1471814690 return false;
1471914691}
1472014692
14721- std::optional<QualType> Sema::BuiltinVectorMath(CallExpr *TheCall,
14722- bool FPOnly) {
14693+ std::optional<QualType>
14694+ Sema::BuiltinVectorMath(CallExpr *TheCall,
14695+ EltwiseBuiltinArgTyRestriction ArgTyRestr) {
1472314696 if (checkArgCount(TheCall, 2))
1472414697 return std::nullopt;
1472514698
@@ -14740,26 +14713,21 @@ std::optional<QualType> Sema::BuiltinVectorMath(CallExpr *TheCall,
1474014713 QualType TyA = Args[0]->getType();
1474114714 QualType TyB = Args[1]->getType();
1474214715
14716+ if (checkMathBuiltinElementType(*this, LocA, TyA, ArgTyRestr, 1))
14717+ return std::nullopt;
14718+
1474314719 if (TyA.getCanonicalType() != TyB.getCanonicalType()) {
1474414720 Diag(LocA, diag::err_typecheck_call_different_arg_types) << TyA << TyB;
1474514721 return std::nullopt;
1474614722 }
1474714723
14748- if (FPOnly) {
14749- if (checkFPMathBuiltinElementType(*this, LocA, TyA, 1))
14750- return std::nullopt;
14751- } else {
14752- if (checkMathBuiltinElementType(*this, LocA, TyA, 1))
14753- return std::nullopt;
14754- }
14755-
1475614724 TheCall->setArg(0, Args[0]);
1475714725 TheCall->setArg(1, Args[1]);
1475814726 return TyA;
1475914727}
1476014728
14761- bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall,
14762- bool CheckForFloatArgs ) {
14729+ bool Sema::BuiltinElementwiseTernaryMath(
14730+ CallExpr *TheCall, EltwiseBuiltinArgTyRestriction ArgTyRestr ) {
1476314731 if (checkArgCount(TheCall, 3))
1476414732 return true;
1476514733
@@ -14779,20 +14747,11 @@ bool Sema::BuiltinElementwiseTernaryMath(CallExpr *TheCall,
1477914747 Args[I] = Converted.get();
1478014748 }
1478114749
14782- if (CheckForFloatArgs) {
14783- int ArgOrdinal = 1;
14784- for (Expr *Arg : Args) {
14785- if (checkFPMathBuiltinElementType(*this, Arg->getBeginLoc(),
14786- Arg->getType(), ArgOrdinal++))
14787- return true;
14788- }
14789- } else {
14790- int ArgOrdinal = 1;
14791- for (Expr *Arg : Args) {
14792- if (checkMathBuiltinElementType(*this, Arg->getBeginLoc(), Arg->getType(),
14793- ArgOrdinal++))
14794- return true;
14795- }
14750+ int ArgOrdinal = 1;
14751+ for (Expr *Arg : Args) {
14752+ if (checkMathBuiltinElementType(*this, Arg->getBeginLoc(), Arg->getType(),
14753+ ArgTyRestr, ArgOrdinal++))
14754+ return true;
1479614755 }
1479714756
1479814757 for (int I = 1; I < 3; ++I) {
0 commit comments