]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/modules: Stream warning suppressions [PR115757]
authorNathaniel Shead <nathanieloshead@gmail.com>
Sun, 7 Jul 2024 03:56:25 +0000 (13:56 +1000)
committerNathaniel Shead <nathanieloshead@gmail.com>
Fri, 26 Jul 2024 04:55:36 +0000 (14:55 +1000)
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
gcc/diagnostic-spec.cc
gcc/diagnostic-spec.h
gcc/testsuite/g++.dg/modules/warn-spec-1_a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/warn-spec-1_b.C [new file with mode: 0644]
gcc/tree.h
gcc/warning-control.cc

index 69764fd772d3756fac081de7527cb1e6e54d9982..d1607a06757551008dace2f3135bcabb746ce6ef 100644 (file)
@@ -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)
index 996ad6b273aab5063d9a45499ba90d54e81afa17..addaf089f035f55d78acb953bbb935a3c830d75b 100644 (file)
@@ -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
index 22d4c0671584cf64b95cc4c5449f615d8a3ccee6..0b155a5cde3faca70692754c086accdee76c6351 100644 (file)
@@ -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 (file)
index 0000000..22be880
--- /dev/null
@@ -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 (file)
index 0000000..aa5f14c
--- /dev/null
@@ -0,0 +1,8 @@
+// PR c++/115757
+// { dg-additional-options "-fmodules-ts -Wunused" }
+
+import test;
+
+int main() {
+  foo(0);
+}
index 28e8e71b036f78b0b5fc570e37764a23badfb66a..5dcbb2fb5dd65a7fb830f23aa7a6148f563c4e4c 100644 (file)
@@ -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.  */
index 08a0bb0e7d5b84ce4d059c32fbd1a9e5c94368f5..11ca5db69c32f033f6c07071aaff5a388e73c691 100644 (file)
@@ -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);
+}