c++/modules: Stream warning suppressions [PR115757]

Currently we don't stream the contents of 'nowarn_map'; this means that
warning suppressions don't get applied in importers, which is
particularly relevant for templates (as in the linked testcase).

Rather than streaming the whole contents of 'nowarn_map', this patch
instead just streams the exported suppressions for each tree node
individually, to not build up additional locations and suppressions for
tree nodes that do not need to be streamed.

	PR c++/115757

gcc/cp/ChangeLog:

	* module.cc (trees_out::core_vals): Write warning specs for
	DECLs and EXPRs.
	(trees_in::core_vals): Read warning specs.

gcc/ChangeLog:

	* tree.h (put_warning_spec_at): Declare new function.
	(has_warning_spec): Likewise.
	(get_warning_spec): Likewise.
	(put_warning_spec): Likewise.
	* diagnostic-spec.h (nowarn_spec_t::from_bits): New function.
	* diagnostic-spec.cc (put_warning_spec_at): New function.
	* warning-control.cc (has_warning_spec): New function.
	(get_warning_spec): New function.
	(put_warning_spec): New function.

gcc/testsuite/ChangeLog:

	* g++.dg/modules/warn-spec-1_a.C: New test.
	* g++.dg/modules/warn-spec-1_b.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
This commit is contained in:
Nathaniel Shead 2024-07-07 13:56:25 +10:00
parent 18eb6ca136
commit fd599d96d4
7 changed files with 93 additions and 0 deletions

View File

@ -6000,6 +6000,10 @@ trees_out::core_vals (tree t)
if (state) if (state)
state->write_location (*this, t->decl_minimal.locus); state->write_location (*this, t->decl_minimal.locus);
if (streaming_p ())
if (has_warning_spec (t))
u (get_warning_spec (t));
} }
if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON)) if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
@ -6113,6 +6117,10 @@ trees_out::core_vals (tree t)
if (state) if (state)
state->write_location (*this, t->exp.locus); state->write_location (*this, t->exp.locus);
if (streaming_p ())
if (has_warning_spec (t))
u (get_warning_spec (t));
/* Walk in forward order, as (for instance) REQUIRES_EXPR has a /* Walk in forward order, as (for instance) REQUIRES_EXPR has a
bunch of unscoped parms on its first operand. It's safer to bunch of unscoped parms on its first operand. It's safer to
create those in order. */ create those in order. */
@ -6576,6 +6584,8 @@ trees_in::core_vals (tree t)
/* Don't zap the locus just yet, we don't record it correctly /* Don't zap the locus just yet, we don't record it correctly
and thus lose all location information. */ and thus lose all location information. */
t->decl_minimal.locus = state->read_location (*this); t->decl_minimal.locus = state->read_location (*this);
if (has_warning_spec (t))
put_warning_spec (t, u ());
} }
if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON)) if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
@ -6654,6 +6664,8 @@ trees_in::core_vals (tree t)
if (CODE_CONTAINS_STRUCT (code, TS_EXP)) if (CODE_CONTAINS_STRUCT (code, TS_EXP))
{ {
t->exp.locus = state->read_location (*this); t->exp.locus = state->read_location (*this);
if (has_warning_spec (t))
put_warning_spec (t, u ());
bool vl = TREE_CODE_CLASS (code) == tcc_vl_exp; bool vl = TREE_CODE_CLASS (code) == tcc_vl_exp;
for (unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t) for (unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t)

View File

@ -179,6 +179,27 @@ suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
return true; return true;
} }
/* Change the warning disposition for LOC to match OPTSPEC. */
void
put_warning_spec_at (location_t loc, unsigned bits)
{
gcc_checking_assert (!RESERVED_LOCATION_P (loc));
nowarn_spec_t optspec = nowarn_spec_t::from_bits (bits);
if (!optspec)
{
if (nowarn_map)
nowarn_map->remove (loc);
}
else
{
if (!nowarn_map)
nowarn_map = nowarn_map_t::create_ggc (32);
nowarn_map->put (loc, optspec);
}
}
/* Copy the no-warning disposition from one location to another. */ /* Copy the no-warning disposition from one location to another. */
void void

View File

@ -56,6 +56,13 @@ public:
nowarn_spec_t (opt_code); nowarn_spec_t (opt_code);
static nowarn_spec_t from_bits (unsigned bits)
{
nowarn_spec_t spec;
spec.m_bits = bits;
return spec;
}
/* Return the raw bitset. */ /* Return the raw bitset. */
operator unsigned() const operator unsigned() const
{ {

View File

@ -0,0 +1,10 @@
// PR c++/115757
// { dg-additional-options "-fmodules-ts -Wunused" }
// { dg-module-cmi test }
export module test;
export template <typename T>
void foo(T n [[maybe_unused]]) {
int x [[maybe_unused]];
}

View File

@ -0,0 +1,8 @@
// PR c++/115757
// { dg-additional-options "-fmodules-ts -Wunused" }
import test;
int main() {
foo(0);
}

View File

@ -6929,6 +6929,8 @@ extern bool warning_suppressed_at (location_t, opt_code = all_warnings);
at a location to disabled by default. */ at a location to disabled by default. */
extern bool suppress_warning_at (location_t, opt_code = all_warnings, extern bool suppress_warning_at (location_t, opt_code = all_warnings,
bool = true); bool = true);
/* Overwrite warning disposition bitmap for a location with given spec. */
extern void put_warning_spec_at (location_t loc, unsigned);
/* Copy warning disposition from one location to another. */ /* Copy warning disposition from one location to another. */
extern void copy_warning (location_t, location_t); extern void copy_warning (location_t, location_t);
@ -6942,6 +6944,13 @@ extern void suppress_warning (tree, opt_code = all_warnings, bool = true)
/* Copy warning disposition from one expression to another. */ /* Copy warning disposition from one expression to another. */
extern void copy_warning (tree, const_tree); extern void copy_warning (tree, const_tree);
/* Whether the tree might have a warning spec. */
extern bool has_warning_spec (const_tree);
/* Retrieve warning spec bitmap for tree streaming. */
extern unsigned get_warning_spec (const_tree);
/* Overwrite warning spec bitmap for a tree with given spec. */
extern void put_warning_spec (tree, unsigned);
/* Return the zero-based number corresponding to the argument being /* Return the zero-based number corresponding to the argument being
deallocated if FNDECL is a deallocation function or an out-of-bounds deallocated if FNDECL is a deallocation function or an out-of-bounds
value if it isn't. */ value if it isn't. */

View File

@ -256,3 +256,29 @@ copy_warning (gimple *to, const gimple *from)
return; return;
copy_warning<gimple *, const gimple *>(to, from); copy_warning<gimple *, const gimple *>(to, from);
} }
/* Whether the tree might have a warning spec. */
bool has_warning_spec (const_tree t)
{
const location_t loc = get_location (t);
return !RESERVED_LOCATION_P (loc) && !get_no_warning_bit (t);
}
/* Retrieve warning dispostion bitmap for tree streaming. */
unsigned
get_warning_spec (const_tree t)
{
const nowarn_spec_t *spec = get_nowarn_spec (t);
return spec ? *spec : 0;
}
/* Write warning disposition bitmap for streamed-in tree. */
void
put_warning_spec (tree t, unsigned bits)
{
const location_t loc = get_location (t);
put_warning_spec_at (loc, bits);
}