| /* Functions to enable and disable individual warnings on an expression |
| and statement basis. |
| Copyright (C) 2021-2022 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; |
| |
| case OPT_Wdangling_pointer_: |
| case OPT_Wreturn_local_addr: |
| case OPT_Wuse_after_free_: |
| m_bits = NW_DANGLING; |
| 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(()) nowarn_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 = nowarn_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_spec_t tem = *from_spec; |
| nowarn_map->put (to, tem); |
| } |
| else |
| nowarn_map->remove (to); |
| } |
| } |