This revision was automatically updated to reflect the committed changes. Closed by commit rGfe4c9b3cb0c3: [clang] Remove libstdc++ friend template hack (authored by urnathan). Herald added a project: clang. Herald added a subscriber: cfe-commits.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101392/new/ https://reviews.llvm.org/D101392 Files: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/SemaCXX/libstdcxx_map_base_hack.cpp 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<typename _Key, typename _Value, typename _Ex, bool __unique, - typename _Hashtable> - 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 <typename _Key, typename _Value, typename _Ex, bool __unique, + // expected-note@-1{{previous template declaration}} + typename _Hashtable> +struct _Map_base {}; } } } namespace std { namespace tr1 { template<typename T> struct X1 { - template<typename _Key2, typename _Pair, typename _Hashtable> + template <typename _Key2, typename _Pair, typename _Hashtable> + // expected-error@-1{{too few template parameters}} friend struct __detail::_Map_base; }; } } -std::tr1::X1<int> x1i; +std::tr1::X1<int> x1i; // expected-note{{in instantiation}} Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1518,48 +1518,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<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")) { - if (cast<Decl>(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<typename _Key, typename _Value, typename _Ex, bool __unique, - typename _Hashtable> - 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 <typename _Key, typename _Value, typename _Ex, bool __unique, + // expected-note@-1{{previous template declaration}} + typename _Hashtable> +struct _Map_base {}; } } } namespace std { namespace tr1 { template<typename T> struct X1 { - template<typename _Key2, typename _Pair, typename _Hashtable> + template <typename _Key2, typename _Pair, typename _Hashtable> + // expected-error@-1{{too few template parameters}} friend struct __detail::_Map_base; }; } } -std::tr1::X1<int> x1i; +std::tr1::X1<int> x1i; // expected-note{{in instantiation}} Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1518,48 +1518,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<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")) { - if (cast<Decl>(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; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits