[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 ( [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