[clang] 2c12a3d - [Sema][AArch64] Emit error for mismatched VLs on streaming mode transitions (#159131)

via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 23 03:05:52 PDT 2025


Author: Mary Kassayova
Date: 2025-09-23T11:05:47+01:00
New Revision: 2c12a3df769a54ab956b2080b8a8b854965b00a6

URL: https://github.com/llvm/llvm-project/commit/2c12a3df769a54ab956b2080b8a8b854965b00a6
DIFF: https://github.com/llvm/llvm-project/commit/2c12a3df769a54ab956b2080b8a8b854965b00a6.diff

LOG: [Sema][AArch64] Emit error for mismatched VLs on streaming mode transitions (#159131)

Update Sema::checkCall to handle the case where a call involves a
streaming mode transition and passes or returns scalable vector types.
Previously, Clang always issued a warning in this case, noting that the
streaming and non-streaming vector lengths may differ at runtime. With
this change:
- if both `-msve-vector-bits` and `-msve-streaming-vector-bits` are
specified and produce different fixed VL values, Clang now emits an
error rather than a warning
- If either flag is missing or vector lengths are equal, the diagnostic
remains a warning

Added: 
    clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaChecking.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index bd896524321d1..dd82c3b092eb5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3983,6 +3983,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 
diff erent 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 %select{non-streaming|streaming}1"
+  " function is undefined behaviour when the streaming-compatible caller is%select{| not}1 in streaming"
+  " mode, because the streaming vector length (%2 bit) and non-streaming vector length (%3 bit) 
diff er">,
+  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 
diff erent"
+  " streaming-mode is undefined behaviour because the streaming vector length (%1 bit) and non-streaming vector length (%2 bit) 
diff er">;
 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 740b472b0eb16..b3b67230f7687 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3855,6 +3855,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 
diff erent.
+    // 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)) {
@@ -3867,12 +3869,30 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
       if (!IsCalleeStreamingCompatible &&
           (CallerFnType == SemaARM::ArmStreamingCompatible ||
            ((CallerFnType == SemaARM::ArmStreaming) ^ IsCalleeStreaming))) {
+        const LangOptions &LO = getLangOpts();
+        unsigned VL = LO.VScaleMin * 128;
+        unsigned SVL = LO.VScaleStreamingMin * 128;
+        bool IsVLMismatch = VL && SVL && VL != SVL;
+
+        auto EmitDiag = [&](bool IsArg) {
+          if (IsVLMismatch) {
+            if (CallerFnType == SemaARM::ArmStreamingCompatible)
+              // Emit warning for streaming-compatible callers
+              Diag(Loc, diag::warn_sme_streaming_compatible_vl_mismatch)
+                  << IsArg << IsCalleeStreaming << 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;
+        };
+
         if (IsScalableArg)
-          Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
-              << /*IsArg=*/true;
+          EmitDiag(true);
         if (IsScalableRet)
-          Diag(Loc, diag::warn_sme_streaming_pass_return_vl_to_non_streaming)
-              << /*IsArg=*/false;
+          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
new file mode 100644
index 0000000000000..41d89869062ff
--- /dev/null
+++ b/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c
@@ -0,0 +1,111 @@
+// 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 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;
+
+__SVInt8_t sme_streaming_returns_vl(void) __arm_streaming;
+
+void sme_streaming_compatible_with_vl_arg(__SVInt8_t a) __arm_streaming_compatible;
+
+__SVInt8_t sme_streaming_compatible_returns_vl(void) __arm_streaming_compatible;
+
+void sme_no_streaming_with_vl_arg(__SVInt8_t a);
+
+__SVInt8_t sme_no_streaming_returns_vl(void);
+
+
+void sme_no_streaming_calling_streaming_with_vl_args() {
+  __SVInt8_t a;
+  // expected-noflags-warning at +2 {{passing a VL-dependent argument to a function with a 
diff erent streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are 
diff erent at runtime}}
+  // expected-flags-error at +1 {{passing a VL-dependent argument to a function with a 
diff erent streaming-mode is undefined behaviour because the streaming vector length (256 bit) and non-streaming vector length (128 bit) 
diff er}}
+  sme_streaming_with_vl_arg(a);
+}
+
+void sme_no_streaming_calling_streaming_with_return_vl() {
+  // expected-noflags-warning at +2 {{returning a VL-dependent argument from a function with a 
diff erent streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are 
diff erent at runtime}}
+  // expected-flags-error at +1 {{returning a VL-dependent argument from a function with a 
diff erent streaming-mode is undefined behaviour because the streaming vector length (256 bit) and non-streaming vector length (128 bit) 
diff er}}
+  __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 at +2 {{passing a VL-dependent argument to a function with a 
diff erent streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are 
diff erent at runtime}}
+  // expected-flags-error at +1 {{passing a VL-dependent argument to a function with a 
diff erent streaming-mode is undefined behaviour because the streaming vector length (256 bit) and non-streaming vector length (128 bit) 
diff er}}
+  sme_no_streaming_with_vl_arg(a);
+}
+
+void sme_streaming_calling_non_streaming_with_return_vl(void) __arm_streaming {
+  // expected-noflags-warning at +2 {{returning a VL-dependent argument from a function with a 
diff erent streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are 
diff erent at runtime}}
+  // expected-flags-error at +1 {{returning a VL-dependent argument from a function with a 
diff erent streaming-mode is undefined behaviour because the streaming vector length (256 bit) and non-streaming vector length (128 bit) 
diff er}}
+  __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 at +2 {{passing a VL-dependent argument to a function with a 
diff erent streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are 
diff erent at runtime}}
+  // expected-flags-warning at +1 {{passing a VL-dependent argument to a streaming function is undefined behaviour when the streaming-compatible caller is not in streaming mode, because the streaming vector length (256 bit) and non-streaming vector length (128 bit) 
diff er}}
+  sme_streaming_with_vl_arg(arg);
+}
+
+void sme_streaming_compatible_calling_sme_streaming_return_vl(void) __arm_streaming_compatible {
+  // expected-noflags-warning at +2 {{returning a VL-dependent argument from a function with a 
diff erent streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are 
diff erent at runtime}}
+  // expected-flags-warning at +1 {{returning a VL-dependent argument from a streaming function is undefined behaviour when the streaming-compatible caller is not in streaming mode, because the streaming vector length (256 bit) and non-streaming vector length (128 bit) 
diff er}}
+  __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 at +2 {{passing a VL-dependent argument to a function with a 
diff erent streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are 
diff erent at runtime}}
+  // expected-flags-warning at +1 {{passing a VL-dependent argument to a non-streaming function is undefined behaviour when the streaming-compatible caller is in streaming mode, because the streaming vector length (256 bit) and non-streaming vector length (128 bit) 
diff er}}
+  sme_no_streaming_with_vl_arg(arg);
+}
+
+void sme_streaming_compatible_calling_no_sme_streaming_return_vl(void) __arm_streaming_compatible {
+  // expected-noflags-warning at +2 {{returning a VL-dependent argument from a function with a 
diff erent streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are 
diff erent at runtime}}
+  // expected-flags-warning at +1 {{returning a VL-dependent argument from a non-streaming function is undefined behaviour when the streaming-compatible caller is in streaming mode, because the streaming vector length (256 bit) and non-streaming vector length (128 bit) 
diff er}}
+  __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_with_vl_args() {
+  __SVInt8_t a;
+  sme_no_streaming_with_vl_arg(a);
+}
+
+void sme_no_streaming_calling_non_streaming_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();
+}


        


More information about the cfe-commits mailing list