Changeset 3f7e12cb for src/InitTweak


Ignore:
Timestamp:
Nov 8, 2017, 5:43:33 PM (8 years ago)
Author:
Aaron Moss <a3moss@…>
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, stuck-waitfor-destruct, with_gc
Children:
954908d
Parents:
78315272 (diff), e35f30a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src/InitTweak
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r78315272 r3f7e12cb  
    3636#include "FixGlobalInit.h"             // for fixGlobalInit
    3737#include "GenInit.h"                   // for genCtorDtor
    38 #include "GenPoly/DeclMutator.h"       // for DeclMutator
    3938#include "GenPoly/GenPoly.h"           // for getFunctionType
    40 #include "GenPoly/PolyMutator.h"       // for PolyMutator
    4139#include "InitTweak.h"                 // for getFunctionName, getCallArg
    4240#include "Parser/LinkageSpec.h"        // for C, Spec, Cforall, isBuiltin
     
    4644#include "SymTab/Indexer.h"            // for Indexer
    4745#include "SymTab/Mangler.h"            // for Mangler
    48 #include "SynTree/AddStmtVisitor.h"    // for AddStmtVisitor
    4946#include "SynTree/Attribute.h"         // for Attribute
    5047#include "SynTree/Constant.h"          // for Constant
     
    5855#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
    5956#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    60 #include "Tuples/Tuples.h"             // for isTtype
    6157
    6258bool ctordtorp = false; // print all debug
     
    9793                        /// true if type does not need to be copy constructed to ensure correctness
    9894                        bool skipCopyConstruct( Type * type );
    99                         void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );
     95                        void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal );
    10096                        void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
    10197
     
    187183                };
    188184
    189                 class FixCopyCtors final : public GenPoly::PolyMutator {
     185                class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {
    190186                  public:
    191187                        FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
     
    194190                        static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount );
    195191
    196                         typedef GenPoly::PolyMutator Parent;
    197                         using Parent::mutate;
    198                         virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
    199                         virtual Expression * mutate( UniqueExpr * unqExpr ) override;
    200                         virtual Expression * mutate( StmtExpr * stmtExpr ) override;
     192                        Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
     193                        void premutate( StmtExpr * stmtExpr );
     194                        void premutate( UniqueExpr * unqExpr );
    201195
    202196                        UnqCount & unqCount;
     
    220214                        void emit( CodeLocation, const Params &... params );
    221215
    222                         FunctionDecl * function = 0;
     216                        FunctionDecl * function = nullptr;
    223217                        std::set< DeclarationWithType * > unhandled;
    224218                        std::map< DeclarationWithType *, CodeLocation > usedUninit;
    225                         ObjectDecl * thisParam = 0;
     219                        ObjectDecl * thisParam = nullptr;
    226220                        bool isCtor = false; // true if current function is a constructor
    227                         StructDecl * structDecl = 0;
     221                        StructDecl * structDecl = nullptr;
    228222                };
    229223
     
    243237                };
    244238
    245                 class FixCtorExprs final : public GenPoly::DeclMutator {
    246                   public:
     239                struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer {
    247240                        /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
    248241                        static void fix( std::list< Declaration * > & translationUnit );
    249242
    250                         using GenPoly::DeclMutator::mutate;
    251                         virtual Expression * mutate( ConstructorExpr * ctorExpr ) override;
     243                        Expression * postmutate( ConstructorExpr * ctorExpr );
    252244                };
    253245        } // namespace
     
    268260
    269261                GenStructMemberCalls::generate( translationUnit );
     262
    270263                // xxx - ctor expansion currently has to be after FixCopyCtors, because there is currently a
    271264                // hack in the way untyped assignments are generated, where the first argument cannot have
     
    297290                        for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    298291                                try {
    299                                         *i = maybeMutate( *i, fixer );
     292                                        maybeMutate( *i, fixer );
    300293                                        translationUnit.splice( i, fixer.pass.staticDtorDecls );
    301294                                } catch( SemanticError &e ) {
     
    316309
    317310                void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
    318                         FixCopyCtors fixer( unqCount );
     311                        PassVisitor<FixCopyCtors> fixer( unqCount );
    319312                        mutateAll( translationUnit, fixer );
    320313                }
     
    326319
    327320                void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) {
    328                         FixCtorExprs fixer;
    329                         fixer.mutateDeclarationList( translationUnit );
     321                        PassVisitor<FixCtorExprs> fixer;
     322                        mutateAll( translationUnit, fixer );
    330323                }
    331324
    332325                Expression * InsertImplicitCalls::postmutate( ApplicationExpr * appExpr ) {
    333                         assert( appExpr );
    334 
    335326                        if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) {
    336                                 if ( LinkageSpec::isBuiltin( function->get_var()->get_linkage() ) ) {
     327                                if ( function->var->linkage.is_builtin ) {
    337328                                        // optimization: don't need to copy construct in order to call intrinsic functions
    338329                                        return appExpr;
    339330                                } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) {
    340331                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    341                                         assert( ftype );
    342                                         if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    343                                                 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    344                                                 Type * t2 = ftype->get_parameters().back()->get_type();
     332                                        assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() );
     333                                        if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->parameters.size() == 2 ) {
     334                                                Type * t1 = getPointerBase( ftype->parameters.front()->get_type() );
     335                                                Type * t2 = ftype->parameters.back()->get_type();
    345336                                                assert( t1 );
    346337
     
    368359                }
    369360
    370                 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
    371                         return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
    372                 }
     361                bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); }
    373362
    374363                Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
     
    377366                        ImplicitCtorDtorStmt * stmt = genCtorDtor( fname, var, cpArg );
    378367                        ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->get_callStmt() );
    379                         Expression * untyped = exprStmt->get_expr();
     368                        Expression * resolved = exprStmt->expr;
     369                        exprStmt->expr = nullptr; // take ownership of expr
    380370
    381371                        // resolve copy constructor
    382372                        // should only be one alternative for copy ctor and dtor expressions, since all arguments are fixed
    383373                        // (VariableExpr and already resolved expression)
    384                         CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
    385                         Expression * resolved = ResolvExpr::findVoidExpression( untyped, indexer );
     374                        CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << resolved << std::endl; )
     375                        ResolvExpr::findVoidExpression( resolved, indexer );
    386376                        assert( resolved );
    387377                        if ( resolved->get_env() ) {
     
    391381                                resolved->set_env( nullptr );
    392382                        } // if
    393 
    394383                        delete stmt;
    395384                        return resolved;
    396385                }
    397386
    398                 void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {
     387                void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal ) {
    399388                        static UniqueName tempNamer("_tmp_cp");
    400389                        assert( env );
    401390                        CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; )
    402                         assert( arg->has_result() );
    403                         Type * result = arg->get_result();
     391                        assert( arg->result );
     392                        Type * result = arg->result;
    404393                        if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types
    405394
    406                         // type may involve type variables, so apply type substitution to get temporary variable's actual type
     395                        // type may involve type variables, so apply type substitution to get temporary variable's actual type.
     396                        // Use applyFree so that types bound in function pointers are not substituted, e.g. in forall(dtype T) void (*)(T).
    407397                        result = result->clone();
    408                         env->apply( result );
    409                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     398                        env->applyFree( result );
     399                        ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr );
    410400                        tmp->get_type()->set_const( false );
    411401
     
    417407                                // if the chosen constructor is intrinsic, the copy is unnecessary, so
    418408                                // don't create the temporary and don't call the copy constructor
    419                                 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() );
    420                                 assert( function );
    421                                 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
    422                         }
     409                                VariableExpr * function = strict_dynamic_cast< VariableExpr * >( appExpr->function );
     410                                if ( function->var->linkage == LinkageSpec::Intrinsic ) {
     411                                        // arguments that need to be boxed need a temporary regardless of whether the copy constructor is intrinsic,
     412                                        // so that the object isn't changed inside of the polymorphic function
     413                                        if ( ! GenPoly::needsBoxing( formal, result, impCpCtorExpr->callExpr, env ) ) return;
     414                                }
     415                        }
     416
     417                        // set a unique name for the temporary once it's certain the call is necessary
     418                        tmp->name = tempNamer.newName();
    423419
    424420                        // replace argument to function call with temporary
    425421                        arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
    426                         impCpCtorExpr->get_tempDecls().push_back( tmp );
    427                         impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
     422                        impCpCtorExpr->tempDecls.push_back( tmp );
     423                        impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) );
    428424                }
    429425
     
    435431                        CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
    436432
    437                         ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr();
     433                        ApplicationExpr * appExpr = impCpCtorExpr->callExpr;
    438434
    439435                        // take each argument and attempt to copy construct it.
    440                         for ( Expression * & arg : appExpr->get_args() ) {
    441                                 copyConstructArg( arg, impCpCtorExpr );
     436                        FunctionType * ftype = GenPoly::getFunctionType( appExpr->function->result );
     437                        assert( ftype );
     438                        auto & params = ftype->parameters;
     439                        auto iter = params.begin();
     440                        for ( Expression * & arg : appExpr->args ) {
     441                                Type * formal = nullptr;
     442                                if ( iter != params.end() ) {
     443                                        DeclarationWithType * param = *iter++;
     444                                        formal = param->get_type();
     445                                }
     446
     447                                copyConstructArg( arg, impCpCtorExpr, formal );
    442448                        } // for
    443449
     
    445451                        // initialized with the return value and is destructed later
    446452                        // xxx - handle named return values?
    447                         Type * result = appExpr->get_result();
     453                        Type * result = appExpr->result;
    448454                        if ( ! result->isVoid() ) {
    449455                                static UniqueName retNamer("_tmp_cp_ret");
    450456                                result = result->clone();
    451457                                env->apply( result );
    452                                 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
    453                                 ret->get_type()->set_const( false );
    454                                 impCpCtorExpr->get_returnDecls().push_back( ret );
     458                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
     459                                ret->type->set_const( false );
     460                                impCpCtorExpr->returnDecls.push_back( ret );
    455461                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    456462                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    457                                         // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
     463                                        // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    458464                                        destructRet( ret, impCpCtorExpr );
    459465                                }
     
    472478                                result = result->clone();
    473479                                env->apply( result );
    474                                 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     480                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    475481                                ret->get_type()->set_const( false );
    476482                                stmtExpr->get_returnDecls().push_front( ret );
     
    493499                                visit_children = false;
    494500                        }
     501                }
     502
     503                // to prevent warnings (‘_unq0’ may be used uninitialized in this function),
     504                // insert an appropriate zero initializer for UniqueExpr temporaries.
     505                Initializer * makeInit( Type * t ) {
     506                        if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) {
     507                                // initizer for empty struct must be empty
     508                                if ( inst->baseStruct->members.empty() ) return new ListInit({});
     509                        } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {
     510                                // initizer for empty union must be empty
     511                                if ( inst->baseUnion->members.empty() ) return new ListInit({});
     512                        }
     513
     514                        return new ListInit( { new SingleInit( new ConstantExpr( Constant::from_int( 0 ) ) ) } );
    495515                }
    496516
     
    509529                        } else {
    510530                                // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
    511                                 unqExpr->set_object( new ObjectDecl( toString("_unq", unqExpr->get_id()), Type::StorageClasses(), LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );
     531                                unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), makeInit( unqExpr->get_result() ) ) );
    512532                                unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
    513533                        }
     
    515535                }
    516536
    517                 Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
     537                Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    518538                        CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; )
    519539
    520                         impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );
    521540                        std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls();
    522541                        std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls();
     
    525544                        // add all temporary declarations and their constructors
    526545                        for ( ObjectDecl * obj : tempDecls ) {
    527                                 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     546                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    528547                        } // for
    529548                        for ( ObjectDecl * obj : returnDecls ) {
    530                                 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     549                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    531550                        } // for
    532551
     
    536555                        } // for
    537556
    538                         // xxx - update to work with multiple return values
    539557                        ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front();
    540558                        Expression * callExpr = impCpCtorExpr->get_callExpr();
     
    561579                                Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    562580                                // move env from callExpr to retExpr
    563                                 retExpr->set_env( callExpr->get_env() );
    564                                 callExpr->set_env( nullptr );
     581                                std::swap( retExpr->env, callExpr->env );
    565582                                return retExpr;
    566583                        } else {
     
    569586                }
    570587
    571                 Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {
     588                void FixCopyCtors::premutate( StmtExpr * stmtExpr ) {
    572589                        // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
    573590                        // since temporaries can be shared across sub-expressions, e.g.
    574591                        //   [A, A] f();
    575592                        //   g([A] x, [A] y);
    576                         //   f(g());
     593                        //   g(f());
    577594                        // f is executed once, so the return temporary is shared across the tuple constructors for x and y.
     595                        // Explicitly mutating children instead of mutating the inner compound statment forces the temporaries to be added
     596                        // to the outer context, rather than inside of the statement expression.
     597                        visit_children = false;
    578598                        std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
    579599                        for ( Statement *& stmt : stmts ) {
    580                                 stmt = stmt->acceptMutator( *this );
     600                                stmt = stmt->acceptMutator( *visitor );
    581601                        } // for
    582                         // stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );
    583602                        assert( stmtExpr->get_result() );
    584603                        Type * result = stmtExpr->get_result();
    585604                        if ( ! result->isVoid() ) {
    586605                                for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
    587                                         stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     606                                        stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    588607                                } // for
    589608                                // add destructors after current statement
     
    592611                                } // for
    593612                                // must have a non-empty body, otherwise it wouldn't have a result
    594                                 CompoundStmt * body = stmtExpr->get_statements();
    595                                 assert( ! body->get_kids().empty() );
     613                                assert( ! stmts.empty() );
    596614                                assert( ! stmtExpr->get_returnDecls().empty() );
    597                                 body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
     615                                stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
    598616                                stmtExpr->get_returnDecls().clear();
    599617                                stmtExpr->get_dtors().clear();
     
    601619                        assert( stmtExpr->get_returnDecls().empty() );
    602620                        assert( stmtExpr->get_dtors().empty() );
    603                         return stmtExpr;
    604                 }
    605 
    606                 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
     621                }
     622
     623                void FixCopyCtors::premutate( UniqueExpr * unqExpr ) {
     624                        visit_children = false;
    607625                        unqCount[ unqExpr->get_id() ]--;
    608626                        static std::unordered_map< int, std::list< Statement * > > dtors;
    609627                        static std::unordered_map< int, UniqueExpr * > unqMap;
    610                         static std::unordered_set< int > addDeref;
    611628                        // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
    612629                        if ( unqMap.count( unqExpr->get_id() ) ) {
     
    619636                                        stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    620637                                }
    621                                 if ( addDeref.count( unqExpr->get_id() ) ) {
    622                                         // other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too
    623                                         return UntypedExpr::createDeref( unqExpr );
    624                                 }
    625                                 return unqExpr;
    626                         }
    627                         FixCopyCtors fixer( unqCount );
     638                                return;
     639                        }
     640                        PassVisitor<FixCopyCtors> fixer( unqCount );
    628641                        unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup
    629                         stmtsToAdd.splice( stmtsToAdd.end(), fixer.stmtsToAdd );
     642                        stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
    630643                        unqMap[unqExpr->get_id()] = unqExpr;
    631644                        if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
    632645                                stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    633646                        } else { // remember dtors for last instance of unique expr
    634                                 dtors[ unqExpr->get_id() ] = fixer.stmtsToAddAfter;
    635                         }
    636                         if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) {
    637                                 // unique expression is now a dereference, because the inner expression is an lvalue returning function call.
    638                                 // Normalize the expression by dereferencing the unique expression, rather than the inner expression
    639                                 // (i.e. move the dereference out a level)
    640                                 assert( getFunctionName( deref ) == "*?" );
    641                                 unqExpr->set_expr( getCallArg( deref, 0 ) );
    642                                 getCallArg( deref, 0 ) = unqExpr;
    643                                 addDeref.insert( unqExpr->get_id() );
    644                                 return deref;
    645                         }
    646                         return unqExpr;
    647                 }
    648 
    649                 DeclarationWithType *FixInit::postmutate( ObjectDecl *objDecl ) {
     647                                dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter;
     648                        }
     649                        return;
     650                }
     651
     652                DeclarationWithType * FixInit::postmutate( ObjectDecl *objDecl ) {
    650653                        // since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate)
    651654                        if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
     
    745748                                        } else {
    746749                                                ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * > ( ctor );
    747                                                 ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit->get_callStmt() );
     750                                                ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit->callStmt );
    748751                                                ApplicationExpr * ctorCall = nullptr;
    749                                                 if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->get_expr() )) && ctorCall->get_args().size() == 2 ) {
     752                                                if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->expr )) && ctorCall->get_args().size() == 2 ) {
    750753                                                        // clean up intrinsic copy constructor calls by making them into SingleInits
    751                                                         objDecl->set_init( new SingleInit( ctorCall->get_args().back() ) );
    752                                                         ctorCall->get_args().pop_back();
     754                                                        Expression * ctorArg = ctorCall->args.back();
     755                                                        std::swap( ctorArg->env, ctorCall->env );
     756                                                        objDecl->init = new SingleInit( ctorArg );
     757
     758                                                        ctorCall->args.pop_back();
    753759                                                } else {
    754760                                                        stmtsToAddAfter.push_back( ctor );
    755                                                         objDecl->set_init( nullptr );
    756                                                         ctorInit->set_ctor( nullptr );
     761                                                        objDecl->init = nullptr;
     762                                                        ctorInit->ctor = nullptr;
    757763                                                }
    758764                                        } // if
    759                                 } else if ( Initializer * init = ctorInit->get_init() ) {
    760                                         objDecl->set_init( init );
    761                                         ctorInit->set_init( nullptr );
     765                                } else if ( Initializer * init = ctorInit->init ) {
     766                                        objDecl->init = init;
     767                                        ctorInit->init = nullptr;
    762768                                } else {
    763769                                        // no constructor and no initializer, which is okay
    764                                         objDecl->set_init( nullptr );
     770                                        objDecl->init = nullptr;
    765771                                } // if
    766772                                delete ctorInit;
     
    819825                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    820826                                        Statement * dtor = ctorInit->get_dtor();
     827                                        // don't need to call intrinsic dtor, because it does nothing, but
     828                                        // non-intrinsic dtors must be called
    821829                                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    822                                                 // don't need to call intrinsic dtor, because it does nothing, but
    823                                                 // non-intrinsic dtors must be called
     830                                                // set dtor location to the object's location for error messages
     831                                                ctorInit->dtor->location = objDecl->location;
    824832                                                reverseDeclOrder.front().push_front( objDecl );
    825833                                        } // if
     
    832840                        GuardValue( labelVars );
    833841                        labelVars.clear();
     842                        // LabelFinder does not recurse into FunctionDecl, so need to visit
     843                        // its children manually.
    834844                        maybeAccept( funcDecl->type, finder );
    835845                        maybeAccept( funcDecl->statements, finder );
     
    933943                }
    934944
     945                void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) {
     946                        for ( auto d : decls ) {
     947                                indexer.addId( d );
     948                        }
     949                }
     950
     951                void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) {
     952                        for ( auto td : tds ) {
     953                                indexer.addType( td );
     954                                addIds( indexer, td->assertions );
     955                        }
     956                }
     957
    935958                void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) {
    936                         GuardValue( funcDecl );
     959                        GuardValue( function );
    937960                        GuardValue( unhandled );
    938961                        GuardValue( usedUninit );
     
    967990                }
    968991
    969                 void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) {
    970                         for ( auto d : decls ) {
    971                                 indexer.addId( d );
    972                         }
    973                 }
    974 
    975                 void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) {
    976                         for ( auto td : tds ) {
    977                                 indexer.addType( td );
    978                                 addIds( indexer, td->assertions );
    979                         }
    980                 }
    981 
    982992                void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) {
    983993                        // remove the unhandled objects from usedUninit, because a call is inserted
     
    10121022                                        // skip non-DWT members
    10131023                                        if ( ! field ) continue;
     1024                                        // skip non-constructable members
     1025                                        if ( ! tryConstruct( field ) ) continue;
    10141026                                        // skip handled members
    10151027                                        if ( ! unhandled.count( field ) ) continue;
     
    11301142                }
    11311143
    1132                 DeclarationWithType * MutatingResolver::mutate( ObjectDecl *objectDecl ) {
     1144                DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) {
    11331145                        // add object to the indexer assumes that there will be no name collisions
    11341146                        // in generated code. If this changes, add mutate methods for entities with
     
    11381150                }
    11391151
    1140                 Expression* MutatingResolver::mutate( UntypedExpr *untypedExpr ) {
    1141                         return strict_dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untypedExpr, indexer ) );
    1142                 }
    1143 
    1144                 Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) {
     1152                Expression * MutatingResolver::mutate( UntypedExpr * untypedExpr ) {
     1153                        Expression * newExpr = untypedExpr;
     1154                        ResolvExpr::findVoidExpression( newExpr, indexer );
     1155                        return newExpr;
     1156                }
     1157
     1158                Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) {
    11451159                        static UniqueName tempNamer( "_tmp_ctor_expr" );
    11461160                        // xxx - is the size check necessary?
    1147                         assert( ctorExpr->has_result() && ctorExpr->get_result()->size() == 1 );
     1161                        assert( ctorExpr->result && ctorExpr->get_result()->size() == 1 );
    11481162
    11491163                        // xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary.
    1150                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr );
    1151                         addDeclaration( tmp );
     1164                        ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr );
     1165                        declsToAddBefore.push_back( tmp );
    11521166
    11531167                        // xxx - this can be TupleAssignExpr now. Need to properly handle this case.
     
    11581172                        delete ctorExpr;
    11591173
     1174                        // build assignment and replace constructor's first argument with new temporary
    11601175                        Expression *& firstArg = callExpr->get_args().front();
    1161 
    1162                         // xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away.
    1163 
    1164                         // generate the type of assignment operator using the type of tmp minus any reference types
    1165                         Type * type = tmp->get_type()->stripReferences();
    1166                         FunctionType * ftype = SymTab::genAssignType( type );
    1167 
    1168                         // generate fake assignment decl and call it using &tmp and &firstArg
    1169                         // since tmp is guaranteed to be a reference and we want to assign pointers
    1170                         FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr );
    1171                         ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) );
    1172                         assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) );
    1173                         Expression * addrArg = new AddressExpr( firstArg );
    1174                         // if firstArg has type T&&, then &firstArg has type T*&.
    1175                         // Cast away the reference to a value type so that the argument
    1176                         // matches the assignment's parameter types
    1177                         if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) {
    1178                                 addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() );
    1179                         }
    1180                         assign->get_args().push_back( addrArg );
     1176                        Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } );
    11811177                        firstArg = new VariableExpr( tmp );
     1178
     1179                        // resolve assignment and dispose of new env
     1180                        ResolvExpr::findVoidExpression( assign, indexer );
     1181                        delete assign->env;
     1182                        assign->env = nullptr;
    11821183
    11831184                        // for constructor expr:
  • src/InitTweak/GenInit.cc

    r78315272 r3f7e12cb  
    2626#include "Common/UniqueName.h"     // for UniqueName
    2727#include "Common/utility.h"        // for ValueGuard, maybeClone
    28 #include "GenPoly/DeclMutator.h"   // for DeclMutator
    2928#include "GenPoly/GenPoly.h"       // for getFunctionType, isPolyType
    3029#include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::const_iter...
     
    6261        };
    6362
    64         struct CtorDtor : public WithGuards, public WithShortCircuiting  {
     63        struct CtorDtor : public WithGuards, public WithShortCircuiting, public WithVisitorRef<CtorDtor>  {
    6564                /// create constructor and destructor statements for object declarations.
    6665                /// the actual call statements will be added in after the resolver has run
     
    7574                // that need to be constructed or destructed
    7675                void previsit( StructDecl *aggregateDecl );
    77                 void previsit( __attribute__((unused)) UnionDecl    * aggregateDecl ) { visit_children = false; }
    78                 void previsit( __attribute__((unused)) EnumDecl     * aggregateDecl ) { visit_children = false; }
    79                 void previsit( __attribute__((unused)) TraitDecl    * aggregateDecl ) { visit_children = false; }
    80                 void previsit( __attribute__((unused)) TypeDecl     * typeDecl )      { visit_children = false; }
    81                 void previsit( __attribute__((unused)) TypedefDecl  * typeDecl )      { visit_children = false; }
    82                 void previsit( __attribute__((unused)) FunctionType * funcType )      { visit_children = false; }
     76                void previsit( AggregateDecl * ) { visit_children = false; }
     77                void previsit( NamedTypeDecl * ) { visit_children = false; }
     78                void previsit( FunctionType * ) { visit_children = false; }
    8379
    8480                void previsit( CompoundStmt * compoundStmt );
     
    8985                // should not have a ConstructorInit generated.
    9086
    91                 bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
    92                 bool isManaged( Type * type ) const; // determine if type is managed
    93                 void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
    94                 GenPoly::ScopedSet< std::string > managedTypes;
     87                ManagedTypes managedTypes;
    9588                bool inFunction = false;
    9689        };
    9790
    98         class HoistArrayDimension final : public GenPoly::DeclMutator {
    99           public:
    100                 typedef GenPoly::DeclMutator Parent;
    101 
     91        struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards {
    10292                /// hoist dimension from array types in object declaration so that it uses a single
    10393                /// const variable of type size_t, so that side effecting array dimensions are only
     
    10595                static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
    10696
    107           private:
    108                 using Parent::mutate;
    109 
    110                 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override;
    111                 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
     97                void premutate( ObjectDecl * objectDecl );
     98                DeclarationWithType * postmutate( ObjectDecl * objectDecl );
     99                void premutate( FunctionDecl *functionDecl );
    112100                // should not traverse into any of these declarations to find objects
    113101                // that need to be constructed or destructed
    114                 virtual Declaration* mutate( StructDecl *aggregateDecl ) override { return aggregateDecl; }
    115                 virtual Declaration* mutate( UnionDecl *aggregateDecl ) override { return aggregateDecl; }
    116                 virtual Declaration* mutate( EnumDecl *aggregateDecl ) override { return aggregateDecl; }
    117                 virtual Declaration* mutate( TraitDecl *aggregateDecl ) override { return aggregateDecl; }
    118                 virtual TypeDecl* mutate( TypeDecl *typeDecl ) override { return typeDecl; }
    119                 virtual Declaration* mutate( TypedefDecl *typeDecl ) override { return typeDecl; }
    120 
    121                 virtual Type* mutate( FunctionType *funcType ) override { return funcType; }
     102                void premutate( AggregateDecl * ) { visit_children = false; }
     103                void premutate( NamedTypeDecl * ) { visit_children = false; }
     104                void premutate( FunctionType * ) { visit_children = false; }
    122105
    123106                void hoist( Type * type );
     
    128111
    129112        void genInit( std::list< Declaration * > & translationUnit ) {
    130                 ReturnFixer::makeReturnTemp( translationUnit );
     113                fixReturnStatements( translationUnit );
    131114                HoistArrayDimension::hoistArrayDimension( translationUnit );
    132115                CtorDtor::generateCtorDtor( translationUnit );
    133116        }
    134117
    135         void ReturnFixer::makeReturnTemp( std::list< Declaration * > & translationUnit ) {
     118        void fixReturnStatements( std::list< Declaration * > & translationUnit ) {
    136119                PassVisitor<ReturnFixer> fixer;
    137120                mutateAll( translationUnit, fixer );
     
    143126                // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address
    144127                // is being returned
    145                 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) {
     128                if ( returnStmt->expr && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) {
    146129                        // explicitly construct the return value using the return expression and the retVal object
    147                         assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
    148 
    149                         stmtsToAddBefore.push_back( genCtorDtor( "?{}", dynamic_cast< ObjectDecl *>( returnVals.front() ), returnStmt->get_expr() ) );
     130                        assertf( returnVals.front()->name != "", "Function %s has unnamed return value\n", funcName.c_str() );
     131
     132                        ObjectDecl * retVal = strict_dynamic_cast< ObjectDecl * >( returnVals.front() );
     133                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( returnStmt->expr ) ) {
     134                                // return statement has already been mutated - don't need to do it again
     135                                if ( varExpr->var == retVal ) return;
     136                        }
     137                        stmtsToAddBefore.push_back( genCtorDtor( "?{}", retVal, returnStmt->get_expr() ) );
    150138
    151139                        // return the retVal object
    152                         returnStmt->set_expr( new VariableExpr( returnVals.front() ) );
     140                        returnStmt->expr = new VariableExpr( returnVals.front() );
    153141                } // if
    154142        }
     
    158146                GuardValue( funcName );
    159147
    160                 ftype = functionDecl->get_functionType();
    161                 funcName = functionDecl->get_name();
     148                ftype = functionDecl->type;
     149                funcName = functionDecl->name;
    162150        }
    163151
     
    165153        // which would be incorrect if it is a side-effecting computation.
    166154        void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
    167                 HoistArrayDimension hoister;
    168                 hoister.mutateDeclarationList( translationUnit );
    169         }
    170 
    171         DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {
     155                PassVisitor<HoistArrayDimension> hoister;
     156                mutateAll( translationUnit, hoister );
     157        }
     158
     159        void HoistArrayDimension::premutate( ObjectDecl * objectDecl ) {
     160                GuardValue( storageClasses );
    172161                storageClasses = objectDecl->get_storageClasses();
    173                 DeclarationWithType * temp = Parent::mutate( objectDecl );
     162        }
     163
     164        DeclarationWithType * HoistArrayDimension::postmutate( ObjectDecl * objectDecl ) {
    174165                hoist( objectDecl->get_type() );
    175                 return temp;
     166                return objectDecl;
    176167        }
    177168
     
    194185
    195186                        arrayType->set_dimension( new VariableExpr( arrayDimension ) );
    196                         addDeclaration( arrayDimension );
     187                        declsToAddBefore.push_back( arrayDimension );
    197188
    198189                        hoist( arrayType->get_base() );
     
    201192        }
    202193
    203         DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
    204                 ValueGuard< bool > oldInFunc( inFunction );
    205                 inFunction = true;
    206                 DeclarationWithType * decl = Parent::mutate( functionDecl );
    207                 return decl;
     194        void HoistArrayDimension::premutate( FunctionDecl * ) {
     195                GuardValue( inFunction );
    208196        }
    209197
     
    213201        }
    214202
    215         bool CtorDtor::isManaged( Type * type ) const {
    216                 // at least for now, references are never constructed
     203        bool ManagedTypes::isManaged( Type * type ) const {
     204                // references are never constructed
    217205                if ( dynamic_cast< ReferenceType * >( type ) ) return false;
    218206                // need to clear and reset qualifiers when determining if a type is managed
     
    221209                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
    222210                        // tuple is also managed if any of its components are managed
    223                         if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {
     211                        if ( std::any_of( tupleType->types.begin(), tupleType->types.end(), [&](Type * type) { return isManaged( type ); }) ) {
    224212                                return true;
    225213                        }
    226214                }
    227215                // 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)
    228                 return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end() || GenPoly::isPolyType( type );
    229         }
    230 
    231         bool CtorDtor::isManaged( ObjectDecl * objDecl ) const {
     216                return managedTypes.find( SymTab::Mangler::mangleConcrete( type ) ) != managedTypes.end() || GenPoly::isPolyType( type );
     217        }
     218
     219        bool ManagedTypes::isManaged( ObjectDecl * objDecl ) const {
    232220                Type * type = objDecl->get_type();
    233221                while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     
    237225        }
    238226
    239         void CtorDtor::handleDWT( DeclarationWithType * dwt ) {
     227        void ManagedTypes::handleDWT( DeclarationWithType * dwt ) {
    240228                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
    241229                if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) {
     
    244232                        Type * type = InitTweak::getPointerBase( params.front()->get_type() );
    245233                        assert( type );
    246                         managedTypes.insert( SymTab::Mangler::mangle( type ) );
    247                 }
    248         }
     234                        managedTypes.insert( SymTab::Mangler::mangleConcrete( type ) );
     235                }
     236        }
     237
     238        void ManagedTypes::handleStruct( StructDecl * aggregateDecl ) {
     239                // don't construct members, but need to take note if there is a managed member,
     240                // because that means that this type is also managed
     241                for ( Declaration * member : aggregateDecl->get_members() ) {
     242                        if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
     243                                if ( isManaged( field ) ) {
     244                                        // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that
     245                                        // polymorphic constructors make generic types managed types
     246                                        StructInstType inst( Type::Qualifiers(), aggregateDecl );
     247                                        managedTypes.insert( SymTab::Mangler::mangleConcrete( &inst ) );
     248                                        break;
     249                                }
     250                        }
     251                }
     252        }
     253
     254        void ManagedTypes::beginScope() { managedTypes.beginScope(); }
     255        void ManagedTypes::endScope() { managedTypes.endScope(); }
    249256
    250257        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) {
     
    291298
    292299        void CtorDtor::previsit( ObjectDecl * objDecl ) {
    293                 handleDWT( objDecl );
     300                managedTypes.handleDWT( objDecl );
    294301                // hands off if @=, extern, builtin, etc.
    295302                // even if unmanaged, try to construct global or static if initializer is not constexpr, since this is not legal C
    296                 if ( tryConstruct( objDecl ) && ( isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {
     303                if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {
    297304                        // constructed objects cannot be designated
    298305                        if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n", objDecl );
     
    305312
    306313        void CtorDtor::previsit( FunctionDecl *functionDecl ) {
     314                visit_children = false;  // do not try and construct parameters or forall parameters
    307315                GuardValue( inFunction );
    308316                inFunction = true;
    309317
    310                 handleDWT( functionDecl );
     318                managedTypes.handleDWT( functionDecl );
    311319
    312320                GuardScope( managedTypes );
     
    314322                for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
    315323                        for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
    316                                 handleDWT( assertion );
     324                                managedTypes.handleDWT( assertion );
    317325                        }
    318326                }
    319327
    320                 PassVisitor<CtorDtor> newCtorDtor;
    321                 newCtorDtor.pass = *this;
    322                 maybeAccept( functionDecl->get_statements(), newCtorDtor );
    323                 visit_children = false;  // do not try and construct parameters or forall parameters - must happen after maybeAccept
     328                maybeAccept( functionDecl->get_statements(), *visitor );
    324329        }
    325330
     
    327332                visit_children = false; // do not try to construct and destruct aggregate members
    328333
    329                 // don't construct members, but need to take note if there is a managed member,
    330                 // because that means that this type is also managed
    331                 for ( Declaration * member : aggregateDecl->get_members() ) {
    332                         if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
    333                                 if ( isManaged( field ) ) {
    334                                         StructInstType inst( Type::Qualifiers(), aggregateDecl );
    335                                         managedTypes.insert( SymTab::Mangler::mangle( &inst ) );
    336                                         break;
    337                                 }
    338                         }
    339                 }
    340         }
    341 
    342         void CtorDtor::previsit( __attribute__((unused)) CompoundStmt * compoundStmt ) {
     334                managedTypes.handleStruct( aggregateDecl );
     335        }
     336
     337        void CtorDtor::previsit( CompoundStmt * ) {
    343338                GuardScope( managedTypes );
    344339        }
  • src/InitTweak/GenInit.h

    r78315272 r3f7e12cb  
    1616#pragma once
    1717
    18 #include <list>               // for list
    19 #include <string>             // for string
     18#include <list>                // for list
     19#include <string>              // for string
    2020
    21 #include "SynTree/SynTree.h"  // for Visitor Nodes
     21#include "SynTree/SynTree.h"   // for Visitor Nodes
     22
     23#include "GenPoly/ScopedSet.h" // for ScopedSet
    2224
    2325namespace InitTweak {
     
    2527        void genInit( std::list< Declaration * > & translationUnit );
    2628
    27   /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
    28   ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr );
     29        /// Converts return statements into copy constructor calls on the hidden return variable
     30        void fixReturnStatements( std::list< Declaration * > & translationUnit );
     31
     32        /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
     33        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr );
    2934
    3035        /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
    3136        ConstructorInit * genCtorInit( ObjectDecl * objDecl );
     37
     38        class ManagedTypes {
     39        public:
     40                bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
     41                bool isManaged( Type * type ) const; // determine if type is managed
     42
     43                void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
     44                void handleStruct( StructDecl * aggregateDecl ); // add type to managed if child is managed
     45
     46                void beginScope();
     47                void endScope();
     48        private:
     49                GenPoly::ScopedSet< std::string > managedTypes;
     50        };
    3251} // namespace
    3352
  • src/InitTweak/InitTweak.cc

    r78315272 r3f7e12cb  
    1 #include <stddef.h>                // for NULL
    21#include <algorithm>               // for find, all_of
    32#include <cassert>                 // for assertf, assert, strict_dynamic_cast
     
    2322#include "SynTree/Type.h"          // for FunctionType, ArrayType, PointerType
    2423#include "SynTree/Visitor.h"       // for Visitor, maybeAccept
     24#include "Tuples/Tuples.h"         // for Tuples::isTtype
    2525
    2626class UntypedValofExpr;
     
    170170        }
    171171
     172        bool InitExpander::addReference() {
     173                bool added = false;
     174                for ( Expression *& expr : cur ) {
     175                        expr = new AddressExpr( expr );
     176                        added = true;
     177                }
     178                return added;
     179        }
     180
    172181        namespace {
    173182                /// given index i, dimension d, initializer init, and callExpr f, generates
     
    184193                        callExpr->get_args().splice( callExpr->get_args().end(), args );
    185194
    186                         *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );
     195                        *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), nullptr );
    187196
    188197                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
     
    250259        // To accomplish this, generate switch statement, consuming all of expander's elements
    251260        Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    252                 if ( ! init ) return NULL;
     261                if ( ! init ) return nullptr;
    253262                CompoundStmt * block = new CompoundStmt( noLabels );
    254263                build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
    255264                if ( block->get_kids().empty() ) {
    256265                        delete block;
    257                         return NULL;
     266                        return nullptr;
    258267                } else {
    259                         init = NULL; // init was consumed in creating the list init
     268                        init = nullptr; // init was consumed in creating the list init
    260269                        return block;
    261270                }
    262271        }
    263272
    264         Statement * ExprImpl::buildListInit( __attribute((unused)) UntypedExpr * dst, __attribute((unused)) std::list< Expression * > & indices ) {
    265                 return NULL;
     273        Statement * ExprImpl::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
     274                return nullptr;
    266275        }
    267276
     
    270279        }
    271280
    272         bool tryConstruct( ObjectDecl * objDecl ) {
     281        Type * getTypeofThis( FunctionType * ftype ) {
     282                assertf( ftype, "getTypeofThis: nullptr ftype" );
     283                ObjectDecl * thisParam = getParamThis( ftype );
     284                ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( thisParam->type );
     285                return refType->base;
     286        }
     287
     288        ObjectDecl * getParamThis( FunctionType * ftype ) {
     289                assertf( ftype, "getParamThis: nullptr ftype" );
     290                auto & params = ftype->parameters;
     291                assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( ftype ).c_str() );
     292                return strict_dynamic_cast< ObjectDecl * >( params.front() );
     293        }
     294
     295        bool tryConstruct( DeclarationWithType * dwt ) {
     296                ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt );
     297                if ( ! objDecl ) return false;
    273298                return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
    274                         (objDecl->get_init() == NULL ||
    275                                 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() ))
    276                         && ! objDecl->get_storageClasses().is_extern;
     299                        (objDecl->get_init() == nullptr ||
     300                                ( objDecl->get_init() != nullptr && objDecl->get_init()->get_maybeConstructed() ))
     301                        && ! objDecl->get_storageClasses().is_extern
     302                        && isConstructable( objDecl->type );
     303        }
     304
     305        bool isConstructable( Type * type ) {
     306                return ! dynamic_cast< VarArgsType * >( type ) && ! dynamic_cast< ReferenceType * >( type ) && ! dynamic_cast< FunctionType * >( type ) && ! Tuples::isTtype( type );
    277307        }
    278308
     
    314344                collectCtorDtorCalls( stmt, matches );
    315345                assert( matches.size() <= 1 );
    316                 return matches.size() == 1 ? matches.front() : NULL;
     346                return matches.size() == 1 ? matches.front() : nullptr;
    317347        }
    318348
     
    332362                        assert( expr );
    333363                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
    334                                 return varExpr->get_var();
     364                                return varExpr->var;
    335365                        } else if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) {
    336                                 return memberExpr->get_member();
     366                                return memberExpr->member;
    337367                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    338                                 return getCalledFunction( castExpr->get_arg() );
     368                                return getCalledFunction( castExpr->arg );
    339369                        } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( expr ) ) {
    340370                                return handleDerefCalledFunction( untypedExpr );
     
    342372                                return handleDerefCalledFunction( appExpr );
    343373                        } else if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) {
    344                                 return getCalledFunction( addrExpr->get_arg() );
     374                                return getCalledFunction( addrExpr->arg );
     375                        } else if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( expr ) ) {
     376                                return getCalledFunction( commaExpr->arg2 );
    345377                        }
    346378                        return nullptr;
     
    359391        ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
    360392                ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
    361                 if ( ! appExpr ) return NULL;
     393                if ( ! appExpr ) return nullptr;
    362394                DeclarationWithType * function = getCalledFunction( appExpr->get_function() );
    363395                assertf( function, "getCalledFunction returned nullptr: %s", toString( appExpr->get_function() ).c_str() );
    364396                // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
    365397                // will call all member dtors, and some members may have a user defined dtor.
    366                 return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;
     398                return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : nullptr;
    367399        }
    368400
     
    482514                        return refType->get_base();
    483515                } else {
    484                         return NULL;
     516                        return nullptr;
    485517                }
    486518        }
     
    488520        Type * isPointerType( Type * type ) {
    489521                if ( getPointerBase( type ) ) return type;
    490                 else return NULL;
     522                else return nullptr;
    491523        }
    492524
     
    557589        FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname ) {
    558590                FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl );
    559                 if ( ! function ) return 0;
    560                 if ( function->get_name() != fname ) return 0;
    561                 FunctionType * ftype = function->get_functionType();
    562                 if ( ftype->get_parameters().size() != 2 ) return 0;
     591                if ( ! function ) return nullptr;
     592                if ( function->name != fname ) return nullptr;
     593                FunctionType * ftype = function->type;
     594                if ( ftype->parameters.size() != 2 ) return nullptr;
    563595
    564596                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    565                 Type * t2 = ftype->get_parameters().back()->get_type();
     597                Type * t2 = ftype->parameters.back()->get_type();
    566598                assert( t1 );
    567599
     
    583615        }
    584616        FunctionDecl * isDefaultConstructor( Declaration * decl ) {
    585                 if ( isConstructor( decl->get_name() ) ) {
     617                if ( isConstructor( decl->name ) ) {
    586618                        if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
    587                                 if ( func->get_functionType()->get_parameters().size() == 1 ) {
     619                                if ( func->type->parameters.size() == 1 ) {
    588620                                        return func;
    589621                                }
  • src/InitTweak/InitTweak.h

    r78315272 r3f7e12cb  
    3030        FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname );
    3131
     32        /// returns the base type of the first parameter to a constructor/destructor/assignment function
     33        Type * getTypeofThis( FunctionType * ftype );
     34
     35        /// returns the first parameter of a constructor/destructor/assignment function
     36        ObjectDecl * getParamThis( FunctionType * ftype );
     37
    3238        /// transform Initializer into an argument list that can be passed to a call expression
    3339        std::list< Expression * > makeInitList( Initializer * init );
    3440
    35         /// True if the resolver should try to construct objDecl
    36         bool tryConstruct( ObjectDecl * objDecl );
     41        /// True if the resolver should try to construct dwt
     42        bool tryConstruct( DeclarationWithType * dwt );
     43
     44        /// True if the type can have a user-defined constructor
     45        bool isConstructable( Type * t );
    3746
    3847        /// True if the Initializer contains designations
     
    96105                void addArrayIndex( Expression * index, Expression * dimension );
    97106                void clearArrayIndices();
     107                bool addReference();
    98108
    99109                class ExpanderImpl;
Note: See TracChangeset for help on using the changeset viewer.