Opened 10 years ago

Closed 4 years ago

#7473 closed Bugs (obsolete)

clang defines __GNUC__ and confuses the libstdcpp3.hpp configuration header

Reported by: philipp.moeller@… Owned by: John Maddock
Milestone: To Be Determined Component: config
Version: Boost 1.56.0 Severity: Problem
Keywords: Cc:

Description

clang defines (at least on the current trunk) GNUC, GNUC_MINOR, and GNUC_PATCHLEVEL to 4, 2, and 1 respectively. When used with -std=c++11 GXX_EXPERIMENTAL_CXX0X will be defined as well. When using libstdcpp in combination with clang the boost configuration header libstdcpp3.hpp will use those broken version to detect library headers and features. Given the relatively low version number, most headers wont be available, which is counter-intuitive and can break in subtle ways.

Change History (18)

comment:1 by viboes, 10 years ago

I guess that you need to link with libc++ with clang as libstdcpp doesn't support c++11 features.

I'm using this

using clang : 3.2xl : /Users/viboes/clang/build/Debug+Asserts/bin/clang++ : <cxxflags>"-std=c++11 -stdlib=libc++" <linkflags>"-std=c++11 -stdlib=libc++" ;

comment:2 by Michel Morin, 10 years ago

Clang can work with more recent versions of libstdc++ than gcc-4.2's libstdc++ (though sometimes patches are needed). With those stdlib, we can use C++11 features.

What is needed here is to use __GLIBCXX__ to detect the version of libstdc++.

comment:3 by Michel Morin, 10 years ago

The above comment (comment 2) is the reply to comment 1.

in reply to:  2 comment:4 by philipp.moeller@…, 10 years ago

Replying to michel:

Clang can work with more recent versions of libstdc++ than gcc-4.2's libstdc++ (though sometimes patches are needed). With those stdlib, we can use C++11 features.

What is needed here is to use __GLIBCXX__ to detect the version of libstdc++.

It seems the mistake is to use the gcc version to detect the version of the library to begin with. However, I cannot find a good reference for the macros that good be used to detect the libstdc++ version besides this page. __GLIBCXX__ doesn't seem particularly helpful unless someone is willing to figure out what those values can be and create a table from them.

comment:5 by John Maddock, 10 years ago

Resolution: wontfix
Status: newclosed

What is needed here is to use __GLIBCXX__ to detect the version of libstdc++.

That's what we used to do originally. However, it caused a whole bunch of problems and we were specifically advised against doing that by the libstdc++ developers. The issue is that __GLIBCXX__ can have a higher value for say gcc-4.4.x than for gcc-4.5.0 but fewer features. I believe the bug here is in clang (or in the way you're using it). As far as I can see the only reliable way to support non-standard configurations like this is to use the supplied configure script to generate a custom configuration: http://www.boost.org/doc/libs/1_53_0/libs/config/doc/html/index.html#boost_config.configuring_boost_for_your_platform.using_the_configure_script

comment:6 by boost@…, 9 years ago

I'm hesitant to reopen because I'm relatively new to boost, but I believe this is still a big issue, and will become even more annoying in the future if nothing is done. It is frustrating that it is such a hurdle to use modern features of the most important C++ library with a modern mature wide spread C++ compiler.

Bumping __GNUC_MINOR__ has been discussed and discarded by clang-dev http://lists.cs.uiuc.edu/pipermail/cfe-dev/2012-May/021510.html

So what about an additional check using __clang_major__ and __clang_minor__? This seems only consistent if you choose (for good reason) not to use __GLIBCXX__. Blaming this to be a bug in clang doesn't really help anyone either.

P.S.: Even Jonathan Wakely advises against using __GXX_EXPERIMENTAL_CXX0X__

http://gcc.gnu.org/ml/gcc-help/2011-05/msg00354.html

comment:7 by anonymous, 9 years ago

Another suggestion: the availabilty of C++11 features may also (should) be tested by checking _ _cplusplus http://gcc.gnu.org/ml/gcc-help/2011-05/msg00355.html

This macro is defined in the C++ Standard and independent of the specific compiler, be it GCC or Clang.

GCC 4.7 is cheating, however, they set _ _cplusplus to 201103L, but haven't fully implemented the new features. This happened in GCC 4.8.1 only: http://gcc.gnu.org/gcc-4.8/cxx0x_status.html

comment:8 by anonymous, 9 years ago

The issue here is that the compiler and std lib are out of synch with each other. Testing the clang or std version doesn't help if the library was actually shipped for an older compiler version as is the case here.

I repeat - what's wrong with using the supplied configure script to fix unsupported configurations like this? See http://www.boost.org/doc/libs/1_53_0/libs/config/doc/html/index.html#boost_config.configuring_boost_for_your_platform.using_the_configure_script

comment:9 by Nicolas.Hoeft@…, 9 years ago

IMHO, the problem is that this configuration (clang + gcc stdlibc++) is not that uncommon on linux and usually work quite well together. libc++ seems not to be in that good shape (for linux) and it's quite a hassle installing it.

The problem with user-defined configurations is that if you are writing a library that uses boost, every user of that library will have to configure boost by himself..

