[PATCH v2 1/2] analyzer: add helper methods for dynamic_cast support

Egas Ribeiro <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.