@@ -3494,6 +3494,93 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
34943494 if (BuiltinCountedByRef(TheCall))
34953495 return ExprError();
34963496 break;
3497+
3498+ case Builtin::BI__builtin_ct_select: {
3499+ if (TheCall->getNumArgs() != 3) {
3500+ // Simple argument count check without complex diagnostics
3501+ if (TheCall->getNumArgs() < 3) {
3502+ return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least)
3503+ << 0 << 3 << TheCall->getNumArgs() << 0
3504+ << TheCall->getCallee()->getSourceRange();
3505+ } else {
3506+ return Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_many_args)
3507+ << 0 << 3 << TheCall->getNumArgs() << 0
3508+ << TheCall->getCallee()->getSourceRange();
3509+ }
3510+ }
3511+ auto *Cond = TheCall->getArg(0);
3512+ auto *A = TheCall->getArg(1);
3513+ auto *B = TheCall->getArg(2);
3514+
3515+ QualType CondTy = Cond->getType();
3516+ if (!CondTy->isIntegerType()) {
3517+ return Diag(Cond->getBeginLoc(), diag::err_typecheck_cond_expect_scalar)
3518+ << CondTy << Cond->getSourceRange();
3519+ }
3520+
3521+ QualType ATy = A->getType();
3522+ QualType BTy = B->getType();
3523+
3524+ // check for scalar or vector scalar type
3525+ if ((!ATy->isScalarType() && !ATy->isVectorType()) ||
3526+ (!BTy->isScalarType() && !BTy->isVectorType())) {
3527+ return Diag(A->getBeginLoc(),
3528+ diag::err_typecheck_cond_incompatible_operands)
3529+ << ATy << BTy << A->getSourceRange() << B->getSourceRange();
3530+ }
3531+
3532+ // Check if both operands have the same type or can be implicitly converted
3533+ QualType ResultTy;
3534+ if (Context.hasSameType(ATy, BTy)) {
3535+ ResultTy = ATy;
3536+ } else {
3537+ // Try to find a common type using the same logic as conditional
3538+ // expressions
3539+ ExprResult ARes = ExprResult(A);
3540+ ExprResult BRes = ExprResult(B);
3541+
3542+ // For arithmetic types, allow promotions within the same category only
3543+ if (ATy->isArithmeticType() && BTy->isArithmeticType()) {
3544+ // Check if both are integer types or both are floating types
3545+ bool AIsInteger = ATy->isIntegerType();
3546+ bool BIsInteger = BTy->isIntegerType();
3547+ bool AIsFloating = ATy->isFloatingType();
3548+ bool BIsFloating = BTy->isFloatingType();
3549+
3550+ if ((AIsInteger && BIsInteger) || (AIsFloating && BIsFloating)) {
3551+ // Both are in the same category, allow usual arithmetic conversions
3552+ ResultTy = UsualArithmeticConversions(
3553+ ARes, BRes, TheCall->getBeginLoc(), ArithConvKind::Conditional);
3554+ if (ARes.isInvalid() || BRes.isInvalid() || ResultTy.isNull()) {
3555+ return Diag(A->getBeginLoc(),
3556+ diag::err_typecheck_cond_incompatible_operands)
3557+ << ATy << BTy << A->getSourceRange() << B->getSourceRange();
3558+ }
3559+ // Update the arguments with any necessary implicit casts
3560+ TheCall->setArg(1, ARes.get());
3561+ TheCall->setArg(2, BRes.get());
3562+ } else {
3563+ // Different categories (int vs float), not allowed
3564+ return Diag(A->getBeginLoc(),
3565+ diag::err_typecheck_cond_incompatible_operands)
3566+ << ATy << BTy << A->getSourceRange() << B->getSourceRange();
3567+ }
3568+ } else {
3569+ // For non-arithmetic types, they must be exactly the same
3570+ return Diag(A->getBeginLoc(),
3571+ diag::err_typecheck_cond_incompatible_operands)
3572+ << ATy << BTy << A->getSourceRange() << B->getSourceRange();
3573+ }
3574+ }
3575+
3576+ ExprResult CondRes = PerformContextuallyConvertToBool(Cond);
3577+ if (CondRes.isInvalid())
3578+ return ExprError();
3579+
3580+ TheCall->setArg(0, CondRes.get());
3581+ TheCall->setType(ResultTy);
3582+ return TheCall;
3583+ } break;
34973584 }
34983585
34993586 if (getLangOpts().HLSL && HLSL().CheckBuiltinFunctionCall(BuiltinID, TheCall))
0 commit comments