[cfe-dev] Keyword warnings in libc++'s type_traits and other headers
Marshall Clow
mclow.lists at gmail.com
Tue Dec 24 12:01:27 PST 2013
On Dec 24, 2013, at 9:57 AM, M.E. O'Neill <oneill at cs.hmc.edu> wrote:
> Howard Hinnant <howard.hinnant at gmail.com> wrote:
>> If there is no breakage I see no reason for libc++ to change.
>
> The issue is partly that the C++ standard (17.6.4.3.2 [global.names]) says:
>
>>> Certain sets of names and function signatures are always reserved to the implementation:
>>> — Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter (2.12) is reserved to the implementation for any use.
>
> If you see libc++ as part of "the implementation" (i.e., there is one single LLVM system that libc++ is part of), then your use of double underscores is absolutely fine (at least technically, if not practically).
>
> If, however, you want libc++ to be usable with other compilers (e.g., GCC), the double underscores don't really belong to you. A conforming C++ compiler could reject all identifiers that begin with double underscores in code that isn't part of the compiler's own implementation. (Of course, arguably a conforming C++ compiler might not let you swap in a new standard library at all.)
>
> But in practical terms, there is a bigger problem -- across several system-level projects, there seems to be a belief in a kind of double underscore magical thinking that goes like this: “Worried about a name clash? Here's the fix! Prefix your identifier with a double underscore and it'll be all good!!”
>
> Various libraries do this. Glibc thinks it's a system library and has the right to all names starting with double underscores. Hence problems stemming from their using identifiers reserved by non-GCC compilers, like __block which got taken by the blocks extension from Objective-C. And it's not just Glibc, other libraries like cygwin that feel "system"ish do it too.
>
> If you want to reduce the risk, instead of using __x and __y, you should instead use _llvm_libcxx_x and _llvm_libcxx_y. It may feel like this is a mouthful, but it's much less risky.
It’s also non-conforming.
The user is perfectly within his rights to use _llvm_libcxx_x as an identifier or macro name (something like)
#define _llvm_libcxx_x(x) do { if (x) {}} while(false);
#include <type_traits>
int main () { _llvm_libcxx_x(true); }
This would fail to compile, and a user who wrote this could file a defect report against libc++ (and they would be correct!)
As a standard library implementation, libc++ *has* to use reserved identifiers (single underscore followed by capital, double underscore) to avoid collisions with identifiers (and macros) that are defined by the user.
If the user wrote this instead:
#define __is_x(x) do { if (x) {}} while(false);
#include <type_traits>
int main () { __is_x(true); }
I could correctly reject a bug report with “all identifiers beginning with __ are reserved. Don’t use them”.
Alp wrote:
> libc++ on the other has the freedom to use any identifier in the global namespace, or indeed to use a C++ private namespace where any name goes, potentially letting you use short private names without any prefix or underscores at all.
This is an incorrect understanding of the situation.
— Marshall
More information about the cfe-dev
mailing list