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.
@@ -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 \
new file mode 100644
@@ -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);
+}
new file mode 100644
@@ -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
@@ -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;
new file mode 100644
@@ -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);
+}