diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 147 | ||||
-rw-r--r-- | gcc/cp/call.cc | 38 | ||||
-rw-r--r-- | gcc/cp/class.cc | 1 | ||||
-rw-r--r-- | gcc/cp/constexpr.cc | 39 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/cvt.cc | 13 | ||||
-rw-r--r-- | gcc/cp/decl.cc | 16 | ||||
-rw-r--r-- | gcc/cp/lambda.cc | 8 | ||||
-rw-r--r-- | gcc/cp/module.cc | 84 | ||||
-rw-r--r-- | gcc/cp/name-lookup.cc | 51 | ||||
-rw-r--r-- | gcc/cp/parser.cc | 86 | ||||
-rw-r--r-- | gcc/cp/pt.cc | 73 | ||||
-rw-r--r-- | gcc/cp/semantics.cc | 1 | ||||
-rw-r--r-- | gcc/cp/typeck.cc | 10 |
14 files changed, 427 insertions, 142 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b7ea75b7..44b592b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,150 @@ +2025-04-05 Patrick Palka <ppalka@redhat.com> + + PR c++/118249 + * constexpr.cc (potential_constant_expression_1) + <case INDIRECT_REF>: Remove obsolete *this handling. + +2025-04-05 Jason Merrill <jason@redhat.com> + + PR c++/118629 + * name-lookup.cc (pushdecl_outermost_localscope): Look for an + sk_block. + +2025-04-04 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/119564 + * decl.cc (cp_tree_node_structure): Add TU_LOCAL_ENTITY; fix + formatting. + +2025-04-04 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/119608 + * module.cc (trees_out::decl_node): Maybe require by-value + walking not just when streaming. + +2025-04-04 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/119462 + * module.cc (trees_in::is_matching_decl): Propagate exception + spec and constexpr to DECL_MAYBE_DELETED; clear if appropriate. + +2025-04-04 Jason Merrill <jason@redhat.com> + + PR c++/99546 + PR c++/113925 + PR c++/106976 + PR c++/109961 + PR c++/117336 + * lambda.cc (build_lambda_object): Handle fake + requires-expr processing_template_decl. + * parser.cc (cp_parser_lambda_expression): Likewise. + +2025-04-04 Patrick Palka <ppalka@redhat.com> + + PR c++/117849 + * semantics.cc (finish_id_expression_1): Allow use of constraint + variable outside an unevaluated context. + +2025-04-03 Patrick Palka <ppalka@redhat.com> + + PR c++/119387 + * constexpr.cc (p2280_active_p): New. + (cxx_eval_constant_expression) <case VAR_DECL>: Use it to + restrict P2280 relaxations. + <case PARM_DECL>: Likewise. + +2025-04-03 Jason Merrill <jason@redhat.com> + + * module.cc (module_state::read_cluster) + (post_load_processing): Clear DECL_EXTERNAL if DECL_COMDAT. + +2025-04-03 Jason Merrill <jason@redhat.com> + + * call.cc (add_candidates): Re-lookup ne_fns if we move into + another namespace. + +2025-04-03 Andrew Pinski <quic_apinski@quicinc.com> + Jakub Jelinek <jakub@redhat.com> + + PR c++/119563 + * call.cc (build_list_conv): Fix a typo in loop gathering + summary information from subsubconvs. + +2025-04-02 Sandra Loosemore <sloosemore@baylibre.com> + + PR middle-end/118965 + * parser.cc (c_parser_omp_clause_init_modifiers): Adjust + error message. + (cp_parser_omp_clause_init): Remove code for recognizing clauses + without modifiers. Diagnose missing target/targetsync modifier. + (cp_finish_omp_declare_variant): Diagnose missing target/targetsync + modifier. + +2025-04-01 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/119551 + * module.cc (trees_out::write_var_def): Only ignore non-inline + variable initializers. + +2025-04-01 Nathaniel Shead <nathanieloshead@gmail.com> + + * parser.cc (cp_parser_diagnose_invalid_type_name): Replace + fmodules-ts with fmodules. + (cp_parser_template_declaration): Likewise. + +2025-04-01 Marek Polacek <polacek@redhat.com> + + PR c++/119383 + * call.cc (build_over_call): Use force_lvalue to ensure op= returns + an lvalue. + * cp-tree.h (force_lvalue): Declare. + * cvt.cc (force_lvalue): New. + * typeck.cc (cp_build_indirect_ref_1): Revert r15-8011. + +2025-03-31 Jason Merrill <jason@redhat.com> + + PR c++/119401 + * pt.cc (regenerate_decl_from_template): Don't regenerate if the + signature involves a lambda. + +2025-03-31 Jakub Jelinek <jakub@redhat.com> + + PR c++/119518 + * decl.cc (finish_function): Don't set TREE_NOTHROW for + functions with "noipa" attribute even when we can prove + they can't throw. + +2025-03-29 Jason Merrill <jason@redhat.com> + + * decl.cc (duplicate_decls): Don't clobber DECL_MODULE_IMPORT_P with + an injected friend. + * name-lookup.cc (check_module_override): Look at all reachable + decls in decl's originating module. + +2025-03-29 Jason Merrill <jason@redhat.com> + + PR c++/64500 + PR c++/116285 + * name-lookup.cc (push_to_top_level): Don't try to store_bindings + for namespace levels. + +2025-03-29 Jakub Jelinek <jakub@redhat.com> + + * name-lookup.cc (maybe_lazily_declare): Fix comment typo, + anout -> about. + +2025-03-29 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/118961 + * class.cc (copy_fndecl_with_name): Mark clones as non-abstract. + * cp-tree.h (setup_explicit_instantiation_definition_linkage): + Declare new function. + * module.cc (trees_in::read_var_def): Use it. + (module_state::read_cluster): Likewise. + * pt.cc (setup_explicit_instantiation_definition_linkage): New + function. + (mark_decl_instantiated): Use it. + 2025-03-27 Tobias Burnus <tburnus@baylibre.com> * cp-tree.h (cp_finish_omp_init_prefer_type): Add. diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index c1c8987..6caac89 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -917,7 +917,7 @@ build_list_conv (tree type, tree ctor, int flags, tsubst_flags_t complain) t->rank = cr_exact; for (j = 0; j < (unsigned) RAW_DATA_LENGTH (val); ++j) { - sub = subsubconvs[i]; + sub = subsubconvs[j]; if (sub->rank > t->rank) t->rank = sub->rank; if (sub->user_conv_p) @@ -6673,6 +6673,7 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, bool check_list_ctor = false; bool check_converting = false; unification_kind_t strict; + tree ne_context = NULL_TREE; tree ne_fns = NULL_TREE; if (!fns) @@ -6719,6 +6720,7 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, tree ne_name = ovl_op_identifier (false, NE_EXPR); if (DECL_CLASS_SCOPE_P (fn)) { + ne_context = DECL_CONTEXT (fn); ne_fns = lookup_fnfields (TREE_TYPE ((*args)[0]), ne_name, 1, tf_none); if (ne_fns == error_mark_node || ne_fns == NULL_TREE) @@ -6728,8 +6730,9 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, } else { - tree context = decl_namespace_context (fn); - ne_fns = lookup_qualified_name (context, ne_name, LOOK_want::NORMAL, + ne_context = decl_namespace_context (fn); + ne_fns = lookup_qualified_name (ne_context, ne_name, + LOOK_want::NORMAL, /*complain*/false); if (ne_fns == error_mark_node || !is_overloaded_fn (ne_fns)) @@ -6828,8 +6831,26 @@ add_candidates (tree fns, tree first_arg, const vec<tree, va_gc> *args, /* When considering reversed operator==, if there's a corresponding operator!= in the same scope, it's not a rewrite target. */ - if (ne_fns) + if (ne_context) { + if (TREE_CODE (ne_context) == NAMESPACE_DECL) + { + /* With argument-dependent lookup, fns can span multiple + namespaces; make sure we look in the fn's namespace for a + corresponding operator!=. */ + tree fn_ns = decl_namespace_context (fn); + if (fn_ns != ne_context) + { + ne_context = fn_ns; + tree ne_name = ovl_op_identifier (false, NE_EXPR); + ne_fns = lookup_qualified_name (ne_context, ne_name, + LOOK_want::NORMAL, + /*complain*/false); + if (ne_fns == error_mark_node + || !is_overloaded_fn (ne_fns)) + ne_fns = NULL_TREE; + } + } bool found = false; for (lkp_iterator ne (ne_fns); !found && ne; ++ne) if (0 && !ne.using_p () @@ -10828,10 +10849,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) if (is_really_empty_class (type, /*ignore_vptr*/true)) { /* Avoid copying empty classes, but ensure op= returns an lvalue even - if the object argument isn't one. This isn't needed in other cases - since MODIFY_EXPR is always considered an lvalue. */ - to = cp_build_addr_expr (to, tf_none); - to = cp_build_indirect_ref (input_location, to, RO_ARROW, complain); + if the object argument isn't one. */ + to = force_lvalue (to, complain); val = build2 (COMPOUND_EXPR, type, arg, to); suppress_warning (val, OPT_Wunused); } @@ -10852,6 +10871,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) tree array_type, alias_set; arg2 = TYPE_SIZE_UNIT (as_base); + /* Ensure op= returns an lvalue even if the object argument isn't + one. */ + to = force_lvalue (to, complain); to = cp_stabilize_reference (to); arg0 = cp_build_addr_expr (to, complain); diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index d5ae69b..2b694b9 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -5169,6 +5169,7 @@ copy_fndecl_with_name (tree fn, tree name, tree_code code, set_constraints (clone, copy_node (ci)); SET_DECL_ASSEMBLER_NAME (clone, NULL_TREE); + DECL_ABSTRACT_P (clone) = false; /* There's no pending inline data for this function. */ DECL_PENDING_INLINE_INFO (clone) = NULL; DECL_PENDING_INLINE_P (clone) = 0; diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 4820bcc..37ea65c 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -1294,6 +1294,22 @@ struct constexpr_ctx { mce_value manifestly_const_eval; }; +/* True if the constexpr relaxations afforded by P2280R4 for unknown + references and objects are in effect. */ + +static bool +p2280_active_p (const constexpr_ctx *ctx) +{ + if (ctx->manifestly_const_eval != mce_true) + /* Disable these relaxations during speculative constexpr folding, + as it can significantly increase compile time/memory use + (PR119387). */ + return false; + + /* P2280R4 was accepted as a DR against C++11. */ + return cxx_dialect >= cxx11; +} + /* Remove T from the global values map, checking for attempts to destroy a value that has already finished its lifetime. */ @@ -7792,7 +7808,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = TARGET_EXPR_INITIAL (r); if (DECL_P (r) /* P2280 allows references to unknown. */ - && !(VAR_P (t) && TYPE_REF_P (TREE_TYPE (t)))) + && !(p2280_active_p (ctx) && VAR_P (t) && TYPE_REF_P (TREE_TYPE (t)))) { if (!ctx->quiet) non_const_var_error (loc, r, /*fundef_p*/false); @@ -7844,9 +7860,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = build_constructor (TREE_TYPE (t), NULL); TREE_CONSTANT (r) = true; } - else if (TYPE_REF_P (TREE_TYPE (t))) + else if (p2280_active_p (ctx) && TYPE_REF_P (TREE_TYPE (t))) /* P2280 allows references to unknown... */; - else if (is_this_parameter (t)) + else if (p2280_active_p (ctx) && is_this_parameter (t)) /* ...as well as the this pointer. */; else { @@ -10263,22 +10279,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, return true; case INDIRECT_REF: - { - tree x = TREE_OPERAND (t, 0); - STRIP_NOPS (x); - if (is_this_parameter (x) && !is_capture_proxy (x)) - { - if (now || !var_in_maybe_constexpr_fn (x)) - { - if (flags & tf_error) - constexpr_error (loc, fundef_p, "use of %<this%> in a " - "constant expression"); - return false; - } - return true; - } - return RECUR (x, rval); - } + return RECUR (TREE_OPERAND (t, 0), rval); case STATEMENT_LIST: for (tree stmt : tsi_range (t)) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f0b4484..927f51b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7079,6 +7079,7 @@ extern tree convert_to_reference (tree, tree, int, int, tree, tsubst_flags_t); extern tree convert_from_reference (tree); extern tree force_rvalue (tree, tsubst_flags_t); +extern tree force_lvalue (tree, tsubst_flags_t); extern tree ocp_convert (tree, tree, int, int, tsubst_flags_t); extern tree cp_convert (tree, tree, tsubst_flags_t); @@ -7692,6 +7693,7 @@ extern tree fn_type_unification (tree, tree, tree, tree, unification_kind_t, int, struct conversion **, bool, bool); +extern void setup_explicit_instantiation_definition_linkage (tree); extern void mark_decl_instantiated (tree, int); extern int more_specialized_fn (tree, tree, int); extern tree type_targs_deducible_from (tree, tree); diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc index bd1f147..f663a6d 100644 --- a/gcc/cp/cvt.cc +++ b/gcc/cp/cvt.cc @@ -575,6 +575,19 @@ force_rvalue (tree expr, tsubst_flags_t complain) return expr; } +/* Force EXPR to be an lvalue, if it isn't already. */ + +tree +force_lvalue (tree expr, tsubst_flags_t complain) +{ + if (!lvalue_p (expr)) + { + expr = cp_build_addr_expr (expr, complain); + expr = cp_build_indirect_ref (input_location, expr, RO_ARROW, complain); + } + return expr; +} + /* If EXPR and ORIG are INTEGER_CSTs, return a version of EXPR that has TREE_OVERFLOW set only if it is set in ORIG. Otherwise, return EXPR diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index a785d5e..4e97093 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -2539,8 +2539,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } /* Propagate purviewness and importingness as with - set_instantiating_module. */ - if (modules_p () && DECL_LANG_SPECIFIC (new_result)) + set_instantiating_module, unless newdecl is a friend injection. */ + if (modules_p () && DECL_LANG_SPECIFIC (new_result) + && !(TREE_CODE (new_result) == FUNCTION_DECL + && DECL_UNIQUE_FRIEND_P (new_result))) { if (DECL_MODULE_PURVIEW_P (new_result)) DECL_MODULE_PURVIEW_P (old_result) = true; @@ -19452,7 +19454,8 @@ finish_function (bool inline_p) && !cp_function_chain->can_throw && !flag_non_call_exceptions && !decl_replaceable_p (fndecl, - opt_for_fn (fndecl, flag_semantic_interposition))) + opt_for_fn (fndecl, flag_semantic_interposition)) + && !lookup_attribute ("noipa", DECL_ATTRIBUTES (fndecl))) TREE_NOTHROW (fndecl) = 1; cleanup: @@ -19831,14 +19834,14 @@ cp_tree_node_structure (union lang_tree_node * t) { switch (TREE_CODE (&t->generic)) { - case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT; + case ARGUMENT_PACK_SELECT: return TS_CP_ARGUMENT_PACK_SELECT; case BASELINK: return TS_CP_BASELINK; - case CONSTRAINT_INFO: return TS_CP_CONSTRAINT_INFO; + case CONSTRAINT_INFO: return TS_CP_CONSTRAINT_INFO; case DEFERRED_NOEXCEPT: return TS_CP_DEFERRED_NOEXCEPT; case DEFERRED_PARSE: return TS_CP_DEFERRED_PARSE; case IDENTIFIER_NODE: return TS_CP_IDENTIFIER; case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR; - case BINDING_VECTOR: return TS_CP_BINDING_VECTOR; + case BINDING_VECTOR: return TS_CP_BINDING_VECTOR; case OVERLOAD: return TS_CP_OVERLOAD; case PTRMEM_CST: return TS_CP_PTRMEM; case STATIC_ASSERT: return TS_CP_STATIC_ASSERT; @@ -19846,6 +19849,7 @@ cp_tree_node_structure (union lang_tree_node * t) case TEMPLATE_INFO: return TS_CP_TEMPLATE_INFO; case TEMPLATE_PARM_INDEX: return TS_CP_TPI; case TRAIT_EXPR: return TS_CP_TRAIT_EXPR; + case TU_LOCAL_ENTITY: return TS_CP_TU_LOCAL_ENTITY; case USERDEF_LITERAL: return TS_CP_USERDEF_LITERAL; default: return TS_CP_GENERIC; } diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc index ed70bb0..f0a54b6 100644 --- a/gcc/cp/lambda.cc +++ b/gcc/cp/lambda.cc @@ -59,7 +59,13 @@ build_lambda_object (tree lambda_expr) vec<constructor_elt, va_gc> *elts = NULL; tree node, expr, type; - if (processing_template_decl || lambda_expr == error_mark_node) + if (processing_template_decl && !in_template_context + && current_binding_level->requires_expression) + /* As in cp_parser_lambda_expression, don't get confused by + cp_parser_requires_expression setting processing_template_decl. In that + case we want to return the result of finish_compound_literal, to avoid + tsubst_lambda_expr. */; + else if (processing_template_decl || lambda_expr == error_mark_node) return lambda_expr; /* Make sure any error messages refer to the lambda-introducer. */ diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 214fb91..37fab5b 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -9004,25 +9004,28 @@ trees_out::decl_node (tree decl, walk_kind ref) if (streaming_p ()) i (tt_parm); tree_node (DECL_CONTEXT (decl)); - if (streaming_p ()) - { - /* That must have put this in the map. */ - walk_kind ref = ref_node (decl); - if (ref != WK_none) - // FIXME:OPTIMIZATION We can wander into bits of the - // template this was instantiated from. For instance - // deferred noexcept and default parms. Currently we'll - // end up cloning those bits of tree. It would be nice - // to reference those specific nodes. I think putting - // those things in the map when we reference their - // template by name. See the note in add_indirects. - return true; - dump (dumper::TREE) - && dump ("Wrote %s reference %N", - TREE_CODE (decl) == PARM_DECL ? "parameter" : "result", - decl); - } + /* That must have put this in the map. */ + walk_kind ref = ref_node (decl); + if (ref != WK_none) + // FIXME:OPTIMIZATION We can wander into bits of the + // template this was instantiated from, for instance + // deferred noexcept and default parms, or references + // to parms from earlier forward-decls (PR c++/119608). + // + // Currently we'll end up cloning those bits of tree. + // It would be nice to reference those specific nodes. + // I think putting those things in the map when we + // reference their template by name. + // + // See the note in add_indirects. + return true; + + if (streaming_p ()) + dump (dumper::TREE) + && dump ("Wrote %s reference %N", + TREE_CODE (decl) == PARM_DECL ? "parameter" : "result", + decl); } return false; @@ -12122,7 +12125,7 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef) instantiate it in the middle of loading. */ tree e_spec = TYPE_RAISES_EXCEPTIONS (e_type); tree d_spec = TYPE_RAISES_EXCEPTIONS (d_type); - if (DEFERRED_NOEXCEPT_SPEC_P (e_spec)) + if (DECL_MAYBE_DELETED (e_inner) || DEFERRED_NOEXCEPT_SPEC_P (e_spec)) { if (!DEFERRED_NOEXCEPT_SPEC_P (d_spec) || (UNEVALUATED_NOEXCEPT_SPEC_P (e_spec) @@ -12161,6 +12164,20 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef) else if (type_uses_auto (d_ret) && !same_type_p (TREE_TYPE (d_type), TREE_TYPE (e_type))) goto mismatch; + + /* Similarly if EXISTING has undeduced constexpr, but DECL's + is already deduced. */ + if (DECL_MAYBE_DELETED (e_inner) && !DECL_MAYBE_DELETED (d_inner) + && DECL_DECLARED_CONSTEXPR_P (d_inner)) + DECL_DECLARED_CONSTEXPR_P (e_inner) = true; + else if (DECL_DECLARED_CONSTEXPR_P (e_inner) + != DECL_DECLARED_CONSTEXPR_P (d_inner)) + goto mismatch; + + /* Don't synthesize a defaulted function if we're importing one + we've already determined. */ + if (!DECL_MAYBE_DELETED (d_inner)) + DECL_MAYBE_DELETED (e_inner) = false; } else if (is_typedef) { @@ -12679,9 +12696,10 @@ trees_in::read_function_def (tree decl, tree maybe_template) void trees_out::write_var_def (tree decl) { - /* The initializer of a variable or variable template is ignored for - determining exposures. */ - auto ovr = make_temp_override (dep_hash->ignore_tu_local, VAR_P (decl)); + /* The initializer of a non-inline variable or variable template is + ignored for determining exposures. */ + auto ovr = make_temp_override (dep_hash->ignore_tu_local, + VAR_P (decl) && !DECL_INLINE_VAR_P (decl)); tree init = DECL_INITIAL (decl); tree_node (init); @@ -12737,6 +12755,9 @@ trees_in::read_var_def (tree decl, tree maybe_template) if (maybe_dup && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (maybe_dup)) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true; tentative_decl_linkage (decl); + if (DECL_EXPLICIT_INSTANTIATION (decl) + && !DECL_EXTERNAL (decl)) + setup_explicit_instantiation_definition_linkage (decl); if (DECL_IMPLICIT_INSTANTIATION (decl) || (DECL_EXPLICIT_INSTANTIATION (decl) && !DECL_EXTERNAL (decl)) @@ -16657,6 +16678,12 @@ module_state::read_cluster (unsigned snum) cfun->language->returns_abnormally = pdata.returns_abnormally; cfun->language->infinite_loop = pdata.infinite_loop; + /* Make sure we emit explicit instantiations. + FIXME do we want to do this in expand_or_defer_fn instead? */ + if (DECL_EXPLICIT_INSTANTIATION (decl) + && !DECL_EXTERNAL (decl)) + setup_explicit_instantiation_definition_linkage (decl); + if (abstract) ; else if (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl)) @@ -16669,6 +16696,15 @@ module_state::read_cluster (unsigned snum) #endif cfun->returns_struct = aggr; expand_or_defer_fn (decl); + + /* If we first see this function after at_eof, it doesn't get + note_vague_linkage_fn from tentative_decl_linkage, so the loop in + c_parse_final_cleanups won't consider it. But with DECL_COMDAT we + can just clear DECL_EXTERNAL and let cgraph decide. + FIXME handle this outside module.cc after GCC 15. */ + if (at_eof && DECL_COMDAT (decl) && DECL_EXTERNAL (decl) + && DECL_NOT_REALLY_EXTERN (decl)) + DECL_EXTERNAL (decl) = false; } } @@ -19149,6 +19185,10 @@ post_load_processing () gcc_checking_assert (DECL_MAYBE_IN_CHARGE_CDTOR_P (decl)); expand_or_defer_fn (decl); + /* As in module_state::read_cluster. */ + if (at_eof && DECL_COMDAT (decl) && DECL_EXTERNAL (decl) + && DECL_NOT_REALLY_EXTERN (decl)) + DECL_EXTERNAL (decl) = false; } cfun = old_cfun; diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 7f1ee86..1cd982e 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -2012,8 +2012,8 @@ get_class_binding_direct (tree klass, tree name, bool want_type) static void maybe_lazily_declare (tree klass, tree name) { - /* See big comment anout module_state::write_pendings regarding adding a check - bit. */ + /* See big comment about module_state::write_pendings regarding adding + a check bit. */ if (modules_p ()) lazy_load_pendings (TYPE_NAME (klass)); @@ -3777,6 +3777,10 @@ check_module_override (tree decl, tree mvec, bool hiding, any reachable declaration, so we should check for overriding here too. */ bool any_reachable = deduction_guide_p (decl); + /* DECL might have an originating module if it's an instantiation of a + friend; we want to look at all reachable decls in that module. */ + unsigned decl_mod = get_originating_module (decl); + if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED) { cluster++; @@ -3789,18 +3793,15 @@ check_module_override (tree decl, tree mvec, bool hiding, /* Are we importing this module? */ if (cluster->indices[jx].span != 1) continue; - if (!cluster->indices[jx].base) + unsigned cluster_mod = cluster->indices[jx].base; + if (!cluster_mod) continue; - if (!any_reachable - && !bitmap_bit_p (imports, cluster->indices[jx].base)) + bool c_any_reachable = (any_reachable || cluster_mod == decl_mod); + if (!c_any_reachable && !bitmap_bit_p (imports, cluster_mod)) continue; /* Is it loaded? */ if (cluster->slots[jx].is_lazy ()) - { - gcc_assert (cluster->indices[jx].span == 1); - lazy_load_binding (cluster->indices[jx].base, - scope, name, &cluster->slots[jx]); - } + lazy_load_binding (cluster_mod, scope, name, &cluster->slots[jx]); tree bind = cluster->slots[jx]; if (!bind) /* Errors could cause there to be nothing. */ @@ -3812,7 +3813,7 @@ check_module_override (tree decl, tree mvec, bool hiding, /* If there was a matching STAT_TYPE here then xref_tag should have found it, but we need to check anyway because a conflicting using-declaration may exist. */ - if (any_reachable) + if (c_any_reachable) { type = STAT_TYPE (bind); bind = STAT_DECL (bind); @@ -5203,9 +5204,11 @@ pushdecl_outermost_localscope (tree x) cp_binding_level *b = NULL; auto_cond_timevar tv (TV_NAME_LOOKUP); - /* Find the scope just inside the function parms. */ - for (cp_binding_level *n = current_binding_level; - n->kind != sk_function_parms; n = b->level_chain) + /* Find the block scope just inside the function parms. */ + cp_binding_level *n = current_binding_level; + while (n && n->kind != sk_block) + n = n->level_chain; + for (; n && n->kind != sk_function_parms; n = b->level_chain) b = n; return b ? do_pushdecl_with_scope (x, b) : error_mark_node; @@ -8675,6 +8678,9 @@ store_class_bindings (vec<cp_class_binding, va_gc> *names, static GTY((deletable)) struct saved_scope *free_saved_scope; +/* Temporarily make the current scope the global namespace, saving away + the current scope for pop_from_top_level. */ + void push_to_top_level (void) { @@ -8716,18 +8722,19 @@ push_to_top_level (void) store_class_bindings (previous_class_level->class_shadowed, &s->old_bindings); - /* Have to include the global scope, because class-scope decls - aren't listed anywhere useful. */ + /* Save and clear any IDENTIFIER_BINDING from local scopes. */ for (; b; b = b->level_chain) { tree t; - /* Template IDs are inserted into the global level. If they were - inserted into namespace level, finish_file wouldn't find them - when doing pending instantiations. Therefore, don't stop at - namespace level, but continue until :: . */ - if (global_scope_p (b)) - break; + /* We don't need to consider namespace scopes, they don't affect + IDENTIFIER_BINDING. */ + if (b->kind == sk_namespace) + { + /* Jump straight to '::'. */ + b = NAMESPACE_LEVEL (global_namespace); + break; + } store_bindings (b->names, &s->old_bindings); /* We also need to check class_shadowed to save class-level type diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 88e722d..812a7c5 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -3901,10 +3901,10 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, inform (location, "%qE is not recognized as a module control-line", id); else if (cxx_dialect < cxx20) - inform (location, "C++20 %qE only available with %<-fmodules-ts%>", + inform (location, "C++20 %qE only available with %<-fmodules%>", id); else - inform (location, "C++20 %qE only available with %<-fmodules-ts%>" + inform (location, "C++20 %qE only available with %<-fmodules%>" ", which is not yet enabled with %<-std=c++20%>", id); } else if (cxx_dialect < cxx11 @@ -11736,21 +11736,34 @@ cp_parser_lambda_expression (cp_parser* parser) if (cp_parser_error_occurred (parser)) return error_mark_node; - type = begin_lambda_type (lambda_expr); - if (type == error_mark_node) - return error_mark_node; + { + /* OK, this is a bit tricksy. cp_parser_requires_expression sets + processing_template_decl to make checking more normal, but that confuses + lambda parsing terribly. In non-template context, we want to parse the + lambda once and not tsubst_lambda_expr. So in that case, clear + processing_template_decl now, and restore it before the call to + build_lambda_object; that way we end up with what looks like a templatey + functional cast to the closure type, which is suitable for the + requires-expression tsubst_expr. This is PR99546 and friends. */ + processing_template_decl_sentinel ptds (/*reset*/false); + if (processing_template_decl && !in_template_context + && current_binding_level->requires_expression) + processing_template_decl = 0; + + type = begin_lambda_type (lambda_expr); + if (type == error_mark_node) + return error_mark_node; - record_lambda_scope (lambda_expr); - record_lambda_scope_discriminator (lambda_expr); + record_lambda_scope (lambda_expr); + record_lambda_scope_discriminator (lambda_expr); - /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */ - determine_visibility (TYPE_NAME (type)); + /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */ + determine_visibility (TYPE_NAME (type)); - /* Now that we've started the type, add the capture fields for any - explicit captures. */ - register_capture_members (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr)); + /* Now that we've started the type, add the capture fields for any + explicit captures. */ + register_capture_members (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr)); - { /* Inside the class, surrounding template-parameter-lists do not apply. */ unsigned int saved_num_template_parameter_lists = parser->num_template_parameter_lists; @@ -18845,7 +18858,7 @@ cp_parser_template_declaration (cp_parser* parser, bool member_p) else if (cxx_dialect < cxx20) warning (0, "keyword %<export%> is deprecated, and is ignored"); else - warning (0, "keyword %<export%> is enabled with %<-fmodules-ts%>"); + warning (0, "keyword %<export%> is enabled with %<-fmodules%>"); } cp_parser_template_declaration_after_export (parser, member_p); @@ -43121,8 +43134,8 @@ cp_parser_omp_clause_init_modifiers (cp_parser *parser, bool *target, while (true); fail: - cp_parser_error (parser, "%<init%> clause with modifier other than " - "%<prefer_type%>, %<target%> or %<targetsync%>"); + cp_parser_error (parser, + "expected %<prefer_type%>, %<target%>, or %<targetsync%>"); return false; } @@ -43140,39 +43153,14 @@ cp_parser_omp_clause_init (cp_parser *parser, tree list) if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return list; - unsigned raw_pos = 1; - while (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type == CPP_NAME) - { - raw_pos++; - if (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type - == CPP_OPEN_PAREN) - { - unsigned n = cp_parser_skip_balanced_tokens (parser, raw_pos); - if (n == raw_pos) - { - raw_pos = 0; - break; - } - raw_pos = n; - } - if (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type == CPP_COLON) - break; - if (cp_lexer_peek_nth_token (parser->lexer, raw_pos)->type != CPP_COMMA) - { - raw_pos = 0; - break; - } - raw_pos++; - } - bool target = false; bool targetsync = false; tree prefer_type_tree = NULL_TREE; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; - if (raw_pos > 1 - && (!cp_parser_omp_clause_init_modifiers (parser, &target, &targetsync, - &prefer_type_tree) - || !cp_parser_require (parser, CPP_COLON, RT_COLON))) + if (!cp_parser_omp_clause_init_modifiers (parser, &target, &targetsync, + &prefer_type_tree) + || !cp_parser_require (parser, CPP_COLON, RT_COLON)) { if (prefer_type_tree == error_mark_node) return error_mark_node; @@ -43182,6 +43170,10 @@ cp_parser_omp_clause_init (cp_parser *parser, tree list) return list; } + if (!target && !targetsync) + error_at (loc, + "missing required %<target%> and/or %<targetsync%> modifier"); + tree nl = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_INIT, list, NULL, false); for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) @@ -50581,6 +50573,10 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, &targetsync, &prefer_type_tree)) goto fail; + if (!target && !targetsync) + error_at (loc, + "missing required %<target%> and/or " + "%<targetsync%> modifier"); tree t = build_tree_list (target ? boolean_true_node : boolean_false_node, targetsync ? boolean_true_node diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 1f5ab4e..95b89f12 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -17741,13 +17741,37 @@ maybe_dependent_member_ref (tree t, tree args, tsubst_flags_t complain, if (TYPE_P (t)) { + bool stripped = false; if (typedef_variant_p (t)) - t = strip_typedefs (t); - tree decl = TYPE_NAME (t); + { + /* Since this transformation may undesirably turn a deduced context + into a non-deduced one, we'd rather strip typedefs than perform + the transformation. */ + tree u = strip_typedefs (t); + if (u != t) + { + stripped = true; + t = u; + } + } + decl = TYPE_NAME (t); if (decl) decl = maybe_dependent_member_ref (decl, args, complain, in_decl); if (!decl) - return NULL_TREE; + { + if (stripped) + /* The original type was an alias from the current instantiation + which we stripped to something outside it. At this point we + need to commit to using the stripped type rather than deferring + to the caller (which would use the original type), to ensure + eligible bits of the stripped type get transformed. */ + return tsubst (t, args, complain, in_decl); + else + /* The original type wasn't a typedef, and we decided it doesn't + need rewriting, so just let the caller (tsubst) substitute it + normally. */ + return NULL_TREE; + } return cp_build_qualified_type (TREE_TYPE (decl), cp_type_quals (t), complain); } @@ -17765,7 +17789,8 @@ maybe_dependent_member_ref (tree t, tree args, tsubst_flags_t complain, if (TREE_CODE (t) == TYPE_DECL) { - if (TREE_CODE (TREE_TYPE (t)) == TYPENAME_TYPE + if (!is_typedef_decl (t) + && TREE_CODE (TREE_TYPE (t)) == TYPENAME_TYPE && TYPE_NAME (TREE_TYPE (t)) == t) /* The TYPE_DECL for a typename has DECL_CONTEXT of the typename scope, but it doesn't need to be rewritten again. */ @@ -25968,6 +25993,23 @@ mark_definable (tree decl) DECL_NOT_REALLY_EXTERN (clone) = 1; } +/* DECL is an explicit instantiation definition, ensure that it will + be written out here and that it won't clash with other instantiations + in other translation units. */ + +void +setup_explicit_instantiation_definition_linkage (tree decl) +{ + mark_definable (decl); + mark_needed (decl); + /* Always make artificials weak. */ + if (DECL_ARTIFICIAL (decl) && flag_weak) + comdat_linkage (decl); + /* We also want to put explicit instantiations in linkonce sections. */ + else if (TREE_PUBLIC (decl)) + maybe_make_one_only (decl); +} + /* Called if RESULT is explicitly instantiated, or is a member of an explicitly instantiated class. */ @@ -26005,16 +26047,8 @@ mark_decl_instantiated (tree result, int extern_p) } else { - mark_definable (result); - mark_needed (result); set_instantiating_module (result); - /* Always make artificials weak. */ - if (DECL_ARTIFICIAL (result) && flag_weak) - comdat_linkage (result); - /* For WIN32 we also want to put explicit instantiations in - linkonce sections. */ - else if (TREE_PUBLIC (result)) - maybe_make_one_only (result); + setup_explicit_instantiation_definition_linkage (result); if (TREE_CODE (result) == FUNCTION_DECL && DECL_TEMPLATE_INSTANTIATED (result)) /* If the function has already been instantiated, clear DECL_EXTERNAL, @@ -27229,6 +27263,19 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args) if (DECL_UNIQUE_FRIEND_P (decl)) goto done; + /* A template with a lambda in the signature also changes type if + regenerated (PR119401). */ + walk_tree_fn find_lambda + = [](tree *tp, int *, void *) + { + if (TREE_CODE (*tp) == LAMBDA_EXPR) + return *tp; + return NULL_TREE; + }; + if (cp_walk_tree_without_duplicates + (&TREE_TYPE (tmpl), find_lambda, nullptr)) + goto done; + /* Use the source location of the definition. */ DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (tmpl); diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 7d8beb8..a10ef34 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -4755,6 +4755,7 @@ finish_id_expression_1 (tree id_expression, body, except inside an unevaluated context (i.e. decltype). */ if (TREE_CODE (decl) == PARM_DECL && DECL_CONTEXT (decl) == NULL_TREE + && !CONSTRAINT_VAR_P (decl) && !cp_unevaluated_operand && !processing_contract_condition && !processing_omp_trait_property_expr) diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index c8e4441..88f8f34 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -3870,13 +3870,11 @@ cp_build_indirect_ref_1 (location_t loc, tree ptr, ref_operator errorstring, return error_mark_node; } else if (do_fold && TREE_CODE (pointer) == ADDR_EXPR - && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))) - /* Don't let this change the value category. '*&TARGET_EXPR' - is an lvalue, but folding it into 'TARGET_EXPR' would turn - it into a prvalue of class type. */ - && lvalue_p (TREE_OPERAND (pointer, 0))) + && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0)))) /* The POINTER was something like `&x'. We simplify `*&x' to - `x'. */ + `x'. This can change the value category: '*&TARGET_EXPR' + is an lvalue and folding it into 'TARGET_EXPR' turns it into + a prvalue of class type. */ return TREE_OPERAND (pointer, 0); else { |