aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog114
-rw-r--r--gcc/cp/call.cc9
-rw-r--r--gcc/cp/class.cc1
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/cvt.cc13
-rw-r--r--gcc/cp/decl.cc12
-rw-r--r--gcc/cp/decl2.cc4
-rw-r--r--gcc/cp/error.cc3
-rw-r--r--gcc/cp/mangle.cc8
-rw-r--r--gcc/cp/module.cc152
-rw-r--r--gcc/cp/name-lookup.cc53
-rw-r--r--gcc/cp/parser.cc9
-rw-r--r--gcc/cp/pt.cc54
-rw-r--r--gcc/cp/rtti.cc18
-rw-r--r--gcc/cp/semantics.cc23
-rw-r--r--gcc/cp/typeck.cc10
-rw-r--r--gcc/cp/typeck2.cc2
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)