Changeset cce9429 for src/InitTweak


Ignore:
Timestamp:
Dec 13, 2016, 6:42:39 PM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
1aa4b71
Parents:
31f379c
Message:

fix function return type in Validate and add single return decl, construct the return decl, fix polymorphic functions to use the return decl

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/GenInit.cc

    r31f379c rcce9429  
    4646                ReturnFixer();
    4747
    48                 using GenPoly::PolyMutator::mutate;
     48                typedef GenPoly::PolyMutator Parent;
     49                using Parent::mutate;
    4950                virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
    5051                virtual Statement * mutate( ReturnStmt * returnStmt ) override;
     
    142143                // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
    143144                // is being returned
     145                // Note: under the assumption that assignments return *this, checking for ?=? here is an optimization, since it shouldn't be necessary to copy construct `this`. This is a temporary optimization until reference types are added, at which point this should be removed, along with the analogous optimization in copy constructor generation.
    144146                if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_isLvalue() ) {
    145                         // ensure return value is not destructed by explicitly creating
    146                         // an empty SingleInit node wherein maybeConstruct is false
    147                         ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, returnVals.front()->get_type()->clone(), new ListInit( std::list<Initializer*>(), noDesignators, false ) );
    148                         stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
    149 
    150                         // and explicitly create the constructor expression separately
     147                        // explicitly construct the return value using the return expression and the retVal object
     148                        assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
    151149                        UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) );
    152                         construct->get_args().push_back( new AddressExpr( new VariableExpr( newObj ) ) );
     150                        construct->get_args().push_back( new AddressExpr( new VariableExpr( returnVals.front() ) ) );
    153151                        construct->get_args().push_back( returnStmt->get_expr() );
    154152                        stmtsToAdd.push_back(new ExprStmt(noLabels, construct));
    155153
    156                         returnStmt->set_expr( new VariableExpr( newObj ) );
     154                        // return the retVal object
     155                        returnStmt->set_expr( new VariableExpr( returnVals.front() ) );
    157156                } // if
    158157                return returnStmt;
     
    160159
    161160        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
    171161                ValueGuard< FunctionType * > oldFtype( ftype );
    172162                ValueGuard< std::string > oldFuncName( funcName );
    173163
    174164                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                 }
    182165                funcName = functionDecl->get_name();
    183                 DeclarationWithType * decl = Mutator::mutate( functionDecl );
    184                 return decl;
     166                return Parent::mutate( functionDecl );
    185167        }
    186168
Note: See TracChangeset for help on using the changeset viewer.