Changeset 42f1279c for src/SymTab


Ignore:
Timestamp:
Mar 19, 2019, 11:31:06 AM (6 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, persistent-indexer, pthread-emulation, qualifiedEnum
Children:
181a6af
Parents:
fdae913
Message:

Eagerly remove over-ridden generated functions

Location:
src/SymTab
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Indexer.cc

    rfdae913 r42f1279c  
    2222#include <unordered_set>           // for unordered_set
    2323#include <utility>                 // for pair, make_pair, move
     24#include <vector>                  // for vector
    2425
    2526#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
     
    386387        }
    387388
     389        /// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function
     390        std::string getOtypeKey( FunctionDecl* function ) {
     391                auto& params = function->type->parameters;
     392                assert( ! params.empty() );
     393                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
     394                Type* base = InitTweak::getPointerBase( params.front()->get_type() );
     395                assert( base );
     396                return Mangler::mangle( base );
     397        }
     398
     399        /// gets the declaration for the function acting on a type specified by otype key,
     400        /// nullptr if none such
     401        FunctionDecl * getFunctionForOtype( DeclarationWithType * decl, const std::string& otypeKey ) {
     402                FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl );
     403                if ( ! func || otypeKey != getOtypeKey( func ) ) return nullptr;
     404                return func;
     405        }
     406
     407        bool Indexer::removeSpecialOverrides(
     408                        Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) {
     409                // if a type contains user defined ctor/dtor/assign, then special rules trigger, which
     410                // determinethe set of ctor/dtor/assign that can be used  by the requester. In particular,
     411                // if the user defines a default ctor, then the generated default ctor is unavailable,
     412                // likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated
     413                // field ctors are available. If the user defines any ctor then the generated default ctor
     414                // is unavailable (intrinsic default ctor must be overridden exactly). If the user defines
     415                // anything that looks like a copy constructor, then the generated copy constructor is
     416                // unavailable, and likewise for the assignment operator.
     417
     418                // only relevant on function declarations
     419                FunctionDecl * function = dynamic_cast< FunctionDecl * >( data.id );
     420                if ( ! function ) return true;
     421                // only need to perform this check for constructors, destructors, and assignment functions
     422                if ( ! CodeGen::isCtorDtorAssign( data.id->name ) ) return true;
     423
     424                // set up information for this type
     425                bool dataIsUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage );
     426                bool dataIsCopyFunc = InitTweak::isCopyFunction( function, function->name );
     427                std::string dataOtypeKey = getOtypeKey( function );
     428
     429                if ( dataIsUserDefinedFunc && dataIsCopyFunc ) {
     430                        // this is a user-defined copy function
     431                        // if this is the first such, delete/remove non-user-defined overloads as needed
     432                        std::vector< std::string > removed;
     433                        std::vector< MangleTable::value_type > deleted;
     434                        bool alreadyUserDefinedFunc = false;
     435                       
     436                        for ( const auto& entry : *mangleTable ) {
     437                                // skip decls that aren't functions or are for the wrong type
     438                                FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
     439                                if ( ! decl ) continue;
     440
     441                                bool isCopyFunc = InitTweak::isCopyFunction( decl, decl->name );
     442                                if ( ! LinkageSpec::isOverridable( decl->linkage ) ) {
     443                                        // matching user-defined function
     444                                        if ( isCopyFunc ) {
     445                                                // mutation already performed, return early
     446                                                return true;
     447                                        } else {
     448                                                // note that non-copy deletions already performed
     449                                                alreadyUserDefinedFunc = true;
     450                                        }
     451                                } else {
     452                                        // non-user-defined function; mark for deletion/removal as appropriate
     453                                        if ( isCopyFunc ) {
     454                                                removed.push_back( entry.first );
     455                                        } else if ( ! alreadyUserDefinedFunc ) {
     456                                                deleted.push_back( entry );
     457                                        }
     458                                }
     459                        }
     460
     461                        // perform removals from mangle table, and deletions if necessary
     462                        for ( const auto& key : removed ) {
     463                                mangleTable = mangleTable->erase( key );
     464                        }
     465                        if ( ! alreadyUserDefinedFunc ) for ( const auto& entry : deleted ) {
     466                                mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } );
     467                        }
     468                } else if ( dataIsUserDefinedFunc ) {
     469                        // this is a user-defined non-copy function
     470                        // if this is the first user-defined function, delete non-user-defined overloads
     471                        std::vector< MangleTable::value_type > deleted;
     472                       
     473                        for ( const auto& entry : *mangleTable ) {
     474                                // skip decls that aren't functions or are for the wrong type
     475                                FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
     476                                if ( ! decl ) continue;
     477
     478                                // exit early if already a matching user-defined function;
     479                                // earlier function will have mutated table
     480                                if ( ! LinkageSpec::isOverridable( decl->linkage ) ) return true;
     481
     482                                // skip mutating intrinsic functions
     483                                if ( decl->linkage == LinkageSpec::Intrinsic ) continue;
     484
     485                                // user-defined non-copy functions do not override copy functions
     486                                if ( InitTweak::isCopyFunction( decl, decl->name ) ) continue;
     487
     488                                // this function to be deleted after mangleTable iteration is complete
     489                                deleted.push_back( entry );
     490                        }
     491
     492                        // mark deletions to update mangle table
     493                        // this needs to be a separate loop because of iterator invalidation
     494                        for ( const auto& entry : deleted ) {
     495                                mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } );
     496                        }
     497                } else if ( function->linkage != LinkageSpec::Intrinsic ) {
     498                        // this is an overridable generated function
     499                        // if there already exists a matching user-defined function, delete this appropriately
     500                        for ( const auto& entry : *mangleTable ) {
     501                                // skip decls that aren't functions or are for the wrong type
     502                                FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
     503                                if ( ! decl ) continue;
     504
     505                                // skip non-user-defined functions
     506                                if ( LinkageSpec::isOverridable( decl->linkage ) ) continue;
     507
     508                                if ( dataIsCopyFunc ) {
     509                                        // remove current function if exists a user-defined copy function
     510                                        // since the signatures for copy functions don't need to match exactly, using
     511                                        // a delete statement is the wrong approach
     512                                        if ( InitTweak::isCopyFunction( decl, decl->name ) ) return false;
     513                                } else {
     514                                        // mark current function deleted by first user-defined function found
     515                                        data.deleteStmt = decl;
     516                                        return true;
     517                                }
     518                        }
     519                }
     520               
     521                // nothing (more) to fix, return true
     522                return true;
     523        }
     524
    388525        void Indexer::addId(
    389526                        DeclarationWithType *decl, OnConflict handleConflicts, Expression * baseExpr,
    390527                        BaseSyntaxNode * deleteStmt ) {
    391528                ++*stats().add_calls;
    392                 if ( decl->name == "" ) return;
     529                const std::string &name = decl->name;
     530                if ( name == "" ) return;
    393531               
    394                 const std::string &name = decl->name;
    395532                std::string mangleName;
    396533                if ( LinkageSpec::isOverridable( decl->linkage ) ) {
     
    454591                // add/overwrite with new identifier
    455592                lazyInitScope();
     593                IdData data{ decl, baseExpr, deleteStmt, scope };
     594                if ( ! removeSpecialOverrides( data, mangleTable ) ) return;
    456595                *stats().map_mutations += 2;
    457                 idTable = idTable->set(
    458                         name,
    459                         mangleTable->set( mangleName, IdData{ decl, baseExpr, deleteStmt, scope } ) );
     596                idTable = idTable->set( name, mangleTable->set( mangleName, std::move(data) ) );
    460597        }
    461598
  • src/SymTab/Indexer.h

    rfdae913 r42f1279c  
    144144                /// Removes matching autogenerated constructors and destructors
    145145                /// so that they will not be selected
    146                 /// void removeSpecialOverrides( FunctionDecl *decl );
    147146                void removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const;
     147
     148                /// Removes matching autogenerated constructors and destructors so that they will not be
     149                /// selected. If returns false, passed decl should not be added.
     150                bool removeSpecialOverrides( IdData& decl, MangleTable::Ptr& mangleTable );
    148151
    149152                /// Options for handling identifier conflicts
Note: See TracChangeset for help on using the changeset viewer.