https://github.com/kmclaughlin-arm updated https://github.com/llvm/llvm-project/pull/121777
>From 00772b871de43a5e30aca2a65a89675117cafbf1 Mon Sep 17 00:00:00 2001 From: Kerry McLaughlin <kerry.mclaugh...@arm.com> Date: Tue, 31 Dec 2024 17:22:02 +0000 Subject: [PATCH 1/2] [AArch64][SME] Add diagnostics to CheckConstexprFunctionDefinition CheckFunctionDeclaration emits diagnostics if any SME attributes are used by a function definition without the required +sme or +sme2 target features. This patch adds similar diagnostics to CheckConstexprFunctionDefinition to ensure this emits the same errors when attributes such as __arm_new("za") are found without +sme/+sme2. --- clang/lib/Sema/SemaDeclCXX.cpp | 22 +++++++++++++++++++ ...-sme-func-attrs-without-target-feature.cpp | 8 ++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index c5a72cf812ebc9..3ee26ebabcfdd5 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1854,6 +1854,28 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, } } + if (Context.getTargetInfo().getTriple().isAArch64()) { + const auto *Attr = NewFD->getAttr<ArmNewAttr>(); + bool LocallyStreaming = NewFD->hasAttr<ArmLocallyStreamingAttr>(); + llvm::StringMap<bool> FeatureMap; + Context.getFunctionFeatureMap(FeatureMap, NewFD); + if (!FeatureMap.contains("sme") && LocallyStreaming) { + Diag(NewFD->getLocation(), + diag::err_sme_definition_using_sm_in_non_sme_target); + return false; + } + if (Attr && Attr->isNewZA() && !FeatureMap.contains("sme")) { + Diag(NewFD->getLocation(), + diag::err_sme_definition_using_za_in_non_sme_target); + return false; + } + if (Attr && Attr->isNewZT0() && !FeatureMap.contains("sme2")) { + Diag(NewFD->getLocation(), + diag::err_sme_definition_using_zt0_in_non_sme2_target); + return false; + } + } + // - each of its parameter types shall be a literal type; (removed in C++23) if (!getLangOpts().CPlusPlus23 && !CheckConstexprParameterTypes(*this, NewFD, Kind)) diff --git a/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp b/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp index ec6bb6f5035784..a046b5aa1325cc 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp +++ b/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -std=c++23 -fsyntax-only -verify %s // This test is testing the diagnostics that Clang emits when compiling without '+sme'. @@ -48,3 +48,9 @@ void streaming_compatible_def2(void (*streaming_fn_ptr)(void) __arm_streaming, // Also test when call-site is not a function. int streaming_decl_ret_int() __arm_streaming; int x = streaming_decl_ret_int(); // expected-error {{call to a streaming function requires 'sme'}} + +void sme_attrs_method_decls() { + [&] __arm_locally_streaming () { return; }(); // expected-error {{function executed in streaming-SVE mode requires 'sme'}} + [&] __arm_new("za") () { return; }(); // expected-error {{function using ZA state requires 'sme'}} + [&] __arm_new("zt0") () { return; }(); // expected-error {{function using ZT0 state requires 'sme2'}} +} >From bbc80c21e66958a149cdfcf37a56ea5825728a2d Mon Sep 17 00:00:00 2001 From: Kerry McLaughlin <kerry.mclaugh...@arm.com> Date: Mon, 6 Jan 2025 15:55:36 +0000 Subject: [PATCH 2/2] - Move diagnostics to SemaARM.cpp --- clang/include/clang/Sema/SemaARM.h | 1 + clang/lib/Sema/SemaARM.cpp | 53 ++++++++++++++++++ clang/lib/Sema/SemaDecl.cpp | 55 +------------------ clang/lib/Sema/SemaDeclCXX.cpp | 24 +------- ...-sme-func-attrs-without-target-feature.cpp | 2 +- 5 files changed, 61 insertions(+), 74 deletions(-) diff --git a/clang/include/clang/Sema/SemaARM.h b/clang/include/clang/Sema/SemaARM.h index 8c4c56e2221301..08b03af7fd4bc6 100644 --- a/clang/include/clang/Sema/SemaARM.h +++ b/clang/include/clang/Sema/SemaARM.h @@ -79,6 +79,7 @@ class SemaARM : public SemaBase { void handleNewAttr(Decl *D, const ParsedAttr &AL); void handleCmseNSEntryAttr(Decl *D, const ParsedAttr &AL); void handleInterruptAttr(Decl *D, const ParsedAttr &AL); + void CheckSMEFunctionDefAttributes(const FunctionDecl *FD); }; SemaARM::ArmStreamingType getArmStreamingFnType(const FunctionDecl *FD); diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp index 411baa066f7097..eafd43eb979ba0 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -1328,4 +1328,57 @@ void SemaARM::handleInterruptAttr(Decl *D, const ParsedAttr &AL) { ARMInterruptAttr(getASTContext(), AL, Kind)); } +// Check if the function definition uses any AArch64 SME features without +// having the '+sme' feature enabled and warn user if sme locally streaming +// function returns or uses arguments with VL-based types. +void SemaARM::CheckSMEFunctionDefAttributes(const FunctionDecl *FD) { + const auto *Attr = FD->getAttr<ArmNewAttr>(); + bool UsesSM = FD->hasAttr<ArmLocallyStreamingAttr>(); + bool UsesZA = Attr && Attr->isNewZA(); + bool UsesZT0 = Attr && Attr->isNewZT0(); + + if (FD->hasAttr<ArmLocallyStreamingAttr>()) { + if (FD->getReturnType()->isSizelessVectorType()) + Diag(FD->getLocation(), + diag::warn_sme_locally_streaming_has_vl_args_returns) + << /*IsArg=*/false; + if (llvm::any_of(FD->parameters(), [](ParmVarDecl *P) { + return P->getOriginalType()->isSizelessVectorType(); + })) + Diag(FD->getLocation(), + diag::warn_sme_locally_streaming_has_vl_args_returns) + << /*IsArg=*/true; + } + if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) { + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + UsesSM |= EPI.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask; + UsesZA |= FunctionType::getArmZAState(EPI.AArch64SMEAttributes) != + FunctionType::ARM_None; + UsesZT0 |= FunctionType::getArmZT0State(EPI.AArch64SMEAttributes) != + FunctionType::ARM_None; + } + + ASTContext &Context = getASTContext(); + if (UsesSM || UsesZA) { + llvm::StringMap<bool> FeatureMap; + Context.getFunctionFeatureMap(FeatureMap, FD); + if (!FeatureMap.contains("sme")) { + if (UsesSM) + Diag(FD->getLocation(), + diag::err_sme_definition_using_sm_in_non_sme_target); + else + Diag(FD->getLocation(), + diag::err_sme_definition_using_za_in_non_sme_target); + } + } + if (UsesZT0) { + llvm::StringMap<bool> FeatureMap; + Context.getFunctionFeatureMap(FeatureMap, FD); + if (!FeatureMap.contains("sme2")) { + Diag(FD->getLocation(), + diag::err_sme_definition_using_zt0_in_non_sme2_target); + } + } +} + } // namespace clang diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 4001c4d263f1d2..1603b622a4faf0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -45,6 +45,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaARM.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" @@ -12286,58 +12287,8 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } } - // Check if the function definition uses any AArch64 SME features without - // having the '+sme' feature enabled and warn user if sme locally streaming - // function returns or uses arguments with VL-based types. - if (DeclIsDefn) { - const auto *Attr = NewFD->getAttr<ArmNewAttr>(); - bool UsesSM = NewFD->hasAttr<ArmLocallyStreamingAttr>(); - bool UsesZA = Attr && Attr->isNewZA(); - bool UsesZT0 = Attr && Attr->isNewZT0(); - - if (NewFD->hasAttr<ArmLocallyStreamingAttr>()) { - if (NewFD->getReturnType()->isSizelessVectorType()) - Diag(NewFD->getLocation(), - diag::warn_sme_locally_streaming_has_vl_args_returns) - << /*IsArg=*/false; - if (llvm::any_of(NewFD->parameters(), [](ParmVarDecl *P) { - return P->getOriginalType()->isSizelessVectorType(); - })) - Diag(NewFD->getLocation(), - diag::warn_sme_locally_streaming_has_vl_args_returns) - << /*IsArg=*/true; - } - if (const auto *FPT = NewFD->getType()->getAs<FunctionProtoType>()) { - FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - UsesSM |= - EPI.AArch64SMEAttributes & FunctionType::SME_PStateSMEnabledMask; - UsesZA |= FunctionType::getArmZAState(EPI.AArch64SMEAttributes) != - FunctionType::ARM_None; - UsesZT0 |= FunctionType::getArmZT0State(EPI.AArch64SMEAttributes) != - FunctionType::ARM_None; - } - - if (UsesSM || UsesZA) { - llvm::StringMap<bool> FeatureMap; - Context.getFunctionFeatureMap(FeatureMap, NewFD); - if (!FeatureMap.contains("sme")) { - if (UsesSM) - Diag(NewFD->getLocation(), - diag::err_sme_definition_using_sm_in_non_sme_target); - else - Diag(NewFD->getLocation(), - diag::err_sme_definition_using_za_in_non_sme_target); - } - } - if (UsesZT0) { - llvm::StringMap<bool> FeatureMap; - Context.getFunctionFeatureMap(FeatureMap, NewFD); - if (!FeatureMap.contains("sme2")) { - Diag(NewFD->getLocation(), - diag::err_sme_definition_using_zt0_in_non_sme2_target); - } - } - } + if (DeclIsDefn && Context.getTargetInfo().getTriple().isAArch64()) + ARM().CheckSMEFunctionDefAttributes(NewFD); return Redeclaration; } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 3ee26ebabcfdd5..e599ff3731a314 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -41,6 +41,7 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaARM.h" #include "clang/Sema/SemaCUDA.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaObjC.h" @@ -1854,27 +1855,8 @@ bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, } } - if (Context.getTargetInfo().getTriple().isAArch64()) { - const auto *Attr = NewFD->getAttr<ArmNewAttr>(); - bool LocallyStreaming = NewFD->hasAttr<ArmLocallyStreamingAttr>(); - llvm::StringMap<bool> FeatureMap; - Context.getFunctionFeatureMap(FeatureMap, NewFD); - if (!FeatureMap.contains("sme") && LocallyStreaming) { - Diag(NewFD->getLocation(), - diag::err_sme_definition_using_sm_in_non_sme_target); - return false; - } - if (Attr && Attr->isNewZA() && !FeatureMap.contains("sme")) { - Diag(NewFD->getLocation(), - diag::err_sme_definition_using_za_in_non_sme_target); - return false; - } - if (Attr && Attr->isNewZT0() && !FeatureMap.contains("sme2")) { - Diag(NewFD->getLocation(), - diag::err_sme_definition_using_zt0_in_non_sme2_target); - return false; - } - } + if (Context.getTargetInfo().getTriple().isAArch64()) + ARM().CheckSMEFunctionDefAttributes(NewFD); // - each of its parameter types shall be a literal type; (removed in C++23) if (!getLangOpts().CPlusPlus23 && diff --git a/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp b/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp index a046b5aa1325cc..02ebfc8060f37e 100644 --- a/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp +++ b/clang/test/Sema/aarch64-sme-func-attrs-without-target-feature.cpp @@ -49,7 +49,7 @@ void streaming_compatible_def2(void (*streaming_fn_ptr)(void) __arm_streaming, int streaming_decl_ret_int() __arm_streaming; int x = streaming_decl_ret_int(); // expected-error {{call to a streaming function requires 'sme'}} -void sme_attrs_method_decls() { +void sme_attrs_lambdas() { [&] __arm_locally_streaming () { return; }(); // expected-error {{function executed in streaming-SVE mode requires 'sme'}} [&] __arm_new("za") () { return; }(); // expected-error {{function using ZA state requires 'sme'}} [&] __arm_new("zt0") () { return; }(); // expected-error {{function using ZT0 state requires 'sme2'}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits