r364880 - [analyzer] exploded-graph-rewriter: Add support for objects under construction.

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 1 19:17:51 PDT 2019


Author: dergachev
Date: Mon Jul  1 19:17:50 2019
New Revision: 364880

URL: http://llvm.org/viewvc/llvm-project?rev=364880&view=rev
Log:
[analyzer] exploded-graph-rewriter: Add support for objects under construction.

This trait is Environment-like, so there was a chance to re-use a lot of code.

Differential Revision: https://reviews.llvm.org/D64047

Added:
    cfe/trunk/test/Analysis/exploded-graph-rewriter/initializers_under_construction.cpp
    cfe/trunk/test/Analysis/exploded-graph-rewriter/objects_under_construction.cpp
Modified:
    cfe/trunk/test/Analysis/exploded-graph-rewriter/constraints.dot
    cfe/trunk/test/Analysis/exploded-graph-rewriter/constraints_diff.dot
    cfe/trunk/test/Analysis/exploded-graph-rewriter/environment.dot
    cfe/trunk/test/Analysis/exploded-graph-rewriter/environment_diff.dot
    cfe/trunk/test/Analysis/exploded-graph-rewriter/store.dot
    cfe/trunk/test/Analysis/exploded-graph-rewriter/store_diff.dot
    cfe/trunk/utils/analyzer/exploded-graph-rewriter.py

