continue;
if (!HasItem) {
- Out << "[" << NL;
+ Out << '[' << NL;
HasItem = true;
}
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;
continue;
if (!HasItem) {
- Out << "[" << NL;
+ Out << '[' << NL;
HasItem = true;
}
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 << ',';
}
}
-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\": ";
+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 *>;
- 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);
- });
+ const auto &Context = LCtx->getAnalysisDeclContext()->getASTContext();
+ PrintingPolicy PP = Context.getPrintingPolicy();
- --Space;
- Indent(Out, Space, IsDot) << "]," << NL; // End of "constructing_objects".
- } else {
- Out << "null," << NL;
+ ++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;
}
- Indent(Out, Space, IsDot) << "\"index_of_element\": ";
- if (LCtx && !State->get<IndexOfElementToConstruct>().isEmpty()) {
- ++Space;
+ 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;
+ }
- auto &Context = getContext();
+ 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) {
- printIndicesOfElementsToConstructJson(Out, State, NL, LC, Context, Space,
- IsDot);
+ printer(Out, State, NL, LC, Space, IsDot, std::forward<Args>(args)...);
});
--Space;
- Indent(Out, Space, IsDot) << "]," << NL; // End of "index_of_element".
- } else {
- Out << "null," << NL;
+ 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 {
+
+ 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);
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() <<
"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": [
"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"
"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",
"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] }" }
"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] }" }
"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] }" }
"store": null,
"environment": null,
"constraints": null,
- "dynamic_types": null,
- "constructing_objects": null,
- "index_of_element": null,
+ "dynamic_types": null,
"checker_messages": null
}
}
"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",
"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",
"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",
"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",
--- /dev/null
+// 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}"];
"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",
"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",
"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",
"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"] }
],
// 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: }
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
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):