From 63d4b15d55ae9548b4cc6145af6bd58ef4ef8c6c Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Sun, 26 Jan 2020 18:40:43 -0500
Subject: [PATCH 04/68] calls.c: refactor special_function_p for use by
 analyzer

This patch refactors some code in special_function_p that checks for
the function being sane to match by name, splitting it out into a new
maybe_special_function_p, and using it it two places in the analyzer.

gcc/analyzer/ChangeLog:
	* analyzer.cc (is_named_call_p): Replace tests for fndecl being
	extern at file scope and having a non-NULL DECL_NAME with a call
	to maybe_special_function_p.
	* function-set.cc (function_set::contains_decl_p): Add call to
	maybe_special_function_p.

gcc/ChangeLog:
	* calls.c (maybe_special_function_p): New function, splitting out
	the check for DECL_NAME being non-NULL and fndecl being extern at
	file scope from...
	(special_function_p): ...here.  Drop check for fndecl being
	non-NULL that was after a usage of DECL_NAME (fndecl).
	* tree.h (maybe_special_function_p): New decl.
---
 gcc/analyzer/analyzer.cc     | 10 +--------
 gcc/analyzer/function-set.cc |  2 ++
 gcc/calls.c                  | 40 +++++++++++++++++++++++++-----------
 gcc/tree.h                   |  2 ++
 4 files changed, 33 insertions(+), 21 deletions(-)

diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc
index 1b5e4c9ecf8..5cf745ea632 100644
--- a/gcc/analyzer/analyzer.cc
+++ b/gcc/analyzer/analyzer.cc
@@ -65,18 +65,10 @@ is_named_call_p (tree fndecl, const char *funcname)
   gcc_assert (fndecl);
   gcc_assert (funcname);
 
-  /* Exclude functions not at the file scope, or not `extern',
-     since they are not the magic functions we would otherwise
-     think they are.  */
-  if (!((DECL_CONTEXT (fndecl) == NULL_TREE
-	 || TREE_CODE (DECL_CONTEXT (fndecl)) == TRANSLATION_UNIT_DECL)
-	&& TREE_PUBLIC (fndecl)))
+  if (!maybe_special_function_p (fndecl))
     return false;
 
   tree identifier = DECL_NAME (fndecl);
-  if (identifier == NULL)
-    return false;
-
   const char *name = IDENTIFIER_POINTER (identifier);
   const char *tname = name;
 
diff --git a/gcc/analyzer/function-set.cc b/gcc/analyzer/function-set.cc
index 6ed15ae95ad..1b6b5d9f9c1 100644
--- a/gcc/analyzer/function-set.cc
+++ b/gcc/analyzer/function-set.cc
@@ -59,6 +59,8 @@ bool
 function_set::contains_decl_p (tree fndecl) const
 {
   gcc_assert (fndecl && DECL_P (fndecl));
+  if (!maybe_special_function_p (fndecl))
+    return false;
   return contains_name_p (IDENTIFIER_POINTER (DECL_NAME (fndecl)));
 }
 
diff --git a/gcc/calls.c b/gcc/calls.c
index 1336f49ea5e..447a36c3707 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -572,22 +572,18 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
     anti_adjust_stack (gen_int_mode (n_popped, Pmode));
 }
 
-/* Determine if the function identified by FNDECL is one with
-   special properties we wish to know about.  Modify FLAGS accordingly.
-
-   For example, if the function might return more than one time (setjmp), then
-   set ECF_RETURNS_TWICE.
+/* Determine if the function identified by FNDECL is one that
+   makes sense to match by name, for those places where we detect
+   "magic" functions by name.
 
-   Set ECF_MAY_BE_ALLOCA for any memory allocation function that might allocate
-   space from the stack such as alloca.  */
+   Return true if FNDECL has a name and is an extern fndecl at file scope.
+   FNDECL must be a non-NULL decl.  */
 
-static int
-special_function_p (const_tree fndecl, int flags)
+bool
+maybe_special_function_p (const_tree fndecl)
 {
   tree name_decl = DECL_NAME (fndecl);
-
-  if (fndecl && name_decl
-      && IDENTIFIER_LENGTH (name_decl) <= 11
+  if (name_decl
       /* Exclude functions not at the file scope, or not `extern',
 	 since they are not the magic functions we would otherwise
 	 think they are.
@@ -598,6 +594,26 @@ special_function_p (const_tree fndecl, int flags)
       && (DECL_CONTEXT (fndecl) == NULL_TREE
 	  || TREE_CODE (DECL_CONTEXT (fndecl)) == TRANSLATION_UNIT_DECL)
       && TREE_PUBLIC (fndecl))
+    return true;
+  return false;
+}
+
+/* Determine if the function identified by FNDECL is one with
+   special properties we wish to know about.  Modify FLAGS accordingly.
+
+   For example, if the function might return more than one time (setjmp), then
+   set ECF_RETURNS_TWICE.
+
+   Set ECF_MAY_BE_ALLOCA for any memory allocation function that might allocate
+   space from the stack such as alloca.  */
+
+static int
+special_function_p (const_tree fndecl, int flags)
+{
+  tree name_decl = DECL_NAME (fndecl);
+
+  if (maybe_special_function_p (fndecl)
+      && IDENTIFIER_LENGTH (name_decl) <= 11)
     {
       const char *name = IDENTIFIER_POINTER (name_decl);
       const char *tname = name;
diff --git a/gcc/tree.h b/gcc/tree.h
index 93422206b63..b7db69267c2 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5611,6 +5611,8 @@ builtin_decl_declared_p (enum built_in_function fncode)
 	  && builtin_info[uns_fncode].declared_p);
 }
 
+extern bool maybe_special_function_p (const_tree fndecl);
+
 /* Return true if T (assumed to be a DECL) is a global variable.
    A variable is considered global if its storage is not automatic.  */
 
-- 
2.21.0

