https://gcc.gnu.org/g:49ddf362f0a7c1fdeb62f13a852a2fdec9d6fe6d
commit r16-4368-g49ddf362f0a7c1fdeb62f13a852a2fdec9d6fe6d Author: Patrick Palka <[email protected]> Date: Fri Oct 10 10:25:25 2025 -0400 c++: base-specifier name lookup is type-only [PR122192] The r13-6098 change to make TYPENAME_TYPE no longer always ignore non-type bindings needs another exception: base-specifiers that are represented as TYPENAME_TYPE, for which lookup must be type-only (by [class.derived.general]/2). This patch fixes this by giving such TYPENAME_TYPEs a tag type of class_type rather than typename_type so that we treat them like elaborated-type-specifiers (another type-only lookup situation). PR c++/122192 gcc/cp/ChangeLog: * decl.cc (make_typename_type): Document base-specifier as another type-only lookup case. * parser.cc (cp_parser_class_name): Propagate tag_type to make_typename_type instead of hardcoding typename_type. (cp_parser_base_specifier): Pass class_type instead of typename_type as tag_type to cp_parser_class_name. gcc/testsuite/ChangeLog: * g++.dg/template/dependent-base6.C: New test. Reviewed-by: Jason Merrill <[email protected]> Diff: --- gcc/cp/decl.cc | 4 +++- gcc/cp/parser.cc | 5 ++--- gcc/testsuite/g++.dg/template/dependent-base6.C | 12 ++++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 31f3c4b77928..f198b7e671da 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -5036,7 +5036,9 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, - the tag corresponds to a class-key or 'enum' so [basic.lookup.elab] applies, or - the tag corresponds to scope_type or tf_qualifying_scope is - set so [basic.lookup.qual]/1 applies. + set so [basic.lookup.qual]/1 applies, or + - we're inside a base-specifier so [class.derived.general]/2 applies; + the tag will already be class_type in that case. TODO: If we'd set/track the scope_type tag thoroughly on all TYPENAME_TYPEs that are followed by :: then we wouldn't need the tf_qualifying_scope flag. */ diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index b4000527bf30..1ed2f3767e1c 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -28154,8 +28154,7 @@ cp_parser_class_name (cp_parser *parser, /* If this is a typename, create a TYPENAME_TYPE. */ if (typename_p && decl != error_mark_node) { - decl = make_typename_type (scope, decl, typename_type, - /*complain=*/tf_error); + decl = make_typename_type (scope, decl, tag_type, /*complain=*/tf_error); if (decl != error_mark_node) decl = TYPE_NAME (decl); } @@ -30556,7 +30555,7 @@ cp_parser_base_specifier (cp_parser* parser) type = cp_parser_class_name (parser, class_scope_p, template_p, - typename_type, + class_type, /*check_dependency_p=*/true, /*class_head_p=*/false, /*is_declaration=*/true); diff --git a/gcc/testsuite/g++.dg/template/dependent-base6.C b/gcc/testsuite/g++.dg/template/dependent-base6.C new file mode 100644 index 000000000000..b4bc5c279a58 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/dependent-base6.C @@ -0,0 +1,12 @@ +// PR c++/122192 +// Verify name lookup within a base-specifier is type-only. + +struct A { + int B; + struct B { }; +}; + +struct S1 : A::B { }; // OK + +template<class T> struct S2 : T::B { }; // OK, used to fail +template struct S2<A>;
