diff options
author | Patrick Palka <ppalka@redhat.com> | 2024-03-01 17:24:15 -0500 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2024-03-01 17:24:15 -0500 |
commit | 574fd1f17f100c7c355ad26bc525ab5a3386bb2d (patch) | |
tree | 86d14ee36c3263809d7eb44aa6ae0a20138bb461 /gcc/cp/module.cc | |
parent | 852b58552991099141f9df5782e1f28d8606af9d (diff) | |
download | gcc-574fd1f17f100c7c355ad26bc525ab5a3386bb2d.zip gcc-574fd1f17f100c7c355ad26bc525ab5a3386bb2d.tar.gz gcc-574fd1f17f100c7c355ad26bc525ab5a3386bb2d.tar.bz2 |
c++/modules: depending local enums [PR104919, PR106009]
For local enums defined in a non-template function or a function template
instantiation it seems we neglect to make the function depend on the enum
definition (which modules considers logically separate), which ultimately
causes the enum definition to not be properly streamed before uses
within the function definition are streamed.
The code responsible for noting such dependencies is
gcc/cp/module.cc
@@ -8784,17 +8784,6 @@ trees_out::decl_node (tree decl, walk_kind ref)
depset *dep = NULL;
if (streaming_p ())
dep = dep_hash->find_dependency (decl);
! else if (TREE_CODE (ctx) != FUNCTION_DECL
! || TREE_CODE (decl) == TEMPLATE_DECL
! || (dep_hash->sneakoscope && DECL_IMPLICIT_TYPEDEF_P (decl))
! || (DECL_LANG_SPECIFIC (decl)
! && DECL_MODULE_IMPORT_P (decl)))
! {
! auto kind = (TREE_CODE (decl) == NAMESPACE_DECL
! && !DECL_NAMESPACE_ALIAS (decl)
! ? depset::EK_NAMESPACE : depset::EK_DECL);
! dep = dep_hash->add_dependency (decl, kind);
! }
if (!dep)
{
and the condition there notably excludes local TYPE_DECLs from a
non-template-pattern function (when streaming a template pattern
we'll see be dealing with the corresponding TEMPLATE_DECL of the
local TYPE_DECL here, so we'll add the dependency).
Local classes on the other hand seem to work properly, but perhaps by
accident: with a local class we end up making the function depend on the
injected-class-name of the local class rather than the local class as a
whole because the injected-class-name satisfies the criteria (since its
context is the local class, not the function).
The 'sneakoscope' flag is set when walking a function declaration and
its purpose seems to be to catch a local type that escapes the function
via a deduced return type (so called voldemort types) and note a
dependency on them. But there seems to be no reason to restrict this
behavior to voldemort types, and indeed consistently noting the dependency
for all local types fixes these PRs (almost). So this patch gets rid of
this flag and enables the dependency tracking unconditionally.
This was nearly enough to make things work, except we now ran into
issues with the local TYPE_/CONST_DECL copies from the pre-gimplified
version of a constexpr function body during streaming. Rather than
making modules cope with this, it occurred to me that we don't need to
make copies of local types when saving the pre-gimplified body (and when
making further copies thereof); only VAR_DECLs etc need to be copied
(so that we don't conflate local variables from different recursive
calls to the same function during constexpr evaluation). So this patch
adjusts copy_fn accordingly.
PR c++/104919
PR c++/106009
gcc/cp/ChangeLog:
* module.cc (depset::hash::sneakoscope): Remove.
(trees_out::decl_node): Always add a dependency on a local type.
(depset::hash::find_dependencies): Remove sneakoscope stuff.
gcc/ChangeLog:
* tree-inline.cc (remap_decl): Handle copy_decl returning the
original decl.
(remap_decls): Handle remap_decl returning the original decl.
(copy_fn): Adjust copy_decl callback to skip TYPE_DECL and
CONST_DECL.
gcc/testsuite/ChangeLog:
* g++.dg/modules/tdef-7.h: Remove outdated comment.
* g++.dg/modules/tdef-7_b.C: Don't expect two TYPE_DECLs.
* g++.dg/modules/enum-13_a.C: New test.
* g++.dg/modules/enum-13_b.C: New test.
Diffstat (limited to 'gcc/cp/module.cc')
-rw-r--r-- | gcc/cp/module.cc | 12 |
1 files changed, 2 insertions, 10 deletions
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 355ee5d..67f132d 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -2522,13 +2522,12 @@ public: hash *chain; /* Original table. */ depset *current; /* Current depset being depended. */ unsigned section; /* When writing out, the section. */ - bool sneakoscope; /* Detecting dark magic (of a voldemort). */ bool reached_unreached; /* We reached an unreached entity. */ public: hash (size_t size, hash *c = NULL) : parent (size), chain (c), current (NULL), section (0), - sneakoscope (false), reached_unreached (false) + reached_unreached (false) { worklist.create (size); } @@ -8753,7 +8752,7 @@ trees_out::decl_node (tree decl, walk_kind ref) dep = dep_hash->find_dependency (decl); else if (TREE_CODE (ctx) != FUNCTION_DECL || TREE_CODE (decl) == TEMPLATE_DECL - || (dep_hash->sneakoscope && DECL_IMPLICIT_TYPEDEF_P (decl)) + || DECL_IMPLICIT_TYPEDEF_P (decl) || (DECL_LANG_SPECIFIC (decl) && DECL_MODULE_IMPORT_P (decl))) { @@ -13432,14 +13431,7 @@ depset::hash::find_dependencies (module_state *module) add_namespace_context (item, ns); } - // FIXME: Perhaps p1815 makes this redundant? Or at - // least simplifies it. Voldemort types are only - // ever emissable when containing (inline) function - // definition is emitted? - /* Turn the Sneakoscope on when depending the decl. */ - sneakoscope = true; walker.decl_value (decl, current); - sneakoscope = false; if (current->has_defn ()) walker.write_definition (decl); } |