diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 114 | ||||
-rw-r--r-- | gcc/cp/call.cc | 9 | ||||
-rw-r--r-- | gcc/cp/class.cc | 1 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/cvt.cc | 13 | ||||
-rw-r--r-- | gcc/cp/decl.cc | 12 | ||||
-rw-r--r-- | gcc/cp/decl2.cc | 4 | ||||
-rw-r--r-- | gcc/cp/error.cc | 3 | ||||
-rw-r--r-- | gcc/cp/mangle.cc | 8 | ||||
-rw-r--r-- | gcc/cp/module.cc | 152 | ||||
-rw-r--r-- | gcc/cp/name-lookup.cc | 53 | ||||
-rw-r--r-- | gcc/cp/parser.cc | 9 | ||||
-rw-r--r-- | gcc/cp/pt.cc | 54 | ||||
-rw-r--r-- | gcc/cp/rtti.cc | 18 | ||||
-rw-r--r-- | gcc/cp/semantics.cc | 23 | ||||
-rw-r--r-- | gcc/cp/typeck.cc | 10 | ||||
-rw-r--r-- | gcc/cp/typeck2.cc | 2 |
17 files changed, 395 insertions, 94 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f15752f..fe8aa4b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,117 @@ +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. + * decl.cc (omp_declare_variant_finalize_one): Call it. + * pt.cc (tsubst_attribute): Minor rebustification for OpenMP + append_args handling. + * semantics.cc (cp_omp_init_prefer_type_update): Rename to ... + (cp_finish_omp_init_prefer_type): ... this; remove static attribute + and return modified tree. Move clause handling to ... + (finish_omp_clauses): ... the caller. + +2025-03-27 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/118920 + * cp-tree.h (equal_abi_tags): Declare. + * mangle.cc (equal_abi_tags): Make external, fix comparison. + (tree_string_cmp): Make internal. + * module.cc (trees_in::check_abi_tags): New function. + (trees_in::decl_value): Use it. + (trees_in::is_matching_decl): Likewise. + +2025-03-27 Nathaniel Shead <nathanieloshead@gmail.com> + Jason Merrill <jason@redhat.com> + + PR c++/118920 + * name-lookup.cc (lookup_imported_hidden_friend): Check for + module entity rather than just module import. + * module.cc (get_originating_module): Rename for_mangle parm to + global_m1. + * error.cc (dump_module_suffix): Don't decorate global module decls. + +2025-03-26 Thomas Schwinge <tschwinge@baylibre.com> + Jason Merrill <jason@redhat.com> + + * rtti.cc (throw_bad_typeid): Adjust implicit '__cxa_bad_typeid' + prototype to reality. Adjust all users. + +2025-03-25 Simon Martin <simon@nasilyan.com> + + PR c++/114525 + * typeck2.cc (build_m_component_ref): Call cp_build_addr_expr + instead of build_address. + +2025-03-25 yxj-github-437 <2457369732@qq.com> + + * parser.cc (cp_parser_lambda_expression): Use cp_evaluated. + +2025-03-24 Jason Merrill <jason@redhat.com> + + * semantics.cc (finish_type_pack_element): Pass mce_true to + maybe_constant_value. + +2025-03-23 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/119154 + * decl2.cc (vague_linkage_p): Revert gnu_linkage handling. + * module.cc (importer_interface): New enumeration. + (get_importer_interface): New function. + (trees_out::core_bools): Use it to determine interface. + (trees_in::is_matching_decl): Propagate gnu_inline handling onto + existing forward declarations. + (trees_in::read_var_def): Also note explicit instantiation + definitions of variable templates to be emitted. + +2025-03-22 Patrick Palka <ppalka@redhat.com> + + PR c++/119379 + * pt.cc (tsubst_decl) <case TYPE_DECL>: Preserve structural-ness + of a partially instantiated typedef. + 2025-03-21 Paul-Antoine Arras <parras@baylibre.com> Tobias Burnus <tburnus@baylibre.com> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index c1c8987..b1469cb 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -10828,10 +10828,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 +10850,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/cp-tree.h b/gcc/cp/cp-tree.h index 07500fa..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); @@ -8055,6 +8057,7 @@ extern tree omp_reduction_id (enum tree_code, tree, tree); extern tree cp_remove_omp_priv_cleanup_stmt (tree *, int *, void *); extern bool cp_check_omp_declare_reduction (tree); extern void finish_omp_declare_simd_methods (tree); +extern tree cp_finish_omp_init_prefer_type (tree); extern tree finish_omp_clauses (tree, enum c_omp_region_type); extern tree push_omp_privatization_clauses (bool); extern void pop_omp_privatization_clauses (tree); @@ -8623,6 +8626,7 @@ extern void mangle_module_substitution (int); extern int mangle_module_component (tree id, bool partition); extern tree mangle_module_global_init (int); extern unsigned HOST_WIDE_INT range_expr_nelts (tree); +extern bool equal_abi_tags (tree, tree); /* in dump.cc */ extern bool cp_dump_tree (void *, 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 337ee65..2ed94fd 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; @@ -8652,6 +8654,9 @@ omp_declare_variant_finalize_one (tree decl, tree attr) = build_int_cst (TREE_TYPE (nargs), tree_to_uhwi (TREE_PURPOSE (nargs)) + 1); } + for (tree t = append_args_list; t; t = TREE_CHAIN (t)) + TREE_VALUE (t) + = cp_finish_omp_init_prefer_type (TREE_VALUE (t)); DECL_ATTRIBUTES (variant) = tree_cons ( get_identifier ("omp declare variant variant args"), TREE_VALUE (adjust_args_list), DECL_ATTRIBUTES (variant)); @@ -19449,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: diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index 4987987..21156f1 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -2482,9 +2482,7 @@ vague_linkage_p (tree decl) DECL_COMDAT. */ if (DECL_COMDAT (decl) || (TREE_CODE (decl) == FUNCTION_DECL - && DECL_DECLARED_INLINE_P (decl) - /* But gnu_inline functions are always external. */ - && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl))) + && DECL_DECLARED_INLINE_P (decl)) || (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INSTANTIATION (decl)) || (VAR_P (decl) && DECL_INLINE_VAR_P (decl))) diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc index 72e1695..ec7527e 100644 --- a/gcc/cp/error.cc +++ b/gcc/cp/error.cc @@ -308,7 +308,8 @@ dump_module_suffix (cxx_pretty_printer *pp, tree decl) return; } - if (unsigned m = get_originating_module (decl)) + int m = get_originating_module (decl, /*global=-1*/true); + if (m > 0) if (const char *n = module_name (m, false)) { pp_character (pp, '@'); diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index 9ca5cf6..02129c6 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -238,7 +238,6 @@ static void write_local_name (tree, const tree, const tree); static void dump_substitution_candidates (void); static tree mangle_decl_string (const tree); static void maybe_check_abi_tags (tree, tree = NULL_TREE, int = 10); -static bool equal_abi_tags (tree, tree); /* Control functions. */ @@ -1673,7 +1672,7 @@ write_source_name (tree identifier) /* Compare two TREE_STRINGs like strcmp. */ -int +static int tree_string_cmp (const void *p1, const void *p2) { if (p1 == p2) @@ -1728,7 +1727,7 @@ write_abi_tags (tree tags) /* True iff the TREE_LISTS T1 and T2 of ABI tags are equivalent. */ -static bool +bool equal_abi_tags (tree t1, tree t2) { releasing_vec v1 = sorted_abi_tags (t1); @@ -1738,7 +1737,8 @@ equal_abi_tags (tree t1, tree t2) if (len1 != v2->length()) return false; for (unsigned i = 0; i < len1; ++i) - if (tree_string_cmp (v1[i], v2[i]) != 0) + if (strcmp (TREE_STRING_POINTER (v1[i]), + TREE_STRING_POINTER (v2[i])) != 0) return false; return true; } diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index beceafe..ce22b2e 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -3012,6 +3012,7 @@ public: bool read_definition (tree decl); private: + void check_abi_tags (tree existing, tree decl, tree &eattr, tree &dattr); bool is_matching_decl (tree existing, tree decl, bool is_typedef); static bool install_implicit_member (tree decl); bool read_function_def (tree decl, tree maybe_template); @@ -5541,6 +5542,50 @@ trees_in::start (unsigned code) return t; } +/* The kinds of interface an importer could have for a decl. */ + +enum class importer_interface { + unknown, /* The definition may or may not need to be emitted. */ + always_import, /* The definition can always be found in another TU. */ + always_emit, /* The definition must be emitted in the importer's TU. */ +}; + +/* Returns what kind of interface an importer will have of DECL. */ + +static importer_interface +get_importer_interface (tree decl) +{ + /* Internal linkage entities must be emitted in each importer if + there is a definition available. */ + if (!TREE_PUBLIC (decl)) + return importer_interface::always_emit; + + /* Entities that aren't vague linkage are either not definitions or + will be emitted in this TU, so importers can just refer to an + external definition. */ + if (!vague_linkage_p (decl)) + return importer_interface::always_import; + + /* For explicit instantiations, importers can always rely on there + being a definition in another TU, unless this is a definition + in a header module: in which case the importer will always need + to emit it. */ + if (DECL_LANG_SPECIFIC (decl) + && DECL_EXPLICIT_INSTANTIATION (decl)) + return (header_module_p () && !DECL_EXTERNAL (decl) + ? importer_interface::always_emit + : importer_interface::always_import); + + /* A gnu_inline function is never emitted in any TU. */ + if (TREE_CODE (decl) == FUNCTION_DECL + && DECL_DECLARED_INLINE_P (decl) + && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl))) + return importer_interface::always_import; + + /* Everything else has vague linkage. */ + return importer_interface::unknown; +} + /* The structure streamers access the raw fields, because the alternative, of using the accessor macros can require using different accessors for the same underlying field, depending on the @@ -5660,7 +5705,8 @@ trees_out::core_bools (tree t, bits_out& bits) we need to import or export any vague-linkage entities on stream-in. */ bool interface_known = t->decl_common.lang_flag_5; - if (interface_known && vague_linkage_p (t)) + if (interface_known + && get_importer_interface (t) == importer_interface::unknown) interface_known = false; WB (interface_known); } @@ -5694,8 +5740,8 @@ trees_out::core_bools (tree t, bits_out& bits) is_external = true; gcc_fallthrough (); case FUNCTION_DECL: - if (TREE_PUBLIC (t) - && !vague_linkage_p (t)) + if (get_importer_interface (t) + == importer_interface::always_import) is_external = true; break; } @@ -8787,8 +8833,11 @@ trees_in::decl_value () tree etype = TREE_TYPE (existing); /* Handle separate declarations with different attributes. */ + tree &dattr = TYPE_ATTRIBUTES (type); tree &eattr = TYPE_ATTRIBUTES (etype); - eattr = merge_attributes (eattr, TYPE_ATTRIBUTES (type)); + check_abi_tags (existing, decl, eattr, dattr); + // TODO: handle other conflicting type attributes + eattr = merge_attributes (eattr, dattr); /* When merging a partial specialisation, the existing decl may have had its TYPE_CANONICAL adjusted. If so we should use structural @@ -11966,6 +12015,51 @@ trees_in::binfo_mergeable (tree *type) return u (); } +/* DECL is a just streamed declaration with attributes DATTR that should + have matching ABI tags as EXISTING's attributes EATTR. Check that the + ABI tags match, and report an error if not. */ + +void +trees_in::check_abi_tags (tree existing, tree decl, tree &eattr, tree &dattr) +{ + tree etags = lookup_attribute ("abi_tag", eattr); + tree dtags = lookup_attribute ("abi_tag", dattr); + if ((etags == nullptr) != (dtags == nullptr) + || (etags && !attribute_value_equal (etags, dtags))) + { + if (etags) + etags = TREE_VALUE (etags); + if (dtags) + dtags = TREE_VALUE (dtags); + + /* We only error if mangling wouldn't consider the tags equivalent. */ + if (!equal_abi_tags (etags, dtags)) + { + auto_diagnostic_group d; + if (dtags) + error_at (DECL_SOURCE_LOCATION (decl), + "mismatching abi tags for %qD with tags %qE", + decl, dtags); + else + error_at (DECL_SOURCE_LOCATION (decl), + "mismatching abi tags for %qD with no tags", decl); + if (etags) + inform (DECL_SOURCE_LOCATION (existing), + "existing declaration here with tags %qE", etags); + else + inform (DECL_SOURCE_LOCATION (existing), + "existing declaration here with no tags"); + } + + /* Always use the existing abi_tags as the canonical set so that + later processing doesn't get confused. */ + if (dtags) + dattr = remove_attribute ("abi_tag", dattr); + if (etags) + duplicate_one_attribute (&dattr, eattr, "abi_tag"); + } +} + /* DECL is a just streamed mergeable decl that should match EXISTING. Check it does and issue an appropriate diagnostic if not. Merge any bits from DECL to EXISTING. This is stricter matching than @@ -12159,10 +12253,28 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef) if (TREE_CODE (d_inner) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (d_inner)) - DECL_DECLARED_INLINE_P (e_inner) = true; + { + DECL_DECLARED_INLINE_P (e_inner) = true; + if (!DECL_SAVED_TREE (e_inner) + && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (d_inner)) + && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (e_inner))) + { + DECL_INTERFACE_KNOWN (e_inner) + |= DECL_INTERFACE_KNOWN (d_inner); + DECL_DISREGARD_INLINE_LIMITS (e_inner) + |= DECL_DISREGARD_INLINE_LIMITS (d_inner); + // TODO: we will eventually want to merge all decl attributes + duplicate_one_attribute (&DECL_ATTRIBUTES (e_inner), + DECL_ATTRIBUTES (d_inner), "gnu_inline"); + } + } if (!DECL_EXTERNAL (d_inner)) DECL_EXTERNAL (e_inner) = false; + if (VAR_OR_FUNCTION_DECL_P (d_inner)) + check_abi_tags (existing, decl, + DECL_ATTRIBUTES (e_inner), DECL_ATTRIBUTES (d_inner)); + if (TREE_CODE (decl) == TEMPLATE_DECL) { /* Merge default template arguments. */ @@ -12567,9 +12679,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); @@ -12625,7 +12738,12 @@ 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)) || (DECL_CLASS_SCOPE_P (decl) && !DECL_VTABLE_OR_VTT_P (decl) && !DECL_TEMPLATE_INFO (decl))) @@ -16543,6 +16661,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)) @@ -20310,20 +20434,24 @@ get_originating_module_decl (tree decl) return decl; } +/* If DECL is imported, return which module imported it, or 0 for the current + module. Except that if GLOBAL_M1, return -1 for decls attached to the + global module. */ + int -get_originating_module (tree decl, bool for_mangle) +get_originating_module (tree decl, bool global_m1) { tree owner = get_originating_module_decl (decl); tree not_tmpl = STRIP_TEMPLATE (owner); if (!DECL_LANG_SPECIFIC (not_tmpl)) - return for_mangle ? -1 : 0; + return global_m1 ? -1 : 0; - if (for_mangle && !DECL_MODULE_ATTACH_P (not_tmpl)) + if (global_m1 && !DECL_MODULE_ATTACH_P (not_tmpl)) return -1; int mod = !DECL_MODULE_IMPORT_P (not_tmpl) ? 0 : get_importing_module (owner); - gcc_checking_assert (!for_mangle || !(*modules)[mod]->is_header ()); + gcc_checking_assert (!global_m1 || !(*modules)[mod]->is_header ()); return mod; } diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 742e5d2..7fadbcc 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); @@ -4568,7 +4569,7 @@ lookup_imported_hidden_friend (tree friend_tmpl) tree inner = DECL_TEMPLATE_RESULT (friend_tmpl); if (!DECL_LANG_SPECIFIC (inner) - || !DECL_MODULE_IMPORT_P (inner)) + || !DECL_MODULE_ENTITY_P (inner)) return NULL_TREE; lazy_load_pendings (friend_tmpl); @@ -4578,16 +4579,16 @@ lookup_imported_hidden_friend (tree friend_tmpl) if (!bind) return NULL_TREE; - /* We're only interested in declarations coming from the same module - of the friend class we're attempting to instantiate. */ - int m = get_originating_module (friend_tmpl); + /* We're only interested in declarations attached to the same module + as the friend class we're attempting to instantiate. */ + int m = get_originating_module (friend_tmpl, /*global=-1*/true); gcc_assert (m != 0); /* There should be at most one class template from the module we're looking for, return it. */ for (ovl_iterator iter (bind); iter; ++iter) if (DECL_CLASS_TEMPLATE_P (*iter) - && get_originating_module (*iter) == m) + && get_originating_module (*iter, true) == m) return *iter; return NULL_TREE; @@ -8675,6 +8676,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 +8720,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 57a4610..f2eea4c 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 @@ -11773,6 +11773,9 @@ cp_parser_lambda_expression (cp_parser* parser) parser->auto_is_implicit_function_template_parm_p = false; parser->omp_array_section_p = false; + /* Inside the lambda, outside unevaluated context do not apply. */ + cp_evaluated ev; + /* The body of a lambda in a discarded statement is not discarded. */ bool discarded = in_discarded_stmt; in_discarded_stmt = 0; @@ -18842,7 +18845,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); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 538ff22..f7c56a1 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -12134,13 +12134,18 @@ tsubst_attribute (tree t, tree *decl_p, tree args, location_t match_loc = cp_expr_loc_or_input_loc (TREE_PURPOSE (chain)); tree ctx = copy_list (TREE_VALUE (val)); tree append_args_list = TREE_CHAIN (TREE_CHAIN (chain)); - if (append_args_list && TREE_VALUE (append_args_list)) + if (append_args_list + && TREE_VALUE (append_args_list) + && TREE_CHAIN (TREE_VALUE (append_args_list))) { - append_args_list = TREE_VALUE (TREE_VALUE (append_args_list)); + append_args_list = TREE_VALUE (append_args_list); + append_args_list = TREE_VALUE (TREE_CHAIN (append_args_list)); for (; append_args_list; append_args_list = TREE_CHAIN (append_args_list)) { tree pref_list = TREE_VALUE (append_args_list); + if (pref_list == NULL_TREE || TREE_CODE (pref_list) != TREE_LIST) + continue; tree fr_list = TREE_VALUE (pref_list); int len = TREE_VEC_LENGTH (fr_list); for (int i = 0; i < len; i++) @@ -15920,6 +15925,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain, if (TYPE_USER_ALIGN (TREE_TYPE (t))) TREE_TYPE (r) = build_aligned_type (TREE_TYPE (r), TYPE_ALIGN (TREE_TYPE (t))); + + /* Preserve structural-ness of a partially instantiated typedef. */ + if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (t)) + && dependent_type_p (TREE_TYPE (r))) + SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (r)); } layout_decl (r, 0); @@ -25958,6 +25968,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. */ @@ -25995,16 +26022,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, @@ -27219,6 +27238,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/rtti.cc b/gcc/cp/rtti.cc index 158b5ba..3539962 100644 --- a/gcc/cp/rtti.cc +++ b/gcc/cp/rtti.cc @@ -204,8 +204,7 @@ throw_bad_cast (void) return build_cxx_call (fn, 0, NULL, tf_warning_or_error); } -/* Return an expression for "__cxa_bad_typeid()". The expression - returned is an lvalue of type "const std::type_info". */ +/* See 'libstdc++-v3/libsupc++/eh_aux_runtime.cc' for '__cxa_bad_typeid'. */ static tree throw_bad_typeid (void) @@ -216,11 +215,8 @@ throw_bad_typeid (void) tree name = get_identifier ("__cxa_bad_typeid"); fn = get_global_binding (name); if (!fn) - { - tree t = build_reference_type (const_type_info_type_node); - t = build_function_type_list (t, NULL_TREE); - fn = push_throw_library_fn (name, t); - } + fn = push_throw_library_fn + (name, build_function_type_list (void_type_node, NULL_TREE)); } return build_cxx_call (fn, 0, NULL, tf_warning_or_error); @@ -259,7 +255,7 @@ get_void_tinfo_ptr (tree type) otherwise return the static type of the expression. */ static tree -get_tinfo_decl_dynamic (tree exp, tsubst_flags_t complain) +get_tinfo_ptr_dynamic (tree exp, tsubst_flags_t complain) { tree type; tree t; @@ -299,7 +295,7 @@ get_tinfo_decl_dynamic (tree exp, tsubst_flags_t complain) /* Otherwise return the type_info for the static type of the expr. */ t = get_tinfo_ptr (type); - return cp_build_fold_indirect_ref (t); + return t; } static bool @@ -369,7 +365,7 @@ build_typeid (tree exp, tsubst_flags_t complain) exp = cp_build_fold_indirect_ref (exp); } - exp = get_tinfo_decl_dynamic (exp, complain); + exp = get_tinfo_ptr_dynamic (exp, complain); if (exp == error_mark_node) return error_mark_node; @@ -383,7 +379,7 @@ build_typeid (tree exp, tsubst_flags_t complain) else mark_type_use (initial_expr); - return exp; + return cp_build_fold_indirect_ref (exp); } /* Generate the NTBS name of a type. If MARK_PRIVATE, put a '*' in front so that diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index b0a5f9a..7d8beb8 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -5086,7 +5086,7 @@ finish_underlying_type (tree type) static tree finish_type_pack_element (tree idx, tree types, tsubst_flags_t complain) { - idx = maybe_constant_value (idx); + idx = maybe_constant_value (idx, NULL_TREE, mce_true); if (TREE_CODE (idx) != INTEGER_CST || !INTEGRAL_TYPE_P (TREE_TYPE (idx))) { if (complain & tf_error) @@ -7466,17 +7466,17 @@ cp_oacc_check_attachments (tree c) /* Update OMP_CLAUSE_INIT_PREFER_TYPE in case template substitution happened. */ -static void -cp_omp_init_prefer_type_update (tree c) +tree +cp_finish_omp_init_prefer_type (tree pref_type) { if (processing_template_decl - || OMP_CLAUSE_INIT_PREFER_TYPE (c) == NULL_TREE - || TREE_CODE (OMP_CLAUSE_INIT_PREFER_TYPE (c)) != TREE_LIST) - return; + || pref_type == NULL_TREE + || TREE_CODE (pref_type) != TREE_LIST) + return pref_type; - tree t = TREE_PURPOSE (OMP_CLAUSE_INIT_PREFER_TYPE (c)); + tree t = TREE_PURPOSE (pref_type); char *str = const_cast<char *> (TREE_STRING_POINTER (t)); - tree fr_list = TREE_VALUE (OMP_CLAUSE_INIT_PREFER_TYPE (c)); + tree fr_list = TREE_VALUE (pref_type); int len = TREE_VEC_LENGTH (fr_list); int cnt = 0; @@ -7502,7 +7502,7 @@ cp_omp_init_prefer_type_update (tree c) || !tree_fits_shwi_p (value)) error_at (loc, "expected string literal or " - "constant integer expression instead of %qE", value); // FIXME of 'qE' and no 'loc'? + "constant integer expression instead of %qE", value); else { HOST_WIDE_INT n = tree_to_shwi (value); @@ -7531,7 +7531,7 @@ cp_omp_init_prefer_type_update (tree c) if (cnt >= len) break; } - OMP_CLAUSE_INIT_PREFER_TYPE (c) = t; + return t; } /* For all elements of CLAUSES, validate them vs OpenMP constraints. @@ -9690,7 +9690,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) break; case OMP_CLAUSE_INIT: init_seen = true; - cp_omp_init_prefer_type_update (c); + OMP_CLAUSE_INIT_PREFER_TYPE (c) + = cp_finish_omp_init_prefer_type (OMP_CLAUSE_INIT_PREFER_TYPE (c)); if (!OMP_CLAUSE_INIT_TARGETSYNC (c)) init_no_targetsync_clause = c; /* FALLTHRU */ 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 { diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc index 1adc05a..45edd18 100644 --- a/gcc/cp/typeck2.cc +++ b/gcc/cp/typeck2.cc @@ -2387,7 +2387,7 @@ build_m_component_ref (tree datum, tree component, tsubst_flags_t complain) (cp_type_quals (type) | cp_type_quals (TREE_TYPE (datum)))); - datum = build_address (datum); + datum = cp_build_addr_expr (datum, complain); /* Convert object to the correct base. */ if (binfo) |