diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-04-08 18:16:15 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-04-08 18:16:15 +0000 |
| commit | 01e09d9d91ac65d85cb0f4ccbcd42204cf343410 (patch) | |
| tree | 543dcdd321978f226e6562934a30127f57163e1e /clang/lib/Sema | |
| parent | cb45bd9cb33932e79cceaca3ba560182ba329f72 (diff) | |
| download | bcm5719-llvm-01e09d9d91ac65d85cb0f4ccbcd42204cf343410.tar.gz bcm5719-llvm-01e09d9d91ac65d85cb0f4ccbcd42204cf343410.zip | |
Introduce an egregious hack to work around a bug in libstdc++ 4.2.x's
<tr1/hashtable> header, where a friend class template
std::tr1::__detail::_Map_base is declared with the wrong template
parameters. GCC doesn't catch the problem, so Clang does a little
back-flip to avoid diagnosing just this one instance of the problem.
llvm-svn: 100790
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9df345a11fc..e4690466d30 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -688,19 +688,52 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { return 0; } + bool AdoptedPreviousTemplateParams = false; if (PrevClassTemplate) { + bool Complain = true; + + // HACK: libstdc++ 4.2.1 contains an ill-formed friend class + // template for struct std::tr1::__detail::_Map_base, where the + // template parameters of the friend declaration don't match the + // template parameters of the original declaration. In this one + // case, we don't complain about the ill-formed friend + // declaration. + if (isFriend && Pattern->getIdentifier() && + Pattern->getIdentifier()->isStr("_Map_base") && + DC->isNamespace() && + cast<NamespaceDecl>(DC)->getIdentifier() && + cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__detail")) { + DeclContext *DCParent = DC->getParent(); + if (DCParent->isNamespace() && + cast<NamespaceDecl>(DCParent)->getIdentifier() && + cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) { + DeclContext *DCParent2 = DCParent->getParent(); + if (DCParent2->isNamespace() && + cast<NamespaceDecl>(DCParent2)->getIdentifier() && + cast<NamespaceDecl>(DCParent2)->getIdentifier()->isStr("std") && + DCParent2->getParent()->isTranslationUnit()) + Complain = false; + } + } + TemplateParameterList *PrevParams = PrevClassTemplate->getTemplateParameters(); // Make sure the parameter lists match. if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, - /*Complain=*/true, - Sema::TPL_TemplateMatch)) - return 0; + Complain, + Sema::TPL_TemplateMatch)) { + if (Complain) + return 0; + + AdoptedPreviousTemplateParams = true; + InstParams = PrevParams; + } // Do some additional validation, then merge default arguments // from the existing declarations. - if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams, + if (!AdoptedPreviousTemplateParams && + SemaRef.CheckTemplateParameterList(InstParams, PrevParams, Sema::TPC_ClassTemplate)) return 0; } |

