10

Whether false is allowed to be implicitly converted to pointer is different between clang++ and g++:

g++-4.8: always a warning with or without -std=c++11

clang++ (trunk): a warning if without -std=c++11, and an error if with -std=c++11

So anyone knows why g++ and clang++ behaves differently, and who is correct? What paragraphs in C++ standard (both C++03 and C++11) talks about the situation.

Thanks.

[hidden ~]$ cat b.cpp const char* f() { return false; } [hidden ~]$ g++ -c b.cpp b.cpp: In function ‘const char* f()’: b.cpp:1:26: warning: converting ‘false’ to pointer type ‘const char*’ [-Wconversion-null] const char* f() { return false; } ^ [hidden ~]$ g++ -std=c++11 -c b.cpp b.cpp: In function ‘const char* f()’: b.cpp:1:26: warning: converting ‘false’ to pointer type ‘const char*’ [-Wconversion-null] const char* f() { return false; } ^ [hidden ~]$ clang++ -c b.cpp b.cpp:1:26: warning: initialization of pointer of type 'const char *' to null from a constant boolean expression [-Wbool-conversion] const char* f() { return false; } ^~~~~ 1 warning generated. [hidden ~]$ clang++ -std=c++11 -c b.cpp b.cpp:1:26: error: cannot initialize return object of type 'const char *' with an rvalue of type 'bool' const char* f() { return false; } ^~~~~ 1 error generated. 
3
  • What does clang++ -std=c++03 do? Commented Jul 6, 2013 at 11:00
  • Warning, the same as without -std=c++11 Commented Jul 6, 2013 at 11:05
  • I somehow wonder if this does not all come down the C roots of C++. C++03 is compatible with C89 in which there was no bool type and false and true would only be macros; however C++11 is compatible with C11 which does have a bool type and thus it no longer makes sense to consider false as just another alias of 0. Commented Jul 6, 2013 at 13:21

1 Answer 1

6

I'd say clang with C++11 is right:

3.9.1 Fundamental types [basic.fundamental]

6 Values of type bool are either true or false. [ Note: There are no signed, unsigned, short, or long bool types or values. — end note ] Values of type bool participate in integral promotions (4.5).

bool does not have value zero, so can not be converted to null pointer:

4.10 Pointer conversions [conv.ptr]

1 A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t. A null pointer constant can be converted to a pointer type;

One might suggest conversion sequence consisting of integral promotion (bool to int) and null pointer conversion, but it would not be valid:

4 Standard conversions [conv]

1 Standard conversions are implicit conversions with built-in meaning. Clause 4 enumerates the full set of such conversions. A standard conversion sequence is a sequence of standard conversions in the following order:

  • Zero or one conversion from the following set: lvalue-to-rvalue conversion, array-to-pointer conversion, and function-to-pointer conversion.
  • Zero or one conversion from the following set: integral promotions, floating point promotion, integral conversions, floating point conversions, floating-integral conversions, pointer conversions, pointer to member conversions, and boolean conversions.
  • Zero or one qualification conversion.

[ Note: A standard conversion sequence can be empty, i.e., it can consist of no conversions. — end note ] A standard conversion sequence will be applied to an expression if necessary to convert it to a required destination type.

Sign up to request clarification or add additional context in comments.

2 Comments

Both compilers allow it in C++03 mode, so Clang is just as wrong as GCC (note, I did report this long ago, see open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1448 ). In C++11, clang only allows it because of a likely(?) forthcoming change in a later Standard that will ban any integral constant expression from being null pointer constants except plain "0". Unfortunately the close reason "The resolution of issue 903 makes it clear that false is not a null pointer constant." is completely irrelevant to my issue report :(
Well, not completely irrelevant, but it misses that the same issue happens with bool v = true; int a = { v }; - this by definition is "narrowing" and ill-formed, but implementations tend to accept it. It would IMO be better to clear up the definition of "false" and "true" to say what is intended here.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.