https://gcc.gnu.org/g:5200296f3eea587963634d73ac9a220a94511bcf
commit r17-4958-g5200296f3eea587963634d73ac9a220a94511bcf Author: Jason Merrill <[email protected]> Date: Wed Oct 7 10:03:47 2026 -0400 c++: tweaks preparing for P1811 A few adjustments that I needed for the P1811 work that also seem independently correct. In pushtag, we want to set TREE_PUBLIC sooner so that check_module_override considers mergeable decls; this also results in correct -Wbuiltin-declaration-mismatch about reusing names of built-ins. It was odd that there were a few if (type) bits after 'done:' in cp_parser_class_head, when all the 'goto done' first set type to NULL_TREE. That is no longer the case, and they're wrong for P1811, so I moved those bits before the label. And in duplicate_decls, for P1811 I will want to skip ahead to freeing newdecl in more cases. One existing early return worked with this change, but a template case did not yet due to newdecl already being in specialization tables. gcc/cp/ChangeLog: * name-lookup.cc (pushtag): Set TREE_PUBLIC sooner. * parser.cc (cp_parser_class_head): Set location and final before 'done' label. * decl.cc (duplicate_decls): Free duplicate namespace alias. gcc/testsuite/ChangeLog: * g++.dg/lookup/builtin4.C: Expect warning. * g++.dg/lookup/hidden-class10.C: Likewise. Diff: --- gcc/cp/decl.cc | 12 ++++++++---- gcc/cp/name-lookup.cc | 5 +++++ gcc/cp/parser.cc | 9 +++++---- gcc/testsuite/g++.dg/lookup/builtin4.C | 2 +- gcc/testsuite/g++.dg/lookup/hidden-class10.C | 2 +- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 24c5f0337b9c..a14e9a4cb719 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -2344,7 +2344,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) if (DECL_NAMESPACE_ALIAS (newdecl) && (DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))) - return olddecl; + goto return_old; /* Leave it to update_binding to merge or report error. */ return NULL_TREE; @@ -2595,9 +2595,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) set OLDDECL's attributes to those of NEWDECL (for template explicit specializations that specify their own attributes independent of those specified for the primary template). */ - const bool merge_attr = (TREE_CODE (newdecl) != FUNCTION_DECL - || !DECL_TEMPLATE_SPECIALIZATION (newdecl) - || DECL_TEMPLATE_SPECIALIZATION (olddecl)); + bool merge_attr; + merge_attr = (TREE_CODE (newdecl) != FUNCTION_DECL + || !DECL_TEMPLATE_SPECIALIZATION (newdecl) + || DECL_TEMPLATE_SPECIALIZATION (olddecl)); if (TREE_CODE (newdecl) == FUNCTION_DECL) { @@ -2816,6 +2817,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } } + /* FIXME we can't goto return_old here without removing newdecl from more + hash tables. */ return olddecl; } @@ -3580,6 +3583,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } } + return_old: /* Remove the associated constraints for newdecl, if any, before reclaiming memory. */ if (flag_concepts) diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 183ea403ef8c..56d21bf50d61 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -8816,6 +8816,11 @@ pushtag (tree name, tree type, TAG_how how) DECL_CONTEXT (tdef) = FROB_CONTEXT (context); set_originating_module (tdef); + /* Set TREE_PUBLIC now for built-in warnings and module merging. */ + if (TREE_CODE (context) == NAMESPACE_DECL + && TREE_PUBLIC (context)) + TREE_PUBLIC (tdef) = 1; + decl = maybe_process_template_type_declaration (type, how == TAG_how::HIDDEN_FRIEND, b); if (decl == error_mark_node) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index b98792a5ad58..9c54b2f22e2d 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -30925,6 +30925,11 @@ cp_parser_class_head (cp_parser* parser, if (type) popclass (); + if (type) + DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location; + if (type && (virt_specifiers & VIRT_SPEC_FINAL)) + CLASSTYPE_FINAL (type) = 1; + done: /* Leave the scope given by the nested-name-specifier. We will enter the class scope itself while processing the members. */ @@ -30937,10 +30942,6 @@ cp_parser_class_head (cp_parser* parser, --parser->num_template_parameter_lists; } - if (type) - DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location; - if (type && (virt_specifiers & VIRT_SPEC_FINAL)) - CLASSTYPE_FINAL (type) = 1; out: parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; return type; diff --git a/gcc/testsuite/g++.dg/lookup/builtin4.C b/gcc/testsuite/g++.dg/lookup/builtin4.C index b1785dcc7fbe..e71131b5a99d 100644 --- a/gcc/testsuite/g++.dg/lookup/builtin4.C +++ b/gcc/testsuite/g++.dg/lookup/builtin4.C @@ -10,6 +10,6 @@ namespace std union abort; } -union abort; +union abort; // { dg-warning "built-in" } using std::abort; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/lookup/hidden-class10.C b/gcc/testsuite/g++.dg/lookup/hidden-class10.C index c9b5ca9f663f..986241558a69 100644 --- a/gcc/testsuite/g++.dg/lookup/hidden-class10.C +++ b/gcc/testsuite/g++.dg/lookup/hidden-class10.C @@ -6,6 +6,6 @@ // function name. class A { - friend class abort; + friend class abort; // { dg-warning "built-in" } abort *b; // { dg-error "type|expected" } };
