[cfe-commits] r166455 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/libstdcxx_common_type_hack.cpp www/cxx_status.html
Richard Smith
richard-llvm at metafoo.co.uk
Mon Oct 22 17:32:41 PDT 2012
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!
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>
More information about the cfe-commits
mailing list