https://github.com/marykass-arm updated 
https://github.com/llvm/llvm-project/pull/159131

>From 035aafb13cff57bfd266c8266bbbbccebe4be685 Mon Sep 17 00:00:00 2001
From: Mary Kassayova <mary.kassay...@arm.com>
Date: Tue, 16 Sep 2025 15:59:14 +0000
Subject: [PATCH 1/3] [Sema][AArch64] Emit error for mismatched VLs on
 streaming mode transitions

---
 .../clang/Basic/DiagnosticSemaKinds.td        |   3 +
 clang/lib/Sema/SemaChecking.cpp               |  28 ++++-
 ...h64-sme-streaming-nonstreaming-vl-checks.c | 110 ++++++++++++++++++
 3 files changed, 135 insertions(+), 6 deletions(-)
 create mode 100644 
clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 409a8202d8a09..eec5047e56334 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3976,6 +3976,9 @@ def warn_sme_streaming_pass_return_vl_to_non_streaming : 
Warning<
   "%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a 
function with a different"
   " streaming-mode is undefined behaviour when the streaming and non-streaming 
vector lengths are different at runtime">,
   InGroup<AArch64SMEAttributes>, DefaultIgnore;
+def err_sme_streaming_transition_vl_mismatch : Error<
+  "%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a 
function with a different"
+  " streaming-mode is invalid because the non-streaming vector length (%1) and 
streaming vector length (%2) differ">;
 def warn_sme_locally_streaming_has_vl_args_returns : Warning<
   "%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a 
locally streaming function is undefined"
   " behaviour when the streaming and non-streaming vector lengths are 
