/* -Winfinite-recursion support.
   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 "tree.h"
#include "gimple.h"
#include "tree-pass.h"
#include "ssa.h"
#include "diagnostic-core.h"
// #include "tree-dfa.h"
#include "attribs.h"
#include "gimple-iterator.h"

namespace {

const pass_data warn_recursion_data =
{
  GIMPLE_PASS, /* type */
  "*infinite-recursion", /* name */
  OPTGROUP_NONE, /* optinfo_flags */
  TV_NONE, /* tv_id */
  PROP_ssa, /* properties_required */
  0, /* properties_provided */
  0, /* properties_destroyed */
  0, /* todo_flags_start */
  0, /* todo_flags_finish */
};

class pass_warn_recursion : public gimple_opt_pass
{
public:
  pass_warn_recursion (gcc::context *);

private:
  virtual bool gate (function *) { return warn_infinite_recursion; }

  virtual unsigned int execute (function *);

  bool find_function_exit (basic_block);

  /* Recursive calls found in M_FUNC.  */
  vec<gimple *> *m_calls;
  /* Basic blocks already visited in the current function.  */
  bitmap m_visited;
  /* The current function.  */
  function *m_func;
  /* The current function code if it's (also) a built-in.  */
  built_in_function m_built_in;
  /* True if M_FUNC is a noreturn function.  */
  bool noreturn_p;
};

/* Initialize the pass and its members.  */

pass_warn_recursion::pass_warn_recursion (gcc::context *ctxt)
  : gimple_opt_pass (warn_recursion_data, ctxt),
    m_calls (), m_visited (), m_func (), m_built_in (), noreturn_p ()
{
}

/* Return true if there is path from BB to M_FUNC exit point along which
   there is no (recursive) call to M_FUNC.  */

bool
pass_warn_recursion::find_function_exit (basic_block bb)
{
  if (!bitmap_set_bit (m_visited, bb->index))
    return false;

  if (bb == EXIT_BLOCK_PTR_FOR_FN (m_func))
    return true;

  /* Iterate over statements in BB, looking for a call to FNDECL.  */
  for (auto si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next_nondebug (&si))
    {
      gimple *stmt = gsi_stmt (si);
      if (!is_gimple_call (stmt))
	continue;

      if (gimple_call_builtin_p (stmt, BUILT_IN_LONGJMP))
	/* A longjmp breaks infinite recursion.  */
	return true;

      if (tree fndecl = gimple_call_fndecl (stmt))
	{
	  /* A throw statement breaks infinite recursion.  */
	  tree id = DECL_NAME (fndecl);
	  const char *name = IDENTIFIER_POINTER (id);
	  if (startswith (name, "__cxa_throw"))
	    return true;
	  /* As does a call to POSIX siglongjmp.  */
	  if (!strcmp (name, "siglongjmp"))
	    return true;

	  if (m_built_in && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
	      && m_built_in == DECL_FUNCTION_CODE (fndecl))
	    {
	      /* The call is being made from the definition of a built-in
		 (e.g., in a replacement of one) to itself.  */
	      m_calls->safe_push (stmt);
	      return false;
	    }
	}

      if (noreturn_p)
	{
	  /* A noreturn call breaks infinite recursion.  */
	  int flags = gimple_call_flags (stmt);
	  if (flags & ECF_NORETURN)
	    return true;
	}

      tree callee = gimple_call_fndecl (stmt);
      if (!callee || m_func->decl != callee)
	continue;

      /* Add the recursive call to the vector and return false.  */
      m_calls->safe_push (stmt);
      return false;
    }

  /* If no call to FNDECL has been found search all BB's successors.  */
  edge e;
  edge_iterator ei;
  FOR_EACH_EDGE (e, ei, bb->succs)
    if (find_function_exit (e->dest))
      return true;

  return false;
}


/* Search FUNC for unconditionally infinitely recursive calls to self
   and issue a warning if it is such a function.  */

unsigned int
pass_warn_recursion::execute (function *func)
{
  auto_bitmap visited;
  auto_vec<gimple *> calls;

  m_visited = visited;
  m_calls = &calls;
  m_func = func;

  /* Avoid diagnosing an apparently infinitely recursive function that
     doesn't return where the infinite recursion might be avoided by
     a call to another noreturn function.  */
  noreturn_p = lookup_attribute ("noreturn", DECL_ATTRIBUTES (m_func->decl));

  if (fndecl_built_in_p (m_func->decl, BUILT_IN_NORMAL))
    m_built_in = DECL_FUNCTION_CODE (m_func->decl);
  else
    m_built_in = BUILT_IN_NONE;

  basic_block entry_bb = ENTRY_BLOCK_PTR_FOR_FN (func);

  if (find_function_exit (entry_bb) || m_calls->length () == 0)
    return 0;

  if (warning_at (DECL_SOURCE_LOCATION (func->decl),
		  OPT_Winfinite_recursion,
		  "infinite recursion detected"))
    for (auto stmt: *m_calls)
      {
	location_t loc = gimple_location (stmt);
	if (loc == UNKNOWN_LOCATION)
	  continue;

	inform (loc, "recursive call");
      }

  return 0;
}

} // namespace

gimple_opt_pass *
make_pass_warn_recursion (gcc::context *ctxt)
{
  return new pass_warn_recursion (ctxt);
}
