@@ -1531,6 +1531,79 @@ void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall,
15311531 TheCall->setType (ReturnType);
15321532}
15331533
1534+ static bool CheckScalarOrVector (Sema *S, CallExpr *TheCall, QualType Scalar,
1535+ unsigned ArgIndex) {
1536+ assert (TheCall->getNumArgs () >= ArgIndex);
1537+ QualType ArgType = TheCall->getArg (ArgIndex)->getType ();
1538+ auto *VTy = ArgType->getAs <VectorType>();
1539+ // not the scalar or vector<scalar>
1540+ if (!(S->Context .hasSameUnqualifiedType (ArgType, Scalar) ||
1541+ (VTy &&
1542+ S->Context .hasSameUnqualifiedType (VTy->getElementType (), Scalar)))) {
1543+ S->Diag (TheCall->getArg (0 )->getBeginLoc (),
1544+ diag::err_typecheck_expect_scalar_or_vector)
1545+ << ArgType << Scalar;
1546+ return true ;
1547+ }
1548+ return false ;
1549+ }
1550+
1551+ static bool CheckBoolSelect (Sema *S, CallExpr *TheCall) {
1552+ assert (TheCall->getNumArgs () == 3 );
1553+ Expr *Arg1 = TheCall->getArg (1 );
1554+ Expr *Arg2 = TheCall->getArg (2 );
1555+ if (!S->Context .hasSameUnqualifiedType (Arg1->getType (), Arg2->getType ())) {
1556+ S->Diag (TheCall->getBeginLoc (),
1557+ diag::err_typecheck_call_different_arg_types)
1558+ << Arg1->getType () << Arg2->getType () << Arg1->getSourceRange ()
1559+ << Arg2->getSourceRange ();
1560+ return true ;
1561+ }
1562+
1563+ TheCall->setType (Arg1->getType ());
1564+ return false ;
1565+ }
1566+
1567+ static bool CheckVectorSelect (Sema *S, CallExpr *TheCall) {
1568+ assert (TheCall->getNumArgs () == 3 );
1569+ Expr *Arg1 = TheCall->getArg (1 );
1570+ Expr *Arg2 = TheCall->getArg (2 );
1571+ if (!Arg1->getType ()->isVectorType ()) {
1572+ S->Diag (Arg1->getBeginLoc (), diag::err_builtin_non_vector_type)
1573+ << " Second" << TheCall->getDirectCallee () << Arg1->getType ()
1574+ << Arg1->getSourceRange ();
1575+ return true ;
1576+ }
1577+
1578+ if (!Arg2->getType ()->isVectorType ()) {
1579+ S->Diag (Arg2->getBeginLoc (), diag::err_builtin_non_vector_type)
1580+ << " Third" << TheCall->getDirectCallee () << Arg2->getType ()
1581+ << Arg2->getSourceRange ();
1582+ return true ;
1583+ }
1584+
1585+ if (!S->Context .hasSameUnqualifiedType (Arg1->getType (), Arg2->getType ())) {
1586+ S->Diag (TheCall->getBeginLoc (),
1587+ diag::err_typecheck_call_different_arg_types)
1588+ << Arg1->getType () << Arg2->getType () << Arg1->getSourceRange ()
1589+ << Arg2->getSourceRange ();
1590+ return true ;
1591+ }
1592+
1593+ // caller has checked that Arg0 is a vector.
1594+ // check all three args have the same length.
1595+ if (TheCall->getArg (0 )->getType ()->getAs <VectorType>()->getNumElements () !=
1596+ Arg1->getType ()->getAs <VectorType>()->getNumElements ()) {
1597+ S->Diag (TheCall->getBeginLoc (),
1598+ diag::err_typecheck_vector_lengths_not_equal)
1599+ << TheCall->getArg (0 )->getType () << Arg1->getType ()
1600+ << TheCall->getArg (0 )->getSourceRange () << Arg1->getSourceRange ();
1601+ return true ;
1602+ }
1603+ TheCall->setType (Arg1->getType ());
1604+ return false ;
1605+ }
1606+
15341607// Note: returning true in this case results in CheckBuiltinFunctionCall
15351608// returning an ExprError
15361609bool SemaHLSL::CheckBuiltinFunctionCall (unsigned BuiltinID, CallExpr *TheCall) {
@@ -1563,6 +1636,20 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
15631636 return true ;
15641637 break ;
15651638 }
1639+ case Builtin::BI__builtin_hlsl_select: {
1640+ if (SemaRef.checkArgCount (TheCall, 3 ))
1641+ return true ;
1642+ if (CheckScalarOrVector (&SemaRef, TheCall, getASTContext ().BoolTy , 0 ))
1643+ return true ;
1644+ QualType ArgTy = TheCall->getArg (0 )->getType ();
1645+ if (ArgTy->isBooleanType () && CheckBoolSelect (&SemaRef, TheCall))
1646+ return true ;
1647+ auto *VTy = ArgTy->getAs <VectorType>();
1648+ if (VTy && VTy->getElementType ()->isBooleanType () &&
1649+ CheckVectorSelect (&SemaRef, TheCall))
1650+ return true ;
1651+ break ;
1652+ }
15661653 case Builtin::BI__builtin_hlsl_elementwise_saturate:
15671654 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
15681655 if (CheckAllArgsHaveFloatRepresentation (&SemaRef, TheCall))
0 commit comments