https://gcc.gnu.org/g:33b856931c78661944f27b60457365ef2b451b54
commit r16-7658-g33b856931c78661944f27b60457365ef2b451b54 Author: Marek Polacek <[email protected]> Date: Mon Feb 23 11:22:08 2026 -0500 c++: error about typename outside of templates In C++11, DR 382 allowed 'typename' to be used outside of templates, so the "not allowed outside of templates" error is no longer accurate. gcc/cp/ChangeLog: * parser.cc (cp_parser_base_specifier): Use the same error for a typename in a base-specifier outside of templates and inside. gcc/testsuite/ChangeLog: * g++.dg/parse/typename6.C: Adjust dg-error. * g++.dg/reflect/pr122634-2.C: Likewise. Reviewed-by: Jason Merrill <[email protected]> Diff: --- gcc/cp/parser.cc | 20 +++++--------------- gcc/testsuite/g++.dg/parse/typename6.C | 2 +- gcc/testsuite/g++.dg/reflect/pr122634-2.C | 2 +- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 9c0c3be06a4e..53fbb75b15a6 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -31930,21 +31930,11 @@ cp_parser_base_specifier (cp_parser* parser) template_p = class_scope_p && cp_parser_optional_template_keyword (parser); if (typename_token && cp_lexer_peek_token (parser->lexer) != splice_token) - { - /* Emit deferred diagnostics for invalid typename keyword if - cp_parser_nested_name_specifier_opt parsed splice-scope-specifier. */ - // TODO This error should be removed: - // struct A { struct B {}; }; - // typename A::B b; - // is valid. - if (!processing_template_decl) - error_at (typename_token->location, - "keyword %<typename%> not allowed outside of templates"); - else - error_at (typename_token->location, - "keyword %<typename%> not allowed in this context " - "(the base class is implicitly a type)"); - } + /* Emit deferred diagnostics for invalid typename keyword if + cp_parser_nested_name_specifier_opt parsed splice-scope-specifier. */ + error_at (typename_token->location, + "keyword %<typename%> not allowed in this context " + "(the base class is implicitly a type)"); if (!parser->scope && cp_lexer_next_token_is_decltype (parser->lexer)) diff --git a/gcc/testsuite/g++.dg/parse/typename6.C b/gcc/testsuite/g++.dg/parse/typename6.C index dc458bee5583..1b764c4b7157 100644 --- a/gcc/testsuite/g++.dg/parse/typename6.C +++ b/gcc/testsuite/g++.dg/parse/typename6.C @@ -13,5 +13,5 @@ struct X : X<B> x; struct C : - public typename A // { dg-error "not allowed outside of templates" } + public typename A // { dg-error "not allowed in this context" } { }; diff --git a/gcc/testsuite/g++.dg/reflect/pr122634-2.C b/gcc/testsuite/g++.dg/reflect/pr122634-2.C index 7db5b1930aaf..4fdfffece533 100644 --- a/gcc/testsuite/g++.dg/reflect/pr122634-2.C +++ b/gcc/testsuite/g++.dg/reflect/pr122634-2.C @@ -3,7 +3,7 @@ // { dg-additional-options "-freflection" } namespace N { struct A {}; } -struct B : typename [: ^^N :] :: A {}; // { dg-error "keyword 'typename' not allowed outside of templates" } +struct B : typename [: ^^N :] :: A {}; // { dg-error "keyword 'typename' not allowed in this context" } template <auto I> struct C : typename [: ^^N :] :: A {}; // { dg-error "keyword 'typename' not allowed in this context" } template <auto I>
