[cfe-dev] RFC: Clang and libstdc++ versions, string.h and cstring conflicts, and glibc patches.

Eli Friedman eli.friedman at gmail.com
Thu Aug 29 17:16:18 PDT 2013


On Thu, Aug 29, 2013 at 2:33 PM, Brooks Moses <bmoses at google.com> wrote:

> Hi all,
>
> So I have this local Clang-related glibc patch that I've been trying
> to push upstream, and it's opened a bit of a can of worms that I would
> like some advice on....
>
> tl;dr: If string.h in glibc 2.19 checks for __clang__ and breaks
> compatibility with libstdc++ 4.3 if it's found, is that bad?  What if
> it checks for a recent version of Clang?
>
>
> The context is straightforward: In C++, some of the functions in
> strings.h have different declarations than they do in C.  You can see
> this easily in libc++'s cstring, where there's a block of inline
> functions that are guarded by an ifdef -- those are there to account
> for C++ inclusions of string.h that are not C++-aware.
> http://llvm.org/svn/llvm-project/libcxx/trunk/include/cstring
>
> (There's a closely-related issue with wcschr, which was a subject of
> another recent email:
> http://lists.cs.uiuc.edu/pipermail/cfe-dev/2013-August/031618.html)
>
> Where this gets complicated is in coordinating the C and C++ libraries
> to make sure there is only one version of these definitions.
> Originally, glibc's headers didn't define these, and so they were
> defined in libstdc++ and libc++ headers.  All is good, except for the
> fact that glibc's headers contain wrong-for-C++ definitions instead.
>
> In 2009, pre-GCC 4.4, a coordinated pair of patches went in to define
> these in glibc and to avoid defining them in libstdc++ if they were
> defined in glibc.  But those aren't synchronized projects -- so in
> glibc's string.h, these are only defined if the GCC version is 4.4 or
> higher, and string.h defines special macros that the libstdc++ headers
> use to determine what to do.
>
> This, of course, broke libc++ when compiling with GCC 4.4, which led
> to bug 7983; the solution to that was to simply not include the
> definitions in cstring when using any version of glibc.  (This breaks
> libc++ with older glibc or GCC versions; I presume that was considered
> irrelevant.)
>
> And that brings us to the problem we have today: compiling C++ code
> with Clang.  Clang reports itself as having compatibility with GCC 4.2
> -- and thus glibc's string.h assumes it's dealing with a version-4.2
> libstdc++ and exports the old wrong-for-C++ C declarations instead of
> the new C++ ones.
>
> This leads to some subtle flavors of sadness, and so we have a
> Google-local patch that changes glibc's strings.h check to check for
> __clang__ as well as for GCC version of 4.4 or later.  I proposed that
> upstream:
> http://sourceware.org/ml/libc-alpha/2013-08/msg00556.html
>
> The glibc maintainers pointed out that this will cause problems if
> someone is using Clang and glibc 2.19 or later but also using a
> libstdc++ that's older than 4.4, or a libc++ before the fix for bug
> 7983 from late 2010.
>
> So, question 1: Are these use-cases that actually need to be
> supported, or are those sufficiently mismatched versions that we can
> just say "don't do that"?
>

The case of an old libc++ doesn't matter; nobody was using libc++ in late
2010.

The case of an old libstdc++ is more interesting... we might care?  In
practice, any of the solutions is probably fine: glibc gets upgraded along
with the system, which implies a newer gcc, which implies clang will find a
newer libstdc++.


> One of the glibc maintainers also pointed out that checking for
> __clang__ is specific to one non-GCC compiler when there are many that
> might be affected, and suggested using __cplusplus >= 199701L instead.
>  Because GCC and Clang had defined this with a non-standard value of 1
> until recently (May 2012 for Clang), this would apply broadly but only
> catch new versions.
>
> Question 2: Would it be objectionable to accept this solution?  It
> limits the version combinations that break for question 1 (in that you
> now need a new glibc _and_ a new Clang along with the old libstdc++ to
> get breakage), but it also means not-new versions of Clang don't get
> the fix either.
>
>
The "right" solution is really something like "#if _LIBCPP_VERSION ||
__GLIBCXX__ > 20070719" (replace 20070719 with the right date), but I don't
know if there's any reliable way to get the right definition of
__GLIBCXX__.  (You should be able to get the definition of _LIBCPP_VERSION
without causing circular dependencies by including ciso646.)

Barring that, there isn't any solution that doesn't break the "new clang
with old libstdc++" case, which is the only case which might possibly
matter, so it's hard to say one solution is better than the other.

-Eli
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130829/d1671b18/attachment.html>


More information about the cfe-dev mailing list