summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp55
-rw-r--r--clang/test/Analysis/iterator-modelling.cpp29
2 files changed, 84 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp
index 9730de0e4cd..0a7015e85e9 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 92427528e7c..2cd7b349be8 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@-1{{FALSE}} expected-warning@-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: ]}
+}
OpenPOWER on IntegriCloud