On Mon, Oct 22, 2012 at 5:32 PM, Richard Smith <[email protected]> wrote: > Author: rsmith > Date: Mon Oct 22 19:32:41 2012 > New Revision: 166455 > > URL: http://llvm.org/viewvc/llvm-project?rev=166455&view=rev > Log: > Ugly ugly hack for libstdc++-4.6 and libstdc++-4.7 compatibility. These > libraries have an incorrect definition of std::common_type (inherited from a > bug in the standard -- see LWG issue 2141), whereby they produce reference > types when they should not. > > If we instantiate a typedef named std::common_type<...>::type, which is > defined > in a system header as decltype(... ? ... : ...), and the decltype produces a > reference type, convert it to the non-reference type. (This doesn't affect any > LWG2141-conforming implementation of common_type, such as libc++'s, because > the > default implementation of common_type<...>::type isn't supposed to produce a > reference type.) > > This is horrible. I'm really sorry. :( Better ideas appreciated!
So, we discussed potentially using a version test macro for this, and I think I might like that. I understand that this will cause a failure with other system libraries, but I actively want that -- they should get a bug report about their broken behavior before we include them in the hack to carry on bravely forward. Essentially, I want to only do this for standard libraries which have *shipped* with this bug and thus cannot be fixed in their source. That gives us a much better chance of deleting this code when those libraries are long gone. > > Added: > cfe/trunk/test/SemaCXX/libstdcxx_common_type_hack.cpp > Modified: > cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp > cfe/trunk/www/cxx_status.html > > Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=166455&r1=166454&r2=166455&view=diff > ============================================================================== > --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) > +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Oct 22 19:32:41 > 2012 > @@ -158,6 +158,22 @@ > SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), > DI->getType()); > } > > + // HACK: g++ has a bug where it gets the value kind of ?: wrong. > + // libstdc++ relies upon this bug in its implementation of common_type. > + // If we happen to be processing that implementation, fake up the g++ ?: > + // semantics. See LWG issue 2141 for more information on the bug. > + const DecltypeType *DT = DI->getType()->getAs<DecltypeType>(); > + CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()); > + if (DT && RD && isa<ConditionalOperator>(DT->getUnderlyingExpr()) && > + DT->isReferenceType() && > + RD->getEnclosingNamespaceContext() == SemaRef.getStdNamespace() && > + RD->getIdentifier() && RD->getIdentifier()->isStr("common_type") && > + D->getIdentifier() && D->getIdentifier()->isStr("type") && > + SemaRef.getSourceManager().isInSystemHeader(D->getLocStart())) > + // Fold it to the (non-reference) type which g++ would have produced. > + DI = SemaRef.Context.getTrivialTypeSourceInfo( > + DI->getType().getNonReferenceType()); > + > // Create the new typedef > TypedefNameDecl *Typedef; > if (IsTypeAlias) > > Added: cfe/trunk/test/SemaCXX/libstdcxx_common_type_hack.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/libstdcxx_common_type_hack.cpp?rev=166455&view=auto > ============================================================================== > --- cfe/trunk/test/SemaCXX/libstdcxx_common_type_hack.cpp (added) > +++ cfe/trunk/test/SemaCXX/libstdcxx_common_type_hack.cpp Mon Oct 22 19:32:41 > 2012 > @@ -0,0 +1,33 @@ > +// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify > + > +// This is a test for an egregious hack in Clang that works around > +// an issue with GCC's <type_traits> implementation. std::common_type > +// relies on pre-standard rules for decltype(), in which it doesn't > +// produce reference types so frequently. > + > +#ifdef BE_THE_HEADER > + > +#pragma GCC system_header > +namespace std { > + template<typename T> T &&declval(); > + > + template<typename...Ts> struct common_type {}; > + template<typename A, typename B> struct common_type<A, B> { > + // Under the rules in the standard, this always produces a > + // reference type. > + typedef decltype(true ? declval<A>() : declval<B>()) type; > + }; > +} > + > +#else > + > +#define BE_THE_HEADER > +#include "libstdcxx_common_type_hack.cpp" > + > +using T = int; > +using T = std::common_type<int, int>::type; > + > +using U = int; // expected-note {{here}} > +using U = decltype(true ? std::declval<int>() : std::declval<int>()); // > expected-error {{different types}} > + > +#endif > > Modified: cfe/trunk/www/cxx_status.html > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=166455&r1=166454&r2=166455&view=diff > ============================================================================== > --- cfe/trunk/www/cxx_status.html (original) > +++ cfe/trunk/www/cxx_status.html Mon Oct 22 19:32:41 2012 > @@ -40,10 +40,11 @@ > > <p>You can use Clang in C++11 mode either > with <a href="http://libcxx.llvm.org/">libc++</a> or with gcc's libstdc++. > -Patches are needed to make <a > href="libstdc++4.4-clang0x.patch">libstdc++-4.4</a>, > +Patches are needed to make <a > href="libstdc++4.4-clang0x.patch">libstdc++-4.4</a> > +work with Clang in C++11 mode. Patches are also needed to make > <a href="libstdc++4.6-clang11.patch">libstdc++-4.6</a>, > -and <a href="libstdc++4.7-clang11.patch">libstdc++-4.7</a> work with Clang in > -C++11 mode.</p> > +and <a href="libstdc++4.7-clang11.patch">libstdc++-4.7</a> work with Clang > +releases prior to version 3.2 in C++11 mode.</p> > > <table width="689" border="1" cellspacing="0"> > <tr> > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