comment:10 by John Maddock, 9 years ago

Here's the thing: I'm quite happy to apply a fix for this, but I just don't see how it can possibly be made to work. To recap:

  • __GLIBCXX__ is useless for this purpose as it reflect release date, not lib version.
  • __clang_major__ tells us nothing about the std lib, only about Clang itself.
  • __cplusplus tells us nothing about the std lib, only Clang itself.
  • I can't see any internal libstdc++ macros can can be used for this purpose.
  • There's no way to tell whether the necessary patches (some official some not) have been applied to libstdc++, to pick one example recent versions of <type_traits> don't compile with clang -std=gnu++11 because clang lacks ___float128. It's trivial to patch, but there's no official clang patch last time I looked.
  • Clang only claims to be compatible with GCC-4.2.1, frankly anything else is unsupported as far as I can see... even though use with later versions is very useful and what most of us actually do!

Finally, if the user has to patch libstdc++, why not patch/configure boost as well? At least Intel's compiler sets the GCC version number to match that of the underlying std lib which avoids all this nonsense.

So... I don't see any way to fix this unless someone submits a patch that "works" and avoids the above pitfalls. The only thing I could think of, would be to use __GLIBCXX__ to detect libstdc++ features only when the compiler is clang. That would work some of the time, but break boost completely some of the time too, which frankly is not a path I want to take.

comment:11 by boost@…, 9 years ago

Thank you johnmaddock for the detailed and rational description. I do have a few remarks though:

  • Is clangs compatibility with gcc really relevant here? Shoudln't the C++11 compatibility be primary here?
  • Yes clang -std=gnu++11 is broken

Simply trying to compile the following with clang++ -std=gnu++11 fails for me due to said lack of __float128:

#include <boost/functional/hash.hpp>

(Boost 1.53.0, clang 3.2.6, libstdc++ of gcc 4.8.0 on arch). IMHO it looks to me that clang (with gnu++11 and libstd++) is broken and should be fixed (since it doesn't allow me to include <utility>). Or would you consider that a case of boost being completely broken?

  • So what about allowing all the nice features if all of the following holds:
    • Compiler is clang
    • __GLIBCXX__ is reasonably new: Pick a date where it is safe to assume that all later releases support the features plus maybe a list of release dates of versions known to support the features.
    • __cplusplus is C++11
    • __STRICT_ANSI__ is defined indicating that it's not gnu++11.

comment:12 by lukester_null@…, 8 years ago

I just tripped over this head-scratcher (why can't I construct a shared_ptr from a unique_ptr?!).

For what it's worth, I've tried a quick hack commenting out all ACTIV_BOOST_NO_CXX11_* macros in libstdcpp3.hpp for 4.3-4.7 GCC when building with clang 3.4 and libstdc++ 4.8.3.

Boost 1.56 with std=c++11 builds successfully, as do all the tests (except 1 that happens with a plain g++ 4.8.3 c++11 build, too).

Doesn't help with the GLIBCXX problem, I'm just pointing out that no patches had to be applied (unless Fedora themselves do so, I suppose).

Regards

Luke Elliott.

comment:13 by John Maddock, 8 years ago

Update: I looked at this again with a view to making cautious use of __GLIBCXX__ when the compiler is clang, but __GLIBCXX__ versions are so scrambled up as to be functionally useless, for example looking at https://www.gnu.org/software/gcc/releases.html I see

libstdc++ 4.3.5 later than 4.5
libstdc++ 4.3.6 later than 4.6
libstdc++ 4.5.4 later than 4.7
libstdc++ 4.6.4 later than 4.8
libstdc++ 4.7.4 later than 4.9

And that's just the obvious ones, and doesn't include "unofficial" releases from Apple etc.

Back to square 1...

Last edited 8 years ago by John Maddock (previous) (diff)

comment:14 by John Maddock, 8 years ago

There's a tentative patch for this issue here: https://github.com/boostorg/config/commit/b36566fe04a89103b7ef5569c03e3a26eb77af36

Replacement header for testing with here: https://raw.githubusercontent.com/boostorg/config/b36566fe04a89103b7ef5569c03e3a26eb77af36/include/boost/config/stdlib/libstdcpp3.hpp

I'd be grateful if as many folks as possible can test this and report back, thanks!

comment:15 by marc.glisse@…, 8 years ago

Sorry for missing this PR, as it was closed a search didn't show it. For 4.8 I can suggest <debug/array> or <ext/random> or <ext/cmath>. For 4.9, maybe <shared_mutex> or <bits/c++14_warning.h>, or <experimental/optional> or <experimental/string_view>. For 5, <experimental/any> for now, maybe something with filesystem soon.

comment:16 by matwey.kornilov@…, 7 years ago

Resolution: wontfix
Status: closedreopened
Version: Boost 1.51.0Boost 1.56.0

Problem is still present at least in 1.56

comment:17 by matwey.kornilov@…, 7 years ago

1.56 is the last broken version

comment:18 by John Maddock, 4 years ago

Resolution: obsolete
Status: reopenedclosed
Note: See TracTickets for help on using tickets.