Changeset adcc065 for src/InitTweak


Ignore:
Timestamp:
Jul 6, 2016, 6:06:27 PM (9 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
3f869f0
Parents:
e04c5ff
Message:

add labelled break to if statement, update comment formatting, add random number test

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    re04c5ff radcc065  
    99// Author           : Rob Schluntz
    1010// Created On       : Wed Jan 13 16:29:30 2016
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Fri May 13 11:44:26 2016
    13 // Update Count     : 30
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Wed Jul  6 17:34:46 2016
     13// Update Count     : 33
    1414//
    1515
     
    4747                class InsertImplicitCalls : public GenPoly::PolyMutator {
    4848                public:
    49                         /// wrap function application expressions as ImplicitCopyCtorExpr nodes
    50                         /// so that it is easy to identify which function calls need their parameters
    51                         /// to be copy constructed
     49                        /// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
     50                        /// function calls need their parameters to be copy constructed
    5251                        static void insert( std::list< Declaration * > & translationUnit );
    5352
     
    5756                class ResolveCopyCtors : public SymTab::Indexer {
    5857                public:
    59                         /// generate temporary ObjectDecls for each argument and return value of each
    60                         /// ImplicitCopyCtorExpr, generate/resolve copy construction expressions for each,
    61                         /// and generate/resolve destructors for both arguments and return value temporaries
     58                        /// generate temporary ObjectDecls for each argument and return value of each ImplicitCopyCtorExpr,
     59                        /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both
     60                        /// arguments and return value temporaries
    6261                        static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
    6362
     
    9392                        for ( ObjectDecl * obj : set.objs ) {
    9493                                out << obj->get_name() << ", " ;
    95                         }
     94                        } // for
    9695                        out << " }";
    9796                        return out;
     
    108107
    109108                        // xxx - This needs to be done better.
    110                         // allow some generalization among different kinds of nodes with
    111                         // with similar parentage (e.g. all expressions, all statements, etc.)
    112                         // important to have this to provide a single entry point so that as
    113                         // new subclasses are added, there is only one place that the code has
    114                         // to be updated, rather than ensure that every specialized class knows
    115                         // about every new kind of statement that might be added.
     109                        // allow some generalization among different kinds of nodes with with similar parentage (e.g. all
     110                        // expressions, all statements, etc.)  important to have this to provide a single entry point so that as new
     111                        // subclasses are added, there is only one place that the code has to be updated, rather than ensure that
     112                        // every specialized class knows about every new kind of statement that might be added.
    116113                        virtual void visit( CompoundStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
    117114                        virtual void visit( ExprStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); }
     
    136133                class InsertDtors : public ObjDeclCollector {
    137134                public:
    138                         /// insert destructor calls at the appropriate places.
    139                         /// must happen before CtorInit nodes are removed (currently by FixInit)
     135                        /// insert destructor calls at the appropriate places.  must happen before CtorInit nodes are removed
     136                        /// (currently by FixInit)
    140137                        static void insert( std::list< Declaration * > & translationUnit );
    141138
     
    168165                class FixCopyCtors : public GenPoly::PolyMutator {
    169166                  public:
    170                         /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors,
    171                         /// call expression, and destructors
     167                        /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, call expression,
     168                        /// and destructors
    172169                        static void fixCopyCtors( std::list< Declaration * > &translationUnit );
    173170
     
    235232                                                        // assignment operator
    236233                                                        return appExpr;
    237                                                 }
     234                                                } // if
    238235                                        } else if ( funcDecl->get_name() == "^?{}" ) {
    239236                                                // correctness: never copy construct arguments to a destructor
    240237                                                return appExpr;
    241                                         }
    242                                 }
    243                         }
     238                                        } // if
     239                                } // if
     240                        } // if
    244241                        CP_CTOR_PRINT( std::cerr << "InsertImplicitCalls: adding a wrapper " << appExpr << std::endl; )
    245242
     
    270267
    271268                        // resolve copy constructor
    272                         // should only be one alternative for copy ctor and dtor expressions, since
    273                         // all arguments are fixed (VariableExpr and already resolved expression)
     269                        // should only be one alternative for copy ctor and dtor expressions, since all arguments are fixed
     270                        // (VariableExpr and already resolved expression)
    274271                        CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
    275272                        ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) );
    276273                        if ( resolved->get_env() ) {
    277274                                env->add( *resolved->get_env() );
    278                         }
     275                        } // if
    279276
    280277                        assert( resolved );
     
    319316                                        impCpCtorExpr->get_tempDecls().push_back( tmp );
    320317                                        impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
    321                                 }
    322                         }
    323 
    324                         // each return value from the call needs to be connected with an ObjectDecl
    325                         // at the call site, which is initialized with the return value and is destructed
    326                         // later
     318                                } // if
     319                        } // for
     320
     321                        // each return value from the call needs to be connected with an ObjectDecl at the call site, which is
     322                        // initialized with the return value and is destructed later
    327323                        // xxx - handle multiple return values
    328324                        ApplicationExpr * callExpr = impCpCtorExpr->get_callExpr();
    329                         // xxx - is this right? callExpr may not have the right environment, because it was attached
    330                         // at a higher level. Trying to pass that environment along.
     325                        // xxx - is this right? callExpr may not have the right environment, because it was attached at a higher
     326                        // level. Trying to pass that environment along.
    331327                        callExpr->set_env( impCpCtorExpr->get_env()->clone() );
    332328                        for ( Type * result : appExpr->get_results() ) {
     
    338334                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    339335                                impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
    340                         }
     336                        } // for
    341337                        CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
    342338                }
     
    356352                        for ( ObjectDecl * obj : tempDecls ) {
    357353                                stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
    358                         }
     354                        } // for
    359355                        for ( ObjectDecl * obj : returnDecls ) {
    360356                                stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
    361                         }
     357                        } // for
    362358
    363359                        // add destructors after current statement
    364360                        for ( Expression * dtor : dtors ) {
    365361                                stmtsToAddAfter.push_back( new ExprStmt( noLabels, dtor ) );
    366                         }
     362                        } // for
    367363
    368364                        // xxx - update to work with multiple return values
     
    390386                                Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    391387                                if ( callExpr->get_results().front()->get_isLvalue() ) {
    392                                         // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any
    393                                         // lvalue returning non-intrinsic function. Add an AddressExpr to the call to negate
    394                                         // the derefence and change the type of the return temporary from T to T* to properly
    395                                         // capture the return value. Then dereference the result of the comma expression, since
    396                                         // the lvalue returning call was originally wrapped with an AddressExpr.
    397                                         // Effectively, this turns
     388                                        // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning
     389                                        // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the
     390                                        // type of the return temporary from T to T* to properly capture the return value. Then dereference
     391                                        // the result of the comma expression, since the lvalue returning call was originally wrapped with
     392                                        // an AddressExpr.  Effectively, this turns
    398393                                        //   lvalue T f();
    399394                                        //   &*f()
     
    410405                                        deref->add_result( resultType );
    411406                                        retExpr = deref;
    412                                 }
     407                                } // if
    413408                                // xxx - might need to set env on retExpr...
    414409                                // retExpr->set_env( env->clone() );
     
    416411                        } else {
    417412                                return callExpr;
    418                         }
     413                        } // if
    419414                }
    420415
    421416                DeclarationWithType *FixInit::mutate( ObjectDecl *objDecl ) {
    422                         // first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors
    423                         // when the init is removed from the ObjectDecl
     417                        // first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors when the init
     418                        // is removed from the ObjectDecl
    424419                        objDecl = dynamic_cast< ObjectDecl * >( Mutator::mutate( objDecl ) );
    425420
     
    474469                                        } else {
    475470                                                stmtsToAddAfter.push_back( ctor );
    476                                         }
     471                                        } // if
    477472                                        objDecl->set_init( NULL );
    478473                                        ctorInit->set_ctor( NULL );
     
    483478                                        // no constructor and no initializer, which is okay
    484479                                        objDecl->set_init( NULL );
    485                                 }
     480                                } // if
    486481                                delete ctorInit;
    487                         }
     482                        } // if
    488483                        return objDecl;
    489484                }
     
    499494                        if ( ObjectDecl * objDecl = dynamic_cast< ObjectDecl * > ( stmt->get_decl() ) ) {
    500495                                curVars.insert( objDecl );
    501                         }
     496                        } // if
    502497                        Parent::visit( stmt );
    503498                }
     
    507502                        for ( Label l : stmt->get_labels() ) {
    508503                                vars[l] = curVars;
    509                         }
     504                        } // for
    510505                }
    511506
     
    513508                void insertDtors( Iterator begin, Iterator end, OutputIterator out ) {
    514509                        for ( Iterator it = begin ; it != end ; ++it ) {
    515                                 // extract destructor statement from the object decl and
    516                                 // insert it into the output. Note that this is only called
    517                                 // on lists of non-static objects with implicit non-intrinsic
    518                                 // dtors, so if the user manually calls an intrinsic dtor
    519                                 // then the call must (and will) still be generated since
    520                                 // the argument may contain side effects.
     510                                // extract destructor statement from the object decl and insert it into the output. Note that this is
     511                                // only called on lists of non-static objects with implicit non-intrinsic dtors, so if the user manually
     512                                // calls an intrinsic dtor then the call must (and will) still be generated since the argument may
     513                                // contain side effects.
    521514                                ObjectDecl * objDecl = *it;
    522515                                ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() );
    523516                                assert( ctorInit && ctorInit->get_dtor() );
    524517                                *out++ = ctorInit->get_dtor()->clone();
    525                         }
     518                        } // for
    526519                }
    527520
     
    537530                                                // non-intrinsic dtors must be called
    538531                                                reverseDeclOrder.front().push_front( objDecl );
    539                                         }
    540                                 }
    541                         }
     532                                        } // if
     533                                } // if
     534                        } // if
    542535                        Parent::visit( objDecl );
    543536                }
    544537
    545538                void InsertDtors::visit( CompoundStmt * compoundStmt ) {
    546                         // visit statements - this will also populate reverseDeclOrder list.
    547                         // don't want to dump all destructors when block is left,
    548                         // just the destructors associated with variables defined in this block,
    549                         // so push a new list to the top of the stack so that we can differentiate scopes
     539                        // visit statements - this will also populate reverseDeclOrder list.  don't want to dump all destructors
     540                        // when block is left, just the destructors associated with variables defined in this block, so push a new
     541                        // list to the top of the stack so that we can differentiate scopes
    550542                        reverseDeclOrder.push_front( OrderedDecls() );
    551543                        Parent::visit( compoundStmt );
     
    561553                        for ( OrderedDecls & od : reverseDeclOrder ) {
    562554                                insertDtors( od.begin(), od.end(), back_inserter( stmtsToAdd ) );
    563                         }
    564                 }
    565 
    566                 // Handle break/continue/goto in the same manner as C++.
    567                 // Basic idea: any objects that are in scope at the BranchStmt
    568                 // but not at the labelled (target) statement must be destructed.
    569                 // If there are any objects in scope at the target location but
    570                 // not at the BranchStmt then those objects would be uninitialized
    571                 // so notify the user of the error.
    572                 // See C++ Reference 6.6 Jump Statements for details.
     555                        } // for
     556                }
     557
     558                // Handle break/continue/goto in the same manner as C++.  Basic idea: any objects that are in scope at the
     559                // BranchStmt but not at the labelled (target) statement must be destructed.  If there are any objects in scope
     560                // at the target location but not at the BranchStmt then those objects would be uninitialized so notify the user
     561                // of the error.  See C++ Reference 6.6 Jump Statements for details.
    573562                void InsertDtors::handleGoto( BranchStmt * stmt ) {
    574563                        assert( stmt->get_target() != "" && "BranchStmt missing a label" );
     
    591580                        if ( ! diff.empty() ) {
    592581                                throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt );
    593                         }
     582                        } // if
    594583                        // S_G-S_L results in set of objects that must be destructed
    595584                        diff.clear();
     
    604593                                        // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order.
    605594                                        copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return diff.count( objDecl ); } );
    606                                 }
     595                                } // for
    607596                                insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAdd ) );
    608                         }
     597                        } // if
    609598                }
    610599
    611600                void InsertDtors::visit( BranchStmt * stmt ) {
    612601                        switch( stmt->get_type() ) {
    613                                 case BranchStmt::Continue:
    614                                 case BranchStmt::Break:
    615                                 // could optimize the break/continue case, because the S_L-S_G check
    616                                 // is unnecessary (this set should always be empty), but it serves
    617                                 // as a small sanity check.
    618                                 case BranchStmt::Goto:
    619                                         handleGoto( stmt );
    620                                         break;
    621                                 default:
    622                                         assert( false );
    623                         }
     602                          case BranchStmt::Continue:
     603                          case BranchStmt::Break:
     604                                // could optimize the break/continue case, because the S_L-S_G check is unnecessary (this set should
     605                                // always be empty), but it serves as a small sanity check.
     606                          case BranchStmt::Goto:
     607                                handleGoto( stmt );
     608                                break;
     609                          default:
     610                                assert( false );
     611                        } // switch
    624612                }
    625613        } // namespace
Note: See TracChangeset for help on using the changeset viewer.