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  

symbol.cc

Go to the documentation of this file.
00001 // $Id: symbol.cc,v 1.6 2003/08/07 23:13:54 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 
00040 // --- Initialize the symbol tables
00041 /*
00042 Identifiers_table * Symbols::Identifiers = new Identifiers_table();
00043 Labels_table      * Symbols::Labels =      new Labels_table();
00044 Tags_table        * Symbols::Tags =        new Tags_table();
00045 Externals_table   * Symbols::Externals =   new Externals_table();
00046 */
00047 bool Symbols::TrackScopeExits = false;
00048 bool Symbols::TrackInsertSymbol = false;
00049 bool Symbols::TrackIds = false;
00050 /*
00051 int Symbols::Level = 0;
00052 */
00053 // ------------------------------------------------------------
00054 //   SymbolTable Template
00055 // ------------------------------------------------------------
00056 
00057 // --- Symbol table destructor
00058 
00059 template <class T>
00060 SymbolTable<T>::~SymbolTable()
00061 {
00062   // -- Delete all the scopes
00063 
00064   for (table_p p = _table.begin() ; p != _table.end(); ++p)
00065     delete (*p);
00066 }
00067 
00068 // mark nodes for garbage collection
00069 template <class T>
00070 void SymbolTable<T>::mark_nodes (void) {
00071   for (table_p p = _table.begin() ; p != _table.end(); ++p) {
00072 
00073     scope * sc = (*p);
00074 
00075     // -- For each entry in the scope, mark the node 
00076 
00077     for (scope_p s = sc->begin(); s != sc->end(); ++s) {
00078       Node *n = (Node *) ((*s).second);
00079       n->mark = true;
00080     }
00081   }
00082 }
00083 
00084 // --- Symbol table reset.
00085 
00086 template <class T>
00087 void SymbolTable<T>::reset()
00088 {
00089   // -- For each scope...
00090 
00091   for (table_p p = _table.begin() ; p != _table.end(); ++p) {
00092 
00093     scope * sc = (*p);
00094 
00095     // -- For each entry in the scope, call the exit proc...
00096 
00097     for (scope_p s = sc->begin(); s != sc->end(); ++s)
00098       notify_exit_scope((*s).second);
00099 
00100     // -- Delete the scope
00101 
00102     delete sc;
00103   }
00104 
00105   _table.clear();
00106   _table.push_front(new scope());
00107 }
00108 
00109 // --- Symbol table insert
00110 // If the new symbol conflicts with a previously declared symbol, then the original
00111 // symbol is returned. It's up to the called to decide what to do.
00112 
00113 template <class T>
00114 T SymbolTable<T>::insert(const string & name, T sym)
00115 {
00116   if (Symbols::TrackInsertSymbol)
00117     cerr << "InsertSymbol(" << name << ", " << ")" << endl;
00118 
00119   // -- Get the current scope
00120   scope * sc = _table.front();
00121 
00122   // -- Check if the name is already there...
00123   scope_p s = sc->find(name);
00124 
00125   // -- If it is, return the original declaration...
00126 
00127   if (s != sc->end())
00128     return (*s).second;
00129 
00130   // -- otherwise, add it to the table...
00131 
00132   (*sc)[name] = sym;
00133 
00134   return (T) 0;
00135 }
00136 
00137 // --- Symbol table lookup
00138 
00139 template <class T>
00140 T SymbolTable<T>::lookup(const string & name)
00141 {
00142   table_p p = _table.begin();
00143   bool found = false;
00144   scope * sc;
00145   scope_p s;
00146   T sym_out;
00147 
00148   do {
00149     sc = (*p);
00150     s = sc->find(name);
00151     if (s != sc->end()) {
00152       found = true;
00153       p = _table.end();
00154     }
00155     else
00156       ++p;
00157   } while (! found && (p != _table.end()));
00158 
00159   if (found)
00160     sym_out = (*s).second;
00161   else
00162     sym_out = (T) 0;
00163 
00164   return sym_out;
00165 }
00166 
00167 // --- Symbol table enter scope
00168 
00169 template <class T>
00170 void SymbolTable<T>::enter_scope()
00171 {
00172   if (_is_nested)
00173    _table. push_front(new scope());
00174 }
00175 
00176 // --- Symbol table exit scope
00177 
00178 template <class T>
00179 void SymbolTable<T>::exit_scope()
00180 {
00181   if (_is_nested) {
00182 
00183     scope * top = _table.front();
00184 
00185     for (scope_p s = top->begin(); s != top->end(); ++s)
00186       notify_exit_scope((*s).second);
00187 
00188     _table.pop_front();
00189     delete top;
00190   }
00191 }
00192 
00193 template <class T>
00194 void SymbolTable<T>::print(FILE * out)
00195 {
00196 }
00197 
00198 template <class T>
00199 string SymbolTable<T>::insert_unique(const string & root, T sym)
00200 {
00201   char buf[33];
00202   static unsigned counter = 0;
00203   T existing;
00204   string new_name;
00205 
00206   // --- First try the unmodified name...
00207 
00208   existing = lookup( root );
00209   if (existing) {
00210 
00211     // --- Find a name that's unique in the table...
00212 
00213     do {
00214       sprintf(buf, "%.16s%d", root.c_str(), ++counter);
00215       string tmp(buf);
00216       existing = lookup( tmp );
00217     } while (existing != 0);
00218 
00219     new_name = string(buf);
00220   }
00221   else
00222     new_name = root;
00223 
00224   // --- Insert the symbol under that name...
00225 
00226   existing = insert(new_name, sym);
00227 
00228   return new_name;
00229 }
00230 
00231 // -- IsAType from type.c
00232 
00233 bool Identifiers_table::is_a_type(const string & name)
00234 {
00235   declNode * var = lookup(name);
00236   if (var)
00237     return var->storage_class() == declNode::TYPEDEF;
00238 
00239   return false;
00240 }
00241 
00242 // ------------------------------------------------------------
00243 // Symbol table constructors
00244 // ------------------------------------------------------------
00245 
00246 Identifiers_table::Identifiers_table()
00247   : SymbolTable< declNode * >(true)
00248 {}
00249 
00250 Labels_table::Labels_table()
00251   : SymbolTable< labelNode * >(false)
00252 {}
00253 
00254 Tags_table::Tags_table()
00255   : SymbolTable< suespecNode * >(true)
00256 {}
00257 
00258 Externals_table::Externals_table()
00259   : SymbolTable< declNode * >(false)
00260 {}
00261 
00262 // ------------------------------------------------------------
00263 //  Shadow and notify_exit_scope methods
00264 // ------------------------------------------------------------
00265 
00266 void Identifiers_table::shadow(declNode * create, declNode * shadowed)
00267 {
00268   // the two are equal only for redundant function/extern declarations
00269   if (create != shadowed  && CBZ::WarningLevel == 5) {
00270     CBZ::Warning(5, create->coord(),
00271                  string("`") + create->name() + string("' shadows previous declaration"));
00272     cerr << "\tPrevious declaration: " << shadowed->coord() << endl;
00273   }
00274 }
00275 
00276 void Identifiers_table::notify_exit_scope(declNode * var)
00277 {
00278   typeNode * type = var->type();
00279   assert(type);
00280 
00281   if (var->references() == 0 && type->typ() != Func) {
00282     if ((var->decl_location() == declNode::BLOCK) &&
00283         (var->storage_class() != declNode::EXTERN))
00284       CBZ::Warning(5, var->coord(), string("unused variable `") + var->name() + string("'"));
00285   }
00286 }
00287 
00288 void Labels_table::shadow(labelNode * create, labelNode * shadowed)
00289 {
00290 }
00291 
00292 void Labels_table::notify_exit_scope(labelNode * label)
00293 {
00294   if (label->is_undeclared())
00295     CBZ::SyntaxError(label->coord(),
00296                      string("undefined label `") + label->name() + string("'"));
00297 
00298   if (label->references().empty()) {
00299     if (label->coord().is_unknown() == false)
00300     CBZ::Warning(5, label->coord(), string("unreferenced label `") + 
00301                  label->name() + string("'"));
00302   }
00303 }
00304 
00305 void Tags_table::shadow(suespecNode * create, suespecNode * shadowed)
00306 {
00307   // the two are equal only for redundant function/extern declarations
00308   if (create != shadowed && CBZ::WarningLevel == 5) {
00309     CBZ::Warning(5, create->coord(),
00310                  string("struct/union/enum tag `") + create->name() + 
00311                  string("' shadows previous declaration"));
00312     cerr << "\tPrevious declaration: " << shadowed->coord() << endl;
00313   }
00314 }
00315 
00316 void Tags_table::notify_exit_scope(suespecNode * dead)
00317 {
00318 }
00319 
00320 void Externals_table::shadow(declNode * create, declNode * shadowed)
00321 {
00322 }
00323 
00324 void Externals_table::notify_exit_scope(declNode * var)
00325 {
00326   typeNode * type = var->type();
00327   assert(type);
00328 
00329   if (var->references() == 0 && type->typ() != Func) {
00330     if ((var->decl_location() == declNode::BLOCK) &&
00331         (var->storage_class() != declNode::EXTERN))
00332       CBZ::Warning(5, var->coord(), string("unused variable `") + var->name() + string("'"));
00333   }
00334 }
00335 
00336 // ------------------------------------------------------------
00337 //   Static symbol methods
00338 // ------------------------------------------------------------
00339 /*
00340 void Symbols::EnterScope()
00341 {
00342   Symbols::Identifiers->enter_scope();
00343   Symbols::Labels->enter_scope();
00344   Symbols::Tags->enter_scope();
00345   Symbols::Externals->enter_scope();
00346 
00347   Level++;
00348 }
00349 
00350 void Symbols::ExitScope()
00351 {
00352   if (Level == 0)
00353     CBZ::SyntaxError(string("missing '{' detected"));
00354   else {
00355 
00356     Symbols::Identifiers->exit_scope();
00357     Symbols::Labels->exit_scope();
00358     Symbols::Tags->exit_scope();
00359     Symbols::Externals->exit_scope();
00360 
00361     Level--;
00362   }
00363 }
00364 
00365 */
00366 
00367 // Force instantiation of the templates
00368 
00369 // stupid gcc needs to have these explicitly instantiated.
00370 // no help from the ANSI C++ standard; what good are templates then?
00371 // yeah, yeah. -- djimenez
00372 
00373 template class SymbolTable<declNode *>;
00374 template class SymbolTable<suespecNode *>;
00375 template class SymbolTable<labelNode *>;

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