template<typename> struct A; template<typename T> struct A { A(Y); }; A<int> a; This invalid code produces: tp.cc: In instantiation of 'struct A<int>': tp.cc:5:8: required from here tp.cc:3:36: error: 'A< <template-parameter-1-1> >::Y' has incomplete type template<typename T> struct A { A(Y); }; ^ tp.cc:3:29: error: declaration of 'struct A<int>' template<typename T> struct A { A(Y); }; ^ This is correct, but "A< <template-parameter-1-1> >::Y" is rather ugly. At the point of the error the parameter has a name, so "A<T>::Y" could be shown instead.
I think there are other bugs about printing "template-parameter-1-1". I don't see why the pretty-printer may ever need to print such a thing.
There are several "bugs" in this case. The first one is that we consider that the type of: template<typename> struct A is "struct A< <template-parameter-1-1> >". It would be nicer to print something like "struct A<typename>" or "struct A<>". Clang never needs to print made up names. The second bug is that I think we record T when parsing, but later we drop it. I wasn't able to find when we drop it. There is a lot going on between the moment we parse T and the moment we parse {, so it is rather difficult to figure out. Stepping in the parser is rather frustrating. I am afraid that the only person that may know what is going or where to look is Jason. There is lookup_template_class, but by the time we call it, we already dropped T (or so it seems to me, maybe it is recorded somewhere else).
BTW, the parser may benefit by marking some functions with "skip" to help debugging. All the cp_lexer_peek_* are useless to step into.
Possibly related PR57014.
This continues to be annoying. Libstdc++ has loads of forward declarations of templates, e.g. in <type_traits>: // Forward declarations template<typename> struct is_reference; template<typename> struct is_function; template<typename> struct is_void; template<typename> struct remove_cv; template<typename> struct is_const; Which means we then get diagnostics containing: std::is_same<_U1, typename std::remove_cv< <template-parameter-1-1> >::type&> I agree with Manu that this could just show "typename" here. We don't refer to the template-parameter-1-1 type again in the diagnostic, so why do we care about uniquely identifying it as 1-1? But why is it even using the name from the remove_cv declaration? That should not be appearing in the *use* of remove_cv here. I've filed that as PR 104094.