Skip to content

Commit

Permalink
c++/modules: Stream additional fields for DECL_STRUCT_FUNCTION [PR113…
Browse files Browse the repository at this point in the history
…580]

This patch just adds enough of the fields from 'function' to fix the ICE
in the linked PR. I suppose there might be more fields from this type
that should be propagated, but I don't know enough to find out which
they might be yet, since a lot of them seem to be only set after
gimplification.

Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

Currently the DECL_STRUCT_FUNCTION for a declaration is always
reconstructed from scratch. This causes issues though, as some fields
used by other parts of the compiler (in this case, specifically
'function_{start,end}_locus') are then not correctly initialised. This
patch makes sure that these fields are also read and written.

	PR c++/113580

gcc/cp/ChangeLog:

	* module.cc (struct post_process_data): Create.
	(trees_in::post_decls): Use.
	(trees_in::post_process): Return entire vector at once.
	Change overload to take post_process_data instead of tree.
	(trees_out::write_function_def): Write needed flags from
	DECL_STRUCT_FUNCTION.
	(trees_in::read_function_def): Read them and pass to
	post_process.
	(module_state::read_cluster): Write flags into cfun.

gcc/testsuite/ChangeLog:

	* g++.dg/modules/pr113580_a.C: New test.
	* g++.dg/modules/pr113580_b.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
  • Loading branch information
wreien authored and ouuleilei-bot committed Jan 26, 2024
1 parent c2d62cd commit 8d433bd
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
47 changes: 38 additions & 9 deletions gcc/cp/module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2837,6 +2837,13 @@ typedef hash_map<tree,uintptr_t,
simple_hashmap_traits<nodel_ptr_hash<tree_node>,uintptr_t> >
duplicate_hash_map;

/* Data needed for post-processing. */
struct post_process_data {
tree decl;
location_t start_locus;
location_t end_locus;
};

/* Tree stream reader. Note that reading a stream doesn't mark the
read trees with TREE_VISITED. Thus it's quite safe to have
multiple concurrent readers. Which is good, because lazy
Expand All @@ -2848,7 +2855,7 @@ class trees_in : public bytes_in {
module_state *state; /* Module being imported. */
vec<tree> back_refs; /* Back references. */
duplicate_hash_map *duplicates; /* Map from existings to duplicate. */
vec<tree> post_decls; /* Decls to post process. */
vec<post_process_data> post_decls; /* Decls to post process. */
unsigned unused; /* Inhibit any interior TREE_USED
marking. */

Expand Down Expand Up @@ -2945,16 +2952,16 @@ class trees_in : public bytes_in {
tree odr_duplicate (tree decl, bool has_defn);

public:
/* Return the next decl to postprocess, or NULL. */
tree post_process ()
/* Return the decls to postprocess. */
const vec<post_process_data>& post_process ()
{
return post_decls.length () ? post_decls.pop () : NULL_TREE;
return post_decls;
}
private:
/* Register DECL for postprocessing. */
void post_process (tree decl)
/* Register DATA for postprocessing. */
void post_process (post_process_data data)
{
post_decls.safe_push (decl);
post_decls.safe_push (data);
}

private:
Expand Down Expand Up @@ -11601,15 +11608,25 @@ trees_out::write_function_def (tree decl)
tree_node (cexpr->body);
}

function* f = DECL_STRUCT_FUNCTION (decl);

if (streaming_p ())
{
unsigned flags = 0;

if (f)
flags |= 2;
if (DECL_NOT_REALLY_EXTERN (decl))
flags |= 1;

u (flags);
}

if (state && f)
{
state->write_location (*this, f->function_start_locus);
state->write_location (*this, f->function_end_locus);
}
}

void
Expand All @@ -11626,6 +11643,8 @@ trees_in::read_function_def (tree decl, tree maybe_template)
tree saved = tree_node ();
tree context = tree_node ();
constexpr_fundef cexpr;
post_process_data pdata {};
pdata.decl = maybe_template;

tree maybe_dup = odr_duplicate (maybe_template, DECL_SAVED_TREE (decl));
bool installing = maybe_dup && !DECL_SAVED_TREE (decl);
Expand All @@ -11642,6 +11661,12 @@ trees_in::read_function_def (tree decl, tree maybe_template)

unsigned flags = u ();

if (flags & 2)
{
pdata.start_locus = state->read_location (*this);
pdata.end_locus = state->read_location (*this);
}

if (get_overrun ())
return NULL_TREE;

Expand All @@ -11658,7 +11683,7 @@ trees_in::read_function_def (tree decl, tree maybe_template)
SET_DECL_FRIEND_CONTEXT (decl, context);
if (cexpr.decl)
register_constexpr_fundef (cexpr);
post_process (maybe_template);
post_process (pdata);
}
else if (maybe_dup)
{
Expand Down Expand Up @@ -15039,8 +15064,10 @@ module_state::read_cluster (unsigned snum)
push_function_context does too much work. */
tree old_cfd = current_function_decl;
struct function *old_cfun = cfun;
while (tree decl = sec.post_process ())
for (const post_process_data& pdata : sec.post_process ())
{
tree decl = pdata.decl;

bool abstract = false;
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
Expand All @@ -15052,6 +15079,8 @@ module_state::read_cluster (unsigned snum)
allocate_struct_function (decl, abstract);
cfun->language = ggc_cleared_alloc<language_function> ();
cfun->language->base.x_stmt_tree.stmts_are_full_exprs_p = 1;
cfun->function_start_locus = pdata.start_locus;
cfun->function_end_locus = pdata.end_locus;

if (abstract)
;
Expand Down
10 changes: 10 additions & 0 deletions gcc/testsuite/g++.dg/modules/pr113580_a.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// PR c++/113580
// { dg-additional-options "-fmodules-ts" }
// { dg-module-cmi A }

export module A;

export {
template <typename T>
void fun(T x) {}
}
10 changes: 10 additions & 0 deletions gcc/testsuite/g++.dg/modules/pr113580_b.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// PR c++/113580
// { dg-additional-options "-fmodules-ts -Wunused-parameter" }

import A;

int main() {
fun(42); // { dg-message "required from here" }
}

// { dg-warning "unused parameter" "" { target *-*-* } 0 }

0 comments on commit 8d433bd

Please sign in to comment.