Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    ra2a8d2a6 rc8dfcd3  
    3131#include "SynTree/Mutator.h"
    3232#include "SymTab/Indexer.h"
     33#include "SymTab/Autogen.h"
    3334#include "GenPoly/PolyMutator.h"
    3435#include "SynTree/AddStmtVisitor.h"
     
    176177                };
    177178
    178                 class WarnStructMembers : public Visitor {
     179                class GenStructMemberCalls : public SymTab::Indexer {
    179180                  public:
    180                         typedef Visitor Parent;
    181                         /// warn if a user-defined constructor or destructor is missing calls for
    182                         /// a struct member or if a member is used before constructed
    183                         static void warnings( std::list< Declaration * > & translationUnit );
     181                        typedef Indexer Parent;
     182                        /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors
     183                        /// for any member that is missing a corresponding ctor/dtor call.
     184                        /// error if a member is used before constructed
     185                        static void generate( std::list< Declaration * > & translationUnit );
    184186
    185187                        virtual void visit( FunctionDecl * funcDecl );
     
    195197
    196198                        FunctionDecl * function = 0;
    197                         std::set< DeclarationWithType * > unhandled;
     199                        std::set< DeclarationWithType * > unhandled, usedUninit;
    198200                        ObjectDecl * thisParam = 0;
     201                        bool isCtor = false; // true if current function is a constructor
     202                };
     203
     204                // very simple resolver-like mutator class - used to
     205                // resolve UntypedExprs that are found within newly
     206                // generated constructor/destructor calls
     207                class MutatingResolver : public Mutator {
     208                  public:
     209                        MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}
     210
     211                        virtual DeclarationWithType* mutate( ObjectDecl *objectDecl );
     212
     213                        virtual Expression* mutate( UntypedExpr *untypedExpr );
     214                        private:
     215                        SymTab::Indexer & indexer;
    199216                };
    200217        } // namespace
     
    212229                FixCopyCtors::fixCopyCtors( translationUnit );
    213230
    214                 WarnStructMembers::warnings( translationUnit );
     231                GenStructMemberCalls::generate( translationUnit );
    215232        }
    216233
     
    257274                }
    258275
    259                 void WarnStructMembers::warnings( std::list< Declaration * > & translationUnit ) {
    260                         if ( true ) { // fix this condition to skip this pass if warnings aren't enabled
    261                                 WarnStructMembers warner;
    262                                 acceptAll( translationUnit, warner );
    263 
    264                                 // visitor doesn't throw so that it can collect all errors
    265                                 if ( ! warner.errors.isEmpty() ) {
    266                                         throw warner.errors;
    267                                 }
     276                void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
     277                        GenStructMemberCalls warner;
     278                        acceptAll( translationUnit, warner );
     279
     280                        // visitor doesn't throw so that it can collect all errors
     281                        if ( ! warner.errors.isEmpty() ) {
     282                                throw warner.errors;
    268283                        }
    269284                }
     
    536551                                                        FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
    537552                                                        dtorCaller->fixUniqueId();
    538                                                         dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
     553                                                        dtorCaller->get_statements()->push_back( dtorStmt );
    539554
    540555                                                        // atexit(dtor_atexit);
     
    551566                                                        // at global scope and there could be multiple function-scoped
    552567                                                        // static variables with the same name in different functions.
     568                                                        // Note: it isn't sufficient to modify only the mangleName, because
     569                                                        // then subsequent Indexer passes can choke on seeing the object's name
     570                                                        // if another object has the same name and type. An unfortunate side-effect
     571                                                        // of renaming the object is that subsequent NameExprs may fail to resolve,
     572                                                        // but there shouldn't be any remaining past this point.
    553573                                                        static UniqueName staticNamer( "_static_var" );
    554                                                         objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() );
     574                                                        objDecl->set_name( objDecl->get_name() + staticNamer.newName() );
     575                                                        objDecl->set_mangleName( SymTab::Mangler::mangle( objDecl ) );
    555576
    556577                                                        objDecl->set_init( NULL );
     
    717738                }
    718739
    719                 void WarnStructMembers::visit( FunctionDecl * funcDecl ) {
    720                         WarnStructMembers old = *this;
    721                         *this = WarnStructMembers();
     740                void GenStructMemberCalls::visit( FunctionDecl * funcDecl ) {
     741                        ValueGuard< FunctionDecl * > oldFunction( funcDecl );
     742                        ValueGuard< std::set< DeclarationWithType * > > oldUnhandled( unhandled );
     743                        ValueGuard< std::set< DeclarationWithType * > > oldUsedUninit( usedUninit );
     744                        ValueGuard< ObjectDecl * > oldThisParam( thisParam );
     745                        ValueGuard< bool > oldIsCtor( isCtor );
     746
     747                        // need to start with fresh sets
     748                        unhandled.clear();
     749                        usedUninit.clear();
    722750
    723751                        function = funcDecl;
    724                         if ( checkWarnings( funcDecl ) ) {
    725                                 FunctionType * type = funcDecl->get_functionType();
     752                        isCtor = isConstructor( function->get_name() );
     753                        if ( checkWarnings( function ) ) {
     754                                FunctionType * type = function->get_functionType();
    726755                                assert( ! type->get_parameters().empty() );
    727756                                thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() );
     
    739768                                }
    740769                        }
    741                         Parent::visit( funcDecl );
    742 
    743                         for ( DeclarationWithType * member : unhandled ) {
    744                                 // emit a warning for each unhandled member
    745                                 emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " may not have been ", isConstructor( funcDecl->get_name() ) ? "constructed" : "destructed" );
     770                        Parent::visit( function );
     771
     772                        // remove the unhandled objects from usedUninit, because a call is inserted
     773                        // to handle them - only objects that are later constructed are used uninitialized.
     774                        std::set< DeclarationWithType * > diff;
     775                        std::set_difference( usedUninit.begin(), usedUninit.end(), unhandled.begin(), unhandled.end(), std::inserter( diff, diff.begin() ) );
     776                        for ( DeclarationWithType * member : diff ) {
     777                                emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " used before being constructed" );
    746778                        }
    747779
    748                         // need to steal the errors before they're lost
    749                         old.errors.append( errors );
    750                         *this = old;
    751                 }
    752 
    753                 void WarnStructMembers::visit( ApplicationExpr * appExpr ) {
     780                        if ( ! unhandled.empty() ) {
     781                                // need to explicitly re-add function parameters in order to resolve copy constructors
     782                                enterScope();
     783                                // maybeAccept( function->get_functionType(), *this );
     784                                for ( DeclarationWithType * member : unhandled ) {
     785                                        // insert and resolve default/copy constructor call for each member that's unhandled
     786                                        std::list< Statement * > stmt;
     787                                        UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
     788                                        deref->get_args().push_back( new VariableExpr( thisParam ) );
     789                                        InitExpander srcParam( (Initializer *)NULL ); // xxx - if copy ctor, need to pass appropriate argument - second param of this function dot member
     790                                        SymTab::genImplicitCall( srcParam, new MemberExpr( member, deref ), function->get_name(), back_inserter( stmt ), member, isCtor );
     791
     792                                        assert( stmt.size() <= 1 );
     793                                        if ( stmt.size() == 1 ) {
     794                                                Statement * callStmt = stmt.front();
     795
     796                                                MutatingResolver resolver( *this );
     797                                                try {
     798                                                        // xxx - these should be in field declaration order
     799                                                        callStmt->acceptMutator( resolver );
     800                                                        if ( isCtor ) {
     801                                                                function->get_statements()->push_front( callStmt );
     802                                                        } else {
     803                                                                // destructor statements should be added at the end
     804                                                                function->get_statements()->push_back( callStmt );
     805                                                        }
     806                                                } catch ( SemanticError & error ) {
     807                                                        emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed",  " and no ", isCtor ? "default constructor" : "destructor", " found" );
     808                                                }
     809                                        }
     810                                }
     811                                leaveScope();
     812                        }
     813                }
     814
     815                void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) {
    754816                        if ( ! checkWarnings( function ) ) return;
    755817
     
    780842                }
    781843
    782                 void WarnStructMembers::handleFirstParam( Expression * firstParam ) {
     844                void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) {
    783845                        using namespace std;
    784846                        if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) {
     
    797859                }
    798860
    799                 void WarnStructMembers::visit( MemberExpr * memberExpr ) {
     861                void GenStructMemberCalls::visit( MemberExpr * memberExpr ) {
    800862                        if ( ! checkWarnings( function ) ) return;
    801                         if ( ! isConstructor( function->get_name() ) ) return;
     863                        if ( ! isCtor ) return;
    802864
    803865                        if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
     
    807869                                                        if ( unhandled.count( memberExpr->get_member() ) ) {
    808870                                                                // emit a warning because a member was used before it was constructed
    809                                                                 emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", memberExpr->get_member()->get_name(), " used before being constructed" );
     871                                                                usedUninit.insert( memberExpr->get_member() );
    810872                                                        }
    811873                                                }
     
    822884
    823885                template< typename... Params >
    824                 void WarnStructMembers::emit( const Params &... params ) {
     886                void GenStructMemberCalls::emit( const Params &... params ) {
    825887                        // toggle warnings vs. errors here.
    826888                        // warn( params... );
    827889                        error( *this, params... );
     890                }
     891
     892                DeclarationWithType * MutatingResolver::mutate( ObjectDecl *objectDecl ) {
     893                        // add object to the indexer assumes that there will be no name collisions
     894                        // in generated code. If this changes, add mutate methods for entities with
     895                        // scope and call {enter,leave}Scope explicitly.
     896                        objectDecl->accept( indexer );
     897                        return objectDecl;
     898                }
     899
     900                Expression* MutatingResolver::mutate( UntypedExpr *untypedExpr ) {
     901                        return safe_dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untypedExpr, indexer ) );
    828902                }
    829903        } // namespace
Note: See TracChangeset for help on using the changeset viewer.