gcc/analyzer/ChangeLog:
        * analyzer-selftests.cc (run_analyzer_selftests): Call
        analyzer_complexity_cc_tests.
        * analyzer-selftests.h (analyzer_complexity_cc_tests): New decl.
        * complexity.cc: Include "selftest.h".
        (complexity::complexity): New ctor.
        (complexity::from_child_complexities): New.
        (complexity::operator+): New.
        (complexity::operator+=): New.
        (selftest::analyzer_complexity_cc_tests): New.
        * complexity.h (complexity::complexity): New ctor decl.
        (complexity::from_child_complexities): New decl.
        (complexity::operator+): New decl.
        (complexity::operator+=): New decl.

Signed-off-by: David Malcolm <[email protected]>
---
 gcc/analyzer/analyzer-selftests.cc |  1 +
 gcc/analyzer/analyzer-selftests.h  |  1 +
 gcc/analyzer/complexity.cc         | 61 ++++++++++++++++++++++++++++++
 gcc/analyzer/complexity.h          | 25 +++++++++++-
 4 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/gcc/analyzer/analyzer-selftests.cc 
b/gcc/analyzer/analyzer-selftests.cc
index a9dc6d9712d..05a73f291c0 100644
--- a/gcc/analyzer/analyzer-selftests.cc
+++ b/gcc/analyzer/analyzer-selftests.cc
@@ -49,6 +49,7 @@ run_analyzer_selftests ()
 {
 #if ENABLE_ANALYZER
   analyzer_access_diagram_cc_tests ();
+  analyzer_complexity_cc_tests ();
   analyzer_concrete_ranges_cc_tests ();
   analyzer_constraint_manager_cc_tests ();
   analyzer_function_set_cc_tests ();
diff --git a/gcc/analyzer/analyzer-selftests.h 
b/gcc/analyzer/analyzer-selftests.h
index 6976aab2294..7b1342bb5cf 100644
--- a/gcc/analyzer/analyzer-selftests.h
+++ b/gcc/analyzer/analyzer-selftests.h
@@ -34,6 +34,7 @@ extern void run_analyzer_selftests ();
 /* Declarations for specific families of tests (by source file), in
    alphabetical order.  */
 extern void analyzer_access_diagram_cc_tests ();
+extern void analyzer_complexity_cc_tests ();
 extern void analyzer_concrete_ranges_cc_tests ();
 extern void analyzer_constraint_manager_cc_tests ();
 extern void analyzer_function_set_cc_tests ();
diff --git a/gcc/analyzer/complexity.cc b/gcc/analyzer/complexity.cc
index f77b3a1a3f2..a4e2231207d 100644
--- a/gcc/analyzer/complexity.cc
+++ b/gcc/analyzer/complexity.cc
@@ -33,12 +33,23 @@ along with GCC; see the file COPYING3.  If not see
 #include "analyzer/svalue.h"
 #include "analyzer/region.h"
 
+#include "selftest.h"
+
 #if ENABLE_ANALYZER
 
 namespace ana {
 
 /* struct complexity.  */
 
+/* Get complexity for a new node that references NODE
+   (the complexity of NODE, plus one for the new node).  */
+
+complexity::complexity (const symbolic::node &node)
+: m_num_nodes (node.get_complexity ().m_num_nodes + 1),
+  m_max_depth (node.get_complexity ().m_max_depth + 1)
+{
+}
+
 /* Get complexity for a new node that references REG
    (the complexity of REG, plus one for the new node).  */
 
@@ -83,6 +94,56 @@ complexity::from_vec_svalue (const vec<const svalue *> &vec)
   return complexity (num_nodes + 1, max_depth + 1);
 }
 
+/* Get complexity for a new node which has children with overall
+   complexity CHILD_COMPLEXITIES.  */
+
+complexity
+complexity::from_child_complexities (const complexity &child_complexities)
+{
+  /* One extra node for the node itself; one more level of depth.  */
+  return complexity (child_complexities.m_num_nodes + 1,
+                    child_complexities.m_max_depth + 1);
+}
+
+/* The sum of two complexity instances is the sum of their
+   numbers of nodes and the maximum of the maxima of their depths.  */
+
+complexity
+complexity::operator+ (const complexity &other) const
+{
+  return complexity (m_num_nodes + other.m_num_nodes,
+                    std::max (m_max_depth, other.m_max_depth));
+}
+
+complexity &
+complexity::operator+= (const complexity &other)
+{
+  *this = *this + other;
+  return *this;
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+void
+analyzer_complexity_cc_tests ()
+{
+  ASSERT_EQ (complexity (1, 1) + complexity (1, 1),
+            complexity (2, 1));
+
+  ASSERT_EQ (complexity (3, 2) + complexity (3, 1),
+            complexity (6, 2));
+
+  ASSERT_EQ (complexity::from_child_complexities (complexity (3, 2)),
+            complexity (4, 3));
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
+
+
 } // namespace ana
 
 #endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/complexity.h b/gcc/analyzer/complexity.h
index 41a241f4659..398af5d9fac 100644
--- a/gcc/analyzer/complexity.h
+++ b/gcc/analyzer/complexity.h
@@ -33,10 +33,31 @@ struct complexity
   : m_num_nodes (num_nodes), m_max_depth (max_depth)
   {}
 
+  complexity (const symbolic::node &n);
   complexity (const region *reg);
   complexity (const svalue *sval);
-  static complexity from_pair (const complexity &c1, const complexity &c);
-  static complexity from_vec_svalue (const vec<const svalue *> &vec);
+
+  static complexity
+  from_pair (const complexity &c1, const complexity &c);
+
+  static complexity
+  from_vec_svalue (const vec<const svalue *> &vec);
+
+  static complexity
+  from_child_complexities (const complexity &child_complexities);
+
+  bool
+  operator== (const complexity &other) const
+  {
+    return (m_num_nodes == other.m_num_nodes
+           && m_max_depth == other.m_max_depth);
+  }
+
+  complexity
+  operator+ (const complexity &other) const;
+
+  complexity &
+  operator+= (const complexity &other);
 
   /* The total number of nodes in the tree of this
      entity, including the entity itself.  */
-- 
2.56.0

Reply via email to