[FYI] C++ compilers vs. __cplusplus (was Re: SV: Re: make failed
for editors/libreoffice)
Jung-uk Kim
junguk.kim at gmail.com
Thu Jul 19 18:08:04 UTC 2012
On 2012-07-19 09:21:30 -0400, Dimitry Andric wrote:
> On 2012-07-19 01:34, Jung-uk Kim wrote:
>> While I was tackling LibreOffice build issues, I found something
>> interesting about __cplusplus. Basically, different C++
>> compilers may have different __cplusplus definitions and it may
>> cause some strangeness. Clang, for example, used to set it to 1
>> but now it is set to C++ standard value since this commit:
>>
>> http://llvm.org/viewvc/llvm-project?view=rev&revision=156113
>
> Yes, this is because gcc started doing the same. Otherwise it
> becomes rather difficult to distinguish C++98, C++0x and C++11 in
> your C++ library implementation (in the GNU case, libstdc++ most
> likely).
Since when Clang started mimicking GCC 4.7?
% /usr/local/bin/clang++ -E -x c++ -dM /dev/null | grep __GNUC
#define __GNUC_GNU_INLINE__ 1
#define __GNUC_MINOR__ 2
#define __GNUC_PATCHLEVEL__ 1
#define __GNUC__ 4
;-)
>> This causes very subtle issues depending on compiler versions
>> and FreeBSD versions. For example, NULL may be defined
>> differently because stable/9 and head have this:
>>
>> #if __cplusplus >= 201103L #define NULL nullptr #elif
>> defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4 #define
>> NULL __null #else #if defined(__LP64__) #define NULL (0L)
>> #else #define NULL 0 #endif /* __LP64__ */ #endif /*
>> __GNUG__ */
>>
>> Before that, we had this:
>>
>> #if defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4
>> #define NULL __null #else #if defined(__LP64__) #define NULL
>> (0L) #else #define NULL 0 #endif /* __LP64__ */ #endif /*
>> __GNUG__ */
>>
>> What a mess...
>
> Well, this is what you get when standards progress to include
> non-standard features (such as gcc's "__null") that are already in
> use, but then subtly change them (calling them "nullptr").
Yes, it is subtle but it can cause a real trouble because NULL can
have different types depending on compiler versions and FreeBSD releases.
% cat test.cc
#include <cstddef>
char *test = reinterpret_cast<char *>(NULL);
% clang++ -c test.cc
% clang++ -c -std=gnu++98 test.cc
% clang++ -c -std=gnu++0x test.cc
% clang++ -c -std=c++98 test.cc
% clang++ -c -std=c++0x test.cc
test.cc:2:14: error: reinterpret_cast from 'nullptr_t' to 'char *' is
not allowed
char *test = reinterpret_cast<char *>(NULL);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
% /usr/local/bin/clang++ -c test.cc
% /usr/local/bin/clang++ -c -std=gnu++98 test.cc
% /usr/local/bin/clang++ -c -std=gnu++0x test.cc
test.cc:2:14: error: reinterpret_cast from 'nullptr_t' to 'char *' is
not allowed
char *test = reinterpret_cast<char *>(NULL);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
% /usr/local/bin/clang++ -c -std=c++98 test.cc
% /usr/local/bin/clang++ -c -std=c++0x test.cc
test.cc:2:14: error: reinterpret_cast from 'nullptr_t' to 'char *' is
not allowed
char *test = reinterpret_cast<char *>(NULL);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
When NULL is __null or an integral type, clang does not complain, of
course.
> However, as long as you can hide the #ifdef ugliness in a header,
> I don't really see the problem. This won't be the last ugly
> definition either. :)
I just wanted to let ports maintainers know about the caveat using
different C++ compilers on different FreeBSD releases.
Jung-uk Kim
More information about the freebsd-ports
mailing list