public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-1801] Add support for per-location warning groups.
@ 2021-06-25  1:31 Martin Sebor
  0 siblings, 0 replies; only message in thread
From: Martin Sebor @ 2021-06-25  1:31 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:7036e9ef462fde8181bece4ac4e03f3aa27204dc

commit r12-1801-g7036e9ef462fde8181bece4ac4e03f3aa27204dc
Author: Martin Sebor <msebor@redhat.com>
Date:   Thu Jun 24 11:11:00 2021 -0600

    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:
---
 gcc/Makefile.in        |   6 +-
 gcc/diagnostic-spec.c  | 179 +++++++++++++++++++++++++++++++++++++
 gcc/diagnostic-spec.h  | 141 +++++++++++++++++++++++++++++
 gcc/gengtype.c         |   2 +-
 gcc/tree.h             |  12 +++
 gcc/warning-control.cc | 238 +++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 575 insertions(+), 3 deletions(-)

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..fbe52c6445c
--- /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:
+      m_bits = 0;
+      break;
+
+    case all_warnings:
+      m_bits = -1;
+      break;
+
+      /* Flow-sensitive warnings about pointer problems issued by both
+	 front ends and the middle end.  */
+    case OPT_Waddress:
+    case OPT_Wnonnull:
+      m_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:
+      m_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:
+      m_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:
+      m_bits = NW_ACCESS;
+      break;
+
+      /* Initialization warning group.  */
+    case OPT_Winit_self:
+    case OPT_Wuninitialized:
+    case OPT_Wmaybe_uninitialized:
+	m_bits = NW_UNINIT;
+      break;
+
+    default:
+      /* A catchall group for everything else.  */
+      m_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 for 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..4e4d260f74a
--- /dev/null
+++ b/gcc/diagnostic-spec.h
@@ -0,0 +1,141 @@
+/* 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.  */
+
+class nowarn_spec_t
+{
+public:
+  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 (): m_bits () { }
+
+  nowarn_spec_t (opt_code);
+
+  /* Return the raw bitset.  */
+  operator unsigned() const
+  {
+    return m_bits;
+  }
+
+  /* Return true if the bitset is clear.  */
+  bool operator!() const
+  {
+    return !m_bits;
+  }
+
+  /* Return the inverse of the bitset.  */
+  nowarn_spec_t operator~() const
+  {
+    nowarn_spec_t res (*this);
+    res.m_bits &= ~NW_ALL;
+    return res;
+  }
+
+  /* Set *THIS to the bitwise OR of *THIS and RHS.  */
+  nowarn_spec_t& operator|= (const nowarn_spec_t &rhs)
+  {
+    m_bits |= rhs.m_bits;
+    return *this;
+  }
+
+  /* Set *THIS to the bitwise AND of *THIS and RHS.  */
+  nowarn_spec_t& operator&= (const nowarn_spec_t &rhs)
+  {
+    m_bits &= rhs.m_bits;
+    return *this;
+  }
+
+  /* Set *THIS to the bitwise exclusive OR of *THIS and RHS.  */
+  nowarn_spec_t& operator^= (const nowarn_spec_t &rhs)
+  {
+    m_bits ^= rhs.m_bits;
+    return *this;
+  }
+
+private:
+  /* Bitset of warning groups.  */
+  unsigned m_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 060ddee09dd..e5d17188089 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.  */
 
@@ -6441,4 +6442,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] only message in thread

only message in thread, other threads:[~2021-06-25  1:31 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-25  1:31 [gcc r12-1801] Add support for per-location warning groups Martin Sebor

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).