[clang] [Sema][AArch64] Emit error for mismatched VLs on streaming mode transitions (PR #159131)
Mary Kassayova via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 22 08:26:28 PDT 2025
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.kassayova at 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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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.kassayova at 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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 at +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 ae9c718425279863aa6ee5b628c9c63610c356dc Mon Sep 17 00:00:00 2001
From: Mary Kassayova <mary.kassayova at arm.com>
Date: Thu, 18 Sep 2025 12:16:15 +0000
Subject: [PATCH 3/3] Added SC warning
---
.../clang/Basic/DiagnosticSemaKinds.td | 7 +++-
clang/lib/Sema/SemaChecking.cpp | 18 +++++++----
...h64-sme-streaming-nonstreaming-vl-checks.c | 32 +++++++++----------
3 files changed, 33 insertions(+), 24 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 56b73f4cc355b..302ad9846391c 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 %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) 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 undefined behaviour 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..59b53ae020f74 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3773,15 +3773,19 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
const LangOptions &LO = getLangOpts();
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 << 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;
};
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..41d89869062ff 100644
--- a/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c
+++ b/clang/test/Sema/aarch64-sme-streaming-nonstreaming-vl-checks.c
@@ -5,66 +5,66 @@
// 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 { }
+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; }
+__SVInt8_t sme_streaming_returns_vl(void) __arm_streaming;
-void sme_streaming_compatible_with_vl_arg(__SVInt8_t a) __arm_streaming_compatible { }
+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; }
+__SVInt8_t sme_streaming_compatible_returns_vl(void) __arm_streaming_compatible;
-void sme_no_streaming_with_vl_arg(__SVInt8_t a) { }
+void sme_no_streaming_with_vl_arg(__SVInt8_t a);
-__SVInt8_t sme_no_streaming_returns_vl(void) { __SVInt8_t r; return r; }
+__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 different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
- // expected-flags-error at +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 at +1 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour 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 at +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 at +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 at +1 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour 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 at +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 at +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 at +1 {{passing a VL-dependent argument to a function with a different streaming-mode is undefined behaviour 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 at +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 at +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 at +1 {{returning a VL-dependent argument from a function with a different streaming-mode is undefined behaviour 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 at +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 at +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 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) differ}}
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 different streaming-mode is undefined behaviour when the streaming and non-streaming vector lengths are different at runtime}}
- // expected-flags-warning at +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 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) 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 at +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 at +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 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) 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 at +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 at +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 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) differ}}
__SVInt8_t r = sme_no_streaming_returns_vl();
}
@@ -93,12 +93,12 @@ 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() {
+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_compatible_with_return_vl() {
+void sme_no_streaming_calling_non_streaming_with_return_vl() {
__SVInt8_t r = sme_no_streaming_returns_vl();
}
More information about the cfe-commits
mailing list