Date: Thu, 19 Jul 2012 14:07:54 -0400 From: Jung-uk Kim <junguk.kim@gmail.com> To: Dimitry Andric <dim@freebsd.org> Cc: freebsd-ports@freebsd.org Subject: Re: [FYI] C++ compilers vs. __cplusplus (was Re: SV: Re: make failed for editors/libreoffice) Message-ID: <50084CFA.9090802@gmail.com> In-Reply-To: <500809DA.1030301@FreeBSD.org> References: <vyh5gfyc7ro596rvdbv95tih.1342623265060@email.android.com> <5006F780.2020004@FreeBSD.org> <44k3y1ndlp.fsf@be-well.ilk.org> <50073701.80205@FreeBSD.org> <500747F2.8010900@FreeBSD.org> <500809DA.1030301@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?50084CFA.9090802>