Add helper methods needed for adding a new known_function for
__dynamic_cast and recognize functions in the __cxxabiv1 namespace.

gcc/analyzer/ChangeLog:

        * analyzer.cc (is_fndecl_in_toplevel_namespace_p): New function,
        factored out of...
        (is_std_function_p): ...here.  Call it.
        (is_cxxabi_function_p): New function.
        * common.h (is_cxxabi_function_p): New decl.
        * known-function-manager.cc (known_function_manager::get_match):
        Also match functions declared in namespace __cxxabiv1.

Signed-off-by: Egas Ribeiro <[email protected]>
---
 gcc/analyzer/analyzer.cc               | 26 +++++++++++++++++++++++---
 gcc/analyzer/common.h                  |  1 +
 gcc/analyzer/known-function-manager.cc | 10 +++++++---
 3 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/gcc/analyzer/analyzer.cc b/gcc/analyzer/analyzer.cc
index f58cfc93fc7..1425e913379 100644
--- a/gcc/analyzer/analyzer.cc
+++ b/gcc/analyzer/analyzer.cc
@@ -349,27 +349,47 @@ is_named_call_p (const_tree fndecl, const char *funcname)
   return 0 == strcmp (tname, funcname);
 }
 
-/* Return true if FNDECL is within the namespace "std".
+/* Return true if FNDECL is declared directly within a top-level
+   namespace named NS_NAME (e.g. "std" or "__cxxabiv1").
    Compare with cp/typeck.cc: decl_in_std_namespace_p, but this doesn't
    rely on being the C++ FE (or handle inline namespaces inside of std).  */
 
 bool
-is_std_function_p (const_tree fndecl)
+is_fndecl_in_toplevel_namespace_p (const_tree fndecl, const char *ns_name)
 {
   tree name_decl = DECL_NAME (fndecl);
   if (!name_decl)
     return false;
+
   if (!DECL_CONTEXT (fndecl))
     return false;
   if (TREE_CODE (DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
     return false;
   tree ns = DECL_CONTEXT (fndecl);
+  /* Require the namespace itself to be at top level.  */
   if (!(DECL_CONTEXT (ns) == NULL_TREE
        || TREE_CODE (DECL_CONTEXT (ns)) == TRANSLATION_UNIT_DECL))
     return false;
   if (!DECL_NAME (ns))
     return false;
-  return id_equal ("std", DECL_NAME (ns));
+
+  return id_equal (ns_name, DECL_NAME (ns));
+}
+
+/* Return true if FNDECL is within the namespace "std".  */
+
+bool
+is_std_function_p (const_tree fndecl)
+{
+  return is_fndecl_in_toplevel_namespace_p (fndecl, "std");
+}
+
+/* Return true if FNDECL is within the namespace "__cxxabiv1".  */
+
+bool
+is_cxxabi_function_p (const_tree fndecl)
+{
+  return is_fndecl_in_toplevel_namespace_p (fndecl, "__cxxabiv1");
 }
 
 /* Like is_named_call_p, but look for std::FUNCNAME.  */
diff --git a/gcc/analyzer/common.h b/gcc/analyzer/common.h
index 8ce1475bc5e..05452ef02ed 100644
--- a/gcc/analyzer/common.h
+++ b/gcc/analyzer/common.h
@@ -544,6 +544,7 @@ extern bool is_named_call_p (const_tree fndecl, const char 
*funcname);
 extern bool is_named_call_p (const_tree fndecl, const char *funcname,
                             const gcall &call, unsigned int num_args);
 extern bool is_std_function_p (const_tree fndecl);
+extern bool is_cxxabi_function_p (const_tree fndecl);
 extern bool is_std_named_call_p (const_tree fndecl, const char *funcname);
 extern bool is_std_named_call_p (const_tree fndecl, const char *funcname,
                                 const gcall &call, unsigned int num_args);
diff --git a/gcc/analyzer/known-function-manager.cc 
b/gcc/analyzer/known-function-manager.cc
index fcc9a618d15..679fe1a7015 100644
--- a/gcc/analyzer/known-function-manager.cc
+++ b/gcc/analyzer/known-function-manager.cc
@@ -120,9 +120,13 @@ known_function_manager::get_match (tree fndecl, const 
call_details &cd) const
       return nullptr;
     }
 
-  if (DECL_CONTEXT (fndecl)
-      && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
-    return nullptr;
+  /* Only match functions declared at global scope, or within namespace
+     __cxxabiv1 (e.g. __dynamic_cast).  */
+  if (!is_cxxabi_function_p (fndecl))
+    if (DECL_CONTEXT (fndecl)
+       && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
+      return nullptr;
+
   if (tree identifier = DECL_NAME (fndecl))
     if (const known_function *candidate = get_by_identifier (identifier))
       if (candidate->matches_call_types_p (cd))
-- 
2.54.0

Reply via email to