I disagree that users should avoid the preprocessor here. If their
code is only compiled by Clang, there is not a lot of compelling
reason for them to pass -Wunknown-attributes=whatever in the first
place. If the code is compiled by more than just Clang, then the only
nonfragile cross-compiler solutions are to use the preprocessor or the
build system. In my experience, developers prefer writing code to
writing build scripts.
Why isn’t there a compelling reason to pass -Wunknown-attributes=whatever? Attributes are useful for all sorts of things, such as static analysis tools. And adding a flag to a build script is not “writing build scripts”. It’s the simplest of build-system logic that I’d expect any developer to know how to do, but not every developer needs to know how to do it, just the ones who add tools to the workflow or update standards, etc.
I’m not certain why you believe using the preprocessor blocks using a
C++11 attribute – it doesn’t. There’s no difference between using
[[clang::foobar]] and a macro that expands to [[clang::foobar]] if the
attribute is supported and [[]] if it’s not, except for the lack of a
warning about ignored attributes.
My point is this: if we use macros anyway, there was no need to standardize attributes in C++11. attribute((whatever)) and MSVC’s __decspec(…) is sufficient (custom attributes could be handled in a similar way, such as how Qt Moc does it). Yes, things like [[noreturn]] and [[nodiscard]] would need to be wrapped in macros, but that’s not too much work.
However, we standardized an attribute syntax for C++11, and in C++17 we clarified that this attribute syntax needs to allow arbitrary attributes, not just standardized or compiler-specific ones.
I am not convinced that hacking build scripts is less work than using
macros. It’s arguable that the first time you need the macro is an
outsized amount of work (because you have to start adding boilerplate
at that point), but I believe the same is true the first time you need
to hack a build script to add the new warning flag + attribute list.
True. However, macros obscure the code:
SOME_ATTRIBUTE
void call_me();
It may be clear that SOME_ATTRIBUTE is an attribute, but I have to chase down the definition of SOME_ATTRIBUTE to determine what it is.
Also consider that some users will prefer to pass -Wno-unknown-attributes than use these macros, meaning they get no typo detection. However, if they could whitelist allowed attributes to turn off the warning for, I’d imagine many of those users would do so. Why not have a fine-grained option for warning control?
Given that (AFAIK) no other compiler gives you granularity to disable
unknown attribute warnings on a per-attribute basis, I don’t think
forcing users to try to deal with this in build scripts does users a
service.
Just because no compiler does it yet doesn’t mean we shouldn’t do it. I’ve submitted a similar feature request on GCC, and it seems well-received. I intend to do the same for MSVC.
This is especially true given that each compiler will require
a different build script change even if the flags are identical
between compilers, because different compilers support different lists
of attributes.
If different compilers support different lists of attributes, that’s not a problem. A -Wignore-unknown-attribute=clang::some_attribute in GCC would be fine in Clang, because it does nothing in Clang. The flag may differ between compilers, though, but that’s not anything developers aren’t already familiar with.