Skip to content

[HLSL][Sema] Fixed Diagnostics that assumed only two arguments #122772

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 23 additions & 13 deletions clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1688,13 +1688,21 @@ static bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
auto *VecTyA = ArgTyA->getAs<VectorType>();
SourceLocation BuiltinLoc = TheCall->getBeginLoc();

bool AllBArgAreVectors = true;
for (unsigned i = 1; i < TheCall->getNumArgs(); ++i) {
ExprResult B = TheCall->getArg(i);
QualType ArgTyB = B.get()->getType();
auto *VecTyB = ArgTyB->getAs<VectorType>();
if (VecTyA == nullptr && VecTyB == nullptr)
return false;

if (VecTyB == nullptr)
AllBArgAreVectors &= false;
if (VecTyA && VecTyB == nullptr) {
// Note: if we get here 'B' is scalar which
// requires a VectorSplat on ArgN
S->Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
<< TheCall->getDirectCallee() << /*useAllTerminology*/ true
<< SourceRange(A.get()->getBeginLoc(), B.get()->getEndLoc());
return true;
}
if (VecTyA && VecTyB) {
bool retValue = false;
if (VecTyA->getElementType() != VecTyB->getElementType()) {
Expand All @@ -1712,21 +1720,23 @@ static bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
// HLSLVectorTruncation.
S->Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
<< TheCall->getDirectCallee() << /*useAllTerminology*/ true
<< SourceRange(TheCall->getArg(0)->getBeginLoc(),
TheCall->getArg(1)->getEndLoc());
<< SourceRange(A.get()->getBeginLoc(), B.get()->getEndLoc());
retValue = true;
}
return retValue;
if (retValue)
return retValue;
}
}

// Note: if we get here one of the args is a scalar which
// requires a VectorSplat on Arg0 or Arg1
S->Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
<< TheCall->getDirectCallee() << /*useAllTerminology*/ true
<< SourceRange(TheCall->getArg(0)->getBeginLoc(),
TheCall->getArg(1)->getEndLoc());
return true;
if (VecTyA == nullptr && AllBArgAreVectors) {
// Note: if we get here 'A' is a scalar which
// requires a VectorSplat on Arg0
S->Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
<< TheCall->getDirectCallee() << /*useAllTerminology*/ true
<< SourceRange(A.get()->getBeginLoc(), A.get()->getEndLoc());
return true;
}
return false;
}

static bool CheckArgTypeMatches(Sema *S, Expr *Arg, QualType ExpectedType) {
Expand Down
36 changes: 34 additions & 2 deletions clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,38 @@ float2 test_lerp_no_second_arg(float2 p0) {
// expected-error@-1 {{no matching function for call to 'lerp'}}
}

float2 test_lerp_vector_size_mismatch(float3 p0, float2 p1) {
float2 test_lerp_vector_trunc_warn1(float3 p0) {
return lerp(p0, p0, p0);
// expected-warning@-1 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}}
}

float2 test_lerp_vector_trunc_warn2(float3 p0, float2 p1) {
return lerp(p0, p0, p1);
// expected-warning@-1 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}}
// expected-warning@-2 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}}
}

float2 test_lerp_vector_trunc_warn3(float3 p0, float2 p1) {
return lerp(p0, p1, p0);
// expected-warning@-1 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}}
// expected-warning@-2 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}}
}

float2 test_lerp_builtin_vector_size_mismatch(float3 p0, float2 p1) {
float2 test_lerp_builtin_vector_size_mismatch_Arg1(float3 p0, float2 p1) {
return __builtin_hlsl_lerp(p0, p1, p1);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float2 test_lerp_builtin_vector_size_mismatch_Arg2(float3 p0, float2 p1) {
return __builtin_hlsl_lerp(p1, p0, p1);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float2 test_lerp_builtin_vector_size_mismatch_Arg3(float3 p0, float2 p1) {
return __builtin_hlsl_lerp(p1, p1, p0);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
}

float test_lerp_scalar_mismatch(float p0, half p1) {
return lerp(p1, p0, p1);
// expected-error@-1 {{call to 'lerp' is ambiguous}}
Expand All @@ -45,6 +67,16 @@ float2 test_builtin_lerp_float2_splat(float p0, float2 p1) {
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
}

float2 test_builtin_lerp_float2_splat2(double p0, double2 p1) {
return __builtin_hlsl_lerp(p1, p0, p1);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
}

float2 test_builtin_lerp_float2_splat3(double p0, double2 p1) {
return __builtin_hlsl_lerp(p1, p1, p0);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
}

float3 test_builtin_lerp_float3_splat(float p0, float3 p1) {
return __builtin_hlsl_lerp(p0, p1, p1);
// expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
Expand Down
Loading