// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // IdTable.cc -- // // Author : Richard C. Bilson // Created On : Sun May 17 17:04:02 2015 // Last Modified By : Rob Schluntz // Last Modified On : Wed Oct 07 12:21:13 2015 // Update Count : 73 // #include #include "SynTree/Declaration.h" #include "ResolvExpr/typeops.h" #include "Indexer.h" #include "Mangler.h" #include "IdTable.h" #include "SemanticError.h" using std::string; namespace SymTab { IdTable::IdTable() : scopeLevel( 0 ) { } void IdTable::enterScope() { scopeLevel++; } void IdTable::leaveScope() { for ( OuterTableType::iterator outer = table.begin(); outer != table.end(); ++outer ) { for ( InnerTableType::iterator inner = outer->second.begin(); inner != outer->second.end(); ++inner ) { std::stack< DeclEntry >& entry = inner->second; // xxx - should be while? if ( ! entry.empty() && entry.top().second == scopeLevel ) { entry.pop(); } // if } // for } // for scopeLevel--; assert( scopeLevel >= 0 ); } void IdTable::addDecl( DeclarationWithType *decl ) { const string &name = decl->get_name(); string manglename; if ( decl->get_linkage() == LinkageSpec::C ) { manglename = name; } else if ( LinkageSpec::isOverridable( decl->get_linkage() ) ) { // mangle the name without including the appropriate suffix // this will make it so that overridable routines are placed // into the same "bucket" as their user defined versions. manglename = Mangler::mangle( decl, false ); } else { manglename = Mangler::mangle( decl ); } // if InnerTableType &declTable = table[ name ]; InnerTableType::iterator it = declTable.find( manglename ); if ( it == declTable.end() ) { // first time this name mangling has been defined declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) ); } else { std::stack< DeclEntry >& entry = it->second; if ( ! entry.empty() && entry.top().second == scopeLevel ) { // if we're giving the same name mangling to things of // different types then there is something wrong Declaration *old = entry.top().first; assert( (dynamic_cast( decl ) && dynamic_cast( old ) ) || (dynamic_cast( decl ) && dynamic_cast( old ) ) ); if ( LinkageSpec::isOverridable( old->get_linkage() ) ) { // new definition shadows the autogenerated one, even at the same scope declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) ); } else if ( decl->get_linkage() != LinkageSpec::C || ResolvExpr::typesCompatible( decl->get_type(), entry.top().first->get_type(), Indexer() ) ) { // typesCompatible doesn't really do the right thing here. When checking compatibility of function types, // we should ignore outermost pointer qualifiers, except _Atomic? FunctionDecl *newentry = dynamic_cast< FunctionDecl* >( decl ); FunctionDecl *oldentry = dynamic_cast< FunctionDecl* >( old ); if ( newentry && oldentry ) { if ( newentry->get_statements() && oldentry->get_statements() ) { throw SemanticError( "duplicate function definition for 1 ", decl ); } // if } else { // two objects with the same mangled name defined in the same scope. // both objects must be marked extern or both must be intrinsic for this to be okay // xxx - perhaps it's actually if either is intrinsic then this is okay? // might also need to be same storage class? ObjectDecl *newobj = dynamic_cast< ObjectDecl* >( decl ); ObjectDecl *oldobj = dynamic_cast< ObjectDecl* >( old ); if (newobj->get_storageClass() != DeclarationNode::Extern && oldobj->get_storageClass() != DeclarationNode::Extern ) { throw SemanticError( "duplicate definition for 3 ", decl ); } // if } // if } else { throw SemanticError( "duplicate definition for ", decl ); } // if } else { // new scope level - shadow existing definition declTable[ manglename ].push( DeclEntry( decl, scopeLevel ) ); } // if } // if // this ensures that no two declarations with the same unmangled name both have C linkage for ( InnerTableType::iterator i = declTable.begin(); i != declTable.end(); ++i ) { if ( ! i->second.empty() && i->second.top().first->get_linkage() == LinkageSpec::C && declTable.size() > 1 ) { InnerTableType::iterator j = i; for ( j++; j != declTable.end(); ++j ) { if ( ! j->second.empty() && j->second.top().first->get_linkage() == LinkageSpec::C ) { throw SemanticError( "invalid overload of C function " ); } // if } // for } // if } // for } void IdTable::lookupId( const std::string &id, std::list< DeclarationWithType* >& decls ) const { OuterTableType::const_iterator outer = table.find( id ); if ( outer == table.end() ) return; const InnerTableType &declTable = outer->second; for ( InnerTableType::const_iterator it = declTable.begin(); it != declTable.end(); ++it ) { const std::stack< DeclEntry >& entry = it->second; if ( ! entry.empty() ) { decls.push_back( entry.top().first ); } // if } // for } DeclarationWithType * IdTable::lookupId( const std::string &id) const { DeclarationWithType* result = 0; int depth = -1; OuterTableType::const_iterator outer = table.find( id ); if ( outer == table.end() ) return 0; const InnerTableType &declTable = outer->second; for ( InnerTableType::const_iterator it = declTable.begin(); it != declTable.end(); ++it ) { const std::stack< DeclEntry >& entry = it->second; if ( ! entry.empty() && entry.top().second > depth ) { result = entry.top().first; depth = entry.top().second; } // if } // for return result; } void IdTable::dump( std::ostream &os ) const { for ( OuterTableType::const_iterator outer = table.begin(); outer != table.end(); ++outer ) { for ( InnerTableType::const_iterator inner = outer->second.begin(); inner != outer->second.end(); ++inner ) { #if 0 const std::stack< DeclEntry >& entry = inner->second; if ( ! entry.empty() ) { // && entry.top().second == scopeLevel ) { os << outer->first << " (" << inner->first << ") (" << entry.top().second << ")" << std::endl; } else { os << outer->first << " (" << inner->first << ") ( entry-empty)" << std::endl; } // if #endif #if 0 std::stack stack = inner->second; os << "dumping a stack" << std::endl; while ( ! stack.empty()) { DeclEntry d = stack.top(); os << outer->first << " (" << inner->first << ") (" << d.second << ") " << std::endl; stack.pop(); } // while #endif } // for } // for #if 0 for ( OuterTableType::const_iterator outer = table.begin(); outer != table.end(); ++outer ) { for ( InnerTableType::const_iterator inner = outer->second.begin(); inner != outer->second.end(); ++inner ) { const std::stack< DeclEntry >& entry = inner->second; if ( ! entry.empty() && entry.top().second == scopeLevel ) { os << outer->first << " (" << inner->first << ") (" << scopeLevel << ")" << std::endl; } // if } // for } // for #endif } } // namespace SymTab // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //