/* Functions to enable and disable individual warnings on an expression
   and statement basis.

   Copyright (C) 2021 Free Software Foundation, Inc.

   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 "gimple.h"
#include "cgraph.h"
#include "hash-map.h"
#include "diagnostic-spec.h"

/* Return the no-warning bit for EXPR.  */

static inline bool
get_no_warning_bit (const_tree expr)
{
  return expr->base.nowarning_flag;
}

/* Return the no-warning bit for statement STMT.  */

static inline bool
get_no_warning_bit (const gimple *stmt)
{
  return stmt->no_warning;
}

/* Set the no-warning bit for EXPR to VALUE.  */

static inline void
set_no_warning_bit (tree expr, bool value)
{
  expr->base.nowarning_flag = value;
}

/* Set the no-warning bit for statement STMT to VALUE.  */

static inline void
set_no_warning_bit (gimple *stmt, bool value)
{
  stmt->no_warning = value;
}

/* Return EXPR location or 'UNKNOWN_LOCATION'.  */

static inline location_t
get_location (const_tree expr)
{
  if (DECL_P (expr))
    return DECL_SOURCE_LOCATION (expr);
  if (EXPR_P (expr))
    return EXPR_LOCATION (expr);
  return UNKNOWN_LOCATION;
}

/* Return STMT location (may be 'UNKNOWN_LOCATION').  */

static inline location_t
get_location (const gimple *stmt)
{
  return gimple_location (stmt);
}

/* Return the no-warning bitmap for decl/expression EXPR.  */

static nowarn_spec_t *
get_nowarn_spec (const_tree expr)
{
  const location_t loc = get_location (expr);

  if (RESERVED_LOCATION_P (loc))
    return NULL;

  if (!get_no_warning_bit (expr))
    return NULL;

  return nowarn_map ? nowarn_map->get (loc) : NULL;
}

/* Return the no-warning bitmap for stateemt STMT.  */

static nowarn_spec_t *
get_nowarn_spec (const gimple *stmt)
{
  const location_t loc = get_location (stmt);

  if (RESERVED_LOCATION_P (loc))
    return NULL;

  if (!get_no_warning_bit (stmt))
    return NULL;

  return nowarn_map ? nowarn_map->get (loc) : NULL;
}

/* Return true if warning OPT is suppressed for decl/expression EXPR.
   By default tests the disposition for any warning.  */

bool
warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */)
{
  const nowarn_spec_t *spec = get_nowarn_spec (expr);

  if (!spec)
    return get_no_warning_bit (expr);

  const nowarn_spec_t optspec (opt);
  bool dis = *spec & optspec;
  gcc_assert (get_no_warning_bit (expr) || !dis);
  return dis;
}

/* Return true if warning OPT is suppressed for statement STMT.
   By default tests the disposition for any warning.  */

bool
warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */)
{
  const nowarn_spec_t *spec = get_nowarn_spec (stmt);

  if (!spec)
    /* Fall back on the single no-warning bit.  */
    return get_no_warning_bit (stmt);

  const nowarn_spec_t optspec (opt);
  bool dis = *spec & optspec;
  gcc_assert (get_no_warning_bit (stmt) || !dis);
  return dis;
}

/* Enable, or by default disable, a warning for the expression.
   The wildcard OPT of -1 controls all warnings.  */

void
suppress_warning (tree expr, opt_code opt /* = all_warnings */,
		  bool supp /* = true */)
{
  if (opt == no_warning)
    return;

  const location_t loc = get_location (expr);

  if (!RESERVED_LOCATION_P (loc))
    supp = suppress_warning_at (loc, opt, supp) || supp;
  set_no_warning_bit (expr, supp);
}

/* Enable, or by default disable, a warning for the statement STMT.
   The wildcard OPT of -1 controls all warnings.  */

void
suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */,
		  bool supp /* = true */)
{
  if (opt == no_warning)
    return;

  const location_t loc = get_location (stmt);

  if (!RESERVED_LOCATION_P (loc))
    supp = suppress_warning_at (loc, opt, supp) || supp;
  set_no_warning_bit (stmt, supp);
}

/* Copy the warning disposition mapping between an expression and/or
   a statement.  */

template <class ToType, class FromType>
void copy_warning (ToType to, FromType from)
{
  const location_t to_loc = get_location (to);

  bool supp = get_no_warning_bit (from);

  nowarn_spec_t *from_spec = get_nowarn_spec (from);
  if (RESERVED_LOCATION_P (to_loc))
    /* We cannot set no-warning dispositions for 'to', so we have no chance but
       lose those potentially set for 'from'.  */
    ;
  else
    {
      if (from_spec)
	{
	  /* If there's an entry in the map the no-warning bit must be set.  */
	  gcc_assert (supp);

	  gcc_checking_assert (nowarn_map);
	  nowarn_map->put (to_loc, *from_spec);
	}
      else
	{
	  if (nowarn_map)
	    nowarn_map->remove (to_loc);
	}
    }

  /* The no-warning bit might be set even if the map has not been consulted, or
     otherwise if there's no entry in the map.  */
  set_no_warning_bit (to, supp);
}

/* Copy the warning disposition mapping from one expression to another.  */

void
copy_warning (tree to, const_tree from)
{
  copy_warning<tree, const_tree>(to, from);
}

/* Copy the warning disposition mapping from a statement to an expression.  */

void
copy_warning (tree to, const gimple *from)
{
  copy_warning<tree, const gimple *>(to, from);
}

/* Copy the warning disposition mapping from an expression to a statement.  */

void
copy_warning (gimple *to, const_tree from)
{
  copy_warning<gimple *, const_tree>(to, from);
}

/* Copy the warning disposition mapping from one statement to another.  */

void
copy_warning (gimple *to, const gimple *from)
{
  copy_warning<gimple *, const gimple *>(to, from);
}
