summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-10-23 00:32:41 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-10-23 00:32:41 +0000
commit2ddcbab8ff9cf1c41ddb287145b101aa97a027ae (patch)
tree1adc8c93d29d7157edd79ea7b39988cb453fe089 /clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
parentd7fa5e420d933dc2b354ff307e1344e380e45d01 (diff)
downloadbcm5719-llvm-2ddcbab8ff9cf1c41ddb287145b101aa97a027ae.tar.gz
bcm5719-llvm-2ddcbab8ff9cf1c41ddb287145b101aa97a027ae.zip
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
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp16
1 files changed, 16 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index ee9d529c69e..19c46ab9c97 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/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<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)
OpenPOWER on IntegriCloud