Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    rc8dfcd3 ra2a8d2a6  
    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 );
     
    197195
    198196                        FunctionDecl * function = 0;
    199                         std::set< DeclarationWithType * > unhandled, usedUninit;
     197                        std::set< DeclarationWithType * > unhandled;
    200198                        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;
    216199                };
    217200        } // namespace
     
    229212                FixCopyCtors::fixCopyCtors( translationUnit );
    230213
    231                 GenStructMemberCalls::generate( translationUnit );
     214                WarnStructMembers::warnings( translationUnit );
    232215        }
    233216
     
    274257                }
    275258
    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;
     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                                }
    283268                        }
    284269                }
     
    551536                                                        FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );
    552537                                                        dtorCaller->fixUniqueId();
    553                                                         dtorCaller->get_statements()->push_back( dtorStmt );
     538                                                        dtorCaller->get_statements()->get_kids().push_back( dtorStmt );
    554539
    555540                                                        // atexit(dtor_atexit);
     
    566551                                                        // at global scope and there could be multiple function-scoped
    567552                                                        // 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.
    573553                                                        static UniqueName staticNamer( "_static_var" );
    574                                                         objDecl->set_name( objDecl->get_name() + staticNamer.newName() );
    575                                                         objDecl->set_mangleName( SymTab::Mangler::mangle( objDecl ) );
     554                                                        objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() );
    576555
    577556                                                        objDecl->set_init( NULL );
     
    738717                }
    739718
    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();
     719                void WarnStructMembers::visit( FunctionDecl * funcDecl ) {
     720                        WarnStructMembers old = *this;
     721                        *this = WarnStructMembers();
    750722
    751723                        function = funcDecl;
    752                         isCtor = isConstructor( function->get_name() );
    753                         if ( checkWarnings( function ) ) {
    754                                 FunctionType * type = function->get_functionType();
     724                        if ( checkWarnings( funcDecl ) ) {
     725                                FunctionType * type = funcDecl->get_functionType();
    755726                                assert( ! type->get_parameters().empty() );
    756727                                thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() );
     
    768739                                }
    769740                        }
    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" );
     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" );
    778746                        }
    779747
    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 ) {
     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 ) {
    816754                        if ( ! checkWarnings( function ) ) return;
    817755
     
    842780                }
    843781
    844                 void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) {
     782                void WarnStructMembers::handleFirstParam( Expression * firstParam ) {
    845783                        using namespace std;
    846784                        if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) {
     
    859797                }
    860798
    861                 void GenStructMemberCalls::visit( MemberExpr * memberExpr ) {
     799                void WarnStructMembers::visit( MemberExpr * memberExpr ) {
    862800                        if ( ! checkWarnings( function ) ) return;
    863                         if ( ! isCtor ) return;
     801                        if ( ! isConstructor( function->get_name() ) ) return;
    864802
    865803                        if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
     
    869807                                                        if ( unhandled.count( memberExpr->get_member() ) ) {
    870808                                                                // emit a warning because a member was used before it was constructed
    871                                                                 usedUninit.insert( memberExpr->get_member() );
     809                                                                emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", memberExpr->get_member()->get_name(), " used before being constructed" );
    872810                                                        }
    873811                                                }
     
    884822
    885823                template< typename... Params >
    886                 void GenStructMemberCalls::emit( const Params &... params ) {
     824                void WarnStructMembers::emit( const Params &... params ) {
    887825                        // toggle warnings vs. errors here.
    888826                        // warn( params... );
    889827                        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 ) );
    902828                }
    903829        } // namespace
Note: See TracChangeset for help on using the changeset viewer.