00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "tree_checker.h"
00039 #include "print_walker.h"
00040
00041 void TreeChecker::setPreDismantled(const char * nodeType, Node * node) {
00042 _preDismantled = true;
00043 if ( _verbose )
00044 cout << nodeType << " node (" << node << ") set the pre-dismantled flag."
00045 << endl;
00046 }
00047
00048 void TreeChecker::setPostDismantled(const char * nodeType, Node * node) {
00049 _postDismantled = true;
00050 if ( _verbose )
00051 cout << nodeType << " node (" << node << ") set the post-dismantled flag."
00052 << endl;
00053 }
00054
00055 void TreeChecker::checkTree (Node * n, const char * type) {
00056 if (_visitedNodes[n]++ > 0) {
00057 cout << "Error: " << type << " node (" << n << ") has been visited "
00058 << _visitedNodes[n] << " times.\n";
00059 print_walker::print(n, cout);
00060 _errorCount++;
00061 }
00062 else if (_verbose)
00063 cout << "Visiting " << type << " node (" << n << ").\n";
00064 }
00065
00066 void TreeChecker::checkField (Node * node, Node * field,
00067 const char * type, const char * fieldName,
00068 bool isError ) {
00069 if (! field) {
00070 if (isError) {
00071 cout << "Error: " << type << " node (" << node
00072 << ") has empty " << fieldName << " field.\n";
00073 _errorCount++;
00074 }
00075 else if (_warning)
00076 cout << type << " node (" << node << ") has empty "
00077 << fieldName << " field.\n";
00078 }
00079 else if (_verbose)
00080 cout << type << " node (" << node << ") has " << fieldName
00081 << " field = " << field << ".\n";
00082 }
00083
00084 void TreeChecker::checkString (Node * node, string & field,
00085 const char * type, const char * fieldName,
00086 bool isError ) {
00087 if (field == "") {
00088 if (isError) {
00089 cout << "Error: " << type << " node (" << node
00090 << ") has empty " << fieldName << " field.\n";
00091 _errorCount++;
00092 }
00093 else if (_warning)
00094 cout << type << " node (" << node << ") has empty "
00095 << fieldName << " field.\n";
00096 }
00097 else if (_verbose)
00098 cout << type << " node (" << node << ") has " << fieldName
00099 << " field = " << field << ".\n";
00100 }
00101
00102 void TreeChecker::checkConstant (Node * node, constant & field,
00103 const char * type, const char * fieldName,
00104 bool isError ) {
00105 if (field.no_val()) {
00106 if (isError) {
00107 cout << "Error: " << type << " node (" << node
00108 << ") has non-constant " << fieldName << " field.\n";
00109 _errorCount++;
00110 }
00111 else
00112 cout << type << " node (" << node << ") has non-constant "
00113 << fieldName << " field.\n";
00114 }
00115 else if (_verbose)
00116 cout << type << " node (" << node << ") has " << fieldName
00117 << " field = " << field.to_string() << ".\n";
00118 }
00119
00120 template <class T>
00121 void TreeChecker::checkOperator(Node * node, Operator * field,
00122 const char * type, const char * fieldName,
00123 T check, string desc,
00124 bool isError ) {
00125 if (! field) {
00126 if (isError) {
00127 cout << "Error: " << type << " node (" << node
00128 << ") has empty " << fieldName << " field.\n";
00129 _errorCount++;
00130 }
00131 else if (_warning)
00132 cout << type << " node (" << node << ") has empty "
00133 << fieldName << " field.\n";
00134 }
00135 else {
00136 if ( ! check(field) ) {
00137 cout << "Error: " << type << " node (" << node
00138 << ") has non-" << desc << " " << fieldName << endl;
00139 _errorCount++;
00140 }
00141 }
00142 }
00143
00144 template <class T>
00145 void TreeChecker::checkFieldInList (Node * node, list<T> & field,
00146 const char * type,
00147 const char * fieldName,
00148 int count, list<T> & collection,
00149 const char * itemName,
00150 bool isError ) {
00151 if (field.empty()) {
00152 if (isError) {
00153 cout << "Error: " << type << " node (" << node
00154 << ") has empty " << fieldName << " field.\n";
00155 _errorCount++;
00156 }
00157 else if (_warning)
00158 cout << type << " node (" << node << ") has empty "
00159 << fieldName << " field.\n";
00160 }
00161 else {
00162 if (field.size() != count) {
00163 cout << "Error: " << type << " node (" << node
00164 << ") has incorrect count for the "
00165 << fieldName << " field ";
00166 cout << "<" << field.size() << " != " << count << ">.\n";
00167 _errorCount++;
00168
00169 typename list<T>::iterator lp;
00170 for (lp = field.begin() ; lp != field.end() ; lp++) {
00171 typename list<T>::iterator p;
00172 p = find(collection.begin(), collection.end(), (*lp));
00173 if (p == collection.end())
00174 cout << " Invalid " << itemName << " node ("
00175 << (*lp) << ")\n";
00176 else if (_verbose)
00177 cout << " " << itemName << " node (" << (*lp) << ")\n";
00178 }
00179 }
00180 else {
00181 if (_verbose) {
00182 cout << type << " node (" << node << ") has "
00183 << field.size() << " " << fieldName;
00184 cout << (field.size() > 1 ? "s:\n" : ":\n");
00185 }
00186 typename list<T>::iterator lp;
00187 for (lp = field.begin() ; lp != field.end() ; lp++) {
00188 typename list<T>::iterator p;
00189 p = find(collection.begin(), collection.end(), (*lp));
00190 if (p == collection.end()) {
00191 cout << "Error: " << type << " node (" << node
00192 << ") has invalid " << itemName << " reference at "
00193 << (*lp) << ".\n";
00194 _errorCount++;
00195 }
00196 else if (_verbose)
00197 cout << " " << itemName << " node (" << (*lp) << ")\n";
00198 }
00199 }
00200 }
00201 }
00202
00203 template <class T>
00204 void TreeChecker::checkList (Node * node, list<T> & field,
00205 const char * type,
00206 const char * fieldName,
00207 bool isError ) {
00208 if (field.empty()) {
00209 if (isError) {
00210 cout << "Error: " << type << " node (" << node
00211 << ") has empty " << fieldName << " field.\n";
00212 _errorCount++;
00213 }
00214 else if (_warning)
00215 cout << type << " node (" << node << ") has empty "
00216 << fieldName << " field.\n";
00217 }
00218 else if (_verbose) {
00219 cout << type << " node (" << node << ") has " << field.size()
00220 << " " << fieldName;
00221 cout << (field.size() > 1 ? "s:\n" : ":\n");
00222 }
00223 }
00224
00225 template <class T>
00226 void TreeChecker::checkFieldInList (Node * node, T field, const char * type,
00227 const char * fieldName,
00228 list<T> & collection,
00229 bool isError ) {
00230 if (! field) {
00231 if (isError) {
00232 cout << "Error: " << type << " node (" << node
00233 << ") has empty " << fieldName << " field.\n";
00234 _errorCount++;
00235 }
00236 else if (_warning)
00237 cout << type << " node (" << node << ") has empty "
00238 << fieldName << " field.\n";
00239 }
00240 else {
00241 typename list<T>::iterator lp;
00242 lp = find(collection.begin(), collection.end(), field);
00243 if (lp == _labels.end()) {
00244 cout << "Error: " << type << " node (" << node << ") has invalid ";
00245 cout << fieldName << " reference at " << field << ".\n";
00246 _errorCount++;
00247 }
00248 else if (_verbose)
00249 cout << type << " node (" << node << ") has " << fieldName
00250 << " field = " << field << ".\n";
00251 }
00252 }
00253
00254 TreeChecker::TreeChecker () :
00255 Walker(Both, Subtree), _preDismantled(false), _postDismantled(false),
00256 _verbose(false), _errorCount(0), _typeDepth(0)
00257 {}
00258
00259 TreeChecker::TreeChecker (bool verbose, bool warning) :
00260 Walker(Both, Subtree), _preDismantled(false), _postDismantled(false),
00261 _verbose(verbose), _warning(warning), _errorCount(0), _typeDepth(0)
00262 {}
00263
00264 TreeChecker::~TreeChecker () {
00265 _visitedNodes.clear();
00266 _gotos.clear();
00267 _labels.clear();
00268 _procs.clear();
00269 _dupProcs.clear();
00270 _switches.clear();
00271 _decls.clear();
00272 _gotoCount.clear();
00273 _formals.clear();
00274 }
00275
00276 void TreeChecker::check() {
00277 for ( unit_list_p u = CBZ::Program.begin(); u != CBZ::Program.end(); u++ )
00278 check(*u);
00279 }
00280
00281 void TreeChecker::check(unitNode * the_unit) {
00282 TreeChecker tc;
00283 the_unit->walk(tc);
00284 }
00285
00286 void TreeChecker::at_node(Node * the_node, Order ord) {
00287 if ( ord == Preorder ) {
00288 checkTree(the_node, "Node");
00289 }
00290 }
00291
00292 void TreeChecker::at_unit (unitNode * unit, Order ord) {
00293 if (ord == Preorder) {
00294 UnitWalker uw;
00295 unit->walk(uw);
00296 _procs = uw.procs();
00297 _dupProcs = uw.dupProcs();
00298 _formals = uw.formals();
00299 }
00300 }
00301
00302 void TreeChecker::at_proc (procNode * proc, Order ord) {
00303 if (ord == Preorder) {
00304 ProcWalker pw;
00305 proc->walk(pw);
00306 _labels = pw.labels();
00307 _gotos = pw.gotos();
00308 _gotoCount = pw.gotoCount();
00309 _switches = pw.switches();
00310 _decls = pw.decls();
00311 _errorCount = 0;
00312 _preDismantled = false;
00313 _postDismantled = false;
00314
00315 cout << "\n---- Begin: Procedure \"" << proc->decl()->name()
00316 << "\"----\n";
00317
00318
00319 proc_list_p dup = find(_dupProcs.begin(), _dupProcs.end(), proc);
00320 if (dup != _dupProcs.end()) {
00321 _errorCount++;
00322 cout << "Error: Procedure \"" << proc->decl()->name()
00323 << "\" at (" << proc << ") is re-declared.\n";
00324 }
00325 }
00326 else {
00327 if (_preDismantled && _postDismantled)
00328 cout << "Note: Procedure \"" << proc->decl()->name()
00329 << "\" contains both dismantled and non-dismantled Nodes.\n";
00330 cout << "---- End: Procedure \"" << proc->decl()->name()
00331 << "\"----\n====> ";
00332 if (_errorCount == 0)
00333 cout << "Procedure \"" << proc->decl()->name()
00334 << "\" has no detected errors.\n";
00335 else {
00336 cout << "Procedure \"" << proc->decl()->name() << "\" has "
00337 << _errorCount << " error"
00338 << (_errorCount > 1 ? "s.\n" : ".\n");
00339 }
00340 }
00341 }
00342
00343 void TreeChecker::at_decl(declNode * the_decl, Order ord) {
00344 if ( ord == Preorder ) {
00345 checkTree(the_decl, "Decl");
00346
00347 checkField(the_decl, the_decl->type(), "Decl", "type");
00348 if (arrayNode * the_array = dynamic_cast<arrayNode *>(the_decl->type())) {
00349
00350 if ( ! the_array->dim() ) {
00351 setPreDismantled("Decl", the_decl);
00352 } else {
00353 the_array->dim()->eval();
00354 checkConstant(the_decl, the_array->dim()->value(), "Decl", "dim");
00355 }
00356 }
00357 }
00358 }
00359
00360
00361 void TreeChecker::at_case (caseNode * the_case, Order ord) {
00362 if (ord == Preorder) {
00363 setPreDismantled("Case", the_case);
00364 checkTree(the_case, "Case");
00365
00366 checkField(the_case, the_case->expr(), "Case", "expr", false);
00367 if (the_case->expr()) {
00368 the_case->expr()->eval();
00369 checkConstant(the_case, the_case->expr()->value(), "Case", "expr");
00370 }
00371 checkField(the_case, the_case->stmt(), "Case", "statement");
00372 checkFieldInList(the_case, the_case->container(), "Case", "switch",
00373 _switches);
00374 }
00375 }
00376
00377 void TreeChecker::at_label (labelNode * the_label, Order ord) {
00378 if (ord == Preorder) {
00379 checkTree(the_label, "Label");
00380 checkString(the_label, the_label->name(), "Label", "name");
00381 checkField(the_label, the_label->stmt(), "Label", "statement");
00382
00383 checkFieldInList(the_label, the_label->references(), "Label", "reference",
00384 _gotoCount[the_label], _gotos, "goto", false);
00385
00386 if (the_label->stmt()) {
00387 stmt_list stmts = the_label->stmt()->stmts();
00388 if (stmts.size() == 0) {
00389 if (_verbose || _warning)
00390 cout << "Label node (" << the_label << ") has an empty block.\n";
00391 setPreDismantled("Label", the_label);
00392 }
00393 else if (stmts.size() > 1) {
00394 if (_verbose || _warning)
00395 cout << "Label node (" << the_label
00396 << ") has a block with multiple statements.\n";
00397 setPreDismantled("Label", the_label);
00398 }
00399 else {
00400 stmtNode * stmt = stmts.front();
00401 if (stmt->typ() == Expr) {
00402 exprstmtNode * exprstmt = (exprstmtNode *) stmt;
00403 exprNode * expr = exprstmt->expr();
00404 if (expr) {
00405 if (_verbose || _warning)
00406 cout << "Label node (" << the_label
00407 << ") has a block with non-empty expression statement.\n";
00408 setPreDismantled("Label", the_label);
00409 }
00410 else {
00411 if (_verbose || _warning)
00412 cout << "Label node (" << the_label
00413 << ") has a block with an empty expression statement.\n";
00414 }
00415 }
00416 else {
00417 if (_verbose || _warning)
00418 cout << "Label node (" << the_label
00419 << ") has a block with non-expression statement.\n";
00420 setPreDismantled("Label", the_label);
00421 }
00422 }
00423 }
00424 }
00425 }
00426
00427
00428 void TreeChecker::at_goto (gotoNode * the_goto, Order ord) {
00429 if (ord == Preorder) {
00430 checkTree(the_goto, "Goto");
00431 checkString(the_goto, the_goto->name(), "Goto", "name");
00432 checkFieldInList(the_goto, the_goto->label(), "Goto", "label", _labels);
00433 }
00434 }
00435
00436 class ComparisonOperator : public OperatorCheck {
00437 public:
00438 bool operator()(Operator * op) {
00439 return op->is_comparison();
00440 }
00441 string desc() { return string("comparison"); }
00442 };
00443
00444 void TreeChecker::at_conditiongoto (conditiongotoNode * the_condgoto,
00445 Order ord) {
00446 if (ord == Preorder) {
00447 setPostDismantled("Condition goto", the_condgoto);
00448 checkTree(the_condgoto, "Condition goto");
00449 checkField(the_condgoto, the_condgoto->left(), "Condition goto",
00450 "left operand");
00451 checkField(the_condgoto, the_condgoto->right(), "Condition goto",
00452 "right operand");
00453 ComparisonOperator co;
00454 checkOperator(the_condgoto, the_condgoto->op(), "Condition goto",
00455 "operator", co, co.desc());
00456 }
00457 }
00458
00459 void TreeChecker::at_break (breakNode * the_break, Order ord) {
00460 if (ord == Preorder) {
00461 setPreDismantled("Break", the_break);
00462 checkTree(the_break, "Break");
00463 checkField(the_break, the_break->container(), "Break", "container");
00464 }
00465 }
00466
00467 void TreeChecker::at_continue (continueNode * the_continue, Order ord) {
00468 if (ord == Preorder) {
00469 setPreDismantled("Continue", the_continue);
00470 checkTree(the_continue, "Continue");
00471 checkField(the_continue, the_continue->container(), "Continue",
00472 "container");
00473 }
00474 }
00475
00476 void TreeChecker::at_return (returnNode * the_return, Order ord) {
00477 if (ord == Preorder) {
00478 checkTree(the_return, "Return");
00479
00480 checkField(the_return, the_return->expr(), "Return", "expr", false);
00481
00482 if (the_return->expr()) {
00483 if (the_return->expr()->typ() != Id) {
00484 setPreDismantled("Return", the_return);
00485 if (_verbose || _warning)
00486 cout << "Return node (" << the_return
00487 << ") has non id return type.\n";
00488 }
00489 else if (_verbose || _warning)
00490 cout << "Return node (" << the_return << ") has id return type.\n";
00491 }
00492 checkFieldInList(the_return, the_return->proc(), "Return", "proc", _procs);
00493 }
00494 }
00495
00496
00497 void TreeChecker::at_if (ifNode * the_if, Order ord) {
00498 if (ord == Preorder) {
00499 setPreDismantled("If", the_if);
00500 checkTree(the_if, "If");
00501 checkField(the_if, the_if->expr(), "If", "expr");
00502
00503 checkField(the_if, the_if->true_br(), "If", "true-branch");
00504
00505 checkField(the_if, the_if->false_br(), "If", "false-branch", false);
00506 }
00507 }
00508
00509 void TreeChecker::at_switch (switchNode * the_switch, Order ord) {
00510 if (ord == Preorder) {
00511 setPreDismantled("Switch", the_switch);
00512 checkTree(the_switch, "Switch");
00513 checkField(the_switch, the_switch->expr(), "Switch",
00514 "conditional expression");
00515 checkField(the_switch, the_switch->stmt(), "Switch", "statements");
00516 checkList(the_switch, the_switch->cases(), "Switch", "cases");
00517
00518
00519 }
00520 }
00521
00522
00523 void TreeChecker::at_for(forNode * the_for, Order ord) {
00524 if ( ord == Preorder ) {
00525 setPreDismantled("For-loop", the_for);
00526 checkTree(the_for, "For-loop");
00527
00528 checkField(the_for, the_for->cond(), "For-loop", "expr", false);
00529 checkField(the_for, the_for->body(), "For-loop", "body");
00530 }
00531 }
00532
00533 void TreeChecker::at_loop (loopNode * loop, Order ord) {
00534 if (ord == Preorder) {
00535 setPreDismantled("Loop", loop);
00536 checkTree(loop, "Loop");
00537 checkField(loop, loop->cond(), "Loop", "expr");
00538 checkField(loop, loop->body(), "Loop", "body");
00539 }
00540 }
00541
00542
00543 void TreeChecker::at_call (callNode * the_call, Order ord) {
00544 if (ord == Preorder) {
00545 if ( _typeDepth == 0 )
00546 setPreDismantled("Call", the_call);
00547 checkTree(the_call, "Call");
00548 checkField(the_call, the_call->name(), "Call", "name");
00549
00550 checkList(the_call, the_call->args(), "Call", "argument list", false);
00551
00552
00553 checkField(the_call, the_call->proc(), "Call", "procedure", false);
00554
00555
00556
00557 if (the_call->name()) {
00558 if (the_call->name()->typ() == Id) {
00559
00560 idNode * id = (idNode *) the_call->name();
00561 if ( _formals.find(id->name()) != _formals.end() ) {
00562 if ( _formals[id->name()] != the_call->args().size() ) {
00563 cout << "Error: Call node (" << the_call
00564 << ") has incorrect number of arguments = "
00565 << the_call->args().size() << ".\n";
00566 _errorCount++;
00567 } else if (_verbose || _warning) {
00568 cout << "Call node (" << the_call << ") has "
00569 << the_call->args().size() << " argument";
00570 cout << ((the_call->args().size() > 1) ? "s.\n" : ".\n");
00571 }
00572 }
00573 } else {
00574
00575
00576 cout << "Unable to check that the actual arguments for call node ("
00577 << the_call << ") match the number of formal parameters." << endl;
00578 }
00579 }
00580
00581
00582 }
00583 }
00584
00585 void TreeChecker::at_id (idNode * id, Order ord) {
00586 if (ord == Preorder) {
00587 checkTree(id, "Id");
00588 checkString(id, id->name(), "Id", "name");
00589 checkFieldInList(id, id->decl(), "Id", "decl", _decls);
00590
00591 }
00592 }
00593
00594 void TreeChecker::at_const (constNode * the_const, Order ord) {
00595 if (ord == Preorder) {
00596 checkTree(the_const, "Const");
00597 the_const->eval();
00598 checkConstant(the_const, the_const->value(), "Const", "value");
00599 }
00600 }
00601
00602 class UnaryOperator : OperatorCheck {
00603 public:
00604 virtual bool operator()(Operator * op) { return op->is_unary(); }
00605 virtual string desc() { return string("unary"); }
00606 };
00607
00608 void TreeChecker::at_unary (unaryNode * unary, Order ord) {
00609 if (ord == Preorder) {
00610 if ( _typeDepth == 0 )
00611 setPreDismantled("Unary", unary);
00612 checkTree(unary, "Unary");
00613 UnaryOperator uo;
00614 checkOperator(unary, unary->op(), "Unary", "operator", uo, uo.desc());
00615 if ( unary->op()->id() != Operator::SIZEOF ) {
00616 checkField(unary, unary->expr(), "Unary", "expr");
00617 } else {
00618 checkField(unary, unary->sizeof_type(), "Unary", "sizeof_type");
00619 }
00620 }
00621 }
00622
00623 class BinaryOperator : public OperatorCheck {
00624 public:
00625 bool operator()(Operator * op) {
00626 return op->is_binary();
00627 }
00628 string desc() { return string("binary"); }
00629 };
00630
00631 void TreeChecker::at_binary (binaryNode * binary, Order ord) {
00632 if (ord == Preorder) {
00633 if ( _typeDepth == 0 )
00634 setPreDismantled("Binary", binary);
00635 checkTree(binary, "binary");
00636 BinaryOperator bo;
00637 checkOperator(binary, binary->op(), "Binary", "operator", bo, bo.desc());
00638 checkField(binary, binary->left(), "Binary", "left side");
00639 checkField(binary, binary->right(), "Binary", "right side");
00640 }
00641 }
00642
00643 void TreeChecker::at_ternary (ternaryNode * ternary, Order ord) {
00644 if (ord == Preorder) {
00645 if ( _typeDepth == 0 )
00646 setPreDismantled("Ternary", ternary);
00647 checkTree(ternary, "Ternary");
00648 ComparisonOperator co;
00649
00650 checkField(ternary, ternary->cond(), "Ternary", "cond");
00651 checkField(ternary, ternary->true_br(), "Ternary", "true branch");
00652 checkField(ternary, ternary->false_br(), "Ternary", "false branch");
00653 }
00654 }
00655
00656 void TreeChecker::at_threeAddr (threeAddrNode * the_3addr, Order ord) {
00657 if (ord == Preorder) {
00658 setPostDismantled("Three address", the_3addr);
00659 checkTree(the_3addr, "Three address");
00660
00661
00662
00663
00664 checkField(the_3addr, the_3addr->lhs(), "Three address", "lhs", false);
00665 Operator * op = the_3addr->op();
00666 if ( op ) {
00667 if ( op->id() == Operator::SIZEOF ) {
00668 checkField(the_3addr, the_3addr->sizeof_type(), "Three address",
00669 "sizeof_type");
00670 } else {
00671 checkField(the_3addr, the_3addr->rhs1(), "Three address", "rhs1");
00672 if ( op->id() == Operator::FUNC_CALL ) {
00673 checkList(the_3addr, the_3addr->arg_list(), "Three address",
00674 "arg_list", false);
00675 } else if ( op->is_dismantled_binary() ) {
00676 checkField(the_3addr, the_3addr->rhs2(), "Three address", "rhs2");
00677 }
00678 }
00679 }
00680 }
00681 }
00682
00683 void TreeChecker::at_operand (operandNode * operand, Order ord) {
00684 if (ord == Preorder) {
00685 setPostDismantled("Operand", operand);
00686 checkTree(operand, "Operand");
00687 checkField(operand, operand->var(), "Operand", "variable");
00688
00689
00690 checkField(operand, operand->cast(), "Operand", "typecast", false);
00691 checkField(operand, operand->index(), "Operand", "index", false);
00692 checkList(operand, operand->fields(), "Operand", "fields", false);
00693 }
00694 }
00695
00696 void TreeChecker::at_cast (castNode * cast, Order ord) {
00697 if (ord == Preorder) {
00698 if ( _typeDepth == 0 )
00699 setPreDismantled("Cast", cast);
00700 checkTree(cast, "Cast");
00701 checkField(cast, cast->expr(), "Cast", "expression");
00702 }
00703 }
00704
00705 void TreeChecker::at_comma (commaNode * comma, Order ord) {
00706 if (ord == Preorder) {
00707 if ( _typeDepth == 0 )
00708 setPreDismantled("Comma", comma);
00709 checkTree(comma, "Comma");
00710 checkList(comma, comma->exprs(), "Comma", "expression list");
00711 }
00712 }
00713
00714 void TreeChecker::at_initializer (initializerNode * init, Order ord) {
00715 if (ord == Preorder) {
00716 if ( _arrayDepth == 0 )
00717 setPreDismantled("Initializer", init);
00718 checkTree(init, "Initializer");
00719 checkList(init, init->exprs(), "Initializer", "expression list");
00720 }
00721 }
00722
00723
00724 void TreeChecker::at_type (typeNode * the_type, Order ord) {
00725 if ( ord == Preorder ) {
00726 _typeDepth++;
00727 } else {
00728 _typeDepth--;
00729 }
00730 }
00731
00732 void TreeChecker::at_func (funcNode * func, Order ord) {
00733 at_type(func, ord);
00734 if (ord == Preorder) {
00735 checkTree(func, "Function");
00736 checkField(func, func->returns(), "Function", "return");
00737
00738
00739 checkFieldInList(func, func->args(), "Function", "argument list",
00740 func->args().size(), _decls, "argument", false);
00741 }
00742 }
00743
00744 void TreeChecker::at_tdef (tdefNode * tdef, Order ord) {
00745 at_type(tdef, ord);
00746 if (ord == Preorder) {
00747
00748 checkTree(tdef, "Typedef");
00749 checkString(tdef, tdef->name(), "Typedef", "name");
00750 checkField(tdef, tdef->def(), "Typedef", "def");
00751 }
00752 }
00753
00754 void TreeChecker::at_array (arrayNode * array, Order ord) {
00755 at_type(array, ord);
00756 if (ord == Preorder) {
00757 _arrayDepth++;
00758 checkTree(array, "Array");
00759 checkField(array, array->dim(), "Array", "dimension expression",
00760 false);
00761
00762 } else {
00763 _arrayDepth--;
00764 }
00765 }
00766
00767 UnitWalker::UnitWalker () :
00768 Walker(Preorder, Subtree)
00769 {}
00770
00771 UnitWalker::~UnitWalker () {
00772 _procs.clear();
00773 _procNames.clear();
00774 _dupProcs.clear();
00775 _formals.clear();
00776 }
00777
00778 void UnitWalker::at_proc (procNode * the_proc, Order ord) {
00779 _procs.push_back(the_proc);
00780 declNode * proc_decl = the_proc->decl();
00781 if ( !proc_decl ) {
00782 cout << "procNode " << the_proc << " contains no declNode." << endl;
00783 return;
00784 }
00785 string procName = proc_decl->name();
00786
00787
00788 funcNode * proc_func = (funcNode *) proc_decl->type();
00789 if ( !proc_func ) {
00790 cout << "procNode " << the_proc << " w/ declNode " << proc_decl
00791 << " does not have Func typ()." << endl;
00792 return;
00793 }
00794 int argc = proc_func->args().size();
00795 if (proc_func->is_void_args())
00796 argc = 0;
00797
00798
00799 if (find(_procNames.begin(), _procNames.end(), procName)
00800 != _procNames.end()) {
00801 _dupProcs.push_back(the_proc);
00802 return;
00803 }
00804 else _procNames.push_back(procName);
00805
00806
00807 if ( _formals.find(procName) == _formals.end() )
00808 _formals[procName] = argc;
00809 }