[cfe-commits] r166455 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/libstdcxx_common_type_hack.cpp www/cxx_status.html

Chandler Carruth chandlerc at google.com
Mon Oct 22 17:40:58 PDT 2012


On Mon, Oct 22, 2012 at 5:32 PM, Richard Smith
<richard-llvm at metafoo.co.uk> 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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits



More information about the cfe-commits mailing list