[clang] 6e9c589 - [Analyzer] Iterator Modeling: Print Container Data and Iterator Positions when printing the Program State

Adam Balogh via cfe-commits cfe-commits at lists.llvm.org
Wed Dec 11 05:18:35 PST 2019


Author: Adam Balogh
Date: 2019-12-11T14:20:17+01:00
New Revision: 6e9c58946eeeebfe8eed7308a3b57611e225ad67

URL: https://github.com/llvm/llvm-project/commit/6e9c58946eeeebfe8eed7308a3b57611e225ad67
DIFF: https://github.com/llvm/llvm-project/commit/6e9c58946eeeebfe8eed7308a3b57611e225ad67.diff

LOG: [Analyzer] Iterator Modeling: Print Container Data and Iterator Positions when printing the Program State

Debugging the Iterator Modeling checker or any of the iterator checkers
is difficult without being able to see the relations between the
iterator variables and their abstract positions, as well as the abstract
symbols denoting the begin and the end of the container.

This patch adds the checker-specific part of the Program State printing
to the Iterator Modeling checker.

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
    clang/test/Analysis/iterator-modelling.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
index 9730de0e4cd3..0a7015e85e93 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
@@ -121,6 +121,9 @@ class IteratorModeling
   void handleEraseAfter(CheckerContext &C, const SVal &Iter) const;
   void handleEraseAfter(CheckerContext &C, const SVal &Iter1,
                         const SVal &Iter2) const;
+  void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
+                  const char *Sep) const override;
+
 public:
   IteratorModeling() {}
 
@@ -1080,6 +1083,58 @@ void IteratorModeling::handleEraseAfter(CheckerContext &C, const SVal &Iter1,
   C.addTransition(State);
 }
 
+void IteratorModeling::printState(raw_ostream &Out, ProgramStateRef State,
+                                  const char *NL, const char *Sep) const {
+
+  auto ContMap = State->get<ContainerMap>();
+
+  if (!ContMap.isEmpty()) {
+    Out << Sep << "Container Data :" << NL;
+    for (const auto Cont : ContMap) {
+      Cont.first->dumpToStream(Out);
+      Out << " : [ ";
+      const auto CData = Cont.second;
+      if (CData.getBegin())
+        CData.getBegin()->dumpToStream(Out);
+      else
+        Out << "<Unknown>";
+      Out << " .. ";
+      if (CData.getEnd())
+        CData.getEnd()->dumpToStream(Out);
+      else
+        Out << "<Unknown>";
+      Out << " ]" << NL;
+    }
+  }
+
+  auto SymbolMap = State->get<IteratorSymbolMap>();
+  auto RegionMap = State->get<IteratorRegionMap>();
+
+  if (!SymbolMap.isEmpty() || !RegionMap.isEmpty()) {
+    Out << Sep << "Iterator Positions :" << NL;
+    for (const auto Sym : SymbolMap) {
+      Sym.first->dumpToStream(Out);
+      Out << " : ";
+      const auto Pos = Sym.second;
+      Out << (Pos.isValid() ? "Valid" : "Invalid") << " ; Container == ";
+      Pos.getContainer()->dumpToStream(Out);
+      Out<<" ; Offset == ";
+      Pos.getOffset()->dumpToStream(Out);
+    }
+
+    for (const auto Reg : RegionMap) {
+      Reg.first->dumpToStream(Out);
+      Out << " : ";
+      const auto Pos = Reg.second;
+      Out << (Pos.isValid() ? "Valid" : "Invalid") << " ; Container == ";
+      Pos.getContainer()->dumpToStream(Out);
+      Out<<" ; Offset == ";
+      Pos.getOffset()->dumpToStream(Out);
+    }
+  }
+}
+
+
 namespace {
 
 const CXXRecordDecl *getCXXRecordDecl(ProgramStateRef State,

diff  --git a/clang/test/Analysis/iterator-modelling.cpp b/clang/test/Analysis/iterator-modelling.cpp
index 92427528e7c0..2cd7b349be81 100644
--- a/clang/test/Analysis/iterator-modelling.cpp
+++ b/clang/test/Analysis/iterator-modelling.cpp
@@ -1,6 +1,9 @@
 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify
+
 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
 
+// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorModeling,debug.ExprInspection -analyzer-config aggressive-binary-operation-simplification=true %s 2>&1 | FileCheck %s
+
 #include "Inputs/system-header-simulator-cxx.h"
 
 template <typename Container>
@@ -1970,3 +1973,29 @@ void non_std_find(std::vector<int> &V, int e) {
                         clang_analyzer_iterator_position(first)); // expected-warning at -1{{FALSE}} expected-warning at -1 0-1{{TRUE}} FIXME: should only expect FALSE in every case
   }
 }
+
+void clang_analyzer_printState();
+
+void print_state(std::vector<int> &V) {
+  const auto i0 = V.cbegin();
+  clang_analyzer_printState();
+
+// CHECK:      "checker_messages": [
+// CHECK-NEXT:   { "checker": "alpha.cplusplus.IteratorModeling", "messages": [
+// CHECK-NEXT:     "Container Data :",
+// CHECK-NEXT:     "SymRegion{reg_$[[#]]<std::vector<int> & V>} : [ conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]} .. <Unknown> ]",
+// CHECK-NEXT:     "Iterator Positions :",
+// CHECK-NEXT:     "i0 : Valid ; Container == SymRegion{reg_$[[#]]<std::vector<int> & V>} ; Offset == conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]}"
+// CHECK-NEXT:   ]}
+
+  const auto i1 = V.cend();
+  clang_analyzer_printState();
+  
+// CHECK:      "checker_messages": [
+// CHECK-NEXT:   { "checker": "alpha.cplusplus.IteratorModeling", "messages": [
+// CHECK-NEXT:     "Container Data :",
+// CHECK-NEXT:     "SymRegion{reg_$[[#]]<std::vector<int> & V>} : [ conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]} .. conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]} ]",
+// CHECK-NEXT:     "Iterator Positions :",
+// CHECK-NEXT:     "i1 : Valid ; Container == SymRegion{reg_$[[#]]<std::vector<int> & V>} ; Offset == conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]}"
+// CHECK-NEXT:   ]}
+}


        


More information about the cfe-commits mailing list