Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1517,48 +1517,18 @@ return nullptr; } - 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(DC)->getIdentifier() && - cast(DC)->getIdentifier()->isStr("__detail")) { - DeclContext *DCParent = DC->getParent(); - if (DCParent->isNamespace() && - cast(DCParent)->getIdentifier() && - cast(DCParent)->getIdentifier()->isStr("tr1")) { - if (cast(DCParent)->isInStdNamespace()) - Complain = false; - } - } - TemplateParameterList *PrevParams = PrevClassTemplate->getMostRecentDecl()->getTemplateParameters(); // Make sure the parameter lists match. - if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, - Complain, - Sema::TPL_TemplateMatch)) { - if (Complain) - return nullptr; - - AdoptedPreviousTemplateParams = true; - InstParams = PrevParams; - } + if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, true, + Sema::TPL_TemplateMatch)) + return nullptr; // Do some additional validation, then merge default arguments // from the existing declarations. - if (!AdoptedPreviousTemplateParams && - SemaRef.CheckTemplateParameterList(InstParams, PrevParams, + if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams, Sema::TPC_ClassTemplate)) return nullptr; } Index: clang/test/SemaCXX/libstdcxx_map_base_hack.cpp =================================================================== --- clang/test/SemaCXX/libstdcxx_map_base_hack.cpp +++ clang/test/SemaCXX/libstdcxx_map_base_hack.cpp @@ -1,25 +1,27 @@ -// RUN: %clang_cc1 -fsyntax-only %s +// RUN: %clang_cc1 -fsyntax-only -verify %s // libstdc++ 4.2.x contains a bug where a friend struct template // declaration for std::tr1::__detail::_Map base has different -// template arguments than the real declaration. Clang has an -// egregious hack to work around this problem, since we can't modify -// all of the world's libstdc++'s. +// template arguments than the real declaration. -namespace std { namespace tr1 { namespace __detail { - template - struct _Map_base { }; +// We no longer contain the hack to workaround the problem. Verify that +// std::tr1::__detail::Map_base is not a unique and special snowflake. +namespace std { namespace tr1 { namespace __detail { +template +struct _Map_base {}; } } } namespace std { namespace tr1 { template struct X1 { - template + template + // expected-error@-1{{too few template parameters}} friend struct __detail::_Map_base; }; } } -std::tr1::X1 x1i; +std::tr1::X1 x1i; // expected-note{{in instantiation}}