In GCC and Clang, we can pass an integer variable into an attribute.
constexpr auto SIZE = 16;
int a [[gnu::vector_size(SIZE)]];
This is particularly useful when we write templates.
template<size_t N>
struct Vec {
int inner [[gnu::vector_size(N)]];
};
However, if the attribute requires a string, I cannot find a way to use a variable like that. Neither of these two approaches works.
constexpr const char* TARGET = "default";
[[gnu::target(TARGET)]] void foo() {}
constexpr const char TARGET[] = "default";
[[gnu::target(TARGET)]] void foo() {}
It there a way to achieve this?
CodePudding user response:
Standard attributes that take strings, like [[depecrated("reason")]]
, take a string literal, and not a variable or other expressions. This is like the message in a static_assert
declaration.
Looking at the gcc documentation for gcc-style __attribute__
specifiers https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax:
A possibly empty comma-separated list of expressions. For example,
format_arg
attributes use this form with the list being a single integer constant expression, andalias
attributes use this form with the list being a single string constant.
Where SIZE
would be an integer constant expression, but "string constant" seems to mean string literal instead of constant expression of type const char[N]
or const char*
. It's probably the case that C [[attribute]]
form would also require a string constant/literal, just like the standard attributes.
You can do this with a macro:
#define TARGET "default"
[[gnu::target(TARGET)]] void foo() {}
Or you can do this for a whole region of code with _Pragma("GCC target default")
:
#pragma GCC push_options
#pragma GCC target "default"
void foo() {}
#pragma GCC pop_options
... Except this seems to be bugged with GCC where some part of the compiler does not recognise target("default")
. And this pragma doesn't seem to work in general in C (with Clang or GCC in some simple tests), so this probably won't work. It may be fixed in the future though.
Either way, these wouldn't work with templates. There doesn't seem to be a technical reason why const char*
type expressions shouldn't be allowed, only no one seems to have implemented it and it hasn't been standardised.