Message ID | 668a1c20.170a0220.c1636.1d22@mx.google.com |
---|---|
State | New |
Headers | show |
Series | c++/modules: Stream warning suppressions [PR115757] | expand |
On 7/7/24 12:39 AM, Nathaniel Shead wrote: > Bootstrapped on x86_64-pc-linux-gnu, successfully regtested modules.exp; > OK for trunk if full regtest passes? Patrick, I assume this change won't mess with your streaming optimizations? OK with Patrick's approval or on Friday, whichever comes first. > -- >8 -- > > 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> > --- > gcc/cp/module.cc | 12 +++++++++ > gcc/diagnostic-spec.cc | 21 ++++++++++++++++ > gcc/diagnostic-spec.h | 7 ++++++ > gcc/testsuite/g++.dg/modules/warn-spec-1_a.C | 10 ++++++++ > gcc/testsuite/g++.dg/modules/warn-spec-1_b.C | 8 ++++++ > gcc/tree.h | 9 +++++++ > gcc/warning-control.cc | 26 ++++++++++++++++++++ > 7 files changed, 93 insertions(+) > create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-1_a.C > create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-1_b.C > > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc > index dc5d046f04d..0f9a689dbec 100644 > --- a/gcc/cp/module.cc > +++ b/gcc/cp/module.cc > @@ -6000,6 +6000,10 @@ trees_out::core_vals (tree t) > > if (state) > 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)) > @@ -6113,6 +6117,10 @@ trees_out::core_vals (tree t) > if (state) > 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 > bunch of unscoped parms on its first operand. It's safer to > 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 > and thus lose all location information. */ > 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)) > @@ -6654,6 +6664,8 @@ trees_in::core_vals (tree t) > if (CODE_CONTAINS_STRUCT (code, TS_EXP)) > { > 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; > for (unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t) > diff --git a/gcc/diagnostic-spec.cc b/gcc/diagnostic-spec.cc > index 996ad6b273a..addaf089f03 100644 > --- a/gcc/diagnostic-spec.cc > +++ b/gcc/diagnostic-spec.cc > @@ -179,6 +179,27 @@ suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */, > 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. */ > > void > diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h > index 22d4c067158..0b155a5cde3 100644 > --- a/gcc/diagnostic-spec.h > +++ b/gcc/diagnostic-spec.h > @@ -56,6 +56,13 @@ public: > > 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. */ > operator unsigned() const > { > diff --git a/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C b/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C > new file mode 100644 > index 00000000000..22be880216d > --- /dev/null > +++ b/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C > @@ -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]]; > +} > diff --git a/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C b/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C > new file mode 100644 > index 00000000000..aa5f14c8572 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C > @@ -0,0 +1,8 @@ > +// PR c++/115757 > +// { dg-additional-options "-fmodules-ts -Wunused" } > + > +import test; > + > +int main() { > + foo(0); > +} > diff --git a/gcc/tree.h b/gcc/tree.h > index 28e8e71b036..5dcbb2fb5dd 100644 > --- a/gcc/tree.h > +++ b/gcc/tree.h > @@ -6929,6 +6929,8 @@ extern bool warning_suppressed_at (location_t, opt_code = all_warnings); > at a location to disabled by default. */ > extern bool suppress_warning_at (location_t, opt_code = all_warnings, > 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. */ > 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. */ > 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 > deallocated if FNDECL is a deallocation function or an out-of-bounds > value if it isn't. */ > diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc > index 08a0bb0e7d5..11ca5db69c3 100644 > --- a/gcc/warning-control.cc > +++ b/gcc/warning-control.cc > @@ -256,3 +256,29 @@ copy_warning (gimple *to, const gimple *from) > return; > 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); > +}
On Tue, 23 Jul 2024, Jason Merrill wrote: > On 7/7/24 12:39 AM, Nathaniel Shead wrote: > > Bootstrapped on x86_64-pc-linux-gnu, successfully regtested modules.exp; > > OK for trunk if full regtest passes? > > Patrick, I assume this change won't mess with your streaming optimizations? Should be fine, those optimizations are currently confined to tree_node_bools where we stream many consecutive bools (and so we want to avoid conditionally streaming a bit, so that the bit buffer position of each streamed bit is statically known). I don't think the technique can really apply to core_vals since it streams mostly trees. > > OK with Patrick's approval or on Friday, whichever comes first. > > > -- >8 -- > > > > 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> > > --- > > gcc/cp/module.cc | 12 +++++++++ > > gcc/diagnostic-spec.cc | 21 ++++++++++++++++ > > gcc/diagnostic-spec.h | 7 ++++++ > > gcc/testsuite/g++.dg/modules/warn-spec-1_a.C | 10 ++++++++ > > gcc/testsuite/g++.dg/modules/warn-spec-1_b.C | 8 ++++++ > > gcc/tree.h | 9 +++++++ > > gcc/warning-control.cc | 26 ++++++++++++++++++++ > > 7 files changed, 93 insertions(+) > > create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-1_a.C > > create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-1_b.C > > > > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc > > index dc5d046f04d..0f9a689dbec 100644 > > --- a/gcc/cp/module.cc > > +++ b/gcc/cp/module.cc > > @@ -6000,6 +6000,10 @@ trees_out::core_vals (tree t) > > if (state) > > 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)) > > @@ -6113,6 +6117,10 @@ trees_out::core_vals (tree t) > > if (state) > > 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 > > bunch of unscoped parms on its first operand. It's safer to > > 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 > > and thus lose all location information. */ > > 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)) > > @@ -6654,6 +6664,8 @@ trees_in::core_vals (tree t) > > if (CODE_CONTAINS_STRUCT (code, TS_EXP)) > > { > > 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; > > for (unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t) > > diff --git a/gcc/diagnostic-spec.cc b/gcc/diagnostic-spec.cc > > index 996ad6b273a..addaf089f03 100644 > > --- a/gcc/diagnostic-spec.cc > > +++ b/gcc/diagnostic-spec.cc > > @@ -179,6 +179,27 @@ suppress_warning_at (location_t loc, opt_code opt /* = > > all_warnings */, > > 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. */ > > void > > diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h > > index 22d4c067158..0b155a5cde3 100644 > > --- a/gcc/diagnostic-spec.h > > +++ b/gcc/diagnostic-spec.h > > @@ -56,6 +56,13 @@ public: > > 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. */ > > operator unsigned() const > > { > > diff --git a/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C > > b/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C > > new file mode 100644 > > index 00000000000..22be880216d > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C > > @@ -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]]; > > +} > > diff --git a/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C > > b/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C > > new file mode 100644 > > index 00000000000..aa5f14c8572 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C > > @@ -0,0 +1,8 @@ > > +// PR c++/115757 > > +// { dg-additional-options "-fmodules-ts -Wunused" } > > + > > +import test; > > + > > +int main() { > > + foo(0); > > +} > > diff --git a/gcc/tree.h b/gcc/tree.h > > index 28e8e71b036..5dcbb2fb5dd 100644 > > --- a/gcc/tree.h > > +++ b/gcc/tree.h > > @@ -6929,6 +6929,8 @@ extern bool warning_suppressed_at (location_t, > > opt_code = all_warnings); > > at a location to disabled by default. */ > > extern bool suppress_warning_at (location_t, opt_code = all_warnings, > > 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. */ > > 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. */ > > 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 > > deallocated if FNDECL is a deallocation function or an out-of-bounds > > value if it isn't. */ > > diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc > > index 08a0bb0e7d5..11ca5db69c3 100644 > > --- a/gcc/warning-control.cc > > +++ b/gcc/warning-control.cc > > @@ -256,3 +256,29 @@ copy_warning (gimple *to, const gimple *from) > > return; > > 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); > > +} > >
On Tue, Jul 23, 2024 at 05:14:30PM -0400, Patrick Palka wrote: > On Tue, 23 Jul 2024, Jason Merrill wrote: > > > On 7/7/24 12:39 AM, Nathaniel Shead wrote: > > > Bootstrapped on x86_64-pc-linux-gnu, successfully regtested modules.exp; > > > OK for trunk if full regtest passes? > > > > Patrick, I assume this change won't mess with your streaming optimizations? > > Should be fine, those optimizations are currently confined to > tree_node_bools where we stream many consecutive bools (and so we want > to avoid conditionally streaming a bit, so that the bit buffer position > of each streamed bit is statically known). I don't think the technique > can really apply to core_vals since it streams mostly trees. > > > > > OK with Patrick's approval or on Friday, whichever comes first. > > Thanks, pushed. > > > -- >8 -- > > > > > > 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> > > > --- > > > gcc/cp/module.cc | 12 +++++++++ > > > gcc/diagnostic-spec.cc | 21 ++++++++++++++++ > > > gcc/diagnostic-spec.h | 7 ++++++ > > > gcc/testsuite/g++.dg/modules/warn-spec-1_a.C | 10 ++++++++ > > > gcc/testsuite/g++.dg/modules/warn-spec-1_b.C | 8 ++++++ > > > gcc/tree.h | 9 +++++++ > > > gcc/warning-control.cc | 26 ++++++++++++++++++++ > > > 7 files changed, 93 insertions(+) > > > create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-1_a.C > > > create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-1_b.C > > > > > > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc > > > index dc5d046f04d..0f9a689dbec 100644 > > > --- a/gcc/cp/module.cc > > > +++ b/gcc/cp/module.cc > > > @@ -6000,6 +6000,10 @@ trees_out::core_vals (tree t) > > > if (state) > > > 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)) > > > @@ -6113,6 +6117,10 @@ trees_out::core_vals (tree t) > > > if (state) > > > 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 > > > bunch of unscoped parms on its first operand. It's safer to > > > 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 > > > and thus lose all location information. */ > > > 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)) > > > @@ -6654,6 +6664,8 @@ trees_in::core_vals (tree t) > > > if (CODE_CONTAINS_STRUCT (code, TS_EXP)) > > > { > > > 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; > > > for (unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t) > > > diff --git a/gcc/diagnostic-spec.cc b/gcc/diagnostic-spec.cc > > > index 996ad6b273a..addaf089f03 100644 > > > --- a/gcc/diagnostic-spec.cc > > > +++ b/gcc/diagnostic-spec.cc > > > @@ -179,6 +179,27 @@ suppress_warning_at (location_t loc, opt_code opt /* = > > > all_warnings */, > > > 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. */ > > > void > > > diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h > > > index 22d4c067158..0b155a5cde3 100644 > > > --- a/gcc/diagnostic-spec.h > > > +++ b/gcc/diagnostic-spec.h > > > @@ -56,6 +56,13 @@ public: > > > 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. */ > > > operator unsigned() const > > > { > > > diff --git a/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C > > > b/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C > > > new file mode 100644 > > > index 00000000000..22be880216d > > > --- /dev/null > > > +++ b/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C > > > @@ -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]]; > > > +} > > > diff --git a/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C > > > b/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C > > > new file mode 100644 > > > index 00000000000..aa5f14c8572 > > > --- /dev/null > > > +++ b/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C > > > @@ -0,0 +1,8 @@ > > > +// PR c++/115757 > > > +// { dg-additional-options "-fmodules-ts -Wunused" } > > > + > > > +import test; > > > + > > > +int main() { > > > + foo(0); > > > +} > > > diff --git a/gcc/tree.h b/gcc/tree.h > > > index 28e8e71b036..5dcbb2fb5dd 100644 > > > --- a/gcc/tree.h > > > +++ b/gcc/tree.h > > > @@ -6929,6 +6929,8 @@ extern bool warning_suppressed_at (location_t, > > > opt_code = all_warnings); > > > at a location to disabled by default. */ > > > extern bool suppress_warning_at (location_t, opt_code = all_warnings, > > > 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. */ > > > 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. */ > > > 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 > > > deallocated if FNDECL is a deallocation function or an out-of-bounds > > > value if it isn't. */ > > > diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc > > > index 08a0bb0e7d5..11ca5db69c3 100644 > > > --- a/gcc/warning-control.cc > > > +++ b/gcc/warning-control.cc > > > @@ -256,3 +256,29 @@ copy_warning (gimple *to, const gimple *from) > > > return; > > > 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); > > > +} > > > > >
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index dc5d046f04d..0f9a689dbec 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -6000,6 +6000,10 @@ trees_out::core_vals (tree t) if (state) 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)) @@ -6113,6 +6117,10 @@ trees_out::core_vals (tree t) if (state) 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 bunch of unscoped parms on its first operand. It's safer to 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 and thus lose all location information. */ 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)) @@ -6654,6 +6664,8 @@ trees_in::core_vals (tree t) if (CODE_CONTAINS_STRUCT (code, TS_EXP)) { 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; for (unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t) diff --git a/gcc/diagnostic-spec.cc b/gcc/diagnostic-spec.cc index 996ad6b273a..addaf089f03 100644 --- a/gcc/diagnostic-spec.cc +++ b/gcc/diagnostic-spec.cc @@ -179,6 +179,27 @@ suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */, 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. */ void diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h index 22d4c067158..0b155a5cde3 100644 --- a/gcc/diagnostic-spec.h +++ b/gcc/diagnostic-spec.h @@ -56,6 +56,13 @@ public: 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. */ operator unsigned() const { diff --git a/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C b/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C new file mode 100644 index 00000000000..22be880216d --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/warn-spec-1_a.C @@ -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]]; +} diff --git a/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C b/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C new file mode 100644 index 00000000000..aa5f14c8572 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/warn-spec-1_b.C @@ -0,0 +1,8 @@ +// PR c++/115757 +// { dg-additional-options "-fmodules-ts -Wunused" } + +import test; + +int main() { + foo(0); +} diff --git a/gcc/tree.h b/gcc/tree.h index 28e8e71b036..5dcbb2fb5dd 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -6929,6 +6929,8 @@ extern bool warning_suppressed_at (location_t, opt_code = all_warnings); at a location to disabled by default. */ extern bool suppress_warning_at (location_t, opt_code = all_warnings, 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. */ 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. */ 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 deallocated if FNDECL is a deallocation function or an out-of-bounds value if it isn't. */ diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc index 08a0bb0e7d5..11ca5db69c3 100644 --- a/gcc/warning-control.cc +++ b/gcc/warning-control.cc @@ -256,3 +256,29 @@ copy_warning (gimple *to, const gimple *from) return; 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); +}
Bootstrapped on x86_64-pc-linux-gnu, successfully regtested modules.exp; OK for trunk if full regtest passes? -- >8 -- 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> --- gcc/cp/module.cc | 12 +++++++++ gcc/diagnostic-spec.cc | 21 ++++++++++++++++ gcc/diagnostic-spec.h | 7 ++++++ gcc/testsuite/g++.dg/modules/warn-spec-1_a.C | 10 ++++++++ gcc/testsuite/g++.dg/modules/warn-spec-1_b.C | 8 ++++++ gcc/tree.h | 9 +++++++ gcc/warning-control.cc | 26 ++++++++++++++++++++ 7 files changed, 93 insertions(+) create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-1_a.C create mode 100644 gcc/testsuite/g++.dg/modules/warn-spec-1_b.C