Modified: cfe/trunk/test/Analysis/exploded-graph-rewriter/constraints.dot
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/constraints.dot?rev=364880&r1=364879&r2=364880&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/constraints.dot (original)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/constraints.dot Mon Jul  1 19:17:50 2019
@@ -20,6 +20,7 @@ Node0x1 [shape=record,label=
         "store": null,
         "environment": null,
         "dynamic_types": null,
+        "constructing_objects": null,
         "constraints": [
           { "symbol": "reg_$0<x>", "range": "{ [0, 0] }" }
         ]

Modified: cfe/trunk/test/Analysis/exploded-graph-rewriter/constraints_diff.dot
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/constraints_diff.dot?rev=364880&r1=364879&r2=364880&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/constraints_diff.dot (original)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/constraints_diff.dot Mon Jul  1 19:17:50 2019
@@ -13,6 +13,7 @@ Node0x1 [shape=record,label=
         "store": null,
         "environment": null,
         "dynamic_types": null,
+        "constructing_objects": null,
         "constraints": [
           { "symbol": "reg_$0<x>", "range": "{ [0, 10] }" }
         ]
@@ -43,6 +44,7 @@ Node0x3 [shape=record,label=
         "store": null,
         "environment": null,
         "dynamic_types": null,
+        "constructing_objects": null,
         "constraints": [
           { "symbol": "reg_$0<x>", "range": "{ [0, 5] }" }
         ]
@@ -62,7 +64,8 @@ Node0x5 [shape=record,label=
         "store": null,
         "environment": null,
         "constraints": null,
-        "dynamic_types": null
+        "dynamic_types": null,
+        "constructing_objects": null
       }
     }
 \l}"];

Modified: cfe/trunk/test/Analysis/exploded-graph-rewriter/environment.dot
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/environment.dot?rev=364880&r1=364879&r2=364880&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/environment.dot (original)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/environment.dot Mon Jul  1 19:17:50 2019
@@ -35,6 +35,7 @@ Node0x1 [shape=record,label=
         "store": null,
         "constraints": null,
         "dynamic_types": null,
+        "constructing_objects": null,
         "environment": {
           "pointer": "0x2",
           "items": [

Modified: cfe/trunk/test/Analysis/exploded-graph-rewriter/environment_diff.dot
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/environment_diff.dot?rev=364880&r1=364879&r2=364880&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/environment_diff.dot (original)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/environment_diff.dot Mon Jul  1 19:17:50 2019
@@ -14,6 +14,7 @@ Node0x1 [shape=record,label=
         "store": null,
         "constraints": null,
         "dynamic_types": null,
+        "constructing_objects": null,
         "environment": {
           "pointer": "0x2",
           "items": [
@@ -61,6 +62,7 @@ Node0x6 [shape=record,label=
         "store": null,
         "constraints": null,
         "dynamic_types": null,
+        "constructing_objects": null,
         "environment": {
           "pointer": "0x2",
           "items": [
@@ -102,6 +104,7 @@ Node0x9 [shape=record,label=
         "store": null,
         "constraints": null,
         "dynamic_types": null,
+        "constructing_objects": null,
         "environment": {
           "pointer": "0x2",
           "items": [

Added: cfe/trunk/test/Analysis/exploded-graph-rewriter/initializers_under_construction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/initializers_under_construction.cpp?rev=364880&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/initializers_under_construction.cpp (added)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/initializers_under_construction.cpp Mon Jul  1 19:17:50 2019
@@ -0,0 +1,25 @@
+// FIXME: Figure out how to use %clang_analyze_cc1 with our lit.local.cfg.
+// RUN: %clang_cc1 -analyze -triple x86_64-unknown-linux-gnu \
+// RUN:                     -analyzer-checker=core \
+// RUN:                     -analyzer-dump-egraph=%t.dot %s
+// RUN: %exploded_graph_rewriter %t.dot | FileCheck %s
+// REQUIRES: asserts
+
+// FIXME: Substitution doesn't seem to work on Windows.
+// UNSUPPORTED: system-windows
+
+struct A {
+  A() {}
+};
+
+struct B {
+  A a;
+  B() : a() {}
+};
+
+void test() {
+  // CHECK: (construct into member variable)
+  // CHECK-SAME: <td align="left">a</td>
+  // CHECK-SAME: <td align="left">&b->a</td>
+  B b;
+}

Added: cfe/trunk/test/Analysis/exploded-graph-rewriter/objects_under_construction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/objects_under_construction.cpp?rev=364880&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/objects_under_construction.cpp (added)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/objects_under_construction.cpp Mon Jul  1 19:17:50 2019
@@ -0,0 +1,48 @@
+// FIXME: Figure out how to use %clang_analyze_cc1 with our lit.local.cfg.
+// RUN: %clang_cc1 -analyze -triple x86_64-unknown-linux-gnu \
+// RUN:                     -analyzer-checker=core \
+// RUN:                     -analyzer-dump-egraph=%t.dot %s
+// RUN: %exploded_graph_rewriter %t.dot | FileCheck %s
+// REQUIRES: asserts
+
+// FIXME: Substitution doesn't seem to work on Windows.
+// UNSUPPORTED: system-windows
+
+struct S {
+  S() {}
+};
+
+void test() {
+  // CHECK: Objects Under Construction:
+  // CHECK-SAME: <tr>
+  // CHECK-SAME:   <td align="left"><b>#0 Call</b></td>
+  // CHECK-SAME:   <td align="left" colspan="2">
+  // CHECK-SAME:     <font color="grey60">test </font>
+  // CHECK-SAME:   </td>
+  // CHECK-SAME: </tr>
+  // CHECK-SAME: <tr>
+  // CHECK-SAME:   <td align="left"><i>S{{[0-9]*}}</i></td>
+  // CHECK-SAME:   <td align="left"><font color="darkgreen"><i>
+  // CHECK-SAME:     (materialize temporary)
+  // CHECK-SAME:   </i></font></td>
+  // CHECK-SAME:   <td align="left">S()</td>
+  // CHECK-SAME:   <td align="left">&s</td>
+  // CHECK-SAME: </tr>
+  // CHECK-SAME: <tr>
+  // CHECK-SAME:   <td align="left"><i>S{{[0-9]*}}</i></td>
+  // CHECK-SAME:   <td align="left"><font color="darkgreen"><i>
+  // CHECK-SAME:     (elide constructor)
+  // CHECK-SAME:   </i></font></td>
+  // CHECK-SAME:   <td align="left">S()</td>
+  // CHECK-SAME:   <td align="left">&s</td>
+  // CHECK-SAME: </tr>
+  // CHECK-SAME: <tr>
+  // CHECK-SAME:   <td align="left"><i>S{{[0-9]*}}</i></td>
+  // CHECK-SAME:   <td align="left"><font color="darkgreen"><i>
+  // CHECK-SAME:     (construct into local variable)
+  // CHECK-SAME:   </i></font></td>
+  // CHECK-SAME:   <td align="left">S s = S();</td>
+  // CHECK-SAME:   <td align="left">&s</td>
+  // CHECK-SAME: </tr>
+  S s = S();
+}

Modified: cfe/trunk/test/Analysis/exploded-graph-rewriter/store.dot
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/store.dot?rev=364880&r1=364879&r2=364880&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/store.dot (original)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/store.dot Mon Jul  1 19:17:50 2019
@@ -30,6 +30,7 @@ Node0x1 [shape=record,label=
         "environment": null,
         "constraints": null,
         "dynamic_types": null,
+        "constructing_objects": null,
         "store": {
           "pointer": "0x2",
           "items": [

Modified: cfe/trunk/test/Analysis/exploded-graph-rewriter/store_diff.dot
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/exploded-graph-rewriter/store_diff.dot?rev=364880&r1=364879&r2=364880&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/exploded-graph-rewriter/store_diff.dot (original)
+++ cfe/trunk/test/Analysis/exploded-graph-rewriter/store_diff.dot Mon Jul  1 19:17:50 2019
@@ -13,6 +13,7 @@ Node0x1 [shape=record,label=
         "environment": null,
         "constraints": null,
         "dynamic_types": null,
+        "constructing_objects": null,
         "store": {
           "pointer": "0x2",
           "items": [
@@ -59,6 +60,7 @@ Node0x4 [shape=record,label=
         "environment": null,
         "constraints": null,
         "dynamic_types": null,
+        "constructing_objects": null,
         "store": {
           "pointer": "0x5",
           "items": [

Modified: cfe/trunk/utils/analyzer/exploded-graph-rewriter.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/analyzer/exploded-graph-rewriter.py?rev=364880&r1=364879&r2=364880&view=diff
==============================================================================
--- cfe/trunk/utils/analyzer/exploded-graph-rewriter.py (original)
+++ cfe/trunk/utils/analyzer/exploded-graph-rewriter.py Mon Jul  1 19:17:50 2019
@@ -71,8 +71,11 @@ class ProgramPoint(object):
 class EnvironmentBindingKey(object):
     def __init__(self, json_ek):
         super(EnvironmentBindingKey, self).__init__()
-        self.stmt_id = json_ek['stmt_id']
+        # CXXCtorInitializer is not a Stmt!
+        self.stmt_id = json_ek['stmt_id'] if 'stmt_id' in json_ek \
+            else json_ek['init_id']
         self.pretty = json_ek['pretty']
+        self.kind = json_ek['kind'] if 'kind' in json_ek else None
 
     def _key(self):
         return self.stmt_id
@@ -122,12 +125,12 @@ class EnvironmentFrame(object):
         return len(removed) != 0 or len(added) != 0
 
 
-# A deserialized Environment.
-class Environment(object):
+# A deserialized Environment. This class can also hold other entities that
+# are similar to Environment, such as Objects Under Construction.
+class GenericEnvironment(object):
     def __init__(self, json_e):
-        super(Environment, self).__init__()
-        self.ptr = json_e['pointer']
-        self.frames = [EnvironmentFrame(f) for f in json_e['items']]
+        super(GenericEnvironment, self).__init__()
+        self.frames = [EnvironmentFrame(f) for f in json_e]
 
     def diff_frames(self, prev):
         # TODO: It's difficult to display a good diff when frame numbers shift.
@@ -214,13 +217,18 @@ class ProgramState(object):
         logging.debug('Adding ProgramState ' + str(state_id))
 
         self.state_id = state_id
+
         self.store = Store(json_ps['store']) \
             if json_ps['store'] is not None else None
-        self.environment = Environment(json_ps['environment']) \
+
+        self.environment = \
+            GenericEnvironment(json_ps['environment']['items']) \
             if json_ps['environment'] is not None else None
+
         self.constraints = GenericMap([
             (c['symbol'], c['range']) for c in json_ps['constraints']
         ]) if json_ps['constraints'] is not None else None
+
         self.dynamic_types = GenericMap([
                 (t['region'], '%s%s' % (t['dyn_type'],
                                         ' (or a sub-class)'
@@ -228,7 +236,10 @@ class ProgramState(object):
                 for t in json_ps['dynamic_types']]) \
             if json_ps['dynamic_types'] is not None else None
 
-        # TODO: Objects under construction.
+        self.constructing_objects = \
+            GenericEnvironment(json_ps['constructing_objects']) \
+            if json_ps['constructing_objects'] is not None else None
+
         # TODO: Checker messages.
 
 
@@ -416,10 +427,15 @@ class DotDumpVisitor(object):
         def dump_binding(f, b, is_added=None):
             self._dump('<tr><td>%s</td>'
                        '<td align="left"><i>S%s</i></td>'
+                       '%s'
                        '<td align="left">%s</td>'
                        '<td align="left">%s</td></tr>'
                        % (self._diff_plus_minus(is_added),
-                          b.stmt_id, b.pretty, f.bindings[b]))
+                          b.stmt_id,
+                          '<td align="left"><font color="darkgreen"><i>'
+                          '(%s)</i></font></td>' % b.kind
+                          if b.kind is not None else '',
+                          b.pretty, f.bindings[b]))
 
         frames_updated = e.diff_frames(prev_e) if prev_e is not None else None
         if frames_updated:
@@ -440,20 +456,25 @@ class DotDumpVisitor(object):
 
         self._dump('</table>')
 
-    def visit_environment_in_state(self, s, prev_s=None):
-        self._dump('<hr /><tr><td align="left"><b>Environment: </b>')
-        if s.environment is None:
+    def visit_environment_in_state(self, selector, title, s, prev_s=None):
+        e = getattr(s, selector)
+        prev_e = getattr(prev_s, selector) if prev_s is not None else None
+        if e is None and prev_e is None:
+            return
+
+        self._dump('<hr /><tr><td align="left"><b>%s: </b>' % title)
+        if e is None:
             self._dump('<i> Nothing!</i>')
         else:
-            if prev_s is not None and prev_s.environment is not None:
-                if s.environment.is_different(prev_s.environment):
+            if prev_e is not None:
+                if e.is_different(prev_e):
                     self._dump('</td></tr><tr><td align="left">')
-                    self.visit_environment(s.environment, prev_s.environment)
+                    self.visit_environment(e, prev_e)
                 else:
                     self._dump('<i> No changes!</i>')
             else:
                 self._dump('</td></tr><tr><td align="left">')
-                self.visit_environment(s.environment)
+                self.visit_environment(e)
 
         self._dump('</td></tr>')
 
@@ -496,19 +517,24 @@ class DotDumpVisitor(object):
         self._dump('</table>')
 
     def visit_store_in_state(self, s, prev_s=None):
+        st = s.store
+        prev_st = prev_s.store if prev_s is not None else None
+        if st is None and prev_st is None:
+            return
+
         self._dump('<hr /><tr><td align="left"><b>Store: </b>')
-        if s.store is None:
+        if st is None:
             self._dump('<i> Nothing!</i>')
         else:
-            if prev_s is not None and prev_s.store is not None:
-                if s.store.is_different(prev_s.store):
+            if prev_st is not None:
+                if s.store.is_different(prev_st):
                     self._dump('</td></tr><tr><td align="left">')
-                    self.visit_store(s.store, prev_s.store)
+                    self.visit_store(st, prev_st)
                 else:
                     self._dump('<i> No changes!</i>')
             else:
                 self._dump('</td></tr><tr><td align="left">')
-                self.visit_store(s.store)
+                self.visit_store(st)
         self._dump('</td></tr>')
 
     def visit_generic_map(self, m, prev_m=None):
@@ -559,11 +585,15 @@ class DotDumpVisitor(object):
 
     def visit_state(self, s, prev_s):
         self.visit_store_in_state(s, prev_s)
-        self.visit_environment_in_state(s, prev_s)
+        self.visit_environment_in_state('environment', 'Environment',
+                                        s, prev_s)
         self.visit_generic_map_in_state('constraints', 'Ranges',
                                         s, prev_s)
         self.visit_generic_map_in_state('dynamic_types', 'Dynamic Types',
                                         s, prev_s)
+        self.visit_environment_in_state('constructing_objects',
+                                        'Objects Under Construction',
+                                        s, prev_s)
 
     def visit_node(self, node):
         self._dump('%s [shape=record,label=<<table border="0">'




More information about the cfe-commits mailing list