diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 60 | ||||
-rw-r--r-- | gcc/cp/call.cc | 27 | ||||
-rw-r--r-- | gcc/cp/constexpr.cc | 22 | ||||
-rw-r--r-- | gcc/cp/decl.cc | 7 | ||||
-rw-r--r-- | gcc/cp/lambda.cc | 8 | ||||
-rw-r--r-- | gcc/cp/module.cc | 68 | ||||
-rw-r--r-- | gcc/cp/name-lookup.cc | 8 | ||||
-rw-r--r-- | gcc/cp/parser.cc | 35 | ||||
-rw-r--r-- | gcc/cp/semantics.cc | 1 |
9 files changed, 193 insertions, 43 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b605560..91ea35d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,63 @@ +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 diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index d853362..6caac89 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -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 () diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 4820bcc..9a57f48 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 { diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 2ed94fd..4e97093 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -19834,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; @@ -19849,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 ce22b2e..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) { @@ -16679,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; } } @@ -19159,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 7fadbcc..1cd982e 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -5204,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; diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 53e6237..812a7c5 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -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; 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) |