C-Breeze
C Compiler Infrastructure

[ Project home page]
Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

tree_checker.cc

Go to the documentation of this file.
00001 // $Id: tree_checker.cc,v 1.4 2003/08/11 17:28:44 abrown Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 //
00007 //  Copyright (c) 2000 University of Texas at Austin
00008 //
00009 //  Samuel Z. Guyer
00010 //  Daniel A. Jimenez
00011 //  Calvin Lin
00012 //
00013 //  Permission is hereby granted, free of charge, to any person
00014 //  obtaining a copy of this software and associated documentation
00015 //  files (the "Software"), to deal in the Software without
00016 //  restriction, including without limitation the rights to use, copy,
00017 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00018 //  of the Software, and to permit persons to whom the Software is
00019 //  furnished to do so, subject to the following conditions:
00020 //
00021 //  The above copyright notice and this permission notice shall be
00022 //  included in all copies or substantial portions of the Software.
00023 //
00024 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00026 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00028 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00029 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00030 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00031 //  THE SOFTWARE.
00032 //
00033 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00034 //  Computer Science for inspiring parts of the C-Breeze design.
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 /*= true*/) {
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 /*= true*/) {
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 /*= true*/) {
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 /*= true*/) {
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 /*= true*/) {
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 /*= true*/) {
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 /*= true*/) {
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);  // collect all proc and related nodes
00296     _procs = uw.procs();  // proc nodes
00297     _dupProcs = uw.dupProcs();  // re-declared proc nodes
00298     _formals = uw.formals();  // formal parameter count
00299   }
00300 }
00301 
00302 void TreeChecker::at_proc (procNode * proc, Order ord) {
00303   if (ord == Preorder) {
00304     ProcWalker pw;
00305     proc->walk(pw);  // collect all kind of nodes for this procedure
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     // check for re-definition of procedure/function
00319     proc_list_p dup = find(_dupProcs.begin(), _dupProcs.end(), proc);
00320     if (dup != _dupProcs.end()) {  // found duplicates
00321       _errorCount++;
00322       cout << "Error: Procedure \"" << proc->decl()->name() 
00323            << "\" at (" << proc << ") is re-declared.\n";
00324     }
00325   }
00326   else { // ord == Postorder
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     // declarations of variables MUST have a type
00347     checkField(the_decl, the_decl->type(), "Decl", "type");
00348     if (arrayNode * the_array = dynamic_cast<arrayNode *>(the_decl->type())) {
00349       // declarations of array's in dismantled code must have 
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 // target node
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     // the expr field may be NULL (default case)
00366     checkField(the_case, the_case->expr(), "Case", "expr", false);
00367     if (the_case->expr()) {  // check for constant-ness
00368       the_case->expr()->eval();  // try to evaluate this expression
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     // some label node may have empty references (gotos)
00383     checkFieldInList(the_label, the_label->references(), "Label", "reference", 
00384                      _gotoCount[the_label], _gotos, "goto", false);
00385 
00386     if (the_label->stmt()) {  // contains a block
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();  // get the only stmt
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 // jump node
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     // the expr field may be NULL
00480     checkField(the_return, the_return->expr(), "Return", "expr", false);
00481     // dismantled code should only return idNode
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 // selection node
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     // TODO: can the true branch be NULL?
00503     checkField(the_if, the_if->true_br(), "If", "true-branch");
00504     // the false branch may be NULL
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     // TODO: should we check that cases who think they belong to the switch
00518     //       actually do belong?
00519   }
00520 }
00521 
00522 // loop node
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     // the expr field may be NULL (empty for loop)
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 // expr node
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     // the argument list may be EMPTY
00550     checkList(the_call, the_call->args(), "Call", "argument list", false);
00551     // the procedure field may be NULL
00552     // TODO: is this only when name()->typ() != Id?
00553     checkField(the_call, the_call->proc(), "Call", "procedure", false);
00554 
00555     // Check that the actual arguments match 
00556     // the number of the formal parameters.
00557     if (the_call->name()) {
00558       if (the_call->name()->typ() == Id) {
00559         // get the argument counts for procedure with this name
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         // TODO: what about comparing to the type of the name()'s decl?
00575         //       aka: for function pointers
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     // TODO: Check that the actual arguments match the types of the 
00581     //       formal parameters (with type promotions).
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     // TODO: check that id is in the the id_list for the declNode.
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();  // try to evaluate the constant expression
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 //     checkOperator(ternary, ternary->cond(), "Ternary", "cond", co, co.desc());
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     // all the fields may be NULL or EMPTY depending on the actual node
00661     // TODO: is that true?  i think the rules are more complex
00662 
00663     // TODO:  check that lhs()->typ() is Id
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     // all the other fields may be NULL or EMPTY depending on the actual node
00689     // TODO:  are they necessary?
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 // type node
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     // TODO: actually should check that number of actual arguments
00738     //       matches that number of formal arguments
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     // TODO:  check with Sam, are these sufficient/correct?
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);  // array dimension may be NULL (in case of [])
00761     // actually, must be constant or constant expression
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   // get the formal argument count
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   // look for re-definition of procedure/function
00799   if (find(_procNames.begin(), _procNames.end(), procName)
00800       != _procNames.end()) {  // found duplicates
00801     _dupProcs.push_back(the_proc);  // re-defined
00802     return;  // quit
00803   }
00804   else _procNames.push_back(procName);  // collect procedure name
00805 
00806   // only insert once
00807   if ( _formals.find(procName) == _formals.end() )
00808     _formals[procName] = argc;
00809 }

Generated on August 27, 2003
Back to the C-Breeze home page