Changeset 0ac366b


Ignore:
Timestamp:
Feb 15, 2018, 11:39:12 AM (7 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
4a161be
Parents:
f5883bd
Message:

Add Indexer support for deleting identifiers

Location:
src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/Common/PassVisitor.h

    rf5883bd r0ac366b  
    305305        void indexerAddUnionFwd ( UnionDecl                 * node  ) { indexer_impl_addUnionFwd ( pass, 0, node ); }
    306306        void indexerAddTrait    ( TraitDecl                 * node  ) { indexer_impl_addTrait    ( pass, 0, node ); }
    307         void indexerAddWith     ( std::list< Expression * > & exprs ) { indexer_impl_addWith     ( pass, 0, exprs ); }
     307        void indexerAddWith     ( std::list< Expression * > & exprs, BaseSyntaxNode * withStmt ) { indexer_impl_addWith     ( pass, 0, exprs, withStmt ); }
    308308
    309309
  • src/Common/PassVisitor.impl.h

    rf5883bd r0ac366b  
    398398                // shadow with exprs and not the other way around.
    399399                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    400                 indexerAddWith( node->withExprs );
     400                indexerAddWith( node->withExprs, node );
    401401                {
    402402                        auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     
    428428                // shadow with exprs and not the other way around.
    429429                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    430                 indexerAddWith( node->withExprs );
     430                indexerAddWith( node->withExprs, node );
    431431                {
    432432                        auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
     
    10691069                // catch statements introduce a level of scope (for the caught exception)
    10701070                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1071                 indexerAddWith( node->exprs );
     1071                indexerAddWith( node->exprs, node );
    10721072                maybeAccept_impl( node->stmt, *this );
    10731073        }
     
    10821082                // catch statements introduce a level of scope (for the caught exception)
    10831083                auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
    1084                 indexerAddWith( node->exprs );
     1084                indexerAddWith( node->exprs, node );
    10851085                maybeMutate_impl( node->stmt, *this );
    10861086        }
  • src/Common/PassVisitor.proto.h

    rf5883bd r0ac366b  
    193193
    194194
    195 #define INDEXER_FUNC( func, type )                                                                                             \
     195#define INDEXER_FUNC1( func, type )                                                                                             \
    196196template<typename pass_type>                                                                                                   \
    197197static inline auto indexer_impl_##func ( pass_type & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {   \
     
    202202static inline void indexer_impl_##func ( pass_type &, long, type ) { }                                                          \
    203203
    204 INDEXER_FUNC( addId     , DeclarationWithType *       );
    205 INDEXER_FUNC( addType   , NamedTypeDecl *             );
    206 INDEXER_FUNC( addStruct , StructDecl *                );
    207 INDEXER_FUNC( addEnum   , EnumDecl *                  );
    208 INDEXER_FUNC( addUnion  , UnionDecl *                 );
    209 INDEXER_FUNC( addTrait  , TraitDecl *                 );
    210 INDEXER_FUNC( addWith   , std::list< Expression * > & );
     204#define INDEXER_FUNC2( func, type1, type2 )                                                                                             \
     205template<typename pass_type>                                                                                                   \
     206static inline auto indexer_impl_##func ( pass_type & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.indexer.func( arg1, arg2 ), void() ) {   \
     207        pass.indexer.func( arg1, arg2 );                                                                                                \
     208}                                                                                                                              \
     209                                                                                                                               \
     210template<typename pass_type>                                                                                                   \
     211static inline void indexer_impl_##func ( pass_type &, long, type1, type2 ) { }
     212
     213
     214INDEXER_FUNC1( addId     , DeclarationWithType *       );
     215INDEXER_FUNC1( addType   , NamedTypeDecl *             );
     216INDEXER_FUNC1( addStruct , StructDecl *                );
     217INDEXER_FUNC1( addEnum   , EnumDecl *                  );
     218INDEXER_FUNC1( addUnion  , UnionDecl *                 );
     219INDEXER_FUNC1( addTrait  , TraitDecl *                 );
     220INDEXER_FUNC2( addWith   , std::list< Expression * > &, BaseSyntaxNode * );
    211221
    212222
  • src/SymTab/Indexer.cc

    rf5883bd r0ac366b  
    286286        }
    287287
    288         DeclarationWithType *Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
    289                 if ( ! tables ) return 0;
    290                 if ( tables->scope < scope ) return 0;
     288        const Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
     289                if ( ! tables ) return nullptr;
     290                if ( tables->scope < scope ) return nullptr;
    291291
    292292                IdTable::const_iterator decls = tables->idTable.find( id );
     
    294294                        const MangleTable &mangleTable = decls->second;
    295295                        MangleTable::const_iterator decl = mangleTable.find( mangleName );
    296                         if ( decl != mangleTable.end() ) return decl->second.id;
     296                        if ( decl != mangleTable.end() ) return &decl->second;
    297297                }
    298298
    299299                return tables->base.lookupIdAtScope( id, mangleName, scope );
     300        }
     301
     302        Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) {
     303                return const_cast<IdData *>(const_cast<const Indexer *>(this)->lookupIdAtScope( id, mangleName, scope ));
    300304        }
    301305
     
    373377        }
    374378
    375         bool addedIdConflicts( DeclarationWithType *existing, DeclarationWithType *added ) {
     379        bool addedIdConflicts( Indexer::IdData & existing, DeclarationWithType *added, BaseSyntaxNode * deleteStmt, Indexer::ConflictFunction handleConflicts ) {
    376380                // if we're giving the same name mangling to things of different types then there is something wrong
    377                 assert( (dynamic_cast<ObjectDecl*>( added ) && dynamic_cast<ObjectDecl*>( existing ) )
    378                         || (dynamic_cast<FunctionDecl*>( added ) && dynamic_cast<FunctionDecl*>( existing ) ) );
    379 
    380                 if ( LinkageSpec::isOverridable( existing->get_linkage() ) ) {
     381                assert( (dynamic_cast<ObjectDecl*>( added ) && dynamic_cast<ObjectDecl*>( existing.id ) )
     382                        || (dynamic_cast<FunctionDecl*>( added ) && dynamic_cast<FunctionDecl*>( existing.id ) ) );
     383
     384                if ( LinkageSpec::isOverridable( existing.id->get_linkage() ) ) {
    381385                        // new definition shadows the autogenerated one, even at the same scope
    382386                        return false;
    383                 } else if ( LinkageSpec::isMangled( added->get_linkage() ) || ResolvExpr::typesCompatible( added->get_type(), existing->get_type(), Indexer() ) ) {
     387                } else if ( LinkageSpec::isMangled( added->get_linkage() ) || ResolvExpr::typesCompatible( added->get_type(), existing.id->get_type(), Indexer() ) ) {
     388
     389                        // it is a conflict if one declaration is deleted and the other is not
     390                        if ( deleteStmt && ! existing.deleteStmt ) {
     391                                return handleConflicts( existing, "deletion of defined identifier " );
     392                        } else if ( ! deleteStmt && existing.deleteStmt ) {
     393                                return handleConflicts( existing, "definition of deleted identifier " );
     394                        }
     395
    384396                        // typesCompatible doesn't really do the right thing here. When checking compatibility of function types,
    385397                        // we should ignore outermost pointer qualifiers, except _Atomic?
    386                         FunctionDecl *newentry = dynamic_cast< FunctionDecl* >( added );
    387                         FunctionDecl *oldentry = dynamic_cast< FunctionDecl* >( existing );
     398                        FunctionDecl * newentry = dynamic_cast< FunctionDecl * >( added );
     399                        FunctionDecl * oldentry = dynamic_cast< FunctionDecl * >( existing.id );
    388400                        if ( newentry && oldentry ) {
    389401                                if ( newentry->get_statements() && oldentry->get_statements() ) {
    390                                         throw SemanticError( "duplicate function definition for ", added );
     402                                        return handleConflicts( existing, "duplicate function definition for " );
    391403                                } // if
    392404                        } else {
     
    395407                                // xxx - perhaps it's actually if either is intrinsic then this is okay?
    396408                                //       might also need to be same storage class?
    397                                 ObjectDecl *newobj = dynamic_cast< ObjectDecl* >( added );
    398                                 ObjectDecl *oldobj = dynamic_cast< ObjectDecl* >( existing );
     409                                ObjectDecl * newobj = dynamic_cast< ObjectDecl * >( added );
     410                                ObjectDecl * oldobj = dynamic_cast< ObjectDecl * >( existing.id );
    399411                                if ( ! newobj->get_storageClasses().is_extern && ! oldobj->get_storageClasses().is_extern ) {
    400                                         throw SemanticError( "duplicate object definition for ", added );
     412                                        return handleConflicts( existing, "duplicate object definition for " );
    401413                                } // if
    402414                        } // if
    403415                } else {
    404                         throw SemanticError( "duplicate definition for ", added );
     416                        return handleConflicts( existing, "duplicate definition for " );
    405417                } // if
    406418
     
    408420        }
    409421
    410         void Indexer::addId( DeclarationWithType *decl, Expression * baseExpr ) {
     422        void Indexer::addId( DeclarationWithType *decl, ConflictFunction handleConflicts, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) {
    411423                if ( decl->name == "" ) return;
    412424                debugPrint( "Adding Id " << decl->name << std::endl );
     
    441453
    442454                // Skip repeat declarations of the same identifier
    443                 DeclarationWithType *existing = lookupIdAtScope( name, mangleName, scope );
    444                 if ( existing && addedIdConflicts( existing, decl ) ) return;
     455                IdData * existing = lookupIdAtScope( name, mangleName, scope );
     456                if ( existing && existing->id && addedIdConflicts( *existing, decl, deleteStmt, handleConflicts ) ) return;
    445457
    446458                // add to indexer
    447                 tables->idTable[ name ][ mangleName ] = { decl, baseExpr };
     459                tables->idTable[ name ][ mangleName ] = { decl, baseExpr, deleteStmt };
    448460                ++tables->size;
     461        }
     462
     463        void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
     464                // default handling of conflicts is to raise an error
     465                addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( msg, decl ); return true; }, baseExpr );
     466        }
     467
     468        void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ) {
     469                // default handling of conflicts is to raise an error
     470                addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( msg, decl ); return true; }, nullptr, deleteStmt );
    449471        }
    450472
     
    573595        }
    574596
    575         void Indexer::addMembers( AggregateDecl * aggr, Expression * expr ) {
     597        void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunction handleConflicts ) {
    576598                for ( Declaration * decl : aggr->members ) {
    577599                        if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
    578                                 addId( dwt, expr );
     600                                addId( dwt, handleConflicts, expr );
    579601                                if ( dwt->name == "" ) {
    580602                                        Type * t = dwt->get_type()->stripReferences();
     
    582604                                                Expression * base = expr->clone();
    583605                                                ResolvExpr::referenceToRvalueConversion( base );
    584                                                 addMembers( t->getAggr(), new MemberExpr( dwt, base ) );
     606                                                addMembers( t->getAggr(), new MemberExpr( dwt, base ), handleConflicts );
    585607                                        }
    586608                                }
     
    589611        }
    590612
    591         void Indexer::addWith( std::list< Expression * > & withExprs ) {
     613        void Indexer::addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt ) {
    592614                for ( Expression * expr : withExprs ) {
    593615                        if ( expr->result ) {
     
    595617                                assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() );
    596618
    597                                 addMembers( aggr, expr );
     619                                addMembers( aggr, expr, [withStmt](IdData & existing, const std::string &) {
     620                                        // on conflict, delete the identifier
     621                                        existing.deleteStmt = withStmt;
     622                                        return true;
     623                                });
    598624                        }
    599625                }
     
    680706
    681707        Expression * Indexer::IdData::combine() const {
     708                Expression * ret = nullptr;
    682709                if ( baseExpr ) {
    683710                        Expression * base = baseExpr->clone();
    684711                        ResolvExpr::referenceToRvalueConversion( base );
    685                         Expression * ret = new MemberExpr( id, base );
     712                        ret = new MemberExpr( id, base );
    686713                        // xxx - this introduces hidden environments, for now remove them.
    687714                        // std::swap( base->env, ret->env );
    688715                        delete base->env;
    689716                        base->env = nullptr;
    690                         return ret;
    691                 } else {
    692                         return new VariableExpr( id );
    693                 }
     717                } else {
     718                        ret = new VariableExpr( id );
     719                }
     720                if ( deleteStmt ) ret = new DeletedExpr( ret, deleteStmt );
     721                return ret;
    694722        }
    695723} // namespace SymTab
  • src/SymTab/Indexer.h

    rf5883bd r0ac366b  
    1919#include <list>               // for list
    2020#include <string>             // for string
     21#include <functional>         // for function
    2122
    2223#include "SynTree/Visitor.h"  // for Visitor
     
    6566
    6667                /// looks up a specific mangled ID at the given scope
    67                 DeclarationWithType *lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
     68                IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope );
     69                const IdData * lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
    6870                /// returns true if there exists a declaration with C linkage and the given name with a different mangled name
    6971                bool hasIncompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
     
    7779                TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const;
    7880
    79                 void addId( DeclarationWithType *decl, Expression * baseExpr = nullptr );
     81                typedef std::function<bool(IdData &, const std::string &)> ConflictFunction;
     82
     83                void addId( DeclarationWithType * decl, Expression * baseExpr = nullptr );
     84                void addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt );
     85
    8086                void addType( NamedTypeDecl *decl );
    8187                void addStruct( const std::string &id );
     
    8793
    8894                /// adds all of the IDs from WithStmt exprs
    89                 void addWith( std::list< Expression * > & withExprs );
     95                void addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt );
    9096
    9197                /// adds all of the members of the Aggregate (addWith helper)
    92                 void addMembers( AggregateDecl * aggr, Expression * expr );
     98                void addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunction );
    9399
    94100                /// convenience function for adding a list of Ids to the indexer
     
    120126                /// Ensures that tables variable is writable (i.e. allocated, uniquely owned by this Indexer, and at the current scope)
    121127                void makeWritable();
     128
     129                /// common code for addId, addDeletedId, etc.
     130                void addId( DeclarationWithType * decl, ConflictFunction, Expression * baseExpr = nullptr, BaseSyntaxNode * deleteStmt = nullptr );
    122131        };
    123132} // namespace SymTab
Note: See TracChangeset for help on using the changeset viewer.