mirror of
https://github.com/intel/llvm.git
synced 2026-02-04 11:38:04 +08:00
[analyzer] Add more information to the Exploded Graph
This patch dumps every state trait in the egraph. Also the empty state traits are no longer dumped, instead they are treated as null by the egraph rewriter script, which solves reverse compatibility issues. Differential Revision: https://reviews.llvm.org/D131187
This commit is contained in:
@@ -693,7 +693,7 @@ printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State,
|
||||
continue;
|
||||
|
||||
if (!HasItem) {
|
||||
Out << "[" << NL;
|
||||
Out << '[' << NL;
|
||||
HasItem = true;
|
||||
}
|
||||
|
||||
@@ -724,12 +724,11 @@ printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State,
|
||||
|
||||
static void printIndicesOfElementsToConstructJson(
|
||||
raw_ostream &Out, ProgramStateRef State, const char *NL,
|
||||
const LocationContext *LCtx, const ASTContext &Context,
|
||||
unsigned int Space = 0, bool IsDot = false) {
|
||||
const LocationContext *LCtx, unsigned int Space = 0, bool IsDot = false) {
|
||||
using KeyT = std::pair<const Expr *, const LocationContext *>;
|
||||
|
||||
PrintingPolicy PP =
|
||||
LCtx->getAnalysisDeclContext()->getASTContext().getPrintingPolicy();
|
||||
const auto &Context = LCtx->getAnalysisDeclContext()->getASTContext();
|
||||
PrintingPolicy PP = Context.getPrintingPolicy();
|
||||
|
||||
++Space;
|
||||
bool HasItem = false;
|
||||
@@ -742,7 +741,7 @@ static void printIndicesOfElementsToConstructJson(
|
||||
continue;
|
||||
|
||||
if (!HasItem) {
|
||||
Out << "[" << NL;
|
||||
Out << '[' << NL;
|
||||
HasItem = true;
|
||||
}
|
||||
|
||||
@@ -761,17 +760,17 @@ static void printIndicesOfElementsToConstructJson(
|
||||
const Expr *E = Key.first;
|
||||
Out << "\"stmt_id\": " << E->getID(Context);
|
||||
|
||||
// Kind - hack to display the current index
|
||||
Out << ", \"kind\": \"Cur: " << Value - 1 << "\"";
|
||||
// Kind
|
||||
Out << ", \"kind\": null";
|
||||
|
||||
// Pretty-print
|
||||
Out << ", \"pretty\": ";
|
||||
Out << "\"" << E->getStmtClassName() << " "
|
||||
Out << "\"" << E->getStmtClassName() << ' '
|
||||
<< E->getSourceRange().printToString(Context.getSourceManager()) << " '"
|
||||
<< QualType::getAsString(E->getType().split(), PP);
|
||||
Out << "'\"";
|
||||
|
||||
Out << ", \"value\": \"Next: " << Value << "\" }";
|
||||
Out << ", \"value\": \"Current index: " << Value - 1 << "\" }";
|
||||
|
||||
if (Key != LastKey)
|
||||
Out << ',';
|
||||
@@ -785,40 +784,168 @@ static void printIndicesOfElementsToConstructJson(
|
||||
}
|
||||
}
|
||||
|
||||
static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State,
|
||||
const char *NL,
|
||||
const LocationContext *LCtx,
|
||||
unsigned int Space = 0,
|
||||
bool IsDot = false) {
|
||||
using KeyT = std::pair<const CXXConstructExpr *, const LocationContext *>;
|
||||
|
||||
const auto &Context = LCtx->getAnalysisDeclContext()->getASTContext();
|
||||
PrintingPolicy PP = Context.getPrintingPolicy();
|
||||
|
||||
++Space;
|
||||
bool HasItem = false;
|
||||
|
||||
// Store the last key.
|
||||
KeyT LastKey;
|
||||
for (const auto &I : State->get<PendingInitLoop>()) {
|
||||
const KeyT &Key = I.first;
|
||||
if (Key.second != LCtx)
|
||||
continue;
|
||||
|
||||
if (!HasItem) {
|
||||
Out << '[' << NL;
|
||||
HasItem = true;
|
||||
}
|
||||
|
||||
LastKey = Key;
|
||||
}
|
||||
|
||||
for (const auto &I : State->get<PendingInitLoop>()) {
|
||||
const KeyT &Key = I.first;
|
||||
unsigned Value = I.second;
|
||||
if (Key.second != LCtx)
|
||||
continue;
|
||||
|
||||
Indent(Out, Space, IsDot) << "{ ";
|
||||
|
||||
const CXXConstructExpr *E = Key.first;
|
||||
Out << "\"stmt_id\": " << E->getID(Context);
|
||||
|
||||
Out << ", \"kind\": null";
|
||||
Out << ", \"pretty\": ";
|
||||
Out << '\"' << E->getStmtClassName() << ' '
|
||||
<< E->getSourceRange().printToString(Context.getSourceManager()) << " '"
|
||||
<< QualType::getAsString(E->getType().split(), PP);
|
||||
Out << "'\"";
|
||||
|
||||
Out << ", \"value\": \"Flattened size: " << Value << "\"}";
|
||||
|
||||
if (Key != LastKey)
|
||||
Out << ',';
|
||||
Out << NL;
|
||||
}
|
||||
|
||||
if (HasItem)
|
||||
Indent(Out, --Space, IsDot) << ']'; // End of "location_context".
|
||||
else {
|
||||
Out << "null ";
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
printPendingArrayDestructionsJson(raw_ostream &Out, ProgramStateRef State,
|
||||
const char *NL, const LocationContext *LCtx,
|
||||
unsigned int Space = 0, bool IsDot = false) {
|
||||
using KeyT = const LocationContext *;
|
||||
|
||||
++Space;
|
||||
bool HasItem = false;
|
||||
|
||||
// Store the last key.
|
||||
KeyT LastKey = nullptr;
|
||||
for (const auto &I : State->get<PendingArrayDestruction>()) {
|
||||
const KeyT &Key = I.first;
|
||||
if (Key != LCtx)
|
||||
continue;
|
||||
|
||||
if (!HasItem) {
|
||||
Out << '[' << NL;
|
||||
HasItem = true;
|
||||
}
|
||||
|
||||
LastKey = Key;
|
||||
}
|
||||
|
||||
for (const auto &I : State->get<PendingArrayDestruction>()) {
|
||||
const KeyT &Key = I.first;
|
||||
if (Key != LCtx)
|
||||
continue;
|
||||
|
||||
Indent(Out, Space, IsDot) << "{ ";
|
||||
|
||||
Out << "\"stmt_id\": null";
|
||||
Out << ", \"kind\": null";
|
||||
Out << ", \"pretty\": \"Current index: \"";
|
||||
Out << ", \"value\": \"" << I.second << "\" }";
|
||||
|
||||
if (Key != LastKey)
|
||||
Out << ',';
|
||||
Out << NL;
|
||||
}
|
||||
|
||||
if (HasItem)
|
||||
Indent(Out, --Space, IsDot) << ']'; // End of "location_context".
|
||||
else {
|
||||
Out << "null ";
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper function to generalize program state trait printing.
|
||||
/// The function invokes Printer as 'Printer(Out, State, NL, LC, Space, IsDot,
|
||||
/// std::forward<Args>(args)...)'. \n One possible type for Printer is
|
||||
/// 'void()(raw_ostream &, ProgramStateRef, const char *, const LocationContext
|
||||
/// *, unsigned int, bool, ...)' \n \param Trait The state trait to be printed.
|
||||
/// \param Printer A void function that prints Trait.
|
||||
/// \param Args An additional parameter pack that is passed to Print upon
|
||||
/// invocation.
|
||||
template <typename Trait, typename Printer, typename... Args>
|
||||
static void printStateTraitWithLocationContextJson(
|
||||
raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx,
|
||||
const char *NL, unsigned int Space, bool IsDot,
|
||||
const char *jsonPropertyName, Printer printer, Args &&...args) {
|
||||
|
||||
using RequiredType =
|
||||
void (*)(raw_ostream &, ProgramStateRef, const char *,
|
||||
const LocationContext *, unsigned int, bool, Args &&...);
|
||||
|
||||
// Try to do as much compile time checking as possible.
|
||||
// FIXME: check for invocable instead of function?
|
||||
static_assert(std::is_function<std::remove_pointer_t<Printer>>::value,
|
||||
"Printer is not a function!");
|
||||
static_assert(std::is_convertible<Printer, RequiredType>::value,
|
||||
"Printer doesn't have the required type!");
|
||||
|
||||
if (LCtx && !State->get<Trait>().isEmpty()) {
|
||||
Indent(Out, Space, IsDot) << '\"' << jsonPropertyName << "\": ";
|
||||
++Space;
|
||||
Out << '[' << NL;
|
||||
LCtx->printJson(Out, NL, Space, IsDot, [&](const LocationContext *LC) {
|
||||
printer(Out, State, NL, LC, Space, IsDot, std::forward<Args>(args)...);
|
||||
});
|
||||
|
||||
--Space;
|
||||
Indent(Out, Space, IsDot) << "]," << NL; // End of "jsonPropertyName".
|
||||
}
|
||||
}
|
||||
|
||||
void ExprEngine::printJson(raw_ostream &Out, ProgramStateRef State,
|
||||
const LocationContext *LCtx, const char *NL,
|
||||
unsigned int Space, bool IsDot) const {
|
||||
Indent(Out, Space, IsDot) << "\"constructing_objects\": ";
|
||||
|
||||
if (LCtx && !State->get<ObjectsUnderConstruction>().isEmpty()) {
|
||||
++Space;
|
||||
Out << '[' << NL;
|
||||
LCtx->printJson(Out, NL, Space, IsDot, [&](const LocationContext *LC) {
|
||||
printObjectsUnderConstructionJson(Out, State, NL, LC, Space, IsDot);
|
||||
});
|
||||
|
||||
--Space;
|
||||
Indent(Out, Space, IsDot) << "]," << NL; // End of "constructing_objects".
|
||||
} else {
|
||||
Out << "null," << NL;
|
||||
}
|
||||
|
||||
Indent(Out, Space, IsDot) << "\"index_of_element\": ";
|
||||
if (LCtx && !State->get<IndexOfElementToConstruct>().isEmpty()) {
|
||||
++Space;
|
||||
|
||||
auto &Context = getContext();
|
||||
Out << '[' << NL;
|
||||
LCtx->printJson(Out, NL, Space, IsDot, [&](const LocationContext *LC) {
|
||||
printIndicesOfElementsToConstructJson(Out, State, NL, LC, Context, Space,
|
||||
IsDot);
|
||||
});
|
||||
|
||||
--Space;
|
||||
Indent(Out, Space, IsDot) << "]," << NL; // End of "index_of_element".
|
||||
} else {
|
||||
Out << "null," << NL;
|
||||
}
|
||||
printStateTraitWithLocationContextJson<ObjectsUnderConstruction>(
|
||||
Out, State, LCtx, NL, Space, IsDot, "constructing_objects",
|
||||
printObjectsUnderConstructionJson);
|
||||
printStateTraitWithLocationContextJson<IndexOfElementToConstruct>(
|
||||
Out, State, LCtx, NL, Space, IsDot, "index_of_element",
|
||||
printIndicesOfElementsToConstructJson);
|
||||
printStateTraitWithLocationContextJson<PendingInitLoop>(
|
||||
Out, State, LCtx, NL, Space, IsDot, "pending_init_loops",
|
||||
printPendingInitLoopJson);
|
||||
printStateTraitWithLocationContextJson<PendingArrayDestruction>(
|
||||
Out, State, LCtx, NL, Space, IsDot, "pending_destructors",
|
||||
printPendingArrayDestructionsJson);
|
||||
|
||||
getCheckerManager().runCheckersForPrintStateJson(Out, State, NL, Space,
|
||||
IsDot);
|
||||
@@ -3714,7 +3841,7 @@ struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
|
||||
OtherNode->getLocation().printJson(Out, /*NL=*/"\\l");
|
||||
Out << ", \"tag\": ";
|
||||
if (const ProgramPointTag *Tag = OtherNode->getLocation().getTag())
|
||||
Out << '\"' << Tag->getTagDescription() << "\"";
|
||||
Out << '\"' << Tag->getTagDescription() << '\"';
|
||||
else
|
||||
Out << "null";
|
||||
Out << ", \"node_id\": " << OtherNode->getID() <<
|
||||
|
||||
@@ -22,9 +22,7 @@ Node0x1 [shape=record,label=
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"environment": null,
|
||||
"checker_messages": [
|
||||
{ "checker": "alpha.core.FooChecker", "messages": [
|
||||
|
||||
@@ -15,9 +15,7 @@ Node0x1 [shape=record,label=
|
||||
"environment": null,
|
||||
"store": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": [
|
||||
{ "checker": "FooChecker", "messages": [
|
||||
"Foo: Bar"
|
||||
@@ -74,9 +72,7 @@ Node0x4 [shape=record,label=
|
||||
"environment": null,
|
||||
"store": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": [
|
||||
{ "checker": "FooChecker", "messages": [
|
||||
"Foo: Bar",
|
||||
|
||||
@@ -22,9 +22,7 @@ Node0x1 [shape=record,label=
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"environment": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": null,
|
||||
"constraints": [
|
||||
{ "symbol": "reg_$0<x>", "range": "{ [0, 0] }" }
|
||||
|
||||
@@ -15,9 +15,7 @@ Node0x1 [shape=record,label=
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"environment": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": null,
|
||||
"constraints": [
|
||||
{ "symbol": "reg_$0<x>", "range": "{ [0, 10] }" }
|
||||
@@ -54,9 +52,7 @@ Node0x3 [shape=record,label=
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"environment": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": null,
|
||||
"constraints": [
|
||||
{ "symbol": "reg_$0<x>", "range": "{ [0, 5] }" }
|
||||
@@ -83,9 +79,7 @@ Node0x5 [shape=record,label=
|
||||
"store": null,
|
||||
"environment": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,9 +44,7 @@ Node0x1 [shape=record,label=
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": null,
|
||||
"environment": {
|
||||
"pointer": "0x2",
|
||||
|
||||
@@ -16,9 +16,7 @@ Node0x1 [shape=record,label=
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": null,
|
||||
"environment": {
|
||||
"pointer": "0x2",
|
||||
@@ -72,9 +70,7 @@ Node0x6 [shape=record,label=
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": null,
|
||||
"environment": {
|
||||
"pointer": "0x2",
|
||||
@@ -122,9 +118,7 @@ Node0x9 [shape=record,label=
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": null,
|
||||
"environment": {
|
||||
"pointer": "0x2",
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
// RUN: %exploded_graph_rewriter %s | FileCheck %s
|
||||
|
||||
// CHECK: <b>Objects Under Construction: </b>
|
||||
// CHECK-SAME:<table border="0">
|
||||
// CHECK-SAME: <tr>
|
||||
// CHECK-SAME: <td></td>
|
||||
// CHECK-SAME: <td align="left"><b>#0 Call</b></td>
|
||||
// CHECK-SAME: <td align="left" colspan="2">
|
||||
// CHECK-SAME: <font color="gray60">main </font>
|
||||
// CHECK-SAME: </td>
|
||||
// CHECK-SAME: </tr>
|
||||
// CHECK-SAME: <tr>
|
||||
// CHECK-SAME: <td></td>
|
||||
// CHECK-SAME: <td align="left"><i>S870</i></td>
|
||||
// CHECK-SAME: <td align="left">
|
||||
// CHECK-SAME: <font color="darkgreen">
|
||||
// CHECK-SAME: <i>(construct into local variable)</i>
|
||||
// CHECK-SAME: </font>
|
||||
// CHECK-SAME: </td>
|
||||
// CHECK-SAME: <td align="left">S s;</td>
|
||||
// CHECK-SAME: <td align="left">&s</td>
|
||||
// CHECK-SAME: </tr>
|
||||
// CHECK-SAME:</table>
|
||||
Node0x1 [shape=record,label=
|
||||
"{
|
||||
{
|
||||
"state_id": 2,
|
||||
"program_points": [
|
||||
{
|
||||
"kind": "BlockEntrance", "block_id": 1,
|
||||
"terminator": null, "term_kind": null,
|
||||
"tag": null, "node_id": 1,
|
||||
"has_report": 0, "is_sink": 0
|
||||
}
|
||||
],
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"environment": null,
|
||||
"constraints": null,
|
||||
"equivalence_classes": null,
|
||||
"disequality_info": null,
|
||||
"dynamic_types": null,
|
||||
"dynamic_casts": null,
|
||||
"constructing_objects": [
|
||||
{
|
||||
"lctx_id": 1, "location_context": "#0 Call", "calling": "main", "location": null, "items": [
|
||||
{ "stmt_id": 870, "kind": "construct into local variable", "argument_index": null, "pretty": "S s;", "value": "&s" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"checker_messages": null
|
||||
}
|
||||
}
|
||||
\l}"];
|
||||
|
||||
// CHECK: <b>Indices Of Elements Under Construction: </b>
|
||||
// CHECK-SAME:<table border="0">
|
||||
// CHECK-SAME: <tr>
|
||||
// CHECK-SAME: <td></td>
|
||||
// CHECK-SAME: <td align="left"><b>#0 Call</b></td>
|
||||
// CHECK-SAME: <td align="left" colspan="2">
|
||||
// CHECK-SAME: <font color="gray60">main </font>
|
||||
// CHECK-SAME: </td>
|
||||
// CHECK-SAME: </tr>
|
||||
// CHECK-SAME: <tr>
|
||||
// CHECK-SAME: <td></td>
|
||||
// CHECK-SAME: <td align="left"><i>S895</i></td>
|
||||
// CHECK-SAME: <td align="left">
|
||||
// CHECK-SAME: <font color="darkgreen"><i> </i></font>
|
||||
// CHECK-SAME: </td>
|
||||
// CHECK-SAME: <td align="left">
|
||||
// CHECK-SAME: CXXConstructExpr <test.cpp:8:7> 'S[2]'
|
||||
// CHECK-SAME: </td>
|
||||
// CHECK-SAME: <td align="left">Current index: 0</td>
|
||||
// CHECK-SAME: </tr>
|
||||
// CHECK-SAME:</table>
|
||||
Node0x2 [shape=record,label=
|
||||
"{
|
||||
{
|
||||
"state_id": 2,
|
||||
"program_points": [
|
||||
{
|
||||
"kind": "BlockEntrance", "block_id": 1,
|
||||
"terminator": null, "term_kind": null,
|
||||
"tag": null, "node_id": 1,
|
||||
"has_report": 0, "is_sink": 0
|
||||
}
|
||||
],
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"environment": null,
|
||||
"constraints": null,
|
||||
"equivalence_classes": null,
|
||||
"disequality_info": null,
|
||||
"dynamic_types": null,
|
||||
"dynamic_casts": null,
|
||||
"index_of_element": [
|
||||
{
|
||||
"lctx_id": 1,
|
||||
"location_context": "#0 Call",
|
||||
"calling": "main",
|
||||
"location": null,
|
||||
"items": [
|
||||
{
|
||||
"stmt_id": 895,
|
||||
"kind": null,
|
||||
"pretty": "CXXConstructExpr <test.cpp:8:7> 'S[2]'",
|
||||
"value": "Current index: 0"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"checker_messages": null
|
||||
}
|
||||
}
|
||||
\l}"];
|
||||
|
||||
// CHECK: <b>Pending Array Init Loop Expressions: </b>
|
||||
// CHECK-SAME:<table border="0">
|
||||
// CHECK-SAME: <tr>
|
||||
// CHECK-SAME: <td></td>
|
||||
// CHECK-SAME: <td align="left"><b>#0 Call</b></td>
|
||||
// CHECK-SAME: <td align="left" colspan="2">
|
||||
// CHECK-SAME: <font color="gray60">main </font>
|
||||
// CHECK-SAME: </td>
|
||||
// CHECK-SAME: </tr>
|
||||
// CHECK-SAME: <tr>
|
||||
// CHECK-SAME: <td></td>
|
||||
// CHECK-SAME: <td align="left"><i>S1112</i></td>
|
||||
// CHECK-SAME: <td align="left">
|
||||
// CHECK-SAME: <font color="darkgreen"><i> </i></font>
|
||||
// CHECK-SAME: </td>
|
||||
// CHECK-SAME: <td align="left">
|
||||
// CHECK-SAME: CXXConstructExpr <test.cpp:10:6> 'S'
|
||||
// CHECK-SAME: </td>
|
||||
// CHECK-SAME: <td align="left">Flattened size: 2</td>
|
||||
// CHECK-SAME: </tr>
|
||||
// CHECK-SAME:</table>
|
||||
Node0x3 [shape=record,label=
|
||||
"{
|
||||
{
|
||||
"state_id": 2,
|
||||
"program_points": [
|
||||
{
|
||||
"kind": "BlockEntrance", "block_id": 1,
|
||||
"terminator": null, "term_kind": null,
|
||||
"tag": null, "node_id": 1,
|
||||
"has_report": 0, "is_sink": 0
|
||||
}
|
||||
],
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"environment": null,
|
||||
"constraints": null,
|
||||
"equivalence_classes": null,
|
||||
"disequality_info": null,
|
||||
"dynamic_types": null,
|
||||
"dynamic_casts": null,
|
||||
"pending_init_loops": [
|
||||
{
|
||||
"lctx_id": 1,
|
||||
"location_context": "#0 Call",
|
||||
"calling": "main",
|
||||
"location": null,
|
||||
"items": [
|
||||
{
|
||||
"stmt_id": 1112,
|
||||
"kind": null,
|
||||
"pretty": "CXXConstructExpr <test.cpp:10:6> 'S'", "value": "Flattened size: 2"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"checker_messages": null
|
||||
}
|
||||
}
|
||||
\l}"];
|
||||
|
||||
// CHECK: <b>Indices of Elements Under Destruction: </b>
|
||||
// CHECK-SAME:<table border="0">
|
||||
// CHECK-SAME: <tr>
|
||||
// CHECK-SAME: <td></td>
|
||||
// CHECK-SAME: <td align="left"><b>#0 Call</b></td>
|
||||
// CHECK-SAME: <td align="left" colspan="2">
|
||||
// CHECK-SAME: <font color="gray60">main </font>
|
||||
// CHECK-SAME: </td>
|
||||
// CHECK-SAME: </tr>
|
||||
// CHECK-SAME: <tr>
|
||||
// CHECK-SAME: <td></td>
|
||||
// CHECK-SAME: <td align="left"><i>SNone</i></td>
|
||||
// CHECK-SAME: <td align="left">
|
||||
// CHECK-SAME: <font color="darkgreen"><i> </i></font>
|
||||
// CHECK-SAME: </td>
|
||||
// CHECK-SAME: <td align="left">Current index: </td>
|
||||
// CHECK-SAME: <td align="left">1</td>
|
||||
// CHECK-SAME: </tr>
|
||||
// CHECK-SAME:</table>
|
||||
Node0x4 [shape=record,label=
|
||||
"{
|
||||
{
|
||||
"state_id": 2,
|
||||
"program_points": [
|
||||
{
|
||||
"kind": "BlockEntrance", "block_id": 1,
|
||||
"terminator": null, "term_kind": null,
|
||||
"tag": null, "node_id": 1,
|
||||
"has_report": 0, "is_sink": 0
|
||||
}
|
||||
],
|
||||
"program_state": {
|
||||
"store": null,
|
||||
"environment": null,
|
||||
"constraints": null,
|
||||
"equivalence_classes": null,
|
||||
"disequality_info": null,
|
||||
"dynamic_types": null,
|
||||
"dynamic_casts": null,
|
||||
"pending_destructors": [
|
||||
{
|
||||
"lctx_id": 1,
|
||||
"location_context": "#0 Call",
|
||||
"calling": "main",
|
||||
"location": null,
|
||||
"items": [
|
||||
{
|
||||
"stmt_id": null,
|
||||
"kind": null,
|
||||
"pretty": "Current index: ",
|
||||
"value": "1"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"checker_messages": null
|
||||
}
|
||||
}
|
||||
\l}"];
|
||||
@@ -32,9 +32,7 @@ Node0x1 [shape=record,label=
|
||||
"program_state": {
|
||||
"environment": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": null,
|
||||
"store": {
|
||||
"pointer": "0x2",
|
||||
|
||||
@@ -18,9 +18,7 @@ Node0x1 [shape=record,label=
|
||||
"program_state": {
|
||||
"environment": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": null,
|
||||
"store": {
|
||||
"pointer": "0x2",
|
||||
@@ -73,9 +71,7 @@ Node0x4 [shape=record,label=
|
||||
"program_state": {
|
||||
"environment": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": null,
|
||||
"store": {
|
||||
"pointer": "0x5",
|
||||
|
||||
@@ -22,9 +22,7 @@ Node0x1 [shape=record,label=
|
||||
"program_state": {
|
||||
"environment": null,
|
||||
"constraints": null,
|
||||
"dynamic_types": null,
|
||||
"constructing_objects": null,
|
||||
"index_of_element": null,
|
||||
"dynamic_types": null,
|
||||
"checker_messages": [
|
||||
{ "checker": "foo", "messages": ["bar"] }
|
||||
],
|
||||
|
||||
@@ -46,8 +46,6 @@ void foo(int x) {
|
||||
// CHECK-NEXT: "disequality_info": null,
|
||||
// CHECK-NEXT: "dynamic_types": null,
|
||||
// CHECK-NEXT: "dynamic_casts": null,
|
||||
// CHECK-NEXT: "constructing_objects": null,
|
||||
// CHECK-NEXT: "index_of_element": null,
|
||||
// CHECK-NEXT: "checker_messages": null
|
||||
// CHECK-NEXT: }
|
||||
|
||||
|
||||
@@ -261,48 +261,74 @@ class CheckerMessages:
|
||||
class ProgramState:
|
||||
def __init__(self, state_id, json_ps):
|
||||
logging.debug('Adding ProgramState ' + str(state_id))
|
||||
|
||||
store_key = 'store'
|
||||
env_key = 'environment'
|
||||
constraints_key = 'constraints'
|
||||
dyn_ty_key = 'dynamic_types'
|
||||
ctor_key = 'constructing_objects'
|
||||
ind_key = 'index_of_element'
|
||||
init_loop_key = 'pending_init_loops'
|
||||
dtor_key = 'pending_destructors'
|
||||
msg_key = 'checker_messages'
|
||||
|
||||
if json_ps is None:
|
||||
json_ps = {
|
||||
'store': None,
|
||||
'environment': None,
|
||||
'constraints': None,
|
||||
'dynamic_types': None,
|
||||
'constructing_objects': None,
|
||||
'index_of_element': None,
|
||||
'checker_messages': None
|
||||
store_key: None,
|
||||
env_key: None,
|
||||
constraints_key: None,
|
||||
dyn_ty_key: None,
|
||||
ctor_key: None,
|
||||
ind_key: None,
|
||||
init_loop_key: None,
|
||||
dtor_key: None,
|
||||
msg_key: None
|
||||
}
|
||||
|
||||
self.state_id = state_id
|
||||
|
||||
self.store = Store(json_ps['store']) \
|
||||
if json_ps['store'] is not None else None
|
||||
self.store = Store(json_ps[store_key]) \
|
||||
if json_ps[store_key] is not None else None
|
||||
|
||||
self.environment = \
|
||||
GenericEnvironment(json_ps['environment']['items']) \
|
||||
if json_ps['environment'] is not None else None
|
||||
GenericEnvironment(json_ps[env_key]['items']) \
|
||||
if json_ps[env_key] 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
|
||||
(c['symbol'], c['range']) for c in json_ps[constraints_key]
|
||||
]) if json_ps[constraints_key] is not None else None
|
||||
|
||||
self.dynamic_types = GenericMap([
|
||||
(t['region'], '%s%s' % (t['dyn_type'],
|
||||
' (or a sub-class)'
|
||||
if t['sub_classable'] else ''))
|
||||
for t in json_ps['dynamic_types']]) \
|
||||
if json_ps['dynamic_types'] is not None else None
|
||||
for t in json_ps[dyn_ty_key]]) \
|
||||
if json_ps[dyn_ty_key] is not None else None
|
||||
|
||||
self.checker_messages = CheckerMessages(json_ps[msg_key]) \
|
||||
if json_ps[msg_key] is not None else None
|
||||
|
||||
# State traits
|
||||
#
|
||||
# For traits we always check if a key exists because if a trait
|
||||
# has no imformation, nothing will be printed in the .dot file
|
||||
# we parse.
|
||||
|
||||
self.constructing_objects = \
|
||||
GenericEnvironment(json_ps['constructing_objects']) \
|
||||
if json_ps['constructing_objects'] is not None else None
|
||||
GenericEnvironment(json_ps[ctor_key]) \
|
||||
if ctor_key in json_ps and json_ps[ctor_key] is not None else None
|
||||
|
||||
self.index_of_element = \
|
||||
GenericEnvironment(json_ps['index_of_element']) \
|
||||
if json_ps['index_of_element'] is not None else None
|
||||
GenericEnvironment(json_ps[ind_key]) \
|
||||
if ind_key in json_ps and json_ps[ind_key] is not None else None
|
||||
|
||||
self.pending_init_loops = \
|
||||
GenericEnvironment(json_ps[init_loop_key]) \
|
||||
if init_loop_key in json_ps and json_ps[init_loop_key] is not None else None
|
||||
|
||||
self.checker_messages = CheckerMessages(json_ps['checker_messages']) \
|
||||
if json_ps['checker_messages'] is not None else None
|
||||
self.pending_destructors = \
|
||||
GenericEnvironment(json_ps[dtor_key]) \
|
||||
if dtor_key in json_ps and json_ps[dtor_key] is not None else None
|
||||
|
||||
|
||||
# A deserialized exploded graph node. Has a default constructor because it
|
||||
@@ -801,6 +827,12 @@ class DotDumpVisitor:
|
||||
self.visit_environment_in_state('index_of_element',
|
||||
'Indices Of Elements Under Construction',
|
||||
s, prev_s)
|
||||
self.visit_environment_in_state('pending_init_loops',
|
||||
'Pending Array Init Loop Expressions',
|
||||
s, prev_s)
|
||||
self.visit_environment_in_state('pending_destructors',
|
||||
'Indices of Elements Under Destruction',
|
||||
s, prev_s)
|
||||
self.visit_checker_messages_in_state(s, prev_s)
|
||||
|
||||
def visit_node(self, node):
|
||||
|
||||
Reference in New Issue
Block a user