aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/module.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/module.cc')
-rw-r--r--gcc/cp/module.cc133
1 files changed, 99 insertions, 34 deletions
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 894c70f..5ff5c46 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;
@@ -12087,6 +12090,8 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
gcc_checking_assert (TREE_CODE (e_inner) == TREE_CODE (d_inner));
}
+ // FIXME: do more precise errors at point of mismatch
+ const char *mismatch_msg = nullptr;
if (TREE_CODE (d_inner) == FUNCTION_DECL)
{
tree e_ret = fndecl_declared_return_type (existing);
@@ -12096,13 +12101,20 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
&& LAMBDA_TYPE_P (DECL_CONTEXT (d_inner)))
/* This has a recursive type that will compare different. */;
else if (!same_type_p (d_ret, e_ret))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting type for imported declaration %#qD");
+ goto mismatch;
+ }
tree e_type = TREE_TYPE (e_inner);
tree d_type = TREE_TYPE (d_inner);
if (DECL_EXTERN_C_P (d_inner) != DECL_EXTERN_C_P (e_inner))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting language linkage for imported "
+ "declaration %#qD");
+ goto mismatch;
+ }
for (tree e_args = TYPE_ARG_TYPES (e_type),
d_args = TYPE_ARG_TYPES (d_type);
@@ -12110,10 +12122,18 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
e_args = TREE_CHAIN (e_args), d_args = TREE_CHAIN (d_args))
{
if (!(e_args && d_args))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting argument list for imported "
+ "declaration %#qD");
+ goto mismatch;
+ }
if (!same_type_p (TREE_VALUE (d_args), TREE_VALUE (e_args)))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting argument types for imported "
+ "declaration %#qD");
+ goto mismatch;
+ }
}
/* If EXISTING has an undeduced or uninstantiated exception
@@ -12122,7 +12142,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)
@@ -12144,9 +12164,14 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
}
}
}
- else if (!DEFERRED_NOEXCEPT_SPEC_P (d_spec)
+ else if (!DECL_MAYBE_DELETED (d_inner)
+ && !DEFERRED_NOEXCEPT_SPEC_P (d_spec)
&& !comp_except_specs (d_spec, e_spec, ce_type))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting %<noexcept%> specifier for "
+ "imported declaration %#qD");
+ goto mismatch;
+ }
/* Similarly if EXISTING has an undeduced return type, but DECL's
is already deduced. */
@@ -12160,20 +12185,48 @@ 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;
+ {
+ mismatch_msg = G_("conflicting deduced return type for "
+ "imported declaration %#qD");
+ 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_MAYBE_DELETED (e_inner) && DECL_MAYBE_DELETED (d_inner))
+ /* Nothing to do. */;
+ else if (DECL_DECLARED_CONSTEXPR_P (e_inner)
+ != DECL_DECLARED_CONSTEXPR_P (d_inner))
+ {
+ mismatch_msg = G_("conflicting %<constexpr%> for imported "
+ "declaration %#qD");
+ 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)
{
if (!DECL_ORIGINAL_TYPE (e_inner)
|| !same_type_p (DECL_ORIGINAL_TYPE (d_inner),
DECL_ORIGINAL_TYPE (e_inner)))
- goto mismatch;
+ {
+ mismatch_msg = G_("conflicting imported declaration %q#D");
+ goto mismatch;
+ }
}
/* Using cp_tree_equal because we can meet TYPE_ARGUMENT_PACKs
here. I suspect the entities that directly do that are things
that shouldn't go to duplicate_decls (FIELD_DECLs etc). */
else if (!cp_tree_equal (TREE_TYPE (decl), TREE_TYPE (existing)))
{
+ mismatch_msg = G_("conflicting type for imported declaration %#qD");
mismatch:
if (DECL_IS_UNDECLARED_BUILTIN (existing))
/* Just like duplicate_decls, presum the user knows what
@@ -12186,11 +12239,9 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
equality isn't feasible in general for local entities. */;
else
{
- // FIXME:QOI Might be template specialization from a module,
- // not necessarily global module
+ gcc_checking_assert (mismatch_msg);
auto_diagnostic_group d;
- error_at (DECL_SOURCE_LOCATION (decl),
- "conflicting global module declaration %#qD", decl);
+ error_at (DECL_SOURCE_LOCATION (decl), mismatch_msg, decl);
inform (DECL_SOURCE_LOCATION (existing),
"existing declaration %#qD", existing);
return false;
@@ -12679,9 +12730,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);
@@ -16678,6 +16730,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;
}
}
@@ -19158,6 +19219,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;