[clang] [HLSL][Sema] Fixed Diagnostics that assumed only two arguments (PR #122772)

Farzon Lotfi via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 15 15:54:41 PST 2025


https://github.com/farzonl updated https://github.com/llvm/llvm-project/pull/122772

>From 7ac4da8f3a80225300f178eb9aec75d46cc4110d Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Mon, 13 Jan 2025 14:26:23 -0500
Subject: [PATCH 1/2] [NFC] Fixed Diagnostics that assumed only two arguments

---
 clang/lib/Sema/SemaHLSL.cpp | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 65ddee05a21512..169a6a6903891c 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1688,8 +1688,9 @@ static bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
   auto *VecTyA = ArgTyA->getAs<VectorType>();
   SourceLocation BuiltinLoc = TheCall->getBeginLoc();
 
+  ExprResult B;
   for (unsigned i = 1; i < TheCall->getNumArgs(); ++i) {
-    ExprResult B = TheCall->getArg(i);
+    B = TheCall->getArg(i);
     QualType ArgTyB = B.get()->getType();
     auto *VecTyB = ArgTyB->getAs<VectorType>();
     if (VecTyA == nullptr && VecTyB == nullptr)
@@ -1712,8 +1713,7 @@ 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;
@@ -1724,8 +1724,7 @@ static bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
   // 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());
+      << SourceRange(A.get()->getBeginLoc(), B.get()->getEndLoc());
   return true;
 }
 

>From 5ca3dc1fb337ed68a7de65539d9eff51b6312c1a Mon Sep 17 00:00:00 2001
From: Farzon Lotfi <farzonlotfi at microsoft.com>
Date: Wed, 15 Jan 2025 18:54:14 -0500
Subject: [PATCH 2/2] address pr comments

---
 clang/lib/Sema/SemaHLSL.cpp                   | 35 +++++++++++-------
 clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl | 36 +++++++++++++++++--
 2 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 169a6a6903891c..1c2dd8aad0a961 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1688,14 +1688,21 @@ static bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
   auto *VecTyA = ArgTyA->getAs<VectorType>();
   SourceLocation BuiltinLoc = TheCall->getBeginLoc();
 
-  ExprResult B;
+  bool AllBArgAreVectors = true;
   for (unsigned i = 1; i < TheCall->getNumArgs(); ++i) {
-    B = TheCall->getArg(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()) {
@@ -1716,16 +1723,20 @@ static bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
             << 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(A.get()->getBeginLoc(), B.get()->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) {
diff --git a/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl
index 56c8b32cc14e0e..c77a07602b390e 100644
--- a/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl
@@ -20,16 +20,38 @@ float2 test_lerp_no_second_arg(float2 p0) {
   // expected-error at -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 at -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 at -1 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}}
+  // expected-warning at -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 at -1 {{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}}
+  // expected-warning at -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 at -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 at -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 at -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 at -1 {{call to 'lerp' is ambiguous}}
@@ -45,6 +67,16 @@ float2 test_builtin_lerp_float2_splat(float p0, float2 p1) {
   // expected-error at -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 at -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 at -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 at -1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}



More information about the cfe-commits mailing list