public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/11] warning control by group and location (PR 74765)
@ 2021-05-24 22:02 Martin Sebor
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
                   ` (2 more replies)
  0 siblings, 3 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:02 UTC (permalink / raw)
  To: gcc-patches

Having just one bit control whether an expression or statement should
be allowed to trigger warnings has been a source of bug reports about
false negatives for years.  PR 74765 has a representative test case
that shows how by setting the bit to avoid -Wparentheses the C++ front
end also ends up preventing valid -Wuninitialized in the middle end,
but there are other such reports for C (e.g., PR 74762) as well as
the middle end.

This patch series solves the problem by associating an expression
(whether a tree node or a GIMPLE statement) with more than one such
bit through its location.  Each new bit in the mapping corresponds
to a group of warnings (e.g., lexical, access, etc.), and each
location may be associated with a simple bitmap with one bit for
each group.  The initial groups are mostly ad hoc and should be
refined over time.  The rare expressions that have no location
continue to have just one bit[1].

The first patch introduces three new APIs without making use of them
in existing code:

   bool get_no_warning (..., int option);
   void set_no_warning (..., int option, ...);
   void copy_no_warning (...);

Subsequent patches then replace invocations of the TREE_NO_WARNING()
macro and the gimple_no_warning_p() and gimple_set_no_warning()
functions throughout GCC with those and remove the legacy APIs to
keep them from being accidentally reintroduced along with the problem.
These are mostly mechanical changes, except that most of the new
invocations also specify the option whose disposition to query for
the expression or location, or which to enable or disable[2].
The last function, copy_no_warning(), copies the disposition from
one expression or location to another.

A couple of design choices might be helpful to explain:

First, introducing "warning groups" rather than controlling each
individual warning is motivated by a) the fact that the latter
would make avoiding redundant warnings for related problems
cumbersome (e.g., after issuing a -Warray-bounds we want to
suppress -Wstringop-overflow as well -Wstringop-overread for
the same access and vice versa), and b) simplicity and efficiency
of the implementation (mapping each option would require a more
complex data structure like a bitmap).

Second, using location_t to associate expressions/statements with
the warning groups also turns out to be more useful in practice
than a direct association between a tree or gimple*, and also
simplifies managing the data structure.  Trees and gimple* come
and go across passes, and maintaining a mapping for them that
accounts for the possibility of them being garbage-collected
and the same addresses reused is less than straightforward.

Martin

[1] My expectation is to work toward providing locations for all
expressions/statements, even if it's the opening or closing brace
of the function they're used in.)

[2] A number of {get,set}_no_warning() calls introduced by the patch
don't provide an option argument and query or set just the one bit in
the expression/statement.  Some of these may be correct as they are,
but others could be refined to also specify an option.  I can do that
in a follow-up patch if someone helps me find the right option.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 1/11] introduce xxx_no_warning APIs
  2021-05-24 22:02 [PATCH 0/11] warning control by group and location (PR 74765) Martin Sebor
@ 2021-05-24 22:07 ` Martin Sebor
  2021-05-24 22:09   ` [PATCH 2/11] use xxx_no_warning APIs in Ada Martin Sebor
                     ` (9 more replies)
  2021-05-24 23:08 ` [PATCH 0/11] warning control by group and location (PR 74765) David Malcolm
  2021-05-30  2:06 ` [PATCH 0/11] " Jeff Law
  2 siblings, 10 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:07 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm, Martin Sebor

[-- Attachment #1: Type: text/plain, Size: 430 bytes --]

The attached patch introduces the get_no_warning(), set_no_warning(),
and copy_no_warning() APIs without making use of them in the rest of
GCC.  They are in three files:

   diagnostic-spec.{h,c}: Location-centric overloads.
   warning-control.cc: Tree- and gimple*-centric overloads.

The location-centric overloads are suitable to use from the diagnostic
subsystem.  The rest can be used from the front ends and the middle end.

[-- Attachment #2: gcc-no-warning-1.diff --]
[-- Type: text/x-patch, Size: 16468 bytes --]

Add support for per-location warning groups.

gcc/ChangeLog:

	* Makefile.in (OBJS-libcommon): Add diagnostic-spec.o.
	* gengtype.c (open_base_files): Add diagnostic-spec.h.
	* diagnostic-spec.c: New file.
	* diagnostic-spec.h: New file.
	* warning-control.cc: New file.

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 1164554e6d6..b7bbcb60051 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1696,6 +1696,7 @@ OBJS = \
 	vmsdbgout.o \
 	vr-values.o \
 	vtable-verify.o \
+	warning-control.o \
 	web.o \
 	wide-int.o \
 	wide-int-print.o \
@@ -1707,8 +1708,8 @@ OBJS = \
 
 # Objects in libcommon.a, potentially used by all host binaries and with
 # no target dependencies.
-OBJS-libcommon = diagnostic.o diagnostic-color.o diagnostic-show-locus.o \
-	diagnostic-format-json.o json.o \
+OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
+	diagnostic-show-locus.o diagnostic-format-json.o json.o \
 	edit-context.o \
 	pretty-print.o intl.o \
 	sbitmap.o \
@@ -2648,6 +2649,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/ipa-modref.h $(srcdir)/ipa-modref.c \
   $(srcdir)/ipa-modref-tree.h \
   $(srcdir)/signop.h \
+  $(srcdir)/diagnostic-spec.h $(srcdir)/diagnostic-spec.c \
   $(srcdir)/dwarf2out.h \
   $(srcdir)/dwarf2asm.c \
   $(srcdir)/dwarf2cfi.c \
diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
new file mode 100644
index 00000000000..582ae3f3fe2
--- /dev/null
+++ b/gcc/diagnostic-spec.c
@@ -0,0 +1,172 @@
+/* Functions to enable and disable individual warnings on an expression
+   and statement basis.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   Contributed by Martin Sebor <msebor@redhat.com>
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "bitmap.h"
+#include "tree.h"
+#include "cgraph.h"
+#include "hash-map.h"
+#include "diagnostic-spec.h"
+#include "pretty-print.h"
+
+/* Initialize *THIS from warning option OPT.  */
+
+nowarn_spec_t::nowarn_spec_t (int opt)
+{
+  /* Create a very simple mapping based on testing and experience.
+     It should become more refined with time. */
+  switch (opt)
+    {
+    case 0:
+    case -1:
+      bits = opt;
+      break;
+
+      /* Flow-sensitive warnings about pointer problems issued by both
+	 front ends and the middle end.  */
+    case OPT_Waddress:
+    case OPT_Wnonnull:
+      bits = NW_NONNULL;
+      break;
+
+      /* Flow-sensitive warnings about arithmetic overflow issued by both
+	 front ends and the middle end.  */
+    case OPT_Woverflow:
+    case OPT_Wshift_count_negative:
+    case OPT_Wshift_count_overflow:
+    case OPT_Wstrict_overflow:
+      bits = NW_VFLOW;
+      break;
+
+      /* Lexical warnings issued by front ends.  */
+    case OPT_Wabi:
+    case OPT_Wlogical_op:
+    case OPT_Wparentheses:
+    case OPT_Wreturn_type:
+    case OPT_Wsizeof_array_div:
+    case OPT_Wstrict_aliasing:
+    case OPT_Wunused:
+    case OPT_Wunused_function:
+    case OPT_Wunused_but_set_variable:
+    case OPT_Wunused_variable:
+    case OPT_Wunused_but_set_parameter:
+      bits = NW_LEXICAL;
+      break;
+
+      /* Access warning group.  */
+    case OPT_Warray_bounds:
+    case OPT_Warray_bounds_:
+    case OPT_Wformat_overflow_:
+    case OPT_Wformat_truncation_:
+    case OPT_Wrestrict:
+    case OPT_Wstrict_aliasing_:
+    case OPT_Wstringop_overflow_:
+    case OPT_Wstringop_overread:
+    case OPT_Wstringop_truncation:
+      bits = NW_ACCESS;
+      break;
+
+      /* Initialization warning group.  */
+    case OPT_Winit_self:
+    case OPT_Wuninitialized:
+    case OPT_Wmaybe_uninitialized:
+	bits = NW_UNINIT;
+      break;
+
+    default:
+      /* A catchall group for everything else.  */
+      bits = NW_OTHER;
+    }
+}
+
+/* Map from location to its no-warning disposition.  */
+
+GTY(()) xint_hash_map_t *nowarn_map;
+
+/* Return the no-warning disposition for location LOC and option OPT
+   or for all/any otions by default.  */
+
+bool
+get_no_warning (location_t loc, int opt /* = -1 */)
+{
+  if (!nowarn_map)
+    return false;
+
+  if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
+    {
+      const nowarn_spec_t optspec (opt);
+      return *pspec & optspec;
+    }
+
+  return false;
+}
+
+/* Set the no-warning disposition for location LOC and option OPT when
+   DIS is true, or clear it when it's false.  Return true if LOC has any
+   warnings disabled at the end of processing.  */
+
+bool
+set_no_warning (location_t loc, int opt /* = -1 */, bool dis /* = true */)
+{
+  const nowarn_spec_t optspec (dis ? opt : 0);
+
+  if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
+    {
+      if (dis)
+	{
+	  *pspec |= optspec;
+	  return true;
+	}
+
+      *pspec &= optspec;
+      if (*pspec)
+	return true;
+
+      nowarn_map->remove (loc);
+      return false;
+    }
+
+  if (!dis)
+    return false;
+
+  if (!nowarn_map)
+    nowarn_map = xint_hash_map_t::create_ggc (32);
+
+  nowarn_map->put (loc, optspec);
+  return true;
+}
+
+/* Copy the no-warning disposition from one location to another.  */
+
+void
+copy_no_warning (location_t to, location_t from)
+{
+  if (!nowarn_map)
+    return;
+
+  if (nowarn_spec_t *pspec = nowarn_map->get (from))
+    nowarn_map->put (to, *pspec);
+  else
+    nowarn_map->remove (to);
+}
diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
new file mode 100644
index 00000000000..e0c02753923
--- /dev/null
+++ b/gcc/diagnostic-spec.h
@@ -0,0 +1,140 @@
+/* Language-independent APIs to enable/disable per-location warnings.
+
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   Contributed by Martin Sebor <msebor@redhat.com>
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef DIAGNOSTIC_SPEC_H_INCLUDED
+#define DIAGNOSTIC_SPEC_H_INCLUDED
+
+#include "hash-map.h"
+
+/* A "bitset" of warning groups.  */
+
+struct nowarn_spec_t
+{
+  enum
+    {
+     /* Middle end warnings about invalid accesses.  */
+     NW_ACCESS = 1 << 0,
+     /* Front end/lexical warnings.  */
+     NW_LEXICAL = 1 << 1,
+     /* Warnings about null pointers.  */
+     NW_NONNULL = 1 << 2,
+     /* Warnings about uninitialized reads.  */
+     NW_UNINIT = 1 << 3,
+     /* Warnings about arithmetic overflow.  */
+     NW_VFLOW = 1 << 4,
+     /* All other unclassified warnings.  */
+     NW_OTHER = 1 << 5,
+     /* All groups of warnings.  */
+     NW_ALL = (NW_ACCESS | NW_LEXICAL | NW_NONNULL
+	       | NW_UNINIT | NW_VFLOW | NW_OTHER)
+   };
+
+  nowarn_spec_t (): bits () { }
+
+  nowarn_spec_t (int);
+
+  /* Return the raw bitset.  */
+  operator unsigned() const
+  {
+    return bits;
+  }
+
+  /* Return true if the bitset is clear.  */
+  bool operator!() const
+  {
+    return !bits;
+  }
+
+  /* Return the inverse of the bitset.  */
+  nowarn_spec_t operator~() const
+  {
+    nowarn_spec_t res (*this);
+    res.bits &= ~NW_ALL;
+    return res;
+  }
+
+  /* Set *THIS to the bitwise OR of *THIS and RHS.  */
+  nowarn_spec_t& operator|= (const nowarn_spec_t &rhs)
+  {
+    bits |= rhs.bits;
+    return *this;
+  }
+
+  /* Set *THIS to the bitwise AND of *THIS and RHS.  */
+  nowarn_spec_t& operator&= (const nowarn_spec_t &rhs)
+  {
+    bits &= rhs.bits;
+    return *this;
+  }
+
+  /* Set *THIS to the bitwise exclusive OR of *THIS and RHS.  */
+  nowarn_spec_t& operator^= (const nowarn_spec_t &rhs)
+  {
+    bits ^= rhs.bits;
+    return *this;
+  }
+
+private:
+  /* Bitset of warning groups.  */
+  unsigned bits;
+};
+
+/* Return the bitwise OR of LHS and RHS.  */
+
+inline nowarn_spec_t
+operator| (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return nowarn_spec_t (lhs) |= rhs;
+}
+
+/* Return the bitwise AND of LHS and RHS.  */
+
+inline nowarn_spec_t
+operator& (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return nowarn_spec_t (lhs) &= rhs;
+}
+
+/* Return true if LHS is equal RHS.  */
+
+inline bool
+operator== (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return static_cast<unsigned>(lhs) == static_cast<unsigned>(rhs);
+}
+
+/* Return true if LHS is not equal RHS.  */
+
+inline bool
+operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return !(lhs == rhs);
+}
+
+typedef location_t key_type_t;
+typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
+typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
+
+/* A mapping from the location of an expression to the warning spec
+   set for it.  */
+extern GTY(()) xint_hash_map_t *nowarn_map;
+
+#endif // DIAGNOSTIC_SPEC_H_INCLUDED
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index b94e2f126ec..c1fa6d35c87 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1727,7 +1727,7 @@ open_base_files (void)
       "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
       "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h",
       "omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h", "symtab-thunks.h",
-      "symtab-clones.h",
+      "symtab-clones.h", "diagnostic-spec.h",
       NULL
     };
     const char *const *ifp;
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
new file mode 100644
index 00000000000..73147b618ad
--- /dev/null
+++ b/gcc/warning-control.cc
@@ -0,0 +1,230 @@
+/* Functions to enable and disable individual warnings on an expression
+   and statement basis.
+
+   Copyright (C) 2021 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "bitmap.h"
+#include "tree.h"
+#include "gimple.h"
+#include "cgraph.h"
+#include "hash-map.h"
+#include "diagnostic-spec.h"
+
+/* Return the no-warning bit for EXPR.  */
+
+static inline bool
+get_no_warning_bit (const_tree expr)
+{
+  return expr->base.nowarning_flag;
+}
+
+/* Return the no-warning bit for statement STMT.  */
+
+static inline bool
+get_no_warning_bit (const gimple *stmt)
+{
+  return stmt->no_warning;
+}
+
+/* Set the no-warning bit for EXPR to VALUE.  */
+
+static inline void
+set_no_warning_bit (tree expr, bool value)
+{
+  expr->base.nowarning_flag = value;
+}
+
+/* Set the no-warning bit for statement STMT to VALUE.  */
+
+static inline void
+set_no_warning_bit (gimple *stmt, bool value)
+{
+  stmt->no_warning = value;
+}
+
+/* Return EXPR location of zero.  */
+
+static inline key_type_t
+convert_to_key (const_tree expr)
+{
+  if (DECL_P (expr))
+    return DECL_SOURCE_LOCATION (expr);
+  if (EXPR_P (expr))
+    return EXPR_LOCATION (expr);
+  return 0;
+}
+
+/* Return STMT location (may be zero).  */
+
+static inline key_type_t
+convert_to_key (const gimple *stmt)
+{
+  return gimple_location (stmt);
+}
+
+/* Return the no-warning bitmap for decl/expression EXPR.  */
+
+static nowarn_spec_t*
+get_nowarn_spec (const_tree expr)
+{
+  const key_type_t key = convert_to_key (expr);
+
+  if (!get_no_warning_bit (expr) || !key)
+    return NULL;
+
+  return nowarn_map ? nowarn_map->get (key) : NULL;
+}
+
+/* Return the no-warning bitmap for stateemt STMT.  */
+
+static nowarn_spec_t*
+get_nowarn_spec (const gimple *stmt)
+{
+  const key_type_t key = convert_to_key (stmt);
+
+  if (!get_no_warning_bit (stmt))
+    return NULL;
+
+  return nowarn_map ? nowarn_map->get (key) : NULL;
+}
+
+/* Return true if warning OPT is enabled for decl/expression EXPR.
+   The wildcard OPT of -1 tests for all warnings being disabled.  */
+
+bool
+get_no_warning (const_tree expr, int opt /* = -1 */)
+{
+  const nowarn_spec_t *spec = get_nowarn_spec (expr);
+
+  if (!spec)
+    return get_no_warning_bit (expr);
+
+  nowarn_spec_t optspec (opt);
+  bool dis = *spec & optspec;
+  gcc_assert (get_no_warning_bit (expr) || !dis);
+  return dis;
+}
+
+/* Return true if warning OPT is enabled for statement STMT.
+   The wildcard OPT of -1 tests for all warnings being disabled.  */
+
+bool
+get_no_warning (const gimple *stmt, int opt /* = -1 */)
+{
+  const nowarn_spec_t *spec = get_nowarn_spec (stmt);
+
+  if (!spec)
+    /* Fall back on the single no-warning bit.  */
+    return get_no_warning_bit (stmt);
+
+  nowarn_spec_t optspec (opt);
+  bool dis = *spec & optspec;
+  gcc_assert (get_no_warning_bit (stmt) || !dis);
+  return dis;
+}
+
+/* Enable, or by default disable, a warning for the expression.
+   The wildcard OPT of -1 controls all warnings.  */
+
+void
+set_no_warning (tree expr, int opt /* = -1 */, bool dis /* = true */)
+{
+  const key_type_t key = convert_to_key (expr);
+
+  dis = set_no_warning (key, opt, dis) || dis;
+  set_no_warning_bit (expr, dis);
+}
+
+/* Enable, or by default disable, a warning for the statement STMT.
+   The wildcard OPT of -1 controls all warnings.  */
+
+void
+set_no_warning (gimple *stmt, int opt /* = -1 */, bool dis /* = true */)
+{
+  const key_type_t key = convert_to_key (stmt);
+  const nowarn_spec_t optspec (opt);
+  dis = set_no_warning (key, opt, dis) || dis;
+  set_no_warning_bit (stmt, dis);
+}
+
+/* Copy the warning disposition mapping between an expression and/or
+   a statement.  */
+
+template <class ToType, class FromType>
+void copy_no_warning (ToType to, FromType from)
+{
+  const key_type_t to_key = convert_to_key (to);
+
+  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
+    {
+      /* If there's an entry in the map the no-warning bit must be set.  */
+      gcc_assert (get_no_warning_bit (from));
+
+      if (!nowarn_map)
+	nowarn_map = xint_hash_map_t::create_ggc (32);
+
+      nowarn_map->put (to_key, *from_map);
+      set_no_warning_bit (to, true);
+    }
+  else
+    {
+      if (nowarn_map)
+	nowarn_map->remove (to_key);
+
+      /* The no-warning bit might be set even if there's no entry
+	 in the map.  */
+      set_no_warning_bit (to, get_no_warning_bit (from));
+    }
+}
+
+/* Copy the warning disposition mapping from one expression to another.  */
+
+void
+copy_no_warning (tree to, const_tree from)
+{
+  copy_no_warning<tree, const_tree>(to, from);
+}
+
+/* Copy the warning disposition mapping from a statement to an expression.  */
+
+void
+copy_no_warning (tree to, const gimple *from)
+{
+  copy_no_warning<tree, const gimple *>(to, from);
+}
+
+/* Copy the warning disposition mapping from an expression to a statement.  */
+
+void
+copy_no_warning (gimple *to, const_tree from)
+{
+  copy_no_warning<gimple *, const_tree>(to, from);
+}
+
+/* Copy the warning disposition mapping from one statement to another.  */
+
+void
+copy_no_warning (gimple *to, const gimple *from)
+{
+  copy_no_warning<gimple *, const gimple *>(to, from);
+}

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 2/11] use xxx_no_warning APIs in Ada
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
@ 2021-05-24 22:09   ` Martin Sebor
  2021-05-25  8:59     ` Eric Botcazou
  2021-05-24 22:10   ` [PATCH 3/11] use xxx_no_warning APIs in C Martin Sebor
                     ` (8 subsequent siblings)
  9 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:09 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 45 bytes --]

[PATCH 2/11] use xxx_no_warning APIs in Ada.

[-- Attachment #2: gcc-no-warning-ada.diff --]
[-- Type: text/x-patch, Size: 1813 bytes --]

Add support for per-location warning groups.

gcc/ada/ChangeLog:

	* gcc-interface/trans.c (Handled_Sequence_Of_Statements_to_gnu):
	Replace TREE_NO_WARNING with set_no_warning.
	(gnat_gimplify_expr): Same.
	* gcc-interface/utils.c (gnat_pushdecl): Same.

diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 9aeaf038118..63d662669ef 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -5357,7 +5357,7 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
 	 because of the unstructured form of EH used by fe_sjlj_eh, there
 	 might be forward edges going to __builtin_setjmp receivers on which
 	 it is uninitialized, although they will never be actually taken.  */
-      TREE_NO_WARNING (gnu_jmpsave_decl) = 1;
+      set_no_warning (gnu_jmpsave_decl, OPT_Wuninitialized);
       gnu_jmpbuf_decl
 	= create_var_decl (get_identifier ("JMP_BUF"), NULL_TREE,
 			   jmpbuf_type,
@@ -8792,7 +8792,7 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p,
       else
 	{
 	  *expr_p = create_tmp_var (type, NULL);
-	  TREE_NO_WARNING (*expr_p) = 1;
+	  set_no_warning (*expr_p);
 	}
 
       gimplify_and_add (TREE_OPERAND (expr, 0), pre_p);
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 80a4160adf3..7d08ae9193a 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -836,7 +836,7 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
   if (!deferred_decl_context)
     DECL_CONTEXT (decl) = context;
 
-  TREE_NO_WARNING (decl) = (No (gnat_node) || Warnings_Off (gnat_node));
+  set_no_warning (decl, (No (gnat_node) || Warnings_Off (gnat_node)));
 
   /* Set the location of DECL and emit a declaration for it.  */
   if (Present (gnat_node) && !renaming_from_instantiation_p (gnat_node))

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 3/11] use xxx_no_warning APIs in C
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
  2021-05-24 22:09   ` [PATCH 2/11] use xxx_no_warning APIs in Ada Martin Sebor
@ 2021-05-24 22:10   ` Martin Sebor
  2021-05-24 22:11   ` [PATCH 4/11] use xxx_no_warning APIs in C family Martin Sebor
                     ` (7 subsequent siblings)
  9 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:10 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 76 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the C
front end.

[-- Attachment #2: gcc-no-warning-c.diff --]
[-- Type: text/x-patch, Size: 12285 bytes --]

Add support for per-location warning groups.

gcc/c/ChangeLog:

	* c-decl.c (pop_scope): Replace direct uses of TREE_NO_WARNING with
	get_no_warning, set_no_warning, and copy_no_warning.
	(diagnose_mismatched_decls): Same.
	(duplicate_decls): Same.
	(grokdeclarator): Same.
	(finish_function): Same.
	(c_write_global_declarations_1): Same.
	* c-fold.c (c_fully_fold_internal): Same.
	* c-parser.c (c_parser_expr_no_commas): Same.
	(c_parser_postfix_expression): Same.
	* c-typeck.c (array_to_pointer_conversion): Same.
	(function_to_pointer_conversion): Same.
	(default_function_array_conversion): Same.
	(convert_lvalue_to_rvalue): Same.
	(default_conversion): Same.
	(build_indirect_ref): Same.
	(build_function_call_vec): Same.
	(build_atomic_assign): Same.
	(build_unary_op): Same.
	(c_finish_return): Same.
	(emit_side_effect_warnings): Same.
	(c_finish_stmt_expr): Same.
	(c_omp_clause_copy_ctor): Same.

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 53b2b5b637d..800f08ed7b9 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -1295,7 +1295,7 @@ pop_scope (void)
 	case VAR_DECL:
 	  /* Warnings for unused variables.  */
 	  if ((!TREE_USED (p) || !DECL_READ_P (p))
-	      && !TREE_NO_WARNING (p)
+	      && !get_no_warning (p, OPT_Wunused_but_set_variable)
 	      && !DECL_IN_SYSTEM_HEADER (p)
 	      && DECL_NAME (p)
 	      && !DECL_ARTIFICIAL (p)
@@ -2159,8 +2159,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
       if (DECL_IN_SYSTEM_HEADER (newdecl)
 	  || DECL_IN_SYSTEM_HEADER (olddecl)
-	  || TREE_NO_WARNING (newdecl)
-	  || TREE_NO_WARNING (olddecl))
+	  || get_no_warning (newdecl, OPT_Wpedantic)
+	  || get_no_warning (olddecl, OPT_Wpedantic))
 	return true;  /* Allow OLDDECL to continue in use.  */
 
       if (variably_modified_type_p (newtype, NULL))
@@ -2953,7 +2953,7 @@ duplicate_decls (tree newdecl, tree olddecl)
   if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
     {
       /* Avoid `unused variable' and other warnings for OLDDECL.  */
-      TREE_NO_WARNING (olddecl) = 1;
+      set_no_warning (olddecl, OPT_Wunused);
       return false;
     }
 
@@ -7540,10 +7540,7 @@ grokdeclarator (const struct c_declarator *declarator,
 			   FIELD_DECL, declarator->u.id.id, type);
 	DECL_NONADDRESSABLE_P (decl) = bitfield;
 	if (bitfield && !declarator->u.id.id)
-	  {
-	    TREE_NO_WARNING (decl) = 1;
-	    DECL_PADDING_P (decl) = 1;
-	  }
+	  DECL_PADDING_P (decl) = 1;
 
 	if (size_varies)
 	  C_DECL_VARIABLE_SIZE (decl) = 1;
@@ -10225,7 +10222,7 @@ finish_function (location_t end_loc)
       && targetm.warn_func_return (fndecl)
       && warning (OPT_Wreturn_type,
 		  "no return statement in function returning non-void"))
-    TREE_NO_WARNING (fndecl) = 1;
+    set_no_warning (fndecl, OPT_Wreturn_type);
 
   /* Complain about parameters that are only set, but never otherwise used.  */
   if (warn_unused_but_set_parameter)
@@ -10240,7 +10237,7 @@ finish_function (location_t end_loc)
 	    && !DECL_READ_P (decl)
 	    && DECL_NAME (decl)
 	    && !DECL_ARTIFICIAL (decl)
-	    && !TREE_NO_WARNING (decl))
+	    && !get_no_warning (decl, OPT_Wunused_but_set_parameter))
 	  warning_at (DECL_SOURCE_LOCATION (decl),
 		      OPT_Wunused_but_set_parameter,
 		      "parameter %qD set but not used", decl);
@@ -12106,19 +12103,20 @@ c_write_global_declarations_1 (tree globals)
 	{
 	  if (C_DECL_USED (decl))
 	    {
+	      /* TODO: Add OPT_Wundefined-inline.  */
 	      if (pedwarn (input_location, 0, "%q+F used but never defined",
 			   decl))
-		TREE_NO_WARNING (decl) = 1;
+		set_no_warning (decl /* OPT_Wundefined-inline.  */);
 	    }
 	  /* For -Wunused-function warn about unused static prototypes.  */
 	  else if (warn_unused_function
 		   && ! DECL_ARTIFICIAL (decl)
-		   && ! TREE_NO_WARNING (decl))
+		   && ! get_no_warning (decl, OPT_Wunused_function))
 	    {
 	      if (warning (OPT_Wunused_function,
 			   "%q+F declared %<static%> but never defined",
 			   decl))
-		TREE_NO_WARNING (decl) = 1;
+		set_no_warning (decl, OPT_Wunused_function);
 	    }
 	}
 
diff --git a/gcc/c/c-fold.c b/gcc/c/c-fold.c
index 68c74cc1eb2..5bc90ad541b 100644
--- a/gcc/c/c-fold.c
+++ b/gcc/c/c-fold.c
@@ -154,7 +154,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
   tree orig_op0, orig_op1, orig_op2;
   bool op0_const = true, op1_const = true, op2_const = true;
   bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
-  bool nowarning = TREE_NO_WARNING (expr);
+  bool nowarning = get_no_warning (expr, OPT_Woverflow);
   bool unused_p;
   bool op0_lval = false;
   source_range old_range;
@@ -670,13 +670,13 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
  out:
   /* Some folding may introduce NON_LVALUE_EXPRs; all lvalue checks
      have been done by this point, so remove them again.  */
-  nowarning |= TREE_NO_WARNING (ret);
+  nowarning |= get_no_warning (ret, OPT_Woverflow);
   STRIP_TYPE_NOPS (ret);
-  if (nowarning && !TREE_NO_WARNING (ret))
+  if (nowarning && !get_no_warning (ret, OPT_Woverflow))
     {
       if (!CAN_HAVE_LOCATION_P (ret))
 	ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
-      TREE_NO_WARNING (ret) = 1;
+      set_no_warning (ret, OPT_Woverflow);
     }
   if (ret != expr)
     {
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index b9930d487fd..7c1f6840e51 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -7558,7 +7558,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
     ret.original_code = MODIFY_EXPR;
   else
     {
-      TREE_NO_WARNING (ret.value) = 1;
+      set_no_warning (ret.value, OPT_Wparentheses);
       ret.original_code = ERROR_MARK;
     }
   ret.original_type = NULL;
@@ -9085,7 +9085,7 @@ c_parser_postfix_expression (c_parser *parser)
 	  c_parser_consume_token (parser);
 	  expr = c_parser_expression (parser);
 	  if (TREE_CODE (expr.value) == MODIFY_EXPR)
-	    TREE_NO_WARNING (expr.value) = 1;
+	    set_no_warning (expr.value, OPT_Wparentheses);
 	  if (expr.original_code != C_MAYBE_CONST_EXPR
 	      && expr.original_code != SIZEOF_EXPR)
 	    expr.original_code = ERROR_MARK;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index c3b85da1125..888f0c99600 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -1911,8 +1911,7 @@ array_to_pointer_conversion (location_t loc, tree exp)
 
   STRIP_TYPE_NOPS (exp);
 
-  if (TREE_NO_WARNING (orig_exp))
-    TREE_NO_WARNING (exp) = 1;
+  copy_no_warning (exp, orig_exp);
 
   ptrtype = build_pointer_type (restype);
 
@@ -1945,8 +1944,7 @@ function_to_pointer_conversion (location_t loc, tree exp)
 
   STRIP_TYPE_NOPS (exp);
 
-  if (TREE_NO_WARNING (orig_exp))
-    TREE_NO_WARNING (exp) = 1;
+  copy_no_warning (exp, orig_exp);
 
   return build_unary_op (loc, ADDR_EXPR, exp, false);
 }
@@ -2055,8 +2053,7 @@ default_function_array_conversion (location_t loc, struct c_expr exp)
 	    exp.value = TREE_OPERAND (exp.value, 0);
 	  }
 
-	if (TREE_NO_WARNING (orig_exp))
-	  TREE_NO_WARNING (exp.value) = 1;
+	copy_no_warning (exp.value, orig_exp);
 
 	lvalue_array_p = !not_lvalue && lvalue_p (exp.value);
 	if (!flag_isoc99 && !lvalue_array_p)
@@ -2154,7 +2151,8 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
       tmp = create_tmp_var_raw (nonatomic_type);
       tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, false);
       TREE_ADDRESSABLE (tmp) = 1;
-      TREE_NO_WARNING (tmp) = 1;
+      /* Do not disable warnings for TMP even though it's artificial.
+	 -Winvalid-memory-model depends on it.  */
 
       /* Issue __atomic_load (&expr, &tmp, SEQ_CST);  */
       fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
@@ -2251,8 +2249,7 @@ default_conversion (tree exp)
   orig_exp = exp;
   STRIP_TYPE_NOPS (exp);
 
-  if (TREE_NO_WARNING (orig_exp))
-    TREE_NO_WARNING (exp) = 1;
+  copy_no_warning (exp, orig_exp);
 
   if (code == VOID_TYPE)
     {
@@ -2616,7 +2613,7 @@ build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
 	  if (warn_strict_aliasing > 2)
 	    if (strict_aliasing_warning (EXPR_LOCATION (pointer),
 					 type, TREE_OPERAND (pointer, 0)))
-	      TREE_NO_WARNING (pointer) = 1;
+	      set_no_warning (pointer, OPT_Wstrict_aliasing_);
 	}
 
       if (TREE_CODE (pointer) == ADDR_EXPR
@@ -3218,7 +3215,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
   /* If -Wnonnull warning has been diagnosed, avoid diagnosing it again
      later.  */
   if (warned_p && TREE_CODE (result) == CALL_EXPR)
-    TREE_NO_WARNING (result) = 1;
+    set_no_warning (result, OPT_Wnonnull);
 
   /* In this improbable scenario, a nested function returns a VM type.
      Create a TARGET_EXPR so that the call always has a LHS, much as
@@ -4167,7 +4164,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
 						      TYPE_UNQUALIFIED);
   val = create_tmp_var_raw (nonatomic_rhs_type);
   TREE_ADDRESSABLE (val) = 1;
-  TREE_NO_WARNING (val) = 1;
+  set_no_warning (val);
   rhs = build4 (TARGET_EXPR, nonatomic_rhs_type, val, rhs, NULL_TREE,
 		NULL_TREE);
   TREE_SIDE_EFFECTS (rhs) = 1;
@@ -4268,7 +4265,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
 
       newval = create_tmp_var_raw (nonatomic_lhs_type);
       TREE_ADDRESSABLE (newval) = 1;
-      TREE_NO_WARNING (newval) = 1;
+      set_no_warning (newval);
       rhs = build4 (TARGET_EXPR, nonatomic_lhs_type, newval, func_call,
 		    NULL_TREE, NULL_TREE);
       SET_EXPR_LOCATION (rhs, loc);
@@ -4287,12 +4284,12 @@ cas_loop:
   old = create_tmp_var_raw (nonatomic_lhs_type);
   old_addr = build_unary_op (loc, ADDR_EXPR, old, false);
   TREE_ADDRESSABLE (old) = 1;
-  TREE_NO_WARNING (old) = 1;
+  set_no_warning (old);
 
   newval = create_tmp_var_raw (nonatomic_lhs_type);
   newval_addr = build_unary_op (loc, ADDR_EXPR, newval, false);
   TREE_ADDRESSABLE (newval) = 1;
-  TREE_NO_WARNING (newval) = 1;
+  set_no_warning (newval);
 
   loop_decl = create_artificial_label (loc);
   loop_label = build1 (LABEL_EXPR, void_type_node, loop_decl);
@@ -4781,8 +4778,6 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
 	else
 	  val = build2 (code, TREE_TYPE (arg), arg, inc);
 	TREE_SIDE_EFFECTS (val) = 1;
-	if (TREE_CODE (val) != code)
-	  TREE_NO_WARNING (val) = 1;
 	ret = val;
 	goto return_build_unary_op;
       }
@@ -10941,7 +10936,8 @@ c_finish_return (location_t loc, tree retval, tree origtype)
     }
 
   ret_stmt = build_stmt (loc, RETURN_EXPR, retval);
-  TREE_NO_WARNING (ret_stmt) |= no_warning;
+  if (no_warning)
+    set_no_warning (ret_stmt, OPT_Wreturn_type);
   return add_stmt (ret_stmt);
 }
 \f
@@ -11217,7 +11213,8 @@ emit_side_effect_warnings (location_t loc, tree expr)
     ;
   else if (!TREE_SIDE_EFFECTS (expr))
     {
-      if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
+      if (!VOID_TYPE_P (TREE_TYPE (expr))
+	  && !get_no_warning (expr, OPT_Wunused_value))
 	warning_at (loc, OPT_Wunused_value, "statement with no effect");
     }
   else if (TREE_CODE (expr) == COMPOUND_EXPR)
@@ -11233,8 +11230,8 @@ emit_side_effect_warnings (location_t loc, tree expr)
       if (!TREE_SIDE_EFFECTS (r)
 	  && !VOID_TYPE_P (TREE_TYPE (r))
 	  && !CONVERT_EXPR_P (r)
-	  && !TREE_NO_WARNING (r)
-	  && !TREE_NO_WARNING (expr))
+	  && !get_no_warning (r, OPT_Wunused_value)
+	  && !get_no_warning (expr, OPT_Wunused_value))
 	warning_at (cloc, OPT_Wunused_value,
 		    "right-hand operand of comma expression has no effect");
     }
@@ -11403,7 +11400,7 @@ c_finish_stmt_expr (location_t loc, tree body)
       last = c_wrap_maybe_const (last, true);
       /* Do not warn if the return value of a statement expression is
 	 unused.  */
-      TREE_NO_WARNING (last) = 1;
+      set_no_warning (last, OPT_Wunused);
       return last;
     }
 
@@ -15368,7 +15365,7 @@ c_omp_clause_copy_ctor (tree clause, tree dst, tree src)
   tree tmp = create_tmp_var (nonatomic_type);
   tree tmp_addr = build_fold_addr_expr (tmp);
   TREE_ADDRESSABLE (tmp) = 1;
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tree src_addr = build_fold_addr_expr (src);
   tree dst_addr = build_fold_addr_expr (dst);
   tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 4/11] use xxx_no_warning APIs in C family
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
  2021-05-24 22:09   ` [PATCH 2/11] use xxx_no_warning APIs in Ada Martin Sebor
  2021-05-24 22:10   ` [PATCH 3/11] use xxx_no_warning APIs in C Martin Sebor
@ 2021-05-24 22:11   ` Martin Sebor
  2021-05-24 22:11   ` [PATCH 5/11] use xxx_no_warning APIs in C++ Martin Sebor
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:11 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 116 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the C
family common subset of the C and C++ front ends.


[-- Attachment #2: gcc-no-warning-c-family.diff --]
[-- Type: text/x-patch, Size: 4448 bytes --]

Add support for per-location warning groups.

gcc/c-family/ChangeLog:

	* c-common.c (c_wrap_maybe_const): Remove TREE_NO_WARNING.
	(c_common_truthvalue_conversion): Replace direct uses of
	TREE_NO_WARNING with get_no_warning, set_no_warning, and
	copy_no_warning.
	(check_function_arguments_recurse): Same.
	* c-gimplify.c (c_gimplify_expr): Same.
	* c-warn.c (overflow_warning): Same.
	(warn_logical_operator): Same.
	(warn_if_unused_value): Same.
	(do_warn_unused_parameter): Same.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index b7daa2e2654..a97376c5fd1 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -3236,7 +3236,6 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
 tree
 c_wrap_maybe_const (tree expr, bool non_const)
 {
-  bool nowarning = TREE_NO_WARNING (expr);
   location_t loc = EXPR_LOCATION (expr);
 
   /* This should never be called for C++.  */
@@ -3247,8 +3246,6 @@ c_wrap_maybe_const (tree expr, bool non_const)
   STRIP_TYPE_NOPS (expr);
   expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
   C_MAYBE_CONST_EXPR_NON_CONST (expr) = non_const;
-  if (nowarning)
-    TREE_NO_WARNING (expr) = 1;
   protected_set_expr_location (expr, loc);
 
   return expr;
@@ -3494,12 +3491,12 @@ c_common_truthvalue_conversion (location_t location, tree expr)
       break;
 
     case MODIFY_EXPR:
-      if (!TREE_NO_WARNING (expr)
+      if (!get_no_warning (expr, OPT_Wparentheses)
 	  && warn_parentheses
 	  && warning_at (location, OPT_Wparentheses,
 			 "suggest parentheses around assignment used as "
 			 "truth value"))
-	TREE_NO_WARNING (expr) = 1;
+	set_no_warning (expr, OPT_Wparentheses);
       break;
 
     case CONST_DECL:
@@ -5880,7 +5877,7 @@ check_function_arguments_recurse (void (*callback)
 				  void *ctx, tree param,
 				  unsigned HOST_WIDE_INT param_num)
 {
-  if (TREE_NO_WARNING (param))
+  if (get_no_warning (param))
     return;
 
   if (CONVERT_EXPR_P (param)
diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
index 39c969d8f40..8a6b36fc846 100644
--- a/gcc/c-family/c-gimplify.c
+++ b/gcc/c-family/c-gimplify.c
@@ -713,7 +713,7 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
 	  && !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
 	  && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p)) == DECL_EXPR_DECL (*expr_p))
 	  && !warn_init_self)
-	TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
+	set_no_warning (DECL_EXPR_DECL (*expr_p), OPT_Winit_self);
       break;
 
     case PREINCREMENT_EXPR:
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index c48dc2e6d24..2af2bc0a43f 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -155,7 +155,7 @@ overflow_warning (location_t loc, tree value, tree expr)
 			 value);
 
   if (warned)
-    TREE_NO_WARNING (value) = 1;
+    set_no_warning (value, OPT_Woverflow);
 }
 
 /* Helper function for walk_tree.  Unwrap C_MAYBE_CONST_EXPRs in an expression
@@ -219,7 +219,7 @@ warn_logical_operator (location_t location, enum tree_code code, tree type,
       && INTEGRAL_TYPE_P (TREE_TYPE (op_left))
       && !CONSTANT_CLASS_P (stripped_op_left)
       && TREE_CODE (stripped_op_left) != CONST_DECL
-      && !TREE_NO_WARNING (op_left)
+      && !get_no_warning (op_left, OPT_Wlogical_op)
       && TREE_CODE (op_right) == INTEGER_CST
       && !integer_zerop (op_right)
       && !integer_onep (op_right))
@@ -234,7 +234,7 @@ warn_logical_operator (location_t location, enum tree_code code, tree type,
 	  = warning_at (location, OPT_Wlogical_op,
 			"logical %<and%> applied to non-boolean constant");
       if (warned)
-	TREE_NO_WARNING (op_left) = true;
+	set_no_warning (op_left, OPT_Wlogical_op);
       return;
     }
 
@@ -588,7 +588,7 @@ bool
 warn_if_unused_value (const_tree exp, location_t locus, bool quiet)
 {
  restart:
-  if (TREE_USED (exp) || TREE_NO_WARNING (exp))
+  if (TREE_USED (exp) || get_no_warning (exp, OPT_Wunused_value))
     return false;
 
   /* Don't warn about void constructs.  This includes casting to void,
@@ -2422,7 +2422,7 @@ do_warn_unused_parameter (tree fn)
        decl; decl = DECL_CHAIN (decl))
     if (!TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
 	&& DECL_NAME (decl) && !DECL_ARTIFICIAL (decl)
-	&& !TREE_NO_WARNING (decl))
+	&& !get_no_warning (decl, OPT_Wunused_parameter))
       warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wunused_parameter,
 		  "unused parameter %qD", decl);
 }

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 5/11] use xxx_no_warning APIs in C++
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
                     ` (2 preceding siblings ...)
  2021-05-24 22:11   ` [PATCH 4/11] use xxx_no_warning APIs in C family Martin Sebor
@ 2021-05-24 22:11   ` Martin Sebor
  2021-05-24 22:12   ` [PATCH 6/11] use xxx_no_warning APIs in Fortran Martin Sebor
                     ` (5 subsequent siblings)
  9 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:11 UTC (permalink / raw)
  To: gcc-patches, Jason Merrill

[-- Attachment #1: Type: text/plain, Size: 461 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the C++
front end.  For the set/get_no_warning calls I tried to find the most
appropriate option to disable and query.  In some cases there are
helpful comments nearby that made this easy.  In other cases it was
less straightforward, and in some I didn't know.  In some of those,
disabling all warnings may be what we want, but in others we might
want to be more selective to further improve efficacy.

[-- Attachment #2: gcc-no-warning-cp.diff --]
[-- Type: text/x-patch, Size: 33617 bytes --]

Add support for per-location warning groups.

	* call.c (build_over_call): Replace direct uses of TREE_NO_WARNING
	with get_no_warning, set_no_warning, and copy_no_warning, or nothing
	if not necessary.
	(set_up_extended_ref_temp): Same.
	* class.c (layout_class_type): Same.
	* constraint.cc (constraint_satisfaction_value): Same.
	* coroutines.cc (finish_co_await_expr): Same.
	(finish_co_yield_expr): Same.
	(finish_co_return_stmt): Same.
	(build_actor_fn): Same.
	(coro_rewrite_function_body): Same.
	(morph_fn_to_coro): Same.
	* cp-gimplify.c (genericize_eh_spec_block): Same.
	(gimplify_expr_stmt): Same.
	(cp_genericize_r): Same.
	(cp_fold): Same.
	* cp-ubsan.c (cp_ubsan_instrument_vptr): Same.
	* cvt.c (cp_fold_convert): Same.
	(convert_to_void): Same.
	* decl.c (wrapup_namespace_globals): Same.
	(grokdeclarator): Same.
	(finish_function): Same.
	(require_deduced_type): Same.
	* decl2.c (no_linkage_error): Same.
	(c_parse_final_cleanups): Same.
	* except.c (expand_end_catch_block): Same.
	* init.c (build_new_1): Same.
	(build_new): Same.
	(build_vec_delete_1): Same.
	(build_vec_init): Same.
	(build_delete): Same.
	* method.c (defaultable_fn_check): Same.
	* parser.c (cp_parser_fold_expression): Same.
	(cp_parser_primary_expression): Same.
	* pt.c (push_tinst_level_loc): Same.
	(tsubst_copy): Same.
	(tsubst_omp_udr): Same.
	(tsubst_copy_and_build): Same.
	* rtti.c (build_if_nonnull): Same.
	* semantics.c (maybe_convert_cond): Same.
	(finish_return_stmt): Same.
	(finish_parenthesized_expr): Same.
	(cp_check_omp_declare_reduction): Same.
	* tree.c (build_cplus_array_type): Same.
	* typeck.c (build_ptrmemfunc_access_expr): Same.
	(cp_build_indirect_ref_1): Same.
	(cp_build_function_call_vec): Same.
	(warn_for_null_address): Same.
	(cp_build_binary_op): Same.
	(unary_complex_lvalue): Same.
	(cp_build_modify_expr): Same.
	(build_x_modify_expr): Same.
	(convert_for_assignment): Same.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4a59b97c110..2355020066a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -9437,7 +9437,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	{
 	  /* Avoid copying empty classes.  */
 	  val = build2 (COMPOUND_EXPR, type, arg, to);
-	  TREE_NO_WARNING (val) = 1;
+	  set_no_warning (val, OPT_Wunused);
 	}
       else if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
 	{
@@ -9468,7 +9468,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		      build2 (MEM_REF, array_type, arg0, alias_set),
 		      build2 (MEM_REF, array_type, arg, alias_set));
 	  val = build2 (COMPOUND_EXPR, TREE_TYPE (to), t, to);
-          TREE_NO_WARNING (val) = 1;
+          set_no_warning (val, OPT_Wunused);
 	}
 
       cp_warn_deprecated_use (fn, complain);
@@ -9542,7 +9542,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
     {
       tree c = extract_call_expr (call);
       if (TREE_CODE (c) == CALL_EXPR)
-	TREE_NO_WARNING (c) = 1;
+	set_no_warning (c /* Suppress all warnings.  */);
     }
   if (TREE_CODE (fn) == ADDR_EXPR)
     {
@@ -12491,11 +12491,11 @@ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups,
     TREE_ADDRESSABLE (var) = 1;
 
   if (TREE_CODE (decl) == FIELD_DECL
-      && extra_warnings && !TREE_NO_WARNING (decl))
+      && extra_warnings && !get_no_warning (decl))
     {
       warning (OPT_Wextra, "a temporary bound to %qD only persists "
 	       "until the constructor exits", decl);
-      TREE_NO_WARNING (decl) = true;
+      set_no_warning (decl);
     }
 
   /* Recursively extend temps in this initializer.  */
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 354addde773..c3024842f87 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6689,7 +6689,7 @@ layout_class_type (tree t, tree *virtuals_p)
 	     laying out an Objective-C class.  The ObjC ABI differs
 	     from the C++ ABI, and so we do not want a warning
 	     here.  */
-	  && !TREE_NO_WARNING (field)
+	  && !get_no_warning (field, OPT_Wabi)
 	  && !last_field_was_bitfield
 	  && !integer_zerop (size_binop (TRUNC_MOD_EXPR,
 					 DECL_FIELD_BIT_OFFSET (field),
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 03ce8eb9ff2..c30127662b5 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3281,14 +3281,14 @@ constraint_satisfaction_value (tree t, tree args, sat_info info)
   else
     r = satisfy_nondeclaration_constraints (t, args, info);
   if (r == error_mark_node && info.quiet ()
-      && !(DECL_P (t) && TREE_NO_WARNING (t)))
+      && !(DECL_P (t) && get_no_warning (t)))
     {
       /* Replay the error noisily.  */
       sat_info noisy (tf_warning_or_error, info.in_decl);
       constraint_satisfaction_value (t, args, noisy);
       if (DECL_P (t) && !args)
 	/* Avoid giving these errors again.  */
-	TREE_NO_WARNING (t) = true;
+	set_no_warning (t);
     }
   return r;
 }
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 71662061f5a..786bffcfad7 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -1078,7 +1078,7 @@ finish_co_await_expr (location_t kw, tree expr)
      is declared to return non-void (most likely).  This is correct - we
      synthesize the return for the ramp in the compiler.  So suppress any
      extraneous warnings during substitution.  */
-  TREE_NO_WARNING (current_function_decl) = true;
+  set_no_warning (current_function_decl, OPT_Wreturn_type);
 
   /* If we don't know the promise type, we can't proceed, build the
      co_await with the expression unchanged.  */
@@ -1154,7 +1154,7 @@ finish_co_yield_expr (location_t kw, tree expr)
      is declared to return non-void (most likely).  This is correct - we
      synthesize the return for the ramp in the compiler.  So suppress any
      extraneous warnings during substitution.  */
-  TREE_NO_WARNING (current_function_decl) = true;
+  set_no_warning (current_function_decl, OPT_Wreturn_type);
 
   /* If we don't know the promise type, we can't proceed, build the
      co_await with the expression unchanged.  */
@@ -1235,7 +1235,7 @@ finish_co_return_stmt (location_t kw, tree expr)
      is declared to return non-void (most likely).  This is correct - we
      synthesize the return for the ramp in the compiler.  So suppress any
      extraneous warnings during substitution.  */
-  TREE_NO_WARNING (current_function_decl) = true;
+  set_no_warning (current_function_decl, OPT_Wreturn_type);
 
   if (processing_template_decl
       && check_for_bare_parameter_packs (expr))
@@ -1259,7 +1259,7 @@ finish_co_return_stmt (location_t kw, tree expr)
 
   /* Suppress -Wreturn-type for co_return, we need to check indirectly
      whether the promise type has a suitable return_void/return_value.  */
-  TREE_NO_WARNING (current_function_decl) = true;
+  set_no_warning (current_function_decl, OPT_Wreturn_type);
 
   if (!processing_template_decl && warn_sequence_point)
     verify_sequence_points (expr);
@@ -2459,7 +2459,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
 
   /* done.  */
   r = build_stmt (loc, RETURN_EXPR, NULL);
-  TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this.  */
+  set_no_warning (r); /* We don't want a warning about this.  */
   r = maybe_cleanup_point_expr_void (r);
   add_stmt (r);
 
@@ -2468,7 +2468,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
   add_stmt (r);
 
   r = build_stmt (loc, RETURN_EXPR, NULL);
-  TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this.  */
+  set_no_warning (r); /* We don't want a warning about this.  */
   r = maybe_cleanup_point_expr_void (r);
   add_stmt (r);
 
@@ -4144,7 +4144,7 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
       finish_if_stmt_cond (not_iarc, not_iarc_if);
       /* If the initial await resume called value is false, rethrow...  */
       tree rethrow = build_throw (fn_start, NULL_TREE);
-      TREE_NO_WARNING (rethrow) = true;
+      set_no_warning (rethrow);
       finish_expr_stmt (rethrow);
       finish_then_clause (not_iarc_if);
       tree iarc_scope = IF_SCOPE (not_iarc_if);
@@ -4245,7 +4245,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
       /* For early errors, we do not want a diagnostic about the missing
 	 ramp return value, since the user cannot fix this - a 'return' is
 	 not allowed in a coroutine.  */
-      TREE_NO_WARNING (orig) = true;
+      set_no_warning (orig, OPT_Wreturn_type);
       /* Discard the body, we can't process it further.  */
       pop_stmt_list (DECL_SAVED_TREE (orig));
       DECL_SAVED_TREE (orig) = push_stmt_list ();
@@ -4271,7 +4271,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
       DECL_SAVED_TREE (orig) = push_stmt_list ();
       append_to_statement_list (fnbody, &DECL_SAVED_TREE (orig));
       /* Suppress warnings about the missing return value.  */
-      TREE_NO_WARNING (orig) = true;
+      set_no_warning (orig, OPT_Wreturn_type);
       return false;
     }
 
@@ -4950,7 +4950,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
       BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
       DECL_SAVED_TREE (orig) = newbody;
       /* Suppress warnings about the missing return value.  */
-      TREE_NO_WARNING (orig) = true;
+      set_no_warning (orig, OPT_Wreturn_type);
       return false;
     }
 
@@ -5161,7 +5161,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
 					      promise_type, fn_start);
       finish_expr_stmt (del_coro_fr);
       tree rethrow = build_throw (fn_start, NULL_TREE);
-      TREE_NO_WARNING (rethrow) = true;
+      set_no_warning (rethrow);
       finish_expr_stmt (rethrow);
       finish_handler (handler);
       TRY_HANDLERS (ramp_cleanup) = pop_stmt_list (TRY_HANDLERS (ramp_cleanup));
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 9079a5b90ca..2b3ec745912 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -101,8 +101,8 @@ genericize_eh_spec_block (tree *stmt_p)
   tree failure = build_call_n (call_unexpected_fn, 1, build_exc_ptr ());
 
   *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure);
-  TREE_NO_WARNING (*stmt_p) = true;
-  TREE_NO_WARNING (TREE_OPERAND (*stmt_p, 1)) = true;
+  set_no_warning (*stmt_p);
+  set_no_warning (TREE_OPERAND (*stmt_p, 1));
 }
 
 /* Return the first non-compound statement in STMT.  */
@@ -214,7 +214,7 @@ gimplify_expr_stmt (tree *stmt_p)
 	{
 	  if (!IS_EMPTY_STMT (stmt)
 	      && !VOID_TYPE_P (TREE_TYPE (stmt))
-	      && !TREE_NO_WARNING (stmt))
+	      && !get_no_warning (stmt, OPT_Wunused_value))
 	    warning (OPT_Wunused_value, "statement with no effect");
 	}
       else
@@ -1322,7 +1322,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
     case THROW_EXPR:
       {
 	location_t loc = location_of (stmt);
-	if (TREE_NO_WARNING (stmt))
+	if (get_no_warning (stmt /* What warning? */))
 	  /* Never mind.  */;
 	else if (wtd->try_block)
 	  {
@@ -2443,8 +2443,9 @@ cp_fold (tree x)
 	    ;
 	  else if (COMPARISON_CLASS_P (x))
 	    {
-	      if (TREE_NO_WARNING (org_x) && warn_nonnull_compare)
-		TREE_NO_WARNING (x) = 1;
+	      if (warn_nonnull_compare
+		  && get_no_warning (org_x, OPT_Wnonnull_compare))
+		set_no_warning (x, OPT_Wnonnull_compare);
 	    }
 	  /* Otherwise give up on optimizing these, let GIMPLE folders
 	     optimize those later on.  */
@@ -2452,8 +2453,9 @@ cp_fold (tree x)
 		   || op1 != TREE_OPERAND (org_x, 1))
 	    {
 	      x = build2_loc (loc, code, TREE_TYPE (org_x), op0, op1);
-	      if (TREE_NO_WARNING (org_x) && warn_nonnull_compare)
-		TREE_NO_WARNING (x) = 1;
+	      if (warn_nonnull_compare
+		  && get_no_warning (org_x, OPT_Wnonnull_compare))
+		set_no_warning (x, OPT_Wnonnull_compare);
 	    }
 	  else
 	    x = org_x;
@@ -2709,7 +2711,7 @@ cp_fold (tree x)
   if (EXPR_P (x) && TREE_CODE (x) == code)
     {
       TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x);
-      TREE_NO_WARNING (x) = TREE_NO_WARNING (org_x);
+      copy_no_warning (x, org_x);
     }
 
   if (!c.evaluation_restricted_p ())
diff --git a/gcc/cp/cp-ubsan.c b/gcc/cp/cp-ubsan.c
index 3dabb6aa18a..bd38faf17f6 100644
--- a/gcc/cp/cp-ubsan.c
+++ b/gcc/cp/cp-ubsan.c
@@ -81,7 +81,7 @@ cp_ubsan_instrument_vptr (location_t loc, tree op, tree type, bool is_addr,
 			      build_zero_cst (TREE_TYPE (op)));
       /* This is a compiler generated comparison, don't emit
 	 e.g. -Wnonnull-compare warning for it.  */
-      TREE_NO_WARNING (cond) = 1;
+      set_no_warning (cond, OPT_Wnonnull_compare);
       vptr = build3_loc (loc, COND_EXPR, uint64_type_node, cond,
 			 vptr, build_int_cst (uint64_type_node, 0));
     }
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 7fa6e8df52b..90beaccc1aa 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -605,8 +605,6 @@ ignore_overflows (tree expr, tree orig)
 tree
 cp_fold_convert (tree type, tree expr)
 {
-  bool nowarn = TREE_NO_WARNING (expr);
-
   tree conv;
   if (TREE_TYPE (expr) == type)
     conv = expr;
@@ -630,8 +628,8 @@ cp_fold_convert (tree type, tree expr)
       conv = ignore_overflows (conv, expr);
     }
 
-  if (nowarn && TREE_CODE (expr) == TREE_CODE (conv))
-    TREE_NO_WARNING (conv) = nowarn;
+  if (TREE_CODE (expr) == TREE_CODE (conv))
+    copy_no_warning (conv, expr);
 
   return conv;
 }
@@ -1208,7 +1206,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
 	/* The second part of a compound expr contains the value.  */
 	tree op1 = TREE_OPERAND (expr,1);
 	tree new_op1;
-	if (implicit != ICV_CAST && !TREE_NO_WARNING (expr))
+	if (implicit != ICV_CAST && !get_no_warning (expr /* What warning? */))
 	  new_op1 = convert_to_void (op1, ICV_RIGHT_OF_COMMA, complain);
 	else
 	  new_op1 = convert_to_void (op1, ICV_CAST, complain);
@@ -1394,7 +1392,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
             if (warn_unused_value
 		&& implicit != ICV_CAST
                 && (complain & tf_warning)
-                && !TREE_NO_WARNING (expr)
+                && !get_no_warning (expr, OPT_Wunused_value)
                 && !is_reference)
               warning_at (loc, OPT_Wunused_value, "value computed is not used");
             expr = TREE_OPERAND (expr, 0);
@@ -1578,7 +1576,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
     {
       if (implicit != ICV_CAST
 	  && warn_unused_value
-	  && !TREE_NO_WARNING (expr)
+	  && !get_no_warning (expr, OPT_Wunused_value)
 	  && !processing_template_decl
 	  && !cp_unevaluated_operand
 	  && (complain & tf_warning))
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 28052df9f45..b23d1eaeb3d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -839,7 +839,7 @@ wrapup_namespace_globals ()
 	      && !TREE_PUBLIC (decl)
 	      && !DECL_ARTIFICIAL (decl)
 	      && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)
-	      && !TREE_NO_WARNING (decl))
+	      && !get_no_warning (decl, OPT_Wunused_function))
 	    warning_at (DECL_SOURCE_LOCATION (decl),
 			OPT_Wunused_function,
 			"%qF declared %<static%> but never defined", decl);
@@ -13851,10 +13851,7 @@ grokdeclarator (const cp_declarator *declarator,
 		decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type);
 		DECL_NONADDRESSABLE_P (decl) = bitfield;
 		if (bitfield && !unqualified_id)
-		  {
-		    TREE_NO_WARNING (decl) = 1;
-		    DECL_PADDING_P (decl) = 1;
-		  }
+		  DECL_PADDING_P (decl) = 1;
 
 		if (storage_class == sc_mutable)
 		  {
@@ -17448,7 +17445,7 @@ finish_function (bool inline_p)
       /* Don't complain if we are declared noreturn.  */
       && !TREE_THIS_VOLATILE (fndecl)
       && !DECL_NAME (DECL_RESULT (fndecl))
-      && !TREE_NO_WARNING (fndecl)
+      && !get_no_warning (fndecl, OPT_Wreturn_type)
       /* Structor return values (if any) are set by the compiler.  */
       && !DECL_CONSTRUCTOR_P (fndecl)
       && !DECL_DESTRUCTOR_P (fndecl)
@@ -17476,7 +17473,7 @@ finish_function (bool inline_p)
       else if (warning_at (&richloc, OPT_Wreturn_type,
 			   "no return statement in function returning "
 			   "non-void"))
-	TREE_NO_WARNING (fndecl) = 1;
+	set_no_warning (fndecl, OPT_Wreturn_type);
     }
 
   /* Lambda closure members are implicitly constexpr if possible.  */
@@ -17550,7 +17547,7 @@ finish_function (bool inline_p)
 	    && !DECL_READ_P (decl)
 	    && DECL_NAME (decl)
 	    && !DECL_ARTIFICIAL (decl)
-	    && !TREE_NO_WARNING (decl)
+	    && !get_no_warning (decl,OPT_Wunused_but_set_parameter)
 	    && !DECL_IN_SYSTEM_HEADER (decl)
 	    && TREE_TYPE (decl) != error_mark_node
 	    && !TYPE_REF_P (TREE_TYPE (decl))
@@ -18041,7 +18038,7 @@ require_deduced_type (tree decl, tsubst_flags_t complain)
 {
   if (undeduced_auto_decl (decl))
     {
-      if (TREE_NO_WARNING (decl) && seen_error ())
+      if (get_no_warning (decl) && seen_error ())
 	/* We probably already complained about deduction failure.  */;
       else if (complain & tf_error)
 	error ("use of %qD before deduction of %<auto%>", decl);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 89f874a32cc..b939c884b95 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4529,7 +4529,7 @@ no_linkage_error (tree decl)
 	  || (errorcount + sorrycount > 0
 	      && DECL_LANG_SPECIFIC (decl)
 	      && DECL_TEMPLATE_INFO (decl)
-	      && TREE_NO_WARNING (decl))))
+	      && get_no_warning (decl /* What warning? */))))
     /* In C++11 it's ok if the decl is defined.  */
     return;
 
@@ -5204,7 +5204,7 @@ c_parse_final_cleanups (void)
 	  && warning_at (DECL_SOURCE_LOCATION (decl), 0,
 			 "inline function %qD used but never defined", decl))
 	/* Avoid a duplicate warning from check_global_declaration.  */
-	TREE_NO_WARNING (decl) = 1;
+	set_no_warning (decl, OPT_Wunused);
     }
 
   /* So must decls that use a type with no linkage.  */
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index cbafc09629b..19ea97ce19b 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -466,7 +466,8 @@ expand_end_catch_block (void)
 	  || DECL_DESTRUCTOR_P (current_function_decl)))
     {
       tree rethrow = build_throw (input_location, NULL_TREE);
-      TREE_NO_WARNING (rethrow) = true;
+      /* Disable all warnings for the generated rethrow statement.  */
+      set_no_warning (rethrow);
       finish_expr_stmt (rethrow);
     }
 }
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index a85f4d50750..52055f10cad 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3536,11 +3536,11 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 	       the arguments to the constructor call.  */
 	    {
 	      /* CLEANUP is compiler-generated, so no diagnostics.  */
-	      TREE_NO_WARNING (cleanup) = true;
+	      set_no_warning (cleanup);
 	      init_expr = build2 (TRY_CATCH_EXPR, void_type_node,
 				  init_expr, cleanup);
 	      /* Likewise, this try-catch is compiler-generated.  */
-	      TREE_NO_WARNING (init_expr) = true;
+	      set_no_warning (init_expr);
 	    }
 	  else
 	    /* Ack!  First we allocate the memory.  Then we set our sentry
@@ -3562,7 +3562,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 	      sentry = TARGET_EXPR_SLOT (begin);
 
 	      /* CLEANUP is compiler-generated, so no diagnostics.  */
-	      TREE_NO_WARNING (cleanup) = true;
+	      set_no_warning (cleanup);
 
 	      TARGET_EXPR_CLEANUP (begin)
 		= build3 (COND_EXPR, void_type_node, sentry,
@@ -3576,7 +3576,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 			  build2 (COMPOUND_EXPR, void_type_node, init_expr,
 				  end));
 	      /* Likewise, this is compiler-generated.  */
-	      TREE_NO_WARNING (init_expr) = true;
+	      set_no_warning (init_expr);
 	    }
 	}
     }
@@ -3823,7 +3823,7 @@ build_new (location_t loc, vec<tree, va_gc> **placement, tree type,
 
   /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain.  */
   rval = build1_loc (loc, NOP_EXPR, TREE_TYPE (rval), rval);
-  TREE_NO_WARNING (rval) = 1;
+  set_no_warning (rval, OPT_Wunused_value);
 
   return rval;
 }
@@ -3995,7 +3995,7 @@ build_vec_delete_1 (location_t loc, tree base, tree maxindex, tree type,
 			  fold_convert (TREE_TYPE (base), nullptr_node));
   /* This is a compiler generated comparison, don't emit
      e.g. -Wnonnull-compare warning for it.  */
-  TREE_NO_WARNING (cond) = 1;
+  set_no_warning (cond, OPT_Wnonnull_compare);
   body = build3_loc (loc, COND_EXPR, void_type_node,
 		     cond, body, integer_zero_node);
   COND_EXPR_IS_VEC_DELETE (body) = true;
@@ -4657,7 +4657,7 @@ build_vec_init (tree base, tree maxindex, tree init,
       atype = build_pointer_type (atype);
       stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
       stmt_expr = cp_build_fold_indirect_ref (stmt_expr);
-      TREE_NO_WARNING (stmt_expr) = 1;
+      set_no_warning (stmt_expr /* What warning? */);
     }
 
   return stmt_expr;
@@ -4924,7 +4924,7 @@ build_delete (location_t loc, tree otype, tree addr,
   /* This is a compiler generated comparison, don't emit
      e.g. -Wnonnull-compare warning for it.  */
   else if (TREE_CODE (ifexp) == NE_EXPR)
-    TREE_NO_WARNING (ifexp) = 1;
+    set_no_warning (ifexp, OPT_Wnonnull_compare);
 
   if (!integer_nonzerop (ifexp))
     expr = build3 (COND_EXPR, void_type_node, ifexp, expr, void_node);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index dd745237f22..9942a73ba6e 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -3284,7 +3284,7 @@ defaultable_fn_check (tree fn)
       /* Avoid do_warn_unused_parameter warnings.  */
       for (tree p = FUNCTION_FIRST_USER_PARM (fn); p; p = DECL_CHAIN (p))
 	if (DECL_NAME (p))
-	  TREE_NO_WARNING (p) = 1;
+	  set_no_warning (p, OPT_Wunused_parameter);
 
       if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
 	/* Defer checking.  */;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bc0505df502..32dced21f5c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1,3 +1,4 @@
+
 /* -*- C++ -*- Parser.
    Copyright (C) 2000-2021 Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
@@ -5322,7 +5323,7 @@ cp_parser_fold_expression (cp_parser *parser, tree expr1)
   /* The operands of a fold-expression are cast-expressions, so binary or
      conditional expressions are not allowed.  We check this here to avoid
      tentative parsing.  */
-  if (EXPR_P (expr1) && TREE_NO_WARNING (expr1))
+  if (EXPR_P (expr1) && get_no_warning (expr1, OPT_Wparentheses))
     /* OK, the expression was parenthesized.  */;
   else if (is_binary_op (TREE_CODE (expr1)))
     error_at (location_of (expr1),
@@ -5603,7 +5604,10 @@ cp_parser_primary_expression (cp_parser *parser,
 	/* Consume the `)'.  */
 	token = cp_lexer_peek_token (parser->lexer);
 	location_t close_paren_loc = token->location;
+	bool no_wparens = get_no_warning (expr, OPT_Wparentheses);
 	expr.set_range (open_paren_loc, close_paren_loc);
+	if (no_wparens)
+	  set_no_warning (expr, OPT_Wparentheses);
 	if (!parens.require_close (parser)
 	    && !cp_parser_uncommitted_to_tentative_parse_p (parser))
 	  cp_parser_skip_to_end_of_statement (parser);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index cbd2f3dc338..170cb4eead0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10942,9 +10942,9 @@ push_tinst_level_loc (tree tldcl, tree targs, location_t loc)
      constant expressions.  */
   if (!targs && limit_bad_template_recursion (tldcl))
     {
-      /* Avoid no_linkage_errors and unused function warnings for this
-	 decl.  */
-      TREE_NO_WARNING (tldcl) = 1;
+      /* Avoid no_linkage_errors and unused function (and all other)
+	 warnings for this decl.  */
+      set_no_warning (tldcl);
       return false;
     }
 
@@ -17087,7 +17087,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
 	tree op2 = tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl);
 	r = build_nt (code, op0, op1, op2);
-	TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+	copy_no_warning (r, t);
 	return r;
       }
 
@@ -19169,8 +19169,7 @@ tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       block = finish_omp_structured_block (block);
       block = maybe_cleanup_point_expr_void (block);
       add_decl_expr (omp_out);
-      if (TREE_NO_WARNING (DECL_EXPR_DECL (stmts[0])))
-	TREE_NO_WARNING (omp_out) = 1;
+      copy_no_warning (omp_out, DECL_EXPR_DECL (stmts[0]));
       add_decl_expr (omp_in);
       finish_expr_stmt (block);
     }
@@ -19846,17 +19845,17 @@ tsubst_copy_and_build (tree t,
 	tree r = build_x_binary_op
 	  (input_location, TREE_CODE (t),
 	   op0,
-	   (TREE_NO_WARNING (TREE_OPERAND (t, 0))
+	   (get_no_warning (TREE_OPERAND (t, 0))
 	    ? ERROR_MARK
 	    : TREE_CODE (TREE_OPERAND (t, 0))),
 	   op1,
-	   (TREE_NO_WARNING (TREE_OPERAND (t, 1))
+	   (get_no_warning (TREE_OPERAND (t, 1))
 	    ? ERROR_MARK
 	    : TREE_CODE (TREE_OPERAND (t, 1))),
 	   /*overload=*/NULL,
 	   complain|decltype_flag);
-	if (EXPR_P (r) && TREE_NO_WARNING (t))
-	  TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+	if (EXPR_P (r))
+	  copy_no_warning (r, t);
 
 	RETURN (r);
       }
@@ -19992,8 +19991,8 @@ tsubst_copy_and_build (tree t,
 	   set and must be copied.  In the latter case,
 	   build_x_modify_expr sets it and it must not be reset
 	   here.  */
-	if (TREE_NO_WARNING (t))
-	  TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+	if (get_no_warning (t, OPT_Wparentheses))
+	  set_no_warning (r, OPT_Wparentheses);
 
 	RETURN (r);
       }
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 82eaa286514..328067bcb6c 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -536,14 +536,14 @@ build_if_nonnull (tree test, tree result, tsubst_flags_t complain)
 
   /* This is a compiler generated comparison, don't emit
      e.g. -Wnonnull-compare warning for it.  */
-  TREE_NO_WARNING (cond) = 1;
+  set_no_warning (cond, OPT_Wnonnull);
 
   null_ptr = cp_convert (TREE_TYPE (result), nullptr_node, complain);
   cond = build3 (COND_EXPR, TREE_TYPE (result), cond, result, null_ptr);
 
   /* Likewise, don't emit -Wnonnull for using the result to call
      a member function.  */
-  TREE_NO_WARNING (cond) = 1;
+  set_no_warning (cond, OPT_Wnonnull);
   return cond;
 }
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0d590c318fb..9454f094374 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -836,12 +836,12 @@ maybe_convert_cond (tree cond)
   cond = convert_from_reference (cond);
 
   if (TREE_CODE (cond) == MODIFY_EXPR
-      && !TREE_NO_WARNING (cond)
       && warn_parentheses
+      && !get_no_warning (cond, OPT_Wparentheses)
       && warning_at (cp_expr_loc_or_input_loc (cond),
 		     OPT_Wparentheses, "suggest parentheses around "
 				       "assignment used as truth value"))
-    TREE_NO_WARNING (cond) = 1;
+    set_no_warning (cond, OPT_Wparentheses);
 
   return condition_conversion (cond);
 }
@@ -1144,7 +1144,7 @@ finish_return_stmt (tree expr)
     {
       /* Suppress -Wreturn-type for this function.  */
       if (warn_return_type)
-	TREE_NO_WARNING (current_function_decl) = true;
+	set_no_warning (current_function_decl, OPT_Wreturn_type);
       return error_mark_node;
     }
 
@@ -1166,7 +1166,8 @@ finish_return_stmt (tree expr)
     }
 
   r = build_stmt (input_location, RETURN_EXPR, expr);
-  TREE_NO_WARNING (r) |= no_warning;
+  if (no_warning)
+    set_no_warning (r, OPT_Wreturn_type);
   r = maybe_cleanup_point_expr_void (r);
   r = add_stmt (r);
 
@@ -2052,7 +2053,7 @@ finish_parenthesized_expr (cp_expr expr)
 {
   if (EXPR_P (expr))
     /* This inhibits warnings in c_common_truthvalue_conversion.  */
-    TREE_NO_WARNING (expr) = 1;
+    set_no_warning (expr, OPT_Wparentheses);
 
   if (TREE_CODE (expr) == OFFSET_REF
       || TREE_CODE (expr) == SCOPE_REF)
@@ -5911,12 +5912,12 @@ cp_check_omp_declare_reduction (tree udr)
     {
       gcc_assert (TREE_CODE (data.stmts[0]) == DECL_EXPR
 		  && TREE_CODE (data.stmts[1]) == DECL_EXPR);
-      if (TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])))
+      if (get_no_warning (DECL_EXPR_DECL (data.stmts[0]) /* What warning? */))
 	return true;
       data.combiner_p = true;
       if (cp_walk_tree (&data.stmts[2], cp_check_omp_declare_reduction_r,
 			&data, NULL))
-	TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])) = 1;
+	set_no_warning (DECL_EXPR_DECL (data.stmts[0]) /* What warning? */);
     }
   if (i >= 6)
     {
@@ -5927,7 +5928,7 @@ cp_check_omp_declare_reduction (tree udr)
 			&data, NULL)
 	  || cp_walk_tree (&DECL_INITIAL (DECL_EXPR_DECL (data.stmts[3])),
 			   cp_check_omp_declare_reduction_r, &data, NULL))
-	TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])) = 1;
+	set_no_warning (DECL_EXPR_DECL (data.stmts[0])  /* Wat warning? */);
       if (i == 7)
 	gcc_assert (TREE_CODE (data.stmts[6]) == DECL_EXPR);
     }
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 72f498f4b3b..c0c0dd128ce 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1126,7 +1126,7 @@ build_cplus_array_type (tree elt_type, tree index_type, int dependent)
 
   /* Avoid spurious warnings with VLAs (c++/54583).  */
   if (TYPE_SIZE (t) && EXPR_P (TYPE_SIZE (t)))
-    TREE_NO_WARNING (TYPE_SIZE (t)) = 1;
+    set_no_warning (TYPE_SIZE (t), OPT_Wunused);
 
   /* Push these needs up to the ARRAY_TYPE so that initialization takes
      place more easily.  */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 703ddd3cc7a..3fe8b0cc7a9 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3316,10 +3316,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
        member = DECL_CHAIN (member))
     if (DECL_NAME (member) == member_name)
       break;
-  tree res = build_simple_component_ref (ptrmem, member);
-
-  TREE_NO_WARNING (res) = 1;
-  return res;
+  return build_simple_component_ref (ptrmem, member);
 }
 
 /* Given an expression PTR for a pointer, return an expression
@@ -3433,7 +3430,7 @@ cp_build_indirect_ref_1 (location_t loc, tree ptr, ref_operator errorstring,
 	  if (warn_strict_aliasing > 2
 	      && cp_strict_aliasing_warning (EXPR_LOCATION (ptr),
 					     type, TREE_OPERAND (ptr, 0)))
-	    TREE_NO_WARNING (ptr) = 1;
+	    set_no_warning (ptr, OPT_Wstrict_aliasing);
 	}
 
       if (VOID_TYPE_P (t))
@@ -4058,7 +4055,7 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
     {
       tree c = extract_call_expr (ret);
       if (TREE_CODE (c) == CALL_EXPR)
-	TREE_NO_WARNING (c) = 1;
+	set_no_warning (c, OPT_Wnonnull);
     }
 
   if (allocated != NULL)
@@ -4440,14 +4437,14 @@ warn_for_null_address (location_t location, tree op, tsubst_flags_t complain)
   if (!warn_address
       || (complain & tf_warning) == 0
       || c_inhibit_evaluation_warnings != 0
-      || TREE_NO_WARNING (op))
+      || get_no_warning (op, OPT_Waddress))
     return;
 
   tree cop = fold_for_warn (op);
 
   if (TREE_CODE (cop) == ADDR_EXPR
       && decl_with_nonnull_addr_p (TREE_OPERAND (cop, 0))
-      && !TREE_NO_WARNING (cop))
+      && !get_no_warning (cop, OPT_Waddress))
     warning_at (location, OPT_Waddress, "the address of %qD will never "
 		"be NULL", TREE_OPERAND (cop, 0));
 
@@ -4868,7 +4865,7 @@ cp_build_binary_op (const op_location_t &location,
 	  else if (TREE_CODE (type0) == ARRAY_TYPE
 		   && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0)))
 		   /* Set by finish_parenthesized_expr.  */
-		   && !TREE_NO_WARNING (op1)
+		   && !get_no_warning (op1, OPT_Wsizeof_array_div)
 		   && (complain & tf_warning))
 	    maybe_warn_sizeof_array_div (location, first_arg, type0,
 					 op1, non_reference (type1));
@@ -5287,7 +5284,7 @@ cp_build_binary_op (const op_location_t &location,
 	  pfn0 = cp_fully_fold (pfn0);
 	  /* Avoid -Waddress warnings (c++/64877).  */
 	  if (TREE_CODE (pfn0) == ADDR_EXPR)
-	    TREE_NO_WARNING (pfn0) = 1;
+	    set_no_warning (pfn0, OPT_Waddress);
 	  pfn1 = pfn_from_ptrmemfunc (op1);
 	  pfn1 = cp_fully_fold (pfn1);
 	  delta0 = delta_from_ptrmemfunc (op0);
@@ -7016,7 +7013,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
                                             tf_warning_or_error);
       arg = build2 (COMPOUND_EXPR, TREE_TYPE (real_result),
 		    arg, real_result);
-      TREE_NO_WARNING (arg) = 1;
+      set_no_warning (arg);
       return arg;
     }
 
@@ -8927,7 +8924,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 
   TREE_SIDE_EFFECTS (result) = 1;
   if (!plain_assign)
-    TREE_NO_WARNING (result) = 1;
+    set_no_warning (result, OPT_Wparentheses);
 
  ret:
   if (preeval)
@@ -8971,7 +8968,7 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 	{
 	  if (rval == error_mark_node)
 	    return rval;
-	  TREE_NO_WARNING (rval) = 1;
+	  set_no_warning (rval /* What warning? */);
 	  if (processing_template_decl)
 	    {
 	      if (overload != NULL_TREE)
@@ -9578,13 +9575,13 @@ convert_for_assignment (tree type, tree rhs,
   if (warn_parentheses
       && TREE_CODE (type) == BOOLEAN_TYPE
       && TREE_CODE (rhs) == MODIFY_EXPR
-      && !TREE_NO_WARNING (rhs)
+      && !get_no_warning (rhs, OPT_Wparentheses)
       && TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE
       && (complain & tf_warning)
       && warning_at (rhs_loc, OPT_Wparentheses,
 		     "suggest parentheses around assignment used as "
 		     "truth value"))
-    TREE_NO_WARNING (rhs) = 1;
+    set_no_warning (rhs, OPT_Wparentheses);
 
   if (complain & tf_warning)
     warn_for_address_or_pointer_of_packed_member (type, rhs);

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 6/11] use xxx_no_warning APIs in Fortran
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
                     ` (3 preceding siblings ...)
  2021-05-24 22:11   ` [PATCH 5/11] use xxx_no_warning APIs in C++ Martin Sebor
@ 2021-05-24 22:12   ` Martin Sebor
  2021-05-24 22:13   ` [PATCH 7/11] " Martin Sebor
                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:12 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 216 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the Fortran
front end.

I don't know the Fortran front end and I made no effort to try to find
the right warning options in the calls to set/get_no_warning.

[-- Attachment #2: gcc-no-warning-fortran.diff --]
[-- Type: text/x-patch, Size: 17307 bytes --]

Add support for per-location warning groups.

gcc/fortran/ChangeLog:

	* trans-array.c (trans_array_constructor): Replace direct uses
	of TREE_NO_WARNING with get_no_warning, and set_no_warning.
	* trans-decl.c (gfc_build_qualified_array): Same.
	(gfc_build_dummy_array_decl): Same.
	(generate_local_decl): Same.
	(gfc_generate_function_code): Same.
	* trans-openmp.c (gfc_omp_clause_default_ctor): Same.
	(gfc_omp_clause_copy_ctor): Same.
	* trans-types.c (get_dtype_type_node): Same.
	(gfc_get_desc_dim_type): Same.
	(gfc_get_array_descriptor_base): Same.
	(gfc_get_caf_vector_type): Same.
	(gfc_get_caf_reference_type): Same.
	* trans.c (gfc_create_var_np): Same.

diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 6d38ea78273..30f9138b5cb 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -2755,7 +2755,7 @@ trans_array_constructor (gfc_ss * ss, locus * where)
   desc = ss_info->data.array.descriptor;
   offset = gfc_index_zero_node;
   offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
-  TREE_NO_WARNING (offsetvar) = 1;
+  set_no_warning (offsetvar);
   TREE_USED (offsetvar) = 0;
   gfc_trans_array_constructor_value (&outer_loop->pre, type, desc, c,
 				     &offset, &offsetvar, dynamic);
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 406b4aeb1d4..81579849fe3 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1039,7 +1039,7 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
       if (GFC_TYPE_ARRAY_LBOUND (type, dim) == NULL_TREE)
 	{
 	  GFC_TYPE_ARRAY_LBOUND (type, dim) = create_index_var ("lbound", nest);
-	  TREE_NO_WARNING (GFC_TYPE_ARRAY_LBOUND (type, dim)) = 1;
+	  set_no_warning (GFC_TYPE_ARRAY_LBOUND (type, dim));
 	}
       /* Don't try to use the unknown bound for assumed shape arrays.  */
       if (GFC_TYPE_ARRAY_UBOUND (type, dim) == NULL_TREE
@@ -1047,13 +1047,13 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
 	      || dim < GFC_TYPE_ARRAY_RANK (type) - 1))
 	{
 	  GFC_TYPE_ARRAY_UBOUND (type, dim) = create_index_var ("ubound", nest);
-	  TREE_NO_WARNING (GFC_TYPE_ARRAY_UBOUND (type, dim)) = 1;
+	  set_no_warning (GFC_TYPE_ARRAY_UBOUND (type, dim));
 	}
 
       if (GFC_TYPE_ARRAY_STRIDE (type, dim) == NULL_TREE)
 	{
 	  GFC_TYPE_ARRAY_STRIDE (type, dim) = create_index_var ("stride", nest);
-	  TREE_NO_WARNING (GFC_TYPE_ARRAY_STRIDE (type, dim)) = 1;
+	  set_no_warning (GFC_TYPE_ARRAY_STRIDE (type, dim));
 	}
     }
   for (dim = GFC_TYPE_ARRAY_RANK (type);
@@ -1062,21 +1062,21 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
       if (GFC_TYPE_ARRAY_LBOUND (type, dim) == NULL_TREE)
 	{
 	  GFC_TYPE_ARRAY_LBOUND (type, dim) = create_index_var ("lbound", nest);
-	  TREE_NO_WARNING (GFC_TYPE_ARRAY_LBOUND (type, dim)) = 1;
+	  set_no_warning (GFC_TYPE_ARRAY_LBOUND (type, dim));
 	}
       /* Don't try to use the unknown ubound for the last coarray dimension.  */
       if (GFC_TYPE_ARRAY_UBOUND (type, dim) == NULL_TREE
           && dim < GFC_TYPE_ARRAY_RANK (type) + GFC_TYPE_ARRAY_CORANK (type) - 1)
 	{
 	  GFC_TYPE_ARRAY_UBOUND (type, dim) = create_index_var ("ubound", nest);
-	  TREE_NO_WARNING (GFC_TYPE_ARRAY_UBOUND (type, dim)) = 1;
+	  set_no_warning (GFC_TYPE_ARRAY_UBOUND (type, dim));
 	}
     }
   if (GFC_TYPE_ARRAY_OFFSET (type) == NULL_TREE)
     {
       GFC_TYPE_ARRAY_OFFSET (type) = gfc_create_var_np (gfc_array_index_type,
 							"offset");
-      TREE_NO_WARNING (GFC_TYPE_ARRAY_OFFSET (type)) = 1;
+      set_no_warning (GFC_TYPE_ARRAY_OFFSET (type));
 
       if (nest)
 	gfc_add_decl_to_parent_function (GFC_TYPE_ARRAY_OFFSET (type));
@@ -1088,7 +1088,7 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
       && as->type != AS_ASSUMED_SIZE)
     {
       GFC_TYPE_ARRAY_SIZE (type) = create_index_var ("size", nest);
-      TREE_NO_WARNING (GFC_TYPE_ARRAY_SIZE (type)) = 1;
+      set_no_warning (GFC_TYPE_ARRAY_SIZE (type));
     }
 
   if (POINTER_TYPE_P (type))
@@ -1293,7 +1293,7 @@ gfc_build_dummy_array_decl (gfc_symbol * sym, tree dummy)
 
   /* Avoid uninitialized warnings for optional dummy arguments.  */
   if (sym->attr.optional)
-    TREE_NO_WARNING (decl) = 1;
+    set_no_warning (decl);
 
   /* We should never get deferred shape arrays here.  We used to because of
      frontend bugs.  */
@@ -5974,7 +5974,7 @@ generate_local_decl (gfc_symbol * sym)
 			     "does not have a default initializer",
 			     sym->name, &sym->declared_at);
 	      if (sym->backend_decl != NULL_TREE)
-		TREE_NO_WARNING(sym->backend_decl) = 1;
+		set_no_warning (sym->backend_decl);
 	    }
 	  else if (warn_unused_dummy_argument)
 	    {
@@ -5984,7 +5984,7 @@ generate_local_decl (gfc_symbol * sym)
 			     &sym->declared_at);
 
 	      if (sym->backend_decl != NULL_TREE)
-		TREE_NO_WARNING(sym->backend_decl) = 1;
+		set_no_warning (sym->backend_decl);
 	    }
 	}
 
@@ -6000,7 +6000,7 @@ generate_local_decl (gfc_symbol * sym)
 			   "explicitly imported at %L", sym->name,
 			   &sym->declared_at);
 	      if (sym->backend_decl != NULL_TREE)
-		TREE_NO_WARNING(sym->backend_decl) = 1;
+		set_no_warning (sym->backend_decl);
 	    }
 	  else if (!sym->attr.use_assoc)
 	    {
@@ -6018,7 +6018,7 @@ generate_local_decl (gfc_symbol * sym)
 			     "Unused variable %qs declared at %L",
 			     sym->name, &sym->declared_at);
 	      if (sym->backend_decl != NULL_TREE)
-		TREE_NO_WARNING(sym->backend_decl) = 1;
+		set_no_warning (sym->backend_decl);
 	    }
 	}
 
@@ -6133,7 +6133,7 @@ generate_local_decl (gfc_symbol * sym)
 	  /* Silence bogus "unused parameter" warnings from the
 	     middle end.  */
 	  if (sym->backend_decl != NULL_TREE)
-		TREE_NO_WARNING (sym->backend_decl) = 1;
+		set_no_warning (sym->backend_decl);
 	}
     }
 
@@ -6964,7 +6964,7 @@ gfc_generate_function_code (gfc_namespace * ns)
 			 "Return value of function %qs at %L not set",
 			 sym->name, &sym->declared_at);
 	  if (warn_return_type > 0)
-	    TREE_NO_WARNING(sym->backend_decl) = 1;
+	    set_no_warning (sym->backend_decl);
 	}
       if (result != NULL_TREE)
 	gfc_add_expr_to_block (&body, gfc_generate_return ());
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 5666cd68c7e..f1d823e9f74 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -729,7 +729,7 @@ gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
 					 else_b));
       /* Avoid -W*uninitialized warnings.  */
       if (DECL_P (decl))
-	TREE_NO_WARNING (decl) = 1;
+	set_no_warning (decl, OPT_Wuninitialized);
     }
   else
     gfc_add_expr_to_block (&block, then_b);
@@ -838,7 +838,7 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
 				     void_type_node, cond, then_b, else_b));
   /* Avoid -W*uninitialized warnings.  */
   if (DECL_P (dest))
-    TREE_NO_WARNING (dest) = 1;
+    set_no_warning (dest, OPT_Wuninitialized);
 
   return gfc_finish_block (&block);
 }
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 9f21b3ee780..d859d37a03c 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -150,23 +150,23 @@ tree get_dtype_type_node (void)
       field = gfc_add_field_to_struct_1 (dtype_node,
 					 get_identifier ("elem_len"),
 					 size_type_node, &dtype_chain);
-      TREE_NO_WARNING (field) = 1;
+      set_no_warning (field);
       field = gfc_add_field_to_struct_1 (dtype_node,
 					 get_identifier ("version"),
 					 integer_type_node, &dtype_chain);
-      TREE_NO_WARNING (field) = 1;
+      set_no_warning (field);
       field = gfc_add_field_to_struct_1 (dtype_node,
 					 get_identifier ("rank"),
 					 signed_char_type_node, &dtype_chain);
-      TREE_NO_WARNING (field) = 1;
+      set_no_warning (field);
       field = gfc_add_field_to_struct_1 (dtype_node,
 					 get_identifier ("type"),
 					 signed_char_type_node, &dtype_chain);
-      TREE_NO_WARNING (field) = 1;
+      set_no_warning (field);
       field = gfc_add_field_to_struct_1 (dtype_node,
 					 get_identifier ("attribute"),
 					 short_integer_type_node, &dtype_chain);
-      TREE_NO_WARNING (field) = 1;
+      set_no_warning (field);
       gfc_finish_type (dtype_node);
       TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (dtype_node)) = 1;
       dtype_type_node = dtype_node;
@@ -1453,17 +1453,17 @@ gfc_get_desc_dim_type (void)
   decl = gfc_add_field_to_struct_1 (type,
 				    get_identifier ("stride"),
 				    gfc_array_index_type, &chain);
-  TREE_NO_WARNING (decl) = 1;
+  set_no_warning (decl);
 
   decl = gfc_add_field_to_struct_1 (type,
 				    get_identifier ("lbound"),
 				    gfc_array_index_type, &chain);
-  TREE_NO_WARNING (decl) = 1;
+  set_no_warning (decl);
 
   decl = gfc_add_field_to_struct_1 (type,
 				    get_identifier ("ubound"),
 				    gfc_array_index_type, &chain);
-  TREE_NO_WARNING (decl) = 1;
+  set_no_warning (decl);
 
   /* Finish off the type.  */
   gfc_finish_type (type);
@@ -1831,19 +1831,19 @@ gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted)
   decl = gfc_add_field_to_struct_1 (fat_type,
 				    get_identifier ("offset"),
 				    gfc_array_index_type, &chain);
-  TREE_NO_WARNING (decl) = 1;
+  set_no_warning (decl);
 
   /* Add the dtype component.  */
   decl = gfc_add_field_to_struct_1 (fat_type,
 				    get_identifier ("dtype"),
 				    get_dtype_type_node (), &chain);
-  TREE_NO_WARNING (decl) = 1;
+  set_no_warning (decl);
 
   /* Add the span component.  */
   decl = gfc_add_field_to_struct_1 (fat_type,
 				    get_identifier ("span"),
 				    gfc_array_index_type, &chain);
-  TREE_NO_WARNING (decl) = 1;
+  set_no_warning (decl);
 
   /* Build the array type for the stride and bound components.  */
   if (dimen + codimen > 0)
@@ -1856,7 +1856,7 @@ gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted)
 
       decl = gfc_add_field_to_struct_1 (fat_type, get_identifier ("dim"),
 					arraytype, &chain);
-      TREE_NO_WARNING (decl) = 1;
+      set_no_warning (decl);
     }
 
   if (flag_coarray == GFC_FCOARRAY_LIB)
@@ -1864,7 +1864,7 @@ gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted)
       decl = gfc_add_field_to_struct_1 (fat_type,
 					get_identifier ("token"),
 					prvoid_type_node, &chain);
-      TREE_NO_WARNING (decl) = 1;
+      set_no_warning (decl);
     }
 
   /* Finish off the type.  */
@@ -2856,7 +2856,7 @@ copy_derived_types:
 	  token = gfc_find_component (derived, caf_name, true, true, NULL);
 	  gcc_assert (token);
 	  c->caf_token = token->backend_decl;
-	  TREE_NO_WARNING (c->caf_token) = 1;
+	  set_no_warning (c->caf_token);
 	}
     }
 
@@ -3521,11 +3521,11 @@ gfc_get_caf_vector_type (int dim)
       tmp = gfc_add_field_to_struct_1 (vect_struct_type,
 				       get_identifier ("vector"),
 				       pvoid_type_node, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      set_no_warning (tmp);
       tmp = gfc_add_field_to_struct_1 (vect_struct_type,
 				       get_identifier ("kind"),
 				       integer_type_node, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      set_no_warning (tmp);
       gfc_finish_type (vect_struct_type);
 
       chain = 0;
@@ -3533,34 +3533,34 @@ gfc_get_caf_vector_type (int dim)
       tmp = gfc_add_field_to_struct_1 (triplet_struct_type,
 				       get_identifier ("lower_bound"),
 				       gfc_array_index_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      set_no_warning (tmp);
       tmp = gfc_add_field_to_struct_1 (triplet_struct_type,
 				       get_identifier ("upper_bound"),
 				       gfc_array_index_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      set_no_warning (tmp);
       tmp = gfc_add_field_to_struct_1 (triplet_struct_type, get_identifier ("stride"),
 				       gfc_array_index_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      set_no_warning (tmp);
       gfc_finish_type (triplet_struct_type);
 
       chain = 0;
       union_type = make_node (UNION_TYPE);
       tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("v"),
                                        vect_struct_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      set_no_warning (tmp);
       tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("triplet"),
 				       triplet_struct_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      set_no_warning (tmp);
       gfc_finish_type (union_type);
 
       chain = 0;
       vec_type = make_node (RECORD_TYPE);
       tmp = gfc_add_field_to_struct_1 (vec_type, get_identifier ("nvec"),
 				       size_type_node, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      set_no_warning (tmp);
       tmp = gfc_add_field_to_struct_1 (vec_type, get_identifier ("u"),
 				       union_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      set_no_warning (tmp);
       gfc_finish_type (vec_type);
       TYPE_NAME (vec_type) = get_identifier ("caf_vector_t");
     }
@@ -3587,11 +3587,11 @@ gfc_get_caf_reference_type ()
   tmp = gfc_add_field_to_struct_1 (c_struct_type,
 				   get_identifier ("offset"),
 				   gfc_array_index_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (c_struct_type,
 				   get_identifier ("caf_token_offset"),
 				   gfc_array_index_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   gfc_finish_type (c_struct_type);
 
   chain = 0;
@@ -3599,15 +3599,15 @@ gfc_get_caf_reference_type ()
   tmp = gfc_add_field_to_struct_1 (s_struct_type,
 				   get_identifier ("start"),
 				   gfc_array_index_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (s_struct_type,
 				   get_identifier ("end"),
 				   gfc_array_index_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (s_struct_type,
 				   get_identifier ("stride"),
 				   gfc_array_index_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   gfc_finish_type (s_struct_type);
 
   chain = 0;
@@ -3615,25 +3615,25 @@ gfc_get_caf_reference_type ()
   tmp = gfc_add_field_to_struct_1 (v_struct_type,
 				   get_identifier ("vector"),
 				   pvoid_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (v_struct_type,
 				   get_identifier ("nvec"),
 				   size_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (v_struct_type,
 				   get_identifier ("kind"),
 				   integer_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   gfc_finish_type (v_struct_type);
 
   chain = 0;
   union_type = make_node (UNION_TYPE);
   tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("s"),
 				   s_struct_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("v"),
 				   v_struct_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   gfc_finish_type (union_type);
 
   tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
@@ -3648,40 +3648,40 @@ gfc_get_caf_reference_type ()
 						    gfc_index_zero_node,
 					 gfc_rank_cst[GFC_MAX_DIMENSIONS - 1])),
 		&chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (a_struct_type,
 				   get_identifier ("static_array_type"),
 				   integer_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (a_struct_type, get_identifier ("dim"),
 				   dim_union_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   gfc_finish_type (a_struct_type);
 
   chain = 0;
   u_union_type = make_node (UNION_TYPE);
   tmp = gfc_add_field_to_struct_1 (u_union_type, get_identifier ("c"),
 				   c_struct_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (u_union_type, get_identifier ("a"),
 				   a_struct_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   gfc_finish_type (u_union_type);
 
   chain = 0;
   reference_type = make_node (RECORD_TYPE);
   tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("next"),
 				   build_pointer_type (reference_type), &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("type"),
 				   integer_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("item_size"),
 				   size_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("u"),
 				   u_union_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  set_no_warning (tmp);
   gfc_finish_type (reference_type);
   TYPE_NAME (reference_type) = get_identifier ("caf_reference_t");
 
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 9f296bd8c03..f1696924345 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -129,7 +129,7 @@ gfc_create_var_np (tree type, const char *prefix)
 
   /* No warnings for anonymous variables.  */
   if (prefix == NULL)
-    TREE_NO_WARNING (t) = 1;
+    set_no_warning (t);
 
   return t;
 }

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 7/11] use xxx_no_warning APIs in Fortran
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
                     ` (4 preceding siblings ...)
  2021-05-24 22:12   ` [PATCH 6/11] use xxx_no_warning APIs in Fortran Martin Sebor
@ 2021-05-24 22:13   ` Martin Sebor
  2021-05-24 22:14   ` [PATCH 8/11] use xxx_no_warning APIs in Objective-C Martin Sebor
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:13 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 179 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the LTO
front end.  The streaming support doesn't extend to multiple bits yet.
I plan to do that in a follow-up change.

[-- Attachment #2: gcc-no-warning-lto.diff --]
[-- Type: text/x-patch, Size: 3293 bytes --]

Add support for per-location warning groups.

gcc/lto/ChangeLog:

	* gimple-streamer-out.c (output_gimple_stmt): Same.
	* lto-common.c (compare_tree_sccs_1): Expand use of TREE_NO_WARNING.
	* lto-streamer-out.c (hash_tree): Same.
	* tree-streamer-in.c (unpack_ts_base_value_fields): Same.
	* tree-streamer-out.c (pack_ts_base_value_fields): Same.

diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c
index fcbf92300d4..ae382665218 100644
--- a/gcc/gimple-streamer-out.c
+++ b/gcc/gimple-streamer-out.c
@@ -73,7 +73,7 @@ output_gimple_stmt (struct output_block *ob, struct function *fn, gimple *stmt)
   /* Emit the tuple header.  */
   bp = bitpack_create (ob->main_stream);
   bp_pack_var_len_unsigned (&bp, gimple_num_ops (stmt));
-  bp_pack_value (&bp, gimple_no_warning_p (stmt), 1);
+  bp_pack_value (&bp, get_no_warning (stmt), 1);
   if (is_gimple_assign (stmt))
     bp_pack_value (&bp,
 		   gimple_assign_nontemporal_move_p (
diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c
index 02d16f49c11..4f78c90effb 100644
--- a/gcc/lto/lto-common.c
+++ b/gcc/lto/lto-common.c
@@ -1110,8 +1110,8 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
     compare_values (TYPE_UNSIGNED);
   if (TYPE_P (t1))
     compare_values (TYPE_ARTIFICIAL);
-  else
-    compare_values (TREE_NO_WARNING);
+  else if (t1->base.nowarning_flag != t2->base.nowarning_flag)
+    return false;
   compare_values (TREE_NOTHROW);
   compare_values (TREE_STATIC);
   if (code != TREE_BINFO)
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index a26d4885800..7fecb958efa 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -1207,7 +1207,7 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
   if (TYPE_P (t))
     hstate.add_flag (TYPE_ARTIFICIAL (t));
   else
-    hstate.add_flag (TREE_NO_WARNING (t));
+    hstate.add_flag (get_no_warning (t));
   hstate.add_flag (TREE_NOTHROW (t));
   hstate.add_flag (TREE_STATIC (t));
   hstate.add_flag (TREE_PROTECTED (t));
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index 984b1e269cf..fab7c678dae 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -131,7 +131,8 @@ unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
   if (TYPE_P (expr))
     TYPE_ARTIFICIAL (expr) = (unsigned) bp_unpack_value (bp, 1);
   else
-    TREE_NO_WARNING (expr) = (unsigned) bp_unpack_value (bp, 1);
+    /* FIXME: set all warning bits. */
+    set_no_warning (expr, (unsigned) bp_unpack_value (bp, 1));
   TREE_NOTHROW (expr) = (unsigned) bp_unpack_value (bp, 1);
   TREE_STATIC (expr) = (unsigned) bp_unpack_value (bp, 1);
   if (TREE_CODE (expr) != TREE_BINFO)
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 1a43534d117..d81ff60bd68 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -104,7 +104,8 @@ pack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
   if (TYPE_P (expr))
     bp_pack_value (bp, TYPE_ARTIFICIAL (expr), 1);
   else
-    bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
+    /* FIXME: pack all warning bits.  */
+    bp_pack_value (bp, get_no_warning (expr), 1);
   bp_pack_value (bp, TREE_NOTHROW (expr), 1);
   bp_pack_value (bp, TREE_STATIC (expr), 1);
   if (TREE_CODE (expr) != TREE_BINFO)

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 8/11] use xxx_no_warning APIs in Objective-C
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
                     ` (5 preceding siblings ...)
  2021-05-24 22:13   ` [PATCH 7/11] " Martin Sebor
@ 2021-05-24 22:14   ` Martin Sebor
  2021-05-25 14:01     ` Iain Sandoe
  2021-05-24 22:15   ` [PATCH 9/11] use xxx_no_warning APIs in rl78 back end Martin Sebor
                     ` (2 subsequent siblings)
  9 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:14 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 86 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in
the Objective-C front end.

[-- Attachment #2: gcc-no-warning-objc.diff --]
[-- Type: text/x-patch, Size: 3944 bytes --]

Add support for per-location warning groups.

gcc/objc/ChangeLog:

	* objc-act.c (objc_maybe_build_modify_expr): Replace direct uses
	of TREE_NO_WARNING with get_no_warning, and set_no_warning.
	(objc_build_incr_expr_for_property_ref): Same.
	(objc_build_struct): Same.
	(synth_module_prologue): Same.
	* objc-gnu-runtime-abi-01.c (gnu_runtime_01_initialize): Same.
	* objc-next-runtime-abi-01.c (next_runtime_01_initialize): Same.
	* objc-next-runtime-abi-02.c (next_runtime_02_initialize): Same.

diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 796256d437e..a4154709b00 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -2007,7 +2007,7 @@ objc_maybe_build_modify_expr (tree lhs, tree rhs)
 	 correct (maybe a more sophisticated implementation could
 	 avoid generating the compound expression if not needed), but
 	 we need to turn it off.  */
-      TREE_NO_WARNING (compound_expr) = 1;
+      set_no_warning (compound_expr, OPT_Wunused);
       return compound_expr;
     }
   else
@@ -2129,7 +2129,7 @@ objc_build_incr_expr_for_property_ref (location_t location,
 
   /* Prevent C++ from warning with -Wall that "right operand of comma
      operator has no effect".  */
-  TREE_NO_WARNING (compound_expr) = 1;
+  set_no_warning (compound_expr, OPT_Wunused);
   return compound_expr;
 }
 
@@ -2262,8 +2262,9 @@ objc_build_struct (tree klass, tree fields, tree super_name)
       DECL_FIELD_IS_BASE (base) = 1;
 
       if (fields)
-	TREE_NO_WARNING (fields) = 1;	/* Suppress C++ ABI warnings -- we   */
-#endif					/* are following the ObjC ABI here.  */
+	/* Suppress C++ ABI warnings: we are following the ObjC ABI here.  */
+	set_no_warning (fields, OPT_Wabi);
+#endif
       DECL_CHAIN (base) = fields;
       fields = base;
     }
@@ -3112,19 +3113,19 @@ synth_module_prologue (void)
 						TYPE_DECL,
 						objc_object_name,
 						objc_object_type));
-  TREE_NO_WARNING (type) = 1;
+  set_no_warning (type);
 
   type = lang_hooks.decls.pushdecl (build_decl (input_location,
 						TYPE_DECL,
 						objc_instancetype_name,
 						objc_instancetype_type));
-  TREE_NO_WARNING (type) = 1;
+  set_no_warning (type);
 
   type = lang_hooks.decls.pushdecl (build_decl (input_location,
 						TYPE_DECL,
 						objc_class_name,
 						objc_class_type));
-  TREE_NO_WARNING (type) = 1;
+  set_no_warning (type);
 
   /* Forward-declare '@interface Protocol'.  */
   type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
diff --git a/gcc/objc/objc-gnu-runtime-abi-01.c b/gcc/objc/objc-gnu-runtime-abi-01.c
index 4add71edf41..9a63bbf45fd 100644
--- a/gcc/objc/objc-gnu-runtime-abi-01.c
+++ b/gcc/objc/objc-gnu-runtime-abi-01.c
@@ -213,7 +213,7 @@ static void gnu_runtime_01_initialize (void)
 						TYPE_DECL,
 						objc_selector_name,
 						objc_selector_type));
-  TREE_NO_WARNING (type) = 1;
+  set_no_warning (type);
 
   /* typedef id (*IMP)(id, SEL, ...); */
   ftype = build_varargs_function_type_list (objc_object_type,
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
index 3ec6e1703c1..b58e4829674 100644
--- a/gcc/objc/objc-next-runtime-abi-01.c
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -282,7 +282,7 @@ static void next_runtime_01_initialize (void)
 						TYPE_DECL,
 						objc_selector_name,
 						objc_selector_type));
-  TREE_NO_WARNING (type) = 1;
+  set_no_warning (type);
 
   build_v1_class_template ();
   build_super_template ();
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index 3cfcd0b1a57..22266c6e612 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -379,7 +379,7 @@ static void next_runtime_02_initialize (void)
 						TYPE_DECL,
 						objc_selector_name,
 						objc_selector_type));
-  TREE_NO_WARNING (type) = 1;
+  set_no_warning (type);
 
   /* IMP : id (*) (id, _message_ref_t*, ...)
      SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 9/11] use xxx_no_warning APIs in rl78 back end
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
                     ` (6 preceding siblings ...)
  2021-05-24 22:14   ` [PATCH 8/11] use xxx_no_warning APIs in Objective-C Martin Sebor
@ 2021-05-24 22:15   ` Martin Sebor
  2021-05-24 22:16   ` [PATCH 10/11] use xxx_no_warning APIs in libcc1 Martin Sebor
  2021-05-24 22:16   ` [PATCH 11/11] use xxx_no_warning APIs in the middle end Martin Sebor
  9 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:15 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 78 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the rl78
back end.

[-- Attachment #2: gcc-no-warning-config.diff --]
[-- Type: text/x-patch, Size: 670 bytes --]

Add support for per-location warning groups.

gcc/ChangeLog:

	* config/rl78/rl78.c (rl78_handle_naked_attribute): Replace a direct
	use of TREE_NO_WARNING with set_no_warning.

diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index 4c34949a97f..1055d423c83 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -847,7 +847,7 @@ rl78_handle_naked_attribute (tree * node,
   /* Disable warnings about this function - eg reaching the end without
      seeing a return statement - because the programmer is doing things
      that gcc does not know about.  */
-  TREE_NO_WARNING (* node) = 1;
+  set_no_warning (* node);
 
   return NULL_TREE;
 }

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 10/11] use xxx_no_warning APIs in libcc1
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
                     ` (7 preceding siblings ...)
  2021-05-24 22:15   ` [PATCH 9/11] use xxx_no_warning APIs in rl78 back end Martin Sebor
@ 2021-05-24 22:16   ` Martin Sebor
  2021-05-24 22:16   ` [PATCH 11/11] use xxx_no_warning APIs in the middle end Martin Sebor
  9 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:16 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 67 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in libc11.

[-- Attachment #2: gcc-no-warning-libcc1.diff --]
[-- Type: text/x-patch, Size: 619 bytes --]

Add support for per-location warning groups.

libcc1/ChangeLog:

	* libcp1plugin.cc (record_decl_address): Replace a direct use
	of TREE_NO_WARNING with set_no_warning.

diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc
index 79694b91964..469a75c7ff7 100644
--- a/libcc1/libcp1plugin.cc
+++ b/libcc1/libcp1plugin.cc
@@ -541,7 +541,7 @@ record_decl_address (plugin_context *ctx, decl_addr_value value)
   **slot = value;
   /* We don't want GCC to warn about e.g. static functions
      without a code definition.  */
-  TREE_NO_WARNING (value.decl) = 1;
+  set_no_warning (value.decl);
   return *slot;
 }
 

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 11/11] use xxx_no_warning APIs in the middle end
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
                     ` (8 preceding siblings ...)
  2021-05-24 22:16   ` [PATCH 10/11] use xxx_no_warning APIs in libcc1 Martin Sebor
@ 2021-05-24 22:16   ` Martin Sebor
  2021-05-24 23:08     ` David Malcolm
  9 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-05-24 22:16 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 167 bytes --]

The attached patch replaces TREE_NO_WARNING, gimple_get_no_warning_p
and gimple_set_no_warning with the new APIs, get_no_warning,
set_no_warning, and copy_no_warning.

[-- Attachment #2: gcc-no-warning-middle-end.diff --]
[-- Type: text/x-patch, Size: 73168 bytes --]

Add support for per-location warning groups.

gcc/ChangeLog:

	* builtins.c (warn_string_no_nul): Replace uses of TREE_NO_WARNING,
	gimple_no_warning_p and gimple_set_no_warning with get_no_warning,
	and set_no_warning.
	(c_strlen): Same.
	(maybe_warn_for_bound): Same.
	(warn_for_access): Same.
	(check_access): Same.
	(expand_builtin_strncmp): Same.
	(fold_builtin_varargs): Same.
	* calls.c (maybe_warn_nonstring_arg): Same.
	(maybe_warn_rdwr_sizes): Same.
	* cfgexpand.c (expand_call_stmt): Same.
	* cgraphunit.c (check_global_declaration): Same.
	* fold-const.c (fold_undefer_overflow_warnings): Same.
	(fold_truth_not_expr): Same.
	(fold_unary_loc): Same.
	(fold_checksum_tree): Same.
	* gengtype.c (open_base_files): Same.
	* gimple-array-bounds.cc (array_bounds_checker::check_array_ref): Same.
	(array_bounds_checker::check_mem_ref): Same.
	(array_bounds_checker::check_addr_expr): Same.
	(array_bounds_checker::check_array_bounds): Same.
	* gimple-expr.c (copy_var_decl): Same.
	* gimple-fold.c (gimple_fold_builtin_strcpy): Same.
	(gimple_fold_builtin_strncat): Same.
	(gimple_fold_builtin_stxcpy_chk): Same.
	(gimple_fold_builtin_stpcpy): Same.
	(gimple_fold_builtin_sprintf): Same.
	(fold_stmt_1): Same.
	* gimple-ssa-isolate-paths.c (diag_returned_locals): Same.
	* gimple-ssa-nonnull-compare.c (do_warn_nonnull_compare): Same.
	* gimple-ssa-sprintf.c (handle_printf_call): Same.
	* gimple-ssa-store-merging.c (imm_store_chain_info::output_merged_store): Same.
	* gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same.
	(maybe_diag_access_bounds): Same.
	(check_call): Same.
	(check_bounds_or_overlap): Same.
	* gimple.c (gimple_build_call_from_tree): Same.
	* gimplify.c (gimplify_return_expr): Same.
	(gimplify_cond_expr): Same.
	(gimplify_modify_expr_complex_part): Same.
	(gimplify_modify_expr): Same.
	(gimple_push_cleanup): Same.
	(gimplify_expr): Same.
	* omp-expand.c (expand_omp_for_generic): Same.
	(expand_omp_taskloop_for_outer): Same.
	* omp-low.c (lower_rec_input_clauses): Same.
	(lower_lastprivate_clauses): Same.
	(lower_send_clauses): Same.
	(lower_omp_target): Same.
	* tree-cfg.c (pass_warn_function_return::execute): Same.
	* tree-complex.c (create_one_component_var): Same.
	* tree-inline.c (remap_gimple_op_r): Same.
	(copy_tree_body_r): Same.
	(declare_return_variable): Same.
	(expand_call_inline): Same.
	* tree-nested.c (lookup_field_for_decl): Same.
	* tree-sra.c (create_access_replacement): Same.
	(generate_subtree_copies): Same.
	* tree-ssa-ccp.c (pass_post_ipa_warn::execute): Same.
	* tree-ssa-forwprop.c (combine_cond_expr_cond): Same.
	* tree-ssa-loop-ch.c (ch_base::copy_headers): Same.
	* tree-ssa-loop-im.c (execute_sm): Same.
	* tree-ssa-phiopt.c (cond_store_replacement): Same.
	* tree-ssa-strlen.c (maybe_warn_overflow): Same.
	(handle_builtin_strcpy): Same.
	(maybe_diag_stxncpy_trunc): Same.
	(handle_builtin_stxncpy_strncat): Same.
	(handle_builtin_strcat): Same.
	* tree-ssa-uninit.c (get_no_uninit_warning): Same.
	(set_no_uninit_warning): Same.
	(uninit_undefined_value_p): Same.
	(warn_uninit): Same.
	(maybe_warn_operand): Same.
	* tree-vrp.c (compare_values_warnv): Same.
	* vr-values.c (vr_values::extract_range_for_var_from_comparison_expr): Same.
	(test_for_singularity): Same.

	* gimple.h (get_no_warning): New.
	(set_no_warning): Same.
	(copy_no_warning): Same.
	(gimple_set_block): Call gimple_set_location.
	(gimple_set_location): Call copy_warning.
	(gimple_no_warning_p): Remove.
	(gimple_set_no_warning): Same.
	* tree.h (TREE_NO_WARNING): Remove.
	(get_no_warning): New.
	(set_no_warning): Same.
	(copy_no_warning): Same.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index b0c880dc3b5..105deadd42b 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1094,7 +1094,9 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 		    bool exact /* = false */,
 		    const wide_int bndrng[2] /* = NULL */)
 {
-  if ((expr && TREE_NO_WARNING (expr)) || TREE_NO_WARNING (arg))
+  const int opt = OPT_Wstringop_overread;
+  if ((expr && get_no_warning (expr, opt))
+      || get_no_warning (arg, opt))
     return;
 
   loc = expansion_point_location_if_in_system_header (loc);
@@ -1122,14 +1124,14 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
       if (bndrng)
 	{
 	  if (wi::ltu_p (maxsiz, bndrng[0]))
-	    warned = warning_at (loc, OPT_Wstringop_overread,
+	    warned = warning_at (loc, opt,
 				 "%K%qD specified bound %s exceeds "
 				 "maximum object size %E",
 				 expr, func, bndstr, maxobjsize);
 	  else
 	    {
 	      bool maybe = wi::to_wide (size) == bndrng[0];
-	      warned = warning_at (loc, OPT_Wstringop_overread,
+	      warned = warning_at (loc, opt,
 				   exact
 				   ? G_("%K%qD specified bound %s exceeds "
 					"the size %E of unterminated array")
@@ -1144,7 +1146,7 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 	    }
 	}
       else
-	warned = warning_at (loc, OPT_Wstringop_overread,
+	warned = warning_at (loc, opt,
 			     "%K%qD argument missing terminating nul",
 			     expr, func);
     }
@@ -1153,14 +1155,14 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
       if (bndrng)
 	{
 	  if (wi::ltu_p (maxsiz, bndrng[0]))
-	    warned = warning_at (loc, OPT_Wstringop_overread,
+	    warned = warning_at (loc, opt,
 				 "%qs specified bound %s exceeds "
 				 "maximum object size %E",
 				 fname, bndstr, maxobjsize);
 	  else
 	    {
 	      bool maybe = wi::to_wide (size) == bndrng[0];
-	      warned = warning_at (loc, OPT_Wstringop_overread,
+	      warned = warning_at (loc, opt,
 				   exact
 				   ? G_("%qs specified bound %s exceeds "
 					"the size %E of unterminated array")
@@ -1175,7 +1177,7 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 	    }
 	}
       else
-	warned = warning_at (loc, OPT_Wstringop_overread,
+	warned = warning_at (loc, opt,
 			     "%qs argument missing terminating nul",
 			     fname);
     }
@@ -1184,9 +1186,9 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
     {
       inform (DECL_SOURCE_LOCATION (decl),
 	      "referenced argument declared here");
-      TREE_NO_WARNING (arg) = 1;
+      set_no_warning (arg, opt);
       if (expr)
-	TREE_NO_WARNING (expr) = 1;
+	set_no_warning (expr, opt);
     }
 }
 
@@ -1443,14 +1445,14 @@ c_strlen (tree arg, int only_value, c_strlen_data *data, unsigned eltsize)
     {
       /* Suppress multiple warnings for propagated constant strings.  */
       if (only_value != 2
-	  && !TREE_NO_WARNING (arg)
+	  && !get_no_warning (arg/*, OPT_Warray_bounds*/)
 	  && warning_at (loc, OPT_Warray_bounds,
 			 "offset %qwi outside bounds of constant string",
 			 eltoff))
 	{
 	  if (decl)
 	    inform (DECL_SOURCE_LOCATION (decl), "%qE declared here", decl);
-	  TREE_NO_WARNING (arg) = 1;
+	  set_no_warning (arg, OPT_Warray_bounds);
 	}
       return NULL_TREE;
     }
@@ -3936,7 +3938,7 @@ static bool
 maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 		      tree bndrng[2], tree size, const access_data *pad = NULL)
 {
-  if (!bndrng[0] || TREE_NO_WARNING (exp))
+  if (!bndrng[0] || get_no_warning (exp, opt))
     return false;
 
   tree maxobjsize = max_object_size ();
@@ -4028,7 +4030,7 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 		inform (EXPR_LOCATION (pad->src.ref),
 			"source object allocated here");
 	    }
-	  TREE_NO_WARNING (exp) = true;
+	  set_no_warning (exp, opt);
 	}
 
       return warned;
@@ -4075,14 +4077,14 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
     return false;
   else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
     warned = (func
-	      ? warning_at (loc, OPT_Wstringop_overflow_,
+	      ? warning_at (loc, opt,
 			    (maybe
 			     ? G_("%K%qD specified bound %E may exceed "
 				  "destination size %E")
 			     : G_("%K%qD specified bound %E exceeds "
 				  "destination size %E")),
 			    exp, func, bndrng[0], size)
-	      : warning_at (loc, OPT_Wstringop_overflow_,
+	      : warning_at (loc, opt,
 			    (maybe
 			     ? G_("%Kspecified bound %E may exceed "
 				  "destination size %E")
@@ -4091,14 +4093,14 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 			    exp, bndrng[0], size));
   else
     warned = (func
-	      ? warning_at (loc, OPT_Wstringop_overflow_,
+	      ? warning_at (loc, opt,
 			    (maybe
 			     ? G_("%K%qD specified bound [%E, %E] may exceed "
 				  "destination size %E")
 			     : G_("%K%qD specified bound [%E, %E] exceeds "
 				  "destination size %E")),
 			    exp, func, bndrng[0], bndrng[1], size)
-	      : warning_at (loc, OPT_Wstringop_overflow_,
+	      : warning_at (loc, opt,
 			    (maybe
 			     ? G_("%Kspecified bound [%E, %E] exceeds "
 				  "destination size %E")
@@ -4117,7 +4119,7 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 	    inform (EXPR_LOCATION (pad->dst.ref),
 		    "destination object allocated here");
 	}
-      TREE_NO_WARNING (exp) = true;
+      set_no_warning (exp, opt);
     }
 
   return warned;
@@ -4343,7 +4345,7 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 				exp, range[0], range[1], size));
 
       if (warned)
-	TREE_NO_WARNING (exp) = true;
+	set_no_warning (exp, OPT_Wstringop_overread);
 
       return warned;
     }
@@ -4386,7 +4388,7 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 			    exp, range[0], range[1], size));
 
   if (warned)
-    TREE_NO_WARNING (exp) = true;
+    set_no_warning (exp, OPT_Wstringop_overread);
 
   return warned;
 }
@@ -4765,8 +4767,10 @@ check_access (tree exp, tree dstwrite,
 		  && tree_fits_uhwi_p (dstwrite)
 		  && tree_int_cst_lt (dstwrite, range[0]))))
 	{
-	  if (TREE_NO_WARNING (exp)
-	      || (pad && pad->dst.ref && TREE_NO_WARNING (pad->dst.ref)))
+	  const int opt = OPT_Wstringop_overflow_;
+	  if (get_no_warning (exp, opt)
+	      || (pad && pad->dst.ref
+		  && get_no_warning (pad->dst.ref, opt)))
 	    return false;
 
 	  location_t loc = tree_inlined_location (exp);
@@ -4777,12 +4781,12 @@ check_access (tree exp, tree dstwrite,
 		 and a source of unknown length.  The call will write
 		 at least one byte past the end of the destination.  */
 	      warned = (func
-			? warning_at (loc, OPT_Wstringop_overflow_,
+			? warning_at (loc, opt,
 				      "%K%qD writing %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
 				      exp, func, range[0], dstsize)
-			: warning_at (loc, OPT_Wstringop_overflow_,
+			: warning_at (loc, opt,
 				      "%Kwriting %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
@@ -4803,7 +4807,7 @@ check_access (tree exp, tree dstwrite,
 
 	  if (warned)
 	    {
-	      TREE_NO_WARNING (exp) = true;
+	      set_no_warning (exp, OPT_Wstringop_overflow_);
 	      if (pad)
 		pad->dst.inform_access (pad->mode);
 	    }
@@ -4876,19 +4880,21 @@ check_access (tree exp, tree dstwrite,
 
   if (overread)
     {
-      if (TREE_NO_WARNING (exp)
-	  || (srcstr && TREE_NO_WARNING (srcstr))
-	  || (pad && pad->src.ref && TREE_NO_WARNING (pad->src.ref)))
+      const int opt = OPT_Wstringop_overread;
+      if (get_no_warning (exp, opt)
+	  || (srcstr && get_no_warning (srcstr, opt))
+	  || (pad && pad->src.ref
+	      && get_no_warning (pad->src.ref, opt)))
 	return false;
 
       location_t loc = tree_inlined_location (exp);
       const bool read
 	= mode == access_read_only || mode == access_read_write;
       const bool maybe = pad && pad->dst.parmarray;
-      if (warn_for_access (loc, func, exp, OPT_Wstringop_overread, range,
-			   slen, false, read, maybe))
+      if (warn_for_access (loc, func, exp, opt, range, slen, false, read,
+			   maybe))
 	{
-	  TREE_NO_WARNING (exp) = true;
+	  set_no_warning (exp, opt);
 	  if (pad)
 	    pad->src.inform_access (access_read_only);
 	}
@@ -7413,8 +7419,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
   /* Expand the library call ourselves using a stabilized argument
      list to avoid re-evaluating the function's arguments twice.  */
   tree call = build_call_nofold_loc (loc, fndecl, 3, arg1, arg2, len);
-  if (TREE_NO_WARNING (exp))
-    TREE_NO_WARNING (call) = true;
+  copy_no_warning (call, exp);
   gcc_assert (TREE_CODE (call) == CALL_EXPR);
   CALL_EXPR_TAILCALL (call) = CALL_EXPR_TAILCALL (exp);
   return expand_call (call, target, target == const0_rtx);
@@ -13953,7 +13958,7 @@ fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs)
     {
       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
       SET_EXPR_LOCATION (ret, loc);
-      TREE_NO_WARNING (ret) = 1;
+      set_no_warning (ret);
       return ret;
     }
   return NULL_TREE;
diff --git a/gcc/calls.c b/gcc/calls.c
index f3da1839dc5..47e2a2b54de 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1622,7 +1622,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
   if (!fndecl || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
     return false;
 
-  if (TREE_NO_WARNING (exp) || !warn_stringop_overread)
+  if (!warn_stringop_overread || get_no_warning (exp, OPT_Wstringop_overread))
     return false;
 
   /* Avoid clearly invalid calls (more checking done below).  */
@@ -1738,7 +1738,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
 				 exp, fndecl, bndrng[0], bndrng[1],
 				 maxobjsize);
 	  if (warned)
-	    TREE_NO_WARNING (exp) = true;
+	    set_no_warning (exp, OPT_Wstringop_overread);
 
 	  return warned;
 	}
@@ -1915,7 +1915,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
     }
 
   if (any_arg_warned)
-    TREE_NO_WARNING (exp) = true;
+    set_no_warning (exp, OPT_Wstringop_overread);
 
   return any_arg_warned;
 }
@@ -1978,7 +1978,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 
   /* Set if a warning has been issued for any argument (used to decide
      whether to emit an informational note at the end).  */
-  bool any_warned = false;
+  int opt_warned = false;
 
   /* A string describing the attributes that the warnings issued by this
      function apply to.  Used to print one informational note per function
@@ -2053,7 +2053,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 	*sizstr = '\0';
 
       /* Set if a warning has been issued for the current argument.  */
-      bool arg_warned = false;
+      int arg_warned = 0;
       location_t loc = EXPR_LOCATION (exp);
       tree ptr = access.second.ptr;
       if (*sizstr
@@ -2066,24 +2066,25 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 	      const std::string argtypestr
 		= access.second.array_as_string (ptrtype);
 
-	      arg_warned = warning_at (loc, OPT_Wstringop_overflow_,
-				       "%Kbound argument %i value %s is "
-				       "negative for a variable length array "
-				       "argument %i of type %s",
-				       exp, sizidx + 1, sizstr,
-				       ptridx + 1, argtypestr.c_str ());
+	      if (warning_at (loc, OPT_Wstringop_overflow_,
+			      "%Kbound argument %i value %s is "
+			      "negative for a variable length array "
+			      "argument %i of type %s",
+			      exp, sizidx + 1, sizstr,
+			      ptridx + 1, argtypestr.c_str ()))
+		arg_warned = OPT_Wstringop_overflow_;
 	    }
-	  else
-	    arg_warned = warning_at (loc, OPT_Wstringop_overflow_,
-				     "%Kargument %i value %s is negative",
-				     exp, sizidx + 1, sizstr);
+	  else if (warning_at (loc, OPT_Wstringop_overflow_,
+			       "%Kargument %i value %s is negative",
+			       exp, sizidx + 1, sizstr))
+	    arg_warned = OPT_Wstringop_overflow_;
 
 	  if (arg_warned)
 	    {
 	      append_attrname (access, attrstr, sizeof attrstr);
 	      /* Remember a warning has been issued and avoid warning
 		 again below for the same attribute.  */
-	      any_warned = true;
+	      opt_warned = arg_warned;
 	      continue;
 	    }
 	}
@@ -2121,31 +2122,33 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		  const std::string argtypestr
 		    = access.second.array_as_string (ptrtype);
 
-		  arg_warned = warning_at (loc, OPT_Wnonnull,
-					   "%Kargument %i of variable length "
-					   "array %s is null but "
-					   "the corresponding bound argument "
-					   "%i value is %s",
-					   exp, sizidx + 1, argtypestr.c_str (),
-					   ptridx + 1, sizstr);
+		  if (warning_at (loc, OPT_Wnonnull,
+				  "%Kargument %i of variable length "
+				  "array %s is null but "
+				  "the corresponding bound argument "
+				  "%i value is %s",
+				  exp, sizidx + 1, argtypestr.c_str (),
+				  ptridx + 1, sizstr))
+		    arg_warned = OPT_Wnonnull;
 		}
-	      else
-		arg_warned = warning_at (loc, OPT_Wnonnull,
-					 "%Kargument %i is null but "
-					 "the corresponding size argument "
-					 "%i value is %s",
-					 exp, ptridx + 1, sizidx + 1,
-					 sizstr);
+	      else if (warning_at (loc, OPT_Wnonnull,
+				   "%Kargument %i is null but "
+				   "the corresponding size argument "
+				   "%i value is %s",
+				   exp, ptridx + 1, sizidx + 1,
+				   sizstr))
+		arg_warned = OPT_Wnonnull;
 	    }
 	  else if (access_size && access.second.static_p)
 	    {
 	      /* Warn about null pointers for [static N] array arguments
 		 but do not warn for ordinary (i.e., nonstatic) arrays.  */
-	      arg_warned = warning_at (loc, OPT_Wnonnull,
-				       "%Kargument %i to %<%T[static %E]%> "
-				       "is null where non-null expected",
-				       exp, ptridx + 1, argtype,
-				       access_size);
+	      if (warning_at (loc, OPT_Wnonnull,
+			      "%Kargument %i to %<%T[static %E]%> "
+			      "is null where non-null expected",
+			      exp, ptridx + 1, argtype,
+			      access_size))
+		arg_warned = OPT_Wnonnull;		
 	    }
 
 	  if (arg_warned)
@@ -2153,7 +2156,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 	      append_attrname (access, attrstr, sizeof attrstr);
 	      /* Remember a warning has been issued and avoid warning
 		 again below for the same attribute.  */
-	      any_warned = true;
+	      opt_warned = OPT_Wnonnull;
 	      continue;
 	    }
 	}
@@ -2189,17 +2192,17 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
       /* Clear the no-warning bit in case it was set by check_access
 	 in a prior iteration so that accesses via different arguments
 	 are diagnosed.  */
-      TREE_NO_WARNING (exp) = false;
+      set_no_warning (exp, OPT_Wstringop_overflow_, false);
       access_mode mode = data.mode;
       if (mode == access_deferred)
 	mode = TYPE_READONLY (argtype) ? access_read_only : access_read_write;
       check_access (exp, access_size, /*maxread=*/ NULL_TREE, srcsize,
 		    dstsize, mode, &data);
 
-      if (TREE_NO_WARNING (exp))
+      if (get_no_warning (exp, OPT_Wstringop_overflow_))
+	opt_warned = OPT_Wstringop_overflow_;
+      if (opt_warned)
 	{
-	  any_warned = true;
-
 	  if (access.second.internal_p)
 	    inform (loc, "referencing argument %u of type %qT",
 		    ptridx + 1, ptrtype);
@@ -2221,7 +2224,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		"in a call with type %qT and attribute %qs",
 		fntype, attrstr);
     }
-  else if (any_warned)
+  else if (opt_warned)
     {
       if (fndecl)
 	inform (DECL_SOURCE_LOCATION (fndecl),
@@ -2232,7 +2235,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
     }
 
   /* Set the bit in case if was cleared and not set above.  */
-  TREE_NO_WARNING (exp) = true;
+  set_no_warning (exp, opt_warned);
 }
 
 /* Fill in ARGS_SIZE and ARGS array based on the parameters found in
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 39e5b040427..fcc7cfd3b59 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2807,9 +2807,6 @@ expand_call_stmt (gcall *stmt)
   if (gimple_call_nothrow_p (stmt))
     TREE_NOTHROW (exp) = 1;
 
-  if (gimple_no_warning_p (stmt))
-    TREE_NO_WARNING (exp) = 1;
-
   CALL_EXPR_TAILCALL (exp) = gimple_call_tail_p (stmt);
   CALL_EXPR_MUST_TAIL_CALL (exp) = gimple_call_must_tail_p (stmt);
   CALL_EXPR_RETURN_SLOT_OPT (exp) = gimple_call_return_slot_opt_p (stmt);
@@ -2823,6 +2820,9 @@ expand_call_stmt (gcall *stmt)
   CALL_EXPR_BY_DESCRIPTOR (exp) = gimple_call_by_descriptor_p (stmt);
   SET_EXPR_LOCATION (exp, gimple_location (stmt));
 
+  /* Must come after copying location.  */
+  copy_no_warning (exp, stmt);
+
   /* Ensure RTL is created for debug args.  */
   if (decl && DECL_HAS_DEBUG_ARGS_P (decl))
     {
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 098eb99dc95..40489aab525 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1074,7 +1074,7 @@ check_global_declaration (symtab_node *snode)
       && ! DECL_ARTIFICIAL (decl)
       && ! TREE_PUBLIC (decl))
     {
-      if (TREE_NO_WARNING (decl))
+      if (get_no_warning (decl, OPT_Wunused))
 	;
       else if (snode->referred_to_p (/*include_self=*/false))
 	pedwarn (input_location, 0, "%q+F used but never defined", decl);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3be9c15e6b2..f3bc9ede30c 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -249,7 +249,7 @@ fold_undefer_overflow_warnings (bool issue, const gimple *stmt, int code)
   if (!issue || warnmsg == NULL)
     return;
 
-  if (gimple_no_warning_p (stmt))
+  if (get_no_warning (stmt, OPT_Wstrict_overflow))
     return;
 
   /* Use the smallest code level when deciding to issue the
@@ -4249,8 +4249,7 @@ fold_truth_not_expr (location_t loc, tree arg)
 
       tree ret = build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
 			     TREE_OPERAND (arg, 1));
-      if (TREE_NO_WARNING (arg))
-	TREE_NO_WARNING (ret) = 1;
+      copy_no_warning (ret, arg);
       return ret;
     }
 
@@ -9341,7 +9340,7 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
 	  tem = fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 1));
 	  /* First do the assignment, then return converted constant.  */
 	  tem = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (tem), op0, tem);
-	  TREE_NO_WARNING (tem) = 1;
+	  set_no_warning (tem /* What warning? */);
 	  TREE_USED (tem) = 1;
 	  return tem;
 	}
@@ -13509,10 +13508,10 @@ fold_checksum_tree (const_tree expr, struct md5_ctx *ctx,
 	  TYPE_CACHED_VALUES (tmp) = NULL;
 	}
     }
-  else if (TREE_NO_WARNING (expr) && (DECL_P (expr) || EXPR_P (expr)))
+  else if (get_no_warning (expr) && (DECL_P (expr) || EXPR_P (expr)))
     {
-      /* Allow TREE_NO_WARNING to be set.  Perhaps we shouldn't allow that
-	 and change builtins.c etc. instead - see PR89543.  */
+      /* Allow the no-warning bit to be set.  Perhaps we shouldn't allow
+	 that and change builtins.c etc. instead - see PR89543.  */
       size_t sz = tree_size (expr);
       buf = XALLOCAVAR (union tree_node, sz);
       memcpy ((char *) buf, expr, sz);
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index b94e2f126ec..c1fa6d35c87 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1727,7 +1727,7 @@ open_base_files (void)
       "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
       "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h",
       "omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h", "symtab-thunks.h",
-      "symtab-clones.h",
+      "symtab-clones.h", "diagnostic-spec.h",
       NULL
     };
     const char *const *ifp;
diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
index 199d9f5d216..41615002594 100644
--- a/gcc/gimple-array-bounds.cc
+++ b/gcc/gimple-array-bounds.cc
@@ -175,7 +175,7 @@ bool
 array_bounds_checker::check_array_ref (location_t location, tree ref,
 				       bool ignore_off_by_one)
 {
-  if (TREE_NO_WARNING (ref))
+  if (get_no_warning (ref, OPT_Warray_bounds))
     /* Return true to have the caller prevent warnings for enclosing
        refs.  */
     return true;
@@ -346,7 +346,7 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
       /* Avoid more warnings when checking more significant subscripts
 	 of the same expression.  */
       ref = TREE_OPERAND (ref, 0);
-      TREE_NO_WARNING (ref) = 1;
+      set_no_warning (ref, OPT_Warray_bounds);
 
       if (decl)
 	ref = decl;
@@ -411,7 +411,7 @@ bool
 array_bounds_checker::check_mem_ref (location_t location, tree ref,
 				     bool ignore_off_by_one)
 {
-  if (TREE_NO_WARNING (ref))
+  if (get_no_warning (ref, OPT_Warray_bounds))
     return false;
 
   tree arg = TREE_OPERAND (ref, 0);
@@ -770,7 +770,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
 	    }
 	}
 
-      TREE_NO_WARNING (ref) = 1;
+      set_no_warning (ref, OPT_Warray_bounds);
       return true;
     }
 
@@ -787,7 +787,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
 		      "intermediate array offset %wi is outside array bounds "
 		      "of %qT", tmpidx, reftype))
 	{
-	  TREE_NO_WARNING (ref) = 1;
+	  set_no_warning (ref, OPT_Warray_bounds);
 	  return true;
 	}
     }
@@ -818,7 +818,7 @@ array_bounds_checker::check_addr_expr (location_t location, tree t)
 	warned = check_mem_ref (location, t, ignore_off_by_one);
 
       if (warned)
-	TREE_NO_WARNING (t) = true;
+	set_no_warning (t, OPT_Warray_bounds);
 
       t = TREE_OPERAND (t, 0);
     }
@@ -826,7 +826,7 @@ array_bounds_checker::check_addr_expr (location_t location, tree t)
 
   if (TREE_CODE (t) != MEM_REF
       || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR
-      || TREE_NO_WARNING (t))
+      || get_no_warning (t, OPT_Warray_bounds))
     return;
 
   tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
@@ -886,7 +886,7 @@ array_bounds_checker::check_addr_expr (location_t location, tree t)
       if (DECL_P (t))
 	inform (DECL_SOURCE_LOCATION (t), "while referencing %qD", t);
 
-      TREE_NO_WARNING (t) = 1;
+      set_no_warning (t, OPT_Warray_bounds);
     }
 }
 
@@ -980,9 +980,10 @@ array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree,
        See pr98266 and pr97595.  */
     *walk_subtree = false;
 
-  /* Propagate the no-warning bit to the outer expression.  */
+  /* Propagate the no-warning bit to the outer statement to avoid also
+     issuing -Wstringop-overflow/-overread for the out-of-bounds accesses.  */
   if (warned)
-    TREE_NO_WARNING (t) = true;
+    set_no_warning (wi->stmt, OPT_Warray_bounds);
 
   return NULL_TREE;
 }
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index b8c732b632a..80fba56ead4 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -377,7 +377,6 @@ copy_var_decl (tree var, tree name, tree type)
   DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
   DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
   DECL_CONTEXT (copy) = DECL_CONTEXT (var);
-  TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
   TREE_USED (copy) = 1;
   DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
   DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
@@ -387,6 +386,7 @@ copy_var_decl (tree var, tree name, tree type)
       DECL_USER_ALIGN (copy) = 1;
     }
 
+  copy_no_warning (copy, var);
   return copy;
 }
 
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 68717cf1542..29dd361370a 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -2039,7 +2039,7 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi,
 	 not point to objects and so do not indicate an overlap;
 	 such calls could be the result of sanitization and jump
 	 threading).  */
-      if (!integer_zerop (dest) && !gimple_no_warning_p (stmt))
+      if (!integer_zerop (dest) && !get_no_warning (stmt, OPT_Wrestrict))
 	{
 	  tree func = gimple_call_fndecl (stmt);
 
@@ -2066,9 +2066,9 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi,
   if (nonstr)
     {
       /* Avoid folding calls with unterminated arrays.  */
-      if (!gimple_no_warning_p (stmt))
+      if (!get_no_warning (stmt, OPT_Wstringop_overread))
 	warn_string_no_nul (loc, NULL_TREE, "strcpy", src, nonstr);
-      gimple_set_no_warning (stmt, true);
+      set_no_warning (stmt, OPT_Wstringop_overread);
       return false;
     }
 
@@ -2476,7 +2476,7 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 
   unsigned HOST_WIDE_INT dstsize;
 
-  bool nowarn = gimple_no_warning_p (stmt);
+  bool nowarn = get_no_warning (stmt, OPT_Wstringop_overflow_);
 
   if (!nowarn && compute_builtin_object_size (dst, 1, &dstsize))
     {
@@ -2499,7 +2499,7 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 				    "destination size %wu"),
 			       stmt, fndecl, len, dstsize);
 	  if (nowarn)
-	    gimple_set_no_warning (stmt, true);
+	    set_no_warning (stmt, OPT_Wstringop_overflow_);
 	}
     }
 
@@ -2515,7 +2515,7 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
       if (warning_at (loc, OPT_Wstringop_overflow_,
 		      "%G%qD specified bound %E equals source length",
 		      stmt, fndecl, len))
-	gimple_set_no_warning (stmt, true);
+	set_no_warning (stmt, OPT_Wstringop_overflow_);
     }
 
   tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
@@ -3100,7 +3100,8 @@ gimple_fold_builtin_stxcpy_chk (gimple_stmt_iterator *gsi,
 	 not point to objects and so do not indicate an overlap;
 	 such calls could be the result of sanitization and jump
 	 threading).  */
-      if (!integer_zerop (dest) && !gimple_no_warning_p (stmt))
+      if (!integer_zerop (dest)
+	  && !get_no_warning (stmt, OPT_Wrestrict))
 	{
 	  tree func = gimple_call_fndecl (stmt);
 
@@ -3283,10 +3284,10 @@ gimple_fold_builtin_stpcpy (gimple_stmt_iterator *gsi)
   if (data.decl)
     {
       /* Avoid folding calls with unterminated arrays.  */
-      if (!gimple_no_warning_p (stmt))
+      if (!get_no_warning (stmt, OPT_Wstringop_overread))
 	warn_string_no_nul (loc, NULL_TREE, "stpcpy", src, data.decl, size,
 			    exact);
-      gimple_set_no_warning (stmt, true);
+      set_no_warning (stmt, OPT_Wstringop_overread);
       return false;
     }
 
@@ -3550,8 +3551,7 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator *gsi)
 
       /* Propagate the NO_WARNING bit to avoid issuing the same
 	 warning more than once.  */
-      if (gimple_no_warning_p (stmt))
-	gimple_set_no_warning (repl, true);
+      copy_no_warning (repl, stmt);
 
       gimple_seq_add_stmt_without_update (&stmts, repl);
       if (tree lhs = gimple_call_lhs (stmt))
@@ -3603,8 +3603,7 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator *gsi)
 
       /* Propagate the NO_WARNING bit to avoid issuing the same
 	 warning more than once.  */
-      if (gimple_no_warning_p (stmt))
-	gimple_set_no_warning (repl, true);
+      copy_no_warning (repl, stmt);
 
       gimple_seq_add_stmt_without_update (&stmts, repl);
       if (tree lhs = gimple_call_lhs (stmt))
@@ -6062,7 +6061,7 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree))
 {
   bool changed = false;
   gimple *stmt = gsi_stmt (*gsi);
-  bool nowarning = gimple_no_warning_p (stmt);
+  bool nowarning = get_no_warning (stmt, OPT_Wstrict_overflow);
   unsigned i;
   fold_defer_overflow_warnings ();
 
diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c
index eb23cd41f4b..2dafe849ad3 100644
--- a/gcc/gimple-ssa-isolate-paths.c
+++ b/gcc/gimple-ssa-isolate-paths.c
@@ -400,6 +400,11 @@ diag_returned_locals (bool maybe, const locmap_t &locmap)
       gimple *stmt = (*it).first;
       const args_loc_t &argsloc = (*it).second;
       location_t stmtloc = gimple_location (stmt);
+      if (stmtloc == UNKNOWN_LOCATION)
+	/* When multiple return statements are merged into one it
+	   may not have an associated location.  Use the location
+	   of the closing brace instead.  */
+	stmtloc = cfun->function_end_locus;
 
       auto_diagnostic_group d;
       unsigned nargs = argsloc.locvec.length ();
diff --git a/gcc/gimple-ssa-nonnull-compare.c b/gcc/gimple-ssa-nonnull-compare.c
index 9d7894633dc..517e791204f 100644
--- a/gcc/gimple-ssa-nonnull-compare.c
+++ b/gcc/gimple-ssa-nonnull-compare.c
@@ -97,7 +97,7 @@ do_warn_nonnull_compare (function *fun, tree arg)
       if (op
 	  && (POINTER_TYPE_P (TREE_TYPE (arg))
 	      ? integer_zerop (op) : integer_minus_onep (op))
-	  && !gimple_no_warning_p (stmt))
+	  && !get_no_warning (stmt, OPT_Wnonnull_compare))
 	warning_at (loc, OPT_Wnonnull_compare,
 		    "%<nonnull%> argument %qD compared to NULL", arg);
     }
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index fc744669e4b..ed69a73c183 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -4680,7 +4680,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
 
   bool success = compute_format_length (info, &res, ptr_qry.rvals);
   if (res.warned)
-    gimple_set_no_warning (info.callstmt, true);
+    set_no_warning (info.callstmt, info.warnopt ());
 
   /* When optimizing and the printf return value optimization is enabled,
      attempt to substitute the computed result for the return value of
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 123c92d9b44..51128f4482b 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -4348,10 +4348,12 @@ imm_store_chain_info::output_merged_store (merged_store_group *group)
 		      MR_DEPENDENCE_BASE (ops[j]) = base;
 		    }
 		  if (!integer_zerop (mask))
-		    /* The load might load some bits (that will be masked off
-		       later on) uninitialized, avoid -W*uninitialized
-		       warnings in that case.  */
-		    TREE_NO_WARNING (ops[j]) = 1;
+		    {
+		      /* The load might load some bits (that will be masked
+			 off later on) uninitialized, avoid -W*uninitialized
+			 warnings in that case.  */
+		      set_no_warning (ops[j], OPT_Wuninitialized);
+		    }
 
 		  stmt = gimple_build_assign (make_ssa_name (dest_type), ops[j]);
 		  gimple_set_location (stmt, load_loc);
@@ -4533,7 +4535,7 @@ imm_store_chain_info::output_merged_store (merged_store_group *group)
 		 provably uninitialized (no stores at all yet or previous
 		 store a CLOBBER) we'd optimize away the load and replace
 		 it e.g. with 0.  */
-	      TREE_NO_WARNING (load_src) = 1;
+	      set_no_warning (load_src, OPT_Wuninitialized);
 	      stmt = gimple_build_assign (tem, load_src);
 	      gimple_set_location (stmt, loc);
 	      gimple_set_vuse (stmt, new_vuse);
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index ad37f20afaa..c4a773a45ff 100644
--- a/gcc/gimple-ssa-warn-restrict.c
+++ b/gcc/gimple-ssa-warn-restrict.c
@@ -1425,7 +1425,7 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
   if (!acs.overlap ())
     return false;
 
-  if (gimple_no_warning_p (call))
+  if (get_no_warning (call, OPT_Wrestrict))
     return true;
 
   /* For convenience.  */
@@ -1677,7 +1677,7 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
    validated.  Return true if the offsets are not valid and a diagnostic
    has been issued, or would have been issued if DO_WARN had been true.  */
 
-static bool
+static int
 maybe_diag_access_bounds (gimple *call, tree func, int strict,
 			  const builtin_memref &ref, offset_int wroff,
 			  bool do_warn)
@@ -1689,28 +1689,31 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
      since the result is used to make codegen decisions.  */
   if (ref.sizrange[0] > maxobjsize)
     {
+      const int opt = OPT_Wstringop_overflow_;
       /* Return true without issuing a warning.  */
       if (!do_warn)
-	return true;
+	return opt;
 
-      if (ref.ref && TREE_NO_WARNING (ref.ref))
-	return false;
+      if (ref.ref && get_no_warning (ref.ref, OPT_Wstringop_overflow_))
+	return 0;
 
+      bool warned = false;
       if (warn_stringop_overflow)
 	{
 	  if (ref.sizrange[0] == ref.sizrange[1])
-	    return warning_at (loc, OPT_Wstringop_overflow_,
-			       "%G%qD specified bound %wu "
-			       "exceeds maximum object size %wu",
-			       call, func, ref.sizrange[0].to_uhwi (),
-			       maxobjsize.to_uhwi ());
-
-	  return warning_at (loc, OPT_Wstringop_overflow_,
-			     "%G%qD specified bound between %wu and %wu "
-			     "exceeds maximum object size %wu",
-			     call, func, ref.sizrange[0].to_uhwi (),
-			     ref.sizrange[1].to_uhwi (),
-			     maxobjsize.to_uhwi ());
+	    warned = warning_at (loc, opt,
+				 "%G%qD specified bound %wu "
+				 "exceeds maximum object size %wu",
+				 call, func, ref.sizrange[0].to_uhwi (),
+				 maxobjsize.to_uhwi ());
+	  else
+	    warned = warning_at (loc, opt,
+				 "%G%qD specified bound between %wu and %wu "
+				 "exceeds maximum object size %wu",
+				 call, func, ref.sizrange[0].to_uhwi (),
+				 ref.sizrange[1].to_uhwi (),
+				 maxobjsize.to_uhwi ());
+	  return warned ? opt : 0;
 	}
     }
 
@@ -1732,8 +1735,8 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
   if (!warn_array_bounds)
     return false;
 
-  if (TREE_NO_WARNING (ref.ptr)
-      || (ref.ref && TREE_NO_WARNING (ref.ref)))
+  if (get_no_warning (ref.ptr, OPT_Warray_bounds )
+      || (ref.ref && get_no_warning (ref.ref, OPT_Warray_bounds)))
     return false;
 
   char rangestr[2][64];
@@ -1877,7 +1880,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	}
     }
 
-  return warned;
+  return warned ? OPT_Warray_bounds : 0;
 }
 
 /* Check a CALL statement for restrict-violations and issue warnings
@@ -1888,7 +1891,7 @@ check_call (range_query *query, gimple *call)
 {
   /* Avoid checking the call if it has already been diagnosed for
      some reason.  */
-  if (gimple_no_warning_p (call))
+  if (get_no_warning (call, OPT_Wrestrict))
     return;
 
   tree func = gimple_call_fndecl (call);
@@ -1974,11 +1977,12 @@ check_call (range_query *query, gimple *call)
       || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr))))
     return;
 
-  if (!check_bounds_or_overlap (query, call, dst, src, dstwr, NULL_TREE))
+  int opt = check_bounds_or_overlap (query, call, dst, src, dstwr, NULL_TREE);
+  if (!opt)
     return;
 
   /* Avoid diagnosing the call again.  */
-  gimple_set_no_warning (call, true);
+  set_no_warning (call, OPT_Wrestrict);
 }
 
 } /* anonymous namespace */
@@ -2026,12 +2030,16 @@ check_bounds_or_overlap (range_query *query,
   /* Validate offsets to each reference before the access first to make
      sure they are within the bounds of the destination object if its
      size is known, or PTRDIFF_MAX otherwise.  */
-  if (maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn)
-      || maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn))
+  int opt
+    = maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn);
+  if (!opt)
+    opt = maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn);
+
+  if (opt)
     {
       if (do_warn)
-	gimple_set_no_warning (call, true);
-      return OPT_Warray_bounds;
+	set_no_warning (call, OPT_Wrestrict);
+      return opt;
     }
 
   if (!warn_restrict || bounds_only || !src)
@@ -2058,12 +2066,12 @@ check_bounds_or_overlap (range_query *query,
 	 not point to objects and so do not indicate an overlap;
 	 such calls could be the result of sanitization and jump
 	 threading).  */
-      if (!integer_zerop (dst) && !gimple_no_warning_p (call))
+      if (!integer_zerop (dst) && !get_no_warning (call, OPT_Wrestrict))
 	{
 	  warning_at (loc, OPT_Wrestrict,
 		      "%G%qD source argument is the same as destination",
 		      call, func);
-	  gimple_set_no_warning (call, true);
+	  set_no_warning (call, OPT_Wrestrict);
 	  return OPT_Wrestrict;
 	}
 
@@ -2073,7 +2081,7 @@ check_bounds_or_overlap (range_query *query,
   /* Return false when overlap has been detected.  */
   if (maybe_diag_overlap (loc, call, acs))
     {
-      gimple_set_no_warning (call, true);
+      set_no_warning (call, OPT_Wrestrict);
       return OPT_Wrestrict;
     }
 
diff --git a/gcc/gimple.c b/gcc/gimple.c
index f1044e9c630..0ff1e9ab304 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -399,7 +399,7 @@ gimple_build_call_from_tree (tree t, tree fnptrtype)
   gimple_call_set_va_arg_pack (call, CALL_EXPR_VA_ARG_PACK (t));
   gimple_call_set_nothrow (call, TREE_NOTHROW (t));
   gimple_call_set_by_descriptor (call, CALL_EXPR_BY_DESCRIPTOR (t));
-  gimple_set_no_warning (call, TREE_NO_WARNING (t));
+  copy_no_warning (call, t);
 
   if (fnptrtype)
     {
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 91b92b4a4d1..f95ce872cb5 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1634,6 +1634,21 @@ extern bool gimple_inexpensive_call_p (gcall *);
 extern bool stmt_can_terminate_bb_p (gimple *);
 extern location_t gimple_or_expr_nonartificial_location (gimple *, tree);
 
+/* Return true if a warning is enabled for the statement.  */
+extern bool get_no_warning (const gimple *, int = -1)
+  ATTRIBUTE_NONNULL (1);
+/* Enable, or by default disable, a warning for the statement.  */
+extern void set_no_warning (gimple *, int = -1, bool = true)
+  ATTRIBUTE_NONNULL (1);
+/* Copy the warning disposition mapping from one statement to another.  */
+extern void copy_no_warning (gimple *, const gimple *)
+  ATTRIBUTE_NONNULL (1) ATTRIBUTE_NONNULL (2);
+/* Copy the warning disposition mapping from an expression to a statement.  */
+extern void copy_no_warning (gimple *, const_tree)
+  ATTRIBUTE_NONNULL (1) ATTRIBUTE_NONNULL (2);
+/* Copy the warning disposition mapping from a statement to an expression.  */
+extern void copy_no_warning (tree, const gimple *)
+  ATTRIBUTE_NONNULL (1) ATTRIBUTE_NONNULL (2);
 
 /* Formal (expression) temporary table handling: multiple occurrences of
    the same scalar expression are evaluated into the same temporary.  */
@@ -1854,16 +1869,17 @@ gimple_block (const gimple *g)
   return LOCATION_BLOCK (g->location);
 }
 
+/* Forward declare.  */
+static inline void gimple_set_location (gimple *, location_t);
 
 /* Set BLOCK to be the lexical scope block holding statement G.  */
 
 static inline void
 gimple_set_block (gimple *g, tree block)
 {
-  g->location = set_block (g->location, block);
+  gimple_set_location (g, set_block (g->location, block));
 }
 
-
 /* Return location information for statement G.  */
 
 static inline location_t
@@ -1886,6 +1902,8 @@ gimple_location_safe (const gimple *g)
 static inline void
 gimple_set_location (gimple *g, location_t location)
 {
+  /* Copy the no-warning data to the statement location.  */
+  copy_no_warning (location, g->location);
   g->location = location;
 }
 
@@ -1948,22 +1966,6 @@ gimple_seq_singleton_p (gimple_seq seq)
 	  && (gimple_seq_first (seq) == gimple_seq_last (seq)));
 }
 
-/* Return true if no warnings should be emitted for statement STMT.  */
-
-static inline bool
-gimple_no_warning_p (const gimple *stmt)
-{
-  return stmt->no_warning;
-}
-
-/* Set the no_warning flag of STMT to NO_WARNING.  */
-
-static inline void
-gimple_set_no_warning (gimple *stmt, bool no_warning)
-{
-  stmt->no_warning = (unsigned) no_warning;
-}
-
 /* Set the visited status on statement STMT to VISITED_P.
 
    Please note that this 'visited' property of the gimple statement is
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 719a4e16391..20445b89e27 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1596,7 +1596,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
     {
       maybe_add_early_return_predict_stmt (pre_p);
       greturn *ret = gimple_build_return (ret_expr);
-      gimple_set_no_warning (ret, TREE_NO_WARNING (stmt));
+      copy_no_warning (ret, stmt);
       gimplify_seq_add_stmt (pre_p, ret);
       return GS_ALL_DONE;
     }
@@ -1658,7 +1658,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
 	 we can wind up warning about an uninitialized value for this.  Due
 	 to how this variable is constructed and initialized, this is never
 	 true.  Give up and never warn.  */
-      TREE_NO_WARNING (result) = 1;
+      set_no_warning (result, OPT_Wuninitialized);
 
       gimplify_ctxp->return_temp = result;
     }
@@ -1672,7 +1672,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
 
   maybe_add_early_return_predict_stmt (pre_p);
   ret = gimple_build_return (result);
-  gimple_set_no_warning (ret, TREE_NO_WARNING (stmt));
+  copy_no_warning (ret, stmt);
   gimplify_seq_add_stmt (pre_p, ret);
 
   return GS_ALL_DONE;
@@ -4244,7 +4244,8 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
 				 &arm2);
   cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true,
 				 label_false);
-  gimple_set_no_warning (cond_stmt, TREE_NO_WARNING (COND_EXPR_COND (expr)));
+  gimple_set_location (cond_stmt, EXPR_LOCATION (expr));
+  copy_no_warning (cond_stmt, COND_EXPR_COND (expr));
   gimplify_seq_add_stmt (&seq, cond_stmt);
   gimple_stmt_iterator gsi = gsi_last (seq);
   maybe_fold_stmt (&gsi);
@@ -5694,7 +5695,7 @@ gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
 
   ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
   other = build1 (ocode, TREE_TYPE (rhs), lhs);
-  TREE_NO_WARNING (other) = 1;
+  set_no_warning (other);
   other = get_formal_tmp_var (other, pre_p);
 
   realpart = code == REALPART_EXPR ? rhs : other;
@@ -5979,7 +5980,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       assign = gimple_build_assign (*to_p, *from_p);
       gimple_set_location (assign, EXPR_LOCATION (*expr_p));
       if (COMPARISON_CLASS_P (*from_p))
-	gimple_set_no_warning (assign, TREE_NO_WARNING (*from_p));
+	copy_no_warning (assign, *from_p);
     }
 
   if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
@@ -6738,7 +6739,7 @@ gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p,
 	  /* Because of this manipulation, and the EH edges that jump
 	     threading cannot redirect, the temporary (VAR) will appear
 	     to be used uninitialized.  Don't warn.  */
-	  TREE_NO_WARNING (var) = 1;
+	  set_no_warning (var, OPT_Wuninitialized);
 	}
     }
   else
@@ -14470,7 +14471,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
 	    gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure);
 	    ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
-	    gimple_set_no_warning (ehf, TREE_NO_WARNING (*expr_p));
+	    copy_no_warning (ehf, *expr_p);
 	    gimplify_seq_add_stmt (pre_p, ehf);
 	    ret = GS_ALL_DONE;
 	    break;
diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c
index 0f843bad79a..dbccbfdeefa 100644
--- a/gcc/omp-expand.c
+++ b/gcc/omp-expand.c
@@ -3845,7 +3845,7 @@ expand_omp_for_generic (struct omp_region *region,
 	  for (i = first_zero_iter1;
 	       i < (fd->ordered ? fd->ordered : fd->collapse); i++)
 	    if (SSA_VAR_P (counts[i]))
-	      TREE_NO_WARNING (counts[i]) = 1;
+	      set_no_warning (counts[i], OPT_Wuninitialized);
 	  gsi_prev (&gsi);
 	  e = split_block (entry_bb, gsi_stmt (gsi));
 	  entry_bb = e->dest;
@@ -3862,7 +3862,7 @@ expand_omp_for_generic (struct omp_region *region,
 	     be executed in that case, so just avoid uninit warnings.  */
 	  for (i = first_zero_iter2; i < fd->ordered; i++)
 	    if (SSA_VAR_P (counts[i]))
-	      TREE_NO_WARNING (counts[i]) = 1;
+	      set_no_warning (counts[i], OPT_Wuninitialized);
 	  if (zero_iter1_bb)
 	    make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
 	  else
@@ -7051,7 +7051,7 @@ expand_omp_taskloop_for_outer (struct omp_region *region,
 	     be executed in that case, so just avoid uninit warnings.  */
 	  for (i = first_zero_iter; i < fd->collapse; i++)
 	    if (SSA_VAR_P (counts[i]))
-	      TREE_NO_WARNING (counts[i]) = 1;
+	      set_no_warning (counts[i], OPT_Wuninitialized);
 	  gsi_prev (&gsi);
 	  edge e = split_block (entry_bb, gsi_stmt (gsi));
 	  entry_bb = e->dest;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index d1136d181b3..cb20fdf7609 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -5614,7 +5614,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
 		 able to notice this and not store anything at all, but
 		 we're generating code too early.  Suppress the warning.  */
 	      if (!by_ref)
-		TREE_NO_WARNING (var) = 1;
+		set_no_warning (var, OPT_Wuninitialized);
 	      break;
 
 	    case OMP_CLAUSE__CONDTEMP_:
@@ -6575,7 +6575,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
       uid = create_tmp_var (ptr_type_node, "simduid");
       /* Don't want uninit warnings on simduid, it is always uninitialized,
 	 but we use it not for the value, but for the DECL_UID only.  */
-      TREE_NO_WARNING (uid) = 1;
+      set_no_warning (uid, OPT_Wuninitialized);
       c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
       OMP_CLAUSE__SIMDUID__DECL (c) = uid;
       OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
@@ -7003,7 +7003,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p,
 	      if (predicate
 		  && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
 		      || OMP_CLAUSE_LINEAR_NO_COPYIN (c)))
-		TREE_NO_WARNING (new_var) = 1;
+		set_no_warning (new_var, OPT_Wuninitialized);
 	    }
 
 	  if (!maybe_simt && simduid && DECL_HAS_VALUE_EXPR_P (new_var))
@@ -7834,7 +7834,7 @@ lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
 	  if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
 	      && !by_ref
 	      && is_task_ctx (ctx))
-	    TREE_NO_WARNING (var) = 1;
+	    set_no_warning (var);
 	  do_in = true;
 	  break;
 
@@ -12388,7 +12388,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 		      {
 			if (is_gimple_reg (var)
 			    && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
-			  TREE_NO_WARNING (var) = 1;
+			  set_no_warning (var);
 			var = build_fold_addr_expr (var);
 		      }
 		    else
@@ -12412,7 +12412,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 			   we'll get a warning for the store to avar.
 			   Don't warn in that case, the mapping might
 			   be implicit.  */
-			TREE_NO_WARNING (var) = 1;
+			set_no_warning (var, OPT_Wuninitialized);
 			gimplify_assign (avar, var, &ilist);
 		      }
 		    avar = build_fold_addr_expr (avar);
@@ -12566,7 +12566,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 		if (omp_is_reference (var))
 		  t = build_simple_mem_ref (var);
 		else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
-		  TREE_NO_WARNING (var) = 1;
+		  set_no_warning (var);
 		if (TREE_CODE (type) != POINTER_TYPE)
 		  t = fold_convert (pointer_sized_int_node, t);
 		t = fold_convert (TREE_TYPE (x), t);
@@ -12579,7 +12579,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 		tree avar = create_tmp_var (TREE_TYPE (var));
 		mark_addressable (avar);
 		if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
-		  TREE_NO_WARNING (var) = 1;
+		  set_no_warning (var);
 		gimplify_assign (avar, var, &ilist);
 		avar = build_fold_addr_expr (avar);
 		gimplify_assign (x, avar, &ilist);
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 02256580c98..c85e9146508 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -9428,7 +9428,7 @@ pass_warn_function_return::execute (function *fun)
   /* If we see "return;" in some basic block, then we do reach the end
      without returning a value.  */
   else if (warn_return_type > 0
-	   && !TREE_NO_WARNING (fun->decl)
+	   && !get_no_warning (fun->decl, OPT_Wreturn_type)
 	   && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fun->decl))))
     {
       FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (fun)->preds)
@@ -9437,14 +9437,14 @@ pass_warn_function_return::execute (function *fun)
 	  greturn *return_stmt = dyn_cast <greturn *> (last);
 	  if (return_stmt
 	      && gimple_return_retval (return_stmt) == NULL
-	      && !gimple_no_warning_p (last))
+	      && !get_no_warning (last, OPT_Wreturn_type))
 	    {
 	      location = gimple_location (last);
 	      if (LOCATION_LOCUS (location) == UNKNOWN_LOCATION)
 		location = fun->function_end_locus;
 	      if (warning_at (location, OPT_Wreturn_type,
 			      "control reaches end of non-void function"))
-		TREE_NO_WARNING (fun->decl) = 1;
+		set_no_warning (fun->decl, OPT_Wreturn_type);
 	      break;
 	    }
 	}
@@ -9452,7 +9452,7 @@ pass_warn_function_return::execute (function *fun)
 	 into __builtin_unreachable () call with BUILTINS_LOCATION.
 	 Recognize those too.  */
       basic_block bb;
-      if (!TREE_NO_WARNING (fun->decl))
+      if (!get_no_warning (fun->decl, OPT_Wreturn_type))
 	FOR_EACH_BB_FN (bb, fun)
 	  if (EDGE_COUNT (bb->succs) == 0)
 	    {
@@ -9476,7 +9476,7 @@ pass_warn_function_return::execute (function *fun)
 		    location = fun->function_end_locus;
 		  if (warning_at (location, OPT_Wreturn_type,
 				  "control reaches end of non-void function"))
-		    TREE_NO_WARNING (fun->decl) = 1;
+		    set_no_warning (fun->decl, OPT_Wreturn_type);
 		  break;
 		}
 	    }
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index d7d991714de..c5d57346023 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -456,12 +456,12 @@ create_one_component_var (tree type, tree orig, const char *prefix,
       SET_DECL_DEBUG_EXPR (r, build1 (code, type, orig));
       DECL_HAS_DEBUG_EXPR_P (r) = 1;
       DECL_IGNORED_P (r) = 0;
-      TREE_NO_WARNING (r) = TREE_NO_WARNING (orig);
+      copy_no_warning (r, orig);
     }
   else
     {
       DECL_IGNORED_P (r) = 1;
-      TREE_NO_WARNING (r) = 1;
+      set_no_warning (r);
     }
 
   return r;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 8f945b88c12..2fea85c34bf 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1116,7 +1116,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
 	  *tp = fold_build2 (MEM_REF, type, ptr, TREE_OPERAND (*tp, 1));
 	  TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
 	  TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old);
-	  TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
+	  copy_no_warning (*tp, old);
 	  if (MR_DEPENDENCE_CLIQUE (old) != 0)
 	    {
 	      MR_DEPENDENCE_CLIQUE (*tp)
@@ -1375,7 +1375,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
 	  *tp = fold_build2 (MEM_REF, type, ptr, TREE_OPERAND (*tp, 1));
 	  TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
 	  TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old);
-	  TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
+	  copy_no_warning (*tp, old);
 	  if (MR_DEPENDENCE_CLIQUE (old) != 0)
 	    {
 	      MR_DEPENDENCE_CLIQUE (*tp)
@@ -3753,7 +3753,7 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
 
   /* Do not have the rest of GCC warn about this variable as it should
      not be visible to the user.  */
-  TREE_NO_WARNING (var) = 1;
+  set_no_warning (var /* OPT_Wuninitialized? */);
 
   declare_inline_vars (id->block, var);
 
@@ -5018,7 +5018,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id,
 	 initialized.  We do not want to issue a warning about that
 	 uninitialized variable.  */
       if (DECL_P (modify_dest))
-	TREE_NO_WARNING (modify_dest) = 1;
+	set_no_warning (modify_dest, OPT_Wuninitialized);
 
       if (gimple_call_return_slot_opt_p (call_stmt))
 	{
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index cea917a4d58..5d9e59134d2 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -411,8 +411,8 @@ lookup_field_for_decl (struct nesting_info *info, tree decl,
 	  DECL_USER_ALIGN (field) = DECL_USER_ALIGN (decl);
 	  DECL_IGNORED_P (field) = DECL_IGNORED_P (decl);
 	  DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (decl);
-	  TREE_NO_WARNING (field) = TREE_NO_WARNING (decl);
 	  TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl);
+	  copy_no_warning (field, decl);
 
 	  /* Declare the transformation and adjust the original DECL.  For a
 	     variable or for a parameter when not optimizing, we make it point
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 8dfc923ed7e..2e3efc31666 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -2240,12 +2240,12 @@ create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
 	  DECL_HAS_DEBUG_EXPR_P (repl) = 1;
 	}
       if (access->grp_no_warning)
-	TREE_NO_WARNING (repl) = 1;
+	set_no_warning (repl /* Be more selective! */);
       else
-	TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
+	copy_no_warning (repl, access->base);
     }
   else
-    TREE_NO_WARNING (repl) = 1;
+    set_no_warning (repl /* Be more selective! */);
 
   if (dump_file)
     {
@@ -3556,7 +3556,7 @@ generate_subtree_copies (struct access *access, tree agg,
 	    }
 	  else
 	    {
-	      TREE_NO_WARNING (repl) = 1;
+	      set_no_warning (repl /* Be more selective! */);
 	      if (access->grp_partial_lhs)
 		repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
 						 !insert_after,
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 3834212b867..f0303492f8e 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -3527,7 +3527,7 @@ pass_post_ipa_warn::execute (function *fun)
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
 	{
 	  gimple *stmt = gsi_stmt (gsi);
-	  if (!is_gimple_call (stmt) || gimple_no_warning_p (stmt))
+	  if (!is_gimple_call (stmt) || get_no_warning (stmt, OPT_Wnonnull))
 	    continue;
 
 	  tree fntype = gimple_call_fntype (stmt);
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 0706fd862de..fa72ff007a2 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -403,7 +403,8 @@ combine_cond_expr_cond (gimple *stmt, enum tree_code code, tree type,
       return NULL_TREE;
     }
 
-  fold_undefer_overflow_warnings (!gimple_no_warning_p (stmt), stmt, 0);
+  bool nowarn = get_no_warning (stmt, OPT_Wstrict_overflow);
+  fold_undefer_overflow_warnings (!nowarn, stmt, 0);
 
   return t;
 }
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index 08caa83b4b4..9051820c8a7 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -458,7 +458,7 @@ ch_base::copy_headers (function *fun)
 			  && gimple_cond_code (stmt) != NE_EXPR
 			  && INTEGRAL_TYPE_P (TREE_TYPE (lhs))
 			  && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs)))
-			gimple_set_no_warning (stmt, true);
+			set_no_warning (stmt, OPT_Wstrict_overflow_);
 		    }
 		  else if (is_gimple_assign (stmt))
 		    {
@@ -469,7 +469,7 @@ ch_base::copy_headers (function *fun)
 			  && rhs_code != NE_EXPR
 			  && INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
 			  && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (rhs1)))
-			gimple_set_no_warning (stmt, true);
+			set_no_warning (stmt, OPT_Wstrict_overflow_);
 		    }
 		}
 	    }
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 8034cf68d27..64c63c6ee8b 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -2143,7 +2143,7 @@ execute_sm (class loop *loop, im_mem_ref *ref,
       /* If not emitting a load mark the uninitialized state on the
 	 loop entry as not to be warned for.  */
       tree uninit = create_tmp_reg (TREE_TYPE (aux->tmp_var));
-      TREE_NO_WARNING (uninit) = 1;
+      set_no_warning (uninit, OPT_Wuninitialized);
       load = gimple_build_assign (aux->tmp_var, uninit);
     }
   lim_data = init_lim_data (load);
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 8e8a08bc679..58b764991ff 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -3014,9 +3014,12 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb,
   new_stmt = gimple_build_assign (name, lhs);
   gimple_set_location (new_stmt, locus);
   lhs = unshare_expr (lhs);
-  /* Set TREE_NO_WARNING on the rhs of the load to avoid uninit
-     warnings.  */
-  TREE_NO_WARNING (gimple_assign_rhs1 (new_stmt)) = 1;
+  {
+    /* Set the no-warning bit on the rhs of the load to avoid uninit
+       warnings.  */
+    tree rhs1 = gimple_assign_rhs1 (new_stmt);
+    set_no_warning (rhs1, OPT_Wuninitialized);
+  }
   gsi_insert_on_edge (e1, new_stmt);
 
   /* 3) Create a PHI node at the join block, with one argument
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index c7b5e2c6e6b..88728a2c7f2 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -1918,7 +1918,7 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
 		     strinfo *si = NULL, bool plus_one = false,
 		     bool rawmem = false)
 {
-  if (!len || gimple_no_warning_p (stmt))
+  if (!len || get_no_warning (stmt, OPT_Wstringop_overflow_))
     return;
 
   /* The DECL of the function performing the write if it is done
@@ -1937,7 +1937,7 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
   else
     return;
 
-  if (TREE_NO_WARNING (dest))
+  if (get_no_warning (dest, OPT_Wstringop_overflow_))
     return;
 
   const int ostype = rawmem ? 0 : 1;
@@ -2081,7 +2081,7 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
   if (!warned)
     return;
 
-  gimple_set_no_warning (stmt, true);
+  set_no_warning (stmt, OPT_Wstringop_overflow_);
 
   aref.inform_access (access_write_only);
 }
@@ -2605,15 +2605,15 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
   len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
 
   /* Set the no-warning bit on the transformed statement?  */
-  bool set_no_warning = false;
+  int no_warning_opt = 0;
 
-  if (const strinfo *chksi = olddsi ? olddsi : dsi)
-    if (si
-	&& check_bounds_or_overlap (stmt, chksi->ptr, si->ptr, NULL_TREE, len))
-      {
-	gimple_set_no_warning (stmt, true);
-	set_no_warning = true;
-      }
+  if (const strinfo *chksi = si ? olddsi ? olddsi : dsi : NULL)
+    {
+      no_warning_opt = check_bounds_or_overlap (stmt, chksi->ptr, si->ptr,
+						NULL_TREE, len);
+      if (no_warning_opt)
+	set_no_warning (stmt, no_warning_opt);
+    }
 
   if (fn == NULL_TREE)
     return;
@@ -2647,8 +2647,8 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
   else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
     fprintf (dump_file, "not possible.\n");
 
-  if (set_no_warning)
-    gimple_set_no_warning (stmt, true);
+  if (no_warning_opt)
+    set_no_warning (stmt, no_warning_opt);
 }
 
 /* Check the size argument to the built-in forms of stpncpy and strncpy
@@ -2776,7 +2776,7 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 			  pointer_query *ptr_qry /* = NULL */)
 {
   gimple *stmt = gsi_stmt (gsi);
-  if (gimple_no_warning_p (stmt))
+  if (get_no_warning (stmt, OPT_Wstringop_truncation))
     return false;
 
   wide_int cntrange[2];
@@ -3135,9 +3135,9 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
   else
     srclenp1 = NULL_TREE;
 
-  if (check_bounds_or_overlap (stmt, dst, src, dstlenp1, srclenp1))
+  if (int opt = check_bounds_or_overlap (stmt, dst, src, dstlenp1, srclenp1))
     {
-      gimple_set_no_warning (stmt, true);
+      set_no_warning (stmt, opt);
       return;
     }
 
@@ -3148,7 +3148,7 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
   if (!pss || pss->first <= 0)
     {
       if (maybe_diag_stxncpy_trunc (*gsi, src, len))
-	gimple_set_no_warning (stmt, true);
+	set_no_warning (stmt, OPT_Wstringop_truncation);
 
       return;
     }
@@ -3428,7 +3428,7 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
     }
 
   /* Set the no-warning bit on the transformed statement?  */
-  bool set_no_warning = false;
+  int no_warning_opt = 0;
 
   if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
     {
@@ -3445,12 +3445,10 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
 	  }
 
 	tree sptr = si && si->ptr ? si->ptr : src;
-
-	if (check_bounds_or_overlap (stmt, dst, sptr, NULL_TREE, slen))
-	  {
-	    gimple_set_no_warning (stmt, true);
-	    set_no_warning = true;
-	  }
+	no_warning_opt = check_bounds_or_overlap (stmt, dst, sptr, NULL_TREE,
+						  slen);
+	if (no_warning_opt)
+	  set_no_warning (stmt, no_warning_opt);
       }
 
       /* strcat (p, q) can be transformed into
@@ -3557,11 +3555,10 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
       tree dstsize = fold_build2 (PLUS_EXPR, type, dstlen, one);
       tree sptr = si && si->ptr ? si->ptr : src;
 
-      if (check_bounds_or_overlap (stmt, dst, sptr, dstsize, srcsize))
-	{
-	  gimple_set_no_warning (stmt, true);
-	  set_no_warning = true;
-	}
+      no_warning_opt = check_bounds_or_overlap (stmt, dst, sptr, dstsize,
+						srcsize);
+      if (no_warning_opt)
+	set_no_warning (stmt, no_warning_opt);
     }
 
   tree len = NULL_TREE;
@@ -3627,8 +3624,8 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
   else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
     fprintf (dump_file, "not possible.\n");
 
-  if (set_no_warning)
-    gimple_set_no_warning (stmt, true);
+  if (no_warning_opt)
+    set_no_warning (stmt, no_warning_opt);
 }
 
 /* Handle a call to an allocation function like alloca, malloc or calloc,
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index f55ce1939ac..e1d50ab92a7 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -86,17 +86,33 @@ has_undefined_value_p (tree t)
 	      && possibly_undefined_names->contains (t)));
 }
 
-/* Like has_undefined_value_p, but don't return true if TREE_NO_WARNING
-   is set on SSA_NAME_VAR.  */
+/* Return true if EXPR should suppress either uninitialized warning.  */
+
+static inline bool
+get_no_uninit_warning (tree expr)
+{
+  return get_no_warning (expr, OPT_Wuninitialized);
+}
+
+/* Suppress both uninitialized warnings for EXPR.  */
+
+static inline void
+set_no_uninit_warning (tree expr)
+{
+  set_no_warning (expr, OPT_Wuninitialized);
+}
+
+/* Like has_undefined_value_p, but don't return true if the no-warning
+   bit is set on SSA_NAME_VAR for either uninit warning.  */
 
 static inline bool
 uninit_undefined_value_p (tree t)
 {
   if (!has_undefined_value_p (t))
     return false;
-  if (SSA_NAME_VAR (t) && TREE_NO_WARNING (SSA_NAME_VAR (t)))
-    return false;
-  return true;
+  if (!SSA_NAME_VAR (t))
+    return true;
+  return !get_no_uninit_warning (SSA_NAME_VAR (t));
 }
 
 /* Emit warnings for uninitialized variables.  This is done in two passes.
@@ -164,10 +180,10 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var,
   /* TREE_NO_WARNING either means we already warned, or the front end
      wishes to suppress the warning.  */
   if ((context
-       && (gimple_no_warning_p (context)
+       && (get_no_warning (context, OPT_Wuninitialized)
 	   || (gimple_assign_single_p (context)
-	       && TREE_NO_WARNING (gimple_assign_rhs1 (context)))))
-      || TREE_NO_WARNING (expr))
+	       && get_no_uninit_warning (gimple_assign_rhs1 (context)))))
+      || get_no_uninit_warning (expr))
     return;
 
   if (context != NULL && gimple_has_location (context))
@@ -184,7 +200,7 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var,
   auto_diagnostic_group d;
   if (warning_at (location, wc, gmsgid, expr))
     {
-      TREE_NO_WARNING (expr) = 1;
+      set_no_warning (expr, wc);
 
       if (location == DECL_SOURCE_LOCATION (var))
 	return;
@@ -259,7 +275,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
   use_operand_p luse_p;
   imm_use_iterator liter;
 
-  if (TREE_NO_WARNING (rhs))
+  if (get_no_uninit_warning (rhs))
     return NULL_TREE;
 
   /* Do not warn if the base was marked so or this is a
@@ -267,7 +283,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
   tree base = ao_ref_base (&ref);
   if ((VAR_P (base)
        && DECL_HARD_REGISTER (base))
-      || TREE_NO_WARNING (base))
+      || get_no_uninit_warning (base))
     return NULL_TREE;
 
   /* Do not warn if the access is fully outside of the variable.  */
@@ -406,7 +422,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
     rhs = TREE_OPERAND (rhs, 0);
 
   /* Check again since RHS may have changed above.  */
-  if (TREE_NO_WARNING (rhs))
+  if (get_no_uninit_warning (rhs))
     return NULL_TREE;
 
   /* Avoid warning about empty types such as structs with no members.
@@ -434,7 +450,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
 	     uses or accesses by functions as it may hide important
 	     locations.  */
 	  if (lhs)
-	    TREE_NO_WARNING (rhs) = 1;
+	    set_no_uninit_warning (rhs);
 	  warned = true;
 	}
     }
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 12e6e6f3e22..d9aede22d6e 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -406,10 +406,10 @@ compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p)
 	return -2;
 
       if (strict_overflow_p != NULL
-	  /* Symbolic range building sets TREE_NO_WARNING to declare
+	  /* Symbolic range building sets the no-warning bit to declare
 	     that overflow doesn't happen.  */
-	  && (!inv1 || !TREE_NO_WARNING (val1))
-	  && (!inv2 || !TREE_NO_WARNING (val2)))
+	  && (!inv1 || !get_no_warning (val1, OPT_Woverflow))
+	  && (!inv2 || !get_no_warning (val2, OPT_Woverflow)))
 	*strict_overflow_p = true;
 
       if (!inv1)
@@ -432,10 +432,10 @@ compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p)
 	return -2;
 
       if (strict_overflow_p != NULL
-	  /* Symbolic range building sets TREE_NO_WARNING to declare
+	  /* Symbolic range building sets the no-warning bit to declare
 	     that overflow doesn't happen.  */
-	  && (!sym1 || !TREE_NO_WARNING (val1))
-	  && (!sym2 || !TREE_NO_WARNING (val2)))
+	  && (!sym1 || !get_no_warning (val1, OPT_Woverflow))
+	  && (!sym2 || !get_no_warning (val2, OPT_Woverflow)))
 	*strict_overflow_p = true;
 
       const signop sgn = TYPE_SIGN (TREE_TYPE (val1));
diff --git a/gcc/tree.h b/gcc/tree.h
index 64612cfa368..37593d0a3d8 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -699,13 +699,6 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
 /* Determines whether an ENUMERAL_TYPE has defined the list of constants. */
 #define ENUM_IS_OPAQUE(NODE) (ENUMERAL_TYPE_CHECK (NODE)->base.private_flag)
 
-/* In an expr node (usually a conversion) this means the node was made
-   implicitly and should not lead to any sort of warning.  In a decl node,
-   warnings concerning the decl should be suppressed.  This is used at
-   least for used-before-set warnings, and it set after one warning is
-   emitted.  */
-#define TREE_NO_WARNING(NODE) ((NODE)->base.nowarning_flag)
-
 /* Nonzero if we should warn about the change in empty class parameter
    passing ABI in this TU.  */
 #define TRANSLATION_UNIT_WARN_EMPTY_P(NODE) \
@@ -6430,4 +6423,22 @@ public:
   operator location_t () const { return m_combined_loc; }
 };
 
+/* Return true if a warning is enabled for the decl/expression.  */
+extern bool get_no_warning (const_tree, int = -1) ATTRIBUTE_NONNULL (1);
+/* Enable, or by default disable, a warning for the expression.  */
+extern void set_no_warning (tree, int = -1, bool = true)
+  ATTRIBUTE_NONNULL (1);
+/* Copy the warning disposition mapping from one expression to another.  */
+extern void copy_no_warning (tree, const_tree)
+  ATTRIBUTE_NONNULL (1) ATTRIBUTE_NONNULL (2);
+
+/* Return the disposition for a warning (or all warnings by default)
+   at a location.  */
+extern bool get_no_warning (location_t, int = -1);
+/* Set the disposition for a warning (or all warnings by default)
+   at a location to disabled by default.  */
+extern bool set_no_warning (location_t, int = -1, bool = true);
+/* Copy warning disposition from one location to another.  */
+extern void copy_no_warning (location_t, location_t);
+
 #endif  /* GCC_TREE_H  */
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 02bc0db9088..67c0e35033a 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -697,7 +697,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
 				   build_int_cst (TREE_TYPE (max), 1));
 	      /* Signal to compare_values_warnv this expr doesn't overflow.  */
 	      if (EXPR_P (max))
-		TREE_NO_WARNING (max) = 1;
+		set_no_warning (max, OPT_Woverflow);
 	    }
 
 	  vr_p->update (min, max);
@@ -737,7 +737,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
 				   build_int_cst (TREE_TYPE (min), 1));
 	      /* Signal to compare_values_warnv this expr doesn't overflow.  */
 	      if (EXPR_P (min))
-		TREE_NO_WARNING (min) = 1;
+		set_no_warning (min, OPT_Woverflow);
 	    }
 
 	  vr_p->update (min, max);
@@ -3353,7 +3353,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
 	  max = fold_build2 (MINUS_EXPR, TREE_TYPE (op0), max, one);
 	  /* Signal to compare_values_warnv this expr doesn't overflow.  */
 	  if (EXPR_P (max))
-	    TREE_NO_WARNING (max) = 1;
+	    set_no_warning (max, OPT_Woverflow);
 	}
     }
   else if (cond_code == GE_EXPR || cond_code == GT_EXPR)
@@ -3367,7 +3367,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
 	  min = fold_build2 (PLUS_EXPR, TREE_TYPE (op0), min, one);
 	  /* Signal to compare_values_warnv this expr doesn't overflow.  */
 	  if (EXPR_P (min))
-	    TREE_NO_WARNING (min) = 1;
+	    set_no_warning (min, OPT_Woverflow);
 	}
     }
 

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/11] warning control by group and location (PR 74765)
  2021-05-24 22:02 [PATCH 0/11] warning control by group and location (PR 74765) Martin Sebor
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
@ 2021-05-24 23:08 ` David Malcolm
  2021-05-25  0:42   ` Martin Sebor
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
  2021-05-30  2:06 ` [PATCH 0/11] " Jeff Law
  2 siblings, 2 replies; 98+ messages in thread
From: David Malcolm @ 2021-05-24 23:08 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

On Mon, 2021-05-24 at 16:02 -0600, Martin Sebor wrote:
> Having just one bit control whether an expression or statement should
> be allowed to trigger warnings has been a source of bug reports about
> false negatives for years.  PR 74765 has a representative test case
> that shows how by setting the bit to avoid -Wparentheses the C++ front
> end also ends up preventing valid -Wuninitialized in the middle end,

For reference, PR 74765 has:

int foo(int x, int y)
{
    int i;
    if ((i ==0)) return x;
    return y;
}

int foo2(int x, int y)
{
    int i;
    if (i ==0) return x;
    return y;
}

where both fns have an uninitialized use of "i", but the double-parens
in "foo" have already been warned about, so TREE_NO_WARNING is set,
hence we don't get an uninit warning, right?

> but there are other such reports for C (e.g., PR 74762) as well as
> the middle end.


> This patch series solves the problem by associating an expression
> (whether a tree node or a GIMPLE statement) with more than one such
> bit through its location.  Each new bit in the mapping corresponds
> to a group of warnings (e.g., lexical, access, etc.), and each
> location may be associated with a simple bitmap with one bit for
> each group.  The initial groups are mostly ad hoc and should be
> refined over time.

The overall idea looks promising, thanks.

I didn't see any test cases in the patch kit; do you have some that
demonstrate the fixes for the above PRs?

I'm slightly nervous that, although we're gaining granularity in terms
of the different categories of warning, do we risk losing granularity
due to expressions sharing locations?

>   The rare expressions that have no location
> continue to have just one bit[1].

Where does this get stored?  I see the final patch in the kit removes
TREE_NO_WARNING, but I don't quite follow the logic for where the bit
would then be stored for an expr with UNKNOWN_LOCATION.

> 
> The first patch introduces three new APIs without making use of them
> in existing code:
> 
>    bool get_no_warning (..., int option);
>    void set_no_warning (..., int option, ...);
>    void copy_no_warning (...);

Is it possible to use "enum opt_code" (from the generated options.h)
rather than a plain "int" for these?  Or is this not available
everywhere we use these?

> 
> Subsequent patches then replace invocations of the TREE_NO_WARNING()
> macro and the gimple_no_warning_p() and gimple_set_no_warning()
> functions throughout GCC with those and remove the legacy APIs to
> keep them from being accidentally reintroduced along with the
> problem.
> These are mostly mechanical changes, except that most of the new
> invocations also specify the option whose disposition to query for
> the expression or location, or which to enable or disable[2].
> The last function, copy_no_warning(), copies the disposition from
> one expression or location to another.
> 
> A couple of design choices might be helpful to explain:
> 
> First, introducing "warning groups" rather than controlling each
> individual warning is motivated by a) the fact that the latter
> would make avoiding redundant warnings for related problems
> cumbersome (e.g., after issuing a -Warray-bounds we want to
> suppress -Wstringop-overflow as well -Wstringop-overread for
> the same access and vice versa), and b) simplicity and efficiency
> of the implementation (mapping each option would require a more
> complex data structure like a bitmap).
> 
> Second, using location_t to associate expressions/statements with
> the warning groups also turns out to be more useful in practice
> than a direct association between a tree or gimple*, and also
> simplifies managing the data structure.  Trees and gimple* come
> and go across passes, and maintaining a mapping for them that
> accounts for the possibility of them being garbage-collected
> and the same addresses reused is less than straightforward.

I find some of the terminology rather awkard due to it the negation
we're already using with TREE_NO_WARNING, in that we're turning on a
no_warning flag, and that this is a per-location/expr/stmt thing that's
different from the idea of enabling/disabling a specific warning
altogether (and the pragmas that control that).   Sometimes the patches
refer to enabling/disabling warnings and I think I want "enabling" and
"disabling" to mean the thing the user does with -Wfoo and -Wno-foo.

Would calling it a "warning suppression" or somesuch be more or less
klunky?

> 
> Martin
> 
> [1] My expectation is to work toward providing locations for all
> expressions/statements, even if it's the opening or closing brace
> of the function they're used in.)
> 
> [2] A number of {get,set}_no_warning() calls introduced by the patch
> don't provide an option argument and query or set just the one bit in
> the expression/statement.  Some of these may be correct as they are,
> but others could be refined to also specify an option.  I can do that
> in a follow-up patch if someone helps me find the right option.


Hope this is constructive
Dave


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 11/11] use xxx_no_warning APIs in the middle end
  2021-05-24 22:16   ` [PATCH 11/11] use xxx_no_warning APIs in the middle end Martin Sebor
@ 2021-05-24 23:08     ` David Malcolm
  2021-05-25  0:44       ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: David Malcolm @ 2021-05-24 23:08 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

On Mon, 2021-05-24 at 16:16 -0600, Martin Sebor via Gcc-patches wrote:
> The attached patch replaces TREE_NO_WARNING, gimple_get_no_warning_p
> and gimple_set_no_warning with the new APIs, get_no_warning,
> set_no_warning, and copy_no_warning.

Might be worth splitting this out into
(a) the middle-end changes versus
(b) the final changes that remove the old mechanisms.

Is this missing a change to remove "nowarning_flag" from the pertinent
tree struct?

Dave


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/11] warning control by group and location (PR 74765)
  2021-05-24 23:08 ` [PATCH 0/11] warning control by group and location (PR 74765) David Malcolm
@ 2021-05-25  0:42   ` Martin Sebor
  2021-05-25  9:04     ` Richard Biener
  2021-05-27 11:19     ` Richard Sandiford
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
  1 sibling, 2 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-25  0:42 UTC (permalink / raw)
  To: David Malcolm, gcc-patches

On 5/24/21 5:08 PM, David Malcolm wrote:
> On Mon, 2021-05-24 at 16:02 -0600, Martin Sebor wrote:
>> Having just one bit control whether an expression or statement should
>> be allowed to trigger warnings has been a source of bug reports about
>> false negatives for years.  PR 74765 has a representative test case
>> that shows how by setting the bit to avoid -Wparentheses the C++ front
>> end also ends up preventing valid -Wuninitialized in the middle end,

Thanks for the quick reply!

> 
> For reference, PR 74765 has:
> 
> int foo(int x, int y)
> {
>      int i;
>      if ((i ==0)) return x;
>      return y;
> }
> 
> int foo2(int x, int y)
> {
>      int i;
>      if (i ==0) return x;
>      return y;
> }
> 
> where both fns have an uninitialized use of "i", but the double-parens
> in "foo" have already been warned about, so TREE_NO_WARNING is set,
> hence we don't get an uninit warning, right?

Yes, close.  The double parens are used to suppress warning about
assignment in the if condition (-Wparentheses).  The suppression is
applied to the equality expression which then turns into a GIMPLE_COND
statement with the no-warning set. -Wuninitialized then avoids
triggering because it sees the no-warning bit set on the GIMPLE_COND.

> 
>> but there are other such reports for C (e.g., PR 74762) as well as
>> the middle end.
> 
> 
>> This patch series solves the problem by associating an expression
>> (whether a tree node or a GIMPLE statement) with more than one such
>> bit through its location.  Each new bit in the mapping corresponds
>> to a group of warnings (e.g., lexical, access, etc.), and each
>> location may be associated with a simple bitmap with one bit for
>> each group.  The initial groups are mostly ad hoc and should be
>> refined over time.
> 
> The overall idea looks promising, thanks.
> 
> I didn't see any test cases in the patch kit; do you have some that
> demonstrate the fixes for the above PRs?

Yes.  I have a test case for PR 74765 in my tree and but I missed
including it in the patch series.  I have also started going through
Bugzilla looking for other similar reports.  I'll include those I
find in the revised patch.

> 
> I'm slightly nervous that, although we're gaining granularity in terms
> of the different categories of warning, do we risk losing granularity
> due to expressions sharing locations?

If it's possible for two expressions or statements, say A and B, to
have the same location (is it?) then suppressing warning X for A and
a different warning Y for B would also suppress X for B.  (Note that
both A and B would have to have the existing no-warning bit set for
this to happen).  I haven't seen this happen and I can't off hand
think of how to get into a situation like that.

> 
>>    The rare expressions that have no location
>> continue to have just one bit[1].
> 
> Where does this get stored?  I see the final patch in the kit removes
> TREE_NO_WARNING, but I don't quite follow the logic for where the bit
> would then be stored for an expr with UNKNOWN_LOCATION.

The patch just removes the TREE_NO_WARNING macro (along with
the gimple_no_warning_p/gimple_set_no_warning) functions but not
the no-warning bit itself.  It removes them to avoid accidentally
modifying the bit alone without going through the new API and
updating the location -> warning group mapping.  The bit is still
needed for expression/statements with no location.

> 
>>
>> The first patch introduces three new APIs without making use of them
>> in existing code:
>>
>>     bool get_no_warning (..., int option);
>>     void set_no_warning (..., int option, ...);
>>     void copy_no_warning (...);
> 
> Is it possible to use "enum opt_code" (from the generated options.h)
> rather than a plain "int" for these?  Or is this not available
> everywhere we use these?

I was tempted to do it but I resisted because the existing warning
APIs take an int as an argument.  It doesn't look like there's
a problem with #including "options.h" in the diagnostic subsystem
so I'm down with changing the argument to opt_code.

>> Subsequent patches then replace invocations of the TREE_NO_WARNING()
>> macro and the gimple_no_warning_p() and gimple_set_no_warning()
>> functions throughout GCC with those and remove the legacy APIs to
>> keep them from being accidentally reintroduced along with the
>> problem.
>> These are mostly mechanical changes, except that most of the new
>> invocations also specify the option whose disposition to query for
>> the expression or location, or which to enable or disable[2].
>> The last function, copy_no_warning(), copies the disposition from
>> one expression or location to another.
>>
>> A couple of design choices might be helpful to explain:
>>
>> First, introducing "warning groups" rather than controlling each
>> individual warning is motivated by a) the fact that the latter
>> would make avoiding redundant warnings for related problems
>> cumbersome (e.g., after issuing a -Warray-bounds we want to
>> suppress -Wstringop-overflow as well -Wstringop-overread for
>> the same access and vice versa), and b) simplicity and efficiency
>> of the implementation (mapping each option would require a more
>> complex data structure like a bitmap).
>>
>> Second, using location_t to associate expressions/statements with
>> the warning groups also turns out to be more useful in practice
>> than a direct association between a tree or gimple*, and also
>> simplifies managing the data structure.  Trees and gimple* come
>> and go across passes, and maintaining a mapping for them that
>> accounts for the possibility of them being garbage-collected
>> and the same addresses reused is less than straightforward.
> 
> I find some of the terminology rather awkard due to it the negation
> we're already using with TREE_NO_WARNING, in that we're turning on a
> no_warning flag, and that this is a per-location/expr/stmt thing that's
> different from the idea of enabling/disabling a specific warning
> altogether (and the pragmas that control that).   Sometimes the patches
> refer to enabling/disabling warnings and I think I want "enabling" and
> "disabling" to mean the thing the user does with -Wfoo and -Wno-foo.
> 
> Would calling it a "warning suppression" or somesuch be more or less
> klunky?

I like warning suppression :)  But I'm not sure where you suggest
I use the phrase.

I don't particularly care for the "no" in the API names either
(existing or new) and would prefer a positive form.  I considered
enable_warning() and warning_enabled() but I chose the names I did
because they're close to their established gimple namesakes.  I'm
fine changing them to the alternatives, or if you or someone else
has a preference for different names I'm open to suggestions.  Let
me know.

>>
>> Martin
>>
>> [1] My expectation is to work toward providing locations for all
>> expressions/statements, even if it's the opening or closing brace
>> of the function they're used in.)
>>
>> [2] A number of {get,set}_no_warning() calls introduced by the patch
>> don't provide an option argument and query or set just the one bit in
>> the expression/statement.  Some of these may be correct as they are,
>> but others could be refined to also specify an option.  I can do that
>> in a follow-up patch if someone helps me find the right option.
> 
> 
> Hope this is constructive
> Dave
> 

Yes, thanks.
Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 11/11] use xxx_no_warning APIs in the middle end
  2021-05-24 23:08     ` David Malcolm
@ 2021-05-25  0:44       ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-25  0:44 UTC (permalink / raw)
  To: David Malcolm, Martin Sebor, gcc-patches

On 5/24/21 5:08 PM, David Malcolm via Gcc-patches wrote:
> On Mon, 2021-05-24 at 16:16 -0600, Martin Sebor via Gcc-patches wrote:
>> The attached patch replaces TREE_NO_WARNING, gimple_get_no_warning_p
>> and gimple_set_no_warning with the new APIs, get_no_warning,
>> set_no_warning, and copy_no_warning.
> 
> Might be worth splitting this out into
> (a) the middle-end changes versus
> (b) the final changes that remove the old mechanisms.

Sure, I can do that.

> 
> Is this missing a change to remove "nowarning_flag" from the pertinent
> tree struct?

No, the bit is still used and needed when a tree or GIMPLE statement
has no location.

Martin

> 
> Dave
> 


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 2/11] use xxx_no_warning APIs in Ada
  2021-05-24 22:09   ` [PATCH 2/11] use xxx_no_warning APIs in Ada Martin Sebor
@ 2021-05-25  8:59     ` Eric Botcazou
  2021-05-27 20:29       ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: Eric Botcazou @ 2021-05-25  8:59 UTC (permalink / raw)
  To: Martin Sebor; +Cc: gcc-patches

> [PATCH 2/11] use xxx_no_warning APIs in Ada.

Looks good to me, but remove the useless pair of parentheses in the 3rd hunk.

-- 
Eric Botcazou



^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/11] warning control by group and location (PR 74765)
  2021-05-25  0:42   ` Martin Sebor
@ 2021-05-25  9:04     ` Richard Biener
  2021-05-25 20:50       ` Martin Sebor
  2021-05-27 11:19     ` Richard Sandiford
  1 sibling, 1 reply; 98+ messages in thread
From: Richard Biener @ 2021-05-25  9:04 UTC (permalink / raw)
  To: Martin Sebor; +Cc: David Malcolm, gcc-patches

On Tue, May 25, 2021 at 2:53 AM Martin Sebor via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> On 5/24/21 5:08 PM, David Malcolm wrote:
> > On Mon, 2021-05-24 at 16:02 -0600, Martin Sebor wrote:
> >>    The rare expressions that have no location
> >> continue to have just one bit[1].
> >
> > Where does this get stored?  I see the final patch in the kit removes
> > TREE_NO_WARNING, but I don't quite follow the logic for where the bit
> > would then be stored for an expr with UNKNOWN_LOCATION.
>
> The patch just removes the TREE_NO_WARNING macro (along with
> the gimple_no_warning_p/gimple_set_no_warning) functions but not
> the no-warning bit itself.  It removes them to avoid accidentally
> modifying the bit alone without going through the new API and
> updating the location -> warning group mapping.  The bit is still
> needed for expression/statements with no location.

I wonder if we could clone UNKNOWN_LOCATION, thus when
we set_no_warning on UNKNOWN_LOCATION create a new location
with the source location being still UNKNOWN but with the appropriate
ad-hoc data to disable the warning?  That of course requires the
API to be

location_t set_no_warning (...)

and users would need to update the container with the new location
(or we'd need to use a reference we can update in set_no_warning).

That said - do you have any stats on how many UNKNOWN_LOCATION
locations we run into with boostrap / the testsuite?

Otherwise thanks for tackling this long-standing issue.

Richard.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 8/11] use xxx_no_warning APIs in Objective-C
  2021-05-24 22:14   ` [PATCH 8/11] use xxx_no_warning APIs in Objective-C Martin Sebor
@ 2021-05-25 14:01     ` Iain Sandoe
  2021-05-25 15:48       ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: Iain Sandoe @ 2021-05-25 14:01 UTC (permalink / raw)
  To: Martin Sebor; +Cc: gcc-patches

Hi Martin

Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:

> The attached patch replaces the uses of TREE_NO_WARNING in
> the Objective-C front end.
> <gcc-no-warning-objc.diff>

I’ve been gradually trying to improve/add locations in the ObjC stuff.

To that end, I wonder if it might be worth considering always supplying
the intended masked warning (rather than omitting this when the node
currently has no location).  I guess that would mean that the setter/getter
would need to determine if there was some suitable location (more work
but better abstraction).

This would mean that an improvement/addition to location would automatically
gain the improvement in masked warnings.

This is not an objection (the patch is OK for ObjC as is) .. just a question,

thanks
Iain


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 8/11] use xxx_no_warning APIs in Objective-C
  2021-05-25 14:01     ` Iain Sandoe
@ 2021-05-25 15:48       ` Martin Sebor
  2021-05-25 15:56         ` Iain Sandoe
  0 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-05-25 15:48 UTC (permalink / raw)
  To: Iain Sandoe, Martin Sebor; +Cc: gcc-patches

On 5/25/21 8:01 AM, Iain Sandoe via Gcc-patches wrote:
> Hi Martin
> 
> Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
> 
>> The attached patch replaces the uses of TREE_NO_WARNING in
>> the Objective-C front end.
>> <gcc-no-warning-objc.diff>
> 
> I’ve been gradually trying to improve/add locations in the ObjC stuff.
> 
> To that end, I wonder if it might be worth considering always supplying
> the intended masked warning (rather than omitting this when the node
> currently has no location).  I guess that would mean that the setter/getter
> would need to determine if there was some suitable location (more work
> but better abstraction).
> 
> This would mean that an improvement/addition to location would 
> automatically
> gain the improvement in masked warnings.
> 
> This is not an objection (the patch is OK for ObjC as is) .. just a 
> question,

I'm not sure I understand correctly.

Let me try to clarify: The calls to the {get,set}_no_warning() with
no option introduced by the patch are of two kinds: one where
the intent is to query or suppress all warnings for an expression
(or a DECL, like a synthesized artificial temporary), and another
where it's not apparent from the code which warning is meant to
be queried or suppressed.  I think all the ones in the ObjC front
end are of the latter sort.  (None of these calls are due to
the location being unknown.)

With that, if you are suggesting to try to find the suitable option
to pass to the latter kind of calls above, I agree.  If you have
ideas for what those might be I can give them a try.  Looking at
the ObjC suppression code again, all the set_no_warning() calls
with no option are for what looks like synthesized types, so
maybe that's a clue: could -Wunused be the warning we want to
suppress there?

Martin

> 
> thanks
> Iain
> 


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 8/11] use xxx_no_warning APIs in Objective-C
  2021-05-25 15:48       ` Martin Sebor
@ 2021-05-25 15:56         ` Iain Sandoe
  0 siblings, 0 replies; 98+ messages in thread
From: Iain Sandoe @ 2021-05-25 15:56 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Martin Sebor, gcc-patches

Martin Sebor <msebor@gmail.com> wrote:

> On 5/25/21 8:01 AM, Iain Sandoe via Gcc-patches wrote:
>> Hi Martin
>> Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>>> The attached patch replaces the uses of TREE_NO_WARNING in
>>> the Objective-C front end.
>>> <gcc-no-warning-objc.diff>
>> I’ve been gradually trying to improve/add locations in the ObjC stuff.
>> To that end, I wonder if it might be worth considering always supplying
>> the intended masked warning (rather than omitting this when the node
>> currently has no location).  I guess that would mean that the  
>> setter/getter
>> would need to determine if there was some suitable location (more work
>> but better abstraction).
>> This would mean that an improvement/addition to location would  
>> automatically
>> gain the improvement in masked warnings.
>> This is not an objection (the patch is OK for ObjC as is) .. just a  
>> question,
>
> I'm not sure I understand correctly.
>
> Let me try to clarify: The calls to the {get,set}_no_warning() with
> no option introduced by the patch are of two kinds: one where
> the intent is to query or suppress all warnings for an expression
> (or a DECL, like a synthesized artificial temporary), and another
> where it's not apparent from the code which warning is meant to
> be queried or suppressed.  I think all the ones in the ObjC front
> end are of the latter sort.  (None of these calls are due to
> the location being unknown.)

OK, thanks - that clarifies (and is not particularly surprising, there is
plenty to do there).

> With that, if you are suggesting to try to find the suitable option
> to pass to the latter kind of calls above, I agree.

Something for me to look at when there’s time, then…

>  If you have
> ideas for what those might be I can give them a try.  Looking at
> the ObjC suppression code again, all the set_no_warning() calls
> with no option are for what looks like synthesized types, so
> maybe that's a clue: could -Wunused be the warning we want to
> suppress there?

… I’d not hazard a guess right now,

thanks for the clarification
Iain


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/11] warning control by group and location (PR 74765)
  2021-05-25  9:04     ` Richard Biener
@ 2021-05-25 20:50       ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-25 20:50 UTC (permalink / raw)
  To: Richard Biener; +Cc: David Malcolm, gcc-patches

On 5/25/21 3:04 AM, Richard Biener wrote:
> On Tue, May 25, 2021 at 2:53 AM Martin Sebor via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
>>
>> On 5/24/21 5:08 PM, David Malcolm wrote:
>>> On Mon, 2021-05-24 at 16:02 -0600, Martin Sebor wrote:
>>>>     The rare expressions that have no location
>>>> continue to have just one bit[1].
>>>
>>> Where does this get stored?  I see the final patch in the kit removes
>>> TREE_NO_WARNING, but I don't quite follow the logic for where the bit
>>> would then be stored for an expr with UNKNOWN_LOCATION.
>>
>> The patch just removes the TREE_NO_WARNING macro (along with
>> the gimple_no_warning_p/gimple_set_no_warning) functions but not
>> the no-warning bit itself.  It removes them to avoid accidentally
>> modifying the bit alone without going through the new API and
>> updating the location -> warning group mapping.  The bit is still
>> needed for expression/statements with no location.
> 
> I wonder if we could clone UNKNOWN_LOCATION, thus when
> we set_no_warning on UNKNOWN_LOCATION create a new location
> with the source location being still UNKNOWN but with the appropriate
> ad-hoc data to disable the warning?  That of course requires the
> API to be
> 
> location_t set_no_warning (...)
> 
> and users would need to update the container with the new location
> (or we'd need to use a reference we can update in set_no_warning).

This could be done even in the new set_no_warning(tree, ...), without
changing the callers.  But I think the right place and time to set
the location is in the code that creates the expression.  Doing it
at the time the no-warning bit is being set, either in the new API
or in the caller, seems like papering over the underlying problem.

> 
> That said - do you have any stats on how many UNKNOWN_LOCATION
> locations we run into with boostrap / the testsuite?

During stage1, roughly 2.7% of all calls to set_no_warning() are
with arguments with no location.  Based on the code I've seen
some are to be expected (e.g. eh_filter_expr, try_catch_expr,
and var_decl for artificial temporaries).  The rest are:
compound_expr, cond_expr, eh_filter_expr, imagpart_expr,
indirect_ref, mem_ref, minus_expr, modify_expr, mult_expr,
ne_expr, plus_expr, realpart_expr, try_catch_expr, and var_decl.

The vast majority (90%) are plus_expr.  At least some of them come
from ASSERT_EXPRs.  The location isn't available at the point VRP
calls set_no_warning() but it is available earlier when the ASSERTs
are being created from the COND_EXPR statements.  I can look into
this when I'm done with this.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/11] warning control by group and location (PR 74765)
  2021-05-25  0:42   ` Martin Sebor
  2021-05-25  9:04     ` Richard Biener
@ 2021-05-27 11:19     ` Richard Sandiford
  2021-05-27 16:41       ` Martin Sebor
  1 sibling, 1 reply; 98+ messages in thread
From: Richard Sandiford @ 2021-05-27 11:19 UTC (permalink / raw)
  To: Martin Sebor via Gcc-patches

Thanks for doing this.

Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> […]
> On 5/24/21 5:08 PM, David Malcolm wrote:
>> On Mon, 2021-05-24 at 16:02 -0600, Martin Sebor wrote:
>>> Subsequent patches then replace invocations of the TREE_NO_WARNING()
>>> macro and the gimple_no_warning_p() and gimple_set_no_warning()
>>> functions throughout GCC with those and remove the legacy APIs to
>>> keep them from being accidentally reintroduced along with the
>>> problem.
>>> These are mostly mechanical changes, except that most of the new
>>> invocations also specify the option whose disposition to query for
>>> the expression or location, or which to enable or disable[2].
>>> The last function, copy_no_warning(), copies the disposition from
>>> one expression or location to another.
>>>
>>> A couple of design choices might be helpful to explain:
>>>
>>> First, introducing "warning groups" rather than controlling each
>>> individual warning is motivated by a) the fact that the latter
>>> would make avoiding redundant warnings for related problems
>>> cumbersome (e.g., after issuing a -Warray-bounds we want to
>>> suppress -Wstringop-overflow as well -Wstringop-overread for
>>> the same access and vice versa), and b) simplicity and efficiency
>>> of the implementation (mapping each option would require a more
>>> complex data structure like a bitmap).
>>>
>>> Second, using location_t to associate expressions/statements with
>>> the warning groups also turns out to be more useful in practice
>>> than a direct association between a tree or gimple*, and also
>>> simplifies managing the data structure.  Trees and gimple* come
>>> and go across passes, and maintaining a mapping for them that
>>> accounts for the possibility of them being garbage-collected
>>> and the same addresses reused is less than straightforward.
>> 
>> I find some of the terminology rather awkard due to it the negation
>> we're already using with TREE_NO_WARNING, in that we're turning on a
>> no_warning flag, and that this is a per-location/expr/stmt thing that's
>> different from the idea of enabling/disabling a specific warning
>> altogether (and the pragmas that control that).   Sometimes the patches
>> refer to enabling/disabling warnings and I think I want "enabling" and
>> "disabling" to mean the thing the user does with -Wfoo and -Wno-foo.
>> 
>> Would calling it a "warning suppression" or somesuch be more or less
>> klunky?
>
> I like warning suppression :)  But I'm not sure where you suggest
> I use the phrase.
>
> I don't particularly care for the "no" in the API names either
> (existing or new) and would prefer a positive form.  I considered
> enable_warning() and warning_enabled() but I chose the names I did
> because they're close to their established gimple namesakes.  I'm
> fine changing them to the alternatives, or if you or someone else
> has a preference for different names I'm open to suggestions.  Let
> me know.

Not my area, but FWIW, +1 for David's suggestion of
s/set_no_warning/suppress_warning/ or similar.  As well as the
problem with the double negative in negated conditions, I always have to
remember whether TREE_NO_WARNING means that hasn't been anything to warn
about yet or whether we shouldn't warn in future.

Richard

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/11] warning control by group and location (PR 74765)
  2021-05-27 11:19     ` Richard Sandiford
@ 2021-05-27 16:41       ` Martin Sebor
  2021-05-27 21:55         ` David Malcolm
  0 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-05-27 16:41 UTC (permalink / raw)
  To: Martin Sebor via Gcc-patches, David Malcolm, richard.sandiford

On 5/27/21 5:19 AM, Richard Sandiford wrote:
> Thanks for doing this.
> 
> Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>> […]
>> On 5/24/21 5:08 PM, David Malcolm wrote:
>>> On Mon, 2021-05-24 at 16:02 -0600, Martin Sebor wrote:
>>>> Subsequent patches then replace invocations of the TREE_NO_WARNING()
>>>> macro and the gimple_no_warning_p() and gimple_set_no_warning()
>>>> functions throughout GCC with those and remove the legacy APIs to
>>>> keep them from being accidentally reintroduced along with the
>>>> problem.
>>>> These are mostly mechanical changes, except that most of the new
>>>> invocations also specify the option whose disposition to query for
>>>> the expression or location, or which to enable or disable[2].
>>>> The last function, copy_no_warning(), copies the disposition from
>>>> one expression or location to another.
>>>>
>>>> A couple of design choices might be helpful to explain:
>>>>
>>>> First, introducing "warning groups" rather than controlling each
>>>> individual warning is motivated by a) the fact that the latter
>>>> would make avoiding redundant warnings for related problems
>>>> cumbersome (e.g., after issuing a -Warray-bounds we want to
>>>> suppress -Wstringop-overflow as well -Wstringop-overread for
>>>> the same access and vice versa), and b) simplicity and efficiency
>>>> of the implementation (mapping each option would require a more
>>>> complex data structure like a bitmap).
>>>>
>>>> Second, using location_t to associate expressions/statements with
>>>> the warning groups also turns out to be more useful in practice
>>>> than a direct association between a tree or gimple*, and also
>>>> simplifies managing the data structure.  Trees and gimple* come
>>>> and go across passes, and maintaining a mapping for them that
>>>> accounts for the possibility of them being garbage-collected
>>>> and the same addresses reused is less than straightforward.
>>>
>>> I find some of the terminology rather awkard due to it the negation
>>> we're already using with TREE_NO_WARNING, in that we're turning on a
>>> no_warning flag, and that this is a per-location/expr/stmt thing that's
>>> different from the idea of enabling/disabling a specific warning
>>> altogether (and the pragmas that control that).   Sometimes the patches
>>> refer to enabling/disabling warnings and I think I want "enabling" and
>>> "disabling" to mean the thing the user does with -Wfoo and -Wno-foo.
>>>
>>> Would calling it a "warning suppression" or somesuch be more or less
>>> klunky?
>>
>> I like warning suppression :)  But I'm not sure where you suggest
>> I use the phrase.
>>
>> I don't particularly care for the "no" in the API names either
>> (existing or new) and would prefer a positive form.  I considered
>> enable_warning() and warning_enabled() but I chose the names I did
>> because they're close to their established gimple namesakes.  I'm
>> fine changing them to the alternatives, or if you or someone else
>> has a preference for different names I'm open to suggestions.  Let
>> me know.
> 
> Not my area, but FWIW, +1 for David's suggestion of
> s/set_no_warning/suppress_warning/ or similar.  As well as the
> problem with the double negative in negated conditions, I always have to
> remember whether TREE_NO_WARNING means that hasn't been anything to warn
> about yet or whether we shouldn't warn in future.

Sure.  Jason has a patch out for review to introduce

   warning_enabled_at (location, int option).

With that, how does the following API look? (I'd replace the int
argument above with opt_code myself):

   void enable_warning (location_t, enum opt_code = N_OPTS);
   void disable_warning (location_t, enum opt_code = N_OPTS);
   void copy_warning (location_t, location_t);
   bool warning_enabled_at (location_t, enum opt_code = N_OPTS).

   void enable_warning (tree, enum opt_code = N_OPTS);
   void disable_warning (tree, enum opt_code = N_OPTS);
   void copy_warning (tree, const_tree);
   bool warning_enabled_at (const_tree, enum opt_code = N_OPTS).

   void enable_warning (gimple *, enum opt_code = N_OPTS);
   void disable_warning (gimple *, enum opt_code = N_OPTS);
   void copy_warning (gimple *, const gimple *);
   bool warning_enabled_at (gimple *, enum opt_code = N_OPTS).

Martin

> 
> Richard
> 


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 2/11] use xxx_no_warning APIs in Ada
  2021-05-25  8:59     ` Eric Botcazou
@ 2021-05-27 20:29       ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-05-27 20:29 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

On 5/25/21 2:59 AM, Eric Botcazou wrote:
>> [PATCH 2/11] use xxx_no_warning APIs in Ada.
> 
> Looks good to me, but remove the useless pair of parentheses in the 3rd hunk.
> 

The hunk was actually incorrect, thanks for drawing my attention
to it!  The second argument to the function is the option.  To
suppress all warnings it should have been:

diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 1786fbf8186..f2a6f44da76 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -836,7 +836,7 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
    if (!deferred_decl_context)
      DECL_CONTEXT (decl) = context;

-  TREE_NO_WARNING (decl) = (No (gnat_node) || Warnings_Off (gnat_node));
+  set_no_warning (decl, -1, No (gnat_node) || Warnings_Off (gnat_node));

    /* Set the location of DECL and emit a declaration for it.  */
    if (Present (gnat_node) && !renaming_from_instantiation_p (gnat_node))

This mistake will be caught when I change the functions to take
enum opt_code instead of int as David suggested.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/11] warning control by group and location (PR 74765)
  2021-05-27 16:41       ` Martin Sebor
@ 2021-05-27 21:55         ` David Malcolm
  2021-05-28  4:40           ` Jason Merrill
  0 siblings, 1 reply; 98+ messages in thread
From: David Malcolm @ 2021-05-27 21:55 UTC (permalink / raw)
  To: Martin Sebor, Martin Sebor via Gcc-patches, richard.sandiford

On Thu, 2021-05-27 at 10:41 -0600, Martin Sebor wrote:
> On 5/27/21 5:19 AM, Richard Sandiford wrote:
> > Thanks for doing this.
> > 
> > Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> > > […]
> > > On 5/24/21 5:08 PM, David Malcolm wrote:
> > > > On Mon, 2021-05-24 at 16:02 -0600, Martin Sebor wrote:
> > > > > Subsequent patches then replace invocations of the
> > > > > TREE_NO_WARNING()
> > > > > macro and the gimple_no_warning_p() and
> > > > > gimple_set_no_warning()
> > > > > functions throughout GCC with those and remove the legacy
> > > > > APIs to
> > > > > keep them from being accidentally reintroduced along with the
> > > > > problem.
> > > > > These are mostly mechanical changes, except that most of the
> > > > > new
> > > > > invocations also specify the option whose disposition to
> > > > > query for
> > > > > the expression or location, or which to enable or disable[2].
> > > > > The last function, copy_no_warning(), copies the disposition
> > > > > from
> > > > > one expression or location to another.
> > > > > 
> > > > > A couple of design choices might be helpful to explain:
> > > > > 
> > > > > First, introducing "warning groups" rather than controlling
> > > > > each
> > > > > individual warning is motivated by a) the fact that the
> > > > > latter
> > > > > would make avoiding redundant warnings for related problems
> > > > > cumbersome (e.g., after issuing a -Warray-bounds we want to
> > > > > suppress -Wstringop-overflow as well -Wstringop-overread for
> > > > > the same access and vice versa), and b) simplicity and
> > > > > efficiency
> > > > > of the implementation (mapping each option would require a
> > > > > more
> > > > > complex data structure like a bitmap).
> > > > > 
> > > > > Second, using location_t to associate expressions/statements
> > > > > with
> > > > > the warning groups also turns out to be more useful in
> > > > > practice
> > > > > than a direct association between a tree or gimple*, and also
> > > > > simplifies managing the data structure.  Trees and gimple*
> > > > > come
> > > > > and go across passes, and maintaining a mapping for them that
> > > > > accounts for the possibility of them being garbage-collected
> > > > > and the same addresses reused is less than straightforward.
> > > > 
> > > > I find some of the terminology rather awkard due to it the
> > > > negation
> > > > we're already using with TREE_NO_WARNING, in that we're turning
> > > > on a
> > > > no_warning flag, and that this is a per-location/expr/stmt
> > > > thing that's
> > > > different from the idea of enabling/disabling a specific
> > > > warning
> > > > altogether (and the pragmas that control that).   Sometimes the
> > > > patches
> > > > refer to enabling/disabling warnings and I think I want
> > > > "enabling" and
> > > > "disabling" to mean the thing the user does with -Wfoo and -
> > > > Wno-foo.
> > > > 
> > > > Would calling it a "warning suppression" or somesuch be more or
> > > > less
> > > > klunky?
> > > 
> > > I like warning suppression :)  But I'm not sure where you suggest
> > > I use the phrase.
> > > 
> > > I don't particularly care for the "no" in the API names either
> > > (existing or new) and would prefer a positive form.  I considered
> > > enable_warning() and warning_enabled() but I chose the names I
> > > did
> > > because they're close to their established gimple namesakes.  I'm
> > > fine changing them to the alternatives, or if you or someone else
> > > has a preference for different names I'm open to suggestions. 
> > > Let
> > > me know.
> > 
> > Not my area, but FWIW, +1 for David's suggestion of
> > s/set_no_warning/suppress_warning/ or similar.  As well as the
> > problem with the double negative in negated conditions, I always
> > have to
> > remember whether TREE_NO_WARNING means that hasn't been anything to
> > warn
> > about yet or whether we shouldn't warn in future.
> 
> Sure.  Jason has a patch out for review to introduce
> 
>    warning_enabled_at (location, int option).

CCing Jason.

BTW, do you have a URL for that patch?

> 
> With that, how does the following API look? (I'd replace the int
> argument above with opt_code myself):
> 
>    void enable_warning (location_t, enum opt_code = N_OPTS);
>    void disable_warning (location_t, enum opt_code = N_OPTS);
>    void copy_warning (location_t, location_t);
>    bool warning_enabled_at (location_t, enum opt_code = N_OPTS).
> 
>    void enable_warning (tree, enum opt_code = N_OPTS);
>    void disable_warning (tree, enum opt_code = N_OPTS);
>    void copy_warning (tree, const_tree);
>    bool warning_enabled_at (const_tree, enum opt_code = N_OPTS).
> 
>    void enable_warning (gimple *, enum opt_code = N_OPTS);
>    void disable_warning (gimple *, enum opt_code = N_OPTS);
>    void copy_warning (gimple *, const gimple *);
>    bool warning_enabled_at (gimple *, enum opt_code = N_OPTS).

I'm not so happy with "enable_warning" and "disable_warning" in the
above proposal; it seems to me that three things are being conflated:

(a) whether the user enabled the warning with -Wfoo, whether at the
command line, or by #pragma (and using the location_t to query the
pragma information)

versus

(b) whether we're suppressing a category of warnings for this construct
(and using the location_t to stash the flags)

versus

(c) should the warning actually be emitted at the location

Presumably Jason's patch is a way for our warning code (in the FE and
middle end) to avoid doing expensive things by querying whether the
warning would actually get emitted i.e. it's a way to query (c), so we
can have an early-reject if it returns false, where presumably the
query is cheap relative to the testing that would otherwise occur.  Is
that right?

Perhaps the terminology should be that:
- the user *requests* a warning, (a) above
- our code can *suppress* a warning, for (b) above
- the combination of the two give (c): whether the warning is *enabled*

Or maybe
(a) the user *enables* a warning 
(b) our code can *suppress* a warning (or warning category)
(c) the combination gives whether the warning is *active*.

or somesuch.

Thoughts?
Dave


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/11] warning control by group and location (PR 74765)
  2021-05-27 21:55         ` David Malcolm
@ 2021-05-28  4:40           ` Jason Merrill
  0 siblings, 0 replies; 98+ messages in thread
From: Jason Merrill @ 2021-05-28  4:40 UTC (permalink / raw)
  To: David Malcolm, Martin Sebor, Martin Sebor via Gcc-patches,
	richard.sandiford

On 5/27/21 5:55 PM, David Malcolm wrote:
> On Thu, 2021-05-27 at 10:41 -0600, Martin Sebor wrote:
>> On 5/27/21 5:19 AM, Richard Sandiford wrote:
>>> Thanks for doing this.
>>>
>>> Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>>>> […]
>>>> On 5/24/21 5:08 PM, David Malcolm wrote:
>>>>> On Mon, 2021-05-24 at 16:02 -0600, Martin Sebor wrote:
>>>>>> Subsequent patches then replace invocations of the
>>>>>> TREE_NO_WARNING()
>>>>>> macro and the gimple_no_warning_p() and
>>>>>> gimple_set_no_warning()
>>>>>> functions throughout GCC with those and remove the legacy
>>>>>> APIs to
>>>>>> keep them from being accidentally reintroduced along with the
>>>>>> problem.
>>>>>> These are mostly mechanical changes, except that most of the
>>>>>> new
>>>>>> invocations also specify the option whose disposition to
>>>>>> query for
>>>>>> the expression or location, or which to enable or disable[2].
>>>>>> The last function, copy_no_warning(), copies the disposition
>>>>>> from
>>>>>> one expression or location to another.
>>>>>>
>>>>>> A couple of design choices might be helpful to explain:
>>>>>>
>>>>>> First, introducing "warning groups" rather than controlling
>>>>>> each
>>>>>> individual warning is motivated by a) the fact that the
>>>>>> latter
>>>>>> would make avoiding redundant warnings for related problems
>>>>>> cumbersome (e.g., after issuing a -Warray-bounds we want to
>>>>>> suppress -Wstringop-overflow as well -Wstringop-overread for
>>>>>> the same access and vice versa), and b) simplicity and
>>>>>> efficiency
>>>>>> of the implementation (mapping each option would require a
>>>>>> more
>>>>>> complex data structure like a bitmap).
>>>>>>
>>>>>> Second, using location_t to associate expressions/statements
>>>>>> with
>>>>>> the warning groups also turns out to be more useful in
>>>>>> practice
>>>>>> than a direct association between a tree or gimple*, and also
>>>>>> simplifies managing the data structure.  Trees and gimple*
>>>>>> come
>>>>>> and go across passes, and maintaining a mapping for them that
>>>>>> accounts for the possibility of them being garbage-collected
>>>>>> and the same addresses reused is less than straightforward.
>>>>>
>>>>> I find some of the terminology rather awkard due to it the
>>>>> negation
>>>>> we're already using with TREE_NO_WARNING, in that we're turning
>>>>> on a
>>>>> no_warning flag, and that this is a per-location/expr/stmt
>>>>> thing that's
>>>>> different from the idea of enabling/disabling a specific
>>>>> warning
>>>>> altogether (and the pragmas that control that).   Sometimes the
>>>>> patches
>>>>> refer to enabling/disabling warnings and I think I want
>>>>> "enabling" and
>>>>> "disabling" to mean the thing the user does with -Wfoo and -
>>>>> Wno-foo.
>>>>>
>>>>> Would calling it a "warning suppression" or somesuch be more or
>>>>> less
>>>>> klunky?
>>>>
>>>> I like warning suppression :)  But I'm not sure where you suggest
>>>> I use the phrase.
>>>>
>>>> I don't particularly care for the "no" in the API names either
>>>> (existing or new) and would prefer a positive form.  I considered
>>>> enable_warning() and warning_enabled() but I chose the names I
>>>> did
>>>> because they're close to their established gimple namesakes.  I'm
>>>> fine changing them to the alternatives, or if you or someone else
>>>> has a preference for different names I'm open to suggestions.
>>>> Let
>>>> me know.
>>>
>>> Not my area, but FWIW, +1 for David's suggestion of
>>> s/set_no_warning/suppress_warning/ or similar.  As well as the
>>> problem with the double negative in negated conditions, I always
>>> have to
>>> remember whether TREE_NO_WARNING means that hasn't been anything to
>>> warn
>>> about yet or whether we shouldn't warn in future.
>>
>> Sure.  Jason has a patch out for review to introduce
>>
>>     warning_enabled_at (location, int option).
> 
> CCing Jason.
> 
> BTW, do you have a URL for that patch?

https://gcc.gnu.org/pipermail/gcc-patches/2021-May/571307.html

is the most recent version.

Jason


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/11] warning control by group and location (PR 74765)
  2021-05-24 22:02 [PATCH 0/11] warning control by group and location (PR 74765) Martin Sebor
  2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
  2021-05-24 23:08 ` [PATCH 0/11] warning control by group and location (PR 74765) David Malcolm
@ 2021-05-30  2:06 ` Jeff Law
  2 siblings, 0 replies; 98+ messages in thread
From: Jeff Law @ 2021-05-30  2:06 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 5/24/2021 4:02 PM, Martin Sebor via Gcc-patches wrote:
> Having just one bit control whether an expression or statement should
> be allowed to trigger warnings has been a source of bug reports about
> false negatives for years.  PR 74765 has a representative test case
> that shows how by setting the bit to avoid -Wparentheses the C++ front
> end also ends up preventing valid -Wuninitialized in the middle end,
> but there are other such reports for C (e.g., PR 74762) as well as
> the middle end.
>
> This patch series solves the problem by associating an expression
> (whether a tree node or a GIMPLE statement) with more than one such
> bit through its location.  Each new bit in the mapping corresponds
> to a group of warnings (e.g., lexical, access, etc.), and each
> location may be associated with a simple bitmap with one bit for
> each group.  The initial groups are mostly ad hoc and should be
> refined over time.  The rare expressions that have no location
> continue to have just one bit[1].
>
> The first patch introduces three new APIs without making use of them
> in existing code:
>
>   bool get_no_warning (..., int option);
>   void set_no_warning (..., int option, ...);
>   void copy_no_warning (...);
>
> Subsequent patches then replace invocations of the TREE_NO_WARNING()
> macro and the gimple_no_warning_p() and gimple_set_no_warning()
> functions throughout GCC with those and remove the legacy APIs to
> keep them from being accidentally reintroduced along with the problem.
> These are mostly mechanical changes, except that most of the new
> invocations also specify the option whose disposition to query for
> the expression or location, or which to enable or disable[2].
> The last function, copy_no_warning(), copies the disposition from
> one expression or location to another.
>
> A couple of design choices might be helpful to explain:
>
> First, introducing "warning groups" rather than controlling each
> individual warning is motivated by a) the fact that the latter
> would make avoiding redundant warnings for related problems
> cumbersome (e.g., after issuing a -Warray-bounds we want to
> suppress -Wstringop-overflow as well -Wstringop-overread for
> the same access and vice versa), and b) simplicity and efficiency
> of the implementation (mapping each option would require a more
> complex data structure like a bitmap).
>
> Second, using location_t to associate expressions/statements with
> the warning groups also turns out to be more useful in practice
> than a direct association between a tree or gimple*, and also
> simplifies managing the data structure.  Trees and gimple* come
> and go across passes, and maintaining a mapping for them that
> accounts for the possibility of them being garbage-collected
> and the same addresses reused is less than straightforward.
>
> Martin
>
> [1] My expectation is to work toward providing locations for all
> expressions/statements, even if it's the opening or closing brace
> of the function they're used in.)
>
> [2] A number of {get,set}_no_warning() calls introduced by the patch
> don't provide an option argument and query or set just the one bit in
> the expression/statement.  Some of these may be correct as they are,
> but others could be refined to also specify an option.  I can do that
> in a follow-up patch if someone helps me find the right option.
So definitely on board with the broad approach here.  I think it's 
largely compatible with what Jakub suggested a year or two ago in this 
space as well.

I think you've got some API/naming suggestions, so let's get that 
settled and the bits reposted.

Thanks,

jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 0/13] v2 warning control by group and location (PR 74765)
  2021-05-24 23:08 ` [PATCH 0/11] warning control by group and location (PR 74765) David Malcolm
  2021-05-25  0:42   ` Martin Sebor
@ 2021-06-04 21:27   ` Martin Sebor
  2021-06-04 21:41     ` [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups " Martin Sebor
                       ` (14 more replies)
  1 sibling, 15 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:27 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm, Martin Sebor

This is a revised patch series to add warning control by group and
location, updated based on feedback on the initial series.

v2 changes include:

1) Use opt_code rather than int for the option argument to the new
    APIs.  This let me find and fix a bug in the original Ada change.
2) Use suppress_warning() and warning_suppressed_p() instead of
    get/set_no_warning, and also instead of warning_enabled/disabled
    for the names of the new functions (as requested/clarified offline
    by David).
3) Make the removal of the TREE_NO_WARNING macro and
    the gimple_get_no_warning_p() and gimple_set_no_warning()
    functions a standalone patch.
4) Include tests for PR 74765 and 74762 fixed by these changes.

I have retested the whole patch series on x86_64-linux.

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
@ 2021-06-04 21:41     ` Martin Sebor
  2021-06-21 21:34       ` [PING][PATCH " Martin Sebor
  2021-06-22 23:18       ` [PATCH " David Malcolm
  2021-06-04 21:41     ` [PATCH 2/13] v2 Use new per-location warning APIs in Ada Martin Sebor
                       ` (13 subsequent siblings)
  14 siblings, 2 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:41 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 436 bytes --]

The attached patch introduces the suppress_warning(),
warning_suppressed(), and copy_no_warning() APIs without making
use of them in the rest of GCC.  They are in three files:

   diagnostic-spec.{h,c}: Location-centric overloads.
   warning-control.cc: Tree- and gimple*-centric overloads.

The location-centric overloads are suitable to use from the diagnostic
subsystem.  The rest can be used from the front ends and the middle end.

[-- Attachment #2: gcc-no-warning-1.diff --]
[-- Type: text/x-patch, Size: 16748 bytes --]

Add support for per-location warning groups.

gcc/ChangeLog:

	* Makefile.in (OBJS-libcommon): Add diagnostic-spec.o.
	* gengtype.c (open_base_files): Add diagnostic-spec.h.
	* diagnostic-spec.c: New file.
	* diagnostic-spec.h: New file.
	* warning-control.cc: New file.

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 4cb2966157e..35eef812ac8 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1696,6 +1696,7 @@ OBJS = \
 	vmsdbgout.o \
 	vr-values.o \
 	vtable-verify.o \
+	warning-control.o \
 	web.o \
 	wide-int.o \
 	wide-int-print.o \
@@ -1707,8 +1708,8 @@ OBJS = \
 
 # Objects in libcommon.a, potentially used by all host binaries and with
 # no target dependencies.
-OBJS-libcommon = diagnostic.o diagnostic-color.o diagnostic-show-locus.o \
-	diagnostic-format-json.o json.o \
+OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
+	diagnostic-show-locus.o diagnostic-format-json.o json.o \
 	edit-context.o \
 	pretty-print.o intl.o \
 	sbitmap.o \
@@ -2648,6 +2649,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/ipa-modref.h $(srcdir)/ipa-modref.c \
   $(srcdir)/ipa-modref-tree.h \
   $(srcdir)/signop.h \
+  $(srcdir)/diagnostic-spec.h $(srcdir)/diagnostic-spec.c \
   $(srcdir)/dwarf2out.h \
   $(srcdir)/dwarf2asm.c \
   $(srcdir)/dwarf2cfi.c \
diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
new file mode 100644
index 00000000000..c5668831a9b
--- /dev/null
+++ b/gcc/diagnostic-spec.c
@@ -0,0 +1,177 @@
+/* Functions to enable and disable individual warnings on an expression
+   and statement basis.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   Contributed by Martin Sebor <msebor@redhat.com>
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "bitmap.h"
+#include "tree.h"
+#include "cgraph.h"
+#include "hash-map.h"
+#include "diagnostic-spec.h"
+#include "pretty-print.h"
+#include "options.h"
+
+/* Initialize *THIS from warning option OPT.  */
+
+nowarn_spec_t::nowarn_spec_t (opt_code opt)
+{
+  /* Create a very simple mapping based on testing and experience.
+     It should become more refined with time. */
+  switch (opt)
+    {
+    case no_warning:
+      bits = 0;
+      break;
+
+    case all_warnings:
+      bits = -1;
+      break;
+
+      /* Flow-sensitive warnings about pointer problems issued by both
+	 front ends and the middle end.  */
+    case OPT_Waddress:
+    case OPT_Wnonnull:
+      bits = NW_NONNULL;
+      break;
+
+      /* Flow-sensitive warnings about arithmetic overflow issued by both
+	 front ends and the middle end.  */
+    case OPT_Woverflow:
+    case OPT_Wshift_count_negative:
+    case OPT_Wshift_count_overflow:
+    case OPT_Wstrict_overflow:
+      bits = NW_VFLOW;
+      break;
+
+      /* Lexical warnings issued by front ends.  */
+    case OPT_Wabi:
+    case OPT_Wlogical_op:
+    case OPT_Wparentheses:
+    case OPT_Wreturn_type:
+    case OPT_Wsizeof_array_div:
+    case OPT_Wstrict_aliasing:
+    case OPT_Wunused:
+    case OPT_Wunused_function:
+    case OPT_Wunused_but_set_variable:
+    case OPT_Wunused_variable:
+    case OPT_Wunused_but_set_parameter:
+      bits = NW_LEXICAL;
+      break;
+
+      /* Access warning group.  */
+    case OPT_Warray_bounds:
+    case OPT_Warray_bounds_:
+    case OPT_Wformat_overflow_:
+    case OPT_Wformat_truncation_:
+    case OPT_Wrestrict:
+    case OPT_Wstrict_aliasing_:
+    case OPT_Wstringop_overflow_:
+    case OPT_Wstringop_overread:
+    case OPT_Wstringop_truncation:
+      bits = NW_ACCESS;
+      break;
+
+      /* Initialization warning group.  */
+    case OPT_Winit_self:
+    case OPT_Wuninitialized:
+    case OPT_Wmaybe_uninitialized:
+	bits = NW_UNINIT;
+      break;
+
+    default:
+      /* A catchall group for everything else.  */
+      bits = NW_OTHER;
+    }
+}
+
+/* Map from location to its no-warning disposition.  */
+
+GTY(()) xint_hash_map_t *nowarn_map;
+
+/* Return the no-warning disposition for location LOC and option OPT
+   or for all/any otions by default.  */
+
+bool
+warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
+{
+  if (!nowarn_map)
+    return false;
+
+  if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
+    {
+      const nowarn_spec_t optspec (opt);
+      return *pspec & optspec;
+    }
+
+  return false;
+}
+
+/* Set the warning disposition for location LOC and option OPT when to
+   disabled if DIS is true and to enabled otherwise.  Return true if
+   LOC has any warnings disabled at the end of processing.  */
+
+bool
+suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
+		     bool dis /* = true */)
+{
+  const nowarn_spec_t optspec (dis ? opt : opt_code ());
+
+  if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
+    {
+      if (dis)
+	{
+	  *pspec |= optspec;
+	  return true;
+	}
+
+      *pspec &= optspec;
+      if (*pspec)
+	return true;
+
+      nowarn_map->remove (loc);
+      return false;
+    }
+
+  if (!dis || opt == no_warning)
+    return false;
+
+  if (!nowarn_map)
+    nowarn_map = xint_hash_map_t::create_ggc (32);
+
+  nowarn_map->put (loc, optspec);
+  return true;
+}
+
+/* Copy the no-warning disposition from one location to another.  */
+
+void
+copy_warning (location_t to, location_t from)
+{
+  if (!nowarn_map)
+    return;
+
+  if (nowarn_spec_t *pspec = nowarn_map->get (from))
+    nowarn_map->put (to, *pspec);
+  else
+    nowarn_map->remove (to);
+}
diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
new file mode 100644
index 00000000000..62d9270ca6d
--- /dev/null
+++ b/gcc/diagnostic-spec.h
@@ -0,0 +1,140 @@
+/* Language-independent APIs to enable/disable per-location warnings.
+
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   Contributed by Martin Sebor <msebor@redhat.com>
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef DIAGNOSTIC_SPEC_H_INCLUDED
+#define DIAGNOSTIC_SPEC_H_INCLUDED
+
+#include "hash-map.h"
+
+/* A "bitset" of warning groups.  */
+
+struct nowarn_spec_t
+{
+  enum
+    {
+     /* Middle end warnings about invalid accesses.  */
+     NW_ACCESS = 1 << 0,
+     /* Front end/lexical warnings.  */
+     NW_LEXICAL = 1 << 1,
+     /* Warnings about null pointers.  */
+     NW_NONNULL = 1 << 2,
+     /* Warnings about uninitialized reads.  */
+     NW_UNINIT = 1 << 3,
+     /* Warnings about arithmetic overflow.  */
+     NW_VFLOW = 1 << 4,
+     /* All other unclassified warnings.  */
+     NW_OTHER = 1 << 5,
+     /* All groups of warnings.  */
+     NW_ALL = (NW_ACCESS | NW_LEXICAL | NW_NONNULL
+	       | NW_UNINIT | NW_VFLOW | NW_OTHER)
+   };
+
+  nowarn_spec_t (): bits () { }
+
+  nowarn_spec_t (opt_code);
+
+  /* Return the raw bitset.  */
+  operator unsigned() const
+  {
+    return bits;
+  }
+
+  /* Return true if the bitset is clear.  */
+  bool operator!() const
+  {
+    return !bits;
+  }
+
+  /* Return the inverse of the bitset.  */
+  nowarn_spec_t operator~() const
+  {
+    nowarn_spec_t res (*this);
+    res.bits &= ~NW_ALL;
+    return res;
+  }
+
+  /* Set *THIS to the bitwise OR of *THIS and RHS.  */
+  nowarn_spec_t& operator|= (const nowarn_spec_t &rhs)
+  {
+    bits |= rhs.bits;
+    return *this;
+  }
+
+  /* Set *THIS to the bitwise AND of *THIS and RHS.  */
+  nowarn_spec_t& operator&= (const nowarn_spec_t &rhs)
+  {
+    bits &= rhs.bits;
+    return *this;
+  }
+
+  /* Set *THIS to the bitwise exclusive OR of *THIS and RHS.  */
+  nowarn_spec_t& operator^= (const nowarn_spec_t &rhs)
+  {
+    bits ^= rhs.bits;
+    return *this;
+  }
+
+private:
+  /* Bitset of warning groups.  */
+  unsigned bits;
+};
+
+/* Return the bitwise OR of LHS and RHS.  */
+
+inline nowarn_spec_t
+operator| (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return nowarn_spec_t (lhs) |= rhs;
+}
+
+/* Return the bitwise AND of LHS and RHS.  */
+
+inline nowarn_spec_t
+operator& (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return nowarn_spec_t (lhs) &= rhs;
+}
+
+/* Return true if LHS is equal RHS.  */
+
+inline bool
+operator== (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return static_cast<unsigned>(lhs) == static_cast<unsigned>(rhs);
+}
+
+/* Return true if LHS is not equal RHS.  */
+
+inline bool
+operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return !(lhs == rhs);
+}
+
+typedef location_t key_type_t;
+typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
+typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
+
+/* A mapping from the location of an expression to the warning spec
+   set for it.  */
+extern GTY(()) xint_hash_map_t *nowarn_map;
+
+#endif // DIAGNOSTIC_SPEC_H_INCLUDED
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index b94e2f126ec..c1fa6d35c87 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1727,7 +1727,7 @@ open_base_files (void)
       "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
       "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h",
       "omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h", "symtab-thunks.h",
-      "symtab-clones.h",
+      "symtab-clones.h", "diagnostic-spec.h",
       NULL
     };
     const char *const *ifp;
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
new file mode 100644
index 00000000000..21161caae3a
--- /dev/null
+++ b/gcc/warning-control.cc
@@ -0,0 +1,238 @@
+/* Functions to enable and disable individual warnings on an expression
+   and statement basis.
+
+   Copyright (C) 2021 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "bitmap.h"
+#include "tree.h"
+#include "gimple.h"
+#include "cgraph.h"
+#include "hash-map.h"
+#include "diagnostic-spec.h"
+
+/* Return the no-warning bit for EXPR.  */
+
+static inline bool
+get_no_warning_bit (const_tree expr)
+{
+  return expr->base.nowarning_flag;
+}
+
+/* Return the no-warning bit for statement STMT.  */
+
+static inline bool
+get_no_warning_bit (const gimple *stmt)
+{
+  return stmt->no_warning;
+}
+
+/* Set the no-warning bit for EXPR to VALUE.  */
+
+static inline void
+set_no_warning_bit (tree expr, bool value)
+{
+  expr->base.nowarning_flag = value;
+}
+
+/* Set the no-warning bit for statement STMT to VALUE.  */
+
+static inline void
+set_no_warning_bit (gimple *stmt, bool value)
+{
+  stmt->no_warning = value;
+}
+
+/* Return EXPR location or zero.  */
+
+static inline key_type_t
+convert_to_key (const_tree expr)
+{
+  if (DECL_P (expr))
+    return DECL_SOURCE_LOCATION (expr);
+  if (EXPR_P (expr))
+    return EXPR_LOCATION (expr);
+  return 0;
+}
+
+/* Return STMT location (may be zero).  */
+
+static inline key_type_t
+convert_to_key (const gimple *stmt)
+{
+  return gimple_location (stmt);
+}
+
+/* Return the no-warning bitmap for decl/expression EXPR.  */
+
+static nowarn_spec_t *
+get_nowarn_spec (const_tree expr)
+{
+  const key_type_t key = convert_to_key (expr);
+
+  if (!get_no_warning_bit (expr) || !key)
+    return NULL;
+
+  return nowarn_map ? nowarn_map->get (key) : NULL;
+}
+
+/* Return the no-warning bitmap for stateemt STMT.  */
+
+static nowarn_spec_t *
+get_nowarn_spec (const gimple *stmt)
+{
+  const key_type_t key = convert_to_key (stmt);
+
+  if (!get_no_warning_bit (stmt))
+    return NULL;
+
+  return nowarn_map ? nowarn_map->get (key) : NULL;
+}
+
+/* Return true if warning OPT is suppressed for decl/expression EXPR.
+   By default tests the disposition for any warning.  */
+
+bool
+warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
+{
+  const nowarn_spec_t *spec = get_nowarn_spec (expr);
+
+  if (!spec)
+    return get_no_warning_bit (expr);
+
+  const nowarn_spec_t optspec (opt);
+  bool dis = *spec & optspec;
+  gcc_assert (get_no_warning_bit (expr) || !dis);
+  return dis;
+}
+
+/* Return true if warning OPT is suppressed for statement STMT.
+   By default tests the disposition for any warning.  */
+
+bool
+warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */)
+{
+  const nowarn_spec_t *spec = get_nowarn_spec (stmt);
+
+  if (!spec)
+    /* Fall back on the single no-warning bit.  */
+    return get_no_warning_bit (stmt);
+
+  const nowarn_spec_t optspec (opt);
+  bool dis = *spec & optspec;
+  gcc_assert (get_no_warning_bit (stmt) || !dis);
+  return dis;
+}
+
+/* Enable, or by default disable, a warning for the expression.
+   The wildcard OPT of -1 controls all warnings.  */
+
+void
+suppress_warning (tree expr, opt_code opt /* = all_warnings */,
+		  bool dis /* = true */)
+{
+  if (opt == no_warning)
+    return;
+
+  const key_type_t key = convert_to_key (expr);
+
+  dis = suppress_warning_at (key, opt, dis) || dis;
+  set_no_warning_bit (expr, dis);
+}
+
+/* Enable, or by default disable, a warning for the statement STMT.
+   The wildcard OPT of -1 controls all warnings.  */
+
+void
+suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
+		  bool dis /* = true */)
+{
+  if (opt == no_warning)
+    return;
+
+  const key_type_t key = convert_to_key (stmt);
+
+  dis = suppress_warning_at (key, opt, dis) || dis;
+  set_no_warning_bit (stmt, dis);
+}
+
+/* Copy the warning disposition mapping between an expression and/or
+   a statement.  */
+
+template <class ToType, class FromType>
+void copy_warning (ToType to, FromType from)
+{
+  const key_type_t to_key = convert_to_key (to);
+
+  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
+    {
+      /* If there's an entry in the map the no-warning bit must be set.  */
+      gcc_assert (get_no_warning_bit (from));
+
+      if (!nowarn_map)
+	nowarn_map = xint_hash_map_t::create_ggc (32);
+
+      nowarn_map->put (to_key, *from_map);
+      set_no_warning_bit (to, true);
+    }
+  else
+    {
+      if (nowarn_map)
+	nowarn_map->remove (to_key);
+
+      /* The no-warning bit might be set even if there's no entry
+	 in the map.  */
+      set_no_warning_bit (to, get_no_warning_bit (from));
+    }
+}
+
+/* Copy the warning disposition mapping from one expression to another.  */
+
+void
+copy_warning (tree to, const_tree from)
+{
+  copy_warning<tree, const_tree>(to, from);
+}
+
+/* Copy the warning disposition mapping from a statement to an expression.  */
+
+void
+copy_warning (tree to, const gimple *from)
+{
+  copy_warning<tree, const gimple *>(to, from);
+}
+
+/* Copy the warning disposition mapping from an expression to a statement.  */
+
+void
+copy_warning (gimple *to, const_tree from)
+{
+  copy_warning<gimple *, const_tree>(to, from);
+}
+
+/* Copy the warning disposition mapping from one statement to another.  */
+
+void
+copy_warning (gimple *to, const gimple *from)
+{
+  copy_warning<gimple *, const gimple *>(to, from);
+}

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 2/13] v2 Use new per-location warning APIs in Ada.
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
  2021-06-04 21:41     ` [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups " Martin Sebor
@ 2021-06-04 21:41     ` Martin Sebor
  2021-06-24  5:07       ` Jeff Law
  2021-06-04 21:41     ` [PATCH 3/13] v2 Use new per-location warning APIs in C front end Martin Sebor
                       ` (12 subsequent siblings)
  14 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:41 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 159 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the Ada front
end with the new suppress_warning(), warning_suppressed_p(), and
copy_warning() APIs.

[-- Attachment #2: gcc-no-warning-ada.diff --]
[-- Type: text/x-patch, Size: 1840 bytes --]

Add support for per-location warning groups.

gcc/ada/ChangeLog:

	* gcc-interface/trans.c (Handled_Sequence_Of_Statements_to_gnu):
	Replace TREE_NO_WARNING with suppress_warning.
	(gnat_gimplify_expr): Same.
	* gcc-interface/utils.c (gnat_pushdecl): Same.

diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index ee014a35cc2..949b7733766 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -5363,7 +5363,7 @@ Handled_Sequence_Of_Statements_to_gnu (Node_Id gnat_node)
 	 because of the unstructured form of EH used by fe_sjlj_eh, there
 	 might be forward edges going to __builtin_setjmp receivers on which
 	 it is uninitialized, although they will never be actually taken.  */
-      TREE_NO_WARNING (gnu_jmpsave_decl) = 1;
+      suppress_warning (gnu_jmpsave_decl, OPT_Wuninitialized);
       gnu_jmpbuf_decl
 	= create_var_decl (get_identifier ("JMP_BUF"), NULL_TREE,
 			   jmpbuf_type,
@@ -8805,7 +8805,7 @@ gnat_gimplify_expr (tree *expr_p, gimple_seq *pre_p,
       else
 	{
 	  *expr_p = create_tmp_var (type, NULL);
-	  TREE_NO_WARNING (*expr_p) = 1;
+	  suppress_warning (*expr_p);
 	}
 
       gimplify_and_add (TREE_OPERAND (expr, 0), pre_p);
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 1786fbf8186..982274c6d77 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -836,7 +836,8 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
   if (!deferred_decl_context)
     DECL_CONTEXT (decl) = context;
 
-  TREE_NO_WARNING (decl) = (No (gnat_node) || Warnings_Off (gnat_node));
+  suppress_warning (decl, all_warnings,
+		    No (gnat_node) || Warnings_Off (gnat_node));
 
   /* Set the location of DECL and emit a declaration for it.  */
   if (Present (gnat_node) && !renaming_from_instantiation_p (gnat_node))

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 3/13] v2 Use new per-location warning APIs in C front end
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
  2021-06-04 21:41     ` [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups " Martin Sebor
  2021-06-04 21:41     ` [PATCH 2/13] v2 Use new per-location warning APIs in Ada Martin Sebor
@ 2021-06-04 21:41     ` Martin Sebor
  2021-06-21 21:35       ` [PING][PATCH " Martin Sebor
  2021-06-24  5:09       ` [PATCH " Jeff Law
  2021-06-04 21:42     ` [PATCH 4/13] v2 Use new per-location warning APIs in C family code Martin Sebor
                       ` (11 subsequent siblings)
  14 siblings, 2 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:41 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 157 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the C front
end with the new suppress_warning(), warning_suppressed_p(), and
copy_warning() APIs.

[-- Attachment #2: gcc-no-warning-c.diff --]
[-- Type: text/x-patch, Size: 12379 bytes --]

Add support for per-location warning groups.

gcc/c/ChangeLog:

	* c-decl.c (pop_scope): Replace direct uses of TREE_NO_WARNING with
	warning_suppressed_p, suppress_warning, and copy_no_warning.
	(diagnose_mismatched_decls): Same.
	(duplicate_decls): Same.
	(grokdeclarator): Same.
	(finish_function): Same.
	(c_write_global_declarations_1): Same.
	* c-fold.c (c_fully_fold_internal): Same.
	* c-parser.c (c_parser_expr_no_commas): Same.
	(c_parser_postfix_expression): Same.
	* c-typeck.c (array_to_pointer_conversion): Same.
	(function_to_pointer_conversion): Same.
	(default_function_array_conversion): Same.
	(convert_lvalue_to_rvalue): Same.
	(default_conversion): Same.
	(build_indirect_ref): Same.
	(build_function_call_vec): Same.
	(build_atomic_assign): Same.
	(build_unary_op): Same.
	(c_finish_return): Same.
	(emit_side_effect_warnings): Same.
	(c_finish_stmt_expr): Same.
	(c_omp_clause_copy_ctor): Same.

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 28f851b9d0b..adfdd56d49d 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -1295,7 +1295,7 @@ pop_scope (void)
 	case VAR_DECL:
 	  /* Warnings for unused variables.  */
 	  if ((!TREE_USED (p) || !DECL_READ_P (p))
-	      && !TREE_NO_WARNING (p)
+	      && !warning_suppressed_p (p, OPT_Wunused_but_set_variable)
 	      && !DECL_IN_SYSTEM_HEADER (p)
 	      && DECL_NAME (p)
 	      && !DECL_ARTIFICIAL (p)
@@ -2159,8 +2159,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
       if (DECL_IN_SYSTEM_HEADER (newdecl)
 	  || DECL_IN_SYSTEM_HEADER (olddecl)
-	  || TREE_NO_WARNING (newdecl)
-	  || TREE_NO_WARNING (olddecl))
+	  || warning_suppressed_p (newdecl, OPT_Wpedantic)
+	  || warning_suppressed_p (olddecl, OPT_Wpedantic))
 	return true;  /* Allow OLDDECL to continue in use.  */
 
       if (variably_modified_type_p (newtype, NULL))
@@ -2953,7 +2953,7 @@ duplicate_decls (tree newdecl, tree olddecl)
   if (!diagnose_mismatched_decls (newdecl, olddecl, &newtype, &oldtype))
     {
       /* Avoid `unused variable' and other warnings for OLDDECL.  */
-      TREE_NO_WARNING (olddecl) = 1;
+      suppress_warning (olddecl, OPT_Wunused);
       return false;
     }
 
@@ -7540,10 +7540,7 @@ grokdeclarator (const struct c_declarator *declarator,
 			   FIELD_DECL, declarator->u.id.id, type);
 	DECL_NONADDRESSABLE_P (decl) = bitfield;
 	if (bitfield && !declarator->u.id.id)
-	  {
-	    TREE_NO_WARNING (decl) = 1;
-	    DECL_PADDING_P (decl) = 1;
-	  }
+	  DECL_PADDING_P (decl) = 1;
 
 	if (size_varies)
 	  C_DECL_VARIABLE_SIZE (decl) = 1;
@@ -10232,7 +10229,7 @@ finish_function (location_t end_loc)
       && targetm.warn_func_return (fndecl)
       && warning (OPT_Wreturn_type,
 		  "no return statement in function returning non-void"))
-    TREE_NO_WARNING (fndecl) = 1;
+    suppress_warning (fndecl, OPT_Wreturn_type);
 
   /* Complain about parameters that are only set, but never otherwise used.  */
   if (warn_unused_but_set_parameter)
@@ -10247,7 +10244,7 @@ finish_function (location_t end_loc)
 	    && !DECL_READ_P (decl)
 	    && DECL_NAME (decl)
 	    && !DECL_ARTIFICIAL (decl)
-	    && !TREE_NO_WARNING (decl))
+	    && !warning_suppressed_p (decl, OPT_Wunused_but_set_parameter))
 	  warning_at (DECL_SOURCE_LOCATION (decl),
 		      OPT_Wunused_but_set_parameter,
 		      "parameter %qD set but not used", decl);
@@ -12114,19 +12111,20 @@ c_write_global_declarations_1 (tree globals)
 	{
 	  if (C_DECL_USED (decl))
 	    {
+	      /* TODO: Add OPT_Wundefined-inline.  */
 	      if (pedwarn (input_location, 0, "%q+F used but never defined",
 			   decl))
-		TREE_NO_WARNING (decl) = 1;
+		suppress_warning (decl /* OPT_Wundefined-inline.  */);
 	    }
 	  /* For -Wunused-function warn about unused static prototypes.  */
 	  else if (warn_unused_function
 		   && ! DECL_ARTIFICIAL (decl)
-		   && ! TREE_NO_WARNING (decl))
+		   && ! warning_suppressed_p (decl, OPT_Wunused_function))
 	    {
 	      if (warning (OPT_Wunused_function,
 			   "%q+F declared %<static%> but never defined",
 			   decl))
-		TREE_NO_WARNING (decl) = 1;
+		suppress_warning (decl, OPT_Wunused_function);
 	    }
 	}
 
diff --git a/gcc/c/c-fold.c b/gcc/c/c-fold.c
index 68c74cc1eb2..0ebcb469d28 100644
--- a/gcc/c/c-fold.c
+++ b/gcc/c/c-fold.c
@@ -154,7 +154,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
   tree orig_op0, orig_op1, orig_op2;
   bool op0_const = true, op1_const = true, op2_const = true;
   bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
-  bool nowarning = TREE_NO_WARNING (expr);
+  bool nowarning = warning_suppressed_p (expr, OPT_Woverflow);
   bool unused_p;
   bool op0_lval = false;
   source_range old_range;
@@ -670,13 +670,13 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
  out:
   /* Some folding may introduce NON_LVALUE_EXPRs; all lvalue checks
      have been done by this point, so remove them again.  */
-  nowarning |= TREE_NO_WARNING (ret);
+  nowarning |= warning_suppressed_p (ret, OPT_Woverflow);
   STRIP_TYPE_NOPS (ret);
-  if (nowarning && !TREE_NO_WARNING (ret))
+  if (nowarning && !warning_suppressed_p (ret, OPT_Woverflow))
     {
       if (!CAN_HAVE_LOCATION_P (ret))
 	ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
-      TREE_NO_WARNING (ret) = 1;
+      suppress_warning (ret, OPT_Woverflow);
     }
   if (ret != expr)
     {
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index c491b128da5..a188870bfb8 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -7558,7 +7558,7 @@ c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
     ret.original_code = MODIFY_EXPR;
   else
     {
-      TREE_NO_WARNING (ret.value) = 1;
+      suppress_warning (ret.value, OPT_Wparentheses);
       ret.original_code = ERROR_MARK;
     }
   ret.original_type = NULL;
@@ -9085,7 +9085,7 @@ c_parser_postfix_expression (c_parser *parser)
 	  c_parser_consume_token (parser);
 	  expr = c_parser_expression (parser);
 	  if (TREE_CODE (expr.value) == MODIFY_EXPR)
-	    TREE_NO_WARNING (expr.value) = 1;
+	    suppress_warning (expr.value, OPT_Wparentheses);
 	  if (expr.original_code != C_MAYBE_CONST_EXPR
 	      && expr.original_code != SIZEOF_EXPR)
 	    expr.original_code = ERROR_MARK;
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index be3f4f09f6e..4f4d368dfb3 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -1911,8 +1911,7 @@ array_to_pointer_conversion (location_t loc, tree exp)
 
   STRIP_TYPE_NOPS (exp);
 
-  if (TREE_NO_WARNING (orig_exp))
-    TREE_NO_WARNING (exp) = 1;
+  copy_warning (exp, orig_exp);
 
   ptrtype = build_pointer_type (restype);
 
@@ -1945,8 +1944,7 @@ function_to_pointer_conversion (location_t loc, tree exp)
 
   STRIP_TYPE_NOPS (exp);
 
-  if (TREE_NO_WARNING (orig_exp))
-    TREE_NO_WARNING (exp) = 1;
+  copy_warning (exp, orig_exp);
 
   return build_unary_op (loc, ADDR_EXPR, exp, false);
 }
@@ -2055,8 +2053,7 @@ default_function_array_conversion (location_t loc, struct c_expr exp)
 	    exp.value = TREE_OPERAND (exp.value, 0);
 	  }
 
-	if (TREE_NO_WARNING (orig_exp))
-	  TREE_NO_WARNING (exp.value) = 1;
+	copy_warning (exp.value, orig_exp);
 
 	lvalue_array_p = !not_lvalue && lvalue_p (exp.value);
 	if (!flag_isoc99 && !lvalue_array_p)
@@ -2154,7 +2151,8 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
       tmp = create_tmp_var_raw (nonatomic_type);
       tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, false);
       TREE_ADDRESSABLE (tmp) = 1;
-      TREE_NO_WARNING (tmp) = 1;
+      /* Do not disable warnings for TMP even though it's artificial.
+	 -Winvalid-memory-model depends on it.  */
 
       /* Issue __atomic_load (&expr, &tmp, SEQ_CST);  */
       fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
@@ -2251,8 +2249,7 @@ default_conversion (tree exp)
   orig_exp = exp;
   STRIP_TYPE_NOPS (exp);
 
-  if (TREE_NO_WARNING (orig_exp))
-    TREE_NO_WARNING (exp) = 1;
+  copy_warning (exp, orig_exp);
 
   if (code == VOID_TYPE)
     {
@@ -2616,7 +2613,7 @@ build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
 	  if (warn_strict_aliasing > 2)
 	    if (strict_aliasing_warning (EXPR_LOCATION (pointer),
 					 type, TREE_OPERAND (pointer, 0)))
-	      TREE_NO_WARNING (pointer) = 1;
+	      suppress_warning (pointer, OPT_Wstrict_aliasing_);
 	}
 
       if (TREE_CODE (pointer) == ADDR_EXPR
@@ -3218,7 +3215,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
   /* If -Wnonnull warning has been diagnosed, avoid diagnosing it again
      later.  */
   if (warned_p && TREE_CODE (result) == CALL_EXPR)
-    TREE_NO_WARNING (result) = 1;
+    suppress_warning (result, OPT_Wnonnull);
 
   /* In this improbable scenario, a nested function returns a VM type.
      Create a TARGET_EXPR so that the call always has a LHS, much as
@@ -4167,7 +4164,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
 						      TYPE_UNQUALIFIED);
   val = create_tmp_var_raw (nonatomic_rhs_type);
   TREE_ADDRESSABLE (val) = 1;
-  TREE_NO_WARNING (val) = 1;
+  suppress_warning (val);
   rhs = build4 (TARGET_EXPR, nonatomic_rhs_type, val, rhs, NULL_TREE,
 		NULL_TREE);
   TREE_SIDE_EFFECTS (rhs) = 1;
@@ -4268,7 +4265,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode,
 
       newval = create_tmp_var_raw (nonatomic_lhs_type);
       TREE_ADDRESSABLE (newval) = 1;
-      TREE_NO_WARNING (newval) = 1;
+      suppress_warning (newval);
       rhs = build4 (TARGET_EXPR, nonatomic_lhs_type, newval, func_call,
 		    NULL_TREE, NULL_TREE);
       SET_EXPR_LOCATION (rhs, loc);
@@ -4287,12 +4284,12 @@ cas_loop:
   old = create_tmp_var_raw (nonatomic_lhs_type);
   old_addr = build_unary_op (loc, ADDR_EXPR, old, false);
   TREE_ADDRESSABLE (old) = 1;
-  TREE_NO_WARNING (old) = 1;
+  suppress_warning (old);
 
   newval = create_tmp_var_raw (nonatomic_lhs_type);
   newval_addr = build_unary_op (loc, ADDR_EXPR, newval, false);
   TREE_ADDRESSABLE (newval) = 1;
-  TREE_NO_WARNING (newval) = 1;
+  suppress_warning (newval);
 
   loop_decl = create_artificial_label (loc);
   loop_label = build1 (LABEL_EXPR, void_type_node, loop_decl);
@@ -4781,8 +4778,6 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
 	else
 	  val = build2 (code, TREE_TYPE (arg), arg, inc);
 	TREE_SIDE_EFFECTS (val) = 1;
-	if (TREE_CODE (val) != code)
-	  TREE_NO_WARNING (val) = 1;
 	ret = val;
 	goto return_build_unary_op;
       }
@@ -10941,7 +10936,8 @@ c_finish_return (location_t loc, tree retval, tree origtype)
     }
 
   ret_stmt = build_stmt (loc, RETURN_EXPR, retval);
-  TREE_NO_WARNING (ret_stmt) |= no_warning;
+  if (no_warning)
+    suppress_warning (ret_stmt, OPT_Wreturn_type);
   return add_stmt (ret_stmt);
 }
 \f
@@ -11217,7 +11213,8 @@ emit_side_effect_warnings (location_t loc, tree expr)
     ;
   else if (!TREE_SIDE_EFFECTS (expr))
     {
-      if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
+      if (!VOID_TYPE_P (TREE_TYPE (expr))
+	  && !warning_suppressed_p (expr, OPT_Wunused_value))
 	warning_at (loc, OPT_Wunused_value, "statement with no effect");
     }
   else if (TREE_CODE (expr) == COMPOUND_EXPR)
@@ -11233,8 +11230,8 @@ emit_side_effect_warnings (location_t loc, tree expr)
       if (!TREE_SIDE_EFFECTS (r)
 	  && !VOID_TYPE_P (TREE_TYPE (r))
 	  && !CONVERT_EXPR_P (r)
-	  && !TREE_NO_WARNING (r)
-	  && !TREE_NO_WARNING (expr))
+	  && !warning_suppressed_p (r, OPT_Wunused_value)
+	  && !warning_suppressed_p (expr, OPT_Wunused_value))
 	warning_at (cloc, OPT_Wunused_value,
 		    "right-hand operand of comma expression has no effect");
     }
@@ -11403,7 +11400,7 @@ c_finish_stmt_expr (location_t loc, tree body)
       last = c_wrap_maybe_const (last, true);
       /* Do not warn if the return value of a statement expression is
 	 unused.  */
-      TREE_NO_WARNING (last) = 1;
+      suppress_warning (last, OPT_Wunused);
       return last;
     }
 
@@ -15453,7 +15450,7 @@ c_omp_clause_copy_ctor (tree clause, tree dst, tree src)
   tree tmp = create_tmp_var (nonatomic_type);
   tree tmp_addr = build_fold_addr_expr (tmp);
   TREE_ADDRESSABLE (tmp) = 1;
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tree src_addr = build_fold_addr_expr (src);
   tree dst_addr = build_fold_addr_expr (dst);
   tree seq_cst = build_int_cst (integer_type_node, MEMMODEL_SEQ_CST);

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 4/13] v2 Use new per-location warning APIs in C family code
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (2 preceding siblings ...)
  2021-06-04 21:41     ` [PATCH 3/13] v2 Use new per-location warning APIs in C front end Martin Sebor
@ 2021-06-04 21:42     ` Martin Sebor
  2021-06-21 21:35       ` [PING][PATCH " Martin Sebor
  2021-06-24  5:06       ` [PATCH " Jeff Law
  2021-06-04 21:42     ` [PATCH 5/13] v2 Use new per-location warning APIs in the RL78 back end Martin Sebor
                       ` (10 subsequent siblings)
  14 siblings, 2 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:42 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 171 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the shared
C family front end with the new suppress_warning(),
warning_suppressed_p(), and copy_warning() APIs.

[-- Attachment #2: gcc-no-warning-c-family.diff --]
[-- Type: text/x-patch, Size: 4494 bytes --]

Add support for per-location warning groups.

gcc/c-family/ChangeLog:

	* c-common.c (c_wrap_maybe_const): Remove TREE_NO_WARNING.
	(c_common_truthvalue_conversion): Replace direct uses of
	TREE_NO_WARNING with warning_suppressed_p, suppress_warning, and
	copy_no_warning.
	(check_function_arguments_recurse): Same.
	* c-gimplify.c (c_gimplify_expr): Same.
	* c-warn.c (overflow_warning): Same.
	(warn_logical_operator): Same.
	(warn_if_unused_value): Same.
	(do_warn_unused_parameter): Same.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index c4eb2b1c920..681fcc972f4 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -3375,7 +3375,6 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
 tree
 c_wrap_maybe_const (tree expr, bool non_const)
 {
-  bool nowarning = TREE_NO_WARNING (expr);
   location_t loc = EXPR_LOCATION (expr);
 
   /* This should never be called for C++.  */
@@ -3386,8 +3385,6 @@ c_wrap_maybe_const (tree expr, bool non_const)
   STRIP_TYPE_NOPS (expr);
   expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
   C_MAYBE_CONST_EXPR_NON_CONST (expr) = non_const;
-  if (nowarning)
-    TREE_NO_WARNING (expr) = 1;
   protected_set_expr_location (expr, loc);
 
   return expr;
@@ -3633,12 +3630,12 @@ c_common_truthvalue_conversion (location_t location, tree expr)
       break;
 
     case MODIFY_EXPR:
-      if (!TREE_NO_WARNING (expr)
+      if (!warning_suppressed_p (expr, OPT_Wparentheses)
 	  && warn_parentheses
 	  && warning_at (location, OPT_Wparentheses,
 			 "suggest parentheses around assignment used as "
 			 "truth value"))
-	TREE_NO_WARNING (expr) = 1;
+	suppress_warning (expr, OPT_Wparentheses);
       break;
 
     case CONST_DECL:
@@ -6019,7 +6016,7 @@ check_function_arguments_recurse (void (*callback)
 				  void *ctx, tree param,
 				  unsigned HOST_WIDE_INT param_num)
 {
-  if (TREE_NO_WARNING (param))
+  if (warning_suppressed_p (param))
     return;
 
   if (CONVERT_EXPR_P (param)
diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
index 39c969d8f40..0d38b706f4c 100644
--- a/gcc/c-family/c-gimplify.c
+++ b/gcc/c-family/c-gimplify.c
@@ -713,7 +713,7 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
 	  && !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
 	  && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p)) == DECL_EXPR_DECL (*expr_p))
 	  && !warn_init_self)
-	TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
+	suppress_warning (DECL_EXPR_DECL (*expr_p), OPT_Winit_self);
       break;
 
     case PREINCREMENT_EXPR:
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index a587b993fde..cfa2373585f 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -155,7 +155,7 @@ overflow_warning (location_t loc, tree value, tree expr)
 			 value);
 
   if (warned)
-    TREE_NO_WARNING (value) = 1;
+    suppress_warning (value, OPT_Woverflow);
 }
 
 /* Helper function for walk_tree.  Unwrap C_MAYBE_CONST_EXPRs in an expression
@@ -219,7 +219,7 @@ warn_logical_operator (location_t location, enum tree_code code, tree type,
       && INTEGRAL_TYPE_P (TREE_TYPE (op_left))
       && !CONSTANT_CLASS_P (stripped_op_left)
       && TREE_CODE (stripped_op_left) != CONST_DECL
-      && !TREE_NO_WARNING (op_left)
+      && !warning_suppressed_p (op_left, OPT_Wlogical_op)
       && TREE_CODE (op_right) == INTEGER_CST
       && !integer_zerop (op_right)
       && !integer_onep (op_right))
@@ -234,7 +234,7 @@ warn_logical_operator (location_t location, enum tree_code code, tree type,
 	  = warning_at (location, OPT_Wlogical_op,
 			"logical %<and%> applied to non-boolean constant");
       if (warned)
-	TREE_NO_WARNING (op_left) = true;
+	suppress_warning (op_left, OPT_Wlogical_op);
       return;
     }
 
@@ -588,7 +588,7 @@ bool
 warn_if_unused_value (const_tree exp, location_t locus, bool quiet)
 {
  restart:
-  if (TREE_USED (exp) || TREE_NO_WARNING (exp))
+  if (TREE_USED (exp) || warning_suppressed_p (exp, OPT_Wunused_value))
     return false;
 
   /* Don't warn about void constructs.  This includes casting to void,
@@ -2422,7 +2422,7 @@ do_warn_unused_parameter (tree fn)
        decl; decl = DECL_CHAIN (decl))
     if (!TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL
 	&& DECL_NAME (decl) && !DECL_ARTIFICIAL (decl)
-	&& !TREE_NO_WARNING (decl))
+	&& !warning_suppressed_p (decl, OPT_Wunused_parameter))
       warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wunused_parameter,
 		  "unused parameter %qD", decl);
 }

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 5/13] v2 Use new per-location warning APIs in the RL78 back end
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (3 preceding siblings ...)
  2021-06-04 21:42     ` [PATCH 4/13] v2 Use new per-location warning APIs in C family code Martin Sebor
@ 2021-06-04 21:42     ` Martin Sebor
  2021-06-24  5:06       ` Jeff Law
  2021-06-04 21:42     ` [PATCH 6/13] v2 Use new per-location warning APIs in the C++ front end Martin Sebor
                       ` (9 subsequent siblings)
  14 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:42 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 142 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the RL78
back end with the new suppress_warning() and warning_suppressed_p()
APIs.

[-- Attachment #2: gcc-no-warning-rl78.diff --]
[-- Type: text/x-patch, Size: 674 bytes --]

Add support for per-location warning groups.

gcc/ChangeLog:

	* config/rl78/rl78.c (rl78_handle_naked_attribute): Replace a direct
	use of TREE_NO_WARNING with suppress_warning.

diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index 4c34949a97f..22d1690a035 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -847,7 +847,7 @@ rl78_handle_naked_attribute (tree * node,
   /* Disable warnings about this function - eg reaching the end without
      seeing a return statement - because the programmer is doing things
      that gcc does not know about.  */
-  TREE_NO_WARNING (* node) = 1;
+  suppress_warning (* node);
 
   return NULL_TREE;
 }

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 6/13] v2 Use new per-location warning APIs in the C++ front end
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (4 preceding siblings ...)
  2021-06-04 21:42     ` [PATCH 5/13] v2 Use new per-location warning APIs in the RL78 back end Martin Sebor
@ 2021-06-04 21:42     ` Martin Sebor
  2021-06-21 21:37       ` [PING][PATCH " Martin Sebor
  2021-06-24  5:12       ` [PATCH " Jeff Law
  2021-06-04 21:42     ` [PATCH 7/13] v2 Use new per-location warning APIs in the FORTRAN " Martin Sebor
                       ` (8 subsequent siblings)
  14 siblings, 2 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:42 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 159 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the C++
front end with the new suppress_warning(), warning_suppressed_p(),
and copy_warning() APIs.

[-- Attachment #2: gcc-no-warning-cp.diff --]
[-- Type: text/x-patch, Size: 33890 bytes --]

Add support for per-location warning groups.

	* call.c (build_over_call): Replace direct uses of TREE_NO_WARNING
	with warning_suppressed_p, suppress_warning, and copy_no_warning, or
	nothing if not necessary.
	(set_up_extended_ref_temp): Same.
	* class.c (layout_class_type): Same.
	* constraint.cc (constraint_satisfaction_value): Same.
	* coroutines.cc (finish_co_await_expr): Same.
	(finish_co_yield_expr): Same.
	(finish_co_return_stmt): Same.
	(build_actor_fn): Same.
	(coro_rewrite_function_body): Same.
	(morph_fn_to_coro): Same.
	* cp-gimplify.c (genericize_eh_spec_block): Same.
	(gimplify_expr_stmt): Same.
	(cp_genericize_r): Same.
	(cp_fold): Same.
	* cp-ubsan.c (cp_ubsan_instrument_vptr): Same.
	* cvt.c (cp_fold_convert): Same.
	(convert_to_void): Same.
	* decl.c (wrapup_namespace_globals): Same.
	(grokdeclarator): Same.
	(finish_function): Same.
	(require_deduced_type): Same.
	* decl2.c (no_linkage_error): Same.
	(c_parse_final_cleanups): Same.
	* except.c (expand_end_catch_block): Same.
	* init.c (build_new_1): Same.
	(build_new): Same.
	(build_vec_delete_1): Same.
	(build_vec_init): Same.
	(build_delete): Same.
	* method.c (defaultable_fn_check): Same.
	* parser.c (cp_parser_fold_expression): Same.
	(cp_parser_primary_expression): Same.
	* pt.c (push_tinst_level_loc): Same.
	(tsubst_copy): Same.
	(tsubst_omp_udr): Same.
	(tsubst_copy_and_build): Same.
	* rtti.c (build_if_nonnull): Same.
	* semantics.c (maybe_convert_cond): Same.
	(finish_return_stmt): Same.
	(finish_parenthesized_expr): Same.
	(cp_check_omp_declare_reduction): Same.
	* tree.c (build_cplus_array_type): Same.
	* typeck.c (build_ptrmemfunc_access_expr): Same.
	(cp_build_indirect_ref_1): Same.
	(cp_build_function_call_vec): Same.
	(warn_for_null_address): Same.
	(cp_build_binary_op): Same.
	(unary_complex_lvalue): Same.
	(cp_build_modify_expr): Same.
	(build_x_modify_expr): Same.
	(convert_for_assignment): Same.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 17fc60cd4af..0afddd56496 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -9461,7 +9461,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	{
 	  /* Avoid copying empty classes.  */
 	  val = build2 (COMPOUND_EXPR, type, arg, to);
-	  TREE_NO_WARNING (val) = 1;
+	  suppress_warning (val, OPT_Wunused);
 	}
       else if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
 	{
@@ -9492,7 +9492,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 		      build2 (MEM_REF, array_type, arg0, alias_set),
 		      build2 (MEM_REF, array_type, arg, alias_set));
 	  val = build2 (COMPOUND_EXPR, TREE_TYPE (to), t, to);
-          TREE_NO_WARNING (val) = 1;
+          suppress_warning (val, OPT_Wunused);
 	}
 
       cp_warn_deprecated_use (fn, complain);
@@ -9566,7 +9566,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
     {
       tree c = extract_call_expr (call);
       if (TREE_CODE (c) == CALL_EXPR)
-	TREE_NO_WARNING (c) = 1;
+	suppress_warning (c /* Suppress all warnings.  */);
     }
   if (TREE_CODE (fn) == ADDR_EXPR)
     {
@@ -12516,11 +12516,11 @@ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups,
     TREE_ADDRESSABLE (var) = 1;
 
   if (TREE_CODE (decl) == FIELD_DECL
-      && extra_warnings && !TREE_NO_WARNING (decl))
+      && extra_warnings && !warning_suppressed_p (decl))
     {
       warning (OPT_Wextra, "a temporary bound to %qD only persists "
 	       "until the constructor exits", decl);
-      TREE_NO_WARNING (decl) = true;
+      suppress_warning (decl);
     }
 
   /* Recursively extend temps in this initializer.  */
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b53a4dbdd4e..c89ffadcef8 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6704,7 +6704,7 @@ layout_class_type (tree t, tree *virtuals_p)
 	     laying out an Objective-C class.  The ObjC ABI differs
 	     from the C++ ABI, and so we do not want a warning
 	     here.  */
-	  && !TREE_NO_WARNING (field)
+	  && !warning_suppressed_p (field, OPT_Wabi)
 	  && !last_field_was_bitfield
 	  && !integer_zerop (size_binop (TRUNC_MOD_EXPR,
 					 DECL_FIELD_BIT_OFFSET (field),
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 03ce8eb9ff2..ae88666e4a2 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3281,14 +3281,14 @@ constraint_satisfaction_value (tree t, tree args, sat_info info)
   else
     r = satisfy_nondeclaration_constraints (t, args, info);
   if (r == error_mark_node && info.quiet ()
-      && !(DECL_P (t) && TREE_NO_WARNING (t)))
+      && !(DECL_P (t) && warning_suppressed_p (t)))
     {
       /* Replay the error noisily.  */
       sat_info noisy (tf_warning_or_error, info.in_decl);
       constraint_satisfaction_value (t, args, noisy);
       if (DECL_P (t) && !args)
 	/* Avoid giving these errors again.  */
-	TREE_NO_WARNING (t) = true;
+	suppress_warning (t);
     }
   return r;
 }
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 1bf1931e7be..a1b0b31f497 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -1078,7 +1078,7 @@ finish_co_await_expr (location_t kw, tree expr)
      is declared to return non-void (most likely).  This is correct - we
      synthesize the return for the ramp in the compiler.  So suppress any
      extraneous warnings during substitution.  */
-  TREE_NO_WARNING (current_function_decl) = true;
+  suppress_warning (current_function_decl, OPT_Wreturn_type);
 
   /* If we don't know the promise type, we can't proceed, build the
      co_await with the expression unchanged.  */
@@ -1154,7 +1154,7 @@ finish_co_yield_expr (location_t kw, tree expr)
      is declared to return non-void (most likely).  This is correct - we
      synthesize the return for the ramp in the compiler.  So suppress any
      extraneous warnings during substitution.  */
-  TREE_NO_WARNING (current_function_decl) = true;
+  suppress_warning (current_function_decl, OPT_Wreturn_type);
 
   /* If we don't know the promise type, we can't proceed, build the
      co_await with the expression unchanged.  */
@@ -1235,7 +1235,7 @@ finish_co_return_stmt (location_t kw, tree expr)
      is declared to return non-void (most likely).  This is correct - we
      synthesize the return for the ramp in the compiler.  So suppress any
      extraneous warnings during substitution.  */
-  TREE_NO_WARNING (current_function_decl) = true;
+  suppress_warning (current_function_decl, OPT_Wreturn_type);
 
   if (processing_template_decl
       && check_for_bare_parameter_packs (expr))
@@ -1259,7 +1259,7 @@ finish_co_return_stmt (location_t kw, tree expr)
 
   /* Suppress -Wreturn-type for co_return, we need to check indirectly
      whether the promise type has a suitable return_void/return_value.  */
-  TREE_NO_WARNING (current_function_decl) = true;
+  suppress_warning (current_function_decl, OPT_Wreturn_type);
 
   if (!processing_template_decl && warn_sequence_point)
     verify_sequence_points (expr);
@@ -2458,7 +2458,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
 
   /* done.  */
   r = build_stmt (loc, RETURN_EXPR, NULL);
-  TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this.  */
+  suppress_warning (r); /* We don't want a warning about this.  */
   r = maybe_cleanup_point_expr_void (r);
   add_stmt (r);
 
@@ -2467,7 +2467,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
   add_stmt (r);
 
   r = build_stmt (loc, RETURN_EXPR, NULL);
-  TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this.  */
+  suppress_warning (r); /* We don't want a warning about this.  */
   r = maybe_cleanup_point_expr_void (r);
   add_stmt (r);
 
@@ -4142,7 +4142,7 @@ coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
       finish_if_stmt_cond (not_iarc, not_iarc_if);
       /* If the initial await resume called value is false, rethrow...  */
       tree rethrow = build_throw (fn_start, NULL_TREE);
-      TREE_NO_WARNING (rethrow) = true;
+      suppress_warning (rethrow);
       finish_expr_stmt (rethrow);
       finish_then_clause (not_iarc_if);
       tree iarc_scope = IF_SCOPE (not_iarc_if);
@@ -4243,7 +4243,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
       /* For early errors, we do not want a diagnostic about the missing
 	 ramp return value, since the user cannot fix this - a 'return' is
 	 not allowed in a coroutine.  */
-      TREE_NO_WARNING (orig) = true;
+      suppress_warning (orig, OPT_Wreturn_type);
       /* Discard the body, we can't process it further.  */
       pop_stmt_list (DECL_SAVED_TREE (orig));
       DECL_SAVED_TREE (orig) = push_stmt_list ();
@@ -4269,7 +4269,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
       DECL_SAVED_TREE (orig) = push_stmt_list ();
       append_to_statement_list (fnbody, &DECL_SAVED_TREE (orig));
       /* Suppress warnings about the missing return value.  */
-      TREE_NO_WARNING (orig) = true;
+      suppress_warning (orig, OPT_Wreturn_type);
       return false;
     }
 
@@ -4948,7 +4948,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
       BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
       DECL_SAVED_TREE (orig) = newbody;
       /* Suppress warnings about the missing return value.  */
-      TREE_NO_WARNING (orig) = true;
+      suppress_warning (orig, OPT_Wreturn_type);
       return false;
     }
 
@@ -5159,7 +5159,7 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
 					      promise_type, fn_start);
       finish_expr_stmt (del_coro_fr);
       tree rethrow = build_throw (fn_start, NULL_TREE);
-      TREE_NO_WARNING (rethrow) = true;
+      suppress_warning (rethrow);
       finish_expr_stmt (rethrow);
       finish_handler (handler);
       TRY_HANDLERS (ramp_cleanup) = pop_stmt_list (TRY_HANDLERS (ramp_cleanup));
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 9079a5b90ca..8e14226844a 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -101,8 +101,8 @@ genericize_eh_spec_block (tree *stmt_p)
   tree failure = build_call_n (call_unexpected_fn, 1, build_exc_ptr ());
 
   *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure);
-  TREE_NO_WARNING (*stmt_p) = true;
-  TREE_NO_WARNING (TREE_OPERAND (*stmt_p, 1)) = true;
+  suppress_warning (*stmt_p);
+  suppress_warning (TREE_OPERAND (*stmt_p, 1));
 }
 
 /* Return the first non-compound statement in STMT.  */
@@ -214,7 +214,7 @@ gimplify_expr_stmt (tree *stmt_p)
 	{
 	  if (!IS_EMPTY_STMT (stmt)
 	      && !VOID_TYPE_P (TREE_TYPE (stmt))
-	      && !TREE_NO_WARNING (stmt))
+	      && !warning_suppressed_p (stmt, OPT_Wunused_value))
 	    warning (OPT_Wunused_value, "statement with no effect");
 	}
       else
@@ -1322,7 +1322,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
     case THROW_EXPR:
       {
 	location_t loc = location_of (stmt);
-	if (TREE_NO_WARNING (stmt))
+	if (warning_suppressed_p (stmt /* What warning? */))
 	  /* Never mind.  */;
 	else if (wtd->try_block)
 	  {
@@ -2443,8 +2443,9 @@ cp_fold (tree x)
 	    ;
 	  else if (COMPARISON_CLASS_P (x))
 	    {
-	      if (TREE_NO_WARNING (org_x) && warn_nonnull_compare)
-		TREE_NO_WARNING (x) = 1;
+	      if (warn_nonnull_compare
+		  && warning_suppressed_p (org_x, OPT_Wnonnull_compare))
+		suppress_warning (x, OPT_Wnonnull_compare);
 	    }
 	  /* Otherwise give up on optimizing these, let GIMPLE folders
 	     optimize those later on.  */
@@ -2452,8 +2453,9 @@ cp_fold (tree x)
 		   || op1 != TREE_OPERAND (org_x, 1))
 	    {
 	      x = build2_loc (loc, code, TREE_TYPE (org_x), op0, op1);
-	      if (TREE_NO_WARNING (org_x) && warn_nonnull_compare)
-		TREE_NO_WARNING (x) = 1;
+	      if (warn_nonnull_compare
+		  && warning_suppressed_p (org_x, OPT_Wnonnull_compare))
+		suppress_warning (x, OPT_Wnonnull_compare);
 	    }
 	  else
 	    x = org_x;
@@ -2709,7 +2711,7 @@ cp_fold (tree x)
   if (EXPR_P (x) && TREE_CODE (x) == code)
     {
       TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x);
-      TREE_NO_WARNING (x) = TREE_NO_WARNING (org_x);
+      copy_warning (x, org_x);
     }
 
   if (!c.evaluation_restricted_p ())
diff --git a/gcc/cp/cp-ubsan.c b/gcc/cp/cp-ubsan.c
index 3dabb6aa18a..78545945d75 100644
--- a/gcc/cp/cp-ubsan.c
+++ b/gcc/cp/cp-ubsan.c
@@ -81,7 +81,7 @@ cp_ubsan_instrument_vptr (location_t loc, tree op, tree type, bool is_addr,
 			      build_zero_cst (TREE_TYPE (op)));
       /* This is a compiler generated comparison, don't emit
 	 e.g. -Wnonnull-compare warning for it.  */
-      TREE_NO_WARNING (cond) = 1;
+      suppress_warning (cond, OPT_Wnonnull_compare);
       vptr = build3_loc (loc, COND_EXPR, uint64_type_node, cond,
 			 vptr, build_int_cst (uint64_type_node, 0));
     }
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 330d65854b4..d035e611be4 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -605,8 +605,6 @@ ignore_overflows (tree expr, tree orig)
 tree
 cp_fold_convert (tree type, tree expr)
 {
-  bool nowarn = TREE_NO_WARNING (expr);
-
   tree conv;
   if (TREE_TYPE (expr) == type)
     conv = expr;
@@ -630,8 +628,8 @@ cp_fold_convert (tree type, tree expr)
       conv = ignore_overflows (conv, expr);
     }
 
-  if (nowarn && TREE_CODE (expr) == TREE_CODE (conv))
-    TREE_NO_WARNING (conv) = nowarn;
+  if (TREE_CODE (expr) == TREE_CODE (conv))
+    copy_warning (conv, expr);
 
   return conv;
 }
@@ -1208,7 +1206,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
 	/* The second part of a compound expr contains the value.  */
 	tree op1 = TREE_OPERAND (expr,1);
 	tree new_op1;
-	if (implicit != ICV_CAST && !TREE_NO_WARNING (expr))
+	if (implicit != ICV_CAST && !warning_suppressed_p (expr /* What warning? */))
 	  new_op1 = convert_to_void (op1, ICV_RIGHT_OF_COMMA, complain);
 	else
 	  new_op1 = convert_to_void (op1, ICV_CAST, complain);
@@ -1394,7 +1392,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
             if (warn_unused_value
 		&& implicit != ICV_CAST
                 && (complain & tf_warning)
-                && !TREE_NO_WARNING (expr)
+                && !warning_suppressed_p (expr, OPT_Wunused_value)
                 && !is_reference)
               warning_at (loc, OPT_Wunused_value, "value computed is not used");
             expr = TREE_OPERAND (expr, 0);
@@ -1578,7 +1576,7 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
     {
       if (implicit != ICV_CAST
 	  && warn_unused_value
-	  && !TREE_NO_WARNING (expr)
+	  && !warning_suppressed_p (expr, OPT_Wunused_value)
 	  && !processing_template_decl
 	  && !cp_unevaluated_operand
 	  && (complain & tf_warning))
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index a3687dbb0dd..430979c47b9 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -839,7 +839,7 @@ wrapup_namespace_globals ()
 	      && !TREE_PUBLIC (decl)
 	      && !DECL_ARTIFICIAL (decl)
 	      && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)
-	      && !TREE_NO_WARNING (decl))
+	      && !warning_suppressed_p (decl, OPT_Wunused_function))
 	    warning_at (DECL_SOURCE_LOCATION (decl),
 			OPT_Wunused_function,
 			"%qF declared %<static%> but never defined", decl);
@@ -13883,10 +13883,7 @@ grokdeclarator (const cp_declarator *declarator,
 		decl = build_decl (id_loc, FIELD_DECL, unqualified_id, type);
 		DECL_NONADDRESSABLE_P (decl) = bitfield;
 		if (bitfield && !unqualified_id)
-		  {
-		    TREE_NO_WARNING (decl) = 1;
-		    DECL_PADDING_P (decl) = 1;
-		  }
+		  DECL_PADDING_P (decl) = 1;
 
 		if (storage_class == sc_mutable)
 		  {
@@ -17472,7 +17469,7 @@ finish_function (bool inline_p)
       /* Don't complain if we are declared noreturn.  */
       && !TREE_THIS_VOLATILE (fndecl)
       && !DECL_NAME (DECL_RESULT (fndecl))
-      && !TREE_NO_WARNING (fndecl)
+      && !warning_suppressed_p (fndecl, OPT_Wreturn_type)
       /* Structor return values (if any) are set by the compiler.  */
       && !DECL_CONSTRUCTOR_P (fndecl)
       && !DECL_DESTRUCTOR_P (fndecl)
@@ -17500,7 +17497,7 @@ finish_function (bool inline_p)
       else if (warning_at (&richloc, OPT_Wreturn_type,
 			   "no return statement in function returning "
 			   "non-void"))
-	TREE_NO_WARNING (fndecl) = 1;
+	suppress_warning (fndecl, OPT_Wreturn_type);
     }
 
   /* Lambda closure members are implicitly constexpr if possible.  */
@@ -17574,7 +17571,7 @@ finish_function (bool inline_p)
 	    && !DECL_READ_P (decl)
 	    && DECL_NAME (decl)
 	    && !DECL_ARTIFICIAL (decl)
-	    && !TREE_NO_WARNING (decl)
+	    && !warning_suppressed_p (decl,OPT_Wunused_but_set_parameter)
 	    && !DECL_IN_SYSTEM_HEADER (decl)
 	    && TREE_TYPE (decl) != error_mark_node
 	    && !TYPE_REF_P (TREE_TYPE (decl))
@@ -18065,7 +18062,7 @@ require_deduced_type (tree decl, tsubst_flags_t complain)
 {
   if (undeduced_auto_decl (decl))
     {
-      if (TREE_NO_WARNING (decl) && seen_error ())
+      if (warning_suppressed_p (decl) && seen_error ())
 	/* We probably already complained about deduction failure.  */;
       else if (complain & tf_error)
 	error ("use of %qD before deduction of %<auto%>", decl);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index e46fded908a..090a83bd670 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4529,7 +4529,7 @@ no_linkage_error (tree decl)
 	  || (errorcount + sorrycount > 0
 	      && DECL_LANG_SPECIFIC (decl)
 	      && DECL_TEMPLATE_INFO (decl)
-	      && TREE_NO_WARNING (decl))))
+	      && warning_suppressed_p (decl /* What warning? */))))
     /* In C++11 it's ok if the decl is defined.  */
     return;
 
@@ -5204,7 +5204,7 @@ c_parse_final_cleanups (void)
 	  && warning_at (DECL_SOURCE_LOCATION (decl), 0,
 			 "inline function %qD used but never defined", decl))
 	/* Avoid a duplicate warning from check_global_declaration.  */
-	TREE_NO_WARNING (decl) = 1;
+	suppress_warning (decl, OPT_Wunused);
     }
 
   /* So must decls that use a type with no linkage.  */
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index cbafc09629b..a8cea53cf91 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -466,7 +466,8 @@ expand_end_catch_block (void)
 	  || DECL_DESTRUCTOR_P (current_function_decl)))
     {
       tree rethrow = build_throw (input_location, NULL_TREE);
-      TREE_NO_WARNING (rethrow) = true;
+      /* Disable all warnings for the generated rethrow statement.  */
+      suppress_warning (rethrow);
       finish_expr_stmt (rethrow);
     }
 }
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index b1123287300..2873c13a235 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3536,11 +3536,11 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 	       the arguments to the constructor call.  */
 	    {
 	      /* CLEANUP is compiler-generated, so no diagnostics.  */
-	      TREE_NO_WARNING (cleanup) = true;
+	      suppress_warning (cleanup);
 	      init_expr = build2 (TRY_CATCH_EXPR, void_type_node,
 				  init_expr, cleanup);
 	      /* Likewise, this try-catch is compiler-generated.  */
-	      TREE_NO_WARNING (init_expr) = true;
+	      suppress_warning (init_expr);
 	    }
 	  else
 	    /* Ack!  First we allocate the memory.  Then we set our sentry
@@ -3562,7 +3562,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 	      sentry = TARGET_EXPR_SLOT (begin);
 
 	      /* CLEANUP is compiler-generated, so no diagnostics.  */
-	      TREE_NO_WARNING (cleanup) = true;
+	      suppress_warning (cleanup);
 
 	      TARGET_EXPR_CLEANUP (begin)
 		= build3 (COND_EXPR, void_type_node, sentry,
@@ -3576,7 +3576,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 			  build2 (COMPOUND_EXPR, void_type_node, init_expr,
 				  end));
 	      /* Likewise, this is compiler-generated.  */
-	      TREE_NO_WARNING (init_expr) = true;
+	      suppress_warning (init_expr);
 	    }
 	}
     }
@@ -3823,7 +3823,7 @@ build_new (location_t loc, vec<tree, va_gc> **placement, tree type,
 
   /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain.  */
   rval = build1_loc (loc, NOP_EXPR, TREE_TYPE (rval), rval);
-  TREE_NO_WARNING (rval) = 1;
+  suppress_warning (rval, OPT_Wunused_value);
 
   return rval;
 }
@@ -3995,7 +3995,7 @@ build_vec_delete_1 (location_t loc, tree base, tree maxindex, tree type,
 			  fold_convert (TREE_TYPE (base), nullptr_node));
   /* This is a compiler generated comparison, don't emit
      e.g. -Wnonnull-compare warning for it.  */
-  TREE_NO_WARNING (cond) = 1;
+  suppress_warning (cond, OPT_Wnonnull_compare);
   body = build3_loc (loc, COND_EXPR, void_type_node,
 		     cond, body, integer_zero_node);
   COND_EXPR_IS_VEC_DELETE (body) = true;
@@ -4657,7 +4657,7 @@ build_vec_init (tree base, tree maxindex, tree init,
       atype = build_pointer_type (atype);
       stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
       stmt_expr = cp_build_fold_indirect_ref (stmt_expr);
-      TREE_NO_WARNING (stmt_expr) = 1;
+      suppress_warning (stmt_expr /* What warning? */);
     }
 
   return stmt_expr;
@@ -4927,7 +4927,7 @@ build_delete (location_t loc, tree otype, tree addr,
   /* This is a compiler generated comparison, don't emit
      e.g. -Wnonnull-compare warning for it.  */
   else if (TREE_CODE (ifexp) == NE_EXPR)
-    TREE_NO_WARNING (ifexp) = 1;
+    suppress_warning (ifexp, OPT_Wnonnull_compare);
 
   if (!integer_nonzerop (ifexp))
     expr = build3 (COND_EXPR, void_type_node, ifexp, expr, void_node);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index dd745237f22..f268aab1a79 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -3284,7 +3284,7 @@ defaultable_fn_check (tree fn)
       /* Avoid do_warn_unused_parameter warnings.  */
       for (tree p = FUNCTION_FIRST_USER_PARM (fn); p; p = DECL_CHAIN (p))
 	if (DECL_NAME (p))
-	  TREE_NO_WARNING (p) = 1;
+	  suppress_warning (p, OPT_Wunused_parameter);
 
       if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
 	/* Defer checking.  */;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4a46828e162..8aa73781cc9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1,3 +1,4 @@
+
 /* -*- C++ -*- Parser.
    Copyright (C) 2000-2021 Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
@@ -5322,7 +5323,7 @@ cp_parser_fold_expression (cp_parser *parser, tree expr1)
   /* The operands of a fold-expression are cast-expressions, so binary or
      conditional expressions are not allowed.  We check this here to avoid
      tentative parsing.  */
-  if (EXPR_P (expr1) && TREE_NO_WARNING (expr1))
+  if (EXPR_P (expr1) && warning_suppressed_p (expr1, OPT_Wparentheses))
     /* OK, the expression was parenthesized.  */;
   else if (is_binary_op (TREE_CODE (expr1)))
     error_at (location_of (expr1),
@@ -5604,7 +5605,10 @@ cp_parser_primary_expression (cp_parser *parser,
 	/* Consume the `)'.  */
 	token = cp_lexer_peek_token (parser->lexer);
 	location_t close_paren_loc = token->location;
+	bool no_wparens = warning_suppressed_p (expr, OPT_Wparentheses);
 	expr.set_range (open_paren_loc, close_paren_loc);
+	if (no_wparens)
+	  suppress_warning (expr, OPT_Wparentheses);
 	if (!parens.require_close (parser)
 	    && !cp_parser_uncommitted_to_tentative_parse_p (parser))
 	  cp_parser_skip_to_end_of_statement (parser);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7211bdc5bbc..a7d4a222c8b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10936,9 +10936,9 @@ push_tinst_level_loc (tree tldcl, tree targs, location_t loc)
      constant expressions.  */
   if (!targs && limit_bad_template_recursion (tldcl))
     {
-      /* Avoid no_linkage_errors and unused function warnings for this
-	 decl.  */
-      TREE_NO_WARNING (tldcl) = 1;
+      /* Avoid no_linkage_errors and unused function (and all other)
+	 warnings for this decl.  */
+      suppress_warning (tldcl);
       return false;
     }
 
@@ -17084,7 +17084,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	tree op1 = tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl);
 	tree op2 = tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl);
 	r = build_nt (code, op0, op1, op2);
-	TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+	copy_warning (r, t);
 	return r;
       }
 
@@ -19166,8 +19166,7 @@ tsubst_omp_udr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       block = finish_omp_structured_block (block);
       block = maybe_cleanup_point_expr_void (block);
       add_decl_expr (omp_out);
-      if (TREE_NO_WARNING (DECL_EXPR_DECL (stmts[0])))
-	TREE_NO_WARNING (omp_out) = 1;
+      copy_warning (omp_out, DECL_EXPR_DECL (stmts[0]));
       add_decl_expr (omp_in);
       finish_expr_stmt (block);
     }
@@ -19843,17 +19842,17 @@ tsubst_copy_and_build (tree t,
 	tree r = build_x_binary_op
 	  (input_location, TREE_CODE (t),
 	   op0,
-	   (TREE_NO_WARNING (TREE_OPERAND (t, 0))
+	   (warning_suppressed_p (TREE_OPERAND (t, 0))
 	    ? ERROR_MARK
 	    : TREE_CODE (TREE_OPERAND (t, 0))),
 	   op1,
-	   (TREE_NO_WARNING (TREE_OPERAND (t, 1))
+	   (warning_suppressed_p (TREE_OPERAND (t, 1))
 	    ? ERROR_MARK
 	    : TREE_CODE (TREE_OPERAND (t, 1))),
 	   /*overload=*/NULL,
 	   complain|decltype_flag);
-	if (EXPR_P (r) && TREE_NO_WARNING (t))
-	  TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+	if (EXPR_P (r))
+	  copy_warning (r, t);
 
 	RETURN (r);
       }
@@ -19989,8 +19988,8 @@ tsubst_copy_and_build (tree t,
 	   set and must be copied.  In the latter case,
 	   build_x_modify_expr sets it and it must not be reset
 	   here.  */
-	if (TREE_NO_WARNING (t))
-	  TREE_NO_WARNING (r) = TREE_NO_WARNING (t);
+	if (warning_suppressed_p (t, OPT_Wparentheses))
+	  suppress_warning (r, OPT_Wparentheses);
 
 	RETURN (r);
       }
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 82eaa286514..fcb33088a21 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -536,14 +536,14 @@ build_if_nonnull (tree test, tree result, tsubst_flags_t complain)
 
   /* This is a compiler generated comparison, don't emit
      e.g. -Wnonnull-compare warning for it.  */
-  TREE_NO_WARNING (cond) = 1;
+  suppress_warning (cond, OPT_Wnonnull);
 
   null_ptr = cp_convert (TREE_TYPE (result), nullptr_node, complain);
   cond = build3 (COND_EXPR, TREE_TYPE (result), cond, result, null_ptr);
 
   /* Likewise, don't emit -Wnonnull for using the result to call
      a member function.  */
-  TREE_NO_WARNING (cond) = 1;
+  suppress_warning (cond, OPT_Wnonnull);
   return cond;
 }
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index d08c1ddabf9..79660964e69 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -835,12 +835,12 @@ maybe_convert_cond (tree cond)
   cond = convert_from_reference (cond);
 
   if (TREE_CODE (cond) == MODIFY_EXPR
-      && !TREE_NO_WARNING (cond)
       && warn_parentheses
+      && !warning_suppressed_p (cond, OPT_Wparentheses)
       && warning_at (cp_expr_loc_or_input_loc (cond),
 		     OPT_Wparentheses, "suggest parentheses around "
 				       "assignment used as truth value"))
-    TREE_NO_WARNING (cond) = 1;
+    suppress_warning (cond, OPT_Wparentheses);
 
   return condition_conversion (cond);
 }
@@ -1143,7 +1143,7 @@ finish_return_stmt (tree expr)
     {
       /* Suppress -Wreturn-type for this function.  */
       if (warn_return_type)
-	TREE_NO_WARNING (current_function_decl) = true;
+	suppress_warning (current_function_decl, OPT_Wreturn_type);
       return error_mark_node;
     }
 
@@ -1165,7 +1165,8 @@ finish_return_stmt (tree expr)
     }
 
   r = build_stmt (input_location, RETURN_EXPR, expr);
-  TREE_NO_WARNING (r) |= no_warning;
+  if (no_warning)
+    suppress_warning (r, OPT_Wreturn_type);
   r = maybe_cleanup_point_expr_void (r);
   r = add_stmt (r);
 
@@ -2051,7 +2052,7 @@ finish_parenthesized_expr (cp_expr expr)
 {
   if (EXPR_P (expr))
     /* This inhibits warnings in c_common_truthvalue_conversion.  */
-    TREE_NO_WARNING (expr) = 1;
+    suppress_warning (expr, OPT_Wparentheses);
 
   if (TREE_CODE (expr) == OFFSET_REF
       || TREE_CODE (expr) == SCOPE_REF)
@@ -5926,12 +5927,12 @@ cp_check_omp_declare_reduction (tree udr)
     {
       gcc_assert (TREE_CODE (data.stmts[0]) == DECL_EXPR
 		  && TREE_CODE (data.stmts[1]) == DECL_EXPR);
-      if (TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])))
+      if (warning_suppressed_p (DECL_EXPR_DECL (data.stmts[0]) /* What warning? */))
 	return true;
       data.combiner_p = true;
       if (cp_walk_tree (&data.stmts[2], cp_check_omp_declare_reduction_r,
 			&data, NULL))
-	TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])) = 1;
+	suppress_warning (DECL_EXPR_DECL (data.stmts[0]) /* What warning? */);
     }
   if (i >= 6)
     {
@@ -5942,7 +5943,7 @@ cp_check_omp_declare_reduction (tree udr)
 			&data, NULL)
 	  || cp_walk_tree (&DECL_INITIAL (DECL_EXPR_DECL (data.stmts[3])),
 			   cp_check_omp_declare_reduction_r, &data, NULL))
-	TREE_NO_WARNING (DECL_EXPR_DECL (data.stmts[0])) = 1;
+	suppress_warning (DECL_EXPR_DECL (data.stmts[0])  /* Wat warning? */);
       if (i == 7)
 	gcc_assert (TREE_CODE (data.stmts[6]) == DECL_EXPR);
     }
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index fec5afaa2be..8595b3db9f2 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1127,7 +1127,7 @@ build_cplus_array_type (tree elt_type, tree index_type, int dependent)
 
   /* Avoid spurious warnings with VLAs (c++/54583).  */
   if (TYPE_SIZE (t) && EXPR_P (TYPE_SIZE (t)))
-    TREE_NO_WARNING (TYPE_SIZE (t)) = 1;
+    suppress_warning (TYPE_SIZE (t), OPT_Wunused);
 
   /* Push these needs up to the ARRAY_TYPE so that initialization takes
      place more easily.  */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index dbb2370510c..3d8897d513a 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3326,10 +3326,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
        member = DECL_CHAIN (member))
     if (DECL_NAME (member) == member_name)
       break;
-  tree res = build_simple_component_ref (ptrmem, member);
-
-  TREE_NO_WARNING (res) = 1;
-  return res;
+  return build_simple_component_ref (ptrmem, member);
 }
 
 /* Given an expression PTR for a pointer, return an expression
@@ -3443,7 +3440,7 @@ cp_build_indirect_ref_1 (location_t loc, tree ptr, ref_operator errorstring,
 	  if (warn_strict_aliasing > 2
 	      && cp_strict_aliasing_warning (EXPR_LOCATION (ptr),
 					     type, TREE_OPERAND (ptr, 0)))
-	    TREE_NO_WARNING (ptr) = 1;
+	    suppress_warning (ptr, OPT_Wstrict_aliasing);
 	}
 
       if (VOID_TYPE_P (t))
@@ -4068,7 +4065,7 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
     {
       tree c = extract_call_expr (ret);
       if (TREE_CODE (c) == CALL_EXPR)
-	TREE_NO_WARNING (c) = 1;
+	suppress_warning (c, OPT_Wnonnull);
     }
 
   if (allocated != NULL)
@@ -4450,14 +4447,14 @@ warn_for_null_address (location_t location, tree op, tsubst_flags_t complain)
   if (!warn_address
       || (complain & tf_warning) == 0
       || c_inhibit_evaluation_warnings != 0
-      || TREE_NO_WARNING (op))
+      || warning_suppressed_p (op, OPT_Waddress))
     return;
 
   tree cop = fold_for_warn (op);
 
   if (TREE_CODE (cop) == ADDR_EXPR
       && decl_with_nonnull_addr_p (TREE_OPERAND (cop, 0))
-      && !TREE_NO_WARNING (cop))
+      && !warning_suppressed_p (cop, OPT_Waddress))
     warning_at (location, OPT_Waddress, "the address of %qD will never "
 		"be NULL", TREE_OPERAND (cop, 0));
 
@@ -4878,7 +4875,7 @@ cp_build_binary_op (const op_location_t &location,
 	  else if (TREE_CODE (type0) == ARRAY_TYPE
 		   && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0)))
 		   /* Set by finish_parenthesized_expr.  */
-		   && !TREE_NO_WARNING (op1)
+		   && !warning_suppressed_p (op1, OPT_Wsizeof_array_div)
 		   && (complain & tf_warning))
 	    maybe_warn_sizeof_array_div (location, first_arg, type0,
 					 op1, non_reference (type1));
@@ -5297,7 +5294,7 @@ cp_build_binary_op (const op_location_t &location,
 	  pfn0 = cp_fully_fold (pfn0);
 	  /* Avoid -Waddress warnings (c++/64877).  */
 	  if (TREE_CODE (pfn0) == ADDR_EXPR)
-	    TREE_NO_WARNING (pfn0) = 1;
+	    suppress_warning (pfn0, OPT_Waddress);
 	  pfn1 = pfn_from_ptrmemfunc (op1);
 	  pfn1 = cp_fully_fold (pfn1);
 	  delta0 = delta_from_ptrmemfunc (op0);
@@ -7062,7 +7059,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
                                             tf_warning_or_error);
       arg = build2 (COMPOUND_EXPR, TREE_TYPE (real_result),
 		    arg, real_result);
-      TREE_NO_WARNING (arg) = 1;
+      suppress_warning (arg /* What warning? */);
       return arg;
     }
 
@@ -8973,7 +8970,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 
   TREE_SIDE_EFFECTS (result) = 1;
   if (!plain_assign)
-    TREE_NO_WARNING (result) = 1;
+    suppress_warning (result, OPT_Wparentheses);
 
  ret:
   if (preeval)
@@ -9017,7 +9014,7 @@ build_x_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 	{
 	  if (rval == error_mark_node)
 	    return rval;
-	  TREE_NO_WARNING (rval) = 1;
+	  suppress_warning (rval /* What warning? */);
 	  if (processing_template_decl)
 	    {
 	      if (overload != NULL_TREE)
@@ -9624,13 +9621,13 @@ convert_for_assignment (tree type, tree rhs,
   if (warn_parentheses
       && TREE_CODE (type) == BOOLEAN_TYPE
       && TREE_CODE (rhs) == MODIFY_EXPR
-      && !TREE_NO_WARNING (rhs)
+      && !warning_suppressed_p (rhs, OPT_Wparentheses)
       && TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE
       && (complain & tf_warning)
       && warning_at (rhs_loc, OPT_Wparentheses,
 		     "suggest parentheses around assignment used as "
 		     "truth value"))
-    TREE_NO_WARNING (rhs) = 1;
+    suppress_warning (rhs, OPT_Wparentheses);
 
   if (complain & tf_warning)
     warn_for_address_or_pointer_of_packed_member (type, rhs);

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 7/13] v2 Use new per-location warning APIs in the FORTRAN front end
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (5 preceding siblings ...)
  2021-06-04 21:42     ` [PATCH 6/13] v2 Use new per-location warning APIs in the C++ front end Martin Sebor
@ 2021-06-04 21:42     ` Martin Sebor
  2021-06-21 21:42       ` [PING][PATCH " Martin Sebor
  2021-06-24  5:05       ` [PATCH " Jeff Law
  2021-06-04 21:42     ` [PATCH 8/13] v2 Use new per-location warning APIs in libcc1 Martin Sebor
                       ` (7 subsequent siblings)
  14 siblings, 2 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:42 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 118 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the FORTRAN
front end with the new suppress_warning() API.

[-- Attachment #2: gcc-no-warning-fortran.diff --]
[-- Type: text/x-patch, Size: 17435 bytes --]

Add support for per-location warning groups.

gcc/fortran/ChangeLog:

	* trans-array.c (trans_array_constructor): Replace direct uses
	of TREE_NO_WARNING with warning_suppressed_p, and suppress_warning.
	* trans-decl.c (gfc_build_qualified_array): Same.
	(gfc_build_dummy_array_decl): Same.
	(generate_local_decl): Same.
	(gfc_generate_function_code): Same.
	* trans-openmp.c (gfc_omp_clause_default_ctor): Same.
	(gfc_omp_clause_copy_ctor): Same.
	* trans-types.c (get_dtype_type_node): Same.
	(gfc_get_desc_dim_type): Same.
	(gfc_get_array_descriptor_base): Same.
	(gfc_get_caf_vector_type): Same.
	(gfc_get_caf_reference_type): Same.
	* trans.c (gfc_create_var_np): Same.

diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 7eeef554c0f..64a050ff196 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -2755,7 +2755,7 @@ trans_array_constructor (gfc_ss * ss, locus * where)
   desc = ss_info->data.array.descriptor;
   offset = gfc_index_zero_node;
   offsetvar = gfc_create_var_np (gfc_array_index_type, "offset");
-  TREE_NO_WARNING (offsetvar) = 1;
+  suppress_warning (offsetvar);
   TREE_USED (offsetvar) = 0;
   gfc_trans_array_constructor_value (&outer_loop->pre, type, desc, c,
 				     &offset, &offsetvar, dynamic);
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index c32bd05bb1b..3f7953c8400 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -1040,7 +1040,7 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
       if (GFC_TYPE_ARRAY_LBOUND (type, dim) == NULL_TREE)
 	{
 	  GFC_TYPE_ARRAY_LBOUND (type, dim) = create_index_var ("lbound", nest);
-	  TREE_NO_WARNING (GFC_TYPE_ARRAY_LBOUND (type, dim)) = 1;
+	  suppress_warning (GFC_TYPE_ARRAY_LBOUND (type, dim));
 	}
       /* Don't try to use the unknown bound for assumed shape arrays.  */
       if (GFC_TYPE_ARRAY_UBOUND (type, dim) == NULL_TREE
@@ -1048,13 +1048,13 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
 	      || dim < GFC_TYPE_ARRAY_RANK (type) - 1))
 	{
 	  GFC_TYPE_ARRAY_UBOUND (type, dim) = create_index_var ("ubound", nest);
-	  TREE_NO_WARNING (GFC_TYPE_ARRAY_UBOUND (type, dim)) = 1;
+	  suppress_warning (GFC_TYPE_ARRAY_UBOUND (type, dim));
 	}
 
       if (GFC_TYPE_ARRAY_STRIDE (type, dim) == NULL_TREE)
 	{
 	  GFC_TYPE_ARRAY_STRIDE (type, dim) = create_index_var ("stride", nest);
-	  TREE_NO_WARNING (GFC_TYPE_ARRAY_STRIDE (type, dim)) = 1;
+	  suppress_warning (GFC_TYPE_ARRAY_STRIDE (type, dim));
 	}
     }
   for (dim = GFC_TYPE_ARRAY_RANK (type);
@@ -1063,21 +1063,21 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
       if (GFC_TYPE_ARRAY_LBOUND (type, dim) == NULL_TREE)
 	{
 	  GFC_TYPE_ARRAY_LBOUND (type, dim) = create_index_var ("lbound", nest);
-	  TREE_NO_WARNING (GFC_TYPE_ARRAY_LBOUND (type, dim)) = 1;
+	  suppress_warning (GFC_TYPE_ARRAY_LBOUND (type, dim));
 	}
       /* Don't try to use the unknown ubound for the last coarray dimension.  */
       if (GFC_TYPE_ARRAY_UBOUND (type, dim) == NULL_TREE
           && dim < GFC_TYPE_ARRAY_RANK (type) + GFC_TYPE_ARRAY_CORANK (type) - 1)
 	{
 	  GFC_TYPE_ARRAY_UBOUND (type, dim) = create_index_var ("ubound", nest);
-	  TREE_NO_WARNING (GFC_TYPE_ARRAY_UBOUND (type, dim)) = 1;
+	  suppress_warning (GFC_TYPE_ARRAY_UBOUND (type, dim));
 	}
     }
   if (GFC_TYPE_ARRAY_OFFSET (type) == NULL_TREE)
     {
       GFC_TYPE_ARRAY_OFFSET (type) = gfc_create_var_np (gfc_array_index_type,
 							"offset");
-      TREE_NO_WARNING (GFC_TYPE_ARRAY_OFFSET (type)) = 1;
+      suppress_warning (GFC_TYPE_ARRAY_OFFSET (type));
 
       if (nest)
 	gfc_add_decl_to_parent_function (GFC_TYPE_ARRAY_OFFSET (type));
@@ -1089,7 +1089,7 @@ gfc_build_qualified_array (tree decl, gfc_symbol * sym)
       && as->type != AS_ASSUMED_SIZE)
     {
       GFC_TYPE_ARRAY_SIZE (type) = create_index_var ("size", nest);
-      TREE_NO_WARNING (GFC_TYPE_ARRAY_SIZE (type)) = 1;
+      suppress_warning (GFC_TYPE_ARRAY_SIZE (type));
     }
 
   if (POINTER_TYPE_P (type))
@@ -1294,7 +1294,7 @@ gfc_build_dummy_array_decl (gfc_symbol * sym, tree dummy)
 
   /* Avoid uninitialized warnings for optional dummy arguments.  */
   if (sym->attr.optional)
-    TREE_NO_WARNING (decl) = 1;
+    suppress_warning (decl);
 
   /* We should never get deferred shape arrays here.  We used to because of
      frontend bugs.  */
@@ -5981,7 +5981,7 @@ generate_local_decl (gfc_symbol * sym)
 			     "does not have a default initializer",
 			     sym->name, &sym->declared_at);
 	      if (sym->backend_decl != NULL_TREE)
-		TREE_NO_WARNING(sym->backend_decl) = 1;
+		suppress_warning (sym->backend_decl);
 	    }
 	  else if (warn_unused_dummy_argument)
 	    {
@@ -5991,7 +5991,7 @@ generate_local_decl (gfc_symbol * sym)
 			     &sym->declared_at);
 
 	      if (sym->backend_decl != NULL_TREE)
-		TREE_NO_WARNING(sym->backend_decl) = 1;
+		suppress_warning (sym->backend_decl);
 	    }
 	}
 
@@ -6007,7 +6007,7 @@ generate_local_decl (gfc_symbol * sym)
 			   "explicitly imported at %L", sym->name,
 			   &sym->declared_at);
 	      if (sym->backend_decl != NULL_TREE)
-		TREE_NO_WARNING(sym->backend_decl) = 1;
+		suppress_warning (sym->backend_decl);
 	    }
 	  else if (!sym->attr.use_assoc)
 	    {
@@ -6025,7 +6025,7 @@ generate_local_decl (gfc_symbol * sym)
 			     "Unused variable %qs declared at %L",
 			     sym->name, &sym->declared_at);
 	      if (sym->backend_decl != NULL_TREE)
-		TREE_NO_WARNING(sym->backend_decl) = 1;
+		suppress_warning (sym->backend_decl);
 	    }
 	}
 
@@ -6140,7 +6140,7 @@ generate_local_decl (gfc_symbol * sym)
 	  /* Silence bogus "unused parameter" warnings from the
 	     middle end.  */
 	  if (sym->backend_decl != NULL_TREE)
-		TREE_NO_WARNING (sym->backend_decl) = 1;
+		suppress_warning (sym->backend_decl);
 	}
     }
 
@@ -6971,7 +6971,7 @@ gfc_generate_function_code (gfc_namespace * ns)
 			 "Return value of function %qs at %L not set",
 			 sym->name, &sym->declared_at);
 	  if (warn_return_type > 0)
-	    TREE_NO_WARNING(sym->backend_decl) = 1;
+	    suppress_warning (sym->backend_decl);
 	}
       if (result != NULL_TREE)
 	gfc_add_expr_to_block (&body, gfc_generate_return ());
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 1e22cdb82b7..39260027473 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -763,7 +763,7 @@ gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
 					 else_b));
       /* Avoid -W*uninitialized warnings.  */
       if (DECL_P (decl))
-	TREE_NO_WARNING (decl) = 1;
+	suppress_warning (decl, OPT_Wuninitialized);
     }
   else
     gfc_add_expr_to_block (&block, then_b);
@@ -948,7 +948,7 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
 				     void_type_node, cond, then_b, else_b));
   /* Avoid -W*uninitialized warnings.  */
   if (DECL_P (dest))
-    TREE_NO_WARNING (dest) = 1;
+    suppress_warning (dest, OPT_Wuninitialized);
 
   return gfc_finish_block (&block);
 }
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 9f21b3ee780..4e26aea7fe7 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -150,23 +150,23 @@ tree get_dtype_type_node (void)
       field = gfc_add_field_to_struct_1 (dtype_node,
 					 get_identifier ("elem_len"),
 					 size_type_node, &dtype_chain);
-      TREE_NO_WARNING (field) = 1;
+      suppress_warning (field);
       field = gfc_add_field_to_struct_1 (dtype_node,
 					 get_identifier ("version"),
 					 integer_type_node, &dtype_chain);
-      TREE_NO_WARNING (field) = 1;
+      suppress_warning (field);
       field = gfc_add_field_to_struct_1 (dtype_node,
 					 get_identifier ("rank"),
 					 signed_char_type_node, &dtype_chain);
-      TREE_NO_WARNING (field) = 1;
+      suppress_warning (field);
       field = gfc_add_field_to_struct_1 (dtype_node,
 					 get_identifier ("type"),
 					 signed_char_type_node, &dtype_chain);
-      TREE_NO_WARNING (field) = 1;
+      suppress_warning (field);
       field = gfc_add_field_to_struct_1 (dtype_node,
 					 get_identifier ("attribute"),
 					 short_integer_type_node, &dtype_chain);
-      TREE_NO_WARNING (field) = 1;
+      suppress_warning (field);
       gfc_finish_type (dtype_node);
       TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (dtype_node)) = 1;
       dtype_type_node = dtype_node;
@@ -1453,17 +1453,17 @@ gfc_get_desc_dim_type (void)
   decl = gfc_add_field_to_struct_1 (type,
 				    get_identifier ("stride"),
 				    gfc_array_index_type, &chain);
-  TREE_NO_WARNING (decl) = 1;
+  suppress_warning (decl);
 
   decl = gfc_add_field_to_struct_1 (type,
 				    get_identifier ("lbound"),
 				    gfc_array_index_type, &chain);
-  TREE_NO_WARNING (decl) = 1;
+  suppress_warning (decl);
 
   decl = gfc_add_field_to_struct_1 (type,
 				    get_identifier ("ubound"),
 				    gfc_array_index_type, &chain);
-  TREE_NO_WARNING (decl) = 1;
+  suppress_warning (decl);
 
   /* Finish off the type.  */
   gfc_finish_type (type);
@@ -1831,19 +1831,19 @@ gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted)
   decl = gfc_add_field_to_struct_1 (fat_type,
 				    get_identifier ("offset"),
 				    gfc_array_index_type, &chain);
-  TREE_NO_WARNING (decl) = 1;
+  suppress_warning (decl);
 
   /* Add the dtype component.  */
   decl = gfc_add_field_to_struct_1 (fat_type,
 				    get_identifier ("dtype"),
 				    get_dtype_type_node (), &chain);
-  TREE_NO_WARNING (decl) = 1;
+  suppress_warning (decl);
 
   /* Add the span component.  */
   decl = gfc_add_field_to_struct_1 (fat_type,
 				    get_identifier ("span"),
 				    gfc_array_index_type, &chain);
-  TREE_NO_WARNING (decl) = 1;
+  suppress_warning (decl);
 
   /* Build the array type for the stride and bound components.  */
   if (dimen + codimen > 0)
@@ -1856,7 +1856,7 @@ gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted)
 
       decl = gfc_add_field_to_struct_1 (fat_type, get_identifier ("dim"),
 					arraytype, &chain);
-      TREE_NO_WARNING (decl) = 1;
+      suppress_warning (decl);
     }
 
   if (flag_coarray == GFC_FCOARRAY_LIB)
@@ -1864,7 +1864,7 @@ gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted)
       decl = gfc_add_field_to_struct_1 (fat_type,
 					get_identifier ("token"),
 					prvoid_type_node, &chain);
-      TREE_NO_WARNING (decl) = 1;
+      suppress_warning (decl);
     }
 
   /* Finish off the type.  */
@@ -2856,7 +2856,7 @@ copy_derived_types:
 	  token = gfc_find_component (derived, caf_name, true, true, NULL);
 	  gcc_assert (token);
 	  c->caf_token = token->backend_decl;
-	  TREE_NO_WARNING (c->caf_token) = 1;
+	  suppress_warning (c->caf_token);
 	}
     }
 
@@ -3521,11 +3521,11 @@ gfc_get_caf_vector_type (int dim)
       tmp = gfc_add_field_to_struct_1 (vect_struct_type,
 				       get_identifier ("vector"),
 				       pvoid_type_node, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      suppress_warning (tmp);
       tmp = gfc_add_field_to_struct_1 (vect_struct_type,
 				       get_identifier ("kind"),
 				       integer_type_node, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      suppress_warning (tmp);
       gfc_finish_type (vect_struct_type);
 
       chain = 0;
@@ -3533,34 +3533,34 @@ gfc_get_caf_vector_type (int dim)
       tmp = gfc_add_field_to_struct_1 (triplet_struct_type,
 				       get_identifier ("lower_bound"),
 				       gfc_array_index_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      suppress_warning (tmp);
       tmp = gfc_add_field_to_struct_1 (triplet_struct_type,
 				       get_identifier ("upper_bound"),
 				       gfc_array_index_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      suppress_warning (tmp);
       tmp = gfc_add_field_to_struct_1 (triplet_struct_type, get_identifier ("stride"),
 				       gfc_array_index_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      suppress_warning (tmp);
       gfc_finish_type (triplet_struct_type);
 
       chain = 0;
       union_type = make_node (UNION_TYPE);
       tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("v"),
                                        vect_struct_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      suppress_warning (tmp);
       tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("triplet"),
 				       triplet_struct_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      suppress_warning (tmp);
       gfc_finish_type (union_type);
 
       chain = 0;
       vec_type = make_node (RECORD_TYPE);
       tmp = gfc_add_field_to_struct_1 (vec_type, get_identifier ("nvec"),
 				       size_type_node, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      suppress_warning (tmp);
       tmp = gfc_add_field_to_struct_1 (vec_type, get_identifier ("u"),
 				       union_type, &chain);
-      TREE_NO_WARNING (tmp) = 1;
+      suppress_warning (tmp);
       gfc_finish_type (vec_type);
       TYPE_NAME (vec_type) = get_identifier ("caf_vector_t");
     }
@@ -3587,11 +3587,11 @@ gfc_get_caf_reference_type ()
   tmp = gfc_add_field_to_struct_1 (c_struct_type,
 				   get_identifier ("offset"),
 				   gfc_array_index_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (c_struct_type,
 				   get_identifier ("caf_token_offset"),
 				   gfc_array_index_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   gfc_finish_type (c_struct_type);
 
   chain = 0;
@@ -3599,15 +3599,15 @@ gfc_get_caf_reference_type ()
   tmp = gfc_add_field_to_struct_1 (s_struct_type,
 				   get_identifier ("start"),
 				   gfc_array_index_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (s_struct_type,
 				   get_identifier ("end"),
 				   gfc_array_index_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (s_struct_type,
 				   get_identifier ("stride"),
 				   gfc_array_index_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   gfc_finish_type (s_struct_type);
 
   chain = 0;
@@ -3615,25 +3615,25 @@ gfc_get_caf_reference_type ()
   tmp = gfc_add_field_to_struct_1 (v_struct_type,
 				   get_identifier ("vector"),
 				   pvoid_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (v_struct_type,
 				   get_identifier ("nvec"),
 				   size_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (v_struct_type,
 				   get_identifier ("kind"),
 				   integer_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   gfc_finish_type (v_struct_type);
 
   chain = 0;
   union_type = make_node (UNION_TYPE);
   tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("s"),
 				   s_struct_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("v"),
 				   v_struct_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   gfc_finish_type (union_type);
 
   tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
@@ -3648,40 +3648,40 @@ gfc_get_caf_reference_type ()
 						    gfc_index_zero_node,
 					 gfc_rank_cst[GFC_MAX_DIMENSIONS - 1])),
 		&chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (a_struct_type,
 				   get_identifier ("static_array_type"),
 				   integer_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (a_struct_type, get_identifier ("dim"),
 				   dim_union_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   gfc_finish_type (a_struct_type);
 
   chain = 0;
   u_union_type = make_node (UNION_TYPE);
   tmp = gfc_add_field_to_struct_1 (u_union_type, get_identifier ("c"),
 				   c_struct_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (u_union_type, get_identifier ("a"),
 				   a_struct_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   gfc_finish_type (u_union_type);
 
   chain = 0;
   reference_type = make_node (RECORD_TYPE);
   tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("next"),
 				   build_pointer_type (reference_type), &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("type"),
 				   integer_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("item_size"),
 				   size_type_node, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("u"),
 				   u_union_type, &chain);
-  TREE_NO_WARNING (tmp) = 1;
+  suppress_warning (tmp);
   gfc_finish_type (reference_type);
   TYPE_NAME (reference_type) = get_identifier ("caf_reference_t");
 
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 3ffa394d406..6db02bcdf24 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -129,7 +129,7 @@ gfc_create_var_np (tree type, const char *prefix)
 
   /* No warnings for anonymous variables.  */
   if (prefix == NULL)
-    TREE_NO_WARNING (t) = 1;
+    suppress_warning (t);
 
   return t;
 }

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 8/13] v2 Use new per-location warning APIs in libcc1
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (6 preceding siblings ...)
  2021-06-04 21:42     ` [PATCH 7/13] v2 Use new per-location warning APIs in the FORTRAN " Martin Sebor
@ 2021-06-04 21:42     ` Martin Sebor
  2021-06-24  5:04       ` Jeff Law
  2021-06-04 21:43     ` [PATCH 9/13] v2 Use new per-location warning APIs in LTO Martin Sebor
                       ` (6 subsequent siblings)
  14 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:42 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 103 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in libcc1 with
the new suppress_warning() API.

[-- Attachment #2: gcc-no-warning-libcc1.diff --]
[-- Type: text/x-patch, Size: 623 bytes --]

Add support for per-location warning groups.

libcc1/ChangeLog:

	* libcp1plugin.cc (record_decl_address): Replace a direct use
	of TREE_NO_WARNING with suppress_warning.

diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc
index 79694b91964..ea6ee553401 100644
--- a/libcc1/libcp1plugin.cc
+++ b/libcc1/libcp1plugin.cc
@@ -541,7 +541,7 @@ record_decl_address (plugin_context *ctx, decl_addr_value value)
   **slot = value;
   /* We don't want GCC to warn about e.g. static functions
      without a code definition.  */
-  TREE_NO_WARNING (value.decl) = 1;
+  suppress_warning (value.decl);
   return *slot;
 }
 

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 9/13] v2 Use new per-location warning APIs in LTO
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (7 preceding siblings ...)
  2021-06-04 21:42     ` [PATCH 8/13] v2 Use new per-location warning APIs in libcc1 Martin Sebor
@ 2021-06-04 21:43     ` Martin Sebor
  2021-06-21 21:54       ` [PING][PATCH " Martin Sebor
  2021-06-24  5:03       ` [PATCH " Jeff Law
  2021-06-04 21:43     ` [PATCH 10/13] v2 Use new per-location warning APIs in the middle end Martin Sebor
                       ` (5 subsequent siblings)
  14 siblings, 2 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:43 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 186 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in the LTO
front end with the new suppress_warning() API.  It adds a couple of
FIXMEs that I plan to take care of in a follow up.

[-- Attachment #2: gcc-no-warning-lto.diff --]
[-- Type: text/x-patch, Size: 3321 bytes --]

Add support for per-location warning groups.

gcc/lto/ChangeLog:

	* gimple-streamer-out.c (output_gimple_stmt): Same.
	* lto-common.c (compare_tree_sccs_1): Expand use of TREE_NO_WARNING.
	* lto-streamer-out.c (hash_tree): Same.
	* tree-streamer-in.c (unpack_ts_base_value_fields): Same.
	* tree-streamer-out.c (pack_ts_base_value_fields): Same.

diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c
index fcbf92300d4..7f7e06a79b8 100644
--- a/gcc/gimple-streamer-out.c
+++ b/gcc/gimple-streamer-out.c
@@ -73,7 +73,7 @@ output_gimple_stmt (struct output_block *ob, struct function *fn, gimple *stmt)
   /* Emit the tuple header.  */
   bp = bitpack_create (ob->main_stream);
   bp_pack_var_len_unsigned (&bp, gimple_num_ops (stmt));
-  bp_pack_value (&bp, gimple_no_warning_p (stmt), 1);
+  bp_pack_value (&bp, warning_suppressed_p (stmt), 1);
   if (is_gimple_assign (stmt))
     bp_pack_value (&bp,
 		   gimple_assign_nontemporal_move_p (
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index a26d4885800..f1809e60c1e 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -1207,7 +1207,7 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
   if (TYPE_P (t))
     hstate.add_flag (TYPE_ARTIFICIAL (t));
   else
-    hstate.add_flag (TREE_NO_WARNING (t));
+    hstate.add_flag (warning_suppressed_p (t));
   hstate.add_flag (TREE_NOTHROW (t));
   hstate.add_flag (TREE_STATIC (t));
   hstate.add_flag (TREE_PROTECTED (t));
diff --git a/gcc/lto/lto-common.c b/gcc/lto/lto-common.c
index bfe52a2e942..9e7ea877e66 100644
--- a/gcc/lto/lto-common.c
+++ b/gcc/lto/lto-common.c
@@ -1110,8 +1110,8 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map)
     compare_values (TYPE_UNSIGNED);
   if (TYPE_P (t1))
     compare_values (TYPE_ARTIFICIAL);
-  else
-    compare_values (TREE_NO_WARNING);
+  else if (t1->base.nowarning_flag != t2->base.nowarning_flag)
+    return false;
   compare_values (TREE_NOTHROW);
   compare_values (TREE_STATIC);
   if (code != TREE_BINFO)
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index e0522bf2ac1..31dbf2fb992 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -131,7 +131,8 @@ unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
   if (TYPE_P (expr))
     TYPE_ARTIFICIAL (expr) = (unsigned) bp_unpack_value (bp, 1);
   else
-    TREE_NO_WARNING (expr) = (unsigned) bp_unpack_value (bp, 1);
+    /* FIXME: set all warning bits. */
+    suppress_warning (expr, N_OPTS, (unsigned) bp_unpack_value (bp, 1));
   TREE_NOTHROW (expr) = (unsigned) bp_unpack_value (bp, 1);
   TREE_STATIC (expr) = (unsigned) bp_unpack_value (bp, 1);
   if (TREE_CODE (expr) != TREE_BINFO)
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 855d1cd59b9..b76e0c59c6f 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -104,7 +104,8 @@ pack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
   if (TYPE_P (expr))
     bp_pack_value (bp, TYPE_ARTIFICIAL (expr), 1);
   else
-    bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
+    /* FIXME: pack all warning bits.  */
+    bp_pack_value (bp, warning_suppressed_p (expr), 1);
   bp_pack_value (bp, TREE_NOTHROW (expr), 1);
   bp_pack_value (bp, TREE_STATIC (expr), 1);
   if (TREE_CODE (expr) != TREE_BINFO)

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 10/13] v2 Use new per-location warning APIs in the middle end
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (8 preceding siblings ...)
  2021-06-04 21:43     ` [PATCH 9/13] v2 Use new per-location warning APIs in LTO Martin Sebor
@ 2021-06-04 21:43     ` Martin Sebor
  2021-06-21 21:58       ` [PING][PATCH " Martin Sebor
  2021-06-24  5:15       ` [PATCH " Jeff Law
  2021-06-04 21:43     ` [PATCH 11/13] v2 Use new per-location warning APIs in the Objective-C front end Martin Sebor
                       ` (4 subsequent siblings)
  14 siblings, 2 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:43 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 193 bytes --]

The attached patch introduces declarations of the new
suppress_warning(), warning_suppressed_p(), and copy_warning() APIs,
and replaces the uses of TREE_NO_WARNING in the middle end with them.

[-- Attachment #2: gcc-no-warning-middle-end.diff --]
[-- Type: text/x-patch, Size: 81294 bytes --]

Add support for per-location warning groups.

gcc/ChangeLog:

	* builtins.c (warn_string_no_nul): Replace uses of TREE_NO_WARNING,
	gimple_no_warning_p and gimple_set_no_warning with
	warning_suppressed_p, and suppress_warning.
	(c_strlen): Same.
	(maybe_warn_for_bound): Same.
	(warn_for_access): Same.
	(check_access): Same.
	(expand_builtin_strncmp): Same.
	(fold_builtin_varargs): Same.
	* calls.c (maybe_warn_nonstring_arg): Same.
	(maybe_warn_rdwr_sizes): Same.
	* cfgexpand.c (expand_call_stmt): Same.
	* cgraphunit.c (check_global_declaration): Same.
	* fold-const.c (fold_undefer_overflow_warnings): Same.
	(fold_truth_not_expr): Same.
	(fold_unary_loc): Same.
	(fold_checksum_tree): Same.
	* gengtype.c (open_base_files): Same.
	* gimple-array-bounds.cc (array_bounds_checker::check_array_ref): Same.
	(array_bounds_checker::check_mem_ref): Same.
	(array_bounds_checker::check_addr_expr): Same.
	(array_bounds_checker::check_array_bounds): Same.
	* gimple-expr.c (copy_var_decl): Same.
	* gimple-fold.c (gimple_fold_builtin_strcpy): Same.
	(gimple_fold_builtin_strncat): Same.
	(gimple_fold_builtin_stxcpy_chk): Same.
	(gimple_fold_builtin_stpcpy): Same.
	(gimple_fold_builtin_sprintf): Same.
	(fold_stmt_1): Same.
	* gimple-ssa-isolate-paths.c (diag_returned_locals): Same.
	* gimple-ssa-nonnull-compare.c (do_warn_nonnull_compare): Same.
	* gimple-ssa-sprintf.c (handle_printf_call): Same.
	* gimple-ssa-store-merging.c (imm_store_chain_info::output_merged_store): Same.
	* gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same.
	(maybe_diag_access_bounds): Same.
	(check_call): Same.
	(check_bounds_or_overlap): Same.
	* gimple.c (gimple_build_call_from_tree): Same.
	* gimplify.c (gimplify_return_expr): Same.
	(gimplify_cond_expr): Same.
	(gimplify_modify_expr_complex_part): Same.
	(gimplify_modify_expr): Same.
	(gimple_push_cleanup): Same.
	(gimplify_expr): Same.
	* omp-expand.c (expand_omp_for_generic): Same.
	(expand_omp_taskloop_for_outer): Same.
	* omp-low.c (lower_rec_input_clauses): Same.
	(lower_lastprivate_clauses): Same.
	(lower_send_clauses): Same.
	(lower_omp_target): Same.
	* tree-cfg.c (pass_warn_function_return::execute): Same.
	* tree-complex.c (create_one_component_var): Same.
	* tree-inline.c (remap_gimple_op_r): Same.
	(copy_tree_body_r): Same.
	(declare_return_variable): Same.
	(expand_call_inline): Same.
	* tree-nested.c (lookup_field_for_decl): Same.
	* tree-sra.c (create_access_replacement): Same.
	(generate_subtree_copies): Same.
	* tree-ssa-ccp.c (pass_post_ipa_warn::execute): Same.
	* tree-ssa-forwprop.c (combine_cond_expr_cond): Same.
	* tree-ssa-loop-ch.c (ch_base::copy_headers): Same.
	* tree-ssa-loop-im.c (execute_sm): Same.
	* tree-ssa-phiopt.c (cond_store_replacement): Same.
	* tree-ssa-strlen.c (maybe_warn_overflow): Same.
	(handle_builtin_strcpy): Same.
	(maybe_diag_stxncpy_trunc): Same.
	(handle_builtin_stxncpy_strncat): Same.
	(handle_builtin_strcat): Same.
	* tree-ssa-uninit.c (get_no_uninit_warning): Same.
	(set_no_uninit_warning): Same.
	(uninit_undefined_value_p): Same.
	(warn_uninit): Same.
	(maybe_warn_operand): Same.
	* tree-vrp.c (compare_values_warnv): Same.
	* vr-values.c (vr_values::extract_range_for_var_from_comparison_expr): Same.
	(test_for_singularity): Same.

	* gimple.h (warning_suppressed_p): New function.
	(suppress_warning): Same.
	(copy_no_warning): Same.
	(gimple_set_block): Call gimple_set_location.
	(gimple_set_location): Call copy_warning.
	* tree.h (no_warning, all_warnings): New constants.
	(warning_suppressed_p): New function.
	(suppress_warning): Same.
	(copy_no_warning): Same.

diff --git a/gcc/builtins.c b/gcc/builtins.c
index af1fe49bb48..740fed69873 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -1095,7 +1095,9 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 		    bool exact /* = false */,
 		    const wide_int bndrng[2] /* = NULL */)
 {
-  if ((expr && TREE_NO_WARNING (expr)) || TREE_NO_WARNING (arg))
+  const opt_code opt = OPT_Wstringop_overread;
+  if ((expr && warning_suppressed_p (expr, opt))
+      || warning_suppressed_p (arg, opt))
     return;
 
   loc = expansion_point_location_if_in_system_header (loc);
@@ -1123,14 +1125,14 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
       if (bndrng)
 	{
 	  if (wi::ltu_p (maxsiz, bndrng[0]))
-	    warned = warning_at (loc, OPT_Wstringop_overread,
+	    warned = warning_at (loc, opt,
 				 "%K%qD specified bound %s exceeds "
 				 "maximum object size %E",
 				 expr, func, bndstr, maxobjsize);
 	  else
 	    {
 	      bool maybe = wi::to_wide (size) == bndrng[0];
-	      warned = warning_at (loc, OPT_Wstringop_overread,
+	      warned = warning_at (loc, opt,
 				   exact
 				   ? G_("%K%qD specified bound %s exceeds "
 					"the size %E of unterminated array")
@@ -1145,7 +1147,7 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 	    }
 	}
       else
-	warned = warning_at (loc, OPT_Wstringop_overread,
+	warned = warning_at (loc, opt,
 			     "%K%qD argument missing terminating nul",
 			     expr, func);
     }
@@ -1154,14 +1156,14 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
       if (bndrng)
 	{
 	  if (wi::ltu_p (maxsiz, bndrng[0]))
-	    warned = warning_at (loc, OPT_Wstringop_overread,
+	    warned = warning_at (loc, opt,
 				 "%qs specified bound %s exceeds "
 				 "maximum object size %E",
 				 fname, bndstr, maxobjsize);
 	  else
 	    {
 	      bool maybe = wi::to_wide (size) == bndrng[0];
-	      warned = warning_at (loc, OPT_Wstringop_overread,
+	      warned = warning_at (loc, opt,
 				   exact
 				   ? G_("%qs specified bound %s exceeds "
 					"the size %E of unterminated array")
@@ -1176,7 +1178,7 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
 	    }
 	}
       else
-	warned = warning_at (loc, OPT_Wstringop_overread,
+	warned = warning_at (loc, opt,
 			     "%qs argument missing terminating nul",
 			     fname);
     }
@@ -1185,9 +1187,9 @@ warn_string_no_nul (location_t loc, tree expr, const char *fname,
     {
       inform (DECL_SOURCE_LOCATION (decl),
 	      "referenced argument declared here");
-      TREE_NO_WARNING (arg) = 1;
+      suppress_warning (arg, opt);
       if (expr)
-	TREE_NO_WARNING (expr) = 1;
+	suppress_warning (expr, opt);
     }
 }
 
@@ -1445,14 +1447,14 @@ c_strlen (tree arg, int only_value, c_strlen_data *data, unsigned eltsize)
     {
       /* Suppress multiple warnings for propagated constant strings.  */
       if (only_value != 2
-	  && !TREE_NO_WARNING (arg)
+	  && !warning_suppressed_p (arg, OPT_Warray_bounds)
 	  && warning_at (loc, OPT_Warray_bounds,
 			 "offset %qwi outside bounds of constant string",
 			 eltoff))
 	{
 	  if (decl)
 	    inform (DECL_SOURCE_LOCATION (decl), "%qE declared here", decl);
-	  TREE_NO_WARNING (arg) = 1;
+	  suppress_warning (arg, OPT_Warray_bounds);
 	}
       return NULL_TREE;
     }
@@ -3947,10 +3949,10 @@ determine_block_size (tree len, rtx len_rtx,
    accessing an object with SIZE.  */
 
 static bool
-maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
+maybe_warn_for_bound (opt_code opt, location_t loc, tree exp, tree func,
 		      tree bndrng[2], tree size, const access_data *pad = NULL)
 {
-  if (!bndrng[0] || TREE_NO_WARNING (exp))
+  if (!bndrng[0] || warning_suppressed_p (exp, opt))
     return false;
 
   tree maxobjsize = max_object_size ();
@@ -4042,7 +4044,7 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 		inform (EXPR_LOCATION (pad->src.ref),
 			"source object allocated here");
 	    }
-	  TREE_NO_WARNING (exp) = true;
+	  suppress_warning (exp, opt);
 	}
 
       return warned;
@@ -4089,14 +4091,14 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
     return false;
   else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
     warned = (func
-	      ? warning_at (loc, OPT_Wstringop_overflow_,
+	      ? warning_at (loc, opt,
 			    (maybe
 			     ? G_("%K%qD specified bound %E may exceed "
 				  "destination size %E")
 			     : G_("%K%qD specified bound %E exceeds "
 				  "destination size %E")),
 			    exp, func, bndrng[0], size)
-	      : warning_at (loc, OPT_Wstringop_overflow_,
+	      : warning_at (loc, opt,
 			    (maybe
 			     ? G_("%Kspecified bound %E may exceed "
 				  "destination size %E")
@@ -4105,14 +4107,14 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 			    exp, bndrng[0], size));
   else
     warned = (func
-	      ? warning_at (loc, OPT_Wstringop_overflow_,
+	      ? warning_at (loc, opt,
 			    (maybe
 			     ? G_("%K%qD specified bound [%E, %E] may exceed "
 				  "destination size %E")
 			     : G_("%K%qD specified bound [%E, %E] exceeds "
 				  "destination size %E")),
 			    exp, func, bndrng[0], bndrng[1], size)
-	      : warning_at (loc, OPT_Wstringop_overflow_,
+	      : warning_at (loc, opt,
 			    (maybe
 			     ? G_("%Kspecified bound [%E, %E] exceeds "
 				  "destination size %E")
@@ -4131,7 +4133,7 @@ maybe_warn_for_bound (int opt, location_t loc, tree exp, tree func,
 	    inform (EXPR_LOCATION (pad->dst.ref),
 		    "destination object allocated here");
 	}
-      TREE_NO_WARNING (exp) = true;
+      suppress_warning (exp, opt);
     }
 
   return warned;
@@ -4357,7 +4359,7 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 				exp, range[0], range[1], size));
 
       if (warned)
-	TREE_NO_WARNING (exp) = true;
+	suppress_warning (exp, OPT_Wstringop_overread);
 
       return warned;
     }
@@ -4400,7 +4402,7 @@ warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
 			    exp, range[0], range[1], size));
 
   if (warned)
-    TREE_NO_WARNING (exp) = true;
+    suppress_warning (exp, OPT_Wstringop_overread);
 
   return warned;
 }
@@ -4779,8 +4781,10 @@ check_access (tree exp, tree dstwrite,
 		  && tree_fits_uhwi_p (dstwrite)
 		  && tree_int_cst_lt (dstwrite, range[0]))))
 	{
-	  if (TREE_NO_WARNING (exp)
-	      || (pad && pad->dst.ref && TREE_NO_WARNING (pad->dst.ref)))
+	  const opt_code opt = OPT_Wstringop_overflow_;
+	  if (warning_suppressed_p (exp, opt)
+	      || (pad && pad->dst.ref
+		  && warning_suppressed_p (pad->dst.ref, opt)))
 	    return false;
 
 	  location_t loc = tree_inlined_location (exp);
@@ -4791,12 +4795,12 @@ check_access (tree exp, tree dstwrite,
 		 and a source of unknown length.  The call will write
 		 at least one byte past the end of the destination.  */
 	      warned = (func
-			? warning_at (loc, OPT_Wstringop_overflow_,
+			? warning_at (loc, opt,
 				      "%K%qD writing %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
 				      exp, func, range[0], dstsize)
-			: warning_at (loc, OPT_Wstringop_overflow_,
+			: warning_at (loc, opt,
 				      "%Kwriting %E or more bytes into "
 				      "a region of size %E overflows "
 				      "the destination",
@@ -4817,7 +4821,7 @@ check_access (tree exp, tree dstwrite,
 
 	  if (warned)
 	    {
-	      TREE_NO_WARNING (exp) = true;
+	      suppress_warning (exp, OPT_Wstringop_overflow_);
 	      if (pad)
 		pad->dst.inform_access (pad->mode);
 	    }
@@ -4852,9 +4856,9 @@ check_access (tree exp, tree dstwrite,
 
 	  if (size != maxobjsize && tree_int_cst_lt (size, range[0]))
 	    {
-	      int opt = (dstwrite || mode != access_read_only
-			 ? OPT_Wstringop_overflow_
-			 : OPT_Wstringop_overread);
+	      opt_code opt = (dstwrite || mode != access_read_only
+			      ? OPT_Wstringop_overflow_
+			      : OPT_Wstringop_overread);
 	      maybe_warn_for_bound (opt, loc, exp, func, range, size, pad);
 	      return false;
 	    }
@@ -4890,19 +4894,21 @@ check_access (tree exp, tree dstwrite,
 
   if (overread)
     {
-      if (TREE_NO_WARNING (exp)
-	  || (srcstr && TREE_NO_WARNING (srcstr))
-	  || (pad && pad->src.ref && TREE_NO_WARNING (pad->src.ref)))
+      const opt_code opt = OPT_Wstringop_overread;
+      if (warning_suppressed_p (exp, opt)
+	  || (srcstr && warning_suppressed_p (srcstr, opt))
+	  || (pad && pad->src.ref
+	      && warning_suppressed_p (pad->src.ref, opt)))
 	return false;
 
       location_t loc = tree_inlined_location (exp);
       const bool read
 	= mode == access_read_only || mode == access_read_write;
       const bool maybe = pad && pad->dst.parmarray;
-      if (warn_for_access (loc, func, exp, OPT_Wstringop_overread, range,
-			   slen, false, read, maybe))
+      if (warn_for_access (loc, func, exp, opt, range, slen, false, read,
+			   maybe))
 	{
-	  TREE_NO_WARNING (exp) = true;
+	  suppress_warning (exp, opt);
 	  if (pad)
 	    pad->src.inform_access (access_read_only);
 	}
@@ -7427,8 +7433,7 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target,
   /* Expand the library call ourselves using a stabilized argument
      list to avoid re-evaluating the function's arguments twice.  */
   tree call = build_call_nofold_loc (loc, fndecl, 3, arg1, arg2, len);
-  if (TREE_NO_WARNING (exp))
-    TREE_NO_WARNING (call) = true;
+  copy_warning (call, exp);
   gcc_assert (TREE_CODE (call) == CALL_EXPR);
   CALL_EXPR_TAILCALL (call) = CALL_EXPR_TAILCALL (exp);
   return expand_call (call, target, target == const0_rtx);
@@ -13853,10 +13858,11 @@ maybe_emit_free_warning (tree exp)
 	      else
 		{
 		  tree alloc_decl = gimple_call_fndecl (def_stmt);
-		  int opt = (DECL_IS_OPERATOR_NEW_P (alloc_decl)
-			     || DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
-			     ? OPT_Wmismatched_new_delete
-			     : OPT_Wmismatched_dealloc);
+		  const opt_code opt =
+		    (DECL_IS_OPERATOR_NEW_P (alloc_decl)
+		     || DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
+		     ? OPT_Wmismatched_new_delete
+		     : OPT_Wmismatched_dealloc);
 		  warned = warning_at (loc, opt,
 				       "%K%qD called on pointer returned "
 				       "from a mismatched allocation "
@@ -13967,7 +13973,7 @@ fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs)
     {
       ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
       SET_EXPR_LOCATION (ret, loc);
-      TREE_NO_WARNING (ret) = 1;
+      suppress_warning (ret);
       return ret;
     }
   return NULL_TREE;
diff --git a/gcc/calls.c b/gcc/calls.c
index a7c78ed9c16..bc6bc03d5d4 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1623,7 +1623,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
   if (!fndecl || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
     return false;
 
-  if (TREE_NO_WARNING (exp) || !warn_stringop_overread)
+  if (!warn_stringop_overread || warning_suppressed_p (exp, OPT_Wstringop_overread))
     return false;
 
   /* Avoid clearly invalid calls (more checking done below).  */
@@ -1739,7 +1739,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
 				 exp, fndecl, bndrng[0], bndrng[1],
 				 maxobjsize);
 	  if (warned)
-	    TREE_NO_WARNING (exp) = true;
+	    suppress_warning (exp, OPT_Wstringop_overread);
 
 	  return warned;
 	}
@@ -1916,7 +1916,7 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
     }
 
   if (any_arg_warned)
-    TREE_NO_WARNING (exp) = true;
+    suppress_warning (exp, OPT_Wstringop_overread);
 
   return any_arg_warned;
 }
@@ -1979,7 +1979,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 
   /* Set if a warning has been issued for any argument (used to decide
      whether to emit an informational note at the end).  */
-  bool any_warned = false;
+  opt_code opt_warned = N_OPTS;
 
   /* A string describing the attributes that the warnings issued by this
      function apply to.  Used to print one informational note per function
@@ -2054,7 +2054,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 	*sizstr = '\0';
 
       /* Set if a warning has been issued for the current argument.  */
-      bool arg_warned = false;
+      opt_code arg_warned = N_OPTS;
       location_t loc = EXPR_LOCATION (exp);
       tree ptr = access.second.ptr;
       if (*sizstr
@@ -2067,24 +2067,25 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 	      const std::string argtypestr
 		= access.second.array_as_string (ptrtype);
 
-	      arg_warned = warning_at (loc, OPT_Wstringop_overflow_,
-				       "%Kbound argument %i value %s is "
-				       "negative for a variable length array "
-				       "argument %i of type %s",
-				       exp, sizidx + 1, sizstr,
-				       ptridx + 1, argtypestr.c_str ());
+	      if (warning_at (loc, OPT_Wstringop_overflow_,
+			      "%Kbound argument %i value %s is "
+			      "negative for a variable length array "
+			      "argument %i of type %s",
+			      exp, sizidx + 1, sizstr,
+			      ptridx + 1, argtypestr.c_str ()))
+		arg_warned = OPT_Wstringop_overflow_;
 	    }
-	  else
-	    arg_warned = warning_at (loc, OPT_Wstringop_overflow_,
-				     "%Kargument %i value %s is negative",
-				     exp, sizidx + 1, sizstr);
+	  else if (warning_at (loc, OPT_Wstringop_overflow_,
+			       "%Kargument %i value %s is negative",
+			       exp, sizidx + 1, sizstr))
+	    arg_warned = OPT_Wstringop_overflow_;
 
-	  if (arg_warned)
+	  if (arg_warned != N_OPTS)
 	    {
 	      append_attrname (access, attrstr, sizeof attrstr);
 	      /* Remember a warning has been issued and avoid warning
 		 again below for the same attribute.  */
-	      any_warned = true;
+	      opt_warned = arg_warned;
 	      continue;
 	    }
 	}
@@ -2122,31 +2123,33 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		  const std::string argtypestr
 		    = access.second.array_as_string (ptrtype);
 
-		  arg_warned = warning_at (loc, OPT_Wnonnull,
-					   "%Kargument %i of variable length "
-					   "array %s is null but "
-					   "the corresponding bound argument "
-					   "%i value is %s",
-					   exp, sizidx + 1, argtypestr.c_str (),
-					   ptridx + 1, sizstr);
+		  if (warning_at (loc, OPT_Wnonnull,
+				  "%Kargument %i of variable length "
+				  "array %s is null but "
+				  "the corresponding bound argument "
+				  "%i value is %s",
+				  exp, sizidx + 1, argtypestr.c_str (),
+				  ptridx + 1, sizstr))
+		    arg_warned = OPT_Wnonnull;
 		}
-	      else
-		arg_warned = warning_at (loc, OPT_Wnonnull,
-					 "%Kargument %i is null but "
-					 "the corresponding size argument "
-					 "%i value is %s",
-					 exp, ptridx + 1, sizidx + 1,
-					 sizstr);
+	      else if (warning_at (loc, OPT_Wnonnull,
+				   "%Kargument %i is null but "
+				   "the corresponding size argument "
+				   "%i value is %s",
+				   exp, ptridx + 1, sizidx + 1,
+				   sizstr))
+		arg_warned = OPT_Wnonnull;
 	    }
 	  else if (access_size && access.second.static_p)
 	    {
 	      /* Warn about null pointers for [static N] array arguments
 		 but do not warn for ordinary (i.e., nonstatic) arrays.  */
-	      arg_warned = warning_at (loc, OPT_Wnonnull,
-				       "%Kargument %i to %<%T[static %E]%> "
-				       "is null where non-null expected",
-				       exp, ptridx + 1, argtype,
-				       access_size);
+	      if (warning_at (loc, OPT_Wnonnull,
+			      "%Kargument %i to %<%T[static %E]%> "
+			      "is null where non-null expected",
+			      exp, ptridx + 1, argtype,
+			      access_size))
+		arg_warned = OPT_Wnonnull;		
 	    }
 
 	  if (arg_warned)
@@ -2154,7 +2157,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 	      append_attrname (access, attrstr, sizeof attrstr);
 	      /* Remember a warning has been issued and avoid warning
 		 again below for the same attribute.  */
-	      any_warned = true;
+	      opt_warned = OPT_Wnonnull;
 	      continue;
 	    }
 	}
@@ -2190,17 +2193,17 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
       /* Clear the no-warning bit in case it was set by check_access
 	 in a prior iteration so that accesses via different arguments
 	 are diagnosed.  */
-      TREE_NO_WARNING (exp) = false;
+      suppress_warning (exp, OPT_Wstringop_overflow_, false);
       access_mode mode = data.mode;
       if (mode == access_deferred)
 	mode = TYPE_READONLY (argtype) ? access_read_only : access_read_write;
       check_access (exp, access_size, /*maxread=*/ NULL_TREE, srcsize,
 		    dstsize, mode, &data);
 
-      if (TREE_NO_WARNING (exp))
+      if (warning_suppressed_p (exp, OPT_Wstringop_overflow_))
+	opt_warned = OPT_Wstringop_overflow_;
+      if (opt_warned != N_OPTS)
 	{
-	  any_warned = true;
-
 	  if (access.second.internal_p)
 	    inform (loc, "referencing argument %u of type %qT",
 		    ptridx + 1, ptrtype);
@@ -2222,7 +2225,7 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
 		"in a call with type %qT and attribute %qs",
 		fntype, attrstr);
     }
-  else if (any_warned)
+  else if (opt_warned != N_OPTS)
     {
       if (fndecl)
 	inform (DECL_SOURCE_LOCATION (fndecl),
@@ -2233,7 +2236,8 @@ maybe_warn_rdwr_sizes (rdwr_map *rwm, tree fndecl, tree fntype, tree exp)
     }
 
   /* Set the bit in case if was cleared and not set above.  */
-  TREE_NO_WARNING (exp) = true;
+  if (opt_warned != N_OPTS)
+    suppress_warning (exp, opt_warned);
 }
 
 /* Fill in ARGS_SIZE and ARGS array based on the parameters found in
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 39e5b040427..92be5e044e9 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2807,9 +2807,6 @@ expand_call_stmt (gcall *stmt)
   if (gimple_call_nothrow_p (stmt))
     TREE_NOTHROW (exp) = 1;
 
-  if (gimple_no_warning_p (stmt))
-    TREE_NO_WARNING (exp) = 1;
-
   CALL_EXPR_TAILCALL (exp) = gimple_call_tail_p (stmt);
   CALL_EXPR_MUST_TAIL_CALL (exp) = gimple_call_must_tail_p (stmt);
   CALL_EXPR_RETURN_SLOT_OPT (exp) = gimple_call_return_slot_opt_p (stmt);
@@ -2823,6 +2820,9 @@ expand_call_stmt (gcall *stmt)
   CALL_EXPR_BY_DESCRIPTOR (exp) = gimple_call_by_descriptor_p (stmt);
   SET_EXPR_LOCATION (exp, gimple_location (stmt));
 
+  /* Must come after copying location.  */
+  copy_warning (exp, stmt);
+
   /* Ensure RTL is created for debug args.  */
   if (decl && DECL_HAS_DEBUG_ARGS_P (decl))
     {
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 098eb99dc95..55cb0347149 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1074,7 +1074,7 @@ check_global_declaration (symtab_node *snode)
       && ! DECL_ARTIFICIAL (decl)
       && ! TREE_PUBLIC (decl))
     {
-      if (TREE_NO_WARNING (decl))
+      if (warning_suppressed_p (decl, OPT_Wunused))
 	;
       else if (snode->referred_to_p (/*include_self=*/false))
 	pedwarn (input_location, 0, "%q+F used but never defined", decl);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 33d64bfbbe8..8acc2c09b19 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -250,7 +250,7 @@ fold_undefer_overflow_warnings (bool issue, const gimple *stmt, int code)
   if (!issue || warnmsg == NULL)
     return;
 
-  if (gimple_no_warning_p (stmt))
+  if (warning_suppressed_p (stmt, OPT_Wstrict_overflow))
     return;
 
   /* Use the smallest code level when deciding to issue the
@@ -4250,8 +4250,7 @@ fold_truth_not_expr (location_t loc, tree arg)
 
       tree ret = build2_loc (loc, code, type, TREE_OPERAND (arg, 0),
 			     TREE_OPERAND (arg, 1));
-      if (TREE_NO_WARNING (arg))
-	TREE_NO_WARNING (ret) = 1;
+      copy_warning (ret, arg);
       return ret;
     }
 
@@ -9342,7 +9341,7 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
 	  tem = fold_build1_loc (loc, code, type, TREE_OPERAND (op0, 1));
 	  /* First do the assignment, then return converted constant.  */
 	  tem = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (tem), op0, tem);
-	  TREE_NO_WARNING (tem) = 1;
+	  suppress_warning (tem /* What warning? */);
 	  TREE_USED (tem) = 1;
 	  return tem;
 	}
@@ -13515,10 +13514,10 @@ fold_checksum_tree (const_tree expr, struct md5_ctx *ctx,
 	  TYPE_CACHED_VALUES (tmp) = NULL;
 	}
     }
-  else if (TREE_NO_WARNING (expr) && (DECL_P (expr) || EXPR_P (expr)))
+  else if (warning_suppressed_p (expr) && (DECL_P (expr) || EXPR_P (expr)))
     {
-      /* Allow TREE_NO_WARNING to be set.  Perhaps we shouldn't allow that
-	 and change builtins.c etc. instead - see PR89543.  */
+      /* Allow the no-warning bit to be set.  Perhaps we shouldn't allow
+	 that and change builtins.c etc. instead - see PR89543.  */
       size_t sz = tree_size (expr);
       buf = XALLOCAVAR (union tree_node, sz);
       memcpy ((char *) buf, expr, sz);
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index b94e2f126ec..c1fa6d35c87 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1727,7 +1727,7 @@ open_base_files (void)
       "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
       "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h",
       "omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h", "symtab-thunks.h",
-      "symtab-clones.h",
+      "symtab-clones.h", "diagnostic-spec.h",
       NULL
     };
     const char *const *ifp;
diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
index 199d9f5d216..13f08685f8f 100644
--- a/gcc/gimple-array-bounds.cc
+++ b/gcc/gimple-array-bounds.cc
@@ -175,7 +175,7 @@ bool
 array_bounds_checker::check_array_ref (location_t location, tree ref,
 				       bool ignore_off_by_one)
 {
-  if (TREE_NO_WARNING (ref))
+  if (warning_suppressed_p (ref, OPT_Warray_bounds))
     /* Return true to have the caller prevent warnings for enclosing
        refs.  */
     return true;
@@ -346,7 +346,7 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
       /* Avoid more warnings when checking more significant subscripts
 	 of the same expression.  */
       ref = TREE_OPERAND (ref, 0);
-      TREE_NO_WARNING (ref) = 1;
+      suppress_warning (ref, OPT_Warray_bounds);
 
       if (decl)
 	ref = decl;
@@ -411,7 +411,7 @@ bool
 array_bounds_checker::check_mem_ref (location_t location, tree ref,
 				     bool ignore_off_by_one)
 {
-  if (TREE_NO_WARNING (ref))
+  if (warning_suppressed_p (ref, OPT_Warray_bounds))
     return false;
 
   tree arg = TREE_OPERAND (ref, 0);
@@ -770,7 +770,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
 	    }
 	}
 
-      TREE_NO_WARNING (ref) = 1;
+      suppress_warning (ref, OPT_Warray_bounds);
       return true;
     }
 
@@ -787,7 +787,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref,
 		      "intermediate array offset %wi is outside array bounds "
 		      "of %qT", tmpidx, reftype))
 	{
-	  TREE_NO_WARNING (ref) = 1;
+	  suppress_warning (ref, OPT_Warray_bounds);
 	  return true;
 	}
     }
@@ -818,7 +818,7 @@ array_bounds_checker::check_addr_expr (location_t location, tree t)
 	warned = check_mem_ref (location, t, ignore_off_by_one);
 
       if (warned)
-	TREE_NO_WARNING (t) = true;
+	suppress_warning (t, OPT_Warray_bounds);
 
       t = TREE_OPERAND (t, 0);
     }
@@ -826,7 +826,7 @@ array_bounds_checker::check_addr_expr (location_t location, tree t)
 
   if (TREE_CODE (t) != MEM_REF
       || TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR
-      || TREE_NO_WARNING (t))
+      || warning_suppressed_p (t, OPT_Warray_bounds))
     return;
 
   tree tem = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
@@ -886,7 +886,7 @@ array_bounds_checker::check_addr_expr (location_t location, tree t)
       if (DECL_P (t))
 	inform (DECL_SOURCE_LOCATION (t), "while referencing %qD", t);
 
-      TREE_NO_WARNING (t) = 1;
+      suppress_warning (t, OPT_Warray_bounds);
     }
 }
 
@@ -980,9 +980,10 @@ array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree,
        See pr98266 and pr97595.  */
     *walk_subtree = false;
 
-  /* Propagate the no-warning bit to the outer expression.  */
+  /* Propagate the no-warning bit to the outer statement to avoid also
+     issuing -Wstringop-overflow/-overread for the out-of-bounds accesses.  */
   if (warned)
-    TREE_NO_WARNING (t) = true;
+    suppress_warning (wi->stmt, OPT_Warray_bounds);
 
   return NULL_TREE;
 }
diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c
index c3211795d33..a2563a45c37 100644
--- a/gcc/gimple-expr.c
+++ b/gcc/gimple-expr.c
@@ -377,7 +377,6 @@ copy_var_decl (tree var, tree name, tree type)
   DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
   DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
   DECL_CONTEXT (copy) = DECL_CONTEXT (var);
-  TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
   TREE_USED (copy) = 1;
   DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
   DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);
@@ -387,6 +386,7 @@ copy_var_decl (tree var, tree name, tree type)
       DECL_USER_ALIGN (copy) = 1;
     }
 
+  copy_warning (copy, var);
   return copy;
 }
 
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 1c0e930aba5..68031538145 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -2044,7 +2044,7 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi,
 	 not point to objects and so do not indicate an overlap;
 	 such calls could be the result of sanitization and jump
 	 threading).  */
-      if (!integer_zerop (dest) && !gimple_no_warning_p (stmt))
+      if (!integer_zerop (dest) && !warning_suppressed_p (stmt, OPT_Wrestrict))
 	{
 	  tree func = gimple_call_fndecl (stmt);
 
@@ -2071,9 +2071,9 @@ gimple_fold_builtin_strcpy (gimple_stmt_iterator *gsi,
   if (nonstr)
     {
       /* Avoid folding calls with unterminated arrays.  */
-      if (!gimple_no_warning_p (stmt))
+      if (!warning_suppressed_p (stmt, OPT_Wstringop_overread))
 	warn_string_no_nul (loc, NULL_TREE, "strcpy", src, nonstr);
-      gimple_set_no_warning (stmt, true);
+      suppress_warning (stmt, OPT_Wstringop_overread);
       return false;
     }
 
@@ -2481,7 +2481,7 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 
   unsigned HOST_WIDE_INT dstsize;
 
-  bool nowarn = gimple_no_warning_p (stmt);
+  bool nowarn = warning_suppressed_p (stmt, OPT_Wstringop_overflow_);
 
   if (!nowarn && compute_builtin_object_size (dst, 1, &dstsize))
     {
@@ -2504,7 +2504,7 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
 				    "destination size %wu"),
 			       stmt, fndecl, len, dstsize);
 	  if (nowarn)
-	    gimple_set_no_warning (stmt, true);
+	    suppress_warning (stmt, OPT_Wstringop_overflow_);
 	}
     }
 
@@ -2520,7 +2520,7 @@ gimple_fold_builtin_strncat (gimple_stmt_iterator *gsi)
       if (warning_at (loc, OPT_Wstringop_overflow_,
 		      "%G%qD specified bound %E equals source length",
 		      stmt, fndecl, len))
-	gimple_set_no_warning (stmt, true);
+	suppress_warning (stmt, OPT_Wstringop_overflow_);
     }
 
   tree fn = builtin_decl_implicit (BUILT_IN_STRCAT);
@@ -3105,7 +3105,8 @@ gimple_fold_builtin_stxcpy_chk (gimple_stmt_iterator *gsi,
 	 not point to objects and so do not indicate an overlap;
 	 such calls could be the result of sanitization and jump
 	 threading).  */
-      if (!integer_zerop (dest) && !gimple_no_warning_p (stmt))
+      if (!integer_zerop (dest)
+	  && !warning_suppressed_p (stmt, OPT_Wrestrict))
 	{
 	  tree func = gimple_call_fndecl (stmt);
 
@@ -3288,10 +3289,10 @@ gimple_fold_builtin_stpcpy (gimple_stmt_iterator *gsi)
   if (data.decl)
     {
       /* Avoid folding calls with unterminated arrays.  */
-      if (!gimple_no_warning_p (stmt))
+      if (!warning_suppressed_p (stmt, OPT_Wstringop_overread))
 	warn_string_no_nul (loc, NULL_TREE, "stpcpy", src, data.decl, size,
 			    exact);
-      gimple_set_no_warning (stmt, true);
+      suppress_warning (stmt, OPT_Wstringop_overread);
       return false;
     }
 
@@ -3554,8 +3555,7 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator *gsi)
 
       /* Propagate the NO_WARNING bit to avoid issuing the same
 	 warning more than once.  */
-      if (gimple_no_warning_p (stmt))
-	gimple_set_no_warning (repl, true);
+      copy_warning (repl, stmt);
 
       gimple_seq_add_stmt_without_update (&stmts, repl);
       if (tree lhs = gimple_call_lhs (stmt))
@@ -3606,8 +3606,7 @@ gimple_fold_builtin_sprintf (gimple_stmt_iterator *gsi)
 
       /* Propagate the NO_WARNING bit to avoid issuing the same
 	 warning more than once.  */
-      if (gimple_no_warning_p (stmt))
-	gimple_set_no_warning (repl, true);
+      copy_warning (repl, stmt);
 
       gimple_seq_add_stmt_without_update (&stmts, repl);
       if (tree lhs = gimple_call_lhs (stmt))
@@ -6065,7 +6064,7 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree))
 {
   bool changed = false;
   gimple *stmt = gsi_stmt (*gsi);
-  bool nowarning = gimple_no_warning_p (stmt);
+  bool nowarning = warning_suppressed_p (stmt, OPT_Wstrict_overflow);
   unsigned i;
   fold_defer_overflow_warnings ();
 
diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c
index eb23cd41f4b..2dafe849ad3 100644
--- a/gcc/gimple-ssa-isolate-paths.c
+++ b/gcc/gimple-ssa-isolate-paths.c
@@ -400,6 +400,11 @@ diag_returned_locals (bool maybe, const locmap_t &locmap)
       gimple *stmt = (*it).first;
       const args_loc_t &argsloc = (*it).second;
       location_t stmtloc = gimple_location (stmt);
+      if (stmtloc == UNKNOWN_LOCATION)
+	/* When multiple return statements are merged into one it
+	   may not have an associated location.  Use the location
+	   of the closing brace instead.  */
+	stmtloc = cfun->function_end_locus;
 
       auto_diagnostic_group d;
       unsigned nargs = argsloc.locvec.length ();
diff --git a/gcc/gimple-ssa-nonnull-compare.c b/gcc/gimple-ssa-nonnull-compare.c
index 9d7894633dc..f2757b66b28 100644
--- a/gcc/gimple-ssa-nonnull-compare.c
+++ b/gcc/gimple-ssa-nonnull-compare.c
@@ -97,7 +97,7 @@ do_warn_nonnull_compare (function *fun, tree arg)
       if (op
 	  && (POINTER_TYPE_P (TREE_TYPE (arg))
 	      ? integer_zerop (op) : integer_minus_onep (op))
-	  && !gimple_no_warning_p (stmt))
+	  && !warning_suppressed_p (stmt, OPT_Wnonnull_compare))
 	warning_at (loc, OPT_Wnonnull_compare,
 		    "%<nonnull%> argument %qD compared to NULL", arg);
     }
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index fc744669e4b..41e3be6f9f4 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -330,7 +330,8 @@ get_format_string (tree format, location_t *ploc)
 static bool
 ATTRIBUTE_GCC_DIAG (5, 6)
 fmtwarn (const substring_loc &fmt_loc, location_t param_loc,
-	 const char *corrected_substring, int opt, const char *gmsgid, ...)
+	 const char *corrected_substring, opt_code opt,
+	 const char *gmsgid, ...)
 {
   format_string_diagnostic_t diag (fmt_loc, NULL, param_loc, NULL,
 				   corrected_substring);
@@ -345,7 +346,8 @@ fmtwarn (const substring_loc &fmt_loc, location_t param_loc,
 static bool
 ATTRIBUTE_GCC_DIAG (6, 8) ATTRIBUTE_GCC_DIAG (7, 8)
 fmtwarn_n (const substring_loc &fmt_loc, location_t param_loc,
-	   const char *corrected_substring, int opt, unsigned HOST_WIDE_INT n,
+	   const char *corrected_substring, opt_code opt,
+	   unsigned HOST_WIDE_INT n,
 	   const char *singular_gmsgid, const char *plural_gmsgid, ...)
 {
   format_string_diagnostic_t diag (fmt_loc, NULL, param_loc, NULL,
@@ -921,7 +923,7 @@ struct call_info
   }
 
   /* Return the warning option corresponding to the called function.  */
-  int warnopt () const
+  opt_code warnopt () const
   {
     return bounded ? OPT_Wformat_truncation_ : OPT_Wformat_overflow_;
   }
@@ -4680,7 +4682,7 @@ handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
 
   bool success = compute_format_length (info, &res, ptr_qry.rvals);
   if (res.warned)
-    gimple_set_no_warning (info.callstmt, true);
+    suppress_warning (info.callstmt, info.warnopt ());
 
   /* When optimizing and the printf return value optimization is enabled,
      attempt to substitute the computed result for the return value of
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 123c92d9b44..a9694ddd598 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -4348,10 +4348,12 @@ imm_store_chain_info::output_merged_store (merged_store_group *group)
 		      MR_DEPENDENCE_BASE (ops[j]) = base;
 		    }
 		  if (!integer_zerop (mask))
-		    /* The load might load some bits (that will be masked off
-		       later on) uninitialized, avoid -W*uninitialized
-		       warnings in that case.  */
-		    TREE_NO_WARNING (ops[j]) = 1;
+		    {
+		      /* The load might load some bits (that will be masked
+			 off later on) uninitialized, avoid -W*uninitialized
+			 warnings in that case.  */
+		      suppress_warning (ops[j], OPT_Wuninitialized);
+		    }
 
 		  stmt = gimple_build_assign (make_ssa_name (dest_type), ops[j]);
 		  gimple_set_location (stmt, load_loc);
@@ -4533,7 +4535,7 @@ imm_store_chain_info::output_merged_store (merged_store_group *group)
 		 provably uninitialized (no stores at all yet or previous
 		 store a CLOBBER) we'd optimize away the load and replace
 		 it e.g. with 0.  */
-	      TREE_NO_WARNING (load_src) = 1;
+	      suppress_warning (load_src, OPT_Wuninitialized);
 	      stmt = gimple_build_assign (tem, load_src);
 	      gimple_set_location (stmt, loc);
 	      gimple_set_vuse (stmt, new_vuse);
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index c8c9f9581a8..02771e4cd60 100644
--- a/gcc/gimple-ssa-warn-restrict.c
+++ b/gcc/gimple-ssa-warn-restrict.c
@@ -1431,7 +1431,7 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
   if (!acs.overlap ())
     return false;
 
-  if (gimple_no_warning_p (call))
+  if (warning_suppressed_p (call, OPT_Wrestrict))
     return true;
 
   /* For convenience.  */
@@ -1680,10 +1680,11 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
    be issued, false otherwise.
    Both initial values of the offsets and their final value computed
    by the function by incrementing the initial value by the size are
-   validated.  Return true if the offsets are not valid and a diagnostic
-   has been issued, or would have been issued if DO_WARN had been true.  */
+   validated.  Return the warning number if the offsets are not valid
+   and a diagnostic has been issued, or would have been issued if
+   DO_WARN had been true, otherwise an invalid warning number.  */
 
-static bool
+static opt_code
 maybe_diag_access_bounds (gimple *call, tree func, int strict,
 			  const builtin_memref &ref, offset_int wroff,
 			  bool do_warn)
@@ -1695,28 +1696,31 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
      since the result is used to make codegen decisions.  */
   if (ref.sizrange[0] > maxobjsize)
     {
+      const opt_code opt = OPT_Wstringop_overflow_;
       /* Return true without issuing a warning.  */
       if (!do_warn)
-	return true;
+	return opt;
 
-      if (ref.ref && TREE_NO_WARNING (ref.ref))
-	return false;
+      if (ref.ref && warning_suppressed_p (ref.ref, OPT_Wstringop_overflow_))
+	return no_warning;
 
+      bool warned = false;
       if (warn_stringop_overflow)
 	{
 	  if (ref.sizrange[0] == ref.sizrange[1])
-	    return warning_at (loc, OPT_Wstringop_overflow_,
-			       "%G%qD specified bound %wu "
-			       "exceeds maximum object size %wu",
-			       call, func, ref.sizrange[0].to_uhwi (),
-			       maxobjsize.to_uhwi ());
-
-	  return warning_at (loc, OPT_Wstringop_overflow_,
-			     "%G%qD specified bound between %wu and %wu "
-			     "exceeds maximum object size %wu",
-			     call, func, ref.sizrange[0].to_uhwi (),
-			     ref.sizrange[1].to_uhwi (),
-			     maxobjsize.to_uhwi ());
+	    warned = warning_at (loc, opt,
+				 "%G%qD specified bound %wu "
+				 "exceeds maximum object size %wu",
+				 call, func, ref.sizrange[0].to_uhwi (),
+				 maxobjsize.to_uhwi ());
+	  else
+	    warned = warning_at (loc, opt,
+				 "%G%qD specified bound between %wu and %wu "
+				 "exceeds maximum object size %wu",
+				 call, func, ref.sizrange[0].to_uhwi (),
+				 ref.sizrange[1].to_uhwi (),
+				 maxobjsize.to_uhwi ());
+	  return warned ? opt : no_warning;
 	}
     }
 
@@ -1729,18 +1733,19 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
   offset_int ooboff[] = { ref.offrange[0], ref.offrange[1], wroff };
   tree oobref = ref.offset_out_of_bounds (strict, ooboff);
   if (!oobref)
-    return false;
+    return no_warning;
 
+  const opt_code opt = OPT_Warray_bounds;
   /* Return true without issuing a warning.  */
   if (!do_warn)
-    return true;
+    return opt;
 
   if (!warn_array_bounds)
-    return false;
+    return no_warning;
 
-  if (TREE_NO_WARNING (ref.ptr)
-      || (ref.ref && TREE_NO_WARNING (ref.ref)))
-    return false;
+  if (warning_suppressed_p (ref.ptr, opt)
+      || (ref.ref && warning_suppressed_p (ref.ref, opt)))
+    return no_warning;
 
   char rangestr[2][64];
   if (ooboff[0] == ooboff[1]
@@ -1770,7 +1775,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	  && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
 	{
 	  auto_diagnostic_group d;
-	  if (warning_at (loc, OPT_Warray_bounds,
+	  if (warning_at (loc, opt,
 			  "%G%qD pointer overflow between offset %s "
 			  "and size %s accessing array %qD with type %qT",
 			  call, func, rangestr[0], rangestr[1], ref.base, type))
@@ -1780,13 +1785,13 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	      warned = true;
 	    }
 	  else
-	    warned = warning_at (loc, OPT_Warray_bounds,
+	    warned = warning_at (loc, opt,
 				 "%G%qD pointer overflow between offset %s "
 				 "and size %s",
 				 call, func, rangestr[0], rangestr[1]);
 	}
       else
-	warned = warning_at (loc, OPT_Warray_bounds,
+	warned = warning_at (loc, opt,
 			     "%G%qD pointer overflow between offset %s "
 			     "and size %s",
 			     call, func, rangestr[0], rangestr[1]);
@@ -1802,7 +1807,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	{
 	  auto_diagnostic_group d;
 	  if ((ref.basesize < maxobjsize
-	       && warning_at (loc, OPT_Warray_bounds,
+	       && warning_at (loc, opt,
 			      form
 			      ? G_("%G%qD forming offset %s is out of "
 				   "the bounds [0, %wu] of object %qD with "
@@ -1811,7 +1816,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 				   "[0, %wu] of object %qD with type %qT"),
 			      call, func, rangestr[0], ref.basesize.to_uhwi (),
 			      ref.base, TREE_TYPE (ref.base)))
-	      || warning_at (loc, OPT_Warray_bounds,
+	      || warning_at (loc, opt,
 			     form
 			     ? G_("%G%qD forming offset %s is out of "
 				  "the bounds of object %qD with type %qT")
@@ -1826,7 +1831,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	    }
 	}
       else if (ref.basesize < maxobjsize)
-	warned = warning_at (loc, OPT_Warray_bounds,
+	warned = warning_at (loc, opt,
 			     form
 			     ? G_("%G%qD forming offset %s is out "
 				  "of the bounds [0, %wu]")
@@ -1834,7 +1839,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 				  "of the bounds [0, %wu]"),
 			     call, func, rangestr[0], ref.basesize.to_uhwi ());
       else
-	warned = warning_at (loc, OPT_Warray_bounds,
+	warned = warning_at (loc, opt,
 			     form
 			     ? G_("%G%qD forming offset %s is out of bounds")
 			     : G_("%G%qD offset %s is out of bounds"),
@@ -1848,7 +1853,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	type = TREE_TYPE (type);
       type = TYPE_MAIN_VARIANT (type);
 
-      if (warning_at (loc, OPT_Warray_bounds,
+      if (warning_at (loc, opt,
 		      "%G%qD offset %s from the object at %qE is out "
 		      "of the bounds of %qT",
 		      call, func, rangestr[0], ref.base, type))
@@ -1866,7 +1871,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
       tree refop = TREE_OPERAND (ref.ref, 0);
       tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
 
-      if (warning_at (loc, OPT_Warray_bounds,
+      if (warning_at (loc, opt,
 		      "%G%qD offset %s from the object at %qE is out "
 		      "of the bounds of referenced subobject %qD with "
 		      "type %qT at offset %wi",
@@ -1883,7 +1888,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict,
 	}
     }
 
-  return warned;
+  return warned ? opt : no_warning;
 }
 
 /* Check a CALL statement for restrict-violations and issue warnings
@@ -1894,7 +1899,7 @@ check_call (range_query *query, gimple *call)
 {
   /* Avoid checking the call if it has already been diagnosed for
      some reason.  */
-  if (gimple_no_warning_p (call))
+  if (warning_suppressed_p (call, OPT_Wrestrict))
     return;
 
   tree func = gimple_call_fndecl (call);
@@ -1980,11 +1985,10 @@ check_call (range_query *query, gimple *call)
       || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr))))
     return;
 
-  if (!check_bounds_or_overlap (query, call, dst, src, dstwr, NULL_TREE))
-    return;
-
+  opt_code opt = check_bounds_or_overlap (query, call, dst, src, dstwr,
+					  NULL_TREE);
   /* Avoid diagnosing the call again.  */
-  gimple_set_no_warning (call, true);
+  suppress_warning (call, opt);
 }
 
 } /* anonymous namespace */
@@ -1996,7 +2000,7 @@ check_call (range_query *query, gimple *call)
    without issue a warning.  Return the OPT_Wxxx constant corresponding
    to the warning if one has been detected and zero otherwise.  */
 
-int
+opt_code
 check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize,
 			 tree srcsize, bool bounds_only /* = false */,
 			 bool do_warn /* = true */)
@@ -2006,7 +2010,7 @@ check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize,
 				  bounds_only, do_warn);
 }
 
-int
+opt_code
 check_bounds_or_overlap (range_query *query,
 			 gimple *call, tree dst, tree src, tree dstsize,
 			 tree srcsize, bool bounds_only /* = false */,
@@ -2032,16 +2036,20 @@ check_bounds_or_overlap (range_query *query,
   /* Validate offsets to each reference before the access first to make
      sure they are within the bounds of the destination object if its
      size is known, or PTRDIFF_MAX otherwise.  */
-  if (maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn)
-      || maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn))
+  opt_code opt
+    = maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn);
+  if (opt == no_warning)
+    opt = maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn);
+
+  if (opt != no_warning)
     {
       if (do_warn)
-	gimple_set_no_warning (call, true);
-      return OPT_Warray_bounds;
+	suppress_warning (call, opt);
+      return opt;
     }
 
   if (!warn_restrict || bounds_only || !src)
-    return 0;
+    return no_warning;
 
   if (!bounds_only)
     {
@@ -2051,7 +2059,7 @@ check_bounds_or_overlap (range_query *query,
 	case BUILT_IN_MEMMOVE_CHK:
 	case BUILT_IN_MEMSET:
 	case BUILT_IN_MEMSET_CHK:
-	  return 0;
+	  return no_warning;
 	default:
 	  break;
 	}
@@ -2064,26 +2072,26 @@ check_bounds_or_overlap (range_query *query,
 	 not point to objects and so do not indicate an overlap;
 	 such calls could be the result of sanitization and jump
 	 threading).  */
-      if (!integer_zerop (dst) && !gimple_no_warning_p (call))
+      if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict))
 	{
 	  warning_at (loc, OPT_Wrestrict,
 		      "%G%qD source argument is the same as destination",
 		      call, func);
-	  gimple_set_no_warning (call, true);
+	  suppress_warning (call, OPT_Wrestrict);
 	  return OPT_Wrestrict;
 	}
 
-      return 0;
+      return no_warning;
     }
 
   /* Return false when overlap has been detected.  */
   if (maybe_diag_overlap (loc, call, acs))
     {
-      gimple_set_no_warning (call, true);
+      suppress_warning (call, OPT_Wrestrict);
       return OPT_Wrestrict;
     }
 
-  return 0;
+  return no_warning;
 }
 
 gimple_opt_pass *
diff --git a/gcc/gimple.c b/gcc/gimple.c
index f1044e9c630..60a90667e4b 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -399,7 +399,7 @@ gimple_build_call_from_tree (tree t, tree fnptrtype)
   gimple_call_set_va_arg_pack (call, CALL_EXPR_VA_ARG_PACK (t));
   gimple_call_set_nothrow (call, TREE_NOTHROW (t));
   gimple_call_set_by_descriptor (call, CALL_EXPR_BY_DESCRIPTOR (t));
-  gimple_set_no_warning (call, TREE_NO_WARNING (t));
+  copy_warning (call, t);
 
   if (fnptrtype)
     {
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 91b92b4a4d1..ca5d4acfc71 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1634,6 +1634,24 @@ extern bool gimple_inexpensive_call_p (gcall *);
 extern bool stmt_can_terminate_bb_p (gimple *);
 extern location_t gimple_or_expr_nonartificial_location (gimple *, tree);
 
+/* Return the disposition for a warning (or all warnings by default)
+   for a statement.  */
+extern bool warning_suppressed_p (const gimple *, opt_code = all_warnings)
+  ATTRIBUTE_NONNULL (1);
+/* Set the disposition for a warning (or all warnings by default)
+   at a location to enabled by default.  */
+extern void suppress_warning (gimple *, opt_code = all_warnings,
+			      bool = true) ATTRIBUTE_NONNULL (1);
+
+/* Copy the warning disposition mapping from one statement to another.  */
+extern void copy_warning (gimple *, const gimple *)
+  ATTRIBUTE_NONNULL (1) ATTRIBUTE_NONNULL (2);
+/* Copy the warning disposition mapping from an expression to a statement.  */
+extern void copy_warning (gimple *, const_tree)
+  ATTRIBUTE_NONNULL (1) ATTRIBUTE_NONNULL (2);
+/* Copy the warning disposition mapping from a statement to an expression.  */
+extern void copy_warning (tree, const gimple *)
+  ATTRIBUTE_NONNULL (1) ATTRIBUTE_NONNULL (2);
 
 /* Formal (expression) temporary table handling: multiple occurrences of
    the same scalar expression are evaluated into the same temporary.  */
@@ -1854,16 +1872,17 @@ gimple_block (const gimple *g)
   return LOCATION_BLOCK (g->location);
 }
 
+/* Forward declare.  */
+static inline void gimple_set_location (gimple *, location_t);
 
 /* Set BLOCK to be the lexical scope block holding statement G.  */
 
 static inline void
 gimple_set_block (gimple *g, tree block)
 {
-  g->location = set_block (g->location, block);
+  gimple_set_location (g, set_block (g->location, block));
 }
 
-
 /* Return location information for statement G.  */
 
 static inline location_t
@@ -1886,6 +1905,8 @@ gimple_location_safe (const gimple *g)
 static inline void
 gimple_set_location (gimple *g, location_t location)
 {
+  /* Copy the no-warning data to the statement location.  */
+  copy_warning (location, g->location);
   g->location = location;
 }
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 39f5b973d18..e26c8106cfa 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1599,7 +1599,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
     {
       maybe_add_early_return_predict_stmt (pre_p);
       greturn *ret = gimple_build_return (ret_expr);
-      gimple_set_no_warning (ret, TREE_NO_WARNING (stmt));
+      copy_warning (ret, stmt);
       gimplify_seq_add_stmt (pre_p, ret);
       return GS_ALL_DONE;
     }
@@ -1661,7 +1661,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
 	 we can wind up warning about an uninitialized value for this.  Due
 	 to how this variable is constructed and initialized, this is never
 	 true.  Give up and never warn.  */
-      TREE_NO_WARNING (result) = 1;
+      suppress_warning (result, OPT_Wuninitialized);
 
       gimplify_ctxp->return_temp = result;
     }
@@ -1675,7 +1675,7 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
 
   maybe_add_early_return_predict_stmt (pre_p);
   ret = gimple_build_return (result);
-  gimple_set_no_warning (ret, TREE_NO_WARNING (stmt));
+  copy_warning (ret, stmt);
   gimplify_seq_add_stmt (pre_p, ret);
 
   return GS_ALL_DONE;
@@ -4250,7 +4250,8 @@ gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
 				 &arm2);
   cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true,
 				 label_false);
-  gimple_set_no_warning (cond_stmt, TREE_NO_WARNING (COND_EXPR_COND (expr)));
+  gimple_set_location (cond_stmt, EXPR_LOCATION (expr));
+  copy_warning (cond_stmt, COND_EXPR_COND (expr));
   gimplify_seq_add_stmt (&seq, cond_stmt);
   gimple_stmt_iterator gsi = gsi_last (seq);
   maybe_fold_stmt (&gsi);
@@ -5680,7 +5681,7 @@ gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
 
   ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
   other = build1 (ocode, TREE_TYPE (rhs), lhs);
-  TREE_NO_WARNING (other) = 1;
+  suppress_warning (other);
   other = get_formal_tmp_var (other, pre_p);
 
   realpart = code == REALPART_EXPR ? rhs : other;
@@ -5965,7 +5966,7 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
       assign = gimple_build_assign (*to_p, *from_p);
       gimple_set_location (assign, EXPR_LOCATION (*expr_p));
       if (COMPARISON_CLASS_P (*from_p))
-	gimple_set_no_warning (assign, TREE_NO_WARNING (*from_p));
+	copy_warning (assign, *from_p);
     }
 
   if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
@@ -6724,7 +6725,7 @@ gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p,
 	  /* Because of this manipulation, and the EH edges that jump
 	     threading cannot redirect, the temporary (VAR) will appear
 	     to be used uninitialized.  Don't warn.  */
-	  TREE_NO_WARNING (var) = 1;
+	  suppress_warning (var, OPT_Wuninitialized);
 	}
     }
   else
@@ -14491,7 +14492,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 
 	    gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure);
 	    ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
-	    gimple_set_no_warning (ehf, TREE_NO_WARNING (*expr_p));
+	    copy_warning (ehf, *expr_p);
 	    gimplify_seq_add_stmt (pre_p, ehf);
 	    ret = GS_ALL_DONE;
 	    break;
diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c
index 0f843bad79a..6a0e0966ead 100644
--- a/gcc/omp-expand.c
+++ b/gcc/omp-expand.c
@@ -3845,7 +3845,7 @@ expand_omp_for_generic (struct omp_region *region,
 	  for (i = first_zero_iter1;
 	       i < (fd->ordered ? fd->ordered : fd->collapse); i++)
 	    if (SSA_VAR_P (counts[i]))
-	      TREE_NO_WARNING (counts[i]) = 1;
+	      suppress_warning (counts[i], OPT_Wuninitialized);
 	  gsi_prev (&gsi);
 	  e = split_block (entry_bb, gsi_stmt (gsi));
 	  entry_bb = e->dest;
@@ -3862,7 +3862,7 @@ expand_omp_for_generic (struct omp_region *region,
 	     be executed in that case, so just avoid uninit warnings.  */
 	  for (i = first_zero_iter2; i < fd->ordered; i++)
 	    if (SSA_VAR_P (counts[i]))
-	      TREE_NO_WARNING (counts[i]) = 1;
+	      suppress_warning (counts[i], OPT_Wuninitialized);
 	  if (zero_iter1_bb)
 	    make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
 	  else
@@ -7051,7 +7051,7 @@ expand_omp_taskloop_for_outer (struct omp_region *region,
 	     be executed in that case, so just avoid uninit warnings.  */
 	  for (i = first_zero_iter; i < fd->collapse; i++)
 	    if (SSA_VAR_P (counts[i]))
-	      TREE_NO_WARNING (counts[i]) = 1;
+	      suppress_warning (counts[i], OPT_Wuninitialized);
 	  gsi_prev (&gsi);
 	  edge e = split_block (entry_bb, gsi_stmt (gsi));
 	  entry_bb = e->dest;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 2d5cdf671eb..c5abab6a281 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -5627,7 +5627,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
 		 able to notice this and not store anything at all, but
 		 we're generating code too early.  Suppress the warning.  */
 	      if (!by_ref)
-		TREE_NO_WARNING (var) = 1;
+		suppress_warning (var, OPT_Wuninitialized);
 	      break;
 
 	    case OMP_CLAUSE__CONDTEMP_:
@@ -6588,7 +6588,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
       uid = create_tmp_var (ptr_type_node, "simduid");
       /* Don't want uninit warnings on simduid, it is always uninitialized,
 	 but we use it not for the value, but for the DECL_UID only.  */
-      TREE_NO_WARNING (uid) = 1;
+      suppress_warning (uid, OPT_Wuninitialized);
       c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
       OMP_CLAUSE__SIMDUID__DECL (c) = uid;
       OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
@@ -7016,7 +7016,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p,
 	      if (predicate
 		  && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
 		      || OMP_CLAUSE_LINEAR_NO_COPYIN (c)))
-		TREE_NO_WARNING (new_var) = 1;
+		suppress_warning (new_var, OPT_Wuninitialized);
 	    }
 
 	  if (!maybe_simt && simduid && DECL_HAS_VALUE_EXPR_P (new_var))
@@ -7850,7 +7850,7 @@ lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
 	  if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
 	      && !by_ref
 	      && is_task_ctx (ctx))
-	    TREE_NO_WARNING (var) = 1;
+	    suppress_warning (var);
 	  do_in = true;
 	  break;
 
@@ -12634,7 +12634,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 		      {
 			if (is_gimple_reg (var)
 			    && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
-			  TREE_NO_WARNING (var) = 1;
+			  suppress_warning (var);
 			var = build_fold_addr_expr (var);
 		      }
 		    else
@@ -12658,7 +12658,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 			   we'll get a warning for the store to avar.
 			   Don't warn in that case, the mapping might
 			   be implicit.  */
-			TREE_NO_WARNING (var) = 1;
+			suppress_warning (var, OPT_Wuninitialized);
 			gimplify_assign (avar, var, &ilist);
 		      }
 		    avar = build_fold_addr_expr (avar);
@@ -12812,7 +12812,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 		if (omp_is_reference (var))
 		  t = build_simple_mem_ref (var);
 		else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
-		  TREE_NO_WARNING (var) = 1;
+		  suppress_warning (var);
 		if (TREE_CODE (type) != POINTER_TYPE)
 		  t = fold_convert (pointer_sized_int_node, t);
 		t = fold_convert (TREE_TYPE (x), t);
@@ -12825,7 +12825,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 		tree avar = create_tmp_var (TREE_TYPE (var));
 		mark_addressable (avar);
 		if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
-		  TREE_NO_WARNING (var) = 1;
+		  suppress_warning (var);
 		gimplify_assign (avar, var, &ilist);
 		avar = build_fold_addr_expr (avar);
 		gimplify_assign (x, avar, &ilist);
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 02256580c98..9bb436aad77 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -9428,7 +9428,7 @@ pass_warn_function_return::execute (function *fun)
   /* If we see "return;" in some basic block, then we do reach the end
      without returning a value.  */
   else if (warn_return_type > 0
-	   && !TREE_NO_WARNING (fun->decl)
+	   && !warning_suppressed_p (fun->decl, OPT_Wreturn_type)
 	   && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fun->decl))))
     {
       FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (fun)->preds)
@@ -9437,14 +9437,14 @@ pass_warn_function_return::execute (function *fun)
 	  greturn *return_stmt = dyn_cast <greturn *> (last);
 	  if (return_stmt
 	      && gimple_return_retval (return_stmt) == NULL
-	      && !gimple_no_warning_p (last))
+	      && !warning_suppressed_p (last, OPT_Wreturn_type))
 	    {
 	      location = gimple_location (last);
 	      if (LOCATION_LOCUS (location) == UNKNOWN_LOCATION)
 		location = fun->function_end_locus;
 	      if (warning_at (location, OPT_Wreturn_type,
 			      "control reaches end of non-void function"))
-		TREE_NO_WARNING (fun->decl) = 1;
+		suppress_warning (fun->decl, OPT_Wreturn_type);
 	      break;
 	    }
 	}
@@ -9452,7 +9452,7 @@ pass_warn_function_return::execute (function *fun)
 	 into __builtin_unreachable () call with BUILTINS_LOCATION.
 	 Recognize those too.  */
       basic_block bb;
-      if (!TREE_NO_WARNING (fun->decl))
+      if (!warning_suppressed_p (fun->decl, OPT_Wreturn_type))
 	FOR_EACH_BB_FN (bb, fun)
 	  if (EDGE_COUNT (bb->succs) == 0)
 	    {
@@ -9476,7 +9476,7 @@ pass_warn_function_return::execute (function *fun)
 		    location = fun->function_end_locus;
 		  if (warning_at (location, OPT_Wreturn_type,
 				  "control reaches end of non-void function"))
-		    TREE_NO_WARNING (fun->decl) = 1;
+		    suppress_warning (fun->decl, OPT_Wreturn_type);
 		  break;
 		}
 	    }
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index d7d991714de..a528cdc7fee 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -456,12 +456,12 @@ create_one_component_var (tree type, tree orig, const char *prefix,
       SET_DECL_DEBUG_EXPR (r, build1 (code, type, orig));
       DECL_HAS_DEBUG_EXPR_P (r) = 1;
       DECL_IGNORED_P (r) = 0;
-      TREE_NO_WARNING (r) = TREE_NO_WARNING (orig);
+      copy_warning (r, orig);
     }
   else
     {
       DECL_IGNORED_P (r) = 1;
-      TREE_NO_WARNING (r) = 1;
+      suppress_warning (r);
     }
 
   return r;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 05d1a253d5b..9ec2013b56d 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1116,7 +1116,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
 	  *tp = fold_build2 (MEM_REF, type, ptr, TREE_OPERAND (*tp, 1));
 	  TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
 	  TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old);
-	  TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
+	  copy_warning (*tp, old);
 	  if (MR_DEPENDENCE_CLIQUE (old) != 0)
 	    {
 	      MR_DEPENDENCE_CLIQUE (*tp)
@@ -1375,7 +1375,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
 	  *tp = fold_build2 (MEM_REF, type, ptr, TREE_OPERAND (*tp, 1));
 	  TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
 	  TREE_SIDE_EFFECTS (*tp) = TREE_SIDE_EFFECTS (old);
-	  TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
+	  copy_warning (*tp, old);
 	  if (MR_DEPENDENCE_CLIQUE (old) != 0)
 	    {
 	      MR_DEPENDENCE_CLIQUE (*tp)
@@ -3775,7 +3775,7 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
 
   /* Do not have the rest of GCC warn about this variable as it should
      not be visible to the user.  */
-  TREE_NO_WARNING (var) = 1;
+  suppress_warning (var /* OPT_Wuninitialized? */);
 
   declare_inline_vars (id->block, var);
 
@@ -5033,7 +5033,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id,
 	 initialized.  We do not want to issue a warning about that
 	 uninitialized variable.  */
       if (DECL_P (modify_dest))
-	TREE_NO_WARNING (modify_dest) = 1;
+	suppress_warning (modify_dest, OPT_Wuninitialized);
 
       if (gimple_call_return_slot_opt_p (call_stmt))
 	{
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index cea917a4d58..5ca6db248d5 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -411,8 +411,8 @@ lookup_field_for_decl (struct nesting_info *info, tree decl,
 	  DECL_USER_ALIGN (field) = DECL_USER_ALIGN (decl);
 	  DECL_IGNORED_P (field) = DECL_IGNORED_P (decl);
 	  DECL_NONADDRESSABLE_P (field) = !TREE_ADDRESSABLE (decl);
-	  TREE_NO_WARNING (field) = TREE_NO_WARNING (decl);
 	  TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl);
+	  copy_warning (field, decl);
 
 	  /* Declare the transformation and adjust the original DECL.  For a
 	     variable or for a parameter when not optimizing, we make it point
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 8dfc923ed7e..385b228dbbc 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -2240,12 +2240,12 @@ create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
 	  DECL_HAS_DEBUG_EXPR_P (repl) = 1;
 	}
       if (access->grp_no_warning)
-	TREE_NO_WARNING (repl) = 1;
+	suppress_warning (repl /* Be more selective! */);
       else
-	TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
+	copy_warning (repl, access->base);
     }
   else
-    TREE_NO_WARNING (repl) = 1;
+    suppress_warning (repl /* Be more selective! */);
 
   if (dump_file)
     {
@@ -3556,7 +3556,7 @@ generate_subtree_copies (struct access *access, tree agg,
 	    }
 	  else
 	    {
-	      TREE_NO_WARNING (repl) = 1;
+	      suppress_warning (repl /* Be more selective! */);
 	      if (access->grp_partial_lhs)
 		repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
 						 !insert_after,
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 3834212b867..42585412325 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -3527,7 +3527,7 @@ pass_post_ipa_warn::execute (function *fun)
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
 	{
 	  gimple *stmt = gsi_stmt (gsi);
-	  if (!is_gimple_call (stmt) || gimple_no_warning_p (stmt))
+	  if (!is_gimple_call (stmt) || warning_suppressed_p (stmt, OPT_Wnonnull))
 	    continue;
 
 	  tree fntype = gimple_call_fntype (stmt);
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index beb2702f3b6..db3b18b275c 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -403,7 +403,8 @@ combine_cond_expr_cond (gimple *stmt, enum tree_code code, tree type,
       return NULL_TREE;
     }
 
-  fold_undefer_overflow_warnings (!gimple_no_warning_p (stmt), stmt, 0);
+  bool nowarn = warning_suppressed_p (stmt, OPT_Wstrict_overflow);
+  fold_undefer_overflow_warnings (!nowarn, stmt, 0);
 
   return t;
 }
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index 08caa83b4b4..dfa5dc87c34 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -458,7 +458,7 @@ ch_base::copy_headers (function *fun)
 			  && gimple_cond_code (stmt) != NE_EXPR
 			  && INTEGRAL_TYPE_P (TREE_TYPE (lhs))
 			  && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs)))
-			gimple_set_no_warning (stmt, true);
+			suppress_warning (stmt, OPT_Wstrict_overflow_);
 		    }
 		  else if (is_gimple_assign (stmt))
 		    {
@@ -469,7 +469,7 @@ ch_base::copy_headers (function *fun)
 			  && rhs_code != NE_EXPR
 			  && INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
 			  && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (rhs1)))
-			gimple_set_no_warning (stmt, true);
+			suppress_warning (stmt, OPT_Wstrict_overflow_);
 		    }
 		}
 	    }
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 8034cf68d27..c3fecb26b2b 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -2143,7 +2143,7 @@ execute_sm (class loop *loop, im_mem_ref *ref,
       /* If not emitting a load mark the uninitialized state on the
 	 loop entry as not to be warned for.  */
       tree uninit = create_tmp_reg (TREE_TYPE (aux->tmp_var));
-      TREE_NO_WARNING (uninit) = 1;
+      suppress_warning (uninit, OPT_Wuninitialized);
       load = gimple_build_assign (aux->tmp_var, uninit);
     }
   lim_data = init_lim_data (load);
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 969b868397e..1763ad4ce7b 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -3010,9 +3010,12 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb,
   new_stmt = gimple_build_assign (name, lhs);
   gimple_set_location (new_stmt, locus);
   lhs = unshare_expr (lhs);
-  /* Set TREE_NO_WARNING on the rhs of the load to avoid uninit
-     warnings.  */
-  TREE_NO_WARNING (gimple_assign_rhs1 (new_stmt)) = 1;
+  {
+    /* Set the no-warning bit on the rhs of the load to avoid uninit
+       warnings.  */
+    tree rhs1 = gimple_assign_rhs1 (new_stmt);
+    suppress_warning (rhs1, OPT_Wuninitialized);
+  }
   gsi_insert_on_edge (e1, new_stmt);
 
   /* 3) Create a PHI node at the join block, with one argument
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 423075b2bd1..656dfa465f4 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -1935,7 +1935,7 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
 		     strinfo *si = NULL, bool plus_one = false,
 		     bool rawmem = false)
 {
-  if (!len || gimple_no_warning_p (stmt))
+  if (!len || warning_suppressed_p (stmt, OPT_Wstringop_overflow_))
     return;
 
   /* The DECL of the function performing the write if it is done
@@ -1954,7 +1954,7 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
   else
     return;
 
-  if (TREE_NO_WARNING (dest))
+  if (warning_suppressed_p (dest, OPT_Wstringop_overflow_))
     return;
 
   const int ostype = rawmem ? 0 : 1;
@@ -2098,7 +2098,7 @@ maybe_warn_overflow (gimple *stmt, tree len, pointer_query &ptr_qry,
   if (!warned)
     return;
 
-  gimple_set_no_warning (stmt, true);
+  suppress_warning (stmt, OPT_Wstringop_overflow_);
 
   aref.inform_access (access_write_only);
 }
@@ -2621,16 +2621,16 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
   len = fold_convert_loc (loc, type, unshare_expr (srclen));
   len = fold_build2_loc (loc, PLUS_EXPR, type, len, build_int_cst (type, 1));
 
-  /* Set the no-warning bit on the transformed statement?  */
-  bool set_no_warning = false;
+  /* Disable warning for the transformed statement?  */
+  opt_code no_warning_opt = no_warning;
 
-  if (const strinfo *chksi = olddsi ? olddsi : dsi)
-    if (si
-	&& check_bounds_or_overlap (stmt, chksi->ptr, si->ptr, NULL_TREE, len))
-      {
-	gimple_set_no_warning (stmt, true);
-	set_no_warning = true;
-      }
+  if (const strinfo *chksi = si ? olddsi ? olddsi : dsi : NULL)
+    {
+      no_warning_opt = check_bounds_or_overlap (stmt, chksi->ptr, si->ptr,
+						NULL_TREE, len);
+      if (no_warning_opt)
+	suppress_warning (stmt, no_warning_opt);
+    }
 
   if (fn == NULL_TREE)
     return;
@@ -2664,8 +2664,8 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi,
   else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
     fprintf (dump_file, "not possible.\n");
 
-  if (set_no_warning)
-    gimple_set_no_warning (stmt, true);
+  if (no_warning_opt)
+    suppress_warning (stmt, no_warning_opt);
 }
 
 /* Check the size argument to the built-in forms of stpncpy and strncpy
@@ -2793,7 +2793,7 @@ maybe_diag_stxncpy_trunc (gimple_stmt_iterator gsi, tree src, tree cnt,
 			  pointer_query *ptr_qry /* = NULL */)
 {
   gimple *stmt = gsi_stmt (gsi);
-  if (gimple_no_warning_p (stmt))
+  if (warning_suppressed_p (stmt, OPT_Wstringop_truncation))
     return false;
 
   wide_int cntrange[2];
@@ -3153,9 +3153,10 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
   else
     srclenp1 = NULL_TREE;
 
-  if (check_bounds_or_overlap (stmt, dst, src, dstlenp1, srclenp1))
+  opt_code opt = check_bounds_or_overlap (stmt, dst, src, dstlenp1, srclenp1);
+  if (opt != no_warning)
     {
-      gimple_set_no_warning (stmt, true);
+      suppress_warning (stmt, opt);
       return;
     }
 
@@ -3166,7 +3167,7 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
   if (!pss || pss->first <= 0)
     {
       if (maybe_diag_stxncpy_trunc (*gsi, src, len))
-	gimple_set_no_warning (stmt, true);
+	suppress_warning (stmt, OPT_Wstringop_truncation);
 
       return;
     }
@@ -3203,8 +3204,8 @@ handle_builtin_stxncpy_strncat (bool append_p, gimple_stmt_iterator *gsi)
       /* Issue -Wstringop-overflow when appending or when writing into
 	 a destination of a known size.  Otherwise, when copying into
 	 a destination of an unknown size, it's truncation.  */
-      int opt = (append_p || dstsize
-		 ? OPT_Wstringop_overflow_ : OPT_Wstringop_truncation);
+      opt_code opt = (append_p || dstsize
+		      ? OPT_Wstringop_overflow_ : OPT_Wstringop_truncation);
       warned = warning_at (callloc, opt,
 			   "%G%qD specified bound depends on the length "
 			   "of the source argument",
@@ -3445,8 +3446,8 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
 	srclen = get_string_length (si);
     }
 
-  /* Set the no-warning bit on the transformed statement?  */
-  bool set_no_warning = false;
+  /* Disable warning for the transformed statement?  */
+  opt_code no_warning_opt = no_warning;
 
   if (dsi == NULL || get_string_length (dsi) == NULL_TREE)
     {
@@ -3463,12 +3464,10 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
 	  }
 
 	tree sptr = si && si->ptr ? si->ptr : src;
-
-	if (check_bounds_or_overlap (stmt, dst, sptr, NULL_TREE, slen))
-	  {
-	    gimple_set_no_warning (stmt, true);
-	    set_no_warning = true;
-	  }
+	no_warning_opt = check_bounds_or_overlap (stmt, dst, sptr, NULL_TREE,
+						  slen);
+	if (no_warning_opt)
+	  suppress_warning (stmt, no_warning_opt);
       }
 
       /* strcat (p, q) can be transformed into
@@ -3575,11 +3574,10 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
       tree dstsize = fold_build2 (PLUS_EXPR, type, dstlen, one);
       tree sptr = si && si->ptr ? si->ptr : src;
 
-      if (check_bounds_or_overlap (stmt, dst, sptr, dstsize, srcsize))
-	{
-	  gimple_set_no_warning (stmt, true);
-	  set_no_warning = true;
-	}
+      no_warning_opt = check_bounds_or_overlap (stmt, dst, sptr, dstsize,
+						srcsize);
+      if (no_warning_opt)
+	suppress_warning (stmt, no_warning_opt);
     }
 
   tree len = NULL_TREE;
@@ -3645,8 +3643,8 @@ handle_builtin_strcat (enum built_in_function bcode, gimple_stmt_iterator *gsi,
   else if (dump_file && (dump_flags & TDF_DETAILS) != 0)
     fprintf (dump_file, "not possible.\n");
 
-  if (set_no_warning)
-    gimple_set_no_warning (stmt, true);
+  if (no_warning_opt)
+    suppress_warning (stmt, no_warning_opt);
 }
 
 /* Handle a call to an allocation function like alloca, malloc or calloc,
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c
index 7c002f8ed87..99442d7f975 100644
--- a/gcc/tree-ssa-uninit.c
+++ b/gcc/tree-ssa-uninit.c
@@ -87,17 +87,33 @@ has_undefined_value_p (tree t)
 	      && possibly_undefined_names->contains (t)));
 }
 
-/* Like has_undefined_value_p, but don't return true if TREE_NO_WARNING
-   is set on SSA_NAME_VAR.  */
+/* Return true if EXPR should suppress either uninitialized warning.  */
+
+static inline bool
+get_no_uninit_warning (tree expr)
+{
+  return warning_suppressed_p (expr, OPT_Wuninitialized);
+}
+
+/* Suppress both uninitialized warnings for EXPR.  */
+
+static inline void
+set_no_uninit_warning (tree expr)
+{
+  suppress_warning (expr, OPT_Wuninitialized);
+}
+
+/* Like has_undefined_value_p, but don't return true if the no-warning
+   bit is set on SSA_NAME_VAR for either uninit warning.  */
 
 static inline bool
 uninit_undefined_value_p (tree t)
 {
   if (!has_undefined_value_p (t))
     return false;
-  if (SSA_NAME_VAR (t) && TREE_NO_WARNING (SSA_NAME_VAR (t)))
-    return false;
-  return true;
+  if (!SSA_NAME_VAR (t))
+    return true;
+  return !get_no_uninit_warning (SSA_NAME_VAR (t));
 }
 
 /* Emit warnings for uninitialized variables.  This is done in two passes.
@@ -165,10 +181,10 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var,
   /* TREE_NO_WARNING either means we already warned, or the front end
      wishes to suppress the warning.  */
   if ((context
-       && (gimple_no_warning_p (context)
+       && (warning_suppressed_p (context, OPT_Wuninitialized)
 	   || (gimple_assign_single_p (context)
-	       && TREE_NO_WARNING (gimple_assign_rhs1 (context)))))
-      || TREE_NO_WARNING (expr))
+	       && get_no_uninit_warning (gimple_assign_rhs1 (context)))))
+      || get_no_uninit_warning (expr))
     return;
 
   if (context != NULL && gimple_has_location (context))
@@ -185,7 +201,7 @@ warn_uninit (enum opt_code wc, tree t, tree expr, tree var,
   auto_diagnostic_group d;
   if (warning_at (location, wc, gmsgid, expr))
     {
-      TREE_NO_WARNING (expr) = 1;
+      suppress_warning (expr, wc);
 
       if (location == DECL_SOURCE_LOCATION (var))
 	return;
@@ -260,7 +276,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
   use_operand_p luse_p;
   imm_use_iterator liter;
 
-  if (TREE_NO_WARNING (rhs))
+  if (get_no_uninit_warning (rhs))
     return NULL_TREE;
 
   /* Do not warn if the base was marked so or this is a
@@ -268,7 +284,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
   tree base = ao_ref_base (&ref);
   if ((VAR_P (base)
        && DECL_HARD_REGISTER (base))
-      || TREE_NO_WARNING (base))
+      || get_no_uninit_warning (base))
     return NULL_TREE;
 
   /* Do not warn if the access is fully outside of the variable.  */
@@ -407,7 +423,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
     rhs = TREE_OPERAND (rhs, 0);
 
   /* Check again since RHS may have changed above.  */
-  if (TREE_NO_WARNING (rhs))
+  if (get_no_uninit_warning (rhs))
     return NULL_TREE;
 
   /* Avoid warning about empty types such as structs with no members.
@@ -435,7 +451,7 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs,
 	     uses or accesses by functions as it may hide important
 	     locations.  */
 	  if (lhs)
-	    TREE_NO_WARNING (rhs) = 1;
+	    set_no_uninit_warning (rhs);
 	  warned = true;
 	}
     }
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index b9c0e65bd98..0565c9b5073 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -406,10 +406,10 @@ compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p)
 	return -2;
 
       if (strict_overflow_p != NULL
-	  /* Symbolic range building sets TREE_NO_WARNING to declare
+	  /* Symbolic range building sets the no-warning bit to declare
 	     that overflow doesn't happen.  */
-	  && (!inv1 || !TREE_NO_WARNING (val1))
-	  && (!inv2 || !TREE_NO_WARNING (val2)))
+	  && (!inv1 || !warning_suppressed_p (val1, OPT_Woverflow))
+	  && (!inv2 || !warning_suppressed_p (val2, OPT_Woverflow)))
 	*strict_overflow_p = true;
 
       if (!inv1)
@@ -432,10 +432,10 @@ compare_values_warnv (tree val1, tree val2, bool *strict_overflow_p)
 	return -2;
 
       if (strict_overflow_p != NULL
-	  /* Symbolic range building sets TREE_NO_WARNING to declare
+	  /* Symbolic range building sets the no-warning bit to declare
 	     that overflow doesn't happen.  */
-	  && (!sym1 || !TREE_NO_WARNING (val1))
-	  && (!sym2 || !TREE_NO_WARNING (val2)))
+	  && (!sym1 || !warning_suppressed_p (val1, OPT_Woverflow))
+	  && (!sym2 || !warning_suppressed_p (val2, OPT_Woverflow)))
 	*strict_overflow_p = true;
 
       const signop sgn = TYPE_SIGN (TREE_TYPE (val1));
diff --git a/gcc/tree.h b/gcc/tree.h
index 62b2de46479..3c92c58980e 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_TREE_H
 
 #include "tree-core.h"
+#include "options.h"
 
 /* Convert a target-independent built-in function code to a combined_fn.  */
 
@@ -6440,4 +6434,30 @@ public:
   operator location_t () const { return m_combined_loc; }
 };
 
+/* Code that doesn't refer to any warning.  Has no effect on suppression
+   functions.  */
+constexpr opt_code no_warning = opt_code ();
+/* Wildcard code that refers to all warnings.  */
+constexpr opt_code all_warnings = N_OPTS;
+
+/* Return the disposition for a warning (or all warnings by default)
+   at a location.  */
+extern bool warning_suppressed_at (location_t, opt_code = all_warnings);
+/* Set the disposition for a warning (or all warnings by default)
+   at a location to disabled by default.  */
+extern bool suppress_warning_at (location_t, opt_code = all_warnings,
+				 bool = true);
+/* Copy warning disposition from one location to another.  */
+extern void copy_warning (location_t, location_t);
+
+/* Return the disposition for a warning (or all warnings by default)
+   for an expression.  */
+extern bool warning_suppressed_p (const_tree, opt_code = all_warnings);
+/* Set the disposition for a warning (or all warnings by default)
+   at a location to disabled by default.  */
+extern void suppress_warning (tree, opt_code = all_warnings, bool = true)
+  ATTRIBUTE_NONNULL (1);
+/* Copy warning disposition from one expression to another.  */
+extern void copy_warning (tree, const_tree);
+
 #endif  /* GCC_TREE_H  */
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 509c8b093c5..3ae2c68499d 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -699,7 +699,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
 				   build_int_cst (TREE_TYPE (max), 1));
 	      /* Signal to compare_values_warnv this expr doesn't overflow.  */
 	      if (EXPR_P (max))
-		TREE_NO_WARNING (max) = 1;
+		suppress_warning (max, OPT_Woverflow);
 	    }
 
 	  vr_p->update (min, max);
@@ -739,7 +739,7 @@ vr_values::extract_range_for_var_from_comparison_expr (tree var,
 				   build_int_cst (TREE_TYPE (min), 1));
 	      /* Signal to compare_values_warnv this expr doesn't overflow.  */
 	      if (EXPR_P (min))
-		TREE_NO_WARNING (min) = 1;
+		suppress_warning (min, OPT_Woverflow);
 	    }
 
 	  vr_p->update (min, max);
@@ -3355,7 +3355,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
 	  max = fold_build2 (MINUS_EXPR, TREE_TYPE (op0), max, one);
 	  /* Signal to compare_values_warnv this expr doesn't overflow.  */
 	  if (EXPR_P (max))
-	    TREE_NO_WARNING (max) = 1;
+	    suppress_warning (max, OPT_Woverflow);
 	}
     }
   else if (cond_code == GE_EXPR || cond_code == GT_EXPR)
@@ -3369,7 +3369,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
 	  min = fold_build2 (PLUS_EXPR, TREE_TYPE (op0), min, one);
 	  /* Signal to compare_values_warnv this expr doesn't overflow.  */
 	  if (EXPR_P (min))
-	    TREE_NO_WARNING (min) = 1;
+	    suppress_warning (min, OPT_Woverflow);
 	}
     }
 

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 11/13] v2 Use new per-location warning APIs in the Objective-C front end
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (9 preceding siblings ...)
  2021-06-04 21:43     ` [PATCH 10/13] v2 Use new per-location warning APIs in the middle end Martin Sebor
@ 2021-06-04 21:43     ` Martin Sebor
  2021-06-24  5:02       ` Jeff Law
  2021-06-04 21:43     ` [PATCH 12/13] v2 Remove TREE_NO_WARNING and gimple*no_warning* APIs Martin Sebor
                       ` (3 subsequent siblings)
  14 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:43 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 167 bytes --]

The attached patch replaces the uses of TREE_NO_WARNING in
the Objective-C front end with the new suppress_warning(),
warning_suppressed_p(), and copy_warning() APIs.

[-- Attachment #2: gcc-no-warning-objc.diff --]
[-- Type: text/x-patch, Size: 3970 bytes --]

Add support for per-location warning groups.

gcc/objc/ChangeLog:

	* objc-act.c (objc_maybe_build_modify_expr): Replace direct uses
	of TREE_NO_WARNING with warning_suppressed_p, and suppress_warning.
	(objc_build_incr_expr_for_property_ref): Same.
	(objc_build_struct): Same.
	(synth_module_prologue): Same.
	* objc-gnu-runtime-abi-01.c (gnu_runtime_01_initialize): Same.
	* objc-next-runtime-abi-01.c (next_runtime_01_initialize): Same.
	* objc-next-runtime-abi-02.c (next_runtime_02_initialize): Same.

diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 8d106a4de26..ec20891152b 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -2007,7 +2007,7 @@ objc_maybe_build_modify_expr (tree lhs, tree rhs)
 	 correct (maybe a more sophisticated implementation could
 	 avoid generating the compound expression if not needed), but
 	 we need to turn it off.  */
-      TREE_NO_WARNING (compound_expr) = 1;
+      suppress_warning (compound_expr, OPT_Wunused);
       return compound_expr;
     }
   else
@@ -2129,7 +2129,7 @@ objc_build_incr_expr_for_property_ref (location_t location,
 
   /* Prevent C++ from warning with -Wall that "right operand of comma
      operator has no effect".  */
-  TREE_NO_WARNING (compound_expr) = 1;
+  suppress_warning (compound_expr, OPT_Wunused);
   return compound_expr;
 }
 
@@ -2262,8 +2262,9 @@ objc_build_struct (tree klass, tree fields, tree super_name)
       DECL_FIELD_IS_BASE (base) = 1;
 
       if (fields)
-	TREE_NO_WARNING (fields) = 1;	/* Suppress C++ ABI warnings -- we   */
-#endif					/* are following the ObjC ABI here.  */
+	/* Suppress C++ ABI warnings: we are following the ObjC ABI here.  */
+	suppress_warning (fields, OPT_Wabi);
+#endif
       DECL_CHAIN (base) = fields;
       fields = base;
     }
@@ -3112,19 +3113,19 @@ synth_module_prologue (void)
 						TYPE_DECL,
 						objc_object_name,
 						objc_object_type));
-  TREE_NO_WARNING (type) = 1;
+  suppress_warning (type);
 
   type = lang_hooks.decls.pushdecl (build_decl (input_location,
 						TYPE_DECL,
 						objc_instancetype_name,
 						objc_instancetype_type));
-  TREE_NO_WARNING (type) = 1;
+  suppress_warning (type);
 
   type = lang_hooks.decls.pushdecl (build_decl (input_location,
 						TYPE_DECL,
 						objc_class_name,
 						objc_class_type));
-  TREE_NO_WARNING (type) = 1;
+  suppress_warning (type);
 
   /* Forward-declare '@interface Protocol'.  */
   type = get_identifier (PROTOCOL_OBJECT_CLASS_NAME);
diff --git a/gcc/objc/objc-gnu-runtime-abi-01.c b/gcc/objc/objc-gnu-runtime-abi-01.c
index 4add71edf41..976fa1e36cb 100644
--- a/gcc/objc/objc-gnu-runtime-abi-01.c
+++ b/gcc/objc/objc-gnu-runtime-abi-01.c
@@ -213,7 +213,7 @@ static void gnu_runtime_01_initialize (void)
 						TYPE_DECL,
 						objc_selector_name,
 						objc_selector_type));
-  TREE_NO_WARNING (type) = 1;
+  suppress_warning (type);
 
   /* typedef id (*IMP)(id, SEL, ...); */
   ftype = build_varargs_function_type_list (objc_object_type,
diff --git a/gcc/objc/objc-next-runtime-abi-01.c b/gcc/objc/objc-next-runtime-abi-01.c
index 3ec6e1703c1..183fc01abb2 100644
--- a/gcc/objc/objc-next-runtime-abi-01.c
+++ b/gcc/objc/objc-next-runtime-abi-01.c
@@ -282,7 +282,7 @@ static void next_runtime_01_initialize (void)
 						TYPE_DECL,
 						objc_selector_name,
 						objc_selector_type));
-  TREE_NO_WARNING (type) = 1;
+  suppress_warning (type);
 
   build_v1_class_template ();
   build_super_template ();
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index 3cfcd0b1a57..963d1bf1ad8 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -379,7 +379,7 @@ static void next_runtime_02_initialize (void)
 						TYPE_DECL,
 						objc_selector_name,
 						objc_selector_type));
-  TREE_NO_WARNING (type) = 1;
+  suppress_warning (type);
 
   /* IMP : id (*) (id, _message_ref_t*, ...)
      SUPER_IMP : id (*) ( super_t*, _super_message_ref_t*, ...)

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 12/13] v2 Remove TREE_NO_WARNING and gimple*no_warning* APIs
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (10 preceding siblings ...)
  2021-06-04 21:43     ` [PATCH 11/13] v2 Use new per-location warning APIs in the Objective-C front end Martin Sebor
@ 2021-06-04 21:43     ` Martin Sebor
  2021-06-24  5:01       ` Jeff Law
  2021-06-04 21:43     ` [PATCH 13/13] v2 Add regression tests for PR 74765 and 74762 Martin Sebor
                       ` (2 subsequent siblings)
  14 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:43 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 145 bytes --]

The attached patch removes the definitions of the TREE_NO_WARNING macro
and the gimple_get_no_warning_p() and gimple_set_no_warning() functions.

[-- Attachment #2: gcc-no-warning-remove-api.diff --]
[-- Type: text/x-patch, Size: 1812 bytes --]

Remove legacy TREE_NO_WARNING amd gimple_*no_warning* APIs.

gcc/ChangeLog:

	* tree.h (TREE_NO_WARNING): Remove.
	* gimple.h (gimple_no_warning_p): Remove.
	(gimple_suppress_warning): Same.

diff --git a/gcc/tree.h b/gcc/tree.h
index 62b2de46479..3c92c58980e 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -699,13 +700,6 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
 /* Determines whether an ENUMERAL_TYPE has defined the list of constants. */
 #define ENUM_IS_OPAQUE(NODE) (ENUMERAL_TYPE_CHECK (NODE)->base.private_flag)
 
-/* In an expr node (usually a conversion) this means the node was made
-   implicitly and should not lead to any sort of warning.  In a decl node,
-   warnings concerning the decl should be suppressed.  This is used at
-   least for used-before-set warnings, and it set after one warning is
-   emitted.  */
-#define TREE_NO_WARNING(NODE) ((NODE)->base.nowarning_flag)
-
 /* Nonzero if we should warn about the change in empty class parameter
    passing ABI in this TU.  */
 #define TRANSLATION_UNIT_WARN_EMPTY_P(NODE) \
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 91b92b4a4d1..ca5d4acfc71 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1948,22 +1969,6 @@ gimple_seq_singleton_p (gimple_seq seq)
 	  && (gimple_seq_first (seq) == gimple_seq_last (seq)));
 }
 
-/* Return true if no warnings should be emitted for statement STMT.  */
-
-static inline bool
-gimple_no_warning_p (const gimple *stmt)
-{
-  return stmt->no_warning;
-}
-
-/* Set the no_warning flag of STMT to NO_WARNING.  */
-
-static inline void
-gimple_set_no_warning (gimple *stmt, bool no_warning)
-{
-  stmt->no_warning = (unsigned) no_warning;
-}
-
 /* Set the visited status on statement STMT to VISITED_P.
 
    Please note that this 'visited' property of the gimple statement is

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PATCH 13/13] v2 Add regression tests for PR 74765 and 74762
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (11 preceding siblings ...)
  2021-06-04 21:43     ` [PATCH 12/13] v2 Remove TREE_NO_WARNING and gimple*no_warning* APIs Martin Sebor
@ 2021-06-04 21:43     ` Martin Sebor
  2021-06-24  4:56       ` Jeff Law
  2021-06-15  1:29     ` [PING][PATCH 0/13] v2 warning control by group and location (PR 74765) Martin Sebor
  2021-07-17 20:36     ` [PATCH " Jan-Benedict Glaw
  14 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-06-04 21:43 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 100 bytes --]

The attached patch adds regression tests for two closely related bugs
resolved by the patch series.

[-- Attachment #2: gcc-no-warning-tests.diff --]
[-- Type: text/x-patch, Size: 1675 bytes --]

Regression tests for TREE_NO_WARNING enhancement to warning groups.

PR middle-end/74765 - missing uninitialized warning (parenthesis, TREE_NO_WARNING abuse)
PR middle-end/74762 - [9/10/11/12 Regression] missing uninitialized warning (C++, parenthesized expr, TREE_NO_WARNING)

gcc/testsuite/ChangeLog:

	* g++.dg/uninit-pr74762.C: New test.
	* g++.dg/warn/uninit-pr74765.C: Same.

diff --git a/gcc/testsuite/g++.dg/uninit-pr74762.C b/gcc/testsuite/g++.dg/uninit-pr74762.C
new file mode 100644
index 00000000000..ce1bc59773e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/uninit-pr74762.C
@@ -0,0 +1,24 @@
+/* PR c++/74762 - missing uninitialized warning (C++, parenthesized expr)
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+struct tree2;
+struct tree_vector2
+{
+  tree2 *elts[1];
+};
+
+struct tree2
+{
+  struct
+  {
+    tree_vector2 vector;
+  } u;
+};
+
+tree2 *
+const_with_all_bytes_same (tree2 *val)
+{
+  int i;
+  return ((val->u.vector.elts[i]));   // { dg-warning "\\\[-Wuninitialized" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/uninit-pr74765.C b/gcc/testsuite/g++.dg/warn/uninit-pr74765.C
new file mode 100644
index 00000000000..1b8c124b18b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/uninit-pr74765.C
@@ -0,0 +1,24 @@
+/* PR c++/74765 - missing uninitialized warning (parenthesis,
+   TREE_NO_WARNING abuse)
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+int warn_equal_parens (int x, int y)
+{
+  int i;
+
+  if ((i == 0))     // { dg-warning "\\\[-Wuninitialized" }
+    return x;
+
+  return y;
+}
+
+int warn_equal (int x, int y)
+{
+  int i;
+
+  if (i == 0)       // { dg-warning "\\\[-Wuninitialized" }
+    return x;
+
+  return y;
+}

^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PING][PATCH 0/13] v2 warning control by group and location (PR 74765)
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (12 preceding siblings ...)
  2021-06-04 21:43     ` [PATCH 13/13] v2 Add regression tests for PR 74765 and 74762 Martin Sebor
@ 2021-06-15  1:29     ` Martin Sebor
  2021-07-17 20:36     ` [PATCH " Jan-Benedict Glaw
  14 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-15  1:29 UTC (permalink / raw)
  To: gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571971.html

I got the go ahead to commit the Ada and Objective-C subset (patches
2 and 11).  Most of the rest of the patches are mechanical replacements
and so nearly obvious but I'm still looking for a review/approval of
the warning infrastructure and the rest of the changes.

https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571973.html
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571974.html
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571975.html
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571976.html
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571977.html
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571978.html
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571979.html
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571980.html
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571981.html
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571983.html
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571984.html

Approved:
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571972.html
https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571982.html

On 6/4/21 3:27 PM, Martin Sebor wrote:
> This is a revised patch series to add warning control by group and
> location, updated based on feedback on the initial series.
> 
> v2 changes include:
> 
> 1) Use opt_code rather than int for the option argument to the new
>     APIs.  This let me find and fix a bug in the original Ada change.
> 2) Use suppress_warning() and warning_suppressed_p() instead of
>     get/set_no_warning, and also instead of warning_enabled/disabled
>     for the names of the new functions (as requested/clarified offline
>     by David).
> 3) Make the removal of the TREE_NO_WARNING macro and
>     the gimple_get_no_warning_p() and gimple_set_no_warning()
>     functions a standalone patch.
> 4) Include tests for PR 74765 and 74762 fixed by these changes.
> 
> I have retested the whole patch series on x86_64-linux.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PING][PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)
  2021-06-04 21:41     ` [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups " Martin Sebor
@ 2021-06-21 21:34       ` Martin Sebor
  2021-06-22 23:18       ` [PATCH " David Malcolm
  1 sibling, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-21 21:34 UTC (permalink / raw)
  To: gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571973.html

Looking for a review of v2 of the diagnostic infrastructure bits.

On 6/4/21 3:41 PM, Martin Sebor wrote:
> The attached patch introduces the suppress_warning(),
> warning_suppressed(), and copy_no_warning() APIs without making
> use of them in the rest of GCC.  They are in three files:
> 
>    diagnostic-spec.{h,c}: Location-centric overloads.
>    warning-control.cc: Tree- and gimple*-centric overloads.
> 
> The location-centric overloads are suitable to use from the diagnostic
> subsystem.  The rest can be used from the front ends and the middle end.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PING][PATCH 3/13] v2 Use new per-location warning APIs in C front end
  2021-06-04 21:41     ` [PATCH 3/13] v2 Use new per-location warning APIs in C front end Martin Sebor
@ 2021-06-21 21:35       ` Martin Sebor
  2021-06-24  5:09       ` [PATCH " Jeff Law
  1 sibling, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-21 21:35 UTC (permalink / raw)
  To: gcc-patches, Joseph S. Myers

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571974.html

I'm looking for a review of the mostly mechanical C front end changes
to the new suppress_warning() API.

On 6/4/21 3:41 PM, Martin Sebor wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the C front
> end with the new suppress_warning(), warning_suppressed_p(), and
> copy_warning() APIs.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PING][PATCH 4/13] v2 Use new per-location warning APIs in C family code
  2021-06-04 21:42     ` [PATCH 4/13] v2 Use new per-location warning APIs in C family code Martin Sebor
@ 2021-06-21 21:35       ` Martin Sebor
  2021-06-24  5:06       ` [PATCH " Jeff Law
  1 sibling, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-21 21:35 UTC (permalink / raw)
  To: gcc-patches, Jason Merrill, Joseph S. Myers

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571975.html

I'm looking for a review of the mostly mechanical shared subset of
the C and C++ front end changes to the new suppress_warning() API.

On 6/4/21 3:42 PM, Martin Sebor wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the shared
> C family front end with the new suppress_warning(),
> warning_suppressed_p(), and copy_warning() APIs.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PING][PATCH 6/13] v2 Use new per-location warning APIs in the C++ front end
  2021-06-04 21:42     ` [PATCH 6/13] v2 Use new per-location warning APIs in the C++ front end Martin Sebor
@ 2021-06-21 21:37       ` Martin Sebor
  2021-06-24  5:12       ` [PATCH " Jeff Law
  1 sibling, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-21 21:37 UTC (permalink / raw)
  To: gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571977.html

Looking for a review of the C++ front end changes to switch to the new
suppress_warning() API.

On 6/4/21 3:42 PM, Martin Sebor wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the C++
> front end with the new suppress_warning(), warning_suppressed_p(),
> and copy_warning() APIs.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PING][PATCH 7/13] v2 Use new per-location warning APIs in the FORTRAN front end
  2021-06-04 21:42     ` [PATCH 7/13] v2 Use new per-location warning APIs in the FORTRAN " Martin Sebor
@ 2021-06-21 21:42       ` Martin Sebor
  2021-06-24  5:05       ` [PATCH " Jeff Law
  1 sibling, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-21 21:42 UTC (permalink / raw)
  To: gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571978.html

Looking for an approval of the 99%  mechanical changes to switch
the FORTRAN front end from TREE_NO_WARNING to the new suppress_warning()
API.  There's only one place in this patch where a specific warning is
being suppressed -Wuninitialized.  All other calls suppress all
warnings as before, so I don't expect the patch to have any visible
changes.

On 6/4/21 3:42 PM, Martin Sebor wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the FORTRAN
> front end with the new suppress_warning() API.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PING][PATCH 9/13] v2 Use new per-location warning APIs in LTO
  2021-06-04 21:43     ` [PATCH 9/13] v2 Use new per-location warning APIs in LTO Martin Sebor
@ 2021-06-21 21:54       ` Martin Sebor
  2021-06-24  9:32         ` Richard Biener
  2021-06-24  5:03       ` [PATCH " Jeff Law
  1 sibling, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-06-21 21:54 UTC (permalink / raw)
  To: gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571980.html

Looking for a review of the LTO changes to switch TREE_NO_WARNING to
the suppress_warning() API.

On 6/4/21 3:43 PM, Martin Sebor wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the LTO
> front end with the new suppress_warning() API.  It adds a couple of
> FIXMEs that I plan to take care of in a follow up.


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PING][PATCH 10/13] v2 Use new per-location warning APIs in the middle end
  2021-06-04 21:43     ` [PATCH 10/13] v2 Use new per-location warning APIs in the middle end Martin Sebor
@ 2021-06-21 21:58       ` Martin Sebor
  2021-06-24  5:15       ` [PATCH " Jeff Law
  1 sibling, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-21 21:58 UTC (permalink / raw)
  To: gcc-patches

Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571981.html

Looking for a review of the middle end changes to replace the uses
of TREE_NO_WARNING and gimple_{get,set}_no_warning with the new
warning group APIs.  Most of the changes are a mechanical search
and replace kind, just a handful do ever-so-slightly more than
that, but none of those should have any observable effect.

On 6/4/21 3:43 PM, Martin Sebor wrote:
> The attached patch introduces declarations of the new
> suppress_warning(), warning_suppressed_p(), and copy_warning() APIs,
> and replaces the uses of TREE_NO_WARNING in the middle end with them.



^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)
  2021-06-04 21:41     ` [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups " Martin Sebor
  2021-06-21 21:34       ` [PING][PATCH " Martin Sebor
@ 2021-06-22 23:18       ` David Malcolm
  2021-06-22 23:28         ` David Malcolm
  1 sibling, 1 reply; 98+ messages in thread
From: David Malcolm @ 2021-06-22 23:18 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

On Fri, 2021-06-04 at 15:41 -0600, Martin Sebor wrote:
> The attached patch introduces the suppress_warning(),
> warning_suppressed(), and copy_no_warning() APIs without making
> use of them in the rest of GCC.  They are in three files:
> 
>    diagnostic-spec.{h,c}: Location-centric overloads.
>    warning-control.cc: Tree- and gimple*-centric overloads.
> 
> The location-centric overloads are suitable to use from the diagnostic
> subsystem.  The rest can be used from the front ends and the middle
> end.

[...snip...]

> +/* Return true if warning OPT is suppressed for decl/expression EXPR.
> +   By default tests the disposition for any warning.  */
> +
> +bool
> +warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
> +{
> +  const nowarn_spec_t *spec = get_nowarn_spec (expr);
> +
> +  if (!spec)
> +    return get_no_warning_bit (expr);
> +
> +  const nowarn_spec_t optspec (opt);
> +  bool dis = *spec & optspec;
> +  gcc_assert (get_no_warning_bit (expr) || !dis);
> +  return dis;

Looking through the patch, I don't like the use of "dis" for the "is
suppressed" bool, since...

[...snip...]

> +
> +/* Enable, or by default disable, a warning for the statement STMT.
> +   The wildcard OPT of -1 controls all warnings.  */

...I find the above comment to be confusingly worded due to the double-
negative.

If I'm reading your intent correctly, how about this wording:

/* Change the supression of warnings for statement STMT.
   OPT controls which warnings are affected.
   The wildcard OPT of -1 controls all warnings.
   If SUPP is true (the default), enable the suppression of the warnings.
   If SUPP is false, disable the suppression of the warnings.  */

...and rename "dis" to "supp".

Or have I misread the intent of the patch?

> +
> +void
> +suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
> +		  bool dis /* = true */)

> +{
> +  if (opt == no_warning)
> +    return;
> +
> +  const key_type_t key = convert_to_key (stmt);
> +
> +  dis = suppress_warning_at (key, opt, dis) || dis;
> +  set_no_warning_bit (stmt, dis);
> +}

[...snip...]

Dave




^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)
  2021-06-22 23:18       ` [PATCH " David Malcolm
@ 2021-06-22 23:28         ` David Malcolm
  2021-06-23 19:47           ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: David Malcolm @ 2021-06-22 23:28 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

On Tue, 2021-06-22 at 19:18 -0400, David Malcolm wrote:
> On Fri, 2021-06-04 at 15:41 -0600, Martin Sebor wrote:
> > The attached patch introduces the suppress_warning(),
> > warning_suppressed(), and copy_no_warning() APIs without making
> > use of them in the rest of GCC.  They are in three files:
> > 
> >    diagnostic-spec.{h,c}: Location-centric overloads.
> >    warning-control.cc: Tree- and gimple*-centric overloads.
> > 
> > The location-centric overloads are suitable to use from the
> > diagnostic
> > subsystem.  The rest can be used from the front ends and the middle
> > end.
> 
> [...snip...]
> 
> > +/* Return true if warning OPT is suppressed for decl/expression
> > EXPR.
> > +   By default tests the disposition for any warning.  */
> > +
> > +bool
> > +warning_suppressed_p (const_tree expr, opt_code opt /* =
> > all_warnings */)
> > +{
> > +  const nowarn_spec_t *spec = get_nowarn_spec (expr);
> > +
> > +  if (!spec)
> > +    return get_no_warning_bit (expr);
> > +
> > +  const nowarn_spec_t optspec (opt);
> > +  bool dis = *spec & optspec;
> > +  gcc_assert (get_no_warning_bit (expr) || !dis);
> > +  return dis;
> 
> Looking through the patch, I don't like the use of "dis" for the "is
> suppressed" bool, since...
> 
> [...snip...]
> 
> > +
> > +/* Enable, or by default disable, a warning for the statement STMT.
> > +   The wildcard OPT of -1 controls all warnings.  */
> 
> ...I find the above comment to be confusingly worded due to the double-
> negative.
> 
> If I'm reading your intent correctly, how about this wording:
> 
> /* Change the supression of warnings for statement STMT.
>    OPT controls which warnings are affected.
>    The wildcard OPT of -1 controls all warnings.
>    If SUPP is true (the default), enable the suppression of the
> warnings.
>    If SUPP is false, disable the suppression of the warnings.  */
> 
> ...and rename "dis" to "supp".
> 
> Or have I misread the intent of the patch?
> 
> > +
> > +void
> > +suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
> > +                 bool dis /* = true */)
> 
> > +{
> > +  if (opt == no_warning)
> > +    return;
> > +
> > +  const key_type_t key = convert_to_key (stmt);
> > +
> > +  dis = suppress_warning_at (key, opt, dis) || dis;
> > +  set_no_warning_bit (stmt, dis);
> > +}
> 
> [...snip...]

Also, I think I prefer having a separate entrypoints for the "all
warnings" case; on reading through the various patches I think that in
e.g.:

-	  TREE_NO_WARNING (*expr_p) = 1;
+	  suppress_warning (*expr_p);

I prefer:

          suppress_warnings (*expr_p);

(note the plural) since that way we can grep for them, and it seems
like better grammar to me.

Both entrypoints could be implemented by a static suppress_warning_1
internally if that makes it easier.

In that vein, "unsuppress_warning" seems far clearer to me that
"suppress_warning (FOO, false)"; IIRC there are very few uses of this
non-default arg (I couldn't find any in a quick look through the v2
kit).

Does this make sense?
Dave


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)
  2021-06-22 23:28         ` David Malcolm
@ 2021-06-23 19:47           ` Martin Sebor
  2021-06-24  5:26             ` Jeff Law
  2021-09-01 19:35             ` Thomas Schwinge
  0 siblings, 2 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-23 19:47 UTC (permalink / raw)
  To: David Malcolm, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 4621 bytes --]

On 6/22/21 5:28 PM, David Malcolm wrote:
> On Tue, 2021-06-22 at 19:18 -0400, David Malcolm wrote:
>> On Fri, 2021-06-04 at 15:41 -0600, Martin Sebor wrote:
>>> The attached patch introduces the suppress_warning(),
>>> warning_suppressed(), and copy_no_warning() APIs without making
>>> use of them in the rest of GCC.  They are in three files:
>>>
>>>     diagnostic-spec.{h,c}: Location-centric overloads.
>>>     warning-control.cc: Tree- and gimple*-centric overloads.
>>>
>>> The location-centric overloads are suitable to use from the
>>> diagnostic
>>> subsystem.  The rest can be used from the front ends and the middle
>>> end.
>>
>> [...snip...]
>>
>>> +/* Return true if warning OPT is suppressed for decl/expression
>>> EXPR.
>>> +   By default tests the disposition for any warning.  */
>>> +
>>> +bool
>>> +warning_suppressed_p (const_tree expr, opt_code opt /* =
>>> all_warnings */)
>>> +{
>>> +  const nowarn_spec_t *spec = get_nowarn_spec (expr);
>>> +
>>> +  if (!spec)
>>> +    return get_no_warning_bit (expr);
>>> +
>>> +  const nowarn_spec_t optspec (opt);
>>> +  bool dis = *spec & optspec;
>>> +  gcc_assert (get_no_warning_bit (expr) || !dis);
>>> +  return dis;
>>
>> Looking through the patch, I don't like the use of "dis" for the "is
>> suppressed" bool, since...

It's an argument to a a function, unlikely to confuse anyone.  But
I also don't think it's important enough to argue about so I changed
it along with the comment below.

>>
>> [...snip...]
>>
>>> +
>>> +/* Enable, or by default disable, a warning for the statement STMT.
>>> +   The wildcard OPT of -1 controls all warnings.  */
>>
>> ...I find the above comment to be confusingly worded due to the double-
>> negative.
>>
>> If I'm reading your intent correctly, how about this wording:
>>
>> /* Change the supression of warnings for statement STMT.
>>     OPT controls which warnings are affected.
>>     The wildcard OPT of -1 controls all warnings.
>>     If SUPP is true (the default), enable the suppression of the
>> warnings.
>>     If SUPP is false, disable the suppression of the warnings.  */
>>
>> ...and rename "dis" to "supp".
>>
>> Or have I misread the intent of the patch?
>>
>>> +
>>> +void
>>> +suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
>>> +                 bool dis /* = true */)
>>
>>> +{
>>> +  if (opt == no_warning)
>>> +    return;
>>> +
>>> +  const key_type_t key = convert_to_key (stmt);
>>> +
>>> +  dis = suppress_warning_at (key, opt, dis) || dis;
>>> +  set_no_warning_bit (stmt, dis);
>>> +}
>>
>> [...snip...]
> 
> Also, I think I prefer having a separate entrypoints for the "all
> warnings" case; on reading through the various patches I think that in
> e.g.:
> 
> -	  TREE_NO_WARNING (*expr_p) = 1;
> +	  suppress_warning (*expr_p);
> 
> I prefer:
> 
>            suppress_warnings (*expr_p);
> 
> (note the plural) since that way we can grep for them, and it seems
> like better grammar to me.
> 
> Both entrypoints could be implemented by a static suppress_warning_1
> internally if that makes it easier.
> 
> In that vein, "unsuppress_warning" seems far clearer to me that
> "suppress_warning (FOO, false)"; IIRC there are very few uses of this
> non-default arg (I couldn't find any in a quick look through the v2
> kit).
> 
> Does this make sense?

In my experience, names that differ only slightly (such as in just
one letter) tend to easily lead to frustrating mistakes.  The new
warning_suppressed_p() added in this patch also handles multiple
warnings (via a wildcard) and uses a singular form, and as do
the gimple_{get,set}no_warning() functions that are being replaced.
So I don't think the suggested change is needed or would be
an improvement.

Similarly, there is no gimple_unset_no_warning() today and I don't
think adding unsuppress_warning() is necessary or would add value,
especially since there are just a handful of callers that re-enable
warnings.  For the callers that might need to enable or disable
a warning based on some condition, it's more convenient to do so
in a single call then by having to call different functions based
the value of the condition.

In the attached patch I've changed the comment as you asked and
also renamed the dis argument to supp but kept the function names
the same.  I've also moved a few changes to tree.h from a later
patch to this one to let it stand alone and regtested it on its
own on x86_64-linux.  I'll plan to go ahead with this version
unless requestsfor substantive changes come up in the review of
the rest  of the changes.

Thanks
Martin

[-- Attachment #2: gcc-no-warning-1.diff --]
[-- Type: text/x-patch, Size: 17824 bytes --]

Add support for per-location warning groups.

gcc/ChangeLog:

	* Makefile.in (OBJS-libcommon): Add diagnostic-spec.o.
	* gengtype.c (open_base_files): Add diagnostic-spec.h.
	* diagnostic-spec.c: New file.
	* diagnostic-spec.h: New file.
	* tree.h (no_warning, all_warnings, suppress_warning_at): New
	declarations.
	* warning-control.cc: New file.

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index d32de22e4f2..3d8c2b94d70 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1698,6 +1698,7 @@ OBJS = \
 	vmsdbgout.o \
 	vr-values.o \
 	vtable-verify.o \
+	warning-control.o \
 	web.o \
 	wide-int.o \
 	wide-int-print.o \
@@ -1709,8 +1710,8 @@ OBJS = \
 
 # Objects in libcommon.a, potentially used by all host binaries and with
 # no target dependencies.
-OBJS-libcommon = diagnostic.o diagnostic-color.o diagnostic-show-locus.o \
-	diagnostic-format-json.o json.o \
+OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
+	diagnostic-show-locus.o diagnostic-format-json.o json.o \
 	edit-context.o \
 	pretty-print.o intl.o \
 	sbitmap.o \
@@ -2650,6 +2651,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/ipa-modref.h $(srcdir)/ipa-modref.c \
   $(srcdir)/ipa-modref-tree.h \
   $(srcdir)/signop.h \
+  $(srcdir)/diagnostic-spec.h $(srcdir)/diagnostic-spec.c \
   $(srcdir)/dwarf2out.h \
   $(srcdir)/dwarf2asm.c \
   $(srcdir)/dwarf2cfi.c \
diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
new file mode 100644
index 00000000000..9d1cb0b653b
--- /dev/null
+++ b/gcc/diagnostic-spec.c
@@ -0,0 +1,179 @@
+/* Functions to enable and disable individual warnings on an expression
+   and statement basis.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   Contributed by Martin Sebor <msebor@redhat.com>
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "bitmap.h"
+#include "tree.h"
+#include "cgraph.h"
+#include "hash-map.h"
+#include "diagnostic-spec.h"
+#include "pretty-print.h"
+#include "options.h"
+
+/* Initialize *THIS from warning option OPT.  */
+
+nowarn_spec_t::nowarn_spec_t (opt_code opt)
+{
+  /* Create a very simple mapping based on testing and experience.
+     It should become more refined with time. */
+  switch (opt)
+    {
+    case no_warning:
+      bits = 0;
+      break;
+
+    case all_warnings:
+      bits = -1;
+      break;
+
+      /* Flow-sensitive warnings about pointer problems issued by both
+	 front ends and the middle end.  */
+    case OPT_Waddress:
+    case OPT_Wnonnull:
+      bits = NW_NONNULL;
+      break;
+
+      /* Flow-sensitive warnings about arithmetic overflow issued by both
+	 front ends and the middle end.  */
+    case OPT_Woverflow:
+    case OPT_Wshift_count_negative:
+    case OPT_Wshift_count_overflow:
+    case OPT_Wstrict_overflow:
+      bits = NW_VFLOW;
+      break;
+
+      /* Lexical warnings issued by front ends.  */
+    case OPT_Wabi:
+    case OPT_Wlogical_op:
+    case OPT_Wparentheses:
+    case OPT_Wreturn_type:
+    case OPT_Wsizeof_array_div:
+    case OPT_Wstrict_aliasing:
+    case OPT_Wunused:
+    case OPT_Wunused_function:
+    case OPT_Wunused_but_set_variable:
+    case OPT_Wunused_variable:
+    case OPT_Wunused_but_set_parameter:
+      bits = NW_LEXICAL;
+      break;
+
+      /* Access warning group.  */
+    case OPT_Warray_bounds:
+    case OPT_Warray_bounds_:
+    case OPT_Wformat_overflow_:
+    case OPT_Wformat_truncation_:
+    case OPT_Wrestrict:
+    case OPT_Wstrict_aliasing_:
+    case OPT_Wstringop_overflow_:
+    case OPT_Wstringop_overread:
+    case OPT_Wstringop_truncation:
+      bits = NW_ACCESS;
+      break;
+
+      /* Initialization warning group.  */
+    case OPT_Winit_self:
+    case OPT_Wuninitialized:
+    case OPT_Wmaybe_uninitialized:
+	bits = NW_UNINIT;
+      break;
+
+    default:
+      /* A catchall group for everything else.  */
+      bits = NW_OTHER;
+    }
+}
+
+/* Map from location to its no-warning disposition.  */
+
+GTY(()) xint_hash_map_t *nowarn_map;
+
+/* Return the no-warning disposition for location LOC and option OPT
+   or for all/any otions by default.  */
+
+bool
+warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
+{
+  if (!nowarn_map)
+    return false;
+
+  if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
+    {
+      const nowarn_spec_t optspec (opt);
+      return *pspec & optspec;
+    }
+
+  return false;
+}
+
+ /* Change the supression of warnings at location LOC.
+    OPT controls which warnings are affected.
+    The wildcard OPT of -1 controls all warnings.
+    If SUPP is true (the default), enable the suppression of the warnings.
+    If SUPP is false, disable the suppression of the warnings.  */
+
+bool
+suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
+		     bool supp /* = true */)
+{
+  const nowarn_spec_t optspec (supp ? opt : opt_code ());
+
+  if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
+    {
+      if (supp)
+	{
+	  *pspec |= optspec;
+	  return true;
+	}
+
+      *pspec &= optspec;
+      if (*pspec)
+	return true;
+
+      nowarn_map->remove (loc);
+      return false;
+    }
+
+  if (!supp || opt == no_warning)
+    return false;
+
+  if (!nowarn_map)
+    nowarn_map = xint_hash_map_t::create_ggc (32);
+
+  nowarn_map->put (loc, optspec);
+  return true;
+}
+
+/* Copy the no-warning disposition from one location to another.  */
+
+void
+copy_warning (location_t to, location_t from)
+{
+  if (!nowarn_map)
+    return;
+
+  if (nowarn_spec_t *pspec = nowarn_map->get (from))
+    nowarn_map->put (to, *pspec);
+  else
+    nowarn_map->remove (to);
+}
diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
new file mode 100644
index 00000000000..62d9270ca6d
--- /dev/null
+++ b/gcc/diagnostic-spec.h
@@ -0,0 +1,140 @@
+/* Language-independent APIs to enable/disable per-location warnings.
+
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   Contributed by Martin Sebor <msebor@redhat.com>
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef DIAGNOSTIC_SPEC_H_INCLUDED
+#define DIAGNOSTIC_SPEC_H_INCLUDED
+
+#include "hash-map.h"
+
+/* A "bitset" of warning groups.  */
+
+struct nowarn_spec_t
+{
+  enum
+    {
+     /* Middle end warnings about invalid accesses.  */
+     NW_ACCESS = 1 << 0,
+     /* Front end/lexical warnings.  */
+     NW_LEXICAL = 1 << 1,
+     /* Warnings about null pointers.  */
+     NW_NONNULL = 1 << 2,
+     /* Warnings about uninitialized reads.  */
+     NW_UNINIT = 1 << 3,
+     /* Warnings about arithmetic overflow.  */
+     NW_VFLOW = 1 << 4,
+     /* All other unclassified warnings.  */
+     NW_OTHER = 1 << 5,
+     /* All groups of warnings.  */
+     NW_ALL = (NW_ACCESS | NW_LEXICAL | NW_NONNULL
+	       | NW_UNINIT | NW_VFLOW | NW_OTHER)
+   };
+
+  nowarn_spec_t (): bits () { }
+
+  nowarn_spec_t (opt_code);
+
+  /* Return the raw bitset.  */
+  operator unsigned() const
+  {
+    return bits;
+  }
+
+  /* Return true if the bitset is clear.  */
+  bool operator!() const
+  {
+    return !bits;
+  }
+
+  /* Return the inverse of the bitset.  */
+  nowarn_spec_t operator~() const
+  {
+    nowarn_spec_t res (*this);
+    res.bits &= ~NW_ALL;
+    return res;
+  }
+
+  /* Set *THIS to the bitwise OR of *THIS and RHS.  */
+  nowarn_spec_t& operator|= (const nowarn_spec_t &rhs)
+  {
+    bits |= rhs.bits;
+    return *this;
+  }
+
+  /* Set *THIS to the bitwise AND of *THIS and RHS.  */
+  nowarn_spec_t& operator&= (const nowarn_spec_t &rhs)
+  {
+    bits &= rhs.bits;
+    return *this;
+  }
+
+  /* Set *THIS to the bitwise exclusive OR of *THIS and RHS.  */
+  nowarn_spec_t& operator^= (const nowarn_spec_t &rhs)
+  {
+    bits ^= rhs.bits;
+    return *this;
+  }
+
+private:
+  /* Bitset of warning groups.  */
+  unsigned bits;
+};
+
+/* Return the bitwise OR of LHS and RHS.  */
+
+inline nowarn_spec_t
+operator| (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return nowarn_spec_t (lhs) |= rhs;
+}
+
+/* Return the bitwise AND of LHS and RHS.  */
+
+inline nowarn_spec_t
+operator& (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return nowarn_spec_t (lhs) &= rhs;
+}
+
+/* Return true if LHS is equal RHS.  */
+
+inline bool
+operator== (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return static_cast<unsigned>(lhs) == static_cast<unsigned>(rhs);
+}
+
+/* Return true if LHS is not equal RHS.  */
+
+inline bool
+operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
+{
+  return !(lhs == rhs);
+}
+
+typedef location_t key_type_t;
+typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
+typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
+
+/* A mapping from the location of an expression to the warning spec
+   set for it.  */
+extern GTY(()) xint_hash_map_t *nowarn_map;
+
+#endif // DIAGNOSTIC_SPEC_H_INCLUDED
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index b94e2f126ec..c1fa6d35c87 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1727,7 +1727,7 @@ open_base_files (void)
       "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
       "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h",
       "omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h", "symtab-thunks.h",
-      "symtab-clones.h",
+      "symtab-clones.h", "diagnostic-spec.h",
       NULL
     };
     const char *const *ifp;
diff --git a/gcc/tree.h b/gcc/tree.h
index 62b2de46479..973b84be9fc 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_TREE_H
 
 #include "tree-core.h"
+#include "options.h"
 
 /* Convert a target-independent built-in function code to a combined_fn.  */
 
@@ -6440,4 +6441,15 @@ public:
   operator location_t () const { return m_combined_loc; }
 };
 
+/* Code that doesn't refer to any warning.  Has no effect on suppression
+   functions.  */
+constexpr opt_code no_warning = opt_code ();
+/* Wildcard code that refers to all warnings.  */
+constexpr opt_code all_warnings = N_OPTS;
+
+/* Set the disposition for a warning (or all warnings by default)
+   at a location to disabled by default.  */
+extern bool suppress_warning_at (location_t, opt_code = all_warnings,
+				 bool = true);
+
 #endif  /* GCC_TREE_H  */
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
new file mode 100644
index 00000000000..ec8ed232763
--- /dev/null
+++ b/gcc/warning-control.cc
@@ -0,0 +1,238 @@
+/* Functions to enable and disable individual warnings on an expression
+   and statement basis.
+
+   Copyright (C) 2021 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 3, or (at your option) any later
+   version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "bitmap.h"
+#include "tree.h"
+#include "gimple.h"
+#include "cgraph.h"
+#include "hash-map.h"
+#include "diagnostic-spec.h"
+
+/* Return the no-warning bit for EXPR.  */
+
+static inline bool
+get_no_warning_bit (const_tree expr)
+{
+  return expr->base.nowarning_flag;
+}
+
+/* Return the no-warning bit for statement STMT.  */
+
+static inline bool
+get_no_warning_bit (const gimple *stmt)
+{
+  return stmt->no_warning;
+}
+
+/* Set the no-warning bit for EXPR to VALUE.  */
+
+static inline void
+set_no_warning_bit (tree expr, bool value)
+{
+  expr->base.nowarning_flag = value;
+}
+
+/* Set the no-warning bit for statement STMT to VALUE.  */
+
+static inline void
+set_no_warning_bit (gimple *stmt, bool value)
+{
+  stmt->no_warning = value;
+}
+
+/* Return EXPR location or zero.  */
+
+static inline key_type_t
+convert_to_key (const_tree expr)
+{
+  if (DECL_P (expr))
+    return DECL_SOURCE_LOCATION (expr);
+  if (EXPR_P (expr))
+    return EXPR_LOCATION (expr);
+  return 0;
+}
+
+/* Return STMT location (may be zero).  */
+
+static inline key_type_t
+convert_to_key (const gimple *stmt)
+{
+  return gimple_location (stmt);
+}
+
+/* Return the no-warning bitmap for decl/expression EXPR.  */
+
+static nowarn_spec_t *
+get_nowarn_spec (const_tree expr)
+{
+  const key_type_t key = convert_to_key (expr);
+
+  if (!get_no_warning_bit (expr) || !key)
+    return NULL;
+
+  return nowarn_map ? nowarn_map->get (key) : NULL;
+}
+
+/* Return the no-warning bitmap for stateemt STMT.  */
+
+static nowarn_spec_t *
+get_nowarn_spec (const gimple *stmt)
+{
+  const key_type_t key = convert_to_key (stmt);
+
+  if (!get_no_warning_bit (stmt))
+    return NULL;
+
+  return nowarn_map ? nowarn_map->get (key) : NULL;
+}
+
+/* Return true if warning OPT is suppressed for decl/expression EXPR.
+   By default tests the disposition for any warning.  */
+
+bool
+warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
+{
+  const nowarn_spec_t *spec = get_nowarn_spec (expr);
+
+  if (!spec)
+    return get_no_warning_bit (expr);
+
+  const nowarn_spec_t optspec (opt);
+  bool dis = *spec & optspec;
+  gcc_assert (get_no_warning_bit (expr) || !dis);
+  return dis;
+}
+
+/* Return true if warning OPT is suppressed for statement STMT.
+   By default tests the disposition for any warning.  */
+
+bool
+warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */)
+{
+  const nowarn_spec_t *spec = get_nowarn_spec (stmt);
+
+  if (!spec)
+    /* Fall back on the single no-warning bit.  */
+    return get_no_warning_bit (stmt);
+
+  const nowarn_spec_t optspec (opt);
+  bool dis = *spec & optspec;
+  gcc_assert (get_no_warning_bit (stmt) || !dis);
+  return dis;
+}
+
+/* Enable, or by default disable, a warning for the expression.
+   The wildcard OPT of -1 controls all warnings.  */
+
+void
+suppress_warning (tree expr, opt_code opt /* = all_warnings */,
+		  bool supp /* = true */)
+{
+  if (opt == no_warning)
+    return;
+
+  const key_type_t key = convert_to_key (expr);
+
+  supp = suppress_warning_at (key, opt, supp) || supp;
+  set_no_warning_bit (expr, supp);
+}
+
+/* Enable, or by default disable, a warning for the statement STMT.
+   The wildcard OPT of -1 controls all warnings.  */
+
+void
+suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
+		  bool supp /* = true */)
+{
+  if (opt == no_warning)
+    return;
+
+  const key_type_t key = convert_to_key (stmt);
+
+  supp = suppress_warning_at (key, opt, supp) || supp;
+  set_no_warning_bit (stmt, supp);
+}
+
+/* Copy the warning disposition mapping between an expression and/or
+   a statement.  */
+
+template <class ToType, class FromType>
+void copy_warning (ToType to, FromType from)
+{
+  const key_type_t to_key = convert_to_key (to);
+
+  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
+    {
+      /* If there's an entry in the map the no-warning bit must be set.  */
+      gcc_assert (get_no_warning_bit (from));
+
+      if (!nowarn_map)
+	nowarn_map = xint_hash_map_t::create_ggc (32);
+
+      nowarn_map->put (to_key, *from_map);
+      set_no_warning_bit (to, true);
+    }
+  else
+    {
+      if (nowarn_map)
+	nowarn_map->remove (to_key);
+
+      /* The no-warning bit might be set even if there's no entry
+	 in the map.  */
+      set_no_warning_bit (to, get_no_warning_bit (from));
+    }
+}
+
+/* Copy the warning disposition mapping from one expression to another.  */
+
+void
+copy_warning (tree to, const_tree from)
+{
+  copy_warning<tree, const_tree>(to, from);
+}
+
+/* Copy the warning disposition mapping from a statement to an expression.  */
+
+void
+copy_warning (tree to, const gimple *from)
+{
+  copy_warning<tree, const gimple *>(to, from);
+}
+
+/* Copy the warning disposition mapping from an expression to a statement.  */
+
+void
+copy_warning (gimple *to, const_tree from)
+{
+  copy_warning<gimple *, const_tree>(to, from);
+}
+
+/* Copy the warning disposition mapping from one statement to another.  */
+
+void
+copy_warning (gimple *to, const gimple *from)
+{
+  copy_warning<gimple *, const gimple *>(to, from);
+}

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 13/13] v2 Add regression tests for PR 74765 and 74762
  2021-06-04 21:43     ` [PATCH 13/13] v2 Add regression tests for PR 74765 and 74762 Martin Sebor
@ 2021-06-24  4:56       ` Jeff Law
  2021-06-28 21:23         ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: Jeff Law @ 2021-06-24  4:56 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:43 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch adds regression tests for two closely related bugs
> resolved by the patch series.
>
> gcc-no-warning-tests.diff
>
> Regression tests for TREE_NO_WARNING enhancement to warning groups.
>
> PR middle-end/74765 - missing uninitialized warning (parenthesis, TREE_NO_WARNING abuse)
> PR middle-end/74762 - [9/10/11/12 Regression] missing uninitialized warning (C++, parenthesized expr, TREE_NO_WARNING)
>
> gcc/testsuite/ChangeLog:
>
> 	* g++.dg/uninit-pr74762.C: New test.
> 	* g++.dg/warn/uninit-pr74765.C: Same.
>
> diff --git a/gcc/testsuite/g++.dg/uninit-pr74762.C b/gcc/testsuite/g++.dg/uninit-pr74762.C
This is OK once the prereqs are all approved.
jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 12/13] v2 Remove TREE_NO_WARNING and gimple*no_warning* APIs
  2021-06-04 21:43     ` [PATCH 12/13] v2 Remove TREE_NO_WARNING and gimple*no_warning* APIs Martin Sebor
@ 2021-06-24  5:01       ` Jeff Law
  0 siblings, 0 replies; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:01 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:43 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch removes the definitions of the TREE_NO_WARNING macro
> and the gimple_get_no_warning_p() and gimple_set_no_warning() functions.
>
> gcc-no-warning-remove-api.diff
>
> Remove legacy TREE_NO_WARNING amd gimple_*no_warning* APIs.
>
> gcc/ChangeLog:
>
> 	* tree.h (TREE_NO_WARNING): Remove.
> 	* gimple.h (gimple_no_warning_p): Remove.
> 	(gimple_suppress_warning): Same.
Is there any value in marking these as poisoned?  We've done that for 
some macros in the past, but we haven't been consistent with it.    If 
you think it's worth poisoning, the place to do that is system.h.

Approved with or without poisoning once prereqs are approved.

jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 11/13] v2 Use new per-location warning APIs in the Objective-C front end
  2021-06-04 21:43     ` [PATCH 11/13] v2 Use new per-location warning APIs in the Objective-C front end Martin Sebor
@ 2021-06-24  5:02       ` Jeff Law
  2021-06-28 21:22         ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:02 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:43 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in
> the Objective-C front end with the new suppress_warning(),
> warning_suppressed_p(), and copy_warning() APIs.
>
> gcc-no-warning-objc.diff
>
> Add support for per-location warning groups.
>
> gcc/objc/ChangeLog:
>
> 	* objc-act.c (objc_maybe_build_modify_expr): Replace direct uses
> 	of TREE_NO_WARNING with warning_suppressed_p, and suppress_warning.
> 	(objc_build_incr_expr_for_property_ref): Same.
> 	(objc_build_struct): Same.
> 	(synth_module_prologue): Same.
> 	* objc-gnu-runtime-abi-01.c (gnu_runtime_01_initialize): Same.
> 	* objc-next-runtime-abi-01.c (next_runtime_01_initialize): Same.
> 	* objc-next-runtime-abi-02.c (next_runtime_02_initialize): Same.
OK once prereqs are approved.

Jeff

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 9/13] v2 Use new per-location warning APIs in LTO
  2021-06-04 21:43     ` [PATCH 9/13] v2 Use new per-location warning APIs in LTO Martin Sebor
  2021-06-21 21:54       ` [PING][PATCH " Martin Sebor
@ 2021-06-24  5:03       ` Jeff Law
  1 sibling, 0 replies; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:03 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:43 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the LTO
> front end with the new suppress_warning() API.  It adds a couple of
> FIXMEs that I plan to take care of in a follow up.
>
> gcc-no-warning-lto.diff
>
> Add support for per-location warning groups.
>
> gcc/lto/ChangeLog:
>
> 	* gimple-streamer-out.c (output_gimple_stmt): Same.
> 	* lto-common.c (compare_tree_sccs_1): Expand use of TREE_NO_WARNING.
> 	* lto-streamer-out.c (hash_tree): Same.
> 	* tree-streamer-in.c (unpack_ts_base_value_fields): Same.
> 	* tree-streamer-out.c (pack_ts_base_value_fields): Same.
OK once prereqs are approved.

jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 8/13] v2 Use new per-location warning APIs in libcc1
  2021-06-04 21:42     ` [PATCH 8/13] v2 Use new per-location warning APIs in libcc1 Martin Sebor
@ 2021-06-24  5:04       ` Jeff Law
  2021-06-28 21:22         ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:04 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:42 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in libcc1 with
> the new suppress_warning() API.
>
> gcc-no-warning-libcc1.diff
>
> Add support for per-location warning groups.
>
> libcc1/ChangeLog:
>
> 	* libcp1plugin.cc (record_decl_address): Replace a direct use
> 	of TREE_NO_WARNING with suppress_warning.
OK once prereqs are approved.
jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 7/13] v2 Use new per-location warning APIs in the FORTRAN front end
  2021-06-04 21:42     ` [PATCH 7/13] v2 Use new per-location warning APIs in the FORTRAN " Martin Sebor
  2021-06-21 21:42       ` [PING][PATCH " Martin Sebor
@ 2021-06-24  5:05       ` Jeff Law
  2021-06-28 21:21         ` Martin Sebor
  1 sibling, 1 reply; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:05 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:42 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the FORTRAN
> front end with the new suppress_warning() API.
>
> gcc-no-warning-fortran.diff
>
> Add support for per-location warning groups.
>
> gcc/fortran/ChangeLog:
>
> 	* trans-array.c (trans_array_constructor): Replace direct uses
> 	of TREE_NO_WARNING with warning_suppressed_p, and suppress_warning.
> 	* trans-decl.c (gfc_build_qualified_array): Same.
> 	(gfc_build_dummy_array_decl): Same.
> 	(generate_local_decl): Same.
> 	(gfc_generate_function_code): Same.
> 	* trans-openmp.c (gfc_omp_clause_default_ctor): Same.
> 	(gfc_omp_clause_copy_ctor): Same.
> 	* trans-types.c (get_dtype_type_node): Same.
> 	(gfc_get_desc_dim_type): Same.
> 	(gfc_get_array_descriptor_base): Same.
> 	(gfc_get_caf_vector_type): Same.
> 	(gfc_get_caf_reference_type): Same.
> 	* trans.c (gfc_create_var_np): Same.
OK once prereqs are approved.
jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 5/13] v2 Use new per-location warning APIs in the RL78 back end
  2021-06-04 21:42     ` [PATCH 5/13] v2 Use new per-location warning APIs in the RL78 back end Martin Sebor
@ 2021-06-24  5:06       ` Jeff Law
  0 siblings, 0 replies; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:06 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:42 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the RL78
> back end with the new suppress_warning() and warning_suppressed_p()
> APIs.
>
> gcc-no-warning-rl78.diff
>
> Add support for per-location warning groups.
>
> gcc/ChangeLog:
>
> 	* config/rl78/rl78.c (rl78_handle_naked_attribute): Replace a direct
> 	use of TREE_NO_WARNING with suppress_warning.
OK once prereqs are approved.

Jeff

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 4/13] v2 Use new per-location warning APIs in C family code
  2021-06-04 21:42     ` [PATCH 4/13] v2 Use new per-location warning APIs in C family code Martin Sebor
  2021-06-21 21:35       ` [PING][PATCH " Martin Sebor
@ 2021-06-24  5:06       ` Jeff Law
  2021-06-25  1:36         ` Martin Sebor
  1 sibling, 1 reply; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:06 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:42 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the shared
> C family front end with the new suppress_warning(),
> warning_suppressed_p(), and copy_warning() APIs.
>
> gcc-no-warning-c-family.diff
>
> Add support for per-location warning groups.
>
> gcc/c-family/ChangeLog:
>
> 	* c-common.c (c_wrap_maybe_const): Remove TREE_NO_WARNING.
> 	(c_common_truthvalue_conversion): Replace direct uses of
> 	TREE_NO_WARNING with warning_suppressed_p, suppress_warning, and
> 	copy_no_warning.
> 	(check_function_arguments_recurse): Same.
> 	* c-gimplify.c (c_gimplify_expr): Same.
> 	* c-warn.c (overflow_warning): Same.
> 	(warn_logical_operator): Same.
> 	(warn_if_unused_value): Same.
> 	(do_warn_unused_parameter): Same.
OK once prereqs are approved.
jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 2/13] v2 Use new per-location warning APIs in Ada.
  2021-06-04 21:41     ` [PATCH 2/13] v2 Use new per-location warning APIs in Ada Martin Sebor
@ 2021-06-24  5:07       ` Jeff Law
  2021-06-28 21:20         ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:07 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:41 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the Ada front
> end with the new suppress_warning(), warning_suppressed_p(), and
> copy_warning() APIs.
>
> gcc-no-warning-ada.diff
>
> Add support for per-location warning groups.
>
> gcc/ada/ChangeLog:
>
> 	* gcc-interface/trans.c (Handled_Sequence_Of_Statements_to_gnu):
> 	Replace TREE_NO_WARNING with suppress_warning.
> 	(gnat_gimplify_expr): Same.
> 	* gcc-interface/utils.c (gnat_pushdecl): Same.
OK once prereqs are approved.
jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 3/13] v2 Use new per-location warning APIs in C front end
  2021-06-04 21:41     ` [PATCH 3/13] v2 Use new per-location warning APIs in C front end Martin Sebor
  2021-06-21 21:35       ` [PING][PATCH " Martin Sebor
@ 2021-06-24  5:09       ` Jeff Law
  2021-06-25  1:35         ` Martin Sebor
  1 sibling, 1 reply; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:09 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:41 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the C front
> end with the new suppress_warning(), warning_suppressed_p(), and
> copy_warning() APIs.
>
> gcc-no-warning-c.diff
>
> Add support for per-location warning groups.
>
> gcc/c/ChangeLog:
>
> 	* c-decl.c (pop_scope): Replace direct uses of TREE_NO_WARNING with
> 	warning_suppressed_p, suppress_warning, and copy_no_warning.
> 	(diagnose_mismatched_decls): Same.
> 	(duplicate_decls): Same.
> 	(grokdeclarator): Same.
> 	(finish_function): Same.
> 	(c_write_global_declarations_1): Same.
> 	* c-fold.c (c_fully_fold_internal): Same.
> 	* c-parser.c (c_parser_expr_no_commas): Same.
> 	(c_parser_postfix_expression): Same.
> 	* c-typeck.c (array_to_pointer_conversion): Same.
> 	(function_to_pointer_conversion): Same.
> 	(default_function_array_conversion): Same.
> 	(convert_lvalue_to_rvalue): Same.
> 	(default_conversion): Same.
> 	(build_indirect_ref): Same.
> 	(build_function_call_vec): Same.
> 	(build_atomic_assign): Same.
> 	(build_unary_op): Same.
> 	(c_finish_return): Same.
> 	(emit_side_effect_warnings): Same.
> 	(c_finish_stmt_expr): Same.
> 	(c_omp_clause_copy_ctor): Same.
OK once prereqs are approved.
jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 6/13] v2 Use new per-location warning APIs in the C++ front end
  2021-06-04 21:42     ` [PATCH 6/13] v2 Use new per-location warning APIs in the C++ front end Martin Sebor
  2021-06-21 21:37       ` [PING][PATCH " Martin Sebor
@ 2021-06-24  5:12       ` Jeff Law
  2021-06-25  1:38         ` Martin Sebor
  1 sibling, 1 reply; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:12 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:42 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch replaces the uses of TREE_NO_WARNING in the C++
> front end with the new suppress_warning(), warning_suppressed_p(),
> and copy_warning() APIs.
>
> gcc-no-warning-cp.diff
>
> Add support for per-location warning groups.
>
> 	* call.c (build_over_call): Replace direct uses of TREE_NO_WARNING
> 	with warning_suppressed_p, suppress_warning, and copy_no_warning, or
> 	nothing if not necessary.
> 	(set_up_extended_ref_temp): Same.
> 	* class.c (layout_class_type): Same.
> 	* constraint.cc (constraint_satisfaction_value): Same.
> 	* coroutines.cc (finish_co_await_expr): Same.
> 	(finish_co_yield_expr): Same.
> 	(finish_co_return_stmt): Same.
> 	(build_actor_fn): Same.
> 	(coro_rewrite_function_body): Same.
> 	(morph_fn_to_coro): Same.
> 	* cp-gimplify.c (genericize_eh_spec_block): Same.
> 	(gimplify_expr_stmt): Same.
> 	(cp_genericize_r): Same.
> 	(cp_fold): Same.
> 	* cp-ubsan.c (cp_ubsan_instrument_vptr): Same.
> 	* cvt.c (cp_fold_convert): Same.
> 	(convert_to_void): Same.
> 	* decl.c (wrapup_namespace_globals): Same.
> 	(grokdeclarator): Same.
> 	(finish_function): Same.
> 	(require_deduced_type): Same.
> 	* decl2.c (no_linkage_error): Same.
> 	(c_parse_final_cleanups): Same.
> 	* except.c (expand_end_catch_block): Same.
> 	* init.c (build_new_1): Same.
> 	(build_new): Same.
> 	(build_vec_delete_1): Same.
> 	(build_vec_init): Same.
> 	(build_delete): Same.
> 	* method.c (defaultable_fn_check): Same.
> 	* parser.c (cp_parser_fold_expression): Same.
> 	(cp_parser_primary_expression): Same.
> 	* pt.c (push_tinst_level_loc): Same.
> 	(tsubst_copy): Same.
> 	(tsubst_omp_udr): Same.
> 	(tsubst_copy_and_build): Same.
> 	* rtti.c (build_if_nonnull): Same.
> 	* semantics.c (maybe_convert_cond): Same.
> 	(finish_return_stmt): Same.
> 	(finish_parenthesized_expr): Same.
> 	(cp_check_omp_declare_reduction): Same.
> 	* tree.c (build_cplus_array_type): Same.
> 	* typeck.c (build_ptrmemfunc_access_expr): Same.
> 	(cp_build_indirect_ref_1): Same.
> 	(cp_build_function_call_vec): Same.
> 	(warn_for_null_address): Same.
> 	(cp_build_binary_op): Same.
> 	(unary_complex_lvalue): Same.
> 	(cp_build_modify_expr): Same.
> 	(build_x_modify_expr): Same.
> 	(convert_for_assignment): Same.
OK once prereqs are approved.  Note that I wouldn't be terribly 
surprised if changes in the C++ front-end over the last couple weeks 
create a conflict.  Consider resolution of such conflicts (in the C++ 
front-end or elsewhere) or removing additional uses of TREE_NO_WARNING 
that have crept in over the last two weeks pre-approved.

Jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 10/13] v2 Use new per-location warning APIs in the middle end
  2021-06-04 21:43     ` [PATCH 10/13] v2 Use new per-location warning APIs in the middle end Martin Sebor
  2021-06-21 21:58       ` [PING][PATCH " Martin Sebor
@ 2021-06-24  5:15       ` Jeff Law
  2021-06-25  1:40         ` Martin Sebor
  1 sibling, 1 reply; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:15 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches



On 6/4/2021 3:43 PM, Martin Sebor via Gcc-patches wrote:
> The attached patch introduces declarations of the new
> suppress_warning(), warning_suppressed_p(), and copy_warning() APIs,
> and replaces the uses of TREE_NO_WARNING in the middle end with them.
>
> gcc-no-warning-middle-end.diff
>
> Add support for per-location warning groups.
>
> gcc/ChangeLog:
>
> 	* builtins.c (warn_string_no_nul): Replace uses of TREE_NO_WARNING,
> 	gimple_no_warning_p and gimple_set_no_warning with
> 	warning_suppressed_p, and suppress_warning.
> 	(c_strlen): Same.
> 	(maybe_warn_for_bound): Same.
> 	(warn_for_access): Same.
> 	(check_access): Same.
> 	(expand_builtin_strncmp): Same.
> 	(fold_builtin_varargs): Same.
> 	* calls.c (maybe_warn_nonstring_arg): Same.
> 	(maybe_warn_rdwr_sizes): Same.
> 	* cfgexpand.c (expand_call_stmt): Same.
> 	* cgraphunit.c (check_global_declaration): Same.
> 	* fold-const.c (fold_undefer_overflow_warnings): Same.
> 	(fold_truth_not_expr): Same.
> 	(fold_unary_loc): Same.
> 	(fold_checksum_tree): Same.
> 	* gengtype.c (open_base_files): Same.
> 	* gimple-array-bounds.cc (array_bounds_checker::check_array_ref): Same.
> 	(array_bounds_checker::check_mem_ref): Same.
> 	(array_bounds_checker::check_addr_expr): Same.
> 	(array_bounds_checker::check_array_bounds): Same.
> 	* gimple-expr.c (copy_var_decl): Same.
> 	* gimple-fold.c (gimple_fold_builtin_strcpy): Same.
> 	(gimple_fold_builtin_strncat): Same.
> 	(gimple_fold_builtin_stxcpy_chk): Same.
> 	(gimple_fold_builtin_stpcpy): Same.
> 	(gimple_fold_builtin_sprintf): Same.
> 	(fold_stmt_1): Same.
> 	* gimple-ssa-isolate-paths.c (diag_returned_locals): Same.
> 	* gimple-ssa-nonnull-compare.c (do_warn_nonnull_compare): Same.
> 	* gimple-ssa-sprintf.c (handle_printf_call): Same.
> 	* gimple-ssa-store-merging.c (imm_store_chain_info::output_merged_store): Same.
> 	* gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same.
> 	(maybe_diag_access_bounds): Same.
> 	(check_call): Same.
> 	(check_bounds_or_overlap): Same.
> 	* gimple.c (gimple_build_call_from_tree): Same.
> 	* gimplify.c (gimplify_return_expr): Same.
> 	(gimplify_cond_expr): Same.
> 	(gimplify_modify_expr_complex_part): Same.
> 	(gimplify_modify_expr): Same.
> 	(gimple_push_cleanup): Same.
> 	(gimplify_expr): Same.
> 	* omp-expand.c (expand_omp_for_generic): Same.
> 	(expand_omp_taskloop_for_outer): Same.
> 	* omp-low.c (lower_rec_input_clauses): Same.
> 	(lower_lastprivate_clauses): Same.
> 	(lower_send_clauses): Same.
> 	(lower_omp_target): Same.
> 	* tree-cfg.c (pass_warn_function_return::execute): Same.
> 	* tree-complex.c (create_one_component_var): Same.
> 	* tree-inline.c (remap_gimple_op_r): Same.
> 	(copy_tree_body_r): Same.
> 	(declare_return_variable): Same.
> 	(expand_call_inline): Same.
> 	* tree-nested.c (lookup_field_for_decl): Same.
> 	* tree-sra.c (create_access_replacement): Same.
> 	(generate_subtree_copies): Same.
> 	* tree-ssa-ccp.c (pass_post_ipa_warn::execute): Same.
> 	* tree-ssa-forwprop.c (combine_cond_expr_cond): Same.
> 	* tree-ssa-loop-ch.c (ch_base::copy_headers): Same.
> 	* tree-ssa-loop-im.c (execute_sm): Same.
> 	* tree-ssa-phiopt.c (cond_store_replacement): Same.
> 	* tree-ssa-strlen.c (maybe_warn_overflow): Same.
> 	(handle_builtin_strcpy): Same.
> 	(maybe_diag_stxncpy_trunc): Same.
> 	(handle_builtin_stxncpy_strncat): Same.
> 	(handle_builtin_strcat): Same.
> 	* tree-ssa-uninit.c (get_no_uninit_warning): Same.
> 	(set_no_uninit_warning): Same.
> 	(uninit_undefined_value_p): Same.
> 	(warn_uninit): Same.
> 	(maybe_warn_operand): Same.
> 	* tree-vrp.c (compare_values_warnv): Same.
> 	* vr-values.c (vr_values::extract_range_for_var_from_comparison_expr): Same.
> 	(test_for_singularity): Same.
>
> 	* gimple.h (warning_suppressed_p): New function.
> 	(suppress_warning): Same.
> 	(copy_no_warning): Same.
> 	(gimple_set_block): Call gimple_set_location.
> 	(gimple_set_location): Call copy_warning.
> 	* tree.h (no_warning, all_warnings): New constants.
> 	(warning_suppressed_p): New function.
> 	(suppress_warning): Same.
> 	(copy_no_warning): Same.
OK once prereqs are approved.

jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)
  2021-06-23 19:47           ` Martin Sebor
@ 2021-06-24  5:26             ` Jeff Law
  2021-06-25  1:34               ` Martin Sebor
  2021-09-01 19:35             ` Thomas Schwinge
  1 sibling, 1 reply; 98+ messages in thread
From: Jeff Law @ 2021-06-24  5:26 UTC (permalink / raw)
  To: Martin Sebor, David Malcolm, gcc-patches



On 6/23/2021 1:47 PM, Martin Sebor via Gcc-patches wrote:
> On 6/22/21 5:28 PM, David Malcolm wrote:
>> On Tue, 2021-06-22 at 19:18 -0400, David Malcolm wrote:
>>> On Fri, 2021-06-04 at 15:41 -0600, Martin Sebor wrote:
>>>> The attached patch introduces the suppress_warning(),
>>>> warning_suppressed(), and copy_no_warning() APIs without making
>>>> use of them in the rest of GCC.  They are in three files:
>>>>
>>>>     diagnostic-spec.{h,c}: Location-centric overloads.
>>>>     warning-control.cc: Tree- and gimple*-centric overloads.
>>>>
>>>> The location-centric overloads are suitable to use from the
>>>> diagnostic
>>>> subsystem.  The rest can be used from the front ends and the middle
>>>> end.
>>>
>>> [...snip...]
>>>
>>>> +/* Return true if warning OPT is suppressed for decl/expression
>>>> EXPR.
>>>> +   By default tests the disposition for any warning.  */
>>>> +
>>>> +bool
>>>> +warning_suppressed_p (const_tree expr, opt_code opt /* =
>>>> all_warnings */)
>>>> +{
>>>> +  const nowarn_spec_t *spec = get_nowarn_spec (expr);
>>>> +
>>>> +  if (!spec)
>>>> +    return get_no_warning_bit (expr);
>>>> +
>>>> +  const nowarn_spec_t optspec (opt);
>>>> +  bool dis = *spec & optspec;
>>>> +  gcc_assert (get_no_warning_bit (expr) || !dis);
>>>> +  return dis;
>>>
>>> Looking through the patch, I don't like the use of "dis" for the "is
>>> suppressed" bool, since...
>
> It's an argument to a a function, unlikely to confuse anyone.  But
> I also don't think it's important enough to argue about so I changed
> it along with the comment below.
>
>>>
>>> [...snip...]
>>>
>>>> +
>>>> +/* Enable, or by default disable, a warning for the statement STMT.
>>>> +   The wildcard OPT of -1 controls all warnings.  */
>>>
>>> ...I find the above comment to be confusingly worded due to the double-
>>> negative.
>>>
>>> If I'm reading your intent correctly, how about this wording:
>>>
>>> /* Change the supression of warnings for statement STMT.
>>>     OPT controls which warnings are affected.
>>>     The wildcard OPT of -1 controls all warnings.
>>>     If SUPP is true (the default), enable the suppression of the
>>> warnings.
>>>     If SUPP is false, disable the suppression of the warnings.  */
>>>
>>> ...and rename "dis" to "supp".
>>>
>>> Or have I misread the intent of the patch?
>>>
>>>> +
>>>> +void
>>>> +suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
>>>> +                 bool dis /* = true */)
>>>
>>>> +{
>>>> +  if (opt == no_warning)
>>>> +    return;
>>>> +
>>>> +  const key_type_t key = convert_to_key (stmt);
>>>> +
>>>> +  dis = suppress_warning_at (key, opt, dis) || dis;
>>>> +  set_no_warning_bit (stmt, dis);
>>>> +}
>>>
>>> [...snip...]
>>
>> Also, I think I prefer having a separate entrypoints for the "all
>> warnings" case; on reading through the various patches I think that in
>> e.g.:
>>
>> -      TREE_NO_WARNING (*expr_p) = 1;
>> +      suppress_warning (*expr_p);
>>
>> I prefer:
>>
>>            suppress_warnings (*expr_p);
>>
>> (note the plural) since that way we can grep for them, and it seems
>> like better grammar to me.
>>
>> Both entrypoints could be implemented by a static suppress_warning_1
>> internally if that makes it easier.
>>
>> In that vein, "unsuppress_warning" seems far clearer to me that
>> "suppress_warning (FOO, false)"; IIRC there are very few uses of this
>> non-default arg (I couldn't find any in a quick look through the v2
>> kit).
>>
>> Does this make sense?
>
> In my experience, names that differ only slightly (such as in just
> one letter) tend to easily lead to frustrating mistakes.  The new
> warning_suppressed_p() added in this patch also handles multiple
> warnings (via a wildcard) and uses a singular form, and as do
> the gimple_{get,set}no_warning() functions that are being replaced.
> So I don't think the suggested change is needed or would be
> an improvement.
>
> Similarly, there is no gimple_unset_no_warning() today and I don't
> think adding unsuppress_warning() is necessary or would add value,
> especially since there are just a handful of callers that re-enable
> warnings.  For the callers that might need to enable or disable
> a warning based on some condition, it's more convenient to do so
> in a single call then by having to call different functions based
> the value of the condition.
>
> In the attached patch I've changed the comment as you asked and
> also renamed the dis argument to supp but kept the function names
> the same.  I've also moved a few changes to tree.h from a later
> patch to this one to let it stand alone and regtested it on its
> own on x86_64-linux.  I'll plan to go ahead with this version
> unless requestsfor substantive changes come up in the review of
> the rest  of the changes.
>
> Thanks
> Martin
>
> gcc-no-warning-1.diff
>
> Add support for per-location warning groups.
>
> gcc/ChangeLog:
>
> 	* Makefile.in (OBJS-libcommon): Add diagnostic-spec.o.
> 	* gengtype.c (open_base_files): Add diagnostic-spec.h.
> 	* diagnostic-spec.c: New file.
> 	* diagnostic-spec.h: New file.
> 	* tree.h (no_warning, all_warnings, suppress_warning_at): New
> 	declarations.
> 	* warning-control.cc: New file.
>
> diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
> new file mode 100644
> index 00000000000..62d9270ca6d
> --- /dev/null
> +++ b/gcc/diagnostic-spec.h
> @@ -0,0 +1,140 @@
> +/* Language-independent APIs to enable/disable per-location warnings.
> +
> +   Copyright (C) 2021 Free Software Foundation, Inc.
> +   Contributed by Martin Sebor <msebor@redhat.com>
> +
> +   This file is part of GCC.
> +
> +   GCC is free software; you can redistribute it and/or modify it under
> +   the terms of the GNU General Public License as published by the Free
> +   Software Foundation; either version 3, or (at your option) any later
> +   version.
> +
> +   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +   WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +   for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with GCC; see the file COPYING3.  If not see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef DIAGNOSTIC_SPEC_H_INCLUDED
> +#define DIAGNOSTIC_SPEC_H_INCLUDED
> +
> +#include "hash-map.h"
> +
> +/* A "bitset" of warning groups.  */
> +
> +struct nowarn_spec_t
Should probably be "class" not "struct".  Though I don't think we're 
necessarily consistent with this.
> +private:
> +  /* Bitset of warning groups.  */
> +  unsigned bits;
Our conventions are to prefix member fields with m_.

Note that a simple "unsigned" may just be 32 bits.  Though with your 
grouping that may not matter in practice.

I think with the nits fixed this is fine.  I know there's some 
disagreement on singular vs plural, but having two names differing by 
just that is probably going to be more confusing in the end, so I'm on 
the side of using the names as-is.

jeff

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PING][PATCH 9/13] v2 Use new per-location warning APIs in LTO
  2021-06-21 21:54       ` [PING][PATCH " Martin Sebor
@ 2021-06-24  9:32         ` Richard Biener
  2021-06-24 15:27           ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: Richard Biener @ 2021-06-24  9:32 UTC (permalink / raw)
  To: Martin Sebor; +Cc: gcc-patches

On Mon, Jun 21, 2021 at 11:55 PM Martin Sebor via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571980.html
>
> Looking for a review of the LTO changes to switch TREE_NO_WARNING to
> the suppress_warning() API.

Hmm, since the warning suppressions are on location ad-hoc data the appropriate
thing is to adjust the location streaming and that part seems to be missing?

So what you now stream is simply the "everything" fallback, correct?

In particular:

   else
-    bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
+    /* FIXME: pack all warning bits.  */
+    bp_pack_value (bp, warning_suppressed_p (expr), 1);

this looks like a wrong comment in that light.

-  else
-    compare_values (TREE_NO_WARNING);
+  else if (t1->base.nowarning_flag != t2->base.nowarning_flag)
+    return false;

uh.  Can you keep sth like TREE_NO_WARNING_RAW or so?

Thanks,
Richard.

> On 6/4/21 3:43 PM, Martin Sebor wrote:
> > The attached patch replaces the uses of TREE_NO_WARNING in the LTO
> > front end with the new suppress_warning() API.  It adds a couple of
> > FIXMEs that I plan to take care of in a follow up.
>

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PING][PATCH 9/13] v2 Use new per-location warning APIs in LTO
  2021-06-24  9:32         ` Richard Biener
@ 2021-06-24 15:27           ` Martin Sebor
  2021-06-25  7:46             ` Richard Biener
  0 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-06-24 15:27 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches

On 6/24/21 3:32 AM, Richard Biener wrote:
> On Mon, Jun 21, 2021 at 11:55 PM Martin Sebor via Gcc-patches
> <gcc-patches@gcc.gnu.org> wrote:
>>
>> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571980.html
>>
>> Looking for a review of the LTO changes to switch TREE_NO_WARNING to
>> the suppress_warning() API.
> 
> Hmm, since the warning suppressions are on location ad-hoc data the appropriate
> thing is to adjust the location streaming and that part seems to be missing?
> 
> So what you now stream is simply the "everything" fallback, correct?
> 
> In particular:
> 
>     else
> -    bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
> +    /* FIXME: pack all warning bits.  */
> +    bp_pack_value (bp, warning_suppressed_p (expr), 1);
> 
> this looks like a wrong comment in that light.

Yes, this is just a fallback.  I haven't thought about how to handle
the FIXME yet but from your comment it sounds like this code might
stay the same (or maybe even go back to streaming the flag directly)
and the nowarn_spec_t bitmap should be streamed elsewhere?

> 
> -  else
> -    compare_values (TREE_NO_WARNING);
> +  else if (t1->base.nowarning_flag != t2->base.nowarning_flag)
> +    return false;
> 
> uh.  Can you keep sth like TREE_NO_WARNING_RAW or so?

The flag is used directly in fold-const.c and cp/module.cc so
this would be in keeping with that, but I also don't mind adding
a macro for it.  My only concern is with macro getting used to
inadvertently bypass the API.

Martin

> 
> Thanks,
> Richard.
> 
>> On 6/4/21 3:43 PM, Martin Sebor wrote:
>>> The attached patch replaces the uses of TREE_NO_WARNING in the LTO
>>> front end with the new suppress_warning() API.  It adds a couple of
>>> FIXMEs that I plan to take care of in a follow up.
>>


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)
  2021-06-24  5:26             ` Jeff Law
@ 2021-06-25  1:34               ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-25  1:34 UTC (permalink / raw)
  To: Jeff Law, David Malcolm, gcc-patches

On 6/23/21 11:26 PM, Jeff Law wrote:
> 
> 
> On 6/23/2021 1:47 PM, Martin Sebor via Gcc-patches wrote:
>> On 6/22/21 5:28 PM, David Malcolm wrote:
>>> On Tue, 2021-06-22 at 19:18 -0400, David Malcolm wrote:
>>>> On Fri, 2021-06-04 at 15:41 -0600, Martin Sebor wrote:
>>>>> The attached patch introduces the suppress_warning(),
>>>>> warning_suppressed(), and copy_no_warning() APIs without making
>>>>> use of them in the rest of GCC.  They are in three files:
>>>>>
>>>>>     diagnostic-spec.{h,c}: Location-centric overloads.
>>>>>     warning-control.cc: Tree- and gimple*-centric overloads.
>>>>>
>>>>> The location-centric overloads are suitable to use from the
>>>>> diagnostic
>>>>> subsystem.  The rest can be used from the front ends and the middle
>>>>> end.
>>>>
>>>> [...snip...]
>>>>
>>>>> +/* Return true if warning OPT is suppressed for decl/expression
>>>>> EXPR.
>>>>> +   By default tests the disposition for any warning.  */
>>>>> +
>>>>> +bool
>>>>> +warning_suppressed_p (const_tree expr, opt_code opt /* =
>>>>> all_warnings */)
>>>>> +{
>>>>> +  const nowarn_spec_t *spec = get_nowarn_spec (expr);
>>>>> +
>>>>> +  if (!spec)
>>>>> +    return get_no_warning_bit (expr);
>>>>> +
>>>>> +  const nowarn_spec_t optspec (opt);
>>>>> +  bool dis = *spec & optspec;
>>>>> +  gcc_assert (get_no_warning_bit (expr) || !dis);
>>>>> +  return dis;
>>>>
>>>> Looking through the patch, I don't like the use of "dis" for the "is
>>>> suppressed" bool, since...
>>
>> It's an argument to a a function, unlikely to confuse anyone.  But
>> I also don't think it's important enough to argue about so I changed
>> it along with the comment below.
>>
>>>>
>>>> [...snip...]
>>>>
>>>>> +
>>>>> +/* Enable, or by default disable, a warning for the statement STMT.
>>>>> +   The wildcard OPT of -1 controls all warnings.  */
>>>>
>>>> ...I find the above comment to be confusingly worded due to the double-
>>>> negative.
>>>>
>>>> If I'm reading your intent correctly, how about this wording:
>>>>
>>>> /* Change the supression of warnings for statement STMT.
>>>>     OPT controls which warnings are affected.
>>>>     The wildcard OPT of -1 controls all warnings.
>>>>     If SUPP is true (the default), enable the suppression of the
>>>> warnings.
>>>>     If SUPP is false, disable the suppression of the warnings.  */
>>>>
>>>> ...and rename "dis" to "supp".
>>>>
>>>> Or have I misread the intent of the patch?
>>>>
>>>>> +
>>>>> +void
>>>>> +suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
>>>>> +                 bool dis /* = true */)
>>>>
>>>>> +{
>>>>> +  if (opt == no_warning)
>>>>> +    return;
>>>>> +
>>>>> +  const key_type_t key = convert_to_key (stmt);
>>>>> +
>>>>> +  dis = suppress_warning_at (key, opt, dis) || dis;
>>>>> +  set_no_warning_bit (stmt, dis);
>>>>> +}
>>>>
>>>> [...snip...]
>>>
>>> Also, I think I prefer having a separate entrypoints for the "all
>>> warnings" case; on reading through the various patches I think that in
>>> e.g.:
>>>
>>> -      TREE_NO_WARNING (*expr_p) = 1;
>>> +      suppress_warning (*expr_p);
>>>
>>> I prefer:
>>>
>>>            suppress_warnings (*expr_p);
>>>
>>> (note the plural) since that way we can grep for them, and it seems
>>> like better grammar to me.
>>>
>>> Both entrypoints could be implemented by a static suppress_warning_1
>>> internally if that makes it easier.
>>>
>>> In that vein, "unsuppress_warning" seems far clearer to me that
>>> "suppress_warning (FOO, false)"; IIRC there are very few uses of this
>>> non-default arg (I couldn't find any in a quick look through the v2
>>> kit).
>>>
>>> Does this make sense?
>>
>> In my experience, names that differ only slightly (such as in just
>> one letter) tend to easily lead to frustrating mistakes.  The new
>> warning_suppressed_p() added in this patch also handles multiple
>> warnings (via a wildcard) and uses a singular form, and as do
>> the gimple_{get,set}no_warning() functions that are being replaced.
>> So I don't think the suggested change is needed or would be
>> an improvement.
>>
>> Similarly, there is no gimple_unset_no_warning() today and I don't
>> think adding unsuppress_warning() is necessary or would add value,
>> especially since there are just a handful of callers that re-enable
>> warnings.  For the callers that might need to enable or disable
>> a warning based on some condition, it's more convenient to do so
>> in a single call then by having to call different functions based
>> the value of the condition.
>>
>> In the attached patch I've changed the comment as you asked and
>> also renamed the dis argument to supp but kept the function names
>> the same.  I've also moved a few changes to tree.h from a later
>> patch to this one to let it stand alone and regtested it on its
>> own on x86_64-linux.  I'll plan to go ahead with this version
>> unless requestsfor substantive changes come up in the review of
>> the rest  of the changes.
>>
>> Thanks
>> Martin
>>
>> gcc-no-warning-1.diff
>>
>> Add support for per-location warning groups.
>>
>> gcc/ChangeLog:
>>
>> 	* Makefile.in (OBJS-libcommon): Add diagnostic-spec.o.
>> 	* gengtype.c (open_base_files): Add diagnostic-spec.h.
>> 	* diagnostic-spec.c: New file.
>> 	* diagnostic-spec.h: New file.
>> 	* tree.h (no_warning, all_warnings, suppress_warning_at): New
>> 	declarations.
>> 	* warning-control.cc: New file.
>>
>> diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
>> new file mode 100644
>> index 00000000000..62d9270ca6d
>> --- /dev/null
>> +++ b/gcc/diagnostic-spec.h
>> @@ -0,0 +1,140 @@
>> +/* Language-independent APIs to enable/disable per-location warnings.
>> +
>> +   Copyright (C) 2021 Free Software Foundation, Inc.
>> +   Contributed by Martin Sebor<msebor@redhat.com>
>> +
>> +   This file is part of GCC.
>> +
>> +   GCC is free software; you can redistribute it and/or modify it under
>> +   the terms of the GNU General Public License as published by the Free
>> +   Software Foundation; either version 3, or (at your option) any later
>> +   version.
>> +
>> +   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
>> +   WARRANTY; without even the implied warranty of MERCHANTABILITY or
>> +   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
>> +   for more details.
>> +
>> +   You should have received a copy of the GNU General Public License
>> +   along with GCC; see the file COPYING3.  If not see
>> +<http://www.gnu.org/licenses/>.  */
>> +
>> +#ifndef DIAGNOSTIC_SPEC_H_INCLUDED
>> +#define DIAGNOSTIC_SPEC_H_INCLUDED
>> +
>> +#include "hash-map.h"
>> +
>> +/* A "bitset" of warning groups.  */
>> +
>> +struct nowarn_spec_t
> Should probably be "class" not "struct".  Though I don't think we're 
> necessarily consistent with this.
>> +private:
>> +  /* Bitset of warning groups.  */
>> +  unsigned bits;
> Our conventions are to prefix member fields with m_.
> 
> Note that a simple "unsigned" may just be 32 bits.  Though with your 
> grouping that may not matter in practice.
> 
> I think with the nits fixed this is fine.  I know there's some 
> disagreement on singular vs plural, but having two names differing by 
> just that is probably going to be more confusing in the end, so I'm on 
> the side of using the names as-is.

Done and pushed in r12-1801.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 3/13] v2 Use new per-location warning APIs in C front end
  2021-06-24  5:09       ` [PATCH " Jeff Law
@ 2021-06-25  1:35         ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-25  1:35 UTC (permalink / raw)
  To: Jeff Law, gcc-patches

On 6/23/21 11:09 PM, Jeff Law wrote:
> 
> 
> On 6/4/2021 3:41 PM, Martin Sebor via Gcc-patches wrote:
>> The attached patch replaces the uses of TREE_NO_WARNING in the C front
>> end with the new suppress_warning(), warning_suppressed_p(), and
>> copy_warning() APIs.
>>
>> gcc-no-warning-c.diff
>>
>> Add support for per-location warning groups.
>>
>> gcc/c/ChangeLog:
>>
>> 	* c-decl.c (pop_scope): Replace direct uses of TREE_NO_WARNING with
>> 	warning_suppressed_p, suppress_warning, and copy_no_warning.
>> 	(diagnose_mismatched_decls): Same.
>> 	(duplicate_decls): Same.
>> 	(grokdeclarator): Same.
>> 	(finish_function): Same.
>> 	(c_write_global_declarations_1): Same.
>> 	* c-fold.c (c_fully_fold_internal): Same.
>> 	* c-parser.c (c_parser_expr_no_commas): Same.
>> 	(c_parser_postfix_expression): Same.
>> 	* c-typeck.c (array_to_pointer_conversion): Same.
>> 	(function_to_pointer_conversion): Same.
>> 	(default_function_array_conversion): Same.
>> 	(convert_lvalue_to_rvalue): Same.
>> 	(default_conversion): Same.
>> 	(build_indirect_ref): Same.
>> 	(build_function_call_vec): Same.
>> 	(build_atomic_assign): Same.
>> 	(build_unary_op): Same.
>> 	(c_finish_return): Same.
>> 	(emit_side_effect_warnings): Same.
>> 	(c_finish_stmt_expr): Same.
>> 	(c_omp_clause_copy_ctor): Same.
> OK once prereqs are approved.

I've retested this on top of the first patch and pushed r12-1802.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 4/13] v2 Use new per-location warning APIs in C family code
  2021-06-24  5:06       ` [PATCH " Jeff Law
@ 2021-06-25  1:36         ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-25  1:36 UTC (permalink / raw)
  To: Jeff Law, gcc-patches

On 6/23/21 11:06 PM, Jeff Law wrote:
> 
> 
> On 6/4/2021 3:42 PM, Martin Sebor via Gcc-patches wrote:
>> The attached patch replaces the uses of TREE_NO_WARNING in the shared
>> C family front end with the new suppress_warning(),
>> warning_suppressed_p(), and copy_warning() APIs.
>>
>> gcc-no-warning-c-family.diff
>>
>> Add support for per-location warning groups.
>>
>> gcc/c-family/ChangeLog:
>>
>> 	* c-common.c (c_wrap_maybe_const): Remove TREE_NO_WARNING.
>> 	(c_common_truthvalue_conversion): Replace direct uses of
>> 	TREE_NO_WARNING with warning_suppressed_p, suppress_warning, and
>> 	copy_no_warning.
>> 	(check_function_arguments_recurse): Same.
>> 	* c-gimplify.c (c_gimplify_expr): Same.
>> 	* c-warn.c (overflow_warning): Same.
>> 	(warn_logical_operator): Same.
>> 	(warn_if_unused_value): Same.
>> 	(do_warn_unused_parameter): Same.
> OK once prereqs are approved.
> jeff
> 

Retested on top patch 1 and the C FE stuff and pushed r12-1803.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 6/13] v2 Use new per-location warning APIs in the C++ front end
  2021-06-24  5:12       ` [PATCH " Jeff Law
@ 2021-06-25  1:38         ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-25  1:38 UTC (permalink / raw)
  To: Jeff Law, gcc-patches

On 6/23/21 11:12 PM, Jeff Law wrote:
> 
> 
> On 6/4/2021 3:42 PM, Martin Sebor via Gcc-patches wrote:
>> The attached patch replaces the uses of TREE_NO_WARNING in the C++
>> front end with the new suppress_warning(), warning_suppressed_p(),
>> and copy_warning() APIs.
>>
>> gcc-no-warning-cp.diff
>>
>> Add support for per-location warning groups.
>>
>> 	* call.c (build_over_call): Replace direct uses of TREE_NO_WARNING
>> 	with warning_suppressed_p, suppress_warning, and copy_no_warning, or
>> 	nothing if not necessary.
>> 	(set_up_extended_ref_temp): Same.
>> 	* class.c (layout_class_type): Same.
>> 	* constraint.cc (constraint_satisfaction_value): Same.
>> 	* coroutines.cc (finish_co_await_expr): Same.
>> 	(finish_co_yield_expr): Same.
>> 	(finish_co_return_stmt): Same.
>> 	(build_actor_fn): Same.
>> 	(coro_rewrite_function_body): Same.
>> 	(morph_fn_to_coro): Same.
>> 	* cp-gimplify.c (genericize_eh_spec_block): Same.
>> 	(gimplify_expr_stmt): Same.
>> 	(cp_genericize_r): Same.
>> 	(cp_fold): Same.
>> 	* cp-ubsan.c (cp_ubsan_instrument_vptr): Same.
>> 	* cvt.c (cp_fold_convert): Same.
>> 	(convert_to_void): Same.
>> 	* decl.c (wrapup_namespace_globals): Same.
>> 	(grokdeclarator): Same.
>> 	(finish_function): Same.
>> 	(require_deduced_type): Same.
>> 	* decl2.c (no_linkage_error): Same.
>> 	(c_parse_final_cleanups): Same.
>> 	* except.c (expand_end_catch_block): Same.
>> 	* init.c (build_new_1): Same.
>> 	(build_new): Same.
>> 	(build_vec_delete_1): Same.
>> 	(build_vec_init): Same.
>> 	(build_delete): Same.
>> 	* method.c (defaultable_fn_check): Same.
>> 	* parser.c (cp_parser_fold_expression): Same.
>> 	(cp_parser_primary_expression): Same.
>> 	* pt.c (push_tinst_level_loc): Same.
>> 	(tsubst_copy): Same.
>> 	(tsubst_omp_udr): Same.
>> 	(tsubst_copy_and_build): Same.
>> 	* rtti.c (build_if_nonnull): Same.
>> 	* semantics.c (maybe_convert_cond): Same.
>> 	(finish_return_stmt): Same.
>> 	(finish_parenthesized_expr): Same.
>> 	(cp_check_omp_declare_reduction): Same.
>> 	* tree.c (build_cplus_array_type): Same.
>> 	* typeck.c (build_ptrmemfunc_access_expr): Same.
>> 	(cp_build_indirect_ref_1): Same.
>> 	(cp_build_function_call_vec): Same.
>> 	(warn_for_null_address): Same.
>> 	(cp_build_binary_op): Same.
>> 	(unary_complex_lvalue): Same.
>> 	(cp_build_modify_expr): Same.
>> 	(build_x_modify_expr): Same.
>> 	(convert_for_assignment): Same.
> OK once prereqs are approved.  Note that I wouldn't be terribly 
> surprised if changes in the C++ front-end over the last couple weeks 
> create a conflict.  Consider resolution of such conflicts (in the C++ 
> front-end or elsewhere) or removing additional uses of TREE_NO_WARNING 
> that have crept in over the last two weeks pre-approved.
> 
> Jeff
> 

The patch applied cleanly.  I retested it on top of the C bits and
pushed r12-1804.  If there are any new TREE_NO_WARNINGs I'll find
those when I remove the macro.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 10/13] v2 Use new per-location warning APIs in the middle end
  2021-06-24  5:15       ` [PATCH " Jeff Law
@ 2021-06-25  1:40         ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-25  1:40 UTC (permalink / raw)
  To: Jeff Law, gcc-patches

On 6/23/21 11:15 PM, Jeff Law wrote:
> 
> 
> On 6/4/2021 3:43 PM, Martin Sebor via Gcc-patches wrote:
>> The attached patch introduces declarations of the new
>> suppress_warning(), warning_suppressed_p(), and copy_warning() APIs,
>> and replaces the uses of TREE_NO_WARNING in the middle end with them.
>>
>> gcc-no-warning-middle-end.diff
>>
>> Add support for per-location warning groups.
>>
>> gcc/ChangeLog:
>>
>> 	* builtins.c (warn_string_no_nul): Replace uses of TREE_NO_WARNING,
>> 	gimple_no_warning_p and gimple_set_no_warning with
>> 	warning_suppressed_p, and suppress_warning.
>> 	(c_strlen): Same.
>> 	(maybe_warn_for_bound): Same.
>> 	(warn_for_access): Same.
>> 	(check_access): Same.
>> 	(expand_builtin_strncmp): Same.
>> 	(fold_builtin_varargs): Same.
>> 	* calls.c (maybe_warn_nonstring_arg): Same.
>> 	(maybe_warn_rdwr_sizes): Same.
>> 	* cfgexpand.c (expand_call_stmt): Same.
>> 	* cgraphunit.c (check_global_declaration): Same.
>> 	* fold-const.c (fold_undefer_overflow_warnings): Same.
>> 	(fold_truth_not_expr): Same.
>> 	(fold_unary_loc): Same.
>> 	(fold_checksum_tree): Same.
>> 	* gengtype.c (open_base_files): Same.
>> 	* gimple-array-bounds.cc (array_bounds_checker::check_array_ref): Same.
>> 	(array_bounds_checker::check_mem_ref): Same.
>> 	(array_bounds_checker::check_addr_expr): Same.
>> 	(array_bounds_checker::check_array_bounds): Same.
>> 	* gimple-expr.c (copy_var_decl): Same.
>> 	* gimple-fold.c (gimple_fold_builtin_strcpy): Same.
>> 	(gimple_fold_builtin_strncat): Same.
>> 	(gimple_fold_builtin_stxcpy_chk): Same.
>> 	(gimple_fold_builtin_stpcpy): Same.
>> 	(gimple_fold_builtin_sprintf): Same.
>> 	(fold_stmt_1): Same.
>> 	* gimple-ssa-isolate-paths.c (diag_returned_locals): Same.
>> 	* gimple-ssa-nonnull-compare.c (do_warn_nonnull_compare): Same.
>> 	* gimple-ssa-sprintf.c (handle_printf_call): Same.
>> 	* gimple-ssa-store-merging.c (imm_store_chain_info::output_merged_store): Same.
>> 	* gimple-ssa-warn-restrict.c (maybe_diag_overlap): Same.
>> 	(maybe_diag_access_bounds): Same.
>> 	(check_call): Same.
>> 	(check_bounds_or_overlap): Same.
>> 	* gimple.c (gimple_build_call_from_tree): Same.
>> 	* gimplify.c (gimplify_return_expr): Same.
>> 	(gimplify_cond_expr): Same.
>> 	(gimplify_modify_expr_complex_part): Same.
>> 	(gimplify_modify_expr): Same.
>> 	(gimple_push_cleanup): Same.
>> 	(gimplify_expr): Same.
>> 	* omp-expand.c (expand_omp_for_generic): Same.
>> 	(expand_omp_taskloop_for_outer): Same.
>> 	* omp-low.c (lower_rec_input_clauses): Same.
>> 	(lower_lastprivate_clauses): Same.
>> 	(lower_send_clauses): Same.
>> 	(lower_omp_target): Same.
>> 	* tree-cfg.c (pass_warn_function_return::execute): Same.
>> 	* tree-complex.c (create_one_component_var): Same.
>> 	* tree-inline.c (remap_gimple_op_r): Same.
>> 	(copy_tree_body_r): Same.
>> 	(declare_return_variable): Same.
>> 	(expand_call_inline): Same.
>> 	* tree-nested.c (lookup_field_for_decl): Same.
>> 	* tree-sra.c (create_access_replacement): Same.
>> 	(generate_subtree_copies): Same.
>> 	* tree-ssa-ccp.c (pass_post_ipa_warn::execute): Same.
>> 	* tree-ssa-forwprop.c (combine_cond_expr_cond): Same.
>> 	* tree-ssa-loop-ch.c (ch_base::copy_headers): Same.
>> 	* tree-ssa-loop-im.c (execute_sm): Same.
>> 	* tree-ssa-phiopt.c (cond_store_replacement): Same.
>> 	* tree-ssa-strlen.c (maybe_warn_overflow): Same.
>> 	(handle_builtin_strcpy): Same.
>> 	(maybe_diag_stxncpy_trunc): Same.
>> 	(handle_builtin_stxncpy_strncat): Same.
>> 	(handle_builtin_strcat): Same.
>> 	* tree-ssa-uninit.c (get_no_uninit_warning): Same.
>> 	(set_no_uninit_warning): Same.
>> 	(uninit_undefined_value_p): Same.
>> 	(warn_uninit): Same.
>> 	(maybe_warn_operand): Same.
>> 	* tree-vrp.c (compare_values_warnv): Same.
>> 	* vr-values.c (vr_values::extract_range_for_var_from_comparison_expr): Same.
>> 	(test_for_singularity): Same.
>>
>> 	* gimple.h (warning_suppressed_p): New function.
>> 	(suppress_warning): Same.
>> 	(copy_no_warning): Same.
>> 	(gimple_set_block): Call gimple_set_location.
>> 	(gimple_set_location): Call copy_warning.
>> 	* tree.h (no_warning, all_warnings): New constants.
>> 	(warning_suppressed_p): New function.
>> 	(suppress_warning): Same.
>> 	(copy_no_warning): Same.
> OK once prereqs are approved.
> 
> jeff
> 

Retested on top patch 1 plus the C and C++ bits and pushed r12-1805.
I'll do the rest of the approved patches tomorrow.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PING][PATCH 9/13] v2 Use new per-location warning APIs in LTO
  2021-06-24 15:27           ` Martin Sebor
@ 2021-06-25  7:46             ` Richard Biener
  0 siblings, 0 replies; 98+ messages in thread
From: Richard Biener @ 2021-06-25  7:46 UTC (permalink / raw)
  To: Martin Sebor; +Cc: gcc-patches

On Thu, Jun 24, 2021 at 5:27 PM Martin Sebor <msebor@gmail.com> wrote:
>
> On 6/24/21 3:32 AM, Richard Biener wrote:
> > On Mon, Jun 21, 2021 at 11:55 PM Martin Sebor via Gcc-patches
> > <gcc-patches@gcc.gnu.org> wrote:
> >>
> >> Ping: https://gcc.gnu.org/pipermail/gcc-patches/2021-June/571980.html
> >>
> >> Looking for a review of the LTO changes to switch TREE_NO_WARNING to
> >> the suppress_warning() API.
> >
> > Hmm, since the warning suppressions are on location ad-hoc data the appropriate
> > thing is to adjust the location streaming and that part seems to be missing?
> >
> > So what you now stream is simply the "everything" fallback, correct?
> >
> > In particular:
> >
> >     else
> > -    bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
> > +    /* FIXME: pack all warning bits.  */
> > +    bp_pack_value (bp, warning_suppressed_p (expr), 1);
> >
> > this looks like a wrong comment in that light.
>
> Yes, this is just a fallback.  I haven't thought about how to handle
> the FIXME yet but from your comment it sounds like this code might
> stay the same (or maybe even go back to streaming the flag directly)
> and the nowarn_spec_t bitmap should be streamed elsewhere?

Yes, since the bitmap is per location it should be streamed alongside
locations in lto_{input,output}_location.

> >
> > -  else
> > -    compare_values (TREE_NO_WARNING);
> > +  else if (t1->base.nowarning_flag != t2->base.nowarning_flag)
> > +    return false;
> >
> > uh.  Can you keep sth like TREE_NO_WARNING_RAW or so?
>
> The flag is used directly in fold-const.c and cp/module.cc so
> this would be in keeping with that, but I also don't mind adding
> a macro for it.  My only concern is with macro getting used to
> inadvertently bypass the API.

There's precedent with other _RAW accessors, it should be
clear that it bypasses accessors and thus review should easily
spot inadverted uses.

Richard.

> Martin
>
> >
> > Thanks,
> > Richard.
> >
> >> On 6/4/21 3:43 PM, Martin Sebor wrote:
> >>> The attached patch replaces the uses of TREE_NO_WARNING in the LTO
> >>> front end with the new suppress_warning() API.  It adds a couple of
> >>> FIXMEs that I plan to take care of in a follow up.
> >>
>

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 2/13] v2 Use new per-location warning APIs in Ada.
  2021-06-24  5:07       ` Jeff Law
@ 2021-06-28 21:20         ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-28 21:20 UTC (permalink / raw)
  To: Jeff Law, gcc-patches

On 6/23/21 11:07 PM, Jeff Law wrote:
> 
> 
> On 6/4/2021 3:41 PM, Martin Sebor via Gcc-patches wrote:
>> The attached patch replaces the uses of TREE_NO_WARNING in the Ada front
>> end with the new suppress_warning(), warning_suppressed_p(), and
>> copy_warning() APIs.
>>
>> gcc-no-warning-ada.diff
>>
>> Add support for per-location warning groups.
>>
>> gcc/ada/ChangeLog:
>>
>> 	* gcc-interface/trans.c (Handled_Sequence_Of_Statements_to_gnu):
>> 	Replace TREE_NO_WARNING with suppress_warning.
>> 	(gnat_gimplify_expr): Same.
>> 	* gcc-interface/utils.c (gnat_pushdecl): Same.
> OK once prereqs are approved.
> jeff
> 

Pushed in r12-1857.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 7/13] v2 Use new per-location warning APIs in the FORTRAN front end
  2021-06-24  5:05       ` [PATCH " Jeff Law
@ 2021-06-28 21:21         ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-28 21:21 UTC (permalink / raw)
  To: Jeff Law, gcc-patches

On 6/23/21 11:05 PM, Jeff Law wrote:
> 
> 
> On 6/4/2021 3:42 PM, Martin Sebor via Gcc-patches wrote:
>> The attached patch replaces the uses of TREE_NO_WARNING in the FORTRAN
>> front end with the new suppress_warning() API.
>>
>> gcc-no-warning-fortran.diff
>>
>> Add support for per-location warning groups.
>>
>> gcc/fortran/ChangeLog:
>>
>> 	* trans-array.c (trans_array_constructor): Replace direct uses
>> 	of TREE_NO_WARNING with warning_suppressed_p, and suppress_warning.
>> 	* trans-decl.c (gfc_build_qualified_array): Same.
>> 	(gfc_build_dummy_array_decl): Same.
>> 	(generate_local_decl): Same.
>> 	(gfc_generate_function_code): Same.
>> 	* trans-openmp.c (gfc_omp_clause_default_ctor): Same.
>> 	(gfc_omp_clause_copy_ctor): Same.
>> 	* trans-types.c (get_dtype_type_node): Same.
>> 	(gfc_get_desc_dim_type): Same.
>> 	(gfc_get_array_descriptor_base): Same.
>> 	(gfc_get_caf_vector_type): Same.
>> 	(gfc_get_caf_reference_type): Same.
>> 	* trans.c (gfc_create_var_np): Same.
> OK once prereqs are approved.
> jeff
> 

Retested and pushed in r12-1858.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 8/13] v2 Use new per-location warning APIs in libcc1
  2021-06-24  5:04       ` Jeff Law
@ 2021-06-28 21:22         ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-28 21:22 UTC (permalink / raw)
  To: Jeff Law, gcc-patches

On 6/23/21 11:04 PM, Jeff Law wrote:
> 
> 
> On 6/4/2021 3:42 PM, Martin Sebor via Gcc-patches wrote:
>> The attached patch replaces the uses of TREE_NO_WARNING in libcc1 with
>> the new suppress_warning() API.
>>
>> gcc-no-warning-libcc1.diff
>>
>> Add support for per-location warning groups.
>>
>> libcc1/ChangeLog:
>>
>> 	* libcp1plugin.cc (record_decl_address): Replace a direct use
>> 	of TREE_NO_WARNING with suppress_warning.
> OK once prereqs are approved.
> jeff
> 

Pushed in r12-1859.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 11/13] v2 Use new per-location warning APIs in the Objective-C front end
  2021-06-24  5:02       ` Jeff Law
@ 2021-06-28 21:22         ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-28 21:22 UTC (permalink / raw)
  To: Jeff Law, gcc-patches

On 6/23/21 11:02 PM, Jeff Law wrote:
> 
> 
> On 6/4/2021 3:43 PM, Martin Sebor via Gcc-patches wrote:
>> The attached patch replaces the uses of TREE_NO_WARNING in
>> the Objective-C front end with the new suppress_warning(),
>> warning_suppressed_p(), and copy_warning() APIs.
>>
>> gcc-no-warning-objc.diff
>>
>> Add support for per-location warning groups.
>>
>> gcc/objc/ChangeLog:
>>
>> 	* objc-act.c (objc_maybe_build_modify_expr): Replace direct uses
>> 	of TREE_NO_WARNING with warning_suppressed_p, and suppress_warning.
>> 	(objc_build_incr_expr_for_property_ref): Same.
>> 	(objc_build_struct): Same.
>> 	(synth_module_prologue): Same.
>> 	* objc-gnu-runtime-abi-01.c (gnu_runtime_01_initialize): Same.
>> 	* objc-next-runtime-abi-01.c (next_runtime_01_initialize): Same.
>> 	* objc-next-runtime-abi-02.c (next_runtime_02_initialize): Same.
> OK once prereqs are approved.
> 
> Jeff

Retested and pushed in r12-1860.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 13/13] v2 Add regression tests for PR 74765 and 74762
  2021-06-24  4:56       ` Jeff Law
@ 2021-06-28 21:23         ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-06-28 21:23 UTC (permalink / raw)
  To: Jeff Law, gcc-patches

On 6/23/21 10:56 PM, Jeff Law wrote:
> 
> 
> On 6/4/2021 3:43 PM, Martin Sebor via Gcc-patches wrote:
>> The attached patch adds regression tests for two closely related bugs
>> resolved by the patch series.
>>
>> gcc-no-warning-tests.diff
>>
>> Regression tests for TREE_NO_WARNING enhancement to warning groups.
>>
>> PR middle-end/74765 - missing uninitialized warning (parenthesis, TREE_NO_WARNING abuse)
>> PR middle-end/74762 - [9/10/11/12 Regression] missing uninitialized warning (C++, parenthesized expr, TREE_NO_WARNING)
>>
>> gcc/testsuite/ChangeLog:
>>
>> 	* g++.dg/uninit-pr74762.C: New test.
>> 	* g++.dg/warn/uninit-pr74765.C: Same.
>>
>> diff --git a/gcc/testsuite/g++.dg/uninit-pr74762.C b/gcc/testsuite/g++.dg/uninit-pr74762.C
> This is OK once the prereqs are all approved.
> jeff
> 

Pushed in r12-1861.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/13] v2 warning control by group and location (PR 74765)
  2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
                       ` (13 preceding siblings ...)
  2021-06-15  1:29     ` [PING][PATCH 0/13] v2 warning control by group and location (PR 74765) Martin Sebor
@ 2021-07-17 20:36     ` Jan-Benedict Glaw
  2021-07-19 15:08       ` Martin Sebor
  14 siblings, 1 reply; 98+ messages in thread
From: Jan-Benedict Glaw @ 2021-07-17 20:36 UTC (permalink / raw)
  To: Martin Sebor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2644 bytes --]

Hi Martin!

On Fri, 2021-06-04 15:27:04 -0600, Martin Sebor <msebor@gmail.com> wrote:
> This is a revised patch series to add warning control by group and
> location, updated based on feedback on the initial series.
[...]

My automated checking (in this case: Using Debian's "gcc-snapshot"
package) indicates that between versions 1:20210527-1 and
1:20210630-1, building GDB breaks. Your patch is a likely candidate.
It's a case where a method asks for a nonnull argument and later on
checks for NULLness again. The build log is currently available at
(http://wolf.lug-owl.de:8080/jobs/gdb-vax-linux/5), though obviously
breaks for any target:

configure --target=vax-linux --prefix=/tmp/gdb-vax-linux
make all-gdb

[...]
[all 2021-07-16 19:19:25]   CXX    compile/compile.o
[all 2021-07-16 19:19:30] In file included from ./../gdbsupport/common-defs.h:126,
[all 2021-07-16 19:19:30]                  from ./defs.h:28,
[all 2021-07-16 19:19:30]                  from compile/compile.c:20:
[all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h: In constructor 'gdb::unlinker::unlinker(const char*)':
[all 2021-07-16 19:19:30] ./../gdbsupport/gdb_assert.h:35:4: error: 'nonnull' argument 'filename' compared to NULL [-Werror=nonnull-compare]
[all 2021-07-16 19:19:30]    35 |   ((void) ((expr) ? 0 :                                                       \
[all 2021-07-16 19:19:30]       |   ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[all 2021-07-16 19:19:30]    36 |            (gdb_assert_fail (#expr, __FILE__, __LINE__, FUNCTION_NAME), 0)))
[all 2021-07-16 19:19:30]       |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h:38:5: note: in expansion of macro 'gdb_assert'
[all 2021-07-16 19:19:30]    38 |     gdb_assert (filename != NULL);
[all 2021-07-16 19:19:30]       |     ^~~~~~~~~~
[all 2021-07-16 19:19:31] cc1plus: all warnings being treated as errors
[all 2021-07-16 19:19:31] make[1]: *** [Makefile:1641: compile/compile.o] Error 1
[all 2021-07-16 19:19:31] make[1]: Leaving directory '/var/lib/laminar/run/gdb-vax-linux/5/binutils-gdb/gdb'
[all 2021-07-16 19:19:31] make: *** [Makefile:11410: all-gdb] Error 2


Code is this:

 31 class unlinker
 32 {
 33  public:
 34 
 35   unlinker (const char *filename) ATTRIBUTE_NONNULL (2)
 36     : m_filename (filename)
 37   {
 38     gdb_assert (filename != NULL);
 39   }

I'm quite undecided whether this is bad behavior of GCC or bad coding
style in Binutils/GDB, or both.

Thanks,
  Jan-Benedict

-- 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/13] v2 warning control by group and location (PR 74765)
  2021-07-17 20:36     ` [PATCH " Jan-Benedict Glaw
@ 2021-07-19 15:08       ` Martin Sebor
  2021-07-28 11:14         ` Andrew Burgess
  0 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-07-19 15:08 UTC (permalink / raw)
  To: Jan-Benedict Glaw; +Cc: gcc-patches

On 7/17/21 2:36 PM, Jan-Benedict Glaw wrote:
> Hi Martin!
> 
> On Fri, 2021-06-04 15:27:04 -0600, Martin Sebor <msebor@gmail.com> wrote:
>> This is a revised patch series to add warning control by group and
>> location, updated based on feedback on the initial series.
> [...]
> 
> My automated checking (in this case: Using Debian's "gcc-snapshot"
> package) indicates that between versions 1:20210527-1 and
> 1:20210630-1, building GDB breaks. Your patch is a likely candidate.
> It's a case where a method asks for a nonnull argument and later on
> checks for NULLness again. The build log is currently available at
> (http://wolf.lug-owl.de:8080/jobs/gdb-vax-linux/5), though obviously
> breaks for any target:
> 
> configure --target=vax-linux --prefix=/tmp/gdb-vax-linux
> make all-gdb
> 
> [...]
> [all 2021-07-16 19:19:25]   CXX    compile/compile.o
> [all 2021-07-16 19:19:30] In file included from ./../gdbsupport/common-defs.h:126,
> [all 2021-07-16 19:19:30]                  from ./defs.h:28,
> [all 2021-07-16 19:19:30]                  from compile/compile.c:20:
> [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h: In constructor 'gdb::unlinker::unlinker(const char*)':
> [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_assert.h:35:4: error: 'nonnull' argument 'filename' compared to NULL [-Werror=nonnull-compare]
> [all 2021-07-16 19:19:30]    35 |   ((void) ((expr) ? 0 :                                                       \
> [all 2021-07-16 19:19:30]       |   ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> [all 2021-07-16 19:19:30]    36 |            (gdb_assert_fail (#expr, __FILE__, __LINE__, FUNCTION_NAME), 0)))
> [all 2021-07-16 19:19:30]       |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h:38:5: note: in expansion of macro 'gdb_assert'
> [all 2021-07-16 19:19:30]    38 |     gdb_assert (filename != NULL);
> [all 2021-07-16 19:19:30]       |     ^~~~~~~~~~
> [all 2021-07-16 19:19:31] cc1plus: all warnings being treated as errors
> [all 2021-07-16 19:19:31] make[1]: *** [Makefile:1641: compile/compile.o] Error 1
> [all 2021-07-16 19:19:31] make[1]: Leaving directory '/var/lib/laminar/run/gdb-vax-linux/5/binutils-gdb/gdb'
> [all 2021-07-16 19:19:31] make: *** [Makefile:11410: all-gdb] Error 2
> 
> 
> Code is this:
> 
>   31 class unlinker
>   32 {
>   33  public:
>   34
>   35   unlinker (const char *filename) ATTRIBUTE_NONNULL (2)
>   36     : m_filename (filename)
>   37   {
>   38     gdb_assert (filename != NULL);
>   39   }
> 
> I'm quite undecided whether this is bad behavior of GCC or bad coding
> style in Binutils/GDB, or both.

A warning should be expected in this case.  Before the recent GCC
change it was inadvertently suppressed in gdb_assert macros by its
operand being enclosed in parentheses.

Martin

> 
> Thanks,
>    Jan-Benedict
> 


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/13] v2 warning control by group and location (PR 74765)
  2021-07-19 15:08       ` Martin Sebor
@ 2021-07-28 11:14         ` Andrew Burgess
  2021-07-28 16:16           ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: Andrew Burgess @ 2021-07-28 11:14 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Jan-Benedict Glaw, gcc-patches

* Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> [2021-07-19 09:08:35 -0600]:

> On 7/17/21 2:36 PM, Jan-Benedict Glaw wrote:
> > Hi Martin!
> > 
> > On Fri, 2021-06-04 15:27:04 -0600, Martin Sebor <msebor@gmail.com> wrote:
> > > This is a revised patch series to add warning control by group and
> > > location, updated based on feedback on the initial series.
> > [...]
> > 
> > My automated checking (in this case: Using Debian's "gcc-snapshot"
> > package) indicates that between versions 1:20210527-1 and
> > 1:20210630-1, building GDB breaks. Your patch is a likely candidate.
> > It's a case where a method asks for a nonnull argument and later on
> > checks for NULLness again. The build log is currently available at
> > (http://wolf.lug-owl.de:8080/jobs/gdb-vax-linux/5), though obviously
> > breaks for any target:
> > 
> > configure --target=vax-linux --prefix=/tmp/gdb-vax-linux
> > make all-gdb
> > 
> > [...]
> > [all 2021-07-16 19:19:25]   CXX    compile/compile.o
> > [all 2021-07-16 19:19:30] In file included from ./../gdbsupport/common-defs.h:126,
> > [all 2021-07-16 19:19:30]                  from ./defs.h:28,
> > [all 2021-07-16 19:19:30]                  from compile/compile.c:20:
> > [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h: In constructor 'gdb::unlinker::unlinker(const char*)':
> > [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_assert.h:35:4: error: 'nonnull' argument 'filename' compared to NULL [-Werror=nonnull-compare]
> > [all 2021-07-16 19:19:30]    35 |   ((void) ((expr) ? 0 :                                                       \
> > [all 2021-07-16 19:19:30]       |   ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > [all 2021-07-16 19:19:30]    36 |            (gdb_assert_fail (#expr, __FILE__, __LINE__, FUNCTION_NAME), 0)))
> > [all 2021-07-16 19:19:30]       |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h:38:5: note: in expansion of macro 'gdb_assert'
> > [all 2021-07-16 19:19:30]    38 |     gdb_assert (filename != NULL);
> > [all 2021-07-16 19:19:30]       |     ^~~~~~~~~~
> > [all 2021-07-16 19:19:31] cc1plus: all warnings being treated as errors
> > [all 2021-07-16 19:19:31] make[1]: *** [Makefile:1641: compile/compile.o] Error 1
> > [all 2021-07-16 19:19:31] make[1]: Leaving directory '/var/lib/laminar/run/gdb-vax-linux/5/binutils-gdb/gdb'
> > [all 2021-07-16 19:19:31] make: *** [Makefile:11410: all-gdb] Error 2
> > 
> > 
> > Code is this:
> > 
> >   31 class unlinker
> >   32 {
> >   33  public:
> >   34
> >   35   unlinker (const char *filename) ATTRIBUTE_NONNULL (2)
> >   36     : m_filename (filename)
> >   37   {
> >   38     gdb_assert (filename != NULL);
> >   39   }
> > 
> > I'm quite undecided whether this is bad behavior of GCC or bad coding
> > style in Binutils/GDB, or both.
> 
> A warning should be expected in this case.  Before the recent GCC
> change it was inadvertently suppressed in gdb_assert macros by its
> operand being enclosed in parentheses.

This issue was just posted to the GDB list, and I wanted to clarify my
understanding a bit.

I believe that (at least by default) adding the nonnull attribute
allows GCC to assume (in the above case) that filename will not be
NULL and generate code accordingly.

Additionally, passing an explicit NULL (i.e. 'unlinker obj (NULL)')
would cause a compile time error.

But, there's nothing to actually stop a NULL being passed due to, say,
a logic bug in the program.  So, something like this would compile
fine:

  extern const char *ptr;
  unlinker obj (ptr);

And in a separate compilation unit:

  const char *ptr = NULL;

Obviously, the run time behaviour of such a program would be
undefined.

Given the above then, it doesn't seem crazy to want to do something
like the above, that is, add an assert to catch a logic bug in the
program.

Is there an approved mechanism through which I can tell GCC that I
really do want to do a comparison to NULL, without any warning, and
without the check being optimised out?

Thanks,
Andrew

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/13] v2 warning control by group and location (PR 74765)
  2021-07-28 11:14         ` Andrew Burgess
@ 2021-07-28 16:16           ` Martin Sebor
  2021-07-29  8:26             ` Andrew Burgess
  0 siblings, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-07-28 16:16 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: Jan-Benedict Glaw, gcc-patches

On 7/28/21 5:14 AM, Andrew Burgess wrote:
> * Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> [2021-07-19 09:08:35 -0600]:
> 
>> On 7/17/21 2:36 PM, Jan-Benedict Glaw wrote:
>>> Hi Martin!
>>>
>>> On Fri, 2021-06-04 15:27:04 -0600, Martin Sebor <msebor@gmail.com> wrote:
>>>> This is a revised patch series to add warning control by group and
>>>> location, updated based on feedback on the initial series.
>>> [...]
>>>
>>> My automated checking (in this case: Using Debian's "gcc-snapshot"
>>> package) indicates that between versions 1:20210527-1 and
>>> 1:20210630-1, building GDB breaks. Your patch is a likely candidate.
>>> It's a case where a method asks for a nonnull argument and later on
>>> checks for NULLness again. The build log is currently available at
>>> (http://wolf.lug-owl.de:8080/jobs/gdb-vax-linux/5), though obviously
>>> breaks for any target:
>>>
>>> configure --target=vax-linux --prefix=/tmp/gdb-vax-linux
>>> make all-gdb
>>>
>>> [...]
>>> [all 2021-07-16 19:19:25]   CXX    compile/compile.o
>>> [all 2021-07-16 19:19:30] In file included from ./../gdbsupport/common-defs.h:126,
>>> [all 2021-07-16 19:19:30]                  from ./defs.h:28,
>>> [all 2021-07-16 19:19:30]                  from compile/compile.c:20:
>>> [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h: In constructor 'gdb::unlinker::unlinker(const char*)':
>>> [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_assert.h:35:4: error: 'nonnull' argument 'filename' compared to NULL [-Werror=nonnull-compare]
>>> [all 2021-07-16 19:19:30]    35 |   ((void) ((expr) ? 0 :                                                       \
>>> [all 2021-07-16 19:19:30]       |   ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>> [all 2021-07-16 19:19:30]    36 |            (gdb_assert_fail (#expr, __FILE__, __LINE__, FUNCTION_NAME), 0)))
>>> [all 2021-07-16 19:19:30]       |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>> [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h:38:5: note: in expansion of macro 'gdb_assert'
>>> [all 2021-07-16 19:19:30]    38 |     gdb_assert (filename != NULL);
>>> [all 2021-07-16 19:19:30]       |     ^~~~~~~~~~
>>> [all 2021-07-16 19:19:31] cc1plus: all warnings being treated as errors
>>> [all 2021-07-16 19:19:31] make[1]: *** [Makefile:1641: compile/compile.o] Error 1
>>> [all 2021-07-16 19:19:31] make[1]: Leaving directory '/var/lib/laminar/run/gdb-vax-linux/5/binutils-gdb/gdb'
>>> [all 2021-07-16 19:19:31] make: *** [Makefile:11410: all-gdb] Error 2
>>>
>>>
>>> Code is this:
>>>
>>>    31 class unlinker
>>>    32 {
>>>    33  public:
>>>    34
>>>    35   unlinker (const char *filename) ATTRIBUTE_NONNULL (2)
>>>    36     : m_filename (filename)
>>>    37   {
>>>    38     gdb_assert (filename != NULL);
>>>    39   }
>>>
>>> I'm quite undecided whether this is bad behavior of GCC or bad coding
>>> style in Binutils/GDB, or both.
>>
>> A warning should be expected in this case.  Before the recent GCC
>> change it was inadvertently suppressed in gdb_assert macros by its
>> operand being enclosed in parentheses.
> 
> This issue was just posted to the GDB list, and I wanted to clarify my
> understanding a bit.
> 
> I believe that (at least by default) adding the nonnull attribute
> allows GCC to assume (in the above case) that filename will not be
> NULL and generate code accordingly.
> 
> Additionally, passing an explicit NULL (i.e. 'unlinker obj (NULL)')
> would cause a compile time error.
> 
> But, there's nothing to actually stop a NULL being passed due to, say,
> a logic bug in the program.  So, something like this would compile
> fine:
> 
>    extern const char *ptr;
>    unlinker obj (ptr);
> 
> And in a separate compilation unit:
> 
>    const char *ptr = NULL;
> 
> Obviously, the run time behaviour of such a program would be
> undefined.
> 
> Given the above then, it doesn't seem crazy to want to do something
> like the above, that is, add an assert to catch a logic bug in the
> program.
> 
> Is there an approved mechanism through which I can tell GCC that I
> really do want to do a comparison to NULL, without any warning, and
> without the check being optimised out?

The manual says -fno-delete-null-pointer-checks is supposed to
prevent the removal of the null function argument test so I'd
expect adding attribute optimize ("no-delete-null-pointer-checks")
to the definition of the function to have that effect but in my
testing it didn't work (and didn't give a warning for the two
attributes on the same declarataion).  That seems worth filing
a bug for.

An alternate approach that does work is to remove the nonnull
attribute from the definition while leaving it on the declaration.
But the two have to be compiled separately for it to work, which
can be hard to do, especially with LTO.

The only other way I can think of is by playing tricks with volatile.
Even that only seems to work in non-obvious ways such as:

   __attribute__ ((nonnull)) void f (int *p)
   {
      if (!p) abort ();       // eliminated

      volatile int *q = p;
      if (!q) abort ();       // eliminated

      volatile int i = 0;
      if (!&p[i]) abort ();   // works
   }

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/13] v2 warning control by group and location (PR 74765)
  2021-07-28 16:16           ` Martin Sebor
@ 2021-07-29  8:26             ` Andrew Burgess
  2021-07-29 14:41               ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: Andrew Burgess @ 2021-07-29  8:26 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Jan-Benedict Glaw, gcc-patches

* Martin Sebor <msebor@gmail.com> [2021-07-28 10:16:59 -0600]:

> On 7/28/21 5:14 AM, Andrew Burgess wrote:
> > * Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> [2021-07-19 09:08:35 -0600]:
> > 
> > > On 7/17/21 2:36 PM, Jan-Benedict Glaw wrote:
> > > > Hi Martin!
> > > > 
> > > > On Fri, 2021-06-04 15:27:04 -0600, Martin Sebor <msebor@gmail.com> wrote:
> > > > > This is a revised patch series to add warning control by group and
> > > > > location, updated based on feedback on the initial series.
> > > > [...]
> > > > 
> > > > My automated checking (in this case: Using Debian's "gcc-snapshot"
> > > > package) indicates that between versions 1:20210527-1 and
> > > > 1:20210630-1, building GDB breaks. Your patch is a likely candidate.
> > > > It's a case where a method asks for a nonnull argument and later on
> > > > checks for NULLness again. The build log is currently available at
> > > > (http://wolf.lug-owl.de:8080/jobs/gdb-vax-linux/5), though obviously
> > > > breaks for any target:
> > > > 
> > > > configure --target=vax-linux --prefix=/tmp/gdb-vax-linux
> > > > make all-gdb
> > > > 
> > > > [...]
> > > > [all 2021-07-16 19:19:25]   CXX    compile/compile.o
> > > > [all 2021-07-16 19:19:30] In file included from ./../gdbsupport/common-defs.h:126,
> > > > [all 2021-07-16 19:19:30]                  from ./defs.h:28,
> > > > [all 2021-07-16 19:19:30]                  from compile/compile.c:20:
> > > > [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h: In constructor 'gdb::unlinker::unlinker(const char*)':
> > > > [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_assert.h:35:4: error: 'nonnull' argument 'filename' compared to NULL [-Werror=nonnull-compare]
> > > > [all 2021-07-16 19:19:30]    35 |   ((void) ((expr) ? 0 :                                                       \
> > > > [all 2021-07-16 19:19:30]       |   ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > > [all 2021-07-16 19:19:30]    36 |            (gdb_assert_fail (#expr, __FILE__, __LINE__, FUNCTION_NAME), 0)))
> > > > [all 2021-07-16 19:19:30]       |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > > [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h:38:5: note: in expansion of macro 'gdb_assert'
> > > > [all 2021-07-16 19:19:30]    38 |     gdb_assert (filename != NULL);
> > > > [all 2021-07-16 19:19:30]       |     ^~~~~~~~~~
> > > > [all 2021-07-16 19:19:31] cc1plus: all warnings being treated as errors
> > > > [all 2021-07-16 19:19:31] make[1]: *** [Makefile:1641: compile/compile.o] Error 1
> > > > [all 2021-07-16 19:19:31] make[1]: Leaving directory '/var/lib/laminar/run/gdb-vax-linux/5/binutils-gdb/gdb'
> > > > [all 2021-07-16 19:19:31] make: *** [Makefile:11410: all-gdb] Error 2
> > > > 
> > > > 
> > > > Code is this:
> > > > 
> > > >    31 class unlinker
> > > >    32 {
> > > >    33  public:
> > > >    34
> > > >    35   unlinker (const char *filename) ATTRIBUTE_NONNULL (2)
> > > >    36     : m_filename (filename)
> > > >    37   {
> > > >    38     gdb_assert (filename != NULL);
> > > >    39   }
> > > > 
> > > > I'm quite undecided whether this is bad behavior of GCC or bad coding
> > > > style in Binutils/GDB, or both.
> > > 
> > > A warning should be expected in this case.  Before the recent GCC
> > > change it was inadvertently suppressed in gdb_assert macros by its
> > > operand being enclosed in parentheses.
> > 
> > This issue was just posted to the GDB list, and I wanted to clarify my
> > understanding a bit.
> > 
> > I believe that (at least by default) adding the nonnull attribute
> > allows GCC to assume (in the above case) that filename will not be
> > NULL and generate code accordingly.
> > 
> > Additionally, passing an explicit NULL (i.e. 'unlinker obj (NULL)')
> > would cause a compile time error.
> > 
> > But, there's nothing to actually stop a NULL being passed due to, say,
> > a logic bug in the program.  So, something like this would compile
> > fine:
> > 
> >    extern const char *ptr;
> >    unlinker obj (ptr);
> > 
> > And in a separate compilation unit:
> > 
> >    const char *ptr = NULL;
> > 
> > Obviously, the run time behaviour of such a program would be
> > undefined.
> > 
> > Given the above then, it doesn't seem crazy to want to do something
> > like the above, that is, add an assert to catch a logic bug in the
> > program.
> > 
> > Is there an approved mechanism through which I can tell GCC that I
> > really do want to do a comparison to NULL, without any warning, and
> > without the check being optimised out?
>

Thanks for your feedback.

> The manual says -fno-delete-null-pointer-checks is supposed to
> prevent the removal of the null function argument test so I'd
> expect adding attribute optimize ("no-delete-null-pointer-checks")
> to the definition of the function to have that effect but in my
> testing it didn't work (and didn't give a warning for the two
> attributes on the same declarataion).  That seems worth filing
> a bug for.

I've since been pointed at this:

  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100404

Comment #3 of which discusses exactly this issue.

Thanks,
Andrew

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 0/13] v2 warning control by group and location (PR 74765)
  2021-07-29  8:26             ` Andrew Burgess
@ 2021-07-29 14:41               ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-07-29 14:41 UTC (permalink / raw)
  To: Andrew Burgess; +Cc: Jan-Benedict Glaw, gcc-patches

On 7/29/21 2:26 AM, Andrew Burgess wrote:
> * Martin Sebor <msebor@gmail.com> [2021-07-28 10:16:59 -0600]:
> 
>> On 7/28/21 5:14 AM, Andrew Burgess wrote:
>>> * Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> [2021-07-19 09:08:35 -0600]:
>>>
>>>> On 7/17/21 2:36 PM, Jan-Benedict Glaw wrote:
>>>>> Hi Martin!
>>>>>
>>>>> On Fri, 2021-06-04 15:27:04 -0600, Martin Sebor <msebor@gmail.com> wrote:
>>>>>> This is a revised patch series to add warning control by group and
>>>>>> location, updated based on feedback on the initial series.
>>>>> [...]
>>>>>
>>>>> My automated checking (in this case: Using Debian's "gcc-snapshot"
>>>>> package) indicates that between versions 1:20210527-1 and
>>>>> 1:20210630-1, building GDB breaks. Your patch is a likely candidate.
>>>>> It's a case where a method asks for a nonnull argument and later on
>>>>> checks for NULLness again. The build log is currently available at
>>>>> (http://wolf.lug-owl.de:8080/jobs/gdb-vax-linux/5), though obviously
>>>>> breaks for any target:
>>>>>
>>>>> configure --target=vax-linux --prefix=/tmp/gdb-vax-linux
>>>>> make all-gdb
>>>>>
>>>>> [...]
>>>>> [all 2021-07-16 19:19:25]   CXX    compile/compile.o
>>>>> [all 2021-07-16 19:19:30] In file included from ./../gdbsupport/common-defs.h:126,
>>>>> [all 2021-07-16 19:19:30]                  from ./defs.h:28,
>>>>> [all 2021-07-16 19:19:30]                  from compile/compile.c:20:
>>>>> [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h: In constructor 'gdb::unlinker::unlinker(const char*)':
>>>>> [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_assert.h:35:4: error: 'nonnull' argument 'filename' compared to NULL [-Werror=nonnull-compare]
>>>>> [all 2021-07-16 19:19:30]    35 |   ((void) ((expr) ? 0 :                                                       \
>>>>> [all 2021-07-16 19:19:30]       |   ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>>> [all 2021-07-16 19:19:30]    36 |            (gdb_assert_fail (#expr, __FILE__, __LINE__, FUNCTION_NAME), 0)))
>>>>> [all 2021-07-16 19:19:30]       |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>>> [all 2021-07-16 19:19:30] ./../gdbsupport/gdb_unlinker.h:38:5: note: in expansion of macro 'gdb_assert'
>>>>> [all 2021-07-16 19:19:30]    38 |     gdb_assert (filename != NULL);
>>>>> [all 2021-07-16 19:19:30]       |     ^~~~~~~~~~
>>>>> [all 2021-07-16 19:19:31] cc1plus: all warnings being treated as errors
>>>>> [all 2021-07-16 19:19:31] make[1]: *** [Makefile:1641: compile/compile.o] Error 1
>>>>> [all 2021-07-16 19:19:31] make[1]: Leaving directory '/var/lib/laminar/run/gdb-vax-linux/5/binutils-gdb/gdb'
>>>>> [all 2021-07-16 19:19:31] make: *** [Makefile:11410: all-gdb] Error 2
>>>>>
>>>>>
>>>>> Code is this:
>>>>>
>>>>>     31 class unlinker
>>>>>     32 {
>>>>>     33  public:
>>>>>     34
>>>>>     35   unlinker (const char *filename) ATTRIBUTE_NONNULL (2)
>>>>>     36     : m_filename (filename)
>>>>>     37   {
>>>>>     38     gdb_assert (filename != NULL);
>>>>>     39   }
>>>>>
>>>>> I'm quite undecided whether this is bad behavior of GCC or bad coding
>>>>> style in Binutils/GDB, or both.
>>>>
>>>> A warning should be expected in this case.  Before the recent GCC
>>>> change it was inadvertently suppressed in gdb_assert macros by its
>>>> operand being enclosed in parentheses.
>>>
>>> This issue was just posted to the GDB list, and I wanted to clarify my
>>> understanding a bit.
>>>
>>> I believe that (at least by default) adding the nonnull attribute
>>> allows GCC to assume (in the above case) that filename will not be
>>> NULL and generate code accordingly.
>>>
>>> Additionally, passing an explicit NULL (i.e. 'unlinker obj (NULL)')
>>> would cause a compile time error.
>>>
>>> But, there's nothing to actually stop a NULL being passed due to, say,
>>> a logic bug in the program.  So, something like this would compile
>>> fine:
>>>
>>>     extern const char *ptr;
>>>     unlinker obj (ptr);
>>>
>>> And in a separate compilation unit:
>>>
>>>     const char *ptr = NULL;
>>>
>>> Obviously, the run time behaviour of such a program would be
>>> undefined.
>>>
>>> Given the above then, it doesn't seem crazy to want to do something
>>> like the above, that is, add an assert to catch a logic bug in the
>>> program.
>>>
>>> Is there an approved mechanism through which I can tell GCC that I
>>> really do want to do a comparison to NULL, without any warning, and
>>> without the check being optimised out?
>>
> 
> Thanks for your feedback.
> 
>> The manual says -fno-delete-null-pointer-checks is supposed to
>> prevent the removal of the null function argument test so I'd
>> expect adding attribute optimize ("no-delete-null-pointer-checks")
>> to the definition of the function to have that effect but in my
>> testing it didn't work (and didn't give a warning for the two
>> attributes on the same declarataion).  That seems worth filing
>> a bug for.
> 
> I've since been pointed at this:
> 
>    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100404
> 
> Comment #3 of which discusses exactly this issue.

I had forgotten about that discussion and opened PR 101665.  Thanks
for the pointer!  Let me link the two and see about updating
the manual and maybe also issuing a warning when both attributes
are set on the same function.

Martin

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)
  2021-06-23 19:47           ` Martin Sebor
  2021-06-24  5:26             ` Jeff Law
@ 2021-09-01 19:35             ` Thomas Schwinge
  2021-09-02  0:14               ` Martin Sebor
  1 sibling, 1 reply; 98+ messages in thread
From: Thomas Schwinge @ 2021-09-01 19:35 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 14845 bytes --]

Hi!

On 2021-06-23T13:47:08-0600, Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
> On 6/22/21 5:28 PM, David Malcolm wrote:
>> On Tue, 2021-06-22 at 19:18 -0400, David Malcolm wrote:
>>> On Fri, 2021-06-04 at 15:41 -0600, Martin Sebor wrote:
>>>> The attached patch introduces the suppress_warning(),
>>>> warning_suppressed(), and copy_no_warning() APIs [etc.]

Martin, great work on this!

I was a bit surprised to see this key on 'location_t's -- but indeed it
appears to do the right thing.

I now had a bit of a deep dive into some aspects of this, in context of
<https://gcc.gnu.org/PR101574> "gcc/sparseset.h:215:20: error: suggest
parentheses around assignment used as truth value [-Werror=parentheses]"
that I recently filed.  This seems difficult to reproduce, but I'm still
able to reliably reproduce it in one specific build
configuration/directory/machine/whatever.  Initially, we all quickly
assumed that it'd be some GC issue -- but "alas", it's not, at least not
directly.  (But I'll certainly assume that some GC aspects are involved
which make this issue come and go across different GCC sources revisions,
and difficult to reproduce.)

First, two pieces of cleanup:

> --- /dev/null
> +++ b/gcc/warning-control.cc

> +template <class ToType, class FromType>
> +void copy_warning (ToType to, FromType from)
> +{
> +  const key_type_t to_key = convert_to_key (to);
> +
> +  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
> +    {
> +      /* If there's an entry in the map the no-warning bit must be set.  */
> +      gcc_assert (get_no_warning_bit (from));
> +
> +      if (!nowarn_map)
> +     nowarn_map = xint_hash_map_t::create_ggc (32);

OK to push "Simplify 'gcc/diagnostic-spec.h:nowarn_map' setup", see
attached?  If we've just read something from the map, we can be sure that
it exists.  ;-)

> --- /dev/null
> +++ b/gcc/diagnostic-spec.h

> +typedef location_t key_type_t;
> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
> +typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
> +
> +/* A mapping from the location of an expression to the warning spec
> +   set for it.  */
> +extern GTY(()) xint_hash_map_t *nowarn_map;

More on that data structure setup in a later email; here I'd like to
"Clarify 'key_type_t' to 'location_t' as used for
'gcc/diagnostic-spec.h:nowarn_map'", see attached.  OK to push?  To make
it obvious what exactly the key type is.  No change in behavior.

Why is this relevant?  Via current 'int_hash<key_type_t, 0, UINT_MAX>',
we create a 'int_hash' using "spare" value '0' for 'Empty' marker, and
"spare" value 'UINT_MAX' for 'Deleted' marker.  Now, the latter is
unlikely to ever trigger (but still not correct -- patch in testing), but
the former triggers very much so: value '0' is, per 'gcc/input.h':

    #define UNKNOWN_LOCATION ((location_t) 0)

..., and there are no safe-guards in the code here, so we'll happily put
key 'UNKNOWN_LOCATION' into the 'nowarn_map', and all the
'UNKNOWN_LOCATION' entries share (replace?) one single warning
disposition (problem!), and at the same time that key value is also used
as the 'Empty' marker (problem!).  I have not tried to understand why
this doesn't cause much greater breakage, but propose to fix this as per
the attached "Don't maintain a warning spec for
'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574]".  OK to push?

Leaving aside that for 'UNKNOWN_LOCATION' -- per my understanding, at
least, as per above -- the current implementation isn't doing the right
thing anyway, Richard had in
<http://mid.mail-archive.com/CAFiYyc2am7_pcN4+dvgFSxumnQzYuNRefFWf-zDHiJv-n8EA_w@mail.gmail.com>
toyed with the idea that we for "UNKNOWN_LOCATION create a new location
with the source location being still UNKNOWN but with the appropriate
ad-hoc data to disable the warning".  On the other hand, we have Martin's
initial goal,
<http://mid.mail-archive.com/92db3776-af59-fa20-483b-aa67b17d0751@gmail.com>,
that he'd like to "work toward providing locations for all
expressions/statements".  (I agree -- and get rid of "location wrapper"
nodes at the same time...)  So there certainly is follow-on work to be
done re 'UNKNOWN_LOCATION's, but that's orthogonal to the issue I'm
fixing here.  (Just mentioning all this for context.)

I'm reasonably confident that my changes are doing the right things in
general, but please carefully review, especially here:

  - 'gcc/warning-control.cc:suppress_warning' functions: is it correct to
    conditionalize on '!RESERVED_LOCATION_P' the 'suppress_warning_at'
    calls and 'supp' update?  Or, should instead 'suppress_warning_at'
    handle the case of '!RESERVED_LOCATION_P'?  (How?)

  - 'gcc/diagnostic-spec.c:copy_warning' and
    'gcc/warning-control.cc:copy_warning': is the rationale correct for
    the 'gcc_checking_assert (!from_spec)': "If we cannot set no-warning
    dispositions for 'to', ascertain that we don't have any for 'from'.
    Otherwise, we'd lose these."?  If the rationale is correct, then
    observing that in 'gcc/warning-control.cc:copy_warning' this
    currently "triggers during GCC build" is something to be looked into,
    later, I suppose, and otherwise, how should I change this code?

Gating on 'RESERVED_LOCATION_P' is what other similar code in GCC is
doing.  Conveniently, that frees up the two values
'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' for use as 'Empty'/'Deleted'
markers -- patch in testing.

Plus some more cleanup that fell out during analysis/development --
patches in testing.

Oh, and one of these actually (unintentially so) happens to resolve
<https://gcc.gnu.org/PR101204> "[12 Regression] infinite recursion in
gtype-desc.c since r12-1801-g7036e9ef462fde8181bece4ac4e03f3aa27204dc",
so unless you've done any work on that, may I take over that PR?

What my patches are not addressing is <https://gcc.gnu.org/PR101292>
"[12 Regression] recent valgrind error in warning-control.cc since
r12-1804-g65870e75616ee4359d1c13b99be794e6a577bc65", and with the
'gcc_assert (*from_map != 0xa5a5a5a5);' I'm actually able to trigger
that during GCC build itself.

Are you aware of any other PRs related to this functionality that I
should re-evaluate?


Grüße
 Thomas


PS.  Relevant code quoted for reference, in case that's useful:

> --- /dev/null
> +++ b/gcc/diagnostic-spec.h

> [...]

> +typedef location_t key_type_t;
> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
> +typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
> +
> +/* A mapping from the location of an expression to the warning spec
> +   set for it.  */
> +extern GTY(()) xint_hash_map_t *nowarn_map;

> [...]

> --- /dev/null
> +++ b/gcc/diagnostic-spec.c

> [...]

> +/* Map from location to its no-warning disposition.  */
> +
> +GTY(()) xint_hash_map_t *nowarn_map;
> +
> +/* Return the no-warning disposition for location LOC and option OPT
> +   or for all/any otions by default.  */
> +
> +bool
> +warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
> +{
> +  if (!nowarn_map)
> +    return false;
> +
> +  if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
> +    {
> +      const nowarn_spec_t optspec (opt);
> +      return *pspec & optspec;
> +    }
> +
> +  return false;
> +}
> +
> + /* Change the supression of warnings at location LOC.
> +    OPT controls which warnings are affected.
> +    The wildcard OPT of -1 controls all warnings.
> +    If SUPP is true (the default), enable the suppression of the warnings.
> +    If SUPP is false, disable the suppression of the warnings.  */
> +
> +bool
> +suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
> +                  bool supp /* = true */)
> +{
> +  const nowarn_spec_t optspec (supp ? opt : opt_code ());
> +
> +  if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
> +    {
> +      if (supp)
> +     {
> +       *pspec |= optspec;
> +       return true;
> +     }
> +
> +      *pspec &= optspec;
> +      if (*pspec)
> +     return true;
> +
> +      nowarn_map->remove (loc);
> +      return false;
> +    }
> +
> +  if (!supp || opt == no_warning)
> +    return false;
> +
> +  if (!nowarn_map)
> +    nowarn_map = xint_hash_map_t::create_ggc (32);
> +
> +  nowarn_map->put (loc, optspec);
> +  return true;
> +}
> +
> +/* Copy the no-warning disposition from one location to another.  */
> +
> +void
> +copy_warning (location_t to, location_t from)
> +{
> +  if (!nowarn_map)
> +    return;
> +
> +  if (nowarn_spec_t *pspec = nowarn_map->get (from))
> +    nowarn_map->put (to, *pspec);
> +  else
> +    nowarn_map->remove (to);
> +}

> --- /dev/null
> +++ b/gcc/warning-control.cc

> [...]

> +/* Return the no-warning bit for EXPR.  */
> +
> +static inline bool
> +get_no_warning_bit (const_tree expr)
> +{
> +  return expr->base.nowarning_flag;
> +}
> +
> +/* Return the no-warning bit for statement STMT.  */
> +
> +static inline bool
> +get_no_warning_bit (const gimple *stmt)
> +{
> +  return stmt->no_warning;
> +}
> +
> +/* Set the no-warning bit for EXPR to VALUE.  */
> +
> +static inline void
> +set_no_warning_bit (tree expr, bool value)
> +{
> +  expr->base.nowarning_flag = value;
> +}
> +
> +/* Set the no-warning bit for statement STMT to VALUE.  */
> +
> +static inline void
> +set_no_warning_bit (gimple *stmt, bool value)
> +{
> +  stmt->no_warning = value;
> +}
> +
> +/* Return EXPR location or zero.  */
> +
> +static inline key_type_t
> +convert_to_key (const_tree expr)
> +{
> +  if (DECL_P (expr))
> +    return DECL_SOURCE_LOCATION (expr);
> +  if (EXPR_P (expr))
> +    return EXPR_LOCATION (expr);
> +  return 0;
> +}
> +
> +/* Return STMT location (may be zero).  */
> +
> +static inline key_type_t
> +convert_to_key (const gimple *stmt)
> +{
> +  return gimple_location (stmt);
> +}
> +
> +/* Return the no-warning bitmap for decl/expression EXPR.  */
> +
> +static nowarn_spec_t *
> +get_nowarn_spec (const_tree expr)
> +{
> +  const key_type_t key = convert_to_key (expr);
> +
> +  if (!get_no_warning_bit (expr) || !key)
> +    return NULL;
> +
> +  return nowarn_map ? nowarn_map->get (key) : NULL;
> +}
> +
> +/* Return the no-warning bitmap for stateemt STMT.  */
> +
> +static nowarn_spec_t *
> +get_nowarn_spec (const gimple *stmt)
> +{
> +  const key_type_t key = convert_to_key (stmt);
> +
> +  if (!get_no_warning_bit (stmt))
> +    return NULL;
> +
> +  return nowarn_map ? nowarn_map->get (key) : NULL;
> +}
> +
> +/* Return true if warning OPT is suppressed for decl/expression EXPR.
> +   By default tests the disposition for any warning.  */
> +
> +bool
> +warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
> +{
> +  const nowarn_spec_t *spec = get_nowarn_spec (expr);
> +
> +  if (!spec)
> +    return get_no_warning_bit (expr);
> +
> +  const nowarn_spec_t optspec (opt);
> +  bool dis = *spec & optspec;
> +  gcc_assert (get_no_warning_bit (expr) || !dis);
> +  return dis;
> +}
> +
> +/* Return true if warning OPT is suppressed for statement STMT.
> +   By default tests the disposition for any warning.  */
> +
> +bool
> +warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */)
> +{
> +  const nowarn_spec_t *spec = get_nowarn_spec (stmt);
> +
> +  if (!spec)
> +    /* Fall back on the single no-warning bit.  */
> +    return get_no_warning_bit (stmt);
> +
> +  const nowarn_spec_t optspec (opt);
> +  bool dis = *spec & optspec;
> +  gcc_assert (get_no_warning_bit (stmt) || !dis);
> +  return dis;
> +}
> +
> +/* Enable, or by default disable, a warning for the expression.
> +   The wildcard OPT of -1 controls all warnings.  */
> +
> +void
> +suppress_warning (tree expr, opt_code opt /* = all_warnings */,
> +               bool supp /* = true */)
> +{
> +  if (opt == no_warning)
> +    return;
> +
> +  const key_type_t key = convert_to_key (expr);
> +
> +  supp = suppress_warning_at (key, opt, supp) || supp;
> +  set_no_warning_bit (expr, supp);
> +}
> +
> +/* Enable, or by default disable, a warning for the statement STMT.
> +   The wildcard OPT of -1 controls all warnings.  */
> +
> +void
> +suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
> +               bool supp /* = true */)
> +{
> +  if (opt == no_warning)
> +    return;
> +
> +  const key_type_t key = convert_to_key (stmt);
> +
> +  supp = suppress_warning_at (key, opt, supp) || supp;
> +  set_no_warning_bit (stmt, supp);
> +}
> +
> +/* Copy the warning disposition mapping between an expression and/or
> +   a statement.  */
> +
> +template <class ToType, class FromType>
> +void copy_warning (ToType to, FromType from)
> +{
> +  const key_type_t to_key = convert_to_key (to);
> +
> +  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
> +    {
> +      /* If there's an entry in the map the no-warning bit must be set.  */
> +      gcc_assert (get_no_warning_bit (from));
> +
> +      if (!nowarn_map)
> +     nowarn_map = xint_hash_map_t::create_ggc (32);
> +
> +      nowarn_map->put (to_key, *from_map);
> +      set_no_warning_bit (to, true);
> +    }
> +  else
> +    {
> +      if (nowarn_map)
> +     nowarn_map->remove (to_key);
> +
> +      /* The no-warning bit might be set even if there's no entry
> +      in the map.  */
> +      set_no_warning_bit (to, get_no_warning_bit (from));
> +    }
> +}
> +
> +/* Copy the warning disposition mapping from one expression to another.  */
> +
> +void
> +copy_warning (tree to, const_tree from)
> +{
> +  copy_warning<tree, const_tree>(to, from);
> +}
> +
> +/* Copy the warning disposition mapping from a statement to an expression.  */
> +
> +void
> +copy_warning (tree to, const gimple *from)
> +{
> +  copy_warning<tree, const gimple *>(to, from);
> +}
> +
> +/* Copy the warning disposition mapping from an expression to a statement.  */
> +
> +void
> +copy_warning (gimple *to, const_tree from)
> +{
> +  copy_warning<gimple *, const_tree>(to, from);
> +}
> +
> +/* Copy the warning disposition mapping from one statement to another.  */
> +
> +void
> +copy_warning (gimple *to, const gimple *from)
> +{
> +  copy_warning<gimple *, const gimple *>(to, from);
> +}


Grüße
 Thomas


-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Simplify-gcc-diagnostic-spec.h-nowarn_map-setup.patch --]
[-- Type: text/x-diff, Size: 1025 bytes --]

From 095c16ead5d432726f2b6de5ce12fd367600076d Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Wed, 1 Sep 2021 16:48:55 +0200
Subject: [PATCH 1/3] Simplify 'gcc/diagnostic-spec.h:nowarn_map' setup

If we've just read something from the map, we can be sure that it exists.

	gcc/
	* warning-control.cc (copy_warning): Remove 'nowarn_map' setup.
---
 gcc/warning-control.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index ec8ed232763..9c506e163d6 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -188,9 +188,7 @@ void copy_warning (ToType to, FromType from)
       /* If there's an entry in the map the no-warning bit must be set.  */
       gcc_assert (get_no_warning_bit (from));
 
-      if (!nowarn_map)
-	nowarn_map = xint_hash_map_t::create_ggc (32);
-
+      gcc_checking_assert (nowarn_map);
       nowarn_map->put (to_key, *from_map);
       set_no_warning_bit (to, true);
     }
-- 
2.30.2


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-Clarify-key_type_t-to-location_t-as-used-for-gcc-dia.patch --]
[-- Type: text/x-diff, Size: 5439 bytes --]

From 23d9b93401349fca03efaef0fef0960933f4c316 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Tue, 31 Aug 2021 22:01:23 +0200
Subject: [PATCH 2/3] Clarify 'key_type_t' to 'location_t' as used for
 'gcc/diagnostic-spec.h:nowarn_map'

To make it obvious what exactly the key type is.  No change in behavior.

	gcc/
	* diagnostic-spec.h (typedef xint_hash_t): Use 'location_t' instead of...
	(typedef key_type_t): ... this.  Remove.
	(nowarn_map): Document.
	* diagnostic-spec.c (nowarn_map): Likewise.
	* warning-control.cc (convert_to_key): Evolve functions into...
	(get_location): ... these.  Adjust all users.
---
 gcc/diagnostic-spec.c  |  2 +-
 gcc/diagnostic-spec.h  |  6 ++----
 gcc/warning-control.cc | 41 ++++++++++++++++++++++-------------------
 3 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index 5e961e1b9f9..eac5a3317c8 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -105,7 +105,7 @@ nowarn_spec_t::nowarn_spec_t (opt_code opt)
     }
 }
 
-/* Map from location to its no-warning disposition.  */
+/* A mapping from a 'location_t' to the warning spec set for it.  */
 
 GTY(()) xint_hash_map_t *nowarn_map;
 
diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
index 4e4d260f74a..9b3aaaa3ce6 100644
--- a/gcc/diagnostic-spec.h
+++ b/gcc/diagnostic-spec.h
@@ -130,12 +130,10 @@ operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
   return !(lhs == rhs);
 }
 
-typedef location_t key_type_t;
-typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
+typedef int_hash <location_t, 0, UINT_MAX> xint_hash_t;
 typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
 
-/* A mapping from the location of an expression to the warning spec
-   set for it.  */
+/* A mapping from a 'location_t' to the warning spec set for it.  */
 extern GTY(()) xint_hash_map_t *nowarn_map;
 
 #endif // DIAGNOSTIC_SPEC_H_INCLUDED
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index 9c506e163d6..8d6c0828445 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -62,22 +62,22 @@ set_no_warning_bit (gimple *stmt, bool value)
   stmt->no_warning = value;
 }
 
-/* Return EXPR location or zero.  */
+/* Return EXPR location or 'UNKNOWN_LOCATION'.  */
 
-static inline key_type_t
-convert_to_key (const_tree expr)
+static inline location_t
+get_location (const_tree expr)
 {
   if (DECL_P (expr))
     return DECL_SOURCE_LOCATION (expr);
   if (EXPR_P (expr))
     return EXPR_LOCATION (expr);
-  return 0;
+  return UNKNOWN_LOCATION;
 }
 
-/* Return STMT location (may be zero).  */
+/* Return STMT location (may be 'UNKNOWN_LOCATION').  */
 
-static inline key_type_t
-convert_to_key (const gimple *stmt)
+static inline location_t
+get_location (const gimple *stmt)
 {
   return gimple_location (stmt);
 }
@@ -87,12 +87,15 @@ convert_to_key (const gimple *stmt)
 static nowarn_spec_t *
 get_nowarn_spec (const_tree expr)
 {
-  const key_type_t key = convert_to_key (expr);
+  const location_t loc = get_location (expr);
 
-  if (!get_no_warning_bit (expr) || !key)
+  if (loc == UNKNOWN_LOCATION)
     return NULL;
 
-  return nowarn_map ? nowarn_map->get (key) : NULL;
+  if (!get_no_warning_bit (expr))
+    return NULL;
+
+  return nowarn_map ? nowarn_map->get (loc) : NULL;
 }
 
 /* Return the no-warning bitmap for stateemt STMT.  */
@@ -100,12 +103,12 @@ get_nowarn_spec (const_tree expr)
 static nowarn_spec_t *
 get_nowarn_spec (const gimple *stmt)
 {
-  const key_type_t key = convert_to_key (stmt);
+  const location_t loc = get_location (stmt);
 
   if (!get_no_warning_bit (stmt))
     return NULL;
 
-  return nowarn_map ? nowarn_map->get (key) : NULL;
+  return nowarn_map ? nowarn_map->get (loc) : NULL;
 }
 
 /* Return true if warning OPT is suppressed for decl/expression EXPR.
@@ -153,9 +156,9 @@ suppress_warning (tree expr, opt_code opt /* = all_warnings */,
   if (opt == no_warning)
     return;
 
-  const key_type_t key = convert_to_key (expr);
+  const location_t loc = get_location (expr);
 
-  supp = suppress_warning_at (key, opt, supp) || supp;
+  supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (expr, supp);
 }
 
@@ -169,9 +172,9 @@ suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
   if (opt == no_warning)
     return;
 
-  const key_type_t key = convert_to_key (stmt);
+  const location_t loc = get_location (stmt);
 
-  supp = suppress_warning_at (key, opt, supp) || supp;
+  supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (stmt, supp);
 }
 
@@ -181,7 +184,7 @@ suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
 template <class ToType, class FromType>
 void copy_warning (ToType to, FromType from)
 {
-  const key_type_t to_key = convert_to_key (to);
+  const location_t to_loc = get_location (to);
 
   if (nowarn_spec_t *from_map = get_nowarn_spec (from))
     {
@@ -189,13 +192,13 @@ void copy_warning (ToType to, FromType from)
       gcc_assert (get_no_warning_bit (from));
 
       gcc_checking_assert (nowarn_map);
-      nowarn_map->put (to_key, *from_map);
+      nowarn_map->put (to_loc, *from_map);
       set_no_warning_bit (to, true);
     }
   else
     {
       if (nowarn_map)
-	nowarn_map->remove (to_key);
+	nowarn_map->remove (to_loc);
 
       /* The no-warning bit might be set even if there's no entry
 	 in the map.  */
-- 
2.30.2


[-- Attachment #4: 0003-Don-t-maintain-a-warning-spec-for-UNKNOWN_LOCATION-B.patch --]
[-- Type: text/x-diff, Size: 6034 bytes --]

From 79d636fadf43a1ae62e30013f868521a8a0529f5 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Mon, 30 Aug 2021 22:36:47 +0200
Subject: [PATCH 3/3] Don't maintain a warning spec for
 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574]
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This resolves PR101574 "gcc/sparseset.h:215:20: error: suggest parentheses
around assignment used as truth value [-Werror=parentheses]", as (bogusly)
reported at commit a61f6afbee370785cf091fe46e2e022748528307:

    In file included from [...]/source-gcc/gcc/lra-lives.c:43:
    [...]/source-gcc/gcc/lra-lives.c: In function ‘void make_hard_regno_dead(int)’:
    [...]/source-gcc/gcc/sparseset.h:215:20: error: suggest parentheses around assignment used as truth value [-Werror=parentheses]
      215 |        && (((ITER) = sparseset_iter_elm (SPARSESET)) || 1);             \
          |            ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    [...]/source-gcc/gcc/lra-lives.c:304:3: note: in expansion of macro ‘EXECUTE_IF_SET_IN_SPARSESET’
      304 |   EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
          |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~

	gcc/
	PR bootstrap/101574
	* diagnostic-spec.c (warning_suppressed_at, copy_warning): Handle
	'RESERVED_LOCATION_P' locations.
	* warning-control.cc (get_nowarn_spec, suppress_warning)
	(copy_warning): Likewise.
---
 gcc/diagnostic-spec.c  | 24 +++++++++++++++++---
 gcc/warning-control.cc | 50 ++++++++++++++++++++++++++++--------------
 2 files changed, 55 insertions(+), 19 deletions(-)

diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index eac5a3317c8..76b5d5e57f5 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -115,6 +115,8 @@ GTY(()) xint_hash_map_t *nowarn_map;
 bool
 warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
 {
+  gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+
   if (!nowarn_map)
     return false;
 
@@ -137,6 +139,8 @@ bool
 suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
 		     bool supp /* = true */)
 {
+  gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+
   const nowarn_spec_t optspec (supp ? opt : opt_code ());
 
   if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
@@ -173,8 +177,22 @@ copy_warning (location_t to, location_t from)
   if (!nowarn_map)
     return;
 
-  if (nowarn_spec_t *pspec = nowarn_map->get (from))
-    nowarn_map->put (to, *pspec);
+  nowarn_spec_t *from_spec;
+  if (RESERVED_LOCATION_P (from))
+    from_spec = NULL;
   else
-    nowarn_map->remove (to);
+    from_spec = nowarn_map->get (from);
+  if (RESERVED_LOCATION_P (to))
+    {
+      /* If we cannot set no-warning dispositions for 'to', ascertain that we
+	 don't have any for 'from'.  Otherwise, we'd lose these.  */
+      gcc_checking_assert (!from_spec);
+    }
+  else
+    {
+      if (from_spec)
+	nowarn_map->put (to, *from_spec);
+      else
+	nowarn_map->remove (to);
+    }
 }
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index 8d6c0828445..cca4b3bf8e1 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -89,7 +89,7 @@ get_nowarn_spec (const_tree expr)
 {
   const location_t loc = get_location (expr);
 
-  if (loc == UNKNOWN_LOCATION)
+  if (RESERVED_LOCATION_P (loc))
     return NULL;
 
   if (!get_no_warning_bit (expr))
@@ -105,6 +105,9 @@ get_nowarn_spec (const gimple *stmt)
 {
   const location_t loc = get_location (stmt);
 
+  if (RESERVED_LOCATION_P (loc))
+    return NULL;
+
   if (!get_no_warning_bit (stmt))
     return NULL;
 
@@ -158,7 +161,8 @@ suppress_warning (tree expr, opt_code opt /* = all_warnings */,
 
   const location_t loc = get_location (expr);
 
-  supp = suppress_warning_at (loc, opt, supp) || supp;
+  if (!RESERVED_LOCATION_P (loc))
+    supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (expr, supp);
 }
 
@@ -174,7 +178,8 @@ suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
 
   const location_t loc = get_location (stmt);
 
-  supp = suppress_warning_at (loc, opt, supp) || supp;
+  if (!RESERVED_LOCATION_P (loc))
+    supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (stmt, supp);
 }
 
@@ -186,24 +191,37 @@ void copy_warning (ToType to, FromType from)
 {
   const location_t to_loc = get_location (to);
 
-  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
-    {
-      /* If there's an entry in the map the no-warning bit must be set.  */
-      gcc_assert (get_no_warning_bit (from));
+  bool supp = get_no_warning_bit (from);
 
-      gcc_checking_assert (nowarn_map);
-      nowarn_map->put (to_loc, *from_map);
-      set_no_warning_bit (to, true);
+  nowarn_spec_t *from_spec = get_nowarn_spec (from);
+  if (RESERVED_LOCATION_P (to_loc))
+    {
+#if 0 //TODO triggers during GCC build
+      /* If we cannot set no-warning dispositions for 'to', ascertain that we
+	 don't have any for 'from'.  Otherwise, we'd lose these.  */
+      gcc_checking_assert (!from_spec);
+#endif
     }
   else
     {
-      if (nowarn_map)
-	nowarn_map->remove (to_loc);
-
-      /* The no-warning bit might be set even if there's no entry
-	 in the map.  */
-      set_no_warning_bit (to, get_no_warning_bit (from));
+      if (from_spec)
+	{
+	  /* If there's an entry in the map the no-warning bit must be set.  */
+	  gcc_assert (supp);
+
+	  gcc_checking_assert (nowarn_map);
+	  nowarn_map->put (to_loc, *from_spec);
+	}
+      else
+	{
+	  if (nowarn_map)
+	    nowarn_map->remove (to_loc);
+	}
     }
+
+  /* The no-warning bit might be set even if the map has not been consulted, or
+     otherwise if there's no entry in the map.  */
+  set_no_warning_bit (to, supp);
 }
 
 /* Copy the warning disposition mapping from one expression to another.  */
-- 
2.30.2


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)
  2021-09-01 19:35             ` Thomas Schwinge
@ 2021-09-02  0:14               ` Martin Sebor
  2021-09-03 19:16                 ` Thomas Schwinge
  2021-11-09 10:28                 ` Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)) Thomas Schwinge
  0 siblings, 2 replies; 98+ messages in thread
From: Martin Sebor @ 2021-09-02  0:14 UTC (permalink / raw)
  To: Thomas Schwinge, gcc-patches

On 9/1/21 1:35 PM, Thomas Schwinge wrote:
> Hi!
> 
> On 2021-06-23T13:47:08-0600, Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>> On 6/22/21 5:28 PM, David Malcolm wrote:
>>> On Tue, 2021-06-22 at 19:18 -0400, David Malcolm wrote:
>>>> On Fri, 2021-06-04 at 15:41 -0600, Martin Sebor wrote:
>>>>> The attached patch introduces the suppress_warning(),
>>>>> warning_suppressed(), and copy_no_warning() APIs [etc.]
> 
> Martin, great work on this!
> 
> I was a bit surprised to see this key on 'location_t's -- but indeed it
> appears to do the right thing.
> 
> I now had a bit of a deep dive into some aspects of this, in context of
> <https://gcc.gnu.org/PR101574> "gcc/sparseset.h:215:20: error: suggest
> parentheses around assignment used as truth value [-Werror=parentheses]"
> that I recently filed.  This seems difficult to reproduce, but I'm still
> able to reliably reproduce it in one specific build
> configuration/directory/machine/whatever.  Initially, we all quickly
> assumed that it'd be some GC issue -- but "alas", it's not, at least not
> directly.  (But I'll certainly assume that some GC aspects are involved
> which make this issue come and go across different GCC sources revisions,
> and difficult to reproduce.)
> 
> First, two pieces of cleanup:
> 
>> --- /dev/null
>> +++ b/gcc/warning-control.cc
> 
>> +template <class ToType, class FromType>
>> +void copy_warning (ToType to, FromType from)
>> +{
>> +  const key_type_t to_key = convert_to_key (to);
>> +
>> +  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
>> +    {
>> +      /* If there's an entry in the map the no-warning bit must be set.  */
>> +      gcc_assert (get_no_warning_bit (from));
>> +
>> +      if (!nowarn_map)
>> +     nowarn_map = xint_hash_map_t::create_ggc (32);
> 
> OK to push "Simplify 'gcc/diagnostic-spec.h:nowarn_map' setup", see
> attached?  If we've just read something from the map, we can be sure that
> it exists.  ;-)

Cleanup is definitely okay by me.  I can't formally approve anything
but this looks clearly correct and an improvement.

> 
>> --- /dev/null
>> +++ b/gcc/diagnostic-spec.h
> 
>> +typedef location_t key_type_t;
>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
>> +typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
>> +
>> +/* A mapping from the location of an expression to the warning spec
>> +   set for it.  */
>> +extern GTY(()) xint_hash_map_t *nowarn_map;
> 
> More on that data structure setup in a later email; here I'd like to
> "Clarify 'key_type_t' to 'location_t' as used for
> 'gcc/diagnostic-spec.h:nowarn_map'", see attached.  OK to push?  To make
> it obvious what exactly the key type is.  No change in behavior.

That's fine with me too and also like worthwhile cleanup.

FWIW, I used different key_type_t while prototyping the solution but
now that we've settled on location_t I see no reason not to use it
directly.

By the way, it seems we should probably also use a manifest constant
for Empty (probably UNKNOWN_LOCATION since we're reserving it).

> 
> Why is this relevant?  Via current 'int_hash<key_type_t, 0, UINT_MAX>',
> we create a 'int_hash' using "spare" value '0' for 'Empty' marker, and
> "spare" value 'UINT_MAX' for 'Deleted' marker.  Now, the latter is
> unlikely to ever trigger (but still not correct -- patch in testing), but
> the former triggers very much so: value '0' is, per 'gcc/input.h':
> 
>      #define UNKNOWN_LOCATION ((location_t) 0)
> 
> ..., and there are no safe-guards in the code here, so we'll happily put
> key 'UNKNOWN_LOCATION' into the 'nowarn_map', and all the
> 'UNKNOWN_LOCATION' entries share (replace?) one single warning
> disposition (problem!), and at the same time that key value is also used
> as the 'Empty' marker (problem!).  I have not tried to understand why
> this doesn't cause much greater breakage, but propose to fix this as per
> the attached "Don't maintain a warning spec for
> 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574]".  OK to push?

You're right that all expressions/statements with no location end
up sharing the same entry in the map when one is written to.
The entry should never be read from for expressions or statements
(they should fall back on their no-warning bit).  The entry should
only be read by a call to warning_suppressed_at(loc, ...).
The Empty problem aside, I would think it's reasonable to return
the union of all suppressions for location zero (or for the decls
of all builtins).  But I never tested this (I'm not really sure
how), and I forgot to consider that UNKNOWN_LOCATION has the same
value as Empty.  So I agree that it ought to be fixed.

> 
> Leaving aside that for 'UNKNOWN_LOCATION' -- per my understanding, at
> least, as per above -- the current implementation isn't doing the right
> thing anyway, Richard had in
> <http://mid.mail-archive.com/CAFiYyc2am7_pcN4+dvgFSxumnQzYuNRefFWf-zDHiJv-n8EA_w@mail.gmail.com>
> toyed with the idea that we for "UNKNOWN_LOCATION create a new location
> with the source location being still UNKNOWN but with the appropriate
> ad-hoc data to disable the warning".  On the other hand, we have Martin's
> initial goal,
> <http://mid.mail-archive.com/92db3776-af59-fa20-483b-aa67b17d0751@gmail.com>,
> that he'd like to "work toward providing locations for all
> expressions/statements".  (I agree -- and get rid of "location wrapper"
> nodes at the same time...)  So there certainly is follow-on work to be
> done re 'UNKNOWN_LOCATION's, but that's orthogonal to the issue I'm
> fixing here.  (Just mentioning all this for context.)
> 
> I'm reasonably confident that my changes are doing the right things in
> general, but please carefully review, especially here:
> 
>    - 'gcc/warning-control.cc:suppress_warning' functions: is it correct to
>      conditionalize on '!RESERVED_LOCATION_P' the 'suppress_warning_at'
>      calls and 'supp' update?  Or, should instead 'suppress_warning_at'
>      handle the case of '!RESERVED_LOCATION_P'?  (How?)

It seems like six of one vs half a dozen of the other.  I'd say go
with whatever makes more sense to you here :)

> 
>    - 'gcc/diagnostic-spec.c:copy_warning' and
>      'gcc/warning-control.cc:copy_warning': is the rationale correct for
>      the 'gcc_checking_assert (!from_spec)': "If we cannot set no-warning
>      dispositions for 'to', ascertain that we don't have any for 'from'.
>      Otherwise, we'd lose these."?  If the rationale is correct, then
>      observing that in 'gcc/warning-control.cc:copy_warning' this
>      currently "triggers during GCC build" is something to be looked into,
>      later, I suppose, and otherwise, how should I change this code?

copy_warning(location_t, location_t) is called [only] from
gimple_set_location().  The middle end does clear the location of
some statements for which it was previously valid (e.g., return
statements).  So I wouldn't expect this assumption to be safe.  If
that happens, we have no choice but to lose the per-warning detail
and fall back on the no-warning bit.

> Gating on 'RESERVED_LOCATION_P' is what other similar code in GCC is
> doing.  Conveniently, that frees up the two values
> 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' for use as 'Empty'/'Deleted'
> markers -- patch in testing.
> 
> Plus some more cleanup that fell out during analysis/development --
> patches in testing.
> 
> Oh, and one of these actually (unintentially so) happens to resolve
> <https://gcc.gnu.org/PR101204> "[12 Regression] infinite recursion in
> gtype-desc.c since r12-1801-g7036e9ef462fde8181bece4ac4e03f3aa27204dc",
> so unless you've done any work on that, may I take over that PR?

I haven't.  Thanks for offering to take it on!  I'm curious to
hear how your change fixes that problem.

> 
> What my patches are not addressing is <https://gcc.gnu.org/PR101292>
> "[12 Regression] recent valgrind error in warning-control.cc since
> r12-1804-g65870e75616ee4359d1c13b99be794e6a577bc65", and with the
> 'gcc_assert (*from_map != 0xa5a5a5a5);' I'm actually able to trigger
> that during GCC build itself.

Hmm.  That makes me wonder if the change makes PR101204 go latent
rather than fixing the root cause.

> 
> Are you aware of any other PRs related to this functionality that I
> should re-evaluate?

Nope, just these two.  Thanks again for working on it!

(Either David or a middle end maintainer will need to approve the last
patch once it's final.)

Martin

> 
> 
> Grüße
>   Thomas
> 
> 
> PS.  Relevant code quoted for reference, in case that's useful:
> 
>> --- /dev/null
>> +++ b/gcc/diagnostic-spec.h
> 
>> [...]
> 
>> +typedef location_t key_type_t;
>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
>> +typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
>> +
>> +/* A mapping from the location of an expression to the warning spec
>> +   set for it.  */
>> +extern GTY(()) xint_hash_map_t *nowarn_map;
> 
>> [...]
> 
>> --- /dev/null
>> +++ b/gcc/diagnostic-spec.c
> 
>> [...]
> 
>> +/* Map from location to its no-warning disposition.  */
>> +
>> +GTY(()) xint_hash_map_t *nowarn_map;
>> +
>> +/* Return the no-warning disposition for location LOC and option OPT
>> +   or for all/any otions by default.  */
>> +
>> +bool
>> +warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
>> +{
>> +  if (!nowarn_map)
>> +    return false;
>> +
>> +  if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
>> +    {
>> +      const nowarn_spec_t optspec (opt);
>> +      return *pspec & optspec;
>> +    }
>> +
>> +  return false;
>> +}
>> +
>> + /* Change the supression of warnings at location LOC.
>> +    OPT controls which warnings are affected.
>> +    The wildcard OPT of -1 controls all warnings.
>> +    If SUPP is true (the default), enable the suppression of the warnings.
>> +    If SUPP is false, disable the suppression of the warnings.  */
>> +
>> +bool
>> +suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
>> +                  bool supp /* = true */)
>> +{
>> +  const nowarn_spec_t optspec (supp ? opt : opt_code ());
>> +
>> +  if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
>> +    {
>> +      if (supp)
>> +     {
>> +       *pspec |= optspec;
>> +       return true;
>> +     }
>> +
>> +      *pspec &= optspec;
>> +      if (*pspec)
>> +     return true;
>> +
>> +      nowarn_map->remove (loc);
>> +      return false;
>> +    }
>> +
>> +  if (!supp || opt == no_warning)
>> +    return false;
>> +
>> +  if (!nowarn_map)
>> +    nowarn_map = xint_hash_map_t::create_ggc (32);
>> +
>> +  nowarn_map->put (loc, optspec);
>> +  return true;
>> +}
>> +
>> +/* Copy the no-warning disposition from one location to another.  */
>> +
>> +void
>> +copy_warning (location_t to, location_t from)
>> +{
>> +  if (!nowarn_map)
>> +    return;
>> +
>> +  if (nowarn_spec_t *pspec = nowarn_map->get (from))
>> +    nowarn_map->put (to, *pspec);
>> +  else
>> +    nowarn_map->remove (to);
>> +}
> 
>> --- /dev/null
>> +++ b/gcc/warning-control.cc
> 
>> [...]
> 
>> +/* Return the no-warning bit for EXPR.  */
>> +
>> +static inline bool
>> +get_no_warning_bit (const_tree expr)
>> +{
>> +  return expr->base.nowarning_flag;
>> +}
>> +
>> +/* Return the no-warning bit for statement STMT.  */
>> +
>> +static inline bool
>> +get_no_warning_bit (const gimple *stmt)
>> +{
>> +  return stmt->no_warning;
>> +}
>> +
>> +/* Set the no-warning bit for EXPR to VALUE.  */
>> +
>> +static inline void
>> +set_no_warning_bit (tree expr, bool value)
>> +{
>> +  expr->base.nowarning_flag = value;
>> +}
>> +
>> +/* Set the no-warning bit for statement STMT to VALUE.  */
>> +
>> +static inline void
>> +set_no_warning_bit (gimple *stmt, bool value)
>> +{
>> +  stmt->no_warning = value;
>> +}
>> +
>> +/* Return EXPR location or zero.  */
>> +
>> +static inline key_type_t
>> +convert_to_key (const_tree expr)
>> +{
>> +  if (DECL_P (expr))
>> +    return DECL_SOURCE_LOCATION (expr);
>> +  if (EXPR_P (expr))
>> +    return EXPR_LOCATION (expr);
>> +  return 0;
>> +}
>> +
>> +/* Return STMT location (may be zero).  */
>> +
>> +static inline key_type_t
>> +convert_to_key (const gimple *stmt)
>> +{
>> +  return gimple_location (stmt);
>> +}
>> +
>> +/* Return the no-warning bitmap for decl/expression EXPR.  */
>> +
>> +static nowarn_spec_t *
>> +get_nowarn_spec (const_tree expr)
>> +{
>> +  const key_type_t key = convert_to_key (expr);
>> +
>> +  if (!get_no_warning_bit (expr) || !key)
>> +    return NULL;
>> +
>> +  return nowarn_map ? nowarn_map->get (key) : NULL;
>> +}
>> +
>> +/* Return the no-warning bitmap for stateemt STMT.  */
>> +
>> +static nowarn_spec_t *
>> +get_nowarn_spec (const gimple *stmt)
>> +{
>> +  const key_type_t key = convert_to_key (stmt);
>> +
>> +  if (!get_no_warning_bit (stmt))
>> +    return NULL;
>> +
>> +  return nowarn_map ? nowarn_map->get (key) : NULL;
>> +}
>> +
>> +/* Return true if warning OPT is suppressed for decl/expression EXPR.
>> +   By default tests the disposition for any warning.  */
>> +
>> +bool
>> +warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
>> +{
>> +  const nowarn_spec_t *spec = get_nowarn_spec (expr);
>> +
>> +  if (!spec)
>> +    return get_no_warning_bit (expr);
>> +
>> +  const nowarn_spec_t optspec (opt);
>> +  bool dis = *spec & optspec;
>> +  gcc_assert (get_no_warning_bit (expr) || !dis);
>> +  return dis;
>> +}
>> +
>> +/* Return true if warning OPT is suppressed for statement STMT.
>> +   By default tests the disposition for any warning.  */
>> +
>> +bool
>> +warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */)
>> +{
>> +  const nowarn_spec_t *spec = get_nowarn_spec (stmt);
>> +
>> +  if (!spec)
>> +    /* Fall back on the single no-warning bit.  */
>> +    return get_no_warning_bit (stmt);
>> +
>> +  const nowarn_spec_t optspec (opt);
>> +  bool dis = *spec & optspec;
>> +  gcc_assert (get_no_warning_bit (stmt) || !dis);
>> +  return dis;
>> +}
>> +
>> +/* Enable, or by default disable, a warning for the expression.
>> +   The wildcard OPT of -1 controls all warnings.  */
>> +
>> +void
>> +suppress_warning (tree expr, opt_code opt /* = all_warnings */,
>> +               bool supp /* = true */)
>> +{
>> +  if (opt == no_warning)
>> +    return;
>> +
>> +  const key_type_t key = convert_to_key (expr);
>> +
>> +  supp = suppress_warning_at (key, opt, supp) || supp;
>> +  set_no_warning_bit (expr, supp);
>> +}
>> +
>> +/* Enable, or by default disable, a warning for the statement STMT.
>> +   The wildcard OPT of -1 controls all warnings.  */
>> +
>> +void
>> +suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
>> +               bool supp /* = true */)
>> +{
>> +  if (opt == no_warning)
>> +    return;
>> +
>> +  const key_type_t key = convert_to_key (stmt);
>> +
>> +  supp = suppress_warning_at (key, opt, supp) || supp;
>> +  set_no_warning_bit (stmt, supp);
>> +}
>> +
>> +/* Copy the warning disposition mapping between an expression and/or
>> +   a statement.  */
>> +
>> +template <class ToType, class FromType>
>> +void copy_warning (ToType to, FromType from)
>> +{
>> +  const key_type_t to_key = convert_to_key (to);
>> +
>> +  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
>> +    {
>> +      /* If there's an entry in the map the no-warning bit must be set.  */
>> +      gcc_assert (get_no_warning_bit (from));
>> +
>> +      if (!nowarn_map)
>> +     nowarn_map = xint_hash_map_t::create_ggc (32);
>> +
>> +      nowarn_map->put (to_key, *from_map);
>> +      set_no_warning_bit (to, true);
>> +    }
>> +  else
>> +    {
>> +      if (nowarn_map)
>> +     nowarn_map->remove (to_key);
>> +
>> +      /* The no-warning bit might be set even if there's no entry
>> +      in the map.  */
>> +      set_no_warning_bit (to, get_no_warning_bit (from));
>> +    }
>> +}
>> +
>> +/* Copy the warning disposition mapping from one expression to another.  */
>> +
>> +void
>> +copy_warning (tree to, const_tree from)
>> +{
>> +  copy_warning<tree, const_tree>(to, from);
>> +}
>> +
>> +/* Copy the warning disposition mapping from a statement to an expression.  */
>> +
>> +void
>> +copy_warning (tree to, const gimple *from)
>> +{
>> +  copy_warning<tree, const gimple *>(to, from);
>> +}
>> +
>> +/* Copy the warning disposition mapping from an expression to a statement.  */
>> +
>> +void
>> +copy_warning (gimple *to, const_tree from)
>> +{
>> +  copy_warning<gimple *, const_tree>(to, from);
>> +}
>> +
>> +/* Copy the warning disposition mapping from one statement to another.  */
>> +
>> +void
>> +copy_warning (gimple *to, const gimple *from)
>> +{
>> +  copy_warning<gimple *, const gimple *>(to, from);
>> +}
> 
> 
> Grüße
>   Thomas
> 
> 
> -----------------
> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
> 


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)
  2021-09-02  0:14               ` Martin Sebor
@ 2021-09-03 19:16                 ` Thomas Schwinge
  2021-09-10  7:45                   ` [PING] Don't maintain a warning spec for 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)) Thomas Schwinge
  2021-11-09 14:18                   ` Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map' " Thomas Schwinge
  2021-11-09 10:28                 ` Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)) Thomas Schwinge
  1 sibling, 2 replies; 98+ messages in thread
From: Thomas Schwinge @ 2021-09-03 19:16 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 14428 bytes --]

Hi!

Martin, thanks for your review.  Now need someone to formally approve the
third patch.

On 2021-09-01T18:14:46-0600, Martin Sebor <msebor@gmail.com> wrote:
> On 9/1/21 1:35 PM, Thomas Schwinge wrote:
>> On 2021-06-23T13:47:08-0600, Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>>> On 6/22/21 5:28 PM, David Malcolm wrote:
>>>> On Tue, 2021-06-22 at 19:18 -0400, David Malcolm wrote:
>>>>> On Fri, 2021-06-04 at 15:41 -0600, Martin Sebor wrote:
>>>>>> The attached patch introduces the suppress_warning(),
>>>>>> warning_suppressed(), and copy_no_warning() APIs [etc.]

>> I now had a bit of a deep dive into some aspects of this, in context of
>> <https://gcc.gnu.org/PR101574> "gcc/sparseset.h:215:20: error: suggest
>> parentheses around assignment used as truth value [-Werror=parentheses]"
>> that I recently filed.  This seems difficult to reproduce, but I'm still
>> able to reliably reproduce it in one specific build
>> configuration/directory/machine/whatever.  Initially, we all quickly
>> assumed that it'd be some GC issue -- but "alas", it's not, at least not
>> directly.  (But I'll certainly assume that some GC aspects are involved
>> which make this issue come and go across different GCC sources revisions,
>> and difficult to reproduce.)

>> First, two pieces of cleanup:

ACKed by Martin, again attached for convenience.


>>> --- /dev/null
>>> +++ b/gcc/diagnostic-spec.h
>>
>>> +typedef location_t key_type_t;
>>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;

> By the way, it seems we should probably also use a manifest constant
> for Empty (probably UNKNOWN_LOCATION since we're reserving it).

Yes, that will be part of another patch here -- waiting for approval of
"Generalize 'gcc/input.h:struct location_hash'" posted elsewhere.


>> attached "Don't maintain a warning spec for
>> 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574]".  OK to push?
>
> [...].  So I agree that it ought to be fixed.

>> I'm reasonably confident that my changes are doing the right things in
>> general, but please carefully review, especially here:
>>
>>    - 'gcc/warning-control.cc:suppress_warning' functions: is it correct to
>>      conditionalize on '!RESERVED_LOCATION_P' the 'suppress_warning_at'
>>      calls and 'supp' update?  Or, should instead 'suppress_warning_at'
>>      handle the case of '!RESERVED_LOCATION_P'?  (How?)
>
> It seems like six of one vs half a dozen of the other.  I'd say go
> with whatever makes more sense to you here :)

OK, was just trying to make sure that I don't fail to see any non-obvious
intentions here.

>>    - 'gcc/diagnostic-spec.c:copy_warning' and
>>      'gcc/warning-control.cc:copy_warning': is the rationale correct for
>>      the 'gcc_checking_assert (!from_spec)': "If we cannot set no-warning
>>      dispositions for 'to', ascertain that we don't have any for 'from'.
>>      Otherwise, we'd lose these."?  If the rationale is correct, then
>>      observing that in 'gcc/warning-control.cc:copy_warning' this
>>      currently "triggers during GCC build" is something to be looked into,
>>      later, I suppose, and otherwise, how should I change this code?
>
> copy_warning(location_t, location_t) is called [only] from
> gimple_set_location().  The middle end does clear the location of
> some statements for which it was previously valid (e.g., return
> statements).

What I observed was that the 'assert' never triggered for the
'location_t' variant "called [only] from gimple_set_location" -- but does
trigger for some other variant.  Anyway:

> So I wouldn't expect this assumption to be safe.  If
> that happens, we have no choice but to lose the per-warning detail
> and fall back on the no-warning bit.

ACK.  I'm thus clarifying that as follows:

    --- gcc/diagnostic-spec.c
    +++ gcc/diagnostic-spec.c
    @@ -185,7 +185,5 @@ copy_warning (location_t to, location_t from)
       if (RESERVED_LOCATION_P (to))
    -    {
    -      /* If we cannot set no-warning dispositions for 'to', ascertain that we
    -    don't have any for 'from'.  Otherwise, we'd lose these.  */
    -      gcc_checking_assert (!from_spec);
    -    }
    +    /* We cannot set no-warning dispositions for 'to', so we have no chance but
    +       lose those potentially set for 'from'.  */
    +    ;
       else
    --- gcc/warning-control.cc
    +++ gcc/warning-control.cc
    @@ -197,9 +197,5 @@ void copy_warning (ToType to, FromType from)
       if (RESERVED_LOCATION_P (to_loc))
    -    {
    -#if 0 //TODO triggers during GCC build
    -      /* If we cannot set no-warning dispositions for 'to', ascertain that we
    -    don't have any for 'from'.  Otherwise, we'd lose these.  */
    -      gcc_checking_assert (!from_spec);
    -#endif
    -    }
    +    /* We cannot set no-warning dispositions for 'to', so we have no chance but
    +       lose those potentially set for 'from'.  */
    +    ;
       else

> (Either David or a middle end maintainer will need to approve the last
> patch once it's final.)

As far as I'm concerned that would be the attached third patch:
"Don't maintain a warning spec for 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION'
[PR101574]".  OK to push?


Grüße
 Thomas


>> PS.  Relevant code quoted for reference, in case that's useful:
>>
>>> --- /dev/null
>>> +++ b/gcc/diagnostic-spec.h
>>
>>> [...]
>>
>>> +typedef location_t key_type_t;
>>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
>>> +typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
>>> +
>>> +/* A mapping from the location of an expression to the warning spec
>>> +   set for it.  */
>>> +extern GTY(()) xint_hash_map_t *nowarn_map;
>>
>>> [...]
>>
>>> --- /dev/null
>>> +++ b/gcc/diagnostic-spec.c
>>
>>> [...]
>>
>>> +/* Map from location to its no-warning disposition.  */
>>> +
>>> +GTY(()) xint_hash_map_t *nowarn_map;
>>> +
>>> +/* Return the no-warning disposition for location LOC and option OPT
>>> +   or for all/any otions by default.  */
>>> +
>>> +bool
>>> +warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
>>> +{
>>> +  if (!nowarn_map)
>>> +    return false;
>>> +
>>> +  if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
>>> +    {
>>> +      const nowarn_spec_t optspec (opt);
>>> +      return *pspec & optspec;
>>> +    }
>>> +
>>> +  return false;
>>> +}
>>> +
>>> + /* Change the supression of warnings at location LOC.
>>> +    OPT controls which warnings are affected.
>>> +    The wildcard OPT of -1 controls all warnings.
>>> +    If SUPP is true (the default), enable the suppression of the warnings.
>>> +    If SUPP is false, disable the suppression of the warnings.  */
>>> +
>>> +bool
>>> +suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
>>> +                  bool supp /* = true */)
>>> +{
>>> +  const nowarn_spec_t optspec (supp ? opt : opt_code ());
>>> +
>>> +  if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
>>> +    {
>>> +      if (supp)
>>> +     {
>>> +       *pspec |= optspec;
>>> +       return true;
>>> +     }
>>> +
>>> +      *pspec &= optspec;
>>> +      if (*pspec)
>>> +     return true;
>>> +
>>> +      nowarn_map->remove (loc);
>>> +      return false;
>>> +    }
>>> +
>>> +  if (!supp || opt == no_warning)
>>> +    return false;
>>> +
>>> +  if (!nowarn_map)
>>> +    nowarn_map = xint_hash_map_t::create_ggc (32);
>>> +
>>> +  nowarn_map->put (loc, optspec);
>>> +  return true;
>>> +}
>>> +
>>> +/* Copy the no-warning disposition from one location to another.  */
>>> +
>>> +void
>>> +copy_warning (location_t to, location_t from)
>>> +{
>>> +  if (!nowarn_map)
>>> +    return;
>>> +
>>> +  if (nowarn_spec_t *pspec = nowarn_map->get (from))
>>> +    nowarn_map->put (to, *pspec);
>>> +  else
>>> +    nowarn_map->remove (to);
>>> +}
>>
>>> --- /dev/null
>>> +++ b/gcc/warning-control.cc
>>
>>> [...]
>>
>>> +/* Return the no-warning bit for EXPR.  */
>>> +
>>> +static inline bool
>>> +get_no_warning_bit (const_tree expr)
>>> +{
>>> +  return expr->base.nowarning_flag;
>>> +}
>>> +
>>> +/* Return the no-warning bit for statement STMT.  */
>>> +
>>> +static inline bool
>>> +get_no_warning_bit (const gimple *stmt)
>>> +{
>>> +  return stmt->no_warning;
>>> +}
>>> +
>>> +/* Set the no-warning bit for EXPR to VALUE.  */
>>> +
>>> +static inline void
>>> +set_no_warning_bit (tree expr, bool value)
>>> +{
>>> +  expr->base.nowarning_flag = value;
>>> +}
>>> +
>>> +/* Set the no-warning bit for statement STMT to VALUE.  */
>>> +
>>> +static inline void
>>> +set_no_warning_bit (gimple *stmt, bool value)
>>> +{
>>> +  stmt->no_warning = value;
>>> +}
>>> +
>>> +/* Return EXPR location or zero.  */
>>> +
>>> +static inline key_type_t
>>> +convert_to_key (const_tree expr)
>>> +{
>>> +  if (DECL_P (expr))
>>> +    return DECL_SOURCE_LOCATION (expr);
>>> +  if (EXPR_P (expr))
>>> +    return EXPR_LOCATION (expr);
>>> +  return 0;
>>> +}
>>> +
>>> +/* Return STMT location (may be zero).  */
>>> +
>>> +static inline key_type_t
>>> +convert_to_key (const gimple *stmt)
>>> +{
>>> +  return gimple_location (stmt);
>>> +}
>>> +
>>> +/* Return the no-warning bitmap for decl/expression EXPR.  */
>>> +
>>> +static nowarn_spec_t *
>>> +get_nowarn_spec (const_tree expr)
>>> +{
>>> +  const key_type_t key = convert_to_key (expr);
>>> +
>>> +  if (!get_no_warning_bit (expr) || !key)
>>> +    return NULL;
>>> +
>>> +  return nowarn_map ? nowarn_map->get (key) : NULL;
>>> +}
>>> +
>>> +/* Return the no-warning bitmap for stateemt STMT.  */
>>> +
>>> +static nowarn_spec_t *
>>> +get_nowarn_spec (const gimple *stmt)
>>> +{
>>> +  const key_type_t key = convert_to_key (stmt);
>>> +
>>> +  if (!get_no_warning_bit (stmt))
>>> +    return NULL;
>>> +
>>> +  return nowarn_map ? nowarn_map->get (key) : NULL;
>>> +}
>>> +
>>> +/* Return true if warning OPT is suppressed for decl/expression EXPR.
>>> +   By default tests the disposition for any warning.  */
>>> +
>>> +bool
>>> +warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
>>> +{
>>> +  const nowarn_spec_t *spec = get_nowarn_spec (expr);
>>> +
>>> +  if (!spec)
>>> +    return get_no_warning_bit (expr);
>>> +
>>> +  const nowarn_spec_t optspec (opt);
>>> +  bool dis = *spec & optspec;
>>> +  gcc_assert (get_no_warning_bit (expr) || !dis);
>>> +  return dis;
>>> +}
>>> +
>>> +/* Return true if warning OPT is suppressed for statement STMT.
>>> +   By default tests the disposition for any warning.  */
>>> +
>>> +bool
>>> +warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */)
>>> +{
>>> +  const nowarn_spec_t *spec = get_nowarn_spec (stmt);
>>> +
>>> +  if (!spec)
>>> +    /* Fall back on the single no-warning bit.  */
>>> +    return get_no_warning_bit (stmt);
>>> +
>>> +  const nowarn_spec_t optspec (opt);
>>> +  bool dis = *spec & optspec;
>>> +  gcc_assert (get_no_warning_bit (stmt) || !dis);
>>> +  return dis;
>>> +}
>>> +
>>> +/* Enable, or by default disable, a warning for the expression.
>>> +   The wildcard OPT of -1 controls all warnings.  */
>>> +
>>> +void
>>> +suppress_warning (tree expr, opt_code opt /* = all_warnings */,
>>> +               bool supp /* = true */)
>>> +{
>>> +  if (opt == no_warning)
>>> +    return;
>>> +
>>> +  const key_type_t key = convert_to_key (expr);
>>> +
>>> +  supp = suppress_warning_at (key, opt, supp) || supp;
>>> +  set_no_warning_bit (expr, supp);
>>> +}
>>> +
>>> +/* Enable, or by default disable, a warning for the statement STMT.
>>> +   The wildcard OPT of -1 controls all warnings.  */
>>> +
>>> +void
>>> +suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
>>> +               bool supp /* = true */)
>>> +{
>>> +  if (opt == no_warning)
>>> +    return;
>>> +
>>> +  const key_type_t key = convert_to_key (stmt);
>>> +
>>> +  supp = suppress_warning_at (key, opt, supp) || supp;
>>> +  set_no_warning_bit (stmt, supp);
>>> +}
>>> +
>>> +/* Copy the warning disposition mapping between an expression and/or
>>> +   a statement.  */
>>> +
>>> +template <class ToType, class FromType>
>>> +void copy_warning (ToType to, FromType from)
>>> +{
>>> +  const key_type_t to_key = convert_to_key (to);
>>> +
>>> +  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
>>> +    {
>>> +      /* If there's an entry in the map the no-warning bit must be set.  */
>>> +      gcc_assert (get_no_warning_bit (from));
>>> +
>>> +      if (!nowarn_map)
>>> +     nowarn_map = xint_hash_map_t::create_ggc (32);
>>> +
>>> +      nowarn_map->put (to_key, *from_map);
>>> +      set_no_warning_bit (to, true);
>>> +    }
>>> +  else
>>> +    {
>>> +      if (nowarn_map)
>>> +     nowarn_map->remove (to_key);
>>> +
>>> +      /* The no-warning bit might be set even if there's no entry
>>> +      in the map.  */
>>> +      set_no_warning_bit (to, get_no_warning_bit (from));
>>> +    }
>>> +}
>>> +
>>> +/* Copy the warning disposition mapping from one expression to another.  */
>>> +
>>> +void
>>> +copy_warning (tree to, const_tree from)
>>> +{
>>> +  copy_warning<tree, const_tree>(to, from);
>>> +}
>>> +
>>> +/* Copy the warning disposition mapping from a statement to an expression.  */
>>> +
>>> +void
>>> +copy_warning (tree to, const gimple *from)
>>> +{
>>> +  copy_warning<tree, const gimple *>(to, from);
>>> +}
>>> +
>>> +/* Copy the warning disposition mapping from an expression to a statement.  */
>>> +
>>> +void
>>> +copy_warning (gimple *to, const_tree from)
>>> +{
>>> +  copy_warning<gimple *, const_tree>(to, from);
>>> +}
>>> +
>>> +/* Copy the warning disposition mapping from one statement to another.  */
>>> +
>>> +void
>>> +copy_warning (gimple *to, const gimple *from)
>>> +{
>>> +  copy_warning<gimple *, const gimple *>(to, from);
>>> +}


-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Simplify-gcc-diagnostic-spec.h-nowarn_map-setup.patch --]
[-- Type: text/x-diff, Size: 1025 bytes --]

From 095c16ead5d432726f2b6de5ce12fd367600076d Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Wed, 1 Sep 2021 16:48:55 +0200
Subject: [PATCH 1/3] Simplify 'gcc/diagnostic-spec.h:nowarn_map' setup

If we've just read something from the map, we can be sure that it exists.

	gcc/
	* warning-control.cc (copy_warning): Remove 'nowarn_map' setup.
---
 gcc/warning-control.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index ec8ed232763..9c506e163d6 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -188,9 +188,7 @@ void copy_warning (ToType to, FromType from)
       /* If there's an entry in the map the no-warning bit must be set.  */
       gcc_assert (get_no_warning_bit (from));
 
-      if (!nowarn_map)
-	nowarn_map = xint_hash_map_t::create_ggc (32);
-
+      gcc_checking_assert (nowarn_map);
       nowarn_map->put (to_key, *from_map);
       set_no_warning_bit (to, true);
     }
-- 
2.30.2


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-Clarify-key_type_t-to-location_t-as-used-for-gcc-dia.patch --]
[-- Type: text/x-diff, Size: 5439 bytes --]

From 23d9b93401349fca03efaef0fef0960933f4c316 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Tue, 31 Aug 2021 22:01:23 +0200
Subject: [PATCH 2/3] Clarify 'key_type_t' to 'location_t' as used for
 'gcc/diagnostic-spec.h:nowarn_map'

To make it obvious what exactly the key type is.  No change in behavior.

	gcc/
	* diagnostic-spec.h (typedef xint_hash_t): Use 'location_t' instead of...
	(typedef key_type_t): ... this.  Remove.
	(nowarn_map): Document.
	* diagnostic-spec.c (nowarn_map): Likewise.
	* warning-control.cc (convert_to_key): Evolve functions into...
	(get_location): ... these.  Adjust all users.
---
 gcc/diagnostic-spec.c  |  2 +-
 gcc/diagnostic-spec.h  |  6 ++----
 gcc/warning-control.cc | 41 ++++++++++++++++++++++-------------------
 3 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index 5e961e1b9f9..eac5a3317c8 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -105,7 +105,7 @@ nowarn_spec_t::nowarn_spec_t (opt_code opt)
     }
 }
 
-/* Map from location to its no-warning disposition.  */
+/* A mapping from a 'location_t' to the warning spec set for it.  */
 
 GTY(()) xint_hash_map_t *nowarn_map;
 
diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
index 4e4d260f74a..9b3aaaa3ce6 100644
--- a/gcc/diagnostic-spec.h
+++ b/gcc/diagnostic-spec.h
@@ -130,12 +130,10 @@ operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
   return !(lhs == rhs);
 }
 
-typedef location_t key_type_t;
-typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
+typedef int_hash <location_t, 0, UINT_MAX> xint_hash_t;
 typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
 
-/* A mapping from the location of an expression to the warning spec
-   set for it.  */
+/* A mapping from a 'location_t' to the warning spec set for it.  */
 extern GTY(()) xint_hash_map_t *nowarn_map;
 
 #endif // DIAGNOSTIC_SPEC_H_INCLUDED
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index 9c506e163d6..8d6c0828445 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -62,22 +62,22 @@ set_no_warning_bit (gimple *stmt, bool value)
   stmt->no_warning = value;
 }
 
-/* Return EXPR location or zero.  */
+/* Return EXPR location or 'UNKNOWN_LOCATION'.  */
 
-static inline key_type_t
-convert_to_key (const_tree expr)
+static inline location_t
+get_location (const_tree expr)
 {
   if (DECL_P (expr))
     return DECL_SOURCE_LOCATION (expr);
   if (EXPR_P (expr))
     return EXPR_LOCATION (expr);
-  return 0;
+  return UNKNOWN_LOCATION;
 }
 
-/* Return STMT location (may be zero).  */
+/* Return STMT location (may be 'UNKNOWN_LOCATION').  */
 
-static inline key_type_t
-convert_to_key (const gimple *stmt)
+static inline location_t
+get_location (const gimple *stmt)
 {
   return gimple_location (stmt);
 }
@@ -87,12 +87,15 @@ convert_to_key (const gimple *stmt)
 static nowarn_spec_t *
 get_nowarn_spec (const_tree expr)
 {
-  const key_type_t key = convert_to_key (expr);
+  const location_t loc = get_location (expr);
 
-  if (!get_no_warning_bit (expr) || !key)
+  if (loc == UNKNOWN_LOCATION)
     return NULL;
 
-  return nowarn_map ? nowarn_map->get (key) : NULL;
+  if (!get_no_warning_bit (expr))
+    return NULL;
+
+  return nowarn_map ? nowarn_map->get (loc) : NULL;
 }
 
 /* Return the no-warning bitmap for stateemt STMT.  */
@@ -100,12 +103,12 @@ get_nowarn_spec (const_tree expr)
 static nowarn_spec_t *
 get_nowarn_spec (const gimple *stmt)
 {
-  const key_type_t key = convert_to_key (stmt);
+  const location_t loc = get_location (stmt);
 
   if (!get_no_warning_bit (stmt))
     return NULL;
 
-  return nowarn_map ? nowarn_map->get (key) : NULL;
+  return nowarn_map ? nowarn_map->get (loc) : NULL;
 }
 
 /* Return true if warning OPT is suppressed for decl/expression EXPR.
@@ -153,9 +156,9 @@ suppress_warning (tree expr, opt_code opt /* = all_warnings */,
   if (opt == no_warning)
     return;
 
-  const key_type_t key = convert_to_key (expr);
+  const location_t loc = get_location (expr);
 
-  supp = suppress_warning_at (key, opt, supp) || supp;
+  supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (expr, supp);
 }
 
@@ -169,9 +172,9 @@ suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
   if (opt == no_warning)
     return;
 
-  const key_type_t key = convert_to_key (stmt);
+  const location_t loc = get_location (stmt);
 
-  supp = suppress_warning_at (key, opt, supp) || supp;
+  supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (stmt, supp);
 }
 
@@ -181,7 +184,7 @@ suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
 template <class ToType, class FromType>
 void copy_warning (ToType to, FromType from)
 {
-  const key_type_t to_key = convert_to_key (to);
+  const location_t to_loc = get_location (to);
 
   if (nowarn_spec_t *from_map = get_nowarn_spec (from))
     {
@@ -189,13 +192,13 @@ void copy_warning (ToType to, FromType from)
       gcc_assert (get_no_warning_bit (from));
 
       gcc_checking_assert (nowarn_map);
-      nowarn_map->put (to_key, *from_map);
+      nowarn_map->put (to_loc, *from_map);
       set_no_warning_bit (to, true);
     }
   else
     {
       if (nowarn_map)
-	nowarn_map->remove (to_key);
+	nowarn_map->remove (to_loc);
 
       /* The no-warning bit might be set even if there's no entry
 	 in the map.  */
-- 
2.30.2


[-- Attachment #4: 0003-Don-t-maintain-a-warning-spec-for-UNKNOWN_LOCATION-B.patch --]
[-- Type: text/x-diff, Size: 5871 bytes --]

From 51c9a8ac2caa0432730c78d00989fd01f3ac6fe5 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Mon, 30 Aug 2021 22:36:47 +0200
Subject: [PATCH 3/3] Don't maintain a warning spec for
 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574]
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This resolves PR101574 "gcc/sparseset.h:215:20: error: suggest parentheses
around assignment used as truth value [-Werror=parentheses]", as (bogusly)
reported at commit a61f6afbee370785cf091fe46e2e022748528307:

    In file included from [...]/source-gcc/gcc/lra-lives.c:43:
    [...]/source-gcc/gcc/lra-lives.c: In function ‘void make_hard_regno_dead(int)’:
    [...]/source-gcc/gcc/sparseset.h:215:20: error: suggest parentheses around assignment used as truth value [-Werror=parentheses]
      215 |        && (((ITER) = sparseset_iter_elm (SPARSESET)) || 1);             \
          |            ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    [...]/source-gcc/gcc/lra-lives.c:304:3: note: in expansion of macro ‘EXECUTE_IF_SET_IN_SPARSESET’
      304 |   EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
          |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~

	gcc/
	PR bootstrap/101574
	* diagnostic-spec.c (warning_suppressed_at, copy_warning): Handle
	'RESERVED_LOCATION_P' locations.
	* warning-control.cc (get_nowarn_spec, suppress_warning)
	(copy_warning): Likewise.
---
 gcc/diagnostic-spec.c  | 22 ++++++++++++++++---
 gcc/warning-control.cc | 48 +++++++++++++++++++++++++++---------------
 2 files changed, 50 insertions(+), 20 deletions(-)

diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index eac5a3317c8..85ffb725c02 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -115,6 +115,8 @@ GTY(()) xint_hash_map_t *nowarn_map;
 bool
 warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
 {
+  gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+
   if (!nowarn_map)
     return false;
 
@@ -137,6 +139,8 @@ bool
 suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
 		     bool supp /* = true */)
 {
+  gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+
   const nowarn_spec_t optspec (supp ? opt : opt_code ());
 
   if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
@@ -173,8 +177,20 @@ copy_warning (location_t to, location_t from)
   if (!nowarn_map)
     return;
 
-  if (nowarn_spec_t *pspec = nowarn_map->get (from))
-    nowarn_map->put (to, *pspec);
+  nowarn_spec_t *from_spec;
+  if (RESERVED_LOCATION_P (from))
+    from_spec = NULL;
+  else
+    from_spec = nowarn_map->get (from);
+  if (RESERVED_LOCATION_P (to))
+    /* We cannot set no-warning dispositions for 'to', so we have no chance but
+       lose those potentially set for 'from'.  */
+    ;
   else
-    nowarn_map->remove (to);
+    {
+      if (from_spec)
+	nowarn_map->put (to, *from_spec);
+      else
+	nowarn_map->remove (to);
+    }
 }
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index 8d6c0828445..36a47ab6bae 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -89,7 +89,7 @@ get_nowarn_spec (const_tree expr)
 {
   const location_t loc = get_location (expr);
 
-  if (loc == UNKNOWN_LOCATION)
+  if (RESERVED_LOCATION_P (loc))
     return NULL;
 
   if (!get_no_warning_bit (expr))
@@ -105,6 +105,9 @@ get_nowarn_spec (const gimple *stmt)
 {
   const location_t loc = get_location (stmt);
 
+  if (RESERVED_LOCATION_P (loc))
+    return NULL;
+
   if (!get_no_warning_bit (stmt))
     return NULL;
 
@@ -158,7 +161,8 @@ suppress_warning (tree expr, opt_code opt /* = all_warnings */,
 
   const location_t loc = get_location (expr);
 
-  supp = suppress_warning_at (loc, opt, supp) || supp;
+  if (!RESERVED_LOCATION_P (loc))
+    supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (expr, supp);
 }
 
@@ -174,7 +178,8 @@ suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
 
   const location_t loc = get_location (stmt);
 
-  supp = suppress_warning_at (loc, opt, supp) || supp;
+  if (!RESERVED_LOCATION_P (loc))
+    supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (stmt, supp);
 }
 
@@ -186,24 +191,33 @@ void copy_warning (ToType to, FromType from)
 {
   const location_t to_loc = get_location (to);
 
-  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
-    {
-      /* If there's an entry in the map the no-warning bit must be set.  */
-      gcc_assert (get_no_warning_bit (from));
+  bool supp = get_no_warning_bit (from);
 
-      gcc_checking_assert (nowarn_map);
-      nowarn_map->put (to_loc, *from_map);
-      set_no_warning_bit (to, true);
-    }
+  nowarn_spec_t *from_spec = get_nowarn_spec (from);
+  if (RESERVED_LOCATION_P (to_loc))
+    /* We cannot set no-warning dispositions for 'to', so we have no chance but
+       lose those potentially set for 'from'.  */
+    ;
   else
     {
-      if (nowarn_map)
-	nowarn_map->remove (to_loc);
-
-      /* The no-warning bit might be set even if there's no entry
-	 in the map.  */
-      set_no_warning_bit (to, get_no_warning_bit (from));
+      if (from_spec)
+	{
+	  /* If there's an entry in the map the no-warning bit must be set.  */
+	  gcc_assert (supp);
+
+	  gcc_checking_assert (nowarn_map);
+	  nowarn_map->put (to_loc, *from_spec);
+	}
+      else
+	{
+	  if (nowarn_map)
+	    nowarn_map->remove (to_loc);
+	}
     }
+
+  /* The no-warning bit might be set even if the map has not been consulted, or
+     otherwise if there's no entry in the map.  */
+  set_no_warning_bit (to, supp);
 }
 
 /* Copy the warning disposition mapping from one expression to another.  */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [PING] Don't maintain a warning spec for 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765))
  2021-09-03 19:16                 ` Thomas Schwinge
@ 2021-09-10  7:45                   ` Thomas Schwinge
  2021-09-13 14:00                     ` Jeff Law
  2021-11-09 14:18                   ` Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map' " Thomas Schwinge
  1 sibling, 1 reply; 98+ messages in thread
From: Thomas Schwinge @ 2021-09-10  7:45 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 15054 bytes --]

Hi!

Ping.

On 2021-09-03T21:16:46+0200, Thomas Schwinge <thomas@codesourcery.com> wrote:
> Martin, thanks for your review.  Now need someone to formally approve the
> third patch.

Again attached for easy reference.


Grüße
 Thomas


> On 2021-09-01T18:14:46-0600, Martin Sebor <msebor@gmail.com> wrote:
>> On 9/1/21 1:35 PM, Thomas Schwinge wrote:
>>> On 2021-06-23T13:47:08-0600, Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>>>> On 6/22/21 5:28 PM, David Malcolm wrote:
>>>>> On Tue, 2021-06-22 at 19:18 -0400, David Malcolm wrote:
>>>>>> On Fri, 2021-06-04 at 15:41 -0600, Martin Sebor wrote:
>>>>>>> The attached patch introduces the suppress_warning(),
>>>>>>> warning_suppressed(), and copy_no_warning() APIs [etc.]
>
>>> I now had a bit of a deep dive into some aspects of this, in context of
>>> <https://gcc.gnu.org/PR101574> "gcc/sparseset.h:215:20: error: suggest
>>> parentheses around assignment used as truth value [-Werror=parentheses]"
>>> that I recently filed.  This seems difficult to reproduce, but I'm still
>>> able to reliably reproduce it in one specific build
>>> configuration/directory/machine/whatever.  Initially, we all quickly
>>> assumed that it'd be some GC issue -- but "alas", it's not, at least not
>>> directly.  (But I'll certainly assume that some GC aspects are involved
>>> which make this issue come and go across different GCC sources revisions,
>>> and difficult to reproduce.)
>
>>> First, two pieces of cleanup:
>
> ACKed by Martin, again attached for convenience.
>
>
>>>> --- /dev/null
>>>> +++ b/gcc/diagnostic-spec.h
>>>
>>>> +typedef location_t key_type_t;
>>>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
>
>> By the way, it seems we should probably also use a manifest constant
>> for Empty (probably UNKNOWN_LOCATION since we're reserving it).
>
> Yes, that will be part of another patch here -- waiting for approval of
> "Generalize 'gcc/input.h:struct location_hash'" posted elsewhere.
>
>
>>> attached "Don't maintain a warning spec for
>>> 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574]".  OK to push?
>>
>> [...].  So I agree that it ought to be fixed.
>
>>> I'm reasonably confident that my changes are doing the right things in
>>> general, but please carefully review, especially here:
>>>
>>>    - 'gcc/warning-control.cc:suppress_warning' functions: is it correct to
>>>      conditionalize on '!RESERVED_LOCATION_P' the 'suppress_warning_at'
>>>      calls and 'supp' update?  Or, should instead 'suppress_warning_at'
>>>      handle the case of '!RESERVED_LOCATION_P'?  (How?)
>>
>> It seems like six of one vs half a dozen of the other.  I'd say go
>> with whatever makes more sense to you here :)
>
> OK, was just trying to make sure that I don't fail to see any non-obvious
> intentions here.
>
>>>    - 'gcc/diagnostic-spec.c:copy_warning' and
>>>      'gcc/warning-control.cc:copy_warning': is the rationale correct for
>>>      the 'gcc_checking_assert (!from_spec)': "If we cannot set no-warning
>>>      dispositions for 'to', ascertain that we don't have any for 'from'.
>>>      Otherwise, we'd lose these."?  If the rationale is correct, then
>>>      observing that in 'gcc/warning-control.cc:copy_warning' this
>>>      currently "triggers during GCC build" is something to be looked into,
>>>      later, I suppose, and otherwise, how should I change this code?
>>
>> copy_warning(location_t, location_t) is called [only] from
>> gimple_set_location().  The middle end does clear the location of
>> some statements for which it was previously valid (e.g., return
>> statements).
>
> What I observed was that the 'assert' never triggered for the
> 'location_t' variant "called [only] from gimple_set_location" -- but does
> trigger for some other variant.  Anyway:
>
>> So I wouldn't expect this assumption to be safe.  If
>> that happens, we have no choice but to lose the per-warning detail
>> and fall back on the no-warning bit.
>
> ACK.  I'm thus clarifying that as follows:
>
>     --- gcc/diagnostic-spec.c
>     +++ gcc/diagnostic-spec.c
>     @@ -185,7 +185,5 @@ copy_warning (location_t to, location_t from)
>        if (RESERVED_LOCATION_P (to))
>     -    {
>     -      /* If we cannot set no-warning dispositions for 'to', ascertain that we
>     -    don't have any for 'from'.  Otherwise, we'd lose these.  */
>     -      gcc_checking_assert (!from_spec);
>     -    }
>     +    /* We cannot set no-warning dispositions for 'to', so we have no chance but
>     +       lose those potentially set for 'from'.  */
>     +    ;
>        else
>     --- gcc/warning-control.cc
>     +++ gcc/warning-control.cc
>     @@ -197,9 +197,5 @@ void copy_warning (ToType to, FromType from)
>        if (RESERVED_LOCATION_P (to_loc))
>     -    {
>     -#if 0 //TODO triggers during GCC build
>     -      /* If we cannot set no-warning dispositions for 'to', ascertain that we
>     -    don't have any for 'from'.  Otherwise, we'd lose these.  */
>     -      gcc_checking_assert (!from_spec);
>     -#endif
>     -    }
>     +    /* We cannot set no-warning dispositions for 'to', so we have no chance but
>     +       lose those potentially set for 'from'.  */
>     +    ;
>        else
>
>> (Either David or a middle end maintainer will need to approve the last
>> patch once it's final.)
>
> As far as I'm concerned that would be the attached third patch:
> "Don't maintain a warning spec for 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION'
> [PR101574]".  OK to push?
>
>
> Grüße
>  Thomas
>
>
>>> PS.  Relevant code quoted for reference, in case that's useful:
>>>
>>>> --- /dev/null
>>>> +++ b/gcc/diagnostic-spec.h
>>>
>>>> [...]
>>>
>>>> +typedef location_t key_type_t;
>>>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
>>>> +typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
>>>> +
>>>> +/* A mapping from the location of an expression to the warning spec
>>>> +   set for it.  */
>>>> +extern GTY(()) xint_hash_map_t *nowarn_map;
>>>
>>>> [...]
>>>
>>>> --- /dev/null
>>>> +++ b/gcc/diagnostic-spec.c
>>>
>>>> [...]
>>>
>>>> +/* Map from location to its no-warning disposition.  */
>>>> +
>>>> +GTY(()) xint_hash_map_t *nowarn_map;
>>>> +
>>>> +/* Return the no-warning disposition for location LOC and option OPT
>>>> +   or for all/any otions by default.  */
>>>> +
>>>> +bool
>>>> +warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
>>>> +{
>>>> +  if (!nowarn_map)
>>>> +    return false;
>>>> +
>>>> +  if (const nowarn_spec_t* const pspec = nowarn_map->get (loc))
>>>> +    {
>>>> +      const nowarn_spec_t optspec (opt);
>>>> +      return *pspec & optspec;
>>>> +    }
>>>> +
>>>> +  return false;
>>>> +}
>>>> +
>>>> + /* Change the supression of warnings at location LOC.
>>>> +    OPT controls which warnings are affected.
>>>> +    The wildcard OPT of -1 controls all warnings.
>>>> +    If SUPP is true (the default), enable the suppression of the warnings.
>>>> +    If SUPP is false, disable the suppression of the warnings.  */
>>>> +
>>>> +bool
>>>> +suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
>>>> +                  bool supp /* = true */)
>>>> +{
>>>> +  const nowarn_spec_t optspec (supp ? opt : opt_code ());
>>>> +
>>>> +  if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
>>>> +    {
>>>> +      if (supp)
>>>> +     {
>>>> +       *pspec |= optspec;
>>>> +       return true;
>>>> +     }
>>>> +
>>>> +      *pspec &= optspec;
>>>> +      if (*pspec)
>>>> +     return true;
>>>> +
>>>> +      nowarn_map->remove (loc);
>>>> +      return false;
>>>> +    }
>>>> +
>>>> +  if (!supp || opt == no_warning)
>>>> +    return false;
>>>> +
>>>> +  if (!nowarn_map)
>>>> +    nowarn_map = xint_hash_map_t::create_ggc (32);
>>>> +
>>>> +  nowarn_map->put (loc, optspec);
>>>> +  return true;
>>>> +}
>>>> +
>>>> +/* Copy the no-warning disposition from one location to another.  */
>>>> +
>>>> +void
>>>> +copy_warning (location_t to, location_t from)
>>>> +{
>>>> +  if (!nowarn_map)
>>>> +    return;
>>>> +
>>>> +  if (nowarn_spec_t *pspec = nowarn_map->get (from))
>>>> +    nowarn_map->put (to, *pspec);
>>>> +  else
>>>> +    nowarn_map->remove (to);
>>>> +}
>>>
>>>> --- /dev/null
>>>> +++ b/gcc/warning-control.cc
>>>
>>>> [...]
>>>
>>>> +/* Return the no-warning bit for EXPR.  */
>>>> +
>>>> +static inline bool
>>>> +get_no_warning_bit (const_tree expr)
>>>> +{
>>>> +  return expr->base.nowarning_flag;
>>>> +}
>>>> +
>>>> +/* Return the no-warning bit for statement STMT.  */
>>>> +
>>>> +static inline bool
>>>> +get_no_warning_bit (const gimple *stmt)
>>>> +{
>>>> +  return stmt->no_warning;
>>>> +}
>>>> +
>>>> +/* Set the no-warning bit for EXPR to VALUE.  */
>>>> +
>>>> +static inline void
>>>> +set_no_warning_bit (tree expr, bool value)
>>>> +{
>>>> +  expr->base.nowarning_flag = value;
>>>> +}
>>>> +
>>>> +/* Set the no-warning bit for statement STMT to VALUE.  */
>>>> +
>>>> +static inline void
>>>> +set_no_warning_bit (gimple *stmt, bool value)
>>>> +{
>>>> +  stmt->no_warning = value;
>>>> +}
>>>> +
>>>> +/* Return EXPR location or zero.  */
>>>> +
>>>> +static inline key_type_t
>>>> +convert_to_key (const_tree expr)
>>>> +{
>>>> +  if (DECL_P (expr))
>>>> +    return DECL_SOURCE_LOCATION (expr);
>>>> +  if (EXPR_P (expr))
>>>> +    return EXPR_LOCATION (expr);
>>>> +  return 0;
>>>> +}
>>>> +
>>>> +/* Return STMT location (may be zero).  */
>>>> +
>>>> +static inline key_type_t
>>>> +convert_to_key (const gimple *stmt)
>>>> +{
>>>> +  return gimple_location (stmt);
>>>> +}
>>>> +
>>>> +/* Return the no-warning bitmap for decl/expression EXPR.  */
>>>> +
>>>> +static nowarn_spec_t *
>>>> +get_nowarn_spec (const_tree expr)
>>>> +{
>>>> +  const key_type_t key = convert_to_key (expr);
>>>> +
>>>> +  if (!get_no_warning_bit (expr) || !key)
>>>> +    return NULL;
>>>> +
>>>> +  return nowarn_map ? nowarn_map->get (key) : NULL;
>>>> +}
>>>> +
>>>> +/* Return the no-warning bitmap for stateemt STMT.  */
>>>> +
>>>> +static nowarn_spec_t *
>>>> +get_nowarn_spec (const gimple *stmt)
>>>> +{
>>>> +  const key_type_t key = convert_to_key (stmt);
>>>> +
>>>> +  if (!get_no_warning_bit (stmt))
>>>> +    return NULL;
>>>> +
>>>> +  return nowarn_map ? nowarn_map->get (key) : NULL;
>>>> +}
>>>> +
>>>> +/* Return true if warning OPT is suppressed for decl/expression EXPR.
>>>> +   By default tests the disposition for any warning.  */
>>>> +
>>>> +bool
>>>> +warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
>>>> +{
>>>> +  const nowarn_spec_t *spec = get_nowarn_spec (expr);
>>>> +
>>>> +  if (!spec)
>>>> +    return get_no_warning_bit (expr);
>>>> +
>>>> +  const nowarn_spec_t optspec (opt);
>>>> +  bool dis = *spec & optspec;
>>>> +  gcc_assert (get_no_warning_bit (expr) || !dis);
>>>> +  return dis;
>>>> +}
>>>> +
>>>> +/* Return true if warning OPT is suppressed for statement STMT.
>>>> +   By default tests the disposition for any warning.  */
>>>> +
>>>> +bool
>>>> +warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */)
>>>> +{
>>>> +  const nowarn_spec_t *spec = get_nowarn_spec (stmt);
>>>> +
>>>> +  if (!spec)
>>>> +    /* Fall back on the single no-warning bit.  */
>>>> +    return get_no_warning_bit (stmt);
>>>> +
>>>> +  const nowarn_spec_t optspec (opt);
>>>> +  bool dis = *spec & optspec;
>>>> +  gcc_assert (get_no_warning_bit (stmt) || !dis);
>>>> +  return dis;
>>>> +}
>>>> +
>>>> +/* Enable, or by default disable, a warning for the expression.
>>>> +   The wildcard OPT of -1 controls all warnings.  */
>>>> +
>>>> +void
>>>> +suppress_warning (tree expr, opt_code opt /* = all_warnings */,
>>>> +               bool supp /* = true */)
>>>> +{
>>>> +  if (opt == no_warning)
>>>> +    return;
>>>> +
>>>> +  const key_type_t key = convert_to_key (expr);
>>>> +
>>>> +  supp = suppress_warning_at (key, opt, supp) || supp;
>>>> +  set_no_warning_bit (expr, supp);
>>>> +}
>>>> +
>>>> +/* Enable, or by default disable, a warning for the statement STMT.
>>>> +   The wildcard OPT of -1 controls all warnings.  */
>>>> +
>>>> +void
>>>> +suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
>>>> +               bool supp /* = true */)
>>>> +{
>>>> +  if (opt == no_warning)
>>>> +    return;
>>>> +
>>>> +  const key_type_t key = convert_to_key (stmt);
>>>> +
>>>> +  supp = suppress_warning_at (key, opt, supp) || supp;
>>>> +  set_no_warning_bit (stmt, supp);
>>>> +}
>>>> +
>>>> +/* Copy the warning disposition mapping between an expression and/or
>>>> +   a statement.  */
>>>> +
>>>> +template <class ToType, class FromType>
>>>> +void copy_warning (ToType to, FromType from)
>>>> +{
>>>> +  const key_type_t to_key = convert_to_key (to);
>>>> +
>>>> +  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
>>>> +    {
>>>> +      /* If there's an entry in the map the no-warning bit must be set.  */
>>>> +      gcc_assert (get_no_warning_bit (from));
>>>> +
>>>> +      if (!nowarn_map)
>>>> +     nowarn_map = xint_hash_map_t::create_ggc (32);
>>>> +
>>>> +      nowarn_map->put (to_key, *from_map);
>>>> +      set_no_warning_bit (to, true);
>>>> +    }
>>>> +  else
>>>> +    {
>>>> +      if (nowarn_map)
>>>> +     nowarn_map->remove (to_key);
>>>> +
>>>> +      /* The no-warning bit might be set even if there's no entry
>>>> +      in the map.  */
>>>> +      set_no_warning_bit (to, get_no_warning_bit (from));
>>>> +    }
>>>> +}
>>>> +
>>>> +/* Copy the warning disposition mapping from one expression to another.  */
>>>> +
>>>> +void
>>>> +copy_warning (tree to, const_tree from)
>>>> +{
>>>> +  copy_warning<tree, const_tree>(to, from);
>>>> +}
>>>> +
>>>> +/* Copy the warning disposition mapping from a statement to an expression.  */
>>>> +
>>>> +void
>>>> +copy_warning (tree to, const gimple *from)
>>>> +{
>>>> +  copy_warning<tree, const gimple *>(to, from);
>>>> +}
>>>> +
>>>> +/* Copy the warning disposition mapping from an expression to a statement.  */
>>>> +
>>>> +void
>>>> +copy_warning (gimple *to, const_tree from)
>>>> +{
>>>> +  copy_warning<gimple *, const_tree>(to, from);
>>>> +}
>>>> +
>>>> +/* Copy the warning disposition mapping from one statement to another.  */
>>>> +
>>>> +void
>>>> +copy_warning (gimple *to, const gimple *from)
>>>> +{
>>>> +  copy_warning<gimple *, const gimple *>(to, from);
>>>> +}


-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Simplify-gcc-diagnostic-spec.h-nowarn_map-setup.patch --]
[-- Type: text/x-diff, Size: 1025 bytes --]

From 095c16ead5d432726f2b6de5ce12fd367600076d Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Wed, 1 Sep 2021 16:48:55 +0200
Subject: [PATCH 1/3] Simplify 'gcc/diagnostic-spec.h:nowarn_map' setup

If we've just read something from the map, we can be sure that it exists.

	gcc/
	* warning-control.cc (copy_warning): Remove 'nowarn_map' setup.
---
 gcc/warning-control.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index ec8ed232763..9c506e163d6 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -188,9 +188,7 @@ void copy_warning (ToType to, FromType from)
       /* If there's an entry in the map the no-warning bit must be set.  */
       gcc_assert (get_no_warning_bit (from));
 
-      if (!nowarn_map)
-	nowarn_map = xint_hash_map_t::create_ggc (32);
-
+      gcc_checking_assert (nowarn_map);
       nowarn_map->put (to_key, *from_map);
       set_no_warning_bit (to, true);
     }
-- 
2.30.2


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-Clarify-key_type_t-to-location_t-as-used-for-gcc-dia.patch --]
[-- Type: text/x-diff, Size: 5439 bytes --]

From 23d9b93401349fca03efaef0fef0960933f4c316 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Tue, 31 Aug 2021 22:01:23 +0200
Subject: [PATCH 2/3] Clarify 'key_type_t' to 'location_t' as used for
 'gcc/diagnostic-spec.h:nowarn_map'

To make it obvious what exactly the key type is.  No change in behavior.

	gcc/
	* diagnostic-spec.h (typedef xint_hash_t): Use 'location_t' instead of...
	(typedef key_type_t): ... this.  Remove.
	(nowarn_map): Document.
	* diagnostic-spec.c (nowarn_map): Likewise.
	* warning-control.cc (convert_to_key): Evolve functions into...
	(get_location): ... these.  Adjust all users.
---
 gcc/diagnostic-spec.c  |  2 +-
 gcc/diagnostic-spec.h  |  6 ++----
 gcc/warning-control.cc | 41 ++++++++++++++++++++++-------------------
 3 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index 5e961e1b9f9..eac5a3317c8 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -105,7 +105,7 @@ nowarn_spec_t::nowarn_spec_t (opt_code opt)
     }
 }
 
-/* Map from location to its no-warning disposition.  */
+/* A mapping from a 'location_t' to the warning spec set for it.  */
 
 GTY(()) xint_hash_map_t *nowarn_map;
 
diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
index 4e4d260f74a..9b3aaaa3ce6 100644
--- a/gcc/diagnostic-spec.h
+++ b/gcc/diagnostic-spec.h
@@ -130,12 +130,10 @@ operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
   return !(lhs == rhs);
 }
 
-typedef location_t key_type_t;
-typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
+typedef int_hash <location_t, 0, UINT_MAX> xint_hash_t;
 typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
 
-/* A mapping from the location of an expression to the warning spec
-   set for it.  */
+/* A mapping from a 'location_t' to the warning spec set for it.  */
 extern GTY(()) xint_hash_map_t *nowarn_map;
 
 #endif // DIAGNOSTIC_SPEC_H_INCLUDED
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index 9c506e163d6..8d6c0828445 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -62,22 +62,22 @@ set_no_warning_bit (gimple *stmt, bool value)
   stmt->no_warning = value;
 }
 
-/* Return EXPR location or zero.  */
+/* Return EXPR location or 'UNKNOWN_LOCATION'.  */
 
-static inline key_type_t
-convert_to_key (const_tree expr)
+static inline location_t
+get_location (const_tree expr)
 {
   if (DECL_P (expr))
     return DECL_SOURCE_LOCATION (expr);
   if (EXPR_P (expr))
     return EXPR_LOCATION (expr);
-  return 0;
+  return UNKNOWN_LOCATION;
 }
 
-/* Return STMT location (may be zero).  */
+/* Return STMT location (may be 'UNKNOWN_LOCATION').  */
 
-static inline key_type_t
-convert_to_key (const gimple *stmt)
+static inline location_t
+get_location (const gimple *stmt)
 {
   return gimple_location (stmt);
 }
@@ -87,12 +87,15 @@ convert_to_key (const gimple *stmt)
 static nowarn_spec_t *
 get_nowarn_spec (const_tree expr)
 {
-  const key_type_t key = convert_to_key (expr);
+  const location_t loc = get_location (expr);
 
-  if (!get_no_warning_bit (expr) || !key)
+  if (loc == UNKNOWN_LOCATION)
     return NULL;
 
-  return nowarn_map ? nowarn_map->get (key) : NULL;
+  if (!get_no_warning_bit (expr))
+    return NULL;
+
+  return nowarn_map ? nowarn_map->get (loc) : NULL;
 }
 
 /* Return the no-warning bitmap for stateemt STMT.  */
@@ -100,12 +103,12 @@ get_nowarn_spec (const_tree expr)
 static nowarn_spec_t *
 get_nowarn_spec (const gimple *stmt)
 {
-  const key_type_t key = convert_to_key (stmt);
+  const location_t loc = get_location (stmt);
 
   if (!get_no_warning_bit (stmt))
     return NULL;
 
-  return nowarn_map ? nowarn_map->get (key) : NULL;
+  return nowarn_map ? nowarn_map->get (loc) : NULL;
 }
 
 /* Return true if warning OPT is suppressed for decl/expression EXPR.
@@ -153,9 +156,9 @@ suppress_warning (tree expr, opt_code opt /* = all_warnings */,
   if (opt == no_warning)
     return;
 
-  const key_type_t key = convert_to_key (expr);
+  const location_t loc = get_location (expr);
 
-  supp = suppress_warning_at (key, opt, supp) || supp;
+  supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (expr, supp);
 }
 
@@ -169,9 +172,9 @@ suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
   if (opt == no_warning)
     return;
 
-  const key_type_t key = convert_to_key (stmt);
+  const location_t loc = get_location (stmt);
 
-  supp = suppress_warning_at (key, opt, supp) || supp;
+  supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (stmt, supp);
 }
 
@@ -181,7 +184,7 @@ suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
 template <class ToType, class FromType>
 void copy_warning (ToType to, FromType from)
 {
-  const key_type_t to_key = convert_to_key (to);
+  const location_t to_loc = get_location (to);
 
   if (nowarn_spec_t *from_map = get_nowarn_spec (from))
     {
@@ -189,13 +192,13 @@ void copy_warning (ToType to, FromType from)
       gcc_assert (get_no_warning_bit (from));
 
       gcc_checking_assert (nowarn_map);
-      nowarn_map->put (to_key, *from_map);
+      nowarn_map->put (to_loc, *from_map);
       set_no_warning_bit (to, true);
     }
   else
     {
       if (nowarn_map)
-	nowarn_map->remove (to_key);
+	nowarn_map->remove (to_loc);
 
       /* The no-warning bit might be set even if there's no entry
 	 in the map.  */
-- 
2.30.2


[-- Attachment #4: 0003-Don-t-maintain-a-warning-spec-for-UNKNOWN_LOCATION-B.patch --]
[-- Type: text/x-diff, Size: 5871 bytes --]

From 51c9a8ac2caa0432730c78d00989fd01f3ac6fe5 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Mon, 30 Aug 2021 22:36:47 +0200
Subject: [PATCH 3/3] Don't maintain a warning spec for
 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574]
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This resolves PR101574 "gcc/sparseset.h:215:20: error: suggest parentheses
around assignment used as truth value [-Werror=parentheses]", as (bogusly)
reported at commit a61f6afbee370785cf091fe46e2e022748528307:

    In file included from [...]/source-gcc/gcc/lra-lives.c:43:
    [...]/source-gcc/gcc/lra-lives.c: In function ‘void make_hard_regno_dead(int)’:
    [...]/source-gcc/gcc/sparseset.h:215:20: error: suggest parentheses around assignment used as truth value [-Werror=parentheses]
      215 |        && (((ITER) = sparseset_iter_elm (SPARSESET)) || 1);             \
          |            ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    [...]/source-gcc/gcc/lra-lives.c:304:3: note: in expansion of macro ‘EXECUTE_IF_SET_IN_SPARSESET’
      304 |   EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
          |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~

	gcc/
	PR bootstrap/101574
	* diagnostic-spec.c (warning_suppressed_at, copy_warning): Handle
	'RESERVED_LOCATION_P' locations.
	* warning-control.cc (get_nowarn_spec, suppress_warning)
	(copy_warning): Likewise.
---
 gcc/diagnostic-spec.c  | 22 ++++++++++++++++---
 gcc/warning-control.cc | 48 +++++++++++++++++++++++++++---------------
 2 files changed, 50 insertions(+), 20 deletions(-)

diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index eac5a3317c8..85ffb725c02 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -115,6 +115,8 @@ GTY(()) xint_hash_map_t *nowarn_map;
 bool
 warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
 {
+  gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+
   if (!nowarn_map)
     return false;
 
@@ -137,6 +139,8 @@ bool
 suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
 		     bool supp /* = true */)
 {
+  gcc_checking_assert (!RESERVED_LOCATION_P (loc));
+
   const nowarn_spec_t optspec (supp ? opt : opt_code ());
 
   if (nowarn_spec_t *pspec = nowarn_map ? nowarn_map->get (loc) : NULL)
@@ -173,8 +177,20 @@ copy_warning (location_t to, location_t from)
   if (!nowarn_map)
     return;
 
-  if (nowarn_spec_t *pspec = nowarn_map->get (from))
-    nowarn_map->put (to, *pspec);
+  nowarn_spec_t *from_spec;
+  if (RESERVED_LOCATION_P (from))
+    from_spec = NULL;
+  else
+    from_spec = nowarn_map->get (from);
+  if (RESERVED_LOCATION_P (to))
+    /* We cannot set no-warning dispositions for 'to', so we have no chance but
+       lose those potentially set for 'from'.  */
+    ;
   else
-    nowarn_map->remove (to);
+    {
+      if (from_spec)
+	nowarn_map->put (to, *from_spec);
+      else
+	nowarn_map->remove (to);
+    }
 }
diff --git a/gcc/warning-control.cc b/gcc/warning-control.cc
index 8d6c0828445..36a47ab6bae 100644
--- a/gcc/warning-control.cc
+++ b/gcc/warning-control.cc
@@ -89,7 +89,7 @@ get_nowarn_spec (const_tree expr)
 {
   const location_t loc = get_location (expr);
 
-  if (loc == UNKNOWN_LOCATION)
+  if (RESERVED_LOCATION_P (loc))
     return NULL;
 
   if (!get_no_warning_bit (expr))
@@ -105,6 +105,9 @@ get_nowarn_spec (const gimple *stmt)
 {
   const location_t loc = get_location (stmt);
 
+  if (RESERVED_LOCATION_P (loc))
+    return NULL;
+
   if (!get_no_warning_bit (stmt))
     return NULL;
 
@@ -158,7 +161,8 @@ suppress_warning (tree expr, opt_code opt /* = all_warnings */,
 
   const location_t loc = get_location (expr);
 
-  supp = suppress_warning_at (loc, opt, supp) || supp;
+  if (!RESERVED_LOCATION_P (loc))
+    supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (expr, supp);
 }
 
@@ -174,7 +178,8 @@ suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
 
   const location_t loc = get_location (stmt);
 
-  supp = suppress_warning_at (loc, opt, supp) || supp;
+  if (!RESERVED_LOCATION_P (loc))
+    supp = suppress_warning_at (loc, opt, supp) || supp;
   set_no_warning_bit (stmt, supp);
 }
 
@@ -186,24 +191,33 @@ void copy_warning (ToType to, FromType from)
 {
   const location_t to_loc = get_location (to);
 
-  if (nowarn_spec_t *from_map = get_nowarn_spec (from))
-    {
-      /* If there's an entry in the map the no-warning bit must be set.  */
-      gcc_assert (get_no_warning_bit (from));
+  bool supp = get_no_warning_bit (from);
 
-      gcc_checking_assert (nowarn_map);
-      nowarn_map->put (to_loc, *from_map);
-      set_no_warning_bit (to, true);
-    }
+  nowarn_spec_t *from_spec = get_nowarn_spec (from);
+  if (RESERVED_LOCATION_P (to_loc))
+    /* We cannot set no-warning dispositions for 'to', so we have no chance but
+       lose those potentially set for 'from'.  */
+    ;
   else
     {
-      if (nowarn_map)
-	nowarn_map->remove (to_loc);
-
-      /* The no-warning bit might be set even if there's no entry
-	 in the map.  */
-      set_no_warning_bit (to, get_no_warning_bit (from));
+      if (from_spec)
+	{
+	  /* If there's an entry in the map the no-warning bit must be set.  */
+	  gcc_assert (supp);
+
+	  gcc_checking_assert (nowarn_map);
+	  nowarn_map->put (to_loc, *from_spec);
+	}
+      else
+	{
+	  if (nowarn_map)
+	    nowarn_map->remove (to_loc);
+	}
     }
+
+  /* The no-warning bit might be set even if the map has not been consulted, or
+     otherwise if there's no entry in the map.  */
+  set_no_warning_bit (to, supp);
 }
 
 /* Copy the warning disposition mapping from one expression to another.  */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [PING] Don't maintain a warning spec for 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765))
  2021-09-10  7:45                   ` [PING] Don't maintain a warning spec for 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)) Thomas Schwinge
@ 2021-09-13 14:00                     ` Jeff Law
  0 siblings, 0 replies; 98+ messages in thread
From: Jeff Law @ 2021-09-13 14:00 UTC (permalink / raw)
  To: Thomas Schwinge, gcc-patches



On 9/10/2021 1:45 AM, Thomas Schwinge wrote:
>
> 0001-Simplify-gcc-diagnostic-spec.h-nowarn_map-setup.patch
>
>  From 095c16ead5d432726f2b6de5ce12fd367600076d Mon Sep 17 00:00:00 2001
> From: Thomas Schwinge <thomas@codesourcery.com>
> Date: Wed, 1 Sep 2021 16:48:55 +0200
> Subject: [PATCH 1/3] Simplify 'gcc/diagnostic-spec.h:nowarn_map' setup
>
> If we've just read something from the map, we can be sure that it exists.
>
> 	gcc/
> 	* warning-control.cc (copy_warning): Remove 'nowarn_map' setup.
> OK

>
> 0002-Clarify-key_type_t-to-location_t-as-used-for-gcc-dia.patch
>
>  From 23d9b93401349fca03efaef0fef0960933f4c316 Mon Sep 17 00:00:00 2001
> From: Thomas Schwinge <thomas@codesourcery.com>
> Date: Tue, 31 Aug 2021 22:01:23 +0200
> Subject: [PATCH 2/3] Clarify 'key_type_t' to 'location_t' as used for
>   'gcc/diagnostic-spec.h:nowarn_map'
>
> To make it obvious what exactly the key type is.  No change in behavior.
>
> 	gcc/
> 	* diagnostic-spec.h (typedef xint_hash_t): Use 'location_t' instead of...
> 	(typedef key_type_t): ... this.  Remove.
> 	(nowarn_map): Document.
> 	* diagnostic-spec.c (nowarn_map): Likewise.
> 	* warning-control.cc (convert_to_key): Evolve functions into...
> 	(get_location): ... these.  Adjust all users.
OK

>
> 0003-Don-t-maintain-a-warning-spec-for-UNKNOWN_LOCATION-B.patch
>
>  From 51c9a8ac2caa0432730c78d00989fd01f3ac6fe5 Mon Sep 17 00:00:00 2001
> From: Thomas Schwinge <thomas@codesourcery.com>
> Date: Mon, 30 Aug 2021 22:36:47 +0200
> Subject: [PATCH 3/3] Don't maintain a warning spec for
>   'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574]
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
>
> This resolves PR101574 "gcc/sparseset.h:215:20: error: suggest parentheses
> around assignment used as truth value [-Werror=parentheses]", as (bogusly)
> reported at commit a61f6afbee370785cf091fe46e2e022748528307:
>
>      In file included from [...]/source-gcc/gcc/lra-lives.c:43:
>      [...]/source-gcc/gcc/lra-lives.c: In function ‘void make_hard_regno_dead(int)’:
>      [...]/source-gcc/gcc/sparseset.h:215:20: error: suggest parentheses around assignment used as truth value [-Werror=parentheses]
>        215 |        && (((ITER) = sparseset_iter_elm (SPARSESET)) || 1);             \
>            |            ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>      [...]/source-gcc/gcc/lra-lives.c:304:3: note: in expansion of macro ‘EXECUTE_IF_SET_IN_SPARSESET’
>        304 |   EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
>            |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> 	gcc/
> 	PR bootstrap/101574
> 	* diagnostic-spec.c (warning_suppressed_at, copy_warning): Handle
> 	'RESERVED_LOCATION_P' locations.
> 	* warning-control.cc (get_nowarn_spec, suppress_warning)
> 	(copy_warning): Likewise.
OK.

Jeff


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765))
  2021-09-02  0:14               ` Martin Sebor
  2021-09-03 19:16                 ` Thomas Schwinge
@ 2021-11-09 10:28                 ` Thomas Schwinge
  2021-11-09 10:54                   ` Richard Biener
  2021-11-10  4:52                   ` Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204] Martin Sebor
  1 sibling, 2 replies; 98+ messages in thread
From: Thomas Schwinge @ 2021-11-09 10:28 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1737 bytes --]

Hi!

On 2021-09-01T18:14:46-0600, Martin Sebor <msebor@gmail.com> wrote:
> On 9/1/21 1:35 PM, Thomas Schwinge wrote:
>> On 2021-06-23T13:47:08-0600, Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>>> --- /dev/null
>>> +++ b/gcc/diagnostic-spec.h
>>
>>> +typedef location_t key_type_t;
>>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
>>> +typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
>>> +
>>> +/* A mapping from the location of an expression to the warning spec
>>> +   set for it.  */
>>> +extern GTY(()) xint_hash_map_t *nowarn_map;

>> Oh, and one of [my pending changes] actually (unintentially so) happens to resolve
>> <https://gcc.gnu.org/PR101204> "[12 Regression] infinite recursion in
>> gtype-desc.c since r12-1801-g7036e9ef462fde8181bece4ac4e03f3aa27204dc",
>> so unless you've done any work on that, may I take over that PR?
>
> I haven't.  Thanks for offering to take it on!  I'm curious to
> hear how your change fixes that problem.

So, instead of my earlier drive-by fix, I've since distilled what it
actually is that is causing/fixing this (strange...) problem.  OK to push
the attached "Get rid of infinite recursion for 'typedef' used with
GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204]"?  (This, of
course, only fixes the symptom but not the actual underlying problem.
But I'm not going to dig deep into 'gengtype' at this time.)  ;-)


Grüße
 Thomas


-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Get-rid-of-infinite-recursion-for-typedef-used-with-.patch --]
[-- Type: text/x-diff, Size: 3273 bytes --]

From 4d691426a602f3179ef2847903e417fe473955c5 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Tue, 9 Nov 2021 10:55:15 +0100
Subject: [PATCH] Get rid of infinite recursion for 'typedef' used with
 GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204]

Reproduced with clang version 10.0.0-4ubuntu1:

    gtype-desc.c:11333:1: warning: all paths through this function will call itself [-Winfinite-recursion]

... as well as some GCC's '-O2 -fdump-tree-optimized':

    void gt_pch_nx(int_hash<unsigned int, 0u, 4294967295u>*, gt_pointer_operator, void*) ([...])
    {
      <bb 2>:

      <bb 3>:
      goto <bb 3>;

    }

That three-arguments 'gt_pch_nx' function as well as two one-argument
'gt_ggc_mx', 'gt_pch_nx' functions now turn empty:

    [...]
     void
    -gt_ggc_mx (int_hash<location_t,0,UINT_MAX>& x_r ATTRIBUTE_UNUSED)
    +gt_ggc_mx (struct xint_hash_t& x_r ATTRIBUTE_UNUSED)
     {
    -  int_hash<location_t,0,UINT_MAX> * ATTRIBUTE_UNUSED x = &x_r;
    -  gt_ggc_mx (&((*x)));
    +  struct xint_hash_t * ATTRIBUTE_UNUSED x = &x_r;
     }
    [...]
     void
    -gt_pch_nx (int_hash<location_t,0,UINT_MAX>& x_r ATTRIBUTE_UNUSED)
    +gt_pch_nx (struct xint_hash_t& x_r ATTRIBUTE_UNUSED)
     {
    -  int_hash<location_t,0,UINT_MAX> * ATTRIBUTE_UNUSED x = &x_r;
    -  gt_pch_nx (&((*x)));
    +  struct xint_hash_t * ATTRIBUTE_UNUSED x = &x_r;
     }
    [...]
     void
    -gt_pch_nx (int_hash<location_t,0,UINT_MAX>* x ATTRIBUTE_UNUSED,
    +gt_pch_nx (struct xint_hash_t* x ATTRIBUTE_UNUSED,
            ATTRIBUTE_UNUSED gt_pointer_operator op,
            ATTRIBUTE_UNUSED void *cookie)
     {
    -    gt_pch_nx (&((*x)), op, cookie);
     }
    [...]

	gcc/
	PR middle-end/101204
	* diagnostic-spec.h (typedef xint_hash_t): Turn into...
	(struct xint_hash_t): ... this.
	* doc/gty.texi: Update.
---
 gcc/diagnostic-spec.h | 2 +-
 gcc/doc/gty.texi      | 8 ++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
index 9b3aaaa3ce6..d29cdd46290 100644
--- a/gcc/diagnostic-spec.h
+++ b/gcc/diagnostic-spec.h
@@ -130,7 +130,7 @@ operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
   return !(lhs == rhs);
 }
 
-typedef int_hash <location_t, 0, UINT_MAX> xint_hash_t;
+struct xint_hash_t : int_hash<location_t, 0, UINT_MAX> {};
 typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
 
 /* A mapping from a 'location_t' to the warning spec set for it.  */
diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index 2ad7793191b..8900e082225 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -64,6 +64,14 @@ The parser understands simple typedefs such as
 @code{typedef int @var{name};}.
 These don't need to be marked.
 
+However, in combination with GTY, avoid using typedefs such as
+@code{typedef int_hash<@dots{}> @var{name};}
+for these generate infinite-recursion code.
+See @uref{https://gcc.gnu.org/PR101204,PR101204}.
+Instead, you may use
+@code{struct @var{name} : int_hash<@dots{}> @{@};},
+for example.
+
 Since @code{gengtype}'s understanding of C++ is limited, there are
 several constructs and declarations that are not supported inside
 classes/structures marked for automatic GC code generation.  The
-- 
2.33.0


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765))
  2021-11-09 10:28                 ` Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)) Thomas Schwinge
@ 2021-11-09 10:54                   ` Richard Biener
  2021-11-09 12:25                     ` Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204, PR103157] Thomas Schwinge
  2021-11-10  4:52                   ` Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204] Martin Sebor
  1 sibling, 1 reply; 98+ messages in thread
From: Richard Biener @ 2021-11-09 10:54 UTC (permalink / raw)
  To: Thomas Schwinge; +Cc: Martin Sebor, GCC Patches, David Malcolm, Jeff Law

On Tue, Nov 9, 2021 at 11:28 AM Thomas Schwinge <thomas@codesourcery.com> wrote:
>
> Hi!
>
> On 2021-09-01T18:14:46-0600, Martin Sebor <msebor@gmail.com> wrote:
> > On 9/1/21 1:35 PM, Thomas Schwinge wrote:
> >> On 2021-06-23T13:47:08-0600, Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
> >>> --- /dev/null
> >>> +++ b/gcc/diagnostic-spec.h
> >>
> >>> +typedef location_t key_type_t;
> >>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
> >>> +typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
> >>> +
> >>> +/* A mapping from the location of an expression to the warning spec
> >>> +   set for it.  */
> >>> +extern GTY(()) xint_hash_map_t *nowarn_map;
>
> >> Oh, and one of [my pending changes] actually (unintentially so) happens to resolve
> >> <https://gcc.gnu.org/PR101204> "[12 Regression] infinite recursion in
> >> gtype-desc.c since r12-1801-g7036e9ef462fde8181bece4ac4e03f3aa27204dc",
> >> so unless you've done any work on that, may I take over that PR?
> >
> > I haven't.  Thanks for offering to take it on!  I'm curious to
> > hear how your change fixes that problem.
>
> So, instead of my earlier drive-by fix, I've since distilled what it
> actually is that is causing/fixing this (strange...) problem.  OK to push
> the attached "Get rid of infinite recursion for 'typedef' used with
> GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204]"?  (This, of
> course, only fixes the symptom but not the actual underlying problem.
> But I'm not going to dig deep into 'gengtype' at this time.)  ;-)

Did you try if

 typedef hash_map<int_hash<location_t, 0, UINT_MAX>, nowarn_spec_t>
xint_hash_map_t;

works?  Usually a typedef is needed so that gengtype can grok struct
members but it
might very well be confused about two levels of typedefs here?

That said ... I guess this kind of fix is OK - but can you please put
a big fat comment
about this in the actual code and open a bugreport tracking this
gengtype defect?

Thanks,
Richard.

>
> Grüße
>  Thomas
>
>
> -----------------
> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955

^ permalink raw reply	[flat|nested] 98+ messages in thread

* Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204, PR103157]
  2021-11-09 10:54                   ` Richard Biener
@ 2021-11-09 12:25                     ` Thomas Schwinge
  0 siblings, 0 replies; 98+ messages in thread
From: Thomas Schwinge @ 2021-11-09 12:25 UTC (permalink / raw)
  To: Richard Biener, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3863 bytes --]

Hi!

On 2021-11-09T11:54:04+0100, Richard Biener <richard.guenther@gmail.com> wrote:
> On Tue, Nov 9, 2021 at 11:28 AM Thomas Schwinge <thomas@codesourcery.com> wrote:
>> On 2021-09-01T18:14:46-0600, Martin Sebor <msebor@gmail.com> wrote:
>> > On 9/1/21 1:35 PM, Thomas Schwinge wrote:
>> >> On 2021-06-23T13:47:08-0600, Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>> >>> --- /dev/null
>> >>> +++ b/gcc/diagnostic-spec.h
>> >>
>> >>> +typedef location_t key_type_t;
>> >>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
>> >>> +typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
>> >>> +
>> >>> +/* A mapping from the location of an expression to the warning spec
>> >>> +   set for it.  */
>> >>> +extern GTY(()) xint_hash_map_t *nowarn_map;
>>
>> >> Oh, and one of [my pending changes] actually (unintentially so) happens to resolve
>> >> <https://gcc.gnu.org/PR101204> "[12 Regression] infinite recursion in
>> >> gtype-desc.c since r12-1801-g7036e9ef462fde8181bece4ac4e03f3aa27204dc",
>> >> so unless you've done any work on that, may I take over that PR?
>> >
>> > I haven't.  Thanks for offering to take it on!  I'm curious to
>> > hear how your change fixes that problem.
>>
>> So, instead of my earlier drive-by fix, I've since distilled what it
>> actually is that is causing/fixing this (strange...) problem.  OK to push
>> the attached "Get rid of infinite recursion for 'typedef' used with
>> GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204]"?  (This, of
>> course, only fixes the symptom but not the actual underlying problem.
>> But I'm not going to dig deep into 'gengtype' at this time.)  ;-)
>
> Did you try if
>
>  typedef hash_map<int_hash<location_t, 0, UINT_MAX>, nowarn_spec_t>
> xint_hash_map_t;
>
> works?

First, that would be in conflict with my goal of settling on a *single*
'location_hash' type, but also: no, 'gengtype' doesn't grok that either:

    In file included from config.h:8:0,
                     from gtype-desc.c:21:
    [...]/source-gcc/gcc/../include/ansidecl.h:148:55: error: wrong number of template arguments (1, should be at least 2)
     #  define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
                                                           ^
    gtype-desc.c:3014:37: note: in expansion of macro 'ATTRIBUTE_UNUSED'
     gt_ggc_mx (int_hash<location_t& x_r ATTRIBUTE_UNUSED)
                                         ^
    [...]

Note bogus formal parameter 'int_hash<location_t& x_r'.

That probably falls into category "understanding of C++ is limited", as
documented in 'gcc/doc/gty.texi'.  :-|


> Usually a typedef is needed so that gengtype can grok struct
> members but it
> might very well be confused about two levels of typedefs here?
>
> That said ... I guess this kind of fix is OK - but can you please put
> a big fat comment
> about this in the actual code

I had thought about that, but then decided not to do that, as the problem
is general, not specific to this particular code.  Instead, I had put
something into 'gcc/doc/gty.texi'.  Anyway, I've now put something into
that place, too.

> and open a bugreport tracking this
> gengtype defect?

<https://gcc.gnu.org/PR103157> "'gengtype': 'typedef' causing
infinite-recursion code to be generated".

Pushed to master branch commit c71cb26a9e841888f52e4bfcaad94c8f8ecb4fdb
"Get rid of infinite recursion for 'typedef' used with GTY-marked
'gcc/diagnostic-spec.h:nowarn_map' [PR101204, PR103157]", see attached.


Grüße
 Thomas


-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Get-rid-of-infinite-recursion-for-typedef-used-with-.patch --]
[-- Type: text/x-diff, Size: 3487 bytes --]

From c71cb26a9e841888f52e4bfcaad94c8f8ecb4fdb Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Tue, 9 Nov 2021 10:55:15 +0100
Subject: [PATCH] Get rid of infinite recursion for 'typedef' used with
 GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204, PR103157]

Reproduced with clang version 10.0.0-4ubuntu1:

    gtype-desc.c:11333:1: warning: all paths through this function will call itself [-Winfinite-recursion]

... as well as some GCC's '-O2 -fdump-tree-optimized':

    void gt_pch_nx(int_hash<unsigned int, 0u, 4294967295u>*, gt_pointer_operator, void*) ([...])
    {
      <bb 2>:

      <bb 3>:
      goto <bb 3>;

    }

That three-arguments 'gt_pch_nx' function as well as two one-argument
'gt_ggc_mx', 'gt_pch_nx' functions now turn empty:

    [...]
     void
    -gt_ggc_mx (int_hash<location_t,0,UINT_MAX>& x_r ATTRIBUTE_UNUSED)
    +gt_ggc_mx (struct xint_hash_t& x_r ATTRIBUTE_UNUSED)
     {
    -  int_hash<location_t,0,UINT_MAX> * ATTRIBUTE_UNUSED x = &x_r;
    -  gt_ggc_mx (&((*x)));
    +  struct xint_hash_t * ATTRIBUTE_UNUSED x = &x_r;
     }
    [...]
     void
    -gt_pch_nx (int_hash<location_t,0,UINT_MAX>& x_r ATTRIBUTE_UNUSED)
    +gt_pch_nx (struct xint_hash_t& x_r ATTRIBUTE_UNUSED)
     {
    -  int_hash<location_t,0,UINT_MAX> * ATTRIBUTE_UNUSED x = &x_r;
    -  gt_pch_nx (&((*x)));
    +  struct xint_hash_t * ATTRIBUTE_UNUSED x = &x_r;
     }
    [...]
     void
    -gt_pch_nx (int_hash<location_t,0,UINT_MAX>* x ATTRIBUTE_UNUSED,
    +gt_pch_nx (struct xint_hash_t* x ATTRIBUTE_UNUSED,
            ATTRIBUTE_UNUSED gt_pointer_operator op,
            ATTRIBUTE_UNUSED void *cookie)
     {
    -    gt_pch_nx (&((*x)), op, cookie);
     }
    [...]

	gcc/
	PR middle-end/101204
	PR other/103157
	* diagnostic-spec.h (typedef xint_hash_t): Turn into...
	(struct xint_hash_t): ... this.
	* doc/gty.texi: Update.
---
 gcc/diagnostic-spec.h | 6 +++++-
 gcc/doc/gty.texi      | 8 ++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
index 9b3aaaa3ce6..e54e9e3ddbe 100644
--- a/gcc/diagnostic-spec.h
+++ b/gcc/diagnostic-spec.h
@@ -130,7 +130,11 @@ operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
   return !(lhs == rhs);
 }
 
-typedef int_hash <location_t, 0, UINT_MAX> xint_hash_t;
+/* Per PR103157 "'gengtype': 'typedef' causing infinite-recursion code to be
+   generated", don't use
+       typedef int_hash<location_t, 0, UINT_MAX> xint_hash_t;
+   here.  */
+struct xint_hash_t : int_hash<location_t, 0, UINT_MAX> {};
 typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
 
 /* A mapping from a 'location_t' to the warning spec set for it.  */
diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index 2ad7793191b..b996ff2c44e 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -64,6 +64,14 @@ The parser understands simple typedefs such as
 @code{typedef int @var{name};}.
 These don't need to be marked.
 
+However, in combination with GTY, avoid using typedefs such as
+@code{typedef int_hash<@dots{}> @var{name};}
+for these generate infinite-recursion code.
+See @uref{https://gcc.gnu.org/PR103157,PR103157}.
+Instead, you may use
+@code{struct @var{name} : int_hash<@dots{}> @{@};},
+for example.
+
 Since @code{gengtype}'s understanding of C++ is limited, there are
 several constructs and declarations that are not supported inside
 classes/structures marked for automatic GC code generation.  The
-- 
2.33.0


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map' (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765))
  2021-09-03 19:16                 ` Thomas Schwinge
  2021-09-10  7:45                   ` [PING] Don't maintain a warning spec for 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)) Thomas Schwinge
@ 2021-11-09 14:18                   ` Thomas Schwinge
  2021-11-15 15:01                     ` [ping] Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map' Thomas Schwinge
  1 sibling, 1 reply; 98+ messages in thread
From: Thomas Schwinge @ 2021-11-09 14:18 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1158 bytes --]

Hi!

On 2021-09-03T21:16:46+0200, I wrote:
> On 2021-09-01T18:14:46-0600, Martin Sebor <msebor@gmail.com> wrote:
>> On 9/1/21 1:35 PM, Thomas Schwinge wrote:
>>> On 2021-06-23T13:47:08-0600, Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>>>> --- /dev/null
>>>> +++ b/gcc/diagnostic-spec.h
>>>
>>>> +typedef location_t key_type_t;
>>>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
>
>> By the way, it seems we should probably also use a manifest constant
>> for Empty (probably UNKNOWN_LOCATION since we're reserving it).
>
> Yes, that will be part of another patch here -- waiting for approval of
> "Generalize 'gcc/input.h:struct location_hash'" posted elsewhere.

... which I have now pushed, so I may now propose the attached patch to
"Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map'".  OK to
push?


Grüße
 Thomas


-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Use-location_hash-for-gcc-diagnostic-spec.h-nowarn_m.patch --]
[-- Type: text/x-diff, Size: 2379 bytes --]

From d346292fc95f1990abbc9f6a4a8eb89be0f0e88d Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Tue, 31 Aug 2021 23:35:15 +0200
Subject: [PATCH] Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map'

Instead of hard-coded '0'/'UINT_MAX', we now use the 'RESERVED_LOCATION_P'
values 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' as spare values for
'Empty'/'Deleted', and generally simplify the code.

	gcc/
	* diagnostic-spec.h (typedef xint_hash_t)
	(typedef xint_hash_map_t): Replace with...
	(typedef nowarn_map_t): ... this.
	(nowarn_map): Adjust.
	* diagnostic-spec.c (nowarn_map, suppress_warning_at): Likewise.
---
 gcc/diagnostic-spec.c | 4 ++--
 gcc/diagnostic-spec.h | 9 ++-------
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index 85ffb725c02..d1e563d19ba 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -107,7 +107,7 @@ nowarn_spec_t::nowarn_spec_t (opt_code opt)
 
 /* A mapping from a 'location_t' to the warning spec set for it.  */
 
-GTY(()) xint_hash_map_t *nowarn_map;
+GTY(()) nowarn_map_t *nowarn_map;
 
 /* Return the no-warning disposition for location LOC and option OPT
    or for all/any otions by default.  */
@@ -163,7 +163,7 @@ suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
     return false;
 
   if (!nowarn_map)
-    nowarn_map = xint_hash_map_t::create_ggc (32);
+    nowarn_map = nowarn_map_t::create_ggc (32);
 
   nowarn_map->put (loc, optspec);
   return true;
diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
index e54e9e3ddbe..368b75f3254 100644
--- a/gcc/diagnostic-spec.h
+++ b/gcc/diagnostic-spec.h
@@ -130,14 +130,9 @@ operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
   return !(lhs == rhs);
 }
 
-/* Per PR103157 "'gengtype': 'typedef' causing infinite-recursion code to be
-   generated", don't use
-       typedef int_hash<location_t, 0, UINT_MAX> xint_hash_t;
-   here.  */
-struct xint_hash_t : int_hash<location_t, 0, UINT_MAX> {};
-typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
+typedef hash_map<location_hash, nowarn_spec_t> nowarn_map_t;
 
 /* A mapping from a 'location_t' to the warning spec set for it.  */
-extern GTY(()) xint_hash_map_t *nowarn_map;
+extern GTY(()) nowarn_map_t *nowarn_map;
 
 #endif // DIAGNOSTIC_SPEC_H_INCLUDED
-- 
2.33.0


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204]
  2021-11-09 10:28                 ` Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)) Thomas Schwinge
  2021-11-09 10:54                   ` Richard Biener
@ 2021-11-10  4:52                   ` Martin Sebor
  2021-11-24 10:28                     ` 'gengtype' (was: Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204]) Thomas Schwinge
  1 sibling, 1 reply; 98+ messages in thread
From: Martin Sebor @ 2021-11-10  4:52 UTC (permalink / raw)
  To: Thomas Schwinge, gcc-patches

On 11/9/21 3:28 AM, Thomas Schwinge wrote:
> Hi!
> 
> On 2021-09-01T18:14:46-0600, Martin Sebor <msebor@gmail.com> wrote:
>> On 9/1/21 1:35 PM, Thomas Schwinge wrote:
>>> On 2021-06-23T13:47:08-0600, Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>>>> --- /dev/null
>>>> +++ b/gcc/diagnostic-spec.h
>>>
>>>> +typedef location_t key_type_t;
>>>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
>>>> +typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
>>>> +
>>>> +/* A mapping from the location of an expression to the warning spec
>>>> +   set for it.  */
>>>> +extern GTY(()) xint_hash_map_t *nowarn_map;
> 
>>> Oh, and one of [my pending changes] actually (unintentially so) happens to resolve
>>> <https://gcc.gnu.org/PR101204> "[12 Regression] infinite recursion in
>>> gtype-desc.c since r12-1801-g7036e9ef462fde8181bece4ac4e03f3aa27204dc",
>>> so unless you've done any work on that, may I take over that PR?
>>
>> I haven't.  Thanks for offering to take it on!  I'm curious to
>> hear how your change fixes that problem.
> 
> So, instead of my earlier drive-by fix, I've since distilled what it
> actually is that is causing/fixing this (strange...) problem.  OK to push
> the attached "Get rid of infinite recursion for 'typedef' used with
> GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204]"?  (This, of
> course, only fixes the symptom but not the actual underlying problem.
> But I'm not going to dig deep into 'gengtype' at this time.)  ;-)

Great work figuring it out!  Amazing how riddled with bugs this
gengtype stuff is.  Thanks a lot for the patch!

Martin

> 
> 
> Grüße
>   Thomas
> 
> 
> -----------------
> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
> 


^ permalink raw reply	[flat|nested] 98+ messages in thread

* [ping] Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map'
  2021-11-09 14:18                   ` Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map' " Thomas Schwinge
@ 2021-11-15 15:01                     ` Thomas Schwinge
  2021-11-15 16:43                       ` Martin Sebor
  0 siblings, 1 reply; 98+ messages in thread
From: Thomas Schwinge @ 2021-11-15 15:01 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1269 bytes --]

Hi!

Ping.


Grüße
 Thomas


On 2021-11-09T15:18:44+0100, I wrote:
> Hi!
>
> On 2021-09-03T21:16:46+0200, I wrote:
>> On 2021-09-01T18:14:46-0600, Martin Sebor <msebor@gmail.com> wrote:
>>> On 9/1/21 1:35 PM, Thomas Schwinge wrote:
>>>> On 2021-06-23T13:47:08-0600, Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>>>>> --- /dev/null
>>>>> +++ b/gcc/diagnostic-spec.h
>>>>
>>>>> +typedef location_t key_type_t;
>>>>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
>>
>>> By the way, it seems we should probably also use a manifest constant
>>> for Empty (probably UNKNOWN_LOCATION since we're reserving it).
>>
>> Yes, that will be part of another patch here -- waiting for approval of
>> "Generalize 'gcc/input.h:struct location_hash'" posted elsewhere.
>
> ... which I have now pushed, so I may now propose the attached patch to
> "Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map'".  OK to
> push?
>
>
> Grüße
>  Thomas


-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Use-location_hash-for-gcc-diagnostic-spec.h-nowarn_m.patch --]
[-- Type: text/x-diff, Size: 2379 bytes --]

From d346292fc95f1990abbc9f6a4a8eb89be0f0e88d Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Tue, 31 Aug 2021 23:35:15 +0200
Subject: [PATCH] Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map'

Instead of hard-coded '0'/'UINT_MAX', we now use the 'RESERVED_LOCATION_P'
values 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' as spare values for
'Empty'/'Deleted', and generally simplify the code.

	gcc/
	* diagnostic-spec.h (typedef xint_hash_t)
	(typedef xint_hash_map_t): Replace with...
	(typedef nowarn_map_t): ... this.
	(nowarn_map): Adjust.
	* diagnostic-spec.c (nowarn_map, suppress_warning_at): Likewise.
---
 gcc/diagnostic-spec.c | 4 ++--
 gcc/diagnostic-spec.h | 9 ++-------
 2 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c
index 85ffb725c02..d1e563d19ba 100644
--- a/gcc/diagnostic-spec.c
+++ b/gcc/diagnostic-spec.c
@@ -107,7 +107,7 @@ nowarn_spec_t::nowarn_spec_t (opt_code opt)
 
 /* A mapping from a 'location_t' to the warning spec set for it.  */
 
-GTY(()) xint_hash_map_t *nowarn_map;
+GTY(()) nowarn_map_t *nowarn_map;
 
 /* Return the no-warning disposition for location LOC and option OPT
    or for all/any otions by default.  */
@@ -163,7 +163,7 @@ suppress_warning_at (location_t loc, opt_code opt /* = all_warnings */,
     return false;
 
   if (!nowarn_map)
-    nowarn_map = xint_hash_map_t::create_ggc (32);
+    nowarn_map = nowarn_map_t::create_ggc (32);
 
   nowarn_map->put (loc, optspec);
   return true;
diff --git a/gcc/diagnostic-spec.h b/gcc/diagnostic-spec.h
index e54e9e3ddbe..368b75f3254 100644
--- a/gcc/diagnostic-spec.h
+++ b/gcc/diagnostic-spec.h
@@ -130,14 +130,9 @@ operator!= (const nowarn_spec_t &lhs, const nowarn_spec_t &rhs)
   return !(lhs == rhs);
 }
 
-/* Per PR103157 "'gengtype': 'typedef' causing infinite-recursion code to be
-   generated", don't use
-       typedef int_hash<location_t, 0, UINT_MAX> xint_hash_t;
-   here.  */
-struct xint_hash_t : int_hash<location_t, 0, UINT_MAX> {};
-typedef hash_map<xint_hash_t, nowarn_spec_t> xint_hash_map_t;
+typedef hash_map<location_hash, nowarn_spec_t> nowarn_map_t;
 
 /* A mapping from a 'location_t' to the warning spec set for it.  */
-extern GTY(()) xint_hash_map_t *nowarn_map;
+extern GTY(()) nowarn_map_t *nowarn_map;
 
 #endif // DIAGNOSTIC_SPEC_H_INCLUDED
-- 
2.33.0


^ permalink raw reply	[flat|nested] 98+ messages in thread

* Re: [ping] Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map'
  2021-11-15 15:01                     ` [ping] Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map' Thomas Schwinge
@ 2021-11-15 16:43                       ` Martin Sebor
  0 siblings, 0 replies; 98+ messages in thread
From: Martin Sebor @ 2021-11-15 16:43 UTC (permalink / raw)
  To: Thomas Schwinge, gcc-patches

On 11/15/21 8:01 AM, Thomas Schwinge wrote:
> Hi!
> 
> Ping.

This change looks good to me.

Martin

> 
> Grüße
>   Thomas
> 
> 
> On 2021-11-09T15:18:44+0100, I wrote:
>> Hi!
>>
>> On 2021-09-03T21:16:46+0200, I wrote:
>>> On 2021-09-01T18:14:46-0600, Martin Sebor <msebor@gmail.com> wrote:
>>>> On 9/1/21 1:35 PM, Thomas Schwinge wrote:
>>>>> On 2021-06-23T13:47:08-0600, Martin Sebor via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>>>>>> --- /dev/null
>>>>>> +++ b/gcc/diagnostic-spec.h
>>>>>
>>>>>> +typedef location_t key_type_t;
>>>>>> +typedef int_hash <key_type_t, 0, UINT_MAX> xint_hash_t;
>>>
>>>> By the way, it seems we should probably also use a manifest constant
>>>> for Empty (probably UNKNOWN_LOCATION since we're reserving it).
>>>
>>> Yes, that will be part of another patch here -- waiting for approval of
>>> "Generalize 'gcc/input.h:struct location_hash'" posted elsewhere.
>>
>> ... which I have now pushed, so I may now propose the attached patch to
>> "Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map'".  OK to
>> push?
>>
>>
>> Grüße
>>   Thomas
> 
> 
> -----------------
> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955
> 


^ permalink raw reply	[flat|nested] 98+ messages in thread

* 'gengtype' (was: Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204])
  2021-11-10  4:52                   ` Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204] Martin Sebor
@ 2021-11-24 10:28                     ` Thomas Schwinge
  0 siblings, 0 replies; 98+ messages in thread
From: Thomas Schwinge @ 2021-11-24 10:28 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches

Hi!

On 2021-11-09T21:52:50-0700, Martin Sebor <msebor@gmail.com> wrote:
> Amazing how riddled with bugs this
> gengtype stuff is.

Relevant Mike Stump quote from long ago, that I ran into while
researching 'gengtype' vs. 'typedef',
<https://gcc.gnu.org/legacy-ml/gcc/2003-03/msg01259.html>:

| Think of it this way, imagine you had a really good C parser, but that
| you couldn't reuse any of it to write complex transformational style
| code, but rather, had to re-implement a new C parser from scratch and
| you did it, uhm, what's the right word, expediently.

;-\


Alternative approaches to 'gengtype' have been discussed more than once,
but...


Grüße
 Thomas
-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955

^ permalink raw reply	[flat|nested] 98+ messages in thread

end of thread, other threads:[~2021-11-24 10:29 UTC | newest]

Thread overview: 98+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-24 22:02 [PATCH 0/11] warning control by group and location (PR 74765) Martin Sebor
2021-05-24 22:07 ` [PATCH 1/11] introduce xxx_no_warning APIs Martin Sebor
2021-05-24 22:09   ` [PATCH 2/11] use xxx_no_warning APIs in Ada Martin Sebor
2021-05-25  8:59     ` Eric Botcazou
2021-05-27 20:29       ` Martin Sebor
2021-05-24 22:10   ` [PATCH 3/11] use xxx_no_warning APIs in C Martin Sebor
2021-05-24 22:11   ` [PATCH 4/11] use xxx_no_warning APIs in C family Martin Sebor
2021-05-24 22:11   ` [PATCH 5/11] use xxx_no_warning APIs in C++ Martin Sebor
2021-05-24 22:12   ` [PATCH 6/11] use xxx_no_warning APIs in Fortran Martin Sebor
2021-05-24 22:13   ` [PATCH 7/11] " Martin Sebor
2021-05-24 22:14   ` [PATCH 8/11] use xxx_no_warning APIs in Objective-C Martin Sebor
2021-05-25 14:01     ` Iain Sandoe
2021-05-25 15:48       ` Martin Sebor
2021-05-25 15:56         ` Iain Sandoe
2021-05-24 22:15   ` [PATCH 9/11] use xxx_no_warning APIs in rl78 back end Martin Sebor
2021-05-24 22:16   ` [PATCH 10/11] use xxx_no_warning APIs in libcc1 Martin Sebor
2021-05-24 22:16   ` [PATCH 11/11] use xxx_no_warning APIs in the middle end Martin Sebor
2021-05-24 23:08     ` David Malcolm
2021-05-25  0:44       ` Martin Sebor
2021-05-24 23:08 ` [PATCH 0/11] warning control by group and location (PR 74765) David Malcolm
2021-05-25  0:42   ` Martin Sebor
2021-05-25  9:04     ` Richard Biener
2021-05-25 20:50       ` Martin Sebor
2021-05-27 11:19     ` Richard Sandiford
2021-05-27 16:41       ` Martin Sebor
2021-05-27 21:55         ` David Malcolm
2021-05-28  4:40           ` Jason Merrill
2021-06-04 21:27   ` [PATCH 0/13] v2 " Martin Sebor
2021-06-04 21:41     ` [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups " Martin Sebor
2021-06-21 21:34       ` [PING][PATCH " Martin Sebor
2021-06-22 23:18       ` [PATCH " David Malcolm
2021-06-22 23:28         ` David Malcolm
2021-06-23 19:47           ` Martin Sebor
2021-06-24  5:26             ` Jeff Law
2021-06-25  1:34               ` Martin Sebor
2021-09-01 19:35             ` Thomas Schwinge
2021-09-02  0:14               ` Martin Sebor
2021-09-03 19:16                 ` Thomas Schwinge
2021-09-10  7:45                   ` [PING] Don't maintain a warning spec for 'UNKNOWN_LOCATION'/'BUILTINS_LOCATION' [PR101574] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)) Thomas Schwinge
2021-09-13 14:00                     ` Jeff Law
2021-11-09 14:18                   ` Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map' " Thomas Schwinge
2021-11-15 15:01                     ` [ping] Use 'location_hash' for 'gcc/diagnostic-spec.h:nowarn_map' Thomas Schwinge
2021-11-15 16:43                       ` Martin Sebor
2021-11-09 10:28                 ` Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204] (was: [PATCH 1/13] v2 [PATCH 1/13] Add support for per-location warning groups (PR 74765)) Thomas Schwinge
2021-11-09 10:54                   ` Richard Biener
2021-11-09 12:25                     ` Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204, PR103157] Thomas Schwinge
2021-11-10  4:52                   ` Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204] Martin Sebor
2021-11-24 10:28                     ` 'gengtype' (was: Get rid of infinite recursion for 'typedef' used with GTY-marked 'gcc/diagnostic-spec.h:nowarn_map' [PR101204]) Thomas Schwinge
2021-06-04 21:41     ` [PATCH 2/13] v2 Use new per-location warning APIs in Ada Martin Sebor
2021-06-24  5:07       ` Jeff Law
2021-06-28 21:20         ` Martin Sebor
2021-06-04 21:41     ` [PATCH 3/13] v2 Use new per-location warning APIs in C front end Martin Sebor
2021-06-21 21:35       ` [PING][PATCH " Martin Sebor
2021-06-24  5:09       ` [PATCH " Jeff Law
2021-06-25  1:35         ` Martin Sebor
2021-06-04 21:42     ` [PATCH 4/13] v2 Use new per-location warning APIs in C family code Martin Sebor
2021-06-21 21:35       ` [PING][PATCH " Martin Sebor
2021-06-24  5:06       ` [PATCH " Jeff Law
2021-06-25  1:36         ` Martin Sebor
2021-06-04 21:42     ` [PATCH 5/13] v2 Use new per-location warning APIs in the RL78 back end Martin Sebor
2021-06-24  5:06       ` Jeff Law
2021-06-04 21:42     ` [PATCH 6/13] v2 Use new per-location warning APIs in the C++ front end Martin Sebor
2021-06-21 21:37       ` [PING][PATCH " Martin Sebor
2021-06-24  5:12       ` [PATCH " Jeff Law
2021-06-25  1:38         ` Martin Sebor
2021-06-04 21:42     ` [PATCH 7/13] v2 Use new per-location warning APIs in the FORTRAN " Martin Sebor
2021-06-21 21:42       ` [PING][PATCH " Martin Sebor
2021-06-24  5:05       ` [PATCH " Jeff Law
2021-06-28 21:21         ` Martin Sebor
2021-06-04 21:42     ` [PATCH 8/13] v2 Use new per-location warning APIs in libcc1 Martin Sebor
2021-06-24  5:04       ` Jeff Law
2021-06-28 21:22         ` Martin Sebor
2021-06-04 21:43     ` [PATCH 9/13] v2 Use new per-location warning APIs in LTO Martin Sebor
2021-06-21 21:54       ` [PING][PATCH " Martin Sebor
2021-06-24  9:32         ` Richard Biener
2021-06-24 15:27           ` Martin Sebor
2021-06-25  7:46             ` Richard Biener
2021-06-24  5:03       ` [PATCH " Jeff Law
2021-06-04 21:43     ` [PATCH 10/13] v2 Use new per-location warning APIs in the middle end Martin Sebor
2021-06-21 21:58       ` [PING][PATCH " Martin Sebor
2021-06-24  5:15       ` [PATCH " Jeff Law
2021-06-25  1:40         ` Martin Sebor
2021-06-04 21:43     ` [PATCH 11/13] v2 Use new per-location warning APIs in the Objective-C front end Martin Sebor
2021-06-24  5:02       ` Jeff Law
2021-06-28 21:22         ` Martin Sebor
2021-06-04 21:43     ` [PATCH 12/13] v2 Remove TREE_NO_WARNING and gimple*no_warning* APIs Martin Sebor
2021-06-24  5:01       ` Jeff Law
2021-06-04 21:43     ` [PATCH 13/13] v2 Add regression tests for PR 74765 and 74762 Martin Sebor
2021-06-24  4:56       ` Jeff Law
2021-06-28 21:23         ` Martin Sebor
2021-06-15  1:29     ` [PING][PATCH 0/13] v2 warning control by group and location (PR 74765) Martin Sebor
2021-07-17 20:36     ` [PATCH " Jan-Benedict Glaw
2021-07-19 15:08       ` Martin Sebor
2021-07-28 11:14         ` Andrew Burgess
2021-07-28 16:16           ` Martin Sebor
2021-07-29  8:26             ` Andrew Burgess
2021-07-29 14:41               ` Martin Sebor
2021-05-30  2:06 ` [PATCH 0/11] " Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).