209 lines
5.2 KiB
C++
209 lines
5.2 KiB
C++
/* Functions to enable and disable individual warnings on an expression
|
|
and statement basis.
|
|
Copyright (C) 2021-2023 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_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;
|
|
|
|
case OPT_Wpessimizing_move:
|
|
case OPT_Wredundant_move:
|
|
m_bits = NW_REDUNDANT;
|
|
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);
|
|
}
|
|
}
|