different at runtime">,
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 05ee51913aec1..c031d74596fa8 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3756,6 +3756,8 @@ void Sema::checkCall(NamedDecl *FDecl, const 
FunctionProtoType *Proto,
     // If the call requires a streaming-mode change and has scalable vector
     // arguments or return values, then warn the user that the streaming and
     // non-streaming vector lengths may be different.
+    // When both streaming and non-streaming vector lengths are defined and
+    // mismatched, produce an error.
     const auto *CallerFD = dyn_cast<FunctionDecl>(CurContext);
     if (CallerFD && (!FD || !FD->getBuiltinID()) &&
         (IsScalableArg || IsScalableRet)) {
@@ -3768,12 +3770,26 @@ void Sema::checkCall(NamedDecl *FDecl, const 
FunctionProtoType *Proto,
       if (!IsCalleeStreamingCompatible &&
           (CallerFnType == SemaARM::ArmStreamingCompatible ||
            ((CallerFnType == SemaARM::ArmStreaming) ^ IsCalleeStreaming))) {
-        if (IsScalableArg)
-          Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
-              << /*IsArg=*/true;
-        if (IsScalableRet)
-          Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
-              << /*IsArg=*/false;
+        const LangOptions &LO = getLangOpts();
+        auto VL = LO.VScaleMin * 128;
+        auto SVL = LO.VScaleStreamingMin * 128;
+
+        if (IsScalableArg) {
+          if (VL && SVL && VL != SVL)
+            Diag(Loc, diag::err_sme_streaming_transition_vl_mismatch)
+                << /*IsArg=*/true << VL << SVL;
+          else
+            Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
+                << /*IsArg=*/true;
+        }
+        if (IsScalableRet) {
+          if (VL && SVL && VL != SVL)
+            Diag(Loc, diag::err_sme_streaming_transition_vl_mismatch)
+                << /*IsArg=*/false << VL << SVL;
+          else
+            Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
+                << /*IsArg=*/false;
+        }
       }
     }
 
diff --git a/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c 
b/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c
new file mode 100644
index 0000000000000..78473df82d309
--- /dev/null
+++ b/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c
@@ -0,0 +1,110 @@
+// Case 1: No vscale flags — should only produce warnings
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +bf16 
-target-feature +sme -target-feature +sme2 -target-feature +sve 
-Waarch64-sme-attributes -fsyntax-only -verify=expected-noflags %s
+
+// Case 2: Explicit mismatch in vscale flags — should produce errors
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +bf16 
-target-feature +sme -target-feature +sme2 -target-feature +sve 
-Waarch64-sme-attributes -fsyntax-only -mvscale-min=1 -mvscale-max=1 
-mvscale-streaming-min=2 -mvscale-streaming-max=2 -verify=expected-flags %s
+
+void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { } 
+
+__SVInt8_t sme_streaming_returns_vl(void) __arm_streaming { __SVInt8_t r; 
return r; }
+
+void sme_streaming_compatible_with_vl_arg(__SVInt8_t a) 
__arm_streaming_compatible { }
+
+__SVInt8_t sme_streaming_compatible_returns_vl(void) 
__arm_streaming_compatible { __SVInt8_t r; return r; }
+
+void sme_no_streaming_with_vl_arg(__SVInt8_t a) { }
+
+__SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t r; return r; }
+
+
+void sme_no_streaming_calling_streaming_with_vl_args() {
+  __SVInt8_t a;
+  // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
+  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128) and streaming vector length (256) differ}}
+  sme_streaming_with_vl_arg(a);
+}
+
+void sme_no_streaming_calling_streaming_with_return_vl() {
+  // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
+  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128) and streaming vector length (256) differ}}
+  __SVInt8_t r = sme_streaming_returns_vl();
+}
+
+void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming {
+  __SVInt8_t a;
+  // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
+  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128) and streaming vector length (256) differ}}
+  sme_no_streaming_with_vl_arg(a);
+}
+
+void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming {
+  // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
+  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128) and streaming vector length (256) differ}}
+  __SVInt8_t r = sme_no_streaming_returns_vl();
+}
+
+void sme_streaming_compatible_calling_streaming_with_vl_args(__SVInt8_t arg) 
__arm_streaming_compatible {
+  // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
+  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128) and streaming vector length (256) differ}}
+  sme_streaming_with_vl_arg(arg);
+}
+
+void sme_streaming_compatible_calling_sme_streaming_return_vl(void) 
__arm_streaming_compatible {
+  // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
+  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128) and streaming vector length (256) differ}}
+  __SVInt8_t r = sme_streaming_returns_vl();
+}
+
+void sme_streaming_compatible_calling_no_streaming_with_vl_args(__SVInt8_t 
arg) __arm_streaming_compatible {
+  // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
+  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128) and streaming vector length (256) differ}}
+  sme_no_streaming_with_vl_arg(arg);
+}
+
+void sme_streaming_compatible_calling_no_sme_streaming_return_vl(void) 
__arm_streaming_compatible {
+  // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
+  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128) and streaming vector length (256) differ}}
+  __SVInt8_t r = sme_no_streaming_returns_vl();
+}
+
+void sme_streaming_calling_streaming_with_vl_args(__SVInt8_t a) 
__arm_streaming {
+  sme_streaming_with_vl_arg(a);
+}
+
+void sme_streaming_calling_streaming_with_return_vl(void) __arm_streaming {
+  __SVInt8_t r = sme_streaming_returns_vl();
+}
+
+void sme_streaming_calling_streaming_compatible_with_vl_args(__SVInt8_t a) 
__arm_streaming {
+  sme_streaming_compatible_with_vl_arg(a);
+}
+
+void sme_streaming_calling_streaming_compatible_with_return_vl(void) 
__arm_streaming {
+  __SVInt8_t r = sme_streaming_compatible_returns_vl();
+}
+
+void sme_no_streaming_calling_streaming_compatible_with_vl_args() {
+  __SVInt8_t a;
+  sme_streaming_compatible_with_vl_arg(a);
+}
+
+void sme_no_streaming_calling_streaming_compatible_with_return_vl() {
+  __SVInt8_t r = sme_streaming_compatible_returns_vl();
+}
+
+void sme_no_streaming_calling_non_streaming_compatible_with_vl_args() {
+  __SVInt8_t a;
+  sme_no_streaming_with_vl_arg(a);
+}
+
+void sme_no_streaming_calling_non_streaming_compatible_with_return_vl() {
+  __SVInt8_t r = sme_no_streaming_returns_vl();
+}
+
+void 
sme_streaming_compatible_calling_streaming_compatible_with_vl_args(__SVInt8_t 
arg) __arm_streaming_compatible {
+  sme_streaming_compatible_with_vl_arg(arg);
+}
+
+void 
sme_streaming_compatible_calling_streaming_compatible_with_return_vl(void) 
__arm_streaming_compatible {
+  __SVInt8_t r = sme_streaming_compatible_returns_vl();
+}

>From a933ca96f231756e28bf7fe6df6adb09f0b58258 Mon Sep 17 00:00:00 2001
From: Mary Kassayova <mary.kassay...@arm.com>
Date: Wed, 17 Sep 2025 15:48:17 +0000
Subject: [PATCH 2/3] Removed error for SC callers, addressed other comments

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  6 ++--
 clang/lib/Sema/SemaChecking.cpp               | 30 +++++++++----------
 ...h64-sme-streaming-nonstreaming-vl-checks.c | 19 ++++++------
 3 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index eec5047e56334..56b73f4cc355b 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3976,13 +3976,13 @@ def warn_sme_streaming_pass_return_vl_to_non_streaming 
