Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Indexer.cc

    r1057e3d r3f024c9  
    106106                if ( ! CodeGen::isCtorDtorAssign( id ) ) return;
    107107
    108                 // helpful data structure to organize properties for a type
     108                // helpful data structure
    109109                struct ValueType {
    110                         struct DeclBall { // properties for this particular decl
     110                        struct DeclBall {
    111111                                IdData decl;
    112                                 bool isUserDefinedFunc;
     112                                bool isUserDefinedFunc; // properties for this particular decl
     113                                bool isDefaultCtor;
     114                                bool isDtor;
    113115                                bool isCopyFunc;
    114116                        };
    115117                        // properties for this type
     118                        bool existsUserDefinedFunc = false;    // any user-defined function found
     119                        bool existsUserDefinedCtor = false;    // any user-defined constructor found
     120                        bool existsUserDefinedDtor = false;    // any user-defined destructor found
    116121                        bool existsUserDefinedCopyFunc = false;    // user-defined copy ctor found
    117                         BaseSyntaxNode * deleteStmt = nullptr;     // non-null if a user-defined function is found
     122                        bool existsUserDefinedDefaultCtor = false; // user-defined default ctor found
    118123                        std::list< DeclBall > decls;
    119124
     
    122127                        ValueType & operator+=( IdData data ) {
    123128                                DeclarationWithType * function = data.id;
    124                                 bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage );
    125                                 bool isCopyFunc = InitTweak::isCopyFunction( function, function->name );
    126                                 decls.push_back( DeclBall{ data, isUserDefinedFunc, isCopyFunc } );
     129                                bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->get_linkage() );
     130                                bool isDefaultCtor = InitTweak::isDefaultConstructor( function );
     131                                bool isDtor = InitTweak::isDestructor( function );
     132                                bool isCopyFunc = InitTweak::isCopyFunction( function, function->get_name() );
     133                                decls.push_back( DeclBall{ data, isUserDefinedFunc, isDefaultCtor, isDtor, isCopyFunc } );
     134                                existsUserDefinedFunc = existsUserDefinedFunc || isUserDefinedFunc;
     135                                existsUserDefinedCtor = existsUserDefinedCtor || (isUserDefinedFunc && CodeGen::isConstructor( function->get_name() ) );
     136                                existsUserDefinedDtor = existsUserDefinedDtor || (isUserDefinedFunc && isDtor);
    127137                                existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc);
    128                                 if ( isUserDefinedFunc && ! deleteStmt ) {
    129                                         // any user-defined function can act as an implicit delete statement for generated constructors.
    130                                         // a delete stmt should not act as an implicit delete statement.
    131                                         deleteStmt = data.id;
    132                                 }
     138                                existsUserDefinedDefaultCtor = existsUserDefinedDefaultCtor || (isUserDefinedFunc && isDefaultCtor);
    133139                                return *this;
    134140                        }
     
    142148                for ( auto decl : copy ) {
    143149                        if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl.id ) ) {
    144                                 std::list< DeclarationWithType * > & params = function->type->parameters;
     150                                std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters();
    145151                                assert( ! params.empty() );
    146152                                // use base type of pointer, so that qualifiers on the pointer type aren't considered.
     
    154160
    155161                // if a type contains user defined ctor/dtor/assign, then special rules trigger, which determine
    156                 // the set of ctor/dtor/assign that can be used  by the requester. In particular, if the user defines
    157                 // a default ctor, then the generated default ctor is unavailable, likewise for copy ctor
    158                 // and dtor. If the user defines any ctor/dtor, then no generated field ctors are available.
    159                 // If the user defines any ctor then the generated default ctor is unavailable (intrinsic default
    160                 // ctor must be overridden exactly). If the user defines anything that looks like a copy constructor,
    161                 // then the generated copy constructor is unavailable, and likewise for the assignment operator.
     162                // the set of ctor/dtor/assign that are seen by the requester. In particular, if the user defines
     163                // a default ctor, then the generated default ctor should never be seen, likewise for copy ctor
     164                // and dtor. If the user defines any ctor/dtor, then no generated field ctors should be seen.
     165                // If the user defines any ctor then the generated default ctor should not be seen (intrinsic default
     166                // ctor must be overridden exactly).
    162167                for ( std::pair< const std::string, ValueType > & pair : funcMap ) {
    163168                        ValueType & val = pair.second;
    164169                        for ( ValueType::DeclBall ball : val.decls ) {
    165                                 bool isNotUserDefinedFunc = ! ball.isUserDefinedFunc && ball.decl.id->linkage != LinkageSpec::Intrinsic;
    166                                 bool isCopyFunc = ball.isCopyFunc;
    167                                 bool existsUserDefinedCopyFunc = val.existsUserDefinedCopyFunc;
    168 
    169                                 // only implicitly delete non-user defined functions that are not intrinsic, and are
    170                                 // not copy functions (assignment or copy constructor). If a  user-defined copy function exists,
    171                                 // do not pass along the non-user-defined copy functions since signatures do not have to match,
    172                                 // and the generated functions will often be cheaper.
    173                                 if ( isNotUserDefinedFunc ) {
    174                                         if ( isCopyFunc ) {
    175                                                 // Skip over non-user-defined copy functions when there is a user-defined copy function.
    176                                                 // Since their signatures do not have to be exact, deleting them is the wrong choice.
    177                                                 if ( existsUserDefinedCopyFunc ) continue;
    178                                         } else {
    179                                                 // delete non-user-defined non-copy functions if applicable.
    180                                                 // deleteStmt will be non-null only if a user-defined function is found.
    181                                                 ball.decl.deleteStmt = val.deleteStmt;
    182                                         }
     170                                bool noUserDefinedFunc = ! val.existsUserDefinedFunc;
     171                                bool isUserDefinedFunc = ball.isUserDefinedFunc;
     172                                bool isAcceptableDefaultCtor = (! val.existsUserDefinedCtor || (! val.existsUserDefinedDefaultCtor && ball.decl.id->get_linkage() == LinkageSpec::Intrinsic)) && ball.isDefaultCtor; // allow default constructors only when no user-defined constructors exist, except in the case of intrinsics, which require exact overrides
     173                                bool isAcceptableCopyFunc = ! val.existsUserDefinedCopyFunc && ball.isCopyFunc; // handles copy ctor and assignment operator
     174                                bool isAcceptableDtor = ! val.existsUserDefinedDtor && ball.isDtor;
     175                                if ( noUserDefinedFunc || isUserDefinedFunc || isAcceptableDefaultCtor || isAcceptableCopyFunc || isAcceptableDtor ) {
     176                                        // decl conforms to the rules described above, so it should be seen by the requester
     177                                        out.push_back( ball.decl );
    183178                                }
    184                                 out.push_back( ball.decl );
    185179                        }
    186180                }
     
    477471        void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
    478472                // default handling of conflicts is to raise an error
    479                 addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr, decl->isDeleted ? decl : nullptr );
     473                addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr );
    480474        }
    481475
Note: See TracChangeset for help on using the changeset viewer.