diff options
Diffstat (limited to 'gcc/diagnostic-spec.c')
-rw-r--r-- | gcc/diagnostic-spec.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/gcc/diagnostic-spec.c b/gcc/diagnostic-spec.c new file mode 100644 index 0000000..85ffb72 --- /dev/null +++ b/gcc/diagnostic-spec.c @@ -0,0 +1,196 @@ +/* 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_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); + } +} |