diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index ee9d529c69e3..19c46ab9c97f 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -158,6 +158,22 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,
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();
+ CXXRecordDecl *RD = dyn_cast(D->getDeclContext());
+ if (DT && RD && isa(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)
diff --git a/test/SemaCXX/libstdcxx_common_type_hack.cpp b/test/SemaCXX/libstdcxx_common_type_hack.cpp
new file mode 100644
index 000000000000..e9cb22f9dabf
--- /dev/null
+++ b/test/SemaCXX/libstdcxx_common_type_hack.cpp
@@ -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 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 T &&declval();
+
+ template struct common_type {};
+ template struct common_type {
+ // Under the rules in the standard, this always produces a
+ // reference type.
+ typedef decltype(true ? declval() : declval()) type;
+ };
+}
+
+#else
+
+#define BE_THE_HEADER
+#include "libstdcxx_common_type_hack.cpp"
+
+using T = int;
+using T = std::common_type::type;
+
+using U = int; // expected-note {{here}}
+using U = decltype(true ? std::declval() : std::declval()); // expected-error {{different types}}
+
+#endif
diff --git a/www/cxx_status.html b/www/cxx_status.html
index dbf5797c0501..b4821a1fd858 100644
--- a/www/cxx_status.html
+++ b/www/cxx_status.html
@@ -40,10 +40,11 @@ C++11 implementation status
You can use Clang in C++11 mode either
with libc++ or with gcc's libstdc++.
-Patches are needed to make libstdc++-4.4,
+Patches are needed to make libstdc++-4.4
+work with Clang in C++11 mode. Patches are also needed to make
libstdc++-4.6,
-and libstdc++-4.7 work with Clang in
-C++11 mode.
+and libstdc++-4.7 work with Clang
+releases prior to version 3.2 in C++11 mode.