/* 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_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;
    }
}

/* 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
warning_suppressed_at (location_t loc, opt_code opt /* = all_warnings */)
{
  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 */)
{
  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;

  if (nowarn_spec_t *pspec = nowarn_map->get (from))
    nowarn_map->put (to, *pspec);
  else
    nowarn_map->remove (to);
}