: Warning<
   "%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a 
function with a different"
   " streaming-mode is undefined behaviour when the streaming and non-streaming 
vector lengths are different at runtime">,
   InGroup<AArch64SMEAttributes>, DefaultIgnore;
-def err_sme_streaming_transition_vl_mismatch : Error<
-  "%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a 
function with a different"
-  " streaming-mode is invalid because the non-streaming vector length (%1) and 
streaming vector length (%2) differ">;
 def warn_sme_locally_streaming_has_vl_args_returns : Warning<
   "%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a 
locally streaming function is undefined"
   " behaviour when the streaming and non-streaming vector lengths are 
different at runtime">,
   InGroup<AArch64SMEAttributes>, DefaultIgnore;
+def err_sme_streaming_transition_vl_mismatch : Error<
+  "%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a 
function with a different"
+  " streaming-mode is invalid because the non-streaming vector length (%1 bit) 
and streaming vector length (%2 bit) differ">;
 def err_conflicting_attributes_arm_agnostic : Error<
   "__arm_agnostic(\"sme_za_state\") cannot share ZA state with its caller">;
 def err_conflicting_attributes_arm_state : Error<
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index c031d74596fa8..f3201a692f4c0 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3771,25 +3771,25 @@ void Sema::checkCall(NamedDecl *FDecl, const 
FunctionProtoType *Proto,
           (CallerFnType == SemaARM::ArmStreamingCompatible ||
            ((CallerFnType == SemaARM::ArmStreaming) ^ IsCalleeStreaming))) {
         const LangOptions &LO = getLangOpts();
-        auto VL = LO.VScaleMin * 128;
-        auto SVL = LO.VScaleStreamingMin * 128;
+        unsigned VL = LO.VScaleMin * 128;
+        unsigned SVL = LO.VScaleStreamingMin * 128;
 
-        if (IsScalableArg) {
-          if (VL && SVL && VL != SVL)
-            Diag(Loc, diag::err_sme_streaming_transition_vl_mismatch)
-                << /*IsArg=*/true << VL << SVL;
-          else
-            Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
-                << /*IsArg=*/true;
-        }
-        if (IsScalableRet) {
-          if (VL && SVL && VL != SVL)
+        bool IsVLError = CallerFnType != SemaARM::ArmStreamingCompatible &&
+                         (VL && SVL && VL != SVL);
+
+        auto EmitDiag = [&](bool IsArg) {
+          if (IsVLError)
             Diag(Loc, diag::err_sme_streaming_transition_vl_mismatch)
-                << /*IsArg=*/false << VL << SVL;
+                << IsArg << VL << SVL;
           else
             Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
-                << /*IsArg=*/false;
-        }
+                << IsArg;
+        };
+
+        if (IsScalableArg)
+          EmitDiag(true);
+        if (IsScalableRet)
+          EmitDiag(false);
       }
     }
 
diff --git a/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c 
b/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c
index 78473df82d309..e9639ecbdfef3 100644
--- a/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c
+++ b/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c
@@ -1,7 +1,8 @@
 // Case 1: No vscale flags — should only produce warnings
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +bf16 
-target-feature +sme -target-feature +sme2 -target-feature +sve 
-Waarch64-sme-attributes -fsyntax-only -verify=expected-noflags %s
 
-// Case 2: Explicit mismatch in vscale flags — should produce errors
+// Case 2: Explicit mismatch in vscale flags — should produce errors for 
+// streaming and non-streaming callers
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +bf16 
-target-feature +sme -target-feature +sme2 -target-feature +sve 
-Waarch64-sme-attributes -fsyntax-only -mvscale-min=1 -mvscale-max=1 
-mvscale-streaming-min=2 -mvscale-streaming-max=2 -verify=expected-flags %s
 
 void sme_streaming_with_vl_arg(__SVInt8_t a) __arm_streaming { } 
