@@ -1013,6 +1013,66 @@ void SetElementTypeAsReturnType(Sema *S, CallExpr *TheCall,
10131013 TheCall->setType (ReturnType);
10141014}
10151015
1016+ bool CheckBoolSelect (Sema *S, CallExpr *TheCall) {
1017+ assert (TheCall->getNumArgs () == 3 );
1018+ Expr *Arg1 = TheCall->getArg (1 );
1019+ Expr *Arg2 = TheCall->getArg (2 );
1020+ if (!S->Context .hasSameUnqualifiedType (Arg1->getType (),
1021+ Arg2->getType ())) {
1022+ S->Diag (TheCall->getBeginLoc (),
1023+ diag::err_typecheck_call_different_arg_types)
1024+ << Arg1->getType () << Arg2->getType ()
1025+ << Arg1->getSourceRange () << Arg2->getSourceRange ();
1026+ return true ;
1027+ }
1028+
1029+ TheCall->setType (Arg1->getType ());
1030+ return false ;
1031+ }
1032+
1033+ bool CheckVectorSelect (Sema *S, CallExpr *TheCall) {
1034+ assert (TheCall->getNumArgs () == 3 );
1035+ Expr *Arg1 = TheCall->getArg (1 );
1036+ Expr *Arg2 = TheCall->getArg (2 );
1037+ if (!Arg1->getType ()->isVectorType ()) {
1038+ S->Diag (Arg1->getBeginLoc (),
1039+ diag::err_builtin_non_vector_type)
1040+ << " Second" << " __builtin_hlsl_select" << Arg1->getType ()
1041+ << Arg1->getSourceRange ();
1042+ return true ;
1043+ }
1044+
1045+ if (!Arg2->getType ()->isVectorType ()) {
1046+ S->Diag (Arg2->getBeginLoc (),
1047+ diag::err_builtin_non_vector_type)
1048+ << " Third" << " __builtin_hlsl_select" << Arg2->getType ()
1049+ << Arg2->getSourceRange ();
1050+ return true ;
1051+ }
1052+
1053+ if (!S->Context .hasSameUnqualifiedType (Arg1->getType (),
1054+ Arg2->getType ())) {
1055+ S->Diag (TheCall->getBeginLoc (),
1056+ diag::err_typecheck_call_different_arg_types)
1057+ << Arg1->getType () << Arg2->getType ()
1058+ << Arg1->getSourceRange () << Arg2->getSourceRange ();
1059+ return true ;
1060+ }
1061+
1062+ // caller has checked that Arg0 is a vector.
1063+ // check all three args have the same length.
1064+ if (TheCall->getArg (0 )->getType ()->getAs <VectorType>()->getNumElements () !=
1065+ Arg1->getType ()->getAs <VectorType>()->getNumElements ()) {
1066+ S->Diag (TheCall->getBeginLoc (),
1067+ diag::err_typecheck_vector_lengths_not_equal)
1068+ << TheCall->getArg (0 )->getType () << Arg1->getType ()
1069+ << TheCall->getArg (0 )->getSourceRange () << Arg1->getSourceRange ();
1070+ return true ;
1071+ }
1072+
1073+ return false ;
1074+ }
1075+
10161076// Note: returning true in this case results in CheckBuiltinFunctionCall
10171077// returning an ExprError
10181078bool SemaHLSL::CheckBuiltinFunctionCall (unsigned BuiltinID, CallExpr *TheCall) {
@@ -1046,6 +1106,30 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
10461106 break ;
10471107 }
10481108 case Builtin::BI__builtin_hlsl_elementwise_saturate:
1109+ case Builtin::BI__builtin_hlsl_select: {
1110+ if (SemaRef.checkArgCount (TheCall, 3 ))
1111+ return true ;
1112+ QualType ArgTy = TheCall->getArg (0 )->getType ();
1113+ if (ArgTy->isBooleanType ()) {
1114+ if (CheckBoolSelect (&SemaRef, TheCall))
1115+ return true ;
1116+ } else if (ArgTy->isVectorType () &&
1117+ ArgTy->getAs <VectorType>()->getElementType ()->isBooleanType ()) {
1118+ if (CheckVectorSelect (&SemaRef, TheCall))
1119+ return true ;
1120+ } else { // first operand is not a bool or a vector of bools.
1121+ SemaRef.Diag (TheCall->getArg (0 )->getBeginLoc (),
1122+ diag::err_typecheck_convert_incompatible)
1123+ << TheCall->getArg (0 )->getType () << SemaRef.Context .getBOOLType ()
1124+ << 1 << 0 << 0 ;
1125+ SemaRef.Diag (TheCall->getArg (0 )->getBeginLoc (),
1126+ diag::err_builtin_non_vector_type)
1127+ << " First" << " __builtin_hlsl_select" << TheCall->getArg (0 )->getType ()
1128+ << TheCall->getArg (0 )->getSourceRange ();
1129+ return true ;
1130+ }
1131+ break ;
1132+ }
10491133 case Builtin::BI__builtin_hlsl_elementwise_rcp: {
10501134 if (CheckAllArgsHaveFloatRepresentation (&SemaRef, TheCall))
10511135 return true ;
0 commit comments