mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-25 02:28:18 +00:00
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! llvm-svn: 166455
This commit is contained in:
parent
d7fa5e420d
commit
2ddcbab8ff
@ -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<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)
|
||||
|
33
clang/test/SemaCXX/libstdcxx_common_type_hack.cpp
Normal file
33
clang/test/SemaCXX/libstdcxx_common_type_hack.cpp
Normal file
@ -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
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user