Skip to content

Commit 2b7509e

Browse files
authored
[clang][SME] Account for C++ lambdas in SME builtin diagnostics (#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.
1 parent 62bcbe6 commit 2b7509e

File tree

2 files changed

+73
-4
lines changed

2 files changed

+73
-4
lines changed

clang/lib/Sema/SemaARM.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,8 @@ static ArmSMEState getSMEState(unsigned BuiltinID) {
636636

637637
bool SemaARM::CheckSMEBuiltinFunctionCall(unsigned BuiltinID,
638638
CallExpr *TheCall) {
639-
if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
639+
if (const FunctionDecl *FD =
640+
SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
640641
std::optional<ArmStreamingType> BuiltinType;
641642

642643
switch (BuiltinID) {
@@ -676,7 +677,8 @@ bool SemaARM::CheckSMEBuiltinFunctionCall(unsigned BuiltinID,
676677

677678
bool SemaARM::CheckSVEBuiltinFunctionCall(unsigned BuiltinID,
678679
CallExpr *TheCall) {
679-
if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
680+
if (const FunctionDecl *FD =
681+
SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
680682
std::optional<ArmStreamingType> BuiltinType;
681683

682684
switch (BuiltinID) {
@@ -705,7 +707,8 @@ bool SemaARM::CheckSVEBuiltinFunctionCall(unsigned BuiltinID,
705707
bool SemaARM::CheckNeonBuiltinFunctionCall(const TargetInfo &TI,
706708
unsigned BuiltinID,
707709
CallExpr *TheCall) {
708-
if (const FunctionDecl *FD = SemaRef.getCurFunctionDecl()) {
710+
if (const FunctionDecl *FD =
711+
SemaRef.getCurFunctionDecl(/*AllowLambda=*/true)) {
709712

710713
switch (BuiltinID) {
711714
default:

clang/test/Sema/aarch64-incompat-sm-builtin-calls.c renamed to clang/test/Sema/aarch64-incompat-sm-builtin-calls.cpp

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2-
// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve \
2+
// RUN: %clang_cc1 -std=c++23 -triple aarch64-none-linux-gnu -target-feature +sve \
33
// RUN: -target-feature +bf16 -target-feature +sve -target-feature +sme -target-feature +sme2 -target-feature +sve2 -target-feature +neon -Waarch64-sme-attributes -fsyntax-only -verify %s
44

55
// REQUIRES: aarch64-registered-target
@@ -126,3 +126,69 @@ void missing_zt0(void) __arm_streaming {
126126

127127
__arm_new("zt0")
128128
void new_zt0(void) __arm_streaming { svzero_zt(0); }
129+
130+
/// C++ lambda tests:
131+
132+
void use_streaming_builtin_in_lambda(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming __arm_out("za")
133+
{
134+
[&]{
135+
/// The lambda is its own function and does not inherit the SME attributes (so this should error).
136+
// expected-error@+1 {{builtin can only be called from a streaming function}}
137+
svld1_hor_za64(0, slice_base, pg, ptr);
138+
}();
139+
}
140+
141+
void use_streaming_builtin(uint32_t slice_base, svbool_t pg, const void *ptr) __arm_streaming __arm_out("za")
142+
{
143+
/// Without the lambda the same builtin is okay (as the SME attributes apply).
144+
svld1_hor_za64(0, slice_base, pg, ptr);
145+
}
146+
147+
int16x8_t use_neon_builtin_sm(int16x8_t splat) __arm_streaming_compatible {
148+
// expected-error@+1 {{builtin can only be called from a non-streaming function}}
149+
return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33);
150+
}
151+
152+
int16x8_t use_neon_builtin_sm_in_lambda(int16x8_t splat) __arm_streaming_compatible {
153+
return [&]{
154+
/// This should not error (as we switch out of streaming mode to execute the lambda).
155+
/// Note: The result int16x8_t is spilled and reloaded as a q-register.
156+
return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33);
157+
}();
158+
}
159+
160+
float use_incomp_sve_builtin_sm() __arm_streaming {
161+
// expected-error@+1 {{builtin can only be called from a non-streaming function}}
162+
return svadda(svptrue_b32(), 0, svdup_f32(1));
163+
}
164+
165+
float incomp_sve_sm_fadda_sm_in_lambda(void) __arm_streaming {
166+
return [&]{
167+
/// This should work like the Neon builtin.
168+
return svadda(svptrue_b32(), 0, svdup_f32(1));
169+
}();
170+
}
171+
172+
void use_streaming_builtin_in_streaming_lambda(uint32_t slice_base, const void *ptr)
173+
{
174+
[&] __arm_new("za") () __arm_streaming {
175+
// Here the lambda is streaming with ZA state, so this is okay.
176+
svld1_hor_za64(0, slice_base, svptrue_b64(), ptr);
177+
}();
178+
}
179+
180+
int16x8_t use_neon_builtin_in_streaming_lambda(int16x8_t splat) {
181+
return [&]() __arm_streaming_compatible {
182+
/// This should error as the lambda is streaming-compatible.
183+
// expected-error@+1 {{builtin can only be called from a non-streaming function}}
184+
return (int16x8_t)__builtin_neon_vqaddq_v((int8x16_t)splat, (int8x16_t)splat, 33);
185+
}();
186+
}
187+
188+
float incomp_sve_fadda_in_streaming_lambda(void) {
189+
return [&]() __arm_streaming {
190+
// Should error (like the Neon case above).
191+
// expected-error@+1 {{builtin can only be called from a non-streaming function}}
192+
return svadda(svptrue_b32(), 0, svdup_f32(1));
193+
}();
194+
}

0 commit comments

Comments
 (0)