Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    rb16898e r486341f  
    3131#include "SynTree/Mutator.h"
    3232#include "SymTab/Indexer.h"
    33 #include "SymTab/Autogen.h"
    3433#include "GenPoly/PolyMutator.h"
    3534#include "SynTree/AddStmtVisitor.h"
     
    177176                };
    178177
    179                 class GenStructMemberCalls : public SymTab::Indexer {
     178                class WarnStructMembers : public Visitor {
    180179                  public:
    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 );
     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 );
    186184
    187185                        virtual void visit( FunctionDecl * funcDecl );
     
    190188                        virtual void visit( ApplicationExpr * appExpr );
    191189
    192                         SemanticError errors;
    193190                  private:
    194191                        void handleFirstParam( Expression * firstParam );
    195                         template< typename... Params >
    196                         void emit( const Params &... params );
    197192
    198193                        FunctionDecl * function = 0;
    199                         std::set< DeclarationWithType * > unhandled, usedUninit;
     194                        std::set< DeclarationWithType * > unhandled;
    200195                        ObjectDecl * thisParam = 0;
    201                         bool isCtor = false; // true if current function is a constructor
    202                         StructDecl * structDecl = 0;
    203                 };
    204 
    205                 // very simple resolver-like mutator class - used to
    206                 // resolve UntypedExprs that are found within newly
    207                 // generated constructor/destructor calls
    208                 class MutatingResolver : public Mutator {
    209                   public:
    210                         MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}
    211 
    212                         virtual DeclarationWithType* mutate( ObjectDecl *objectDecl );
    213 
    214                         virtual Expression* mutate( UntypedExpr *untypedExpr );
    215                         private:
    216                         SymTab::Indexer & indexer;
    217196                };
    218197        } // namespace
     
    230209                FixCopyCtors::fixCopyCtors( translationUnit );
    231210
    232                 GenStructMemberCalls::generate( translationUnit );
     211                WarnStructMembers::warnings( translationUnit );
    233212        }
    234213
     
    275254                }
    276255
    277                 void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
    278                         GenStructMemberCalls warner;
    279                         acceptAll( translationUnit, warner );
    280 
    281                         // visitor doesn't throw so that it can collect all errors
    282                         if ( ! warner.errors.isEmpty() ) {
    283                                 throw warner.errors;
     256                void WarnStructMembers::warnings( std::list< Declaration * > & translationUnit ) {
     257                        if ( true ) { // fix this condition to skip this pass if warnings aren't enabled
     258                                WarnStructMembers warner;
     259                                acceptAll( translationUnit, warner );
    284260                        }
    285261                }
     
    552528                                                        FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
    553529                                                        dtorCaller->fixUniqueId();
    554                                                         dtorCaller->get_statements()->push_back( dtorStmt );
     530                                                        dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
    555531
    556532                                                        // atexit(dtor_atexit);
     
    567543                                                        // at global scope and there could be multiple function-scoped
    568544                                                        // static variables with the same name in different functions.
    569                                                         // Note: it isn't sufficient to modify only the mangleName, because
    570                                                         // then subsequent Indexer passes can choke on seeing the object's name
    571                                                         // if another object has the same name and type. An unfortunate side-effect
    572                                                         // of renaming the object is that subsequent NameExprs may fail to resolve,
    573                                                         // but there shouldn't be any remaining past this point.
    574545                                                        static UniqueName staticNamer( "_static_var" );
    575                                                         objDecl->set_name( objDecl->get_name() + staticNamer.newName() );
    576                                                         objDecl->set_mangleName( SymTab::Mangler::mangle( objDecl ) );
     546                                                        objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() );
    577547
    578548                                                        objDecl->set_init( NULL );
     
    739709                }
    740710
    741                 void GenStructMemberCalls::visit( FunctionDecl * funcDecl ) {
    742                         ValueGuard< FunctionDecl * > oldFunction( funcDecl );
    743                         ValueGuard< std::set< DeclarationWithType * > > oldUnhandled( unhandled );
    744                         ValueGuard< std::set< DeclarationWithType * > > oldUsedUninit( usedUninit );
    745                         ValueGuard< ObjectDecl * > oldThisParam( thisParam );
    746                         ValueGuard< bool > oldIsCtor( isCtor );
    747                         ValueGuard< StructDecl * > oldStructDecl( structDecl );
    748 
    749                         // need to start with fresh sets
    750                         unhandled.clear();
    751                         usedUninit.clear();
     711                void WarnStructMembers::visit( FunctionDecl * funcDecl ) {
     712                        WarnStructMembers old = *this;
     713                        *this = WarnStructMembers();
    752714
    753715                        function = funcDecl;
    754                         isCtor = isConstructor( function->get_name() );
    755                         if ( checkWarnings( function ) ) {
    756                                 FunctionType * type = function->get_functionType();
     716                        if ( checkWarnings( funcDecl ) ) {
     717                                FunctionType * type = funcDecl->get_functionType();
    757718                                assert( ! type->get_parameters().empty() );
    758719                                thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() );
     
    760721                                StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base() );
    761722                                if ( structType ) {
    762                                         structDecl = structType->get_baseStruct();
     723                                        StructDecl * structDecl = structType->get_baseStruct();
    763724                                        for ( Declaration * member : structDecl->get_members() ) {
    764725                                                if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
     
    770731                                }
    771732                        }
    772                         Parent::visit( function );
    773 
    774                         // remove the unhandled objects from usedUninit, because a call is inserted
    775                         // to handle them - only objects that are later constructed are used uninitialized.
    776                         std::set< DeclarationWithType * > diff;
    777                         std::set_difference( usedUninit.begin(), usedUninit.end(), unhandled.begin(), unhandled.end(), std::inserter( diff, diff.begin() ) );
    778                         for ( DeclarationWithType * member : diff ) {
    779                                 emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", field ", member->get_name(), " used before being constructed" );
     733                        Parent::visit( funcDecl );
     734
     735                        for ( DeclarationWithType * member : unhandled ) {
     736                                // emit a warning for each unhandled member
     737                                warn( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " may not have been ", isConstructor( funcDecl->get_name() ) ? "constructed" : "destructed" );
    780738                        }
    781739
    782                         if ( ! unhandled.empty() ) {
    783                                 // need to explicitly re-add function parameters in order to resolve copy constructors
    784                                 enterScope();
    785                                 maybeAccept( function->get_functionType(), *this );
    786 
    787                                 // need to iterate through members in reverse in order for
    788                                 // ctor/dtor statements to come out in the right order
    789                                 for ( Declaration * member : reverseIterate( structDecl->get_members() ) ) {
    790                                         DeclarationWithType * field = dynamic_cast< DeclarationWithType * >( member );
    791                                         // skip non-DWT members
    792                                         if ( ! field ) continue;
    793                                         // skip handled members
    794                                         if ( ! unhandled.count( field ) ) continue;
    795 
    796                                         // insert and resolve default/copy constructor call for each field that's unhandled
    797                                         std::list< Statement * > stmt;
    798                                         UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
    799                                         deref->get_args().push_back( new VariableExpr( thisParam ) );
    800 
    801                                         Expression * arg2 = 0;
    802                                         if ( isCopyConstructor( function ) ) {
    803                                                 // if copy ctor, need to pass second-param-of-this-function.field
    804                                                 std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters();
    805                                                 assert( params.size() == 2 );
    806                                                 arg2 = new MemberExpr( field, new VariableExpr( params.back() ) );
    807                                         }
    808                                         InitExpander srcParam( arg2 );
    809                                         SymTab::genImplicitCall( srcParam, new MemberExpr( field, deref ), function->get_name(), back_inserter( stmt ), field, isCtor );
    810 
    811                                         assert( stmt.size() <= 1 );
    812                                         if ( stmt.size() == 1 ) {
    813                                                 Statement * callStmt = stmt.front();
    814 
    815                                                 MutatingResolver resolver( *this );
    816                                                 try {
    817                                                         callStmt->acceptMutator( resolver );
    818                                                         if ( isCtor ) {
    819                                                                 function->get_statements()->push_front( callStmt );
    820                                                         } else {
    821                                                                 // destructor statements should be added at the end
    822                                                                 function->get_statements()->push_back( callStmt );
    823                                                         }
    824                                                 } catch ( SemanticError & error ) {
    825                                                         emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", field ", field->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed",  " and no ", isCtor ? "default constructor" : "destructor", " found" );
    826                                                 }
    827                                         }
    828                                 }
    829                                 leaveScope();
    830                         }
    831                 }
    832 
    833                 void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) {
     740                        *this = old;
     741                }
     742
     743                void WarnStructMembers::visit( ApplicationExpr * appExpr ) {
    834744                        if ( ! checkWarnings( function ) ) return;
    835745
     
    850760                                        handleFirstParam( firstParam );
    851761                                }
     762                        } else if ( fname == "?=?" && isIntrinsicCallExpr( appExpr ) ) {
     763                                // forgive use of intrinsic assignment to construct, since instrinsic constructors
     764                                // codegen as assignment anyway.
     765                                assert( appExpr->get_args().size() == 2 );
     766                                handleFirstParam( appExpr->get_args().front() );
    852767                        }
    853768
     
    855770                }
    856771
    857                 void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) {
     772                void WarnStructMembers::handleFirstParam( Expression * firstParam ) {
    858773                        using namespace std;
    859774                        if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) {
     
    872787                }
    873788
    874                 void GenStructMemberCalls::visit( MemberExpr * memberExpr ) {
     789                void WarnStructMembers::visit( MemberExpr * memberExpr ) {
    875790                        if ( ! checkWarnings( function ) ) return;
    876                         if ( ! isCtor ) return;
     791                        if ( ! isConstructor( function->get_name() ) ) return;
    877792
    878793                        if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
     
    882797                                                        if ( unhandled.count( memberExpr->get_member() ) ) {
    883798                                                                // emit a warning because a member was used before it was constructed
    884                                                                 usedUninit.insert( memberExpr->get_member() );
     799                                                                warn( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", memberExpr->get_member()->get_name(), " used before being constructed" );
    885800                                                        }
    886801                                                }
     
    890805                        Parent::visit( memberExpr );
    891806                }
    892 
    893                 template< typename Visitor, typename... Params >
    894                 void error( Visitor & v, const Params &... params ) {
    895                         v.errors.append( toString( params... ) );
    896                 }
    897 
    898                 template< typename... Params >
    899                 void GenStructMemberCalls::emit( const Params &... params ) {
    900                         // toggle warnings vs. errors here.
    901                         // warn( params... );
    902                         error( *this, params... );
    903                 }
    904 
    905                 DeclarationWithType * MutatingResolver::mutate( ObjectDecl *objectDecl ) {
    906                         // add object to the indexer assumes that there will be no name collisions
    907                         // in generated code. If this changes, add mutate methods for entities with
    908                         // scope and call {enter,leave}Scope explicitly.
    909                         objectDecl->accept( indexer );
    910                         return objectDecl;
    911                 }
    912 
    913                 Expression* MutatingResolver::mutate( UntypedExpr *untypedExpr ) {
    914                         return safe_dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untypedExpr, indexer ) );
    915                 }
    916807        } // namespace
    917808} // namespace InitTweak
Note: See TracChangeset for help on using the changeset viewer.