The recently version of Debian's g++ caused compilation errors in some packages during rebuilds. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1120951 Same happens with latest 16.0 trunk version with Godbolt https://godbolt.org/z/xodooafea for this reduced C++ program: #include <set> template <class S> class A { typedef S VertexSet; public: typename VertexSet::size_type size(); private: VertexSet vertices_; }; template <class S> inline typename A<S>::VertexSet::size_type A<S>::size() { return vertices_.size(); } int main() { A<std::set<int>> a; return a.size(); } with the error: <source>:16:55: error: 'class A<S>::VertexSet' resolves to 'A<S>::VertexSet', which is not a non-union class type [-Wtemplate-body] 16 | inline typename A<S>::VertexSet::size_type A<S>::size() | ^ Compiler returned: 1 With older version of g++ 15 is compiled without an error.
Reduced: ``` template <class S> struct A { typedef S c; typename S::n size(); }; template <class S> inline typename A<S>::c::n A<S>::size() { return 0; } ``` Confirmed. This works for me with the GCC 15.2.0 release so either it is a bug introduced afterwards or the report to debian is wrong about the version # (though maybe debian version # is also wrong because it says 15.2.0).
This is rejected since r16-4368-g49ddf362f0a7c1fdeb62f13a852a2fdec9d6fe6d
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:2bf057c53e97004034ed1528d850a214372305b8 commit r16-6141-g2bf057c53e97004034ed1528d850a214372305b8 Author: Patrick Palka <ppalka@redhat.com> Date: Mon Dec 15 14:30:53 2025 -0500 c++: nested typename type resolving to wildcard type [PR122752] Here typename A<S>::VertexSet::size_type within the out-of-line declaration is initially parsed at namespace scope, so the LHS A<S>::VertexSet is treated as a dependent name and represented as a TYPENAME_TYPE with tag_type as class_type.[1] Once we realize we're parsing a member declarator we call maybe_update_decl_type to reprocess the TYPENAME_TYPE relative to the class template scope, during which make_typename_type succeeds in resolving the lookup and returns the member typedef VertexSet (to the TEMPLATE_TYPE_PARM S). But then the caller tsubst complains that this result isn't a class type as per the tag_type. This patch just relaxes tsubst to allow TYPENAME_TYPE getting resolved to a wildcard type regardless of the tag_type. This does mean we lose information about the tag_type during a subsequent tsubst, but that's probably harmless (famous last words). [1]: The tag_type should probably be scope_type. Changing this seems to be a matter of changing cp_parser_qualifying_entity to pass scope_type instead of class_type, but I don't feel confident about that and it seems risky. I then got confused as to why that function passes none_type in the !type_p case; to me it should use scope_type unconditionally, but doing so breaks things. This approach seems safer to backport. PR c++/122752 gcc/cp/ChangeLog: * pt.cc (tsubst) <case TYPENAME_TYPE>: Allow TYPENAME_TYPE resolving to another wildcard type. gcc/testsuite/ChangeLog: * g++.dg/template/dependent-name19.C: New test. Reviewed-by: Jason Merrill <jason@redhat.com>
The releases/gcc-15 branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:bb061a3b815249f2a4f375c3f7c6ea88978b9804 commit r15-10611-gbb061a3b815249f2a4f375c3f7c6ea88978b9804 Author: Patrick Palka <ppalka@redhat.com> Date: Mon Dec 15 14:30:53 2025 -0500 c++: nested typename type resolving to wildcard type [PR122752] Here typename A<S>::VertexSet::size_type within the out-of-line declaration is initially parsed at namespace scope, so the LHS A<S>::VertexSet is treated as a dependent name and represented as a TYPENAME_TYPE with tag_type as class_type.[1] Once we realize we're parsing a member declarator we call maybe_update_decl_type to reprocess the TYPENAME_TYPE relative to the class template scope, during which make_typename_type succeeds in resolving the lookup and returns the member typedef VertexSet (to the TEMPLATE_TYPE_PARM S). But then the caller tsubst complains that this result isn't a class type as per the tag_type. This patch just relaxes tsubst to allow TYPENAME_TYPE getting resolved to a wildcard type regardless of the tag_type. This does mean we lose information about the tag_type during a subsequent tsubst, but that's probably harmless (famous last words). [1]: The tag_type should probably be scope_type. Changing this seems to be a matter of changing cp_parser_qualifying_entity to pass scope_type instead of class_type, but I don't feel confident about that and it seems risky. I then got confused as to why that function passes none_type in the !type_p case; to me it should use scope_type unconditionally, but doing so breaks things. This approach seems safer to backport. PR c++/122752 gcc/cp/ChangeLog: * pt.cc (tsubst) <case TYPENAME_TYPE>: Allow TYPENAME_TYPE resolving to another wildcard type. gcc/testsuite/ChangeLog: * g++.dg/template/dependent-name19.C: New test. Reviewed-by: Jason Merrill <jason@redhat.com> (cherry picked from commit 2bf057c53e97004034ed1528d850a214372305b8)
Should be fixed for GCC 15.3, thanks for the bug report.
*** Bug 123590 has been marked as a duplicate of this bug. ***