From 2ddcbab8ff9cf1c41ddb287145b101aa97a027ae Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 23 Oct 2012 00:32:41 +0000 Subject: 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 --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'clang/lib/Sema/SemaTemplateInstantiateDecl.cpp') 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(); + 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) -- cgit v1.2.3