/* Functions to enable and disable individual warnings on an expression and statement basis. Copyright (C) 2021 Free Software Foundation, Inc. Contributed by Martin Sebor 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 . */ #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_Wsizeof_pointer_memaccess: 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; } } /* A mapping from a 'location_t' to the warning spec set for it. */ 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 */) { gcc_checking_assert (!RESERVED_LOCATION_P (loc)); 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 */) { 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) { 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; 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 { if (from_spec) nowarn_map->put (to, *from_spec); else nowarn_map->remove (to); } }