Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Indexer.cc

    rafc1045 r2a4b088  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 21:37:33 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Mar  2 17:31:29 2016
    13 // Update Count     : 11
    14 //
    15 
    16 #include "Indexer.h"
    17 
    18 #include <string>
    19 #include <typeinfo>
    20 #include <unordered_map>
    21 #include <unordered_set>
    22 #include <utility>
    23 
    24 #include "Mangler.h"
    25 
    26 #include "Common/utility.h"
    27 
    28 #include "ResolvExpr/typeops.h"
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Wed Aug 05 13:52:42 2015
     13// Update Count     : 10
     14//
    2915
    3016#include "SynTree/Declaration.h"
     
    3319#include "SynTree/Initializer.h"
    3420#include "SynTree/Statement.h"
     21#include "Indexer.h"
     22#include <typeinfo>
     23#include "Common/utility.h"
    3524
    3625#define debugPrint(x) if ( doDebug ) { std::cout << x; }
     
    4433        }
    4534
    46         typedef std::unordered_map< std::string, DeclarationWithType* > MangleTable;
    47         typedef std::unordered_map< std::string, MangleTable > IdTable;
    48         typedef std::unordered_map< std::string, NamedTypeDecl* > TypeTable;
    49         typedef std::unordered_map< std::string, StructDecl* > StructTable;
    50         typedef std::unordered_map< std::string, EnumDecl* > EnumTable;
    51         typedef std::unordered_map< std::string, UnionDecl* > UnionTable;
    52         typedef std::unordered_map< std::string, TraitDecl* > TraitTable;
    53 
    54         void dump( const IdTable &table, std::ostream &os ) {
    55                 for ( IdTable::const_iterator id = table.begin(); id != table.end(); ++id ) {
    56                         for ( MangleTable::const_iterator mangle = id->second.begin(); mangle != id->second.end(); ++mangle ) {
    57                                 os << mangle->second << std::endl;
    58                         }
    59                 }
    60         }
    61        
    62         template< typename Decl >
    63         void dump( const std::unordered_map< std::string, Decl* > &table, std::ostream &os ) {
    64                 for ( typename std::unordered_map< std::string, Decl* >::const_iterator it = table.begin(); it != table.end(); ++it ) {
    65                         os << it->second << std::endl;
    66                 } // for
    67         }
    68        
    69         struct Indexer::Impl {
    70                 Impl( unsigned long _scope ) : refCount(1), scope( _scope ), size( 0 ), base(),
    71                                 idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
    72                 Impl( unsigned long _scope, Indexer &&_base ) : refCount(1), scope( _scope ), size( 0 ), base( _base ),
    73                                 idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
    74                 unsigned long refCount;   ///< Number of references to these tables
    75                 unsigned long scope;      ///< Scope these tables are associated with
    76                 unsigned long size;       ///< Number of elements stored in this table
    77                 const Indexer base;       ///< Base indexer this extends
    78                
    79                 IdTable idTable;          ///< Identifier namespace
    80                 TypeTable typeTable;      ///< Type namespace
    81                 StructTable structTable;  ///< Struct namespace
    82                 EnumTable enumTable;      ///< Enum namespace
    83                 UnionTable unionTable;    ///< Union namespace
    84                 TraitTable traitTable;    ///< Trait namespace
    85         };
    86 
    87         Indexer::Impl *Indexer::newRef( Indexer::Impl *toClone ) {
    88                 if ( ! toClone ) return 0;
    89 
    90                 // shorten the search chain by skipping empty links
    91                 Indexer::Impl *ret = toClone->size == 0 ? toClone->base.tables : toClone;
    92                 if ( ret ) { ++ret->refCount; }
    93 
    94                 return ret;
    95         }
    96 
    97         void Indexer::deleteRef( Indexer::Impl *toFree ) {
    98                 if ( ! toFree ) return;
    99 
    100                 if ( --toFree->refCount == 0 ) delete toFree;
    101         }
    102 
    103         void Indexer::makeWritable() {
    104                 if ( ! tables ) {
    105                         // create indexer if not yet set
    106                         tables = new Indexer::Impl( scope );
    107                 } else if ( tables->refCount > 1 || tables->scope != scope ) {
    108                         // make this indexer the base of a fresh indexer at the current scope
    109                         tables = new Indexer::Impl( scope, std::move( *this ) );
    110                 }
    111         }
    112 
    113         Indexer::Indexer( bool _doDebug ) : tables( 0 ), scope( 0 ), doDebug( _doDebug ) {}
    114 
    115         Indexer::Indexer( const Indexer &that ) : tables( newRef( that.tables ) ), scope( that.scope ), doDebug( that.doDebug ) {}
    116 
    117         Indexer::Indexer( Indexer &&that ) : tables( that.tables ), scope( that.scope ), doDebug( that.doDebug ) {
    118                 that.tables = 0;
    119         }
    120 
    121         Indexer::~Indexer() {
    122                 deleteRef( tables );
    123         }
    124 
    125         Indexer& Indexer::operator= ( const Indexer &that ) {
    126                 deleteRef( tables );
    127 
    128                 tables = newRef( that.tables );
    129                 scope = that.scope;
    130                 doDebug = that.doDebug;
    131 
    132                 return *this;
    133         }
    134 
    135         Indexer& Indexer::operator= ( Indexer &&that ) {
    136                 deleteRef( tables );
    137 
    138                 tables = that.tables;
    139                 scope = that.scope;
    140                 doDebug = that.doDebug;
    141 
    142                 that.tables = 0;
    143 
    144                 return *this;
    145         }
     35        Indexer::Indexer( bool useDebug ) : doDebug( useDebug ) {}
     36
     37        Indexer::~Indexer() {}
    14638
    14739        void Indexer::visit( ObjectDecl *objectDecl ) {
     
    15345                if ( objectDecl->get_name() != "" ) {
    15446                        debugPrint( "Adding object " << objectDecl->get_name() << std::endl );
    155                         addId( objectDecl );
     47                        idTable.addDecl( objectDecl );
    15648                } // if
    15749        }
     
    16052                if ( functionDecl->get_name() == "" ) return;
    16153                debugPrint( "Adding function " << functionDecl->get_name() << std::endl );
    162                 addId( functionDecl );
     54                idTable.addDecl( functionDecl );
    16355                enterScope();
    16456                maybeAccept( functionDecl->get_functionType(), *this );
     
    19890                leaveScope();
    19991                debugPrint( "Adding type " << typeDecl->get_name() << std::endl );
    200                 addType( typeDecl );
     92                typeTable.add( typeDecl );
    20193                acceptAll( typeDecl->get_assertions(), *this );
    20294        }
     
    208100                leaveScope();
    209101                debugPrint( "Adding typedef " << typeDecl->get_name() << std::endl );
    210                 addType( typeDecl );
     102                typeTable.add( typeDecl );
    211103        }
    212104
     
    216108                cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
    217109                debugPrint( "Adding fwd decl for struct " << fwdDecl.get_name() << std::endl );
    218                 addStruct( &fwdDecl );
     110                structTable.add( &fwdDecl );
    219111 
    220112                enterScope();
     
    225117                debugPrint( "Adding struct " << aggregateDecl->get_name() << std::endl );
    226118                // this addition replaces the forward declaration
    227                 addStruct( aggregateDecl );
     119                structTable.add( aggregateDecl );
    228120        }
    229121
     
    233125                cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
    234126                debugPrint( "Adding fwd decl for union " << fwdDecl.get_name() << std::endl );
    235                 addUnion( &fwdDecl );
     127                unionTable.add( &fwdDecl );
    236128 
    237129                enterScope();
     
    241133 
    242134                debugPrint( "Adding union " << aggregateDecl->get_name() << std::endl );
    243                 addUnion( aggregateDecl );
     135                unionTable.add( aggregateDecl );
    244136        }
    245137
    246138        void Indexer::visit( EnumDecl *aggregateDecl ) {
    247139                debugPrint( "Adding enum " << aggregateDecl->get_name() << std::endl );
    248                 addEnum( aggregateDecl );
     140                enumTable.add( aggregateDecl );
    249141                // unlike structs, contexts, and unions, enums inject their members into the global scope
    250142                acceptAll( aggregateDecl->get_members(), *this );
    251143        }
    252144
    253         void Indexer::visit( TraitDecl *aggregateDecl ) {
     145        void Indexer::visit( ContextDecl *aggregateDecl ) {
    254146                enterScope();
    255147                acceptAll( aggregateDecl->get_parameters(), *this );
     
    258150 
    259151                debugPrint( "Adding context " << aggregateDecl->get_name() << std::endl );
    260                 addTrait( aggregateDecl );
     152                contextTable.add( aggregateDecl );
    261153        }
    262154
     
    346238        }
    347239
    348         void Indexer::visit( OffsetPackExpr *offsetPackExpr ) {
    349                 acceptAllNewScope( offsetPackExpr->get_results(), *this );
    350                 maybeAccept( offsetPackExpr->get_type(), *this );
    351         }
    352 
    353240        void Indexer::visit( AttrExpr *attrExpr ) {
    354241                acceptAllNewScope( attrExpr->get_results(), *this );
     
    406293
    407294
    408         void Indexer::visit( TraitInstType *contextInst ) {
     295        void Indexer::visit( ContextInstType *contextInst ) {
    409296                acceptAll( contextInst->get_parameters(), *this );
    410297                acceptAll( contextInst->get_members(), *this );
     
    412299
    413300        void Indexer::visit( StructInstType *structInst ) {
    414                 if ( ! lookupStruct( structInst->get_name() ) ) {
     301                if ( ! structTable.lookup( structInst->get_name() ) ) {
    415302                        debugPrint( "Adding struct " << structInst->get_name() << " from implicit forward declaration" << std::endl );
    416                         addStruct( structInst->get_name() );
     303                        structTable.add( structInst->get_name() );
    417304                }
    418305                enterScope();
     
    422309
    423310        void Indexer::visit( UnionInstType *unionInst ) {
    424                 if ( ! lookupUnion( unionInst->get_name() ) ) {
     311                if ( ! unionTable.lookup( unionInst->get_name() ) ) {
    425312                        debugPrint( "Adding union " << unionInst->get_name() << " from implicit forward declaration" << std::endl );
    426                         addUnion( unionInst->get_name() );
     313                        unionTable.add( unionInst->get_name() );
    427314                }
    428315                enterScope();
     
    438325        }
    439326
    440        
    441 
    442         void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &out ) const {
    443                 std::unordered_set< std::string > foundMangleNames;
    444                
    445                 Indexer::Impl *searchTables = tables;
    446                 while ( searchTables ) {
    447 
    448                         IdTable::const_iterator decls = searchTables->idTable.find( id );
    449                         if ( decls != searchTables->idTable.end() ) {
    450                                 const MangleTable &mangleTable = decls->second;
    451                                 for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
    452                                         // mark the mangled name as found, skipping this insertion if a declaration for that name has already been found
    453                                         if ( foundMangleNames.insert( decl->first ).second == false ) continue;
    454                                        
    455                                         out.push_back( decl->second );
    456                                 }
    457                         }
    458                        
    459                         // get declarations from base indexers
    460                         searchTables = searchTables->base.tables;
    461                 }
     327
     328        void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &list ) const {
     329                idTable.lookupId( id, list );
     330        }
     331
     332        DeclarationWithType* Indexer::lookupId( const std::string &id) const {
     333                return idTable.lookupId(id);
    462334        }
    463335
    464336        NamedTypeDecl *Indexer::lookupType( const std::string &id ) const {
    465                 if ( ! tables ) return 0;
    466 
    467                 TypeTable::const_iterator ret = tables->typeTable.find( id );
    468                 return ret != tables->typeTable.end() ? ret->second : tables->base.lookupType( id );
     337                return typeTable.lookup( id );
    469338        }
    470339
    471340        StructDecl *Indexer::lookupStruct( const std::string &id ) const {
    472                 if ( ! tables ) return 0;
    473 
    474                 StructTable::const_iterator ret = tables->structTable.find( id );
    475                 return ret != tables->structTable.end() ? ret->second : tables->base.lookupStruct( id );
     341                return structTable.lookup( id );
    476342        }
    477343
    478344        EnumDecl *Indexer::lookupEnum( const std::string &id ) const {
    479                 if ( ! tables ) return 0;
    480 
    481                 EnumTable::const_iterator ret = tables->enumTable.find( id );
    482                 return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnum( id );
     345                return enumTable.lookup( id );
    483346        }
    484347
    485348        UnionDecl *Indexer::lookupUnion( const std::string &id ) const {
    486                 if ( ! tables ) return 0;
    487 
    488                 UnionTable::const_iterator ret = tables->unionTable.find( id );
    489                 return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnion( id );
    490         }
    491 
    492         TraitDecl *Indexer::lookupTrait( const std::string &id ) const {
    493                 if ( ! tables ) return 0;
    494 
    495                 TraitTable::const_iterator ret = tables->traitTable.find( id );
    496                 return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTrait( id );
    497         }
    498 
    499         DeclarationWithType *Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
    500                 if ( ! tables ) return 0;
    501                 if ( tables->scope < scope ) return 0;
    502 
    503                 IdTable::const_iterator decls = tables->idTable.find( id );
    504                 if ( decls != tables->idTable.end() ) {
    505                         const MangleTable &mangleTable = decls->second;
    506                         MangleTable::const_iterator decl = mangleTable.find( mangleName );
    507                         if ( decl != mangleTable.end() ) return decl->second;
    508                 }
    509 
    510                 return tables->base.lookupIdAtScope( id, mangleName, scope );
    511         }
    512 
    513         bool Indexer::hasIncompatibleCDecl( const std::string &id, const std::string &mangleName ) const {
    514                 if ( ! tables ) return false;
    515 
    516                 IdTable::const_iterator decls = tables->idTable.find( id );
    517                 if ( decls != tables->idTable.end() ) {
    518                         const MangleTable &mangleTable = decls->second;
    519                         for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
    520                                 // check for C decls with the same name, skipping
    521                                 // those with a compatible type (by mangleName)
    522                                 if ( decl->second->get_linkage() == LinkageSpec::C && decl->first != mangleName ) return true;
    523                         }
    524                 }
    525 
    526                 return tables->base.hasIncompatibleCDecl( id, mangleName );
    527         }
    528        
    529         NamedTypeDecl *Indexer::lookupTypeAtScope( const std::string &id, unsigned long scope ) const {
    530                 if ( ! tables ) return 0;
    531                 if ( tables->scope < scope ) return 0;
    532 
    533                 TypeTable::const_iterator ret = tables->typeTable.find( id );
    534                 return ret != tables->typeTable.end() ? ret->second : tables->base.lookupTypeAtScope( id, scope );
    535         }
    536        
    537         StructDecl *Indexer::lookupStructAtScope( const std::string &id, unsigned long scope ) const {
    538                 if ( ! tables ) return 0;
    539                 if ( tables->scope < scope ) return 0;
    540 
    541                 StructTable::const_iterator ret = tables->structTable.find( id );
    542                 return ret != tables->structTable.end() ? ret->second : tables->base.lookupStructAtScope( id, scope );
    543         }
    544        
    545         EnumDecl *Indexer::lookupEnumAtScope( const std::string &id, unsigned long scope ) const {
    546                 if ( ! tables ) return 0;
    547                 if ( tables->scope < scope ) return 0;
    548 
    549                 EnumTable::const_iterator ret = tables->enumTable.find( id );
    550                 return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnumAtScope( id, scope );
    551         }
    552        
    553         UnionDecl *Indexer::lookupUnionAtScope( const std::string &id, unsigned long scope ) const {
    554                 if ( ! tables ) return 0;
    555                 if ( tables->scope < scope ) return 0;
    556 
    557                 UnionTable::const_iterator ret = tables->unionTable.find( id );
    558                 return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnionAtScope( id, scope );
    559         }
    560        
    561         TraitDecl *Indexer::lookupTraitAtScope( const std::string &id, unsigned long scope ) const {
    562                 if ( ! tables ) return 0;
    563                 if ( tables->scope < scope ) return 0;
    564 
    565                 TraitTable::const_iterator ret = tables->traitTable.find( id );
    566                 return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTraitAtScope( id, scope );
    567         }
    568 
    569         bool addedIdConflicts( DeclarationWithType *existing, DeclarationWithType *added ) {
    570                 // if we're giving the same name mangling to things of different types then there is something wrong
    571                 assert( (dynamic_cast<ObjectDecl*>( added ) && dynamic_cast<ObjectDecl*>( existing ) )
    572                         || (dynamic_cast<FunctionDecl*>( added ) && dynamic_cast<FunctionDecl*>( existing ) ) );
    573 
    574                 if ( LinkageSpec::isOverridable( existing->get_linkage() ) ) {
    575                         // new definition shadows the autogenerated one, even at the same scope
    576                         return false;
    577                 } else if ( added->get_linkage() != LinkageSpec::C || ResolvExpr::typesCompatible( added->get_type(), existing->get_type(), Indexer() ) ) {
    578                         // typesCompatible doesn't really do the right thing here. When checking compatibility of function types,
    579                         // we should ignore outermost pointer qualifiers, except _Atomic?
    580                         FunctionDecl *newentry = dynamic_cast< FunctionDecl* >( added );
    581                         FunctionDecl *oldentry = dynamic_cast< FunctionDecl* >( existing );
    582                         if ( newentry && oldentry ) {
    583                                 if ( newentry->get_statements() && oldentry->get_statements() ) {
    584                                         throw SemanticError( "duplicate function definition for ", added );
    585                                 } // if
    586                         } else {
    587                                 // two objects with the same mangled name defined in the same scope.
    588                                 // both objects must be marked extern or both must be intrinsic for this to be okay
    589                                 // xxx - perhaps it's actually if either is intrinsic then this is okay?
    590                                 //       might also need to be same storage class?
    591                                 ObjectDecl *newobj = dynamic_cast< ObjectDecl* >( added );
    592                                 ObjectDecl *oldobj = dynamic_cast< ObjectDecl* >( existing );
    593                                 if ( newobj->get_storageClass() != DeclarationNode::Extern && oldobj->get_storageClass() != DeclarationNode::Extern ) {
    594                                         throw SemanticError( "duplicate object definition for ", added );
    595                                 } // if
    596                         } // if
    597                 } else {
    598                         throw SemanticError( "duplicate definition for ", added );
    599                 } // if
    600 
    601                 return true;
    602         }
    603        
    604         void Indexer::addId( DeclarationWithType *decl ) {
    605                 makeWritable();
    606 
    607                 const std::string &name = decl->get_name();
    608                 std::string mangleName;
    609                 if ( LinkageSpec::isOverridable( decl->get_linkage() ) ) {
    610                         // mangle the name without including the appropriate suffix, so overridable routines are placed into the
    611                         // same "bucket" as their user defined versions.
    612                         mangleName = Mangler::mangle( decl, false );
    613                 } else {
    614                         mangleName = Mangler::mangle( decl );
    615                 } // if
    616 
    617                 DeclarationWithType *existing = lookupIdAtScope( name, mangleName, scope );
    618                 if ( ! existing || ! addedIdConflicts( existing, decl ) ) {
    619                         // this ensures that no two declarations with the same unmangled name both have C linkage
    620                         if ( decl->get_linkage() == LinkageSpec::C && hasIncompatibleCDecl( name, mangleName ) ) {
    621                                 throw SemanticError( "invalid overload of C function ", decl );
    622                         } // NOTE this is broken in Richard's original code in such a way that it never triggers (it
    623                           // doesn't check decls that have the same manglename, and all C-linkage decls are defined to
    624                           // have their name as their manglename, hence the error can never trigger).
    625                           // The code here is closer to correct, but name mangling would have to be completely
    626                           // isomorphic to C type-compatibility, which it may not be.
    627                        
    628                         tables->idTable[ name ][ mangleName ] = decl;
    629                         ++tables->size;
    630                 }
    631         }
    632 
    633         bool addedTypeConflicts( NamedTypeDecl *existing, NamedTypeDecl *added ) {
    634                 if ( existing->get_base() == 0 ) {
    635                         return false;
    636                 } else if ( added->get_base() == 0 ) {
    637                         return true;
    638                 } else {
    639                         throw SemanticError( "redeclaration of ", added );
    640                 }
    641         }
    642        
    643         void Indexer::addType( NamedTypeDecl *decl ) {
    644                 makeWritable();
    645 
    646                 const std::string &id = decl->get_name();
    647                 TypeTable::iterator existing = tables->typeTable.find( id );
    648                 if ( existing == tables->typeTable.end() ) {
    649                         NamedTypeDecl *parent = tables->base.lookupTypeAtScope( id, scope );
    650                         if ( ! parent || ! addedTypeConflicts( parent, decl ) ) {
    651                                 tables->typeTable.insert( existing, std::make_pair( id, decl ) );
    652                                 ++tables->size;
    653                         }
    654                 } else {
    655                         if ( ! addedTypeConflicts( existing->second, decl ) ) {
    656                                 existing->second = decl;
    657                         }
    658                 }
    659         }
    660 
    661         bool addedDeclConflicts( AggregateDecl *existing, AggregateDecl *added ) {
    662                 if ( existing->get_members().empty() ) {
    663                         return false;
    664                 } else if ( ! added->get_members().empty() ) {
    665                         throw SemanticError( "redeclaration of ", added );
    666                 } // if
    667                 return true;
    668         }
    669 
    670         void Indexer::addStruct( const std::string &id ) {
    671                 addStruct( new StructDecl( id ) );
    672         }
    673        
    674         void Indexer::addStruct( StructDecl *decl ) {
    675                 makeWritable();
    676 
    677                 const std::string &id = decl->get_name();
    678                 StructTable::iterator existing = tables->structTable.find( id );
    679                 if ( existing == tables->structTable.end() ) {
    680                         StructDecl *parent = tables->base.lookupStructAtScope( id, scope );
    681                         if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
    682                                 tables->structTable.insert( existing, std::make_pair( id, decl ) );
    683                                 ++tables->size;
    684                         }
    685                 } else {
    686                         if ( ! addedDeclConflicts( existing->second, decl ) ) {
    687                                 existing->second = decl;
    688                         }
    689                 }
    690         }
    691        
    692         void Indexer::addEnum( EnumDecl *decl ) {
    693                 makeWritable();
    694 
    695                 const std::string &id = decl->get_name();
    696                 EnumTable::iterator existing = tables->enumTable.find( id );
    697                 if ( existing == tables->enumTable.end() ) {
    698                         EnumDecl *parent = tables->base.lookupEnumAtScope( id, scope );
    699                         if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
    700                                 tables->enumTable.insert( existing, std::make_pair( id, decl ) );
    701                                 ++tables->size;
    702                         }
    703                 } else {
    704                         if ( ! addedDeclConflicts( existing->second, decl ) ) {
    705                                 existing->second = decl;
    706                         }
    707                 }
    708         }
    709 
    710         void Indexer::addUnion( const std::string &id ) {
    711                 addUnion( new UnionDecl( id ) );
    712         }
    713        
    714         void Indexer::addUnion( UnionDecl *decl ) {
    715                 makeWritable();
    716 
    717                 const std::string &id = decl->get_name();
    718                 UnionTable::iterator existing = tables->unionTable.find( id );
    719                 if ( existing == tables->unionTable.end() ) {
    720                         UnionDecl *parent = tables->base.lookupUnionAtScope( id, scope );
    721                         if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
    722                                 tables->unionTable.insert( existing, std::make_pair( id, decl ) );
    723                                 ++tables->size;
    724                         }
    725                 } else {
    726                         if ( ! addedDeclConflicts( existing->second, decl ) ) {
    727                                 existing->second = decl;
    728                         }
    729                 }
    730         }
    731        
    732         void Indexer::addTrait( TraitDecl *decl ) {
    733                 makeWritable();
    734 
    735                 const std::string &id = decl->get_name();
    736                 TraitTable::iterator existing = tables->traitTable.find( id );
    737                 if ( existing == tables->traitTable.end() ) {
    738                         TraitDecl *parent = tables->base.lookupTraitAtScope( id, scope );
    739                         if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
    740                                 tables->traitTable.insert( existing, std::make_pair( id, decl ) );
    741                                 ++tables->size;
    742                         }
    743                 } else {
    744                         if ( ! addedDeclConflicts( existing->second, decl ) ) {
    745                                 existing->second = decl;
    746                         }
    747                 }
     349                return unionTable.lookup( id );
     350        }
     351
     352        ContextDecl  * Indexer::lookupContext( const std::string &id ) const {
     353                return contextTable.lookup( id );
    748354        }
    749355
    750356        void Indexer::enterScope() {
    751                 ++scope;
    752                
    753357                if ( doDebug ) {
    754                         std::cout << "--- Entering scope " << scope << std::endl;
    755                 }
     358                        std::cout << "--- Entering scope" << std::endl;
     359                }
     360                idTable.enterScope();
     361                typeTable.enterScope();
     362                structTable.enterScope();
     363                enumTable.enterScope();
     364                unionTable.enterScope();
     365                contextTable.enterScope();
    756366        }
    757367
    758368        void Indexer::leaveScope() {
    759369                using std::cout;
    760 
    761                 assert( scope > 0 && "cannot leave initial scope" );
    762                 --scope;
    763 
    764                 while ( tables && tables->scope > scope ) {
    765                         if ( doDebug ) {
    766                                 cout << "--- Leaving scope " << tables->scope << " containing" << std::endl;
    767                                 dump( tables->idTable, cout );
    768                                 dump( tables->typeTable, cout );
    769                                 dump( tables->structTable, cout );
    770                                 dump( tables->enumTable, cout );
    771                                 dump( tables->unionTable, cout );
    772                                 dump( tables->traitTable, cout );
    773                         }
    774 
    775                         // swap tables for base table until we find one at an appropriate scope
    776                         Indexer::Impl *base = newRef( tables->base.tables );
    777                         deleteRef( tables );
    778                         tables = base;
    779                 }
     370                using std::endl;
     371 
     372                if ( doDebug ) {
     373                        cout << "--- Leaving scope containing" << endl;
     374                        idTable.dump( cout );
     375                        typeTable.dump( cout );
     376                        structTable.dump( cout );
     377                        enumTable.dump( cout );
     378                        unionTable.dump( cout );
     379                        contextTable.dump( cout );
     380                }
     381                idTable.leaveScope();
     382                typeTable.leaveScope();
     383                structTable.leaveScope();
     384                enumTable.leaveScope();
     385                unionTable.leaveScope();
     386                contextTable.leaveScope();
    780387        }
    781388
    782389        void Indexer::print( std::ostream &os, int indent ) const {
    783390            using std::cerr;
    784 
    785             cerr << "===idTable===" << std::endl;
    786             if ( tables ) dump( tables->idTable, os );
    787             cerr << "===typeTable===" << std::endl;
    788             if ( tables ) dump( tables->typeTable, os );
    789             cerr << "===structTable===" << std::endl;
    790             if ( tables ) dump( tables->structTable, os );
    791             cerr << "===enumTable===" << std::endl;
    792             if ( tables ) dump( tables->enumTable, os );
    793             cerr << "===unionTable===" << std::endl;
    794             if ( tables ) dump( tables->unionTable, os );
    795             cerr << "===contextTable===" << std::endl;
    796             if ( tables ) dump( tables->traitTable, os );
     391            using std::endl;
     392
     393            cerr << "===idTable===" << endl;
     394            idTable.dump( os );
     395            cerr << "===typeTable===" << endl;
     396            typeTable.dump( os );
     397            cerr << "===structTable===" << endl;
     398            structTable.dump( os );
     399            cerr << "===enumTable===" << endl;
     400            enumTable.dump( os );
     401            cerr << "===unionTable===" << endl;
     402            unionTable.dump( os );
     403            cerr << "===contextTable===" << endl;
     404            contextTable.dump( os );
     405#if 0
     406                idTable.dump( os );
     407                typeTable.dump( os );
     408                structTable.dump( os );
     409                enumTable.dump( os );
     410                unionTable.dump( os );
     411                contextTable.dump( os );
     412#endif
    797413        }
    798414} // namespace SymTab
Note: See TracChangeset for help on using the changeset viewer.