From 399e9c43ce9e3aa30b8aaeec7a6f592e9b7c6893 Mon Sep 17 00:00:00 2001 From: Alex Coplan Date: Mon, 6 Jul 2026 14:22:46 +0100 Subject: [PATCH] Explicitly forbid inheriting SME keyword attributes This patch aims to clarify the interaction between SME keyword attributes and a common compiler extension which allows type attributes to be inherited given a pair of subsequent declarations D1, D2 where D1 has type attributes and D2 has none. The patch just explicitly spells out behaviour which (in my understanding) is: - the intent of the existing specification - existing clang behaviour - intended GCC behaviour (which has regressed in GCC 16, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122483). The hope is that the new wording will help smooth the way for this regression to be fixed in GCC 17. The SME keyword attributes section says: > Except where noted otherwise, function types that have an attribute > are incompatible with function types that do not. I believe the intent here was for this incompatibility to extend to compiler extensions which currently allow code such as: ```c void f(void) [[attr1, ..., attrN]]; void f(void); ``` as a convenience for situations where f is likely to be included from a header file, and the user doesn't want to have to write out all of the attributes in a local redeclaration. E.g. the following C code is currently accepted by both GCC and clang: ```c void f(void) __attribute__((aarch64_vector_pcs)); void f(void); // accepted ``` but if we switch the order of the declarations, it is (correctly) rejected by both compilers: ```c void g(void); void g(void) __attribute__((aarch64_vector_pcs)); // rejected ``` I believe the intent of the ACLE for SME keyword attributes was always to reject code such as: ```cpp void f(void) __arm_inout("za"); void f(void); ``` i.e. that this convenience feature should _not_ apply to those SME keyword attributes that affect type identity. The rationale is along the lines that the above is logically equivalent to something like: ```cpp void f(za_state &); void f(void); ``` which should be considered ill-formed in the same way that e.g.: ```cpp int f(int x); void f(void); ``` is. --- main/acle.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/main/acle.md b/main/acle.md index 08cf03fe..470abd48 100644 --- a/main/acle.md +++ b/main/acle.md @@ -510,6 +510,9 @@ Armv8.4-A [[ARMARMv84]](#ARMARMv84). Support is added for the Dot Product intrin support for SVE2.3 (FEAT_SVE2p3) and SME2.3 shift right narrow intrinsics. * Bumped armv9.6 intrinsics implementation to [**Beta**](#current-status-and-anticipated-changes) * Added support for producer-consumer data placement hints. +* Clarified interaction between SME keyword attributes and a common compiler + extension whereby type attributes can be inherited between subsequent + duplicate decls. ### References @@ -10743,6 +10746,35 @@ The function type attributes cannot be used with K&R-style int f2(void) ATTR { ... } // OK ``` +Some implementations may, as an extension, accept code such as: + +```c +void f(void) [[attr1, attr2, ..., attrN]]; +void f(void); +``` + +where the second declaration inherits the type attributes from the +first, even if the declarations would otherwise be incompatible. + +However, this specification considers such code invalid if the first +declaration is annotated with an SME keyword attribute which would make +the declarations incompatible (as above), due to its absence from the +second declaration. + +Thus, e.g. all of the following (otherwise duplicate) declarations are +ill-formed: + +```c +void f(void) __arm_streaming; +void f(void); // Ill-formed + +void g(void) __arm_streaming_compatible; +void g(void) {} // Ill-formed + +void h(void) __arm_streaming __arm_inout("za"); +void h(void); // Ill-formed +``` + ### SME keyword attributes related to streaming mode