@@ -20,50 +21,50 @@ __SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t 
r; return r; }
 void sme_no_streaming_calling_streaming_with_vl_args() {
   __SVInt8_t a;
   // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128) and streaming vector length (256) differ}}
+  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128 bit) and streaming vector length (256 bit) differ}}
   sme_streaming_with_vl_arg(a);
 }
 
 void sme_no_streaming_calling_streaming_with_return_vl() {
   // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128) and streaming vector length (256) differ}}
+  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128 bit) and streaming vector length (256 bit) differ}}
   __SVInt8_t r = sme_streaming_returns_vl();
 }
 
 void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming {
   __SVInt8_t a;
   // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128) and streaming vector length (256) differ}}
+  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128 bit) and streaming vector length (256 bit) differ}}
   sme_no_streaming_with_vl_arg(a);
 }
 
 void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming {
   // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128) and streaming vector length (256) differ}}
+  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128 bit) and streaming vector length (256 bit) differ}}
   __SVInt8_t r = sme_no_streaming_returns_vl();
 }
 
 void sme_streaming_compatible_calling_streaming_with_vl_args(__SVInt8_t arg) 
__arm_streaming_compatible {
   // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128) and streaming vector length (256) differ}}
+  // expected-flags-warning@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is undefined behaviour when the streaming and 
non-streaming vector lengths are different at runtime}}
   sme_streaming_with_vl_arg(arg);
 }
 
 void sme_streaming_compatible_calling_sme_streaming_return_vl(void) 
__arm_streaming_compatible {
   // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128) and streaming vector length (256) differ}}
+  // expected-flags-warning@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
   __SVInt8_t r = sme_streaming_returns_vl();
 }
 
 void sme_streaming_compatible_calling_no_streaming_with_vl_args(__SVInt8_t 
arg) __arm_streaming_compatible {
   // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128) and streaming vector length (256) differ}}
+  // expected-flags-warning@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is undefined behaviour when the streaming and 
non-streaming vector lengths are different at runtime}}
   sme_no_streaming_with_vl_arg(arg);
 }
 
 void sme_streaming_compatible_calling_no_sme_streaming_return_vl(void) 
__arm_streaming_compatible {
   // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128) and streaming vector length (256) differ}}
+  // expected-flags-warning@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
   __SVInt8_t r = sme_no_streaming_returns_vl();
 }
 

>From eb73662870298d96a5d665af9f4c2b416a9b7507 Mon Sep 17 00:00:00 2001
From: Mary Kassayova <mary.kassay...@arm.com>
Date: Thu, 18 Sep 2025 12:16:15 +0000
Subject: [PATCH 3/3] Added SC warning

---
 .../include/clang/Basic/DiagnosticSemaKinds.td  |  7 ++++++-
 clang/lib/Sema/SemaChecking.cpp                 | 17 +++++++++++------
 ...rch64-sme-streaming-nonstreaming-vl-checks.c | 16 ++++++++--------
 3 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 56b73f4cc355b..3797eff0f407a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3980,9 +3980,14 @@ def warn_sme_locally_streaming_has_vl_args_returns : 
Warning<
   "%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a 
locally streaming function is undefined"
   " behaviour when the streaming and non-streaming vector lengths are 
different at runtime">,
   InGroup<AArch64SMEAttributes>, DefaultIgnore;
+def warn_sme_streaming_compatible_vl_mismatch : Warning<
+  "%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a 
streaming-compatible function"
+  " is undefined behaviour when the callee is in a different streaming mode 
because the streaming vector"
+  " length (%1 bit) and non-streaming vector length (%2 bit) differ">,
+  InGroup<AArch64SMEAttributes>, DefaultIgnore;
 def err_sme_streaming_transition_vl_mismatch : Error<
   "%select{returning|passing}0 a VL-dependent argument %select{from|to}0 a 
function with a different"
-  " streaming-mode is invalid because the non-streaming vector length (%1 bit) 
and streaming vector length (%2 bit) differ">;
+  " streaming-mode is invalid because the streaming vector length (%1 bit) and 
non-streaming vector length (%2 bit) differ">;
 def err_conflicting_attributes_arm_agnostic : Error<
   "__arm_agnostic(\"sme_za_state\") cannot share ZA state with its caller">;
 def err_conflicting_attributes_arm_state : Error<
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index f3201a692f4c0..f26a317ac84e6 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3774,14 +3774,19 @@ void Sema::checkCall(NamedDecl *FDecl, const 
FunctionProtoType *Proto,
         unsigned VL = LO.VScaleMin * 128;
         unsigned SVL = LO.VScaleStreamingMin * 128;
 
-        bool IsVLError = CallerFnType != SemaARM::ArmStreamingCompatible &&
-                         (VL && SVL && VL != SVL);
+        bool IsVLMismatch = VL && SVL && VL != SVL;
 
         auto EmitDiag = [&](bool IsArg) {
-          if (IsVLError)
-            Diag(Loc, diag::err_sme_streaming_transition_vl_mismatch)
-                << IsArg << VL << SVL;
-          else
+          if (IsVLMismatch) {
+            if (CallerFnType == SemaARM::ArmStreamingCompatible)
+              // Emit warning for streaming-compatible callers
+              Diag(Loc, diag::warn_sme_streaming_compatible_vl_mismatch)
+                  << IsArg << SVL << VL;
+            else
+              // Emit error otherwise
+              Diag(Loc, diag::err_sme_streaming_transition_vl_mismatch)
+                  << IsArg << SVL << VL;
+          } else
             Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
                 << IsArg;
         };
diff --git a/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c 
b/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c
index e9639ecbdfef3..819f804408a82 100644
--- a/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c
+++ b/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c
@@ -21,50 +21,50 @@ __SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t 
r; return r; }
 void sme_no_streaming_calling_streaming_with_vl_args() {
   __SVInt8_t a;
   // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128 bit) and streaming vector length (256 bit) differ}}
+  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the streaming vector length 
(256 bit) and non-streaming vector length (128 bit) differ}}
   sme_streaming_with_vl_arg(a);
 }
 
 void sme_no_streaming_calling_streaming_with_return_vl() {
   // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128 bit) and streaming vector length (256 bit) differ}}
+  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the streaming 
vector length (256 bit) and non-streaming vector length (128 bit) differ}}
   __SVInt8_t r = sme_streaming_returns_vl();
 }
 
 void sme_streaming_calling_non_streaming_with_vl_args(void) __arm_streaming {
   __SVInt8_t a;
   // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the non-streaming vector 
length (128 bit) and streaming vector length (256 bit) differ}}
+  // expected-flags-error@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is invalid because the streaming vector length 
(256 bit) and non-streaming vector length (128 bit) differ}}
   sme_no_streaming_with_vl_arg(a);
 }
 
 void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming {
   // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the non-streaming 
vector length (128 bit) and streaming vector length (256 bit) differ}}
+  // expected-flags-error@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is invalid because the streaming 
vector length (256 bit) and non-streaming vector length (128 bit) differ}}
   __SVInt8_t r = sme_no_streaming_returns_vl();
 }
 
 void sme_streaming_compatible_calling_streaming_with_vl_args(__SVInt8_t arg) 
__arm_streaming_compatible {
   // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-warning@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is undefined behaviour when the streaming and 
non-streaming vector lengths are different at runtime}}
+  // expected-flags-warning@+1 {{passing a VL-dependent argument to a 
streaming-compatible function is undefined behaviour when the callee is in a 
different streaming mode because the streaming vector length (256 bit) and 
non-streaming vector length (128 bit) differ}}
   sme_streaming_with_vl_arg(arg);
 }
 
 void sme_streaming_compatible_calling_sme_streaming_return_vl(void) 
__arm_streaming_compatible {
   // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-warning@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
+  // expected-flags-warning@+1 {{returning a VL-dependent argument from a 
streaming-compatible function is undefined behaviour when the callee is in a 
different streaming mode because the streaming vector length (256 bit) and 
non-streaming vector length (128 bit) differ}}
   __SVInt8_t r = sme_streaming_returns_vl();
 }
 
 void sme_streaming_compatible_calling_no_streaming_with_vl_args(__SVInt8_t 
arg) __arm_streaming_compatible {
   // expected-noflags-warning@+2 {{passing a VL-dependent argument to a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-warning@+1 {{passing a VL-dependent argument to a function 
with a different streaming-mode is undefined behaviour when the streaming and 
non-streaming vector lengths are different at runtime}}
+  // expected-flags-warning@+1 {{passing a VL-dependent argument to a 
streaming-compatible function is undefined behaviour when the callee is in a 
different streaming mode because the streaming vector length (256 bit) and 
non-streaming vector length (128 bit) differ}}
   sme_no_streaming_with_vl_arg(arg);
 }
 
 void sme_streaming_compatible_calling_no_sme_streaming_return_vl(void) 
__arm_streaming_compatible {
   // expected-noflags-warning@+2 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
-  // expected-flags-warning@+1 {{returning a VL-dependent argument from a 
function with a different streaming-mode is undefined behaviour when the 
streaming and non-streaming vector lengths are different at runtime}}
+  // expected-flags-warning@+1 {{returning a VL-dependent argument from a 
streaming-compatible function is undefined behaviour when the callee is in a 
different streaming mode because the streaming vector length (256 bit) and 
non-streaming vector length (128 bit) differ}}
   __SVInt8_t r = sme_no_streaming_returns_vl();
 }
 

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to