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  

id_lookup_walker.cc

Go to the documentation of this file.
00001 // $Id: id_lookup_walker.cc,v 1.9 2003/08/07 23:13:47 pnav 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 "c_breeze.h"
00039 #include "scope_walker.h"
00040 #include "id_lookup_walker.h"
00041 
00042 // ------------------------------------------------------------
00043 // Constructor
00044 // ------------------------------------------------------------
00045 
00046 id_lookup_walker::id_lookup_walker(unitNode * u, bool verb)
00047   : scope_walker(u),
00048     _verbose(verb)
00049 {}
00050 
00051 // ------------------------------------------------------------
00052 // Utility class: clear all the pointers first
00053 // ------------------------------------------------------------
00054 
00055 class clear_ids_walker : public Walker
00056 {
00057 public:
00058 
00059   static void clear(unitNode * u)
00060   {
00061     clear_ids_walker ciw;
00062 
00063     u->walk(ciw);
00064   }
00065 
00066 private:
00067 
00068   clear_ids_walker()
00069     : Walker(Preorder, Subtree)
00070   {}
00071 
00072 public:
00073 
00074   virtual void at_tdef(tdefNode * the_tdef, Order ord)
00075   {
00076 // djimenez
00077 // what is this for?  I don't know, but it's screwing up things like:
00078 // typedef int Int;
00079 // struct foo {
00080 //      Int a;
00081 // } foo;
00082 // foo b;
00083 // void bar (void) { b.a; }
00084 
00085 //    the_tdef->def(0);
00086   }
00087 
00088   virtual void at_id(idNode * the_id, Order ord)
00089   {
00090     the_id->decl(0);
00091   }
00092 };
00093 
00094 // ------------------------------------------------------------
00095 // Entry points
00096 // ------------------------------------------------------------
00097 
00098 void id_lookup_walker::fixup(unitNode * u, bool verb)
00099 {
00100   id_lookup_walker idw(u,verb);
00101   clear_ids_walker::clear(u);
00102 
00103   u->walk(idw);
00104 }
00105 
00106 id_lookup_walker * id_lookup_walker::fixup_and_return(unitNode * u, bool verb)
00107 {
00108   id_lookup_walker * idw = new id_lookup_walker(u,verb);
00109   clear_ids_walker::clear(u);
00110 
00111   u->walk(*idw);
00112 
00113   return idw;
00114 }
00115 
00116 // ------------------------------------------------------------
00117 // Handle errors and conflicts
00118 // ------------------------------------------------------------
00119 
00120 void id_lookup_walker::conflict(const Coord & c, const string & msg)
00121 {
00122   if (_verbose)
00123      CBZ::SyntaxError(c, msg);
00124 }
00125 
00126 // ------------------------------------------------------------
00127 // Handle entries into the symbol table
00128 // ------------------------------------------------------------
00129 
00130 void id_lookup_walker::at_proc(procNode * the_proc, Order ord)
00131 {
00132   if (ord == Preorder) {
00133 
00134     // -- Put the formal parameters into the symbol table
00135 
00136     enter_scope();
00137 
00138     funcNode * f = (funcNode *) the_proc->decl()->type();
00139     decl_list & as = f->args();
00140 
00141     for (decl_list_p p = as.begin(); p != as.end(); ++p) {
00142 
00143       if ((*p)->datatype()->is_ellipsis() ||
00144           (*p)->datatype()->is_void())
00145         ;
00146       else
00147         if (! (*p)->name().empty()) {
00148 
00149           // -- Normal declaration...
00150 
00151           declNode * a_decl = (declNode *) (*p);
00152           declNode * o_decl = ids()->insert(a_decl->name(), a_decl);
00153 
00154           // -- Check for conflict...
00155           if (o_decl)
00156             conflict(a_decl->coord(),
00157                      string("formal `") + 
00158                      o_decl->name() + string("' used multiple times"));
00159 
00160         } else
00161           conflict((*p)->coord(),
00162                    string("argument without a name"));
00163     }
00164 
00165     // -- Local variables get their own scope (SZG)
00166 
00167     enter_scope();
00168   }
00169 
00170   if (ord == Postorder) {
00171 
00172     // -- Set decl_location on the func decl
00173 
00174     the_proc->decl()->decl_location(declNode::PROC);
00175 
00176     // -- Exit the local variable scope (SZG)
00177 
00178     exit_scope();
00179 
00180     // -- Exit the formal parameter scope
00181 
00182     exit_scope();
00183   }
00184 
00185 }
00186 
00187 void id_lookup_walker::at_decl(declNode * the_decl, Order ord)
00188 {
00189   // SZG Let's try preorder to fix things like this:
00190   //    struct Foo * f = malloc( sizeof *f );
00191   // if (ord == Postorder) {
00192 
00193   if (ord == Preorder) {
00194 
00195     declNode * orig;
00196 
00197     // -- Skip abstract declarators...
00198 
00199     if (the_decl->name().empty()) {
00200       // djimenez - added this check
00201         if (in_formals()) {
00202                 the_decl->decl_location(declNode::FORMAL);
00203         } else if (in_su()) {
00204                 the_decl->decl_location(declNode::SU);
00205         }
00206       return;
00207     }
00208 
00209     // -- Reset the reference count
00210 
00211     the_decl->references(0);
00212 
00213     // -- Handle formal parameters...
00214 
00215     if (in_formals()) {
00216       the_decl->decl_location(declNode::FORMAL);
00217 
00218       if ((the_decl->storage_class() != declNode::NONE) &&
00219           (the_decl->storage_class() != declNode::REGISTER)) {
00220         conflict(the_decl->coord(),
00221                  string("illegal storage class for parameter `") + 
00222                  the_decl->name() + string("'"));
00223 
00224         //if (the_decl->storage_class() == declNode::TYPEDEF)
00225         //  break;
00226 
00227         // reset storage class for body
00228         //the_decl->storage_class(declNode::NONE);
00229         // why? djimenez
00230       }
00231 
00232       // convert Array to pointer
00233       // djimenez
00234       // why?  it gains us nothing, and if we do this here but not 
00235       // for abstract declarators, we'll get incompatible types
00236       // when they are compared.
00237       
00238       //if (the_decl->type()->typ() == Array) {
00239 //      arrayNode * atype = (arrayNode *) the_decl->get_type();
00240 //      the_decl->type(new ptrNode(atype->type_qualifiers(),
00241 //                                 atype->type(),
00242 //                                 atype->coord()));
00243 
00244         // -- Delete the old type...
00245 //      delete atype;
00246 //     }
00247 
00248       return;
00249     }
00250 
00251     // -- Insert declarations into the symbol tables...
00252 
00253     if ((the_decl->type()->typ() == Func) ||
00254         (the_decl->storage_class() == declNode::EXTERN)) {
00255 
00256     // -- Put externs in the externs symbol table. It allows
00257     // duplicates, as long as they are compatible.
00258 
00259       orig = externs()->insert(the_decl->name(), the_decl);
00260       if (orig) {
00261 
00262         if (the_decl->type()->typ() == Func) {
00263           funcNode * the_func = (funcNode *) the_decl->type();
00264           funcNode * ofunc = (funcNode *) orig->type();
00265 
00266           // -- Duplicate function declarations must be compatible...
00267 
00268           if (! ofunc->is_compatible_with(the_func)) {
00269             conflict(the_func->coord(),
00270                      string("function identifier `") + the_decl->name() +
00271                      "' redeclared\n        Previous declaration: " +
00272                      orig->coord().to_string());
00273           }
00274         }
00275         else {
00276           // "external declarations for the same identifier must agree in
00277           // type and linkage" --  K&R2, A10.2
00278 
00279           if (! (* orig->type() == * the_decl->type()) ) {
00280             conflict(the_decl->coord(),
00281                      string("extern `") + orig->name() + 
00282                      "' redeclared\n        Previous declaration: " +
00283                      orig->coord().to_string());
00284           }
00285         }
00286       }
00287     }
00288     else
00289       if (! in_su() /* && ! in_enum() */) {
00290 
00291         // -- Regular (non-extern) declarations...
00292 
00293         orig = ids()->insert(the_decl->name(), the_decl);
00294         if ((orig) && (orig != the_decl)) {
00295           conflict(the_decl->coord(),
00296                    string("variable `") + orig->name() +
00297                    "' redeclared\n        Previous declaration: " +
00298                    orig->coord().to_string());
00299         }
00300       }
00301 
00302     // -- Set decl_location
00303 
00304     if (in_su())
00305       the_decl->decl_location(declNode::SU);
00306     else
00307       if (in_enum())
00308         the_decl->decl_location(declNode::ENUM);
00309       else
00310         if (symbol_level() == 0)
00311           the_decl->decl_location(declNode::TOP);
00312         else
00313           the_decl->decl_location(declNode::BLOCK);
00314   }
00315 }
00316 
00317 // ------------------------------------------------------------
00318 // Lookup identifiers in table
00319 // ------------------------------------------------------------
00320 
00321 void id_lookup_walker::at_call(callNode * the_call, Order ord)
00322 {
00323   if ((ord == Preorder) &&
00324       (the_call->name()->typ() == Id)) {
00325     idNode * id = (idNode *) the_call->name();
00326     declNode * var;
00327 
00328     var = ids()->lookup(id->name());
00329     if (! var) {
00330       var = externs()->lookup(id->name());
00331       if (var) {
00332         id->decl(var);
00333         var->inc_references();
00334       }
00335       else {
00336         // -- Not found, declare returning int...
00337 
00338         var = new declNode(id->name().c_str(), declNode::EXTERN,
00339                            new funcNode(typeNode::NONE, (decl_list *)0,
00340                                         new primNode(id->coord()),
00341                                         id->coord()),
00342                            (exprNode *)0,
00343                            (exprNode *)0,
00344                            id->coord());
00345 
00346         var->decl_location(declNode::TOP);
00347         var->inc_references();
00348         id->decl(var);
00349 
00350         unit()->undef_funcs().push_back(var);
00351 
00352         declNode * tmp;
00353         tmp = ids()->insert(id->name(), var);
00354         tmp = externs()->insert(id->name(), var);
00355       }
00356     }
00357   }
00358 }
00359 
00360 void id_lookup_walker::at_tdef(tdefNode * the_tdef, Order ord)
00361 {
00362   if (ord == Postorder) {
00363     declNode * d1 = ids()->lookup(the_tdef->name());
00364     declNode * d2 = externs()->lookup(the_tdef->name());
00365     declNode * d;
00366     if (d1 || d2) {
00367       if (d1) d = d1;
00368       if (d2) d = d2;
00369 
00370       the_tdef->def(d->type());
00371       d->inc_references();
00372     }
00373   }
00374 }
00375 
00376 void id_lookup_walker::at_id(idNode * the_id, Order ord)
00377 {
00378   if (ord == Postorder) {
00379 
00380     // -- Skip it if its already been set (in at_call).
00381 
00382     if (the_id->decl())
00383       return;
00384 
00385     declNode * d1 = ids()->lookup(the_id->name());
00386     declNode * d2 = externs()->lookup(the_id->name());
00387     declNode * d;
00388     if (d1 || d2) {
00389       if (d1) 
00390         d = d1;
00391       else if (d2) 
00392         d = d2;
00393 
00394       the_id->decl(d);
00395       d->inc_references();
00396     }
00397     else
00398       conflict(the_id->coord(), string("undeclared variable `") +
00399                the_id->name() + string("'"));
00400   }
00401 }
00402 
00403 void id_lookup_walker::at_binary(binaryNode * the_binary, Order ord)
00404 {
00405   // -- This code is to handle the identifiers that represent struct/union
00406   // fields (only works if the semantic checker has been run first).
00407 
00408   unsigned int opid = the_binary->op()->id();
00409 
00410   if ((ord == Preorder) &&
00411       ((opid == Operator::ARROW) ||
00412        (opid == '.')) &&
00413       the_binary->left()->type())
00414     {
00415       idNode * field = (idNode *) the_binary->right();
00416       exprNode * left = the_binary->left();
00417       typeNode * left_type = left->no_tdef_type();
00418 
00419       if (opid == Operator::ARROW) {
00420         if (left_type->typ() != Ptr)
00421           CBZ::SyntaxError(left->coord(),
00422                            "Left operand of \"->\" must be a pointer");
00423 
00424         left_type = left_type->no_tdef_type();
00425       }
00426 
00427       // -- Make sure the LHS is a struct or union
00428 
00429       if ((left_type->typ() != Struct) &&
00430           (left_type->typ() != Union)) {
00431         CBZ::SyntaxError(left->coord(),
00432                          "Left operand of \"->\"/\".\" must be a struct or union");
00433       }
00434       else {
00435         sueNode * sue = (sueNode *) left_type;
00436         suespecNode * sp = sue->spec();
00437 
00438         declNode * field_decl = sp->find_field(field->name());
00439 
00440         field->decl(field_decl);
00441         if (field_decl)
00442           field_decl->inc_references();
00443       }
00444     }
00445 }

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