https://github.com/MacDue created 
https://github.com/llvm/llvm-project/pull/124750

A C++ lambda does not inherit attributes from the parent function. So the SME 
builtin diagnostics should look at the lambda's attributes, not the parent 
function's.

The fix is very simple and just adds the missing "AllowLambda" flag to the 
function decl lookups.

>From cb83182da6b017397111be606c88a4eeecb4ce9d Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxw...@arm.com>
Date: Tue, 28 Jan 2025 13:34:54 +0000
Subject: [PATCH] [clang][SME] Account for C++ lambdas in SME builtin
 diagnostics

A C++ lambda does not inherit attributes from the parent function. So
the SME builtin diagnostics should look at the lambda's attributes, not
the parent function's.

The fix is very simple and just adds the missing "AllowLambda" flag to
the function decl lookups.
---
 clang/lib/Sema/SemaARM.cpp                    |  9 ++--
 .../aarch64-incompat-sm-builtin-calls.cpp     | 47 +++++++++++++++++++
 2 files changed, 53 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/Sema/aarch64-incompat-sm-builtin-calls.cpp

diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 2620bbc97ba02a..df865d1b7df8c1 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -650,7 +650,8 @@ static ArmSMEState getSMEState(unsigned BuiltinID) {
 
 bool SemaARM::CheckSMEBuiltinFunctionCall(unsigned BuiltinID,
                                           CallExpr *TheCall) {
-  if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
+  if (const FunctionDecl *FD =
+          SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
     std::optional<ArmStreamingType> BuiltinType;
 
     switch (BuiltinID) {
@@ -690,7 +691,8 @@ bool SemaARM::CheckSMEBuiltinFunctionCall(unsigned 
BuiltinID,
 
 bool SemaARM::CheckSVEBuiltinFunctionCall(unsigned BuiltinID,
                                           CallExpr *TheCall) {
-  if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
+  if (const FunctionDecl *FD =
+          SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
     std::optional<ArmStreamingType> BuiltinType;
 
     switch (BuiltinID) {
@@ -719,7 +721,8 @@ bool SemaARM::CheckSVEBuiltinFunctionCall(unsigned 
BuiltinID,
 bool SemaARM::CheckNeonBuiltinFunctionCall(const TargetInfo &TI,
                                            unsigned BuiltinID,
                                            CallExpr *TheCall) {
-  if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
+  if (const FunctionDecl *FD =
+          SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
 
     switch (BuiltinID) {
     default:
diff --git a/clang/test/Sema/aarch64-incompat-sm-builtin-calls.cpp 
b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.cpp
new file mode 100644
index 00000000000000..12ef7ad06b68b1
--- /dev/null
+++ b/clang/test/Sema/aarch64-incompat-sm-builtin-calls.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1  -triple aarch64-none-linux-gnu -target-feature +sve \
+// RUN:   -target-feature +sme -target-feature +neon -x c++ -std=c++20 
-Waarch64-sme-attributes -fsyntax-only -verify %s
+
+// REQUIRES: aarch64-registered-target
+
+#include <arm_sme.h>
+#include <arm_neon.h>
+
+void use_streaming_builtin_in_lambda(uint32_t slice_base, svbool_t pg, const 
void *ptr) __arm_streaming __arm_out("za")
+{
+  [&]{
+    /// The lambda is its own function and does not inherit the SME attributes 
(so this should error).
+    // expected-error@+1 {{builtin can only be called from a streaming 
function}}
+    svld1_hor_za64(0, slice_base, pg, ptr);
+  }();
+}
+
+void use_streaming_builtin(uint32_t slice_base, svbool_t pg, const void *ptr) 
__arm_streaming __arm_out("za")
+{
+  /// Without the lambda the same builtin is okay (as the SME attributes 
apply).
+  svld1_hor_za64(0, slice_base, pg, ptr);
+}
+
+int16x8_t use_neon_builtin_sm(int16x8_t splat) __arm_streaming_compatible {
+  // expected-error@+1 {{builtin can only be called from a non-streaming 
function}}
+  return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, 
(int8x16_t)splat, 33);
+}
+
+int16x8_t use_neon_builtin_sm_in_lambda(int16x8_t splat) 
__arm_streaming_compatible {
+  return [&]{
+    /// This should not error (as we switch out of streaming mode to execute 
the lambda).
+    /// Note: The result int16x8_t is spilled and reloaded as a q-register.
+    return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, 
(int8x16_t)splat, 33);
+  }();
+}
+
+float use_incomp_sve_builtin_sm() __arm_streaming {
+  // expected-error@+1 {{builtin can only be called from a non-streaming 
function}}
+  return svadda(svptrue_b32(), 0, svdup_f32(1));
+}
+
+float incomp_sve_sm_fadda_sm_in_lambda(void) __arm_streaming {
+  return [&]{
+    /// This should work like the Neon builtin.
+    return svadda(svptrue_b32(), 0, svdup_f32(1));
+  }();
+}

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

Reply via email to