diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-10-23 00:32:41 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-10-23 00:32:41 +0000 |
commit | b5b37d194dddb960f43f763b3f9c3e17e7be3c2d (patch) | |
tree | 19592ee7bc4349dd793b866c58a51c9be91d8f0b /lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | 4ec429d1be4ede3d02712714f20470b2c87f748c (diff) |
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!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166455 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index ee9d529c69..19c46ab9c9 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<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) |