<div dir="ltr">On Thu, Aug 29, 2013 at 2:33 PM, Brooks Moses <span dir="ltr"><<a href="mailto:bmoses@google.com" target="_blank">bmoses@google.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Hi all,<br>
<br>
So I have this local Clang-related glibc patch that I've been trying<br>
to push upstream, and it's opened a bit of a can of worms that I would<br>
like some advice on....<br>
<br>
tl;dr: If string.h in glibc 2.19 checks for __clang__ and breaks<br>
compatibility with libstdc++ 4.3 if it's found, is that bad? What if<br>
it checks for a recent version of Clang?<br>
<br>
<br>
The context is straightforward: In C++, some of the functions in<br>
strings.h have different declarations than they do in C. You can see<br>
this easily in libc++'s cstring, where there's a block of inline<br>
functions that are guarded by an ifdef -- those are there to account<br>
for C++ inclusions of string.h that are not C++-aware.<br>
<a href="http://llvm.org/svn/llvm-project/libcxx/trunk/include/cstring" target="_blank">http://llvm.org/svn/llvm-project/libcxx/trunk/include/cstring</a><br>
<br>
(There's a closely-related issue with wcschr, which was a subject of<br>
another recent email:<br>
<a href="http://lists.cs.uiuc.edu/pipermail/cfe-dev/2013-August/031618.html" target="_blank">http://lists.cs.uiuc.edu/pipermail/cfe-dev/2013-August/031618.html</a>)<br>
<br>
Where this gets complicated is in coordinating the C and C++ libraries<br>
to make sure there is only one version of these definitions.<br>
Originally, glibc's headers didn't define these, and so they were<br>
defined in libstdc++ and libc++ headers. All is good, except for the<br>
fact that glibc's headers contain wrong-for-C++ definitions instead.<br>
<br>
In 2009, pre-GCC 4.4, a coordinated pair of patches went in to define<br>
these in glibc and to avoid defining them in libstdc++ if they were<br>
defined in glibc. But those aren't synchronized projects -- so in<br>
glibc's string.h, these are only defined if the GCC version is 4.4 or<br>
higher, and string.h defines special macros that the libstdc++ headers<br>
use to determine what to do.<br>
<br>
This, of course, broke libc++ when compiling with GCC 4.4, which led<br>
to bug 7983; the solution to that was to simply not include the<br>
definitions in cstring when using any version of glibc. (This breaks<br>
libc++ with older glibc or GCC versions; I presume that was considered<br>
irrelevant.)<br>
<br>
And that brings us to the problem we have today: compiling C++ code<br>
with Clang. Clang reports itself as having compatibility with GCC 4.2<br>
-- and thus glibc's string.h assumes it's dealing with a version-4.2<br>
libstdc++ and exports the old wrong-for-C++ C declarations instead of<br>
the new C++ ones.<br>
<br>
This leads to some subtle flavors of sadness, and so we have a<br>
Google-local patch that changes glibc's strings.h check to check for<br>
__clang__ as well as for GCC version of 4.4 or later. I proposed that<br>
upstream:<br>
<a href="http://sourceware.org/ml/libc-alpha/2013-08/msg00556.html" target="_blank">http://sourceware.org/ml/libc-alpha/2013-08/msg00556.html</a><br>
<br>
The glibc maintainers pointed out that this will cause problems if<br>
someone is using Clang and glibc 2.19 or later but also using a<br>
libstdc++ that's older than 4.4, or a libc++ before the fix for bug<br>
7983 from late 2010.<br>
<br>
So, question 1: Are these use-cases that actually need to be<br>
supported, or are those sufficiently mismatched versions that we can<br>
just say "don't do that"?<br></blockquote><div><br></div><div><div>The case of an old libc++ doesn't matter; nobody was using libc++ in late 2010.</div><div> </div><div>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++.</div>
</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
One of the glibc maintainers also pointed out that checking for<br>
__clang__ is specific to one non-GCC compiler when there are many that<br>
might be affected, and suggested using __cplusplus >= 199701L instead.<br>
Because GCC and Clang had defined this with a non-standard value of 1<br>
until recently (May 2012 for Clang), this would apply broadly but only<br>
catch new versions.<br>
<br>
Question 2: Would it be objectionable to accept this solution? It<br>
limits the version combinations that break for question 1 (in that you<br>
now need a new glibc _and_ a new Clang along with the old libstdc++ to<br>
get breakage), but it also means not-new versions of Clang don't get<br>
the fix either.<br>
<br></blockquote><div><br></div><div>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.)</div>
<div><br></div><div>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.</div>
<div><br></div><div>-Eli </div></div></div></div>