Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/GenInit.cc

    rf0121d7 rdcd73d1  
    2929#include "GenPoly/DeclMutator.h"
    3030#include "GenPoly/ScopedSet.h"
    31 #include "ResolvExpr/typeops.h"
    3231
    3332namespace InitTweak {
     
    5150
    5251          protected:
    53                 FunctionType * ftype;
     52                std::list<DeclarationWithType*> returnVals;
    5453                UniqueName tempNamer;
    5554                std::string funcName;
     
    8786
    8887                bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
    89                 bool isManaged( Type * type ) const; // determine if type is managed
    9088                void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
    9189                GenPoly::ScopedSet< std::string > managedTypes;
     
    136134
    137135        Statement *ReturnFixer::mutate( ReturnStmt *returnStmt ) {
    138                 std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals();
     136                // update for multiple return values
    139137                assert( returnVals.size() == 0 || returnVals.size() == 1 );
    140138                // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
     
    158156
    159157        DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) {
    160                 // xxx - need to handle named return values - this pass may need to happen
    161                 // after resolution? the ordering is tricky because return statements must be
    162                 // constructed - the simplest way to do that (while also handling multiple
    163                 // returns) is to structure the returnVals into a tuple, as done here.
    164                 // however, if the tuple return value is structured before resolution,
    165                 // it's difficult to resolve named return values, since the name is lost
    166                 // in conversion to a tuple. this might be easiest to deal with
    167                 // after reference types are added, as it may then be possible to
    168                 // uniformly move named return values to the parameter list directly
    169                 ValueGuard< FunctionType * > oldFtype( ftype );
     158                ValueGuard< std::list<DeclarationWithType*> > oldReturnVals( returnVals );
    170159                ValueGuard< std::string > oldFuncName( funcName );
    171160
    172                 ftype = functionDecl->get_functionType();
    173                 std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
    174                 if ( retVals.size() > 1 ) {
    175                         TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
    176                         ObjectDecl * newRet = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
    177                         retVals.clear();
    178                         retVals.push_back( newRet );
    179                 }
     161                FunctionType * type = functionDecl->get_functionType();
     162                returnVals = type->get_returnVals();
    180163                funcName = functionDecl->get_name();
    181164                DeclarationWithType * decl = Mutator::mutate( functionDecl );
     
    237220        }
    238221
    239         bool CtorDtor::isManaged( Type * type ) const {
    240                 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
    241                         // tuple is also managed if any of its components are managed
    242                         if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {
    243                                 return true;
    244                         }
    245                 }
    246                 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
    247         }
    248 
    249222        bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {
    250223                Type * type = objDecl->get_type();
     
    252225                        type = at->get_base();
    253226                }
    254                 return isManaged( type );
     227                return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
    255228        }
    256229
     
    263236                        managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) );
    264237                }
    265         }
    266 
    267         ConstructorInit * genCtorInit( ObjectDecl * objDecl ) {
    268                 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
    269                 // for each constructable object
    270                 std::list< Statement * > ctor;
    271                 std::list< Statement * > dtor;
    272 
    273                 InitExpander srcParam( objDecl->get_init() );
    274                 InitExpander nullParam( (Initializer *)NULL );
    275                 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
    276                 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
    277 
    278                 // Currently genImplicitCall produces a single Statement - a CompoundStmt
    279                 // which  wraps everything that needs to happen. As such, it's technically
    280                 // possible to use a Statement ** in the above calls, but this is inherently
    281                 // unsafe, so instead we take the slightly less efficient route, but will be
    282                 // immediately informed if somehow the above assumption is broken. In this case,
    283                 // we could always wrap the list of statements at this point with a CompoundStmt,
    284                 // but it seems reasonable at the moment for this to be done by genImplicitCall
    285                 // itself. It is possible that genImplicitCall produces no statements (e.g. if
    286                 // an array type does not have a dimension). In this case, it's fine to ignore
    287                 // the object for the purposes of construction.
    288                 assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
    289                 if ( ctor.size() == 1 ) {
    290                         // need to remember init expression, in case no ctors exist
    291                         // if ctor does exist, want to use ctor expression instead of init
    292                         // push this decision to the resolver
    293                         assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
    294                         return new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() );
    295                 }
    296                 return nullptr;
    297238        }
    298239
     
    307248                        if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl );
    308249
    309                         objDecl->set_init( genCtorInit( objDecl ) );
     250                        // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
     251                        // for each constructable object
     252                        std::list< Statement * > ctor;
     253                        std::list< Statement * > dtor;
     254
     255                        InitExpander srcParam( objDecl->get_init() );
     256                        InitExpander nullParam( (Initializer *)NULL );
     257                        SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
     258                        SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
     259
     260                        // Currently genImplicitCall produces a single Statement - a CompoundStmt
     261                        // which  wraps everything that needs to happen. As such, it's technically
     262                        // possible to use a Statement ** in the above calls, but this is inherently
     263                        // unsafe, so instead we take the slightly less efficient route, but will be
     264                        // immediately informed if somehow the above assumption is broken. In this case,
     265                        // we could always wrap the list of statements at this point with a CompoundStmt,
     266                        // but it seems reasonable at the moment for this to be done by genImplicitCall
     267                        // itself. It is possible that genImplicitCall produces no statements (e.g. if
     268                        // an array type does not have a dimension). In this case, it's fine to ignore
     269                        // the object for the purposes of construction.
     270                        assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
     271                        if ( ctor.size() == 1 ) {
     272                                // need to remember init expression, in case no ctors exist
     273                                // if ctor does exist, want to use ctor expression instead of init
     274                                // push this decision to the resolver
     275                                assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
     276                                objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
     277                        }
    310278                }
    311279                return Parent::mutate( objDecl );
     
    320288                managedTypes.beginScope();
    321289                // go through assertions and recursively add seen ctor/dtors
    322                 for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
     290                for ( TypeDecl * tyDecl : functionDecl->get_functionType()->get_forall() ) {
    323291                        for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
    324292                                assertion = assertion->acceptMutator( *this );
Note: See TracChangeset for help on using the changeset viewer.