Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/GenInit.cc

    r30b65d8 r62e5546  
    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;
     
    138136
    139137        Statement *ReturnFixer::mutate( ReturnStmt *returnStmt ) {
    140                 std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals();
     138                // update for multiple return values
    141139                assert( returnVals.size() == 0 || returnVals.size() == 1 );
    142140                // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
     
    160158
    161159        DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) {
    162                 // xxx - need to handle named return values - this pass may need to happen
    163                 // after resolution? the ordering is tricky because return statements must be
    164                 // constructed - the simplest way to do that (while also handling multiple
    165                 // returns) is to structure the returnVals into a tuple, as done here.
    166                 // however, if the tuple return value is structured before resolution,
    167                 // it's difficult to resolve named return values, since the name is lost
    168                 // in conversion to a tuple. this might be easiest to deal with
    169                 // after reference types are added, as it may then be possible to
    170                 // uniformly move named return values to the parameter list directly
    171                 ValueGuard< FunctionType * > oldFtype( ftype );
     160                ValueGuard< std::list<DeclarationWithType*> > oldReturnVals( returnVals );
    172161                ValueGuard< std::string > oldFuncName( funcName );
    173162
    174                 ftype = functionDecl->get_functionType();
    175                 std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
    176                 if ( retVals.size() > 1 ) {
    177                         TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
    178                         ObjectDecl * newRet = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
    179                         retVals.clear();
    180                         retVals.push_back( newRet );
    181                 }
     163                FunctionType * type = functionDecl->get_functionType();
     164                returnVals = type->get_returnVals();
    182165                funcName = functionDecl->get_name();
    183166                DeclarationWithType * decl = Mutator::mutate( functionDecl );
     
    239222        }
    240223
    241         bool CtorDtor::isManaged( Type * type ) const {
    242                 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
    243                         // tuple is also managed if any of its components are managed
    244                         if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {
    245                                 return true;
    246                         }
    247                 }
    248                 // a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable)
    249                 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end() || GenPoly::isPolyType( type );
    250         }
    251 
    252224        bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {
    253225                Type * type = objDecl->get_type();
     
    255227                        type = at->get_base();
    256228                }
    257                 return isManaged( type );
     229                return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
    258230        }
    259231
     
    266238                        managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) );
    267239                }
    268         }
    269 
    270         ConstructorInit * genCtorInit( ObjectDecl * objDecl ) {
    271                 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
    272                 // for each constructable object
    273                 std::list< Statement * > ctor;
    274                 std::list< Statement * > dtor;
    275 
    276                 InitExpander srcParam( objDecl->get_init() );
    277                 InitExpander nullParam( (Initializer *)NULL );
    278                 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
    279                 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
    280 
    281                 // Currently genImplicitCall produces a single Statement - a CompoundStmt
    282                 // which  wraps everything that needs to happen. As such, it's technically
    283                 // possible to use a Statement ** in the above calls, but this is inherently
    284                 // unsafe, so instead we take the slightly less efficient route, but will be
    285                 // immediately informed if somehow the above assumption is broken. In this case,
    286                 // we could always wrap the list of statements at this point with a CompoundStmt,
    287                 // but it seems reasonable at the moment for this to be done by genImplicitCall
    288                 // itself. It is possible that genImplicitCall produces no statements (e.g. if
    289                 // an array type does not have a dimension). In this case, it's fine to ignore
    290                 // the object for the purposes of construction.
    291                 assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
    292                 if ( ctor.size() == 1 ) {
    293                         // need to remember init expression, in case no ctors exist
    294                         // if ctor does exist, want to use ctor expression instead of init
    295                         // push this decision to the resolver
    296                         assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
    297                         return new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() );
    298                 }
    299                 return nullptr;
    300240        }
    301241
     
    310250                        if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl );
    311251
    312                         objDecl->set_init( genCtorInit( objDecl ) );
     252                        // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
     253                        // for each constructable object
     254                        std::list< Statement * > ctor;
     255                        std::list< Statement * > dtor;
     256
     257                        InitExpander srcParam( objDecl->get_init() );
     258                        InitExpander nullParam( (Initializer *)NULL );
     259                        SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
     260                        SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
     261
     262                        // Currently genImplicitCall produces a single Statement - a CompoundStmt
     263                        // which  wraps everything that needs to happen. As such, it's technically
     264                        // possible to use a Statement ** in the above calls, but this is inherently
     265                        // unsafe, so instead we take the slightly less efficient route, but will be
     266                        // immediately informed if somehow the above assumption is broken. In this case,
     267                        // we could always wrap the list of statements at this point with a CompoundStmt,
     268                        // but it seems reasonable at the moment for this to be done by genImplicitCall
     269                        // itself. It is possible that genImplicitCall produces no statements (e.g. if
     270                        // an array type does not have a dimension). In this case, it's fine to ignore
     271                        // the object for the purposes of construction.
     272                        assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
     273                        if ( ctor.size() == 1 ) {
     274                                // need to remember init expression, in case no ctors exist
     275                                // if ctor does exist, want to use ctor expression instead of init
     276                                // push this decision to the resolver
     277                                assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
     278                                objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
     279                        }
    313280                }
    314281                return Parent::mutate( objDecl );
     
    323290                managedTypes.beginScope();
    324291                // go through assertions and recursively add seen ctor/dtors
    325                 for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
     292                for ( TypeDecl * tyDecl : functionDecl->get_functionType()->get_forall() ) {
    326293                        for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
    327294                                assertion = assertion->acceptMutator( *this );
Note: See TracChangeset for help on using the changeset viewer.