https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95927
--- Comment #1 from Haoxin Tu <haoxintu at gmail dot com> --- Add a more meaningful case. $cat p.cc template <class> struct a {}; class A { struct a < struct x { void b ( ){}} >; }; $g++ p.cc p.cc:3:25: error: types may not be defined in template arguments 3 | struct a < struct x { void b ( ){}} >; | ^ p.cc:3:40: error: expected ‘;’ after struct definition 3 | struct a < struct x { void b ( ){}} >; | ^ | ; p.cc:3:39: error: expected template-argument before ‘;’ token 3 | struct a < struct x { void b ( ){}} >; | ^ p.cc:3:39: error: expected ‘>’ before ‘;’ token p.cc:3:5: error: ‘struct a<A::x>’ redeclared with different access 3 | struct a < struct x { void b ( ){}} >; | ^~~~~~ p.cc:3:41: error: expected unqualified-id before ‘>’ token 3 | struct a < struct x { void b ( ){}} >; | ^ p.cc:4:1: internal compiler error: in cp_lexer_new_from_tokens, at cp/parser.c:701 4 | }; | ^ 0x6adadc cp_parser_push_lexer_for_tokens ../../gcc/cp/parser.c:701 ... While in Clang $clang++ p.cc p.cc:3:23: error: 'x' cannot be defined in a type specifier struct a < struct x { void b ( ){}} >; ^ 1 error generated. I guess Clang is performed better when parsing this case. GCC emits a lot of error messages even throw an ICE, while Clang just emits one.