Changeset a2d4d1c for src/InitTweak


Ignore:
Timestamp:
Sep 26, 2017, 10:15:38 AM (8 years ago)
Author:
Thierry Delisle <tdelisle@…>
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:
19c43b7
Parents:
4dfa562 (diff), a139c11 (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

    r4dfa562 ra2d4d1c  
    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
     
    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;
     
    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
     
    316308
    317309                void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
    318                         FixCopyCtors fixer( unqCount );
     310                        PassVisitor<FixCopyCtors> fixer( unqCount );
    319311                        mutateAll( translationUnit, fixer );
    320312                }
     
    326318
    327319                void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) {
    328                         FixCtorExprs fixer;
    329                         fixer.mutateDeclarationList( translationUnit );
     320                        PassVisitor<FixCtorExprs> fixer;
     321                        mutateAll( translationUnit, fixer );
    330322                }
    331323
     
    339331                                } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) {
    340332                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    341                                         assert( ftype );
     333                                        assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() );
    342334                                        if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    343335                                                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
     
    368360                }
    369361
    370                 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
    371                         return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
    372                 }
     362                bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); }
    373363
    374364                Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
     
    407397                        result = result->clone();
    408398                        env->apply( result );
    409                         ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     399                        ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr );
    410400                        tmp->get_type()->set_const( false );
    411401
     
    421411                                if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
    422412                        }
     413
     414                        // set a unique name for the temporary once it's certain the call is necessary
     415                        tmp->name = tempNamer.newName();
    423416
    424417                        // replace argument to function call with temporary
     
    450443                                result = result->clone();
    451444                                env->apply( result );
    452                                 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     445                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    453446                                ret->get_type()->set_const( false );
    454447                                impCpCtorExpr->get_returnDecls().push_back( ret );
    455448                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    456449                                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
     450                                        // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    458451                                        destructRet( ret, impCpCtorExpr );
    459452                                }
     
    472465                                result = result->clone();
    473466                                env->apply( result );
    474                                 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
     467                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    475468                                ret->get_type()->set_const( false );
    476469                                stmtExpr->get_returnDecls().push_front( ret );
     
    509502                        } else {
    510503                                // 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 ) );
     504                                unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), nullptr ) );
    512505                                unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
    513506                        }
     
    515508                }
    516509
    517                 Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
     510                Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    518511                        CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; )
    519512
    520                         impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );
    521513                        std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls();
    522514                        std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls();
     
    525517                        // add all temporary declarations and their constructors
    526518                        for ( ObjectDecl * obj : tempDecls ) {
    527                                 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     519                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    528520                        } // for
    529521                        for ( ObjectDecl * obj : returnDecls ) {
    530                                 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     522                                stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    531523                        } // for
    532524
     
    536528                        } // for
    537529
    538                         // xxx - update to work with multiple return values
    539530                        ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front();
    540531                        Expression * callExpr = impCpCtorExpr->get_callExpr();
     
    569560                }
    570561
    571                 Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {
     562                void FixCopyCtors::premutate( StmtExpr * stmtExpr ) {
    572563                        // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
    573564                        // since temporaries can be shared across sub-expressions, e.g.
    574565                        //   [A, A] f();
    575566                        //   g([A] x, [A] y);
    576                         //   f(g());
     567                        //   g(f());
    577568                        // f is executed once, so the return temporary is shared across the tuple constructors for x and y.
     569                        // Explicitly mutating children instead of mutating the inner compound statment forces the temporaries to be added
     570                        // to the outer context, rather than inside of the statement expression.
     571                        visit_children = false;
    578572                        std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
    579573                        for ( Statement *& stmt : stmts ) {
    580                                 stmt = stmt->acceptMutator( *this );
     574                                stmt = stmt->acceptMutator( *visitor );
    581575                        } // for
    582                         // stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );
    583576                        assert( stmtExpr->get_result() );
    584577                        Type * result = stmtExpr->get_result();
    585578                        if ( ! result->isVoid() ) {
    586579                                for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
    587                                         stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
     580                                        stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
    588581                                } // for
    589582                                // add destructors after current statement
     
    592585                                } // for
    593586                                // 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() );
     587                                assert( ! stmts.empty() );
    596588                                assert( ! stmtExpr->get_returnDecls().empty() );
    597                                 body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
     589                                stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
    598590                                stmtExpr->get_returnDecls().clear();
    599591                                stmtExpr->get_dtors().clear();
     
    601593                        assert( stmtExpr->get_returnDecls().empty() );
    602594                        assert( stmtExpr->get_dtors().empty() );
    603                         return stmtExpr;
    604                 }
    605 
    606                 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
     595                }
     596
     597                void FixCopyCtors::premutate( UniqueExpr * unqExpr ) {
     598                        visit_children = false;
    607599                        unqCount[ unqExpr->get_id() ]--;
    608600                        static std::unordered_map< int, std::list< Statement * > > dtors;
    609601                        static std::unordered_map< int, UniqueExpr * > unqMap;
    610                         static std::unordered_set< int > addDeref;
    611602                        // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
    612603                        if ( unqMap.count( unqExpr->get_id() ) ) {
     
    619610                                        stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    620611                                }
    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 );
     612                                return;
     613                        }
     614                        PassVisitor<FixCopyCtors> fixer( unqCount );
    628615                        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 );
     616                        stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
    630617                        unqMap[unqExpr->get_id()] = unqExpr;
    631618                        if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
    632619                                stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
    633620                        } 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;
     621                                dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter;
     622                        }
     623                        return;
    647624                }
    648625
     
    819796                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
    820797                                        Statement * dtor = ctorInit->get_dtor();
     798                                        // don't need to call intrinsic dtor, because it does nothing, but
     799                                        // non-intrinsic dtors must be called
    821800                                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    822                                                 // don't need to call intrinsic dtor, because it does nothing, but
    823                                                 // non-intrinsic dtors must be called
     801                                                // set dtor location to the object's location for error messages
     802                                                ctorInit->dtor->location = objDecl->location;
    824803                                                reverseDeclOrder.front().push_front( objDecl );
    825804                                        } // if
     
    1012991                                        // skip non-DWT members
    1013992                                        if ( ! field ) continue;
     993                                        // skip non-constructable members
     994                                        if ( ! tryConstruct( field ) ) continue;
    1014995                                        // skip handled members
    1015996                                        if ( ! unhandled.count( field ) ) continue;
     
    11421123                }
    11431124
    1144                 Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) {
     1125                Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) {
    11451126                        static UniqueName tempNamer( "_tmp_ctor_expr" );
    11461127                        // xxx - is the size check necessary?
     
    11481129
    11491130                        // 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 );
     1131                        ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr );
     1132                        declsToAddBefore.push_back( tmp );
    11521133
    11531134                        // xxx - this can be TupleAssignExpr now. Need to properly handle this case.
     
    11581139                        delete ctorExpr;
    11591140
     1141                        // build assignment and replace constructor's first argument with new temporary
    11601142                        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 );
     1143                        Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } );
    11811144                        firstArg = new VariableExpr( tmp );
     1145
     1146                        // resolve assignment and dispose of new env
     1147                        Expression * resolvedAssign = ResolvExpr::findVoidExpression( assign, indexer );
     1148                        delete resolvedAssign->env;
     1149                        resolvedAssign->env = nullptr;
     1150                        delete assign;
    11821151
    11831152                        // for constructor expr:
     
    11881157                        //   T & tmp;
    11891158                        //   &tmp = &x, ?{}(tmp), tmp
    1190                         CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
     1159                        CommaExpr * commaExpr = new CommaExpr( resolvedAssign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
    11911160                        commaExpr->set_env( env );
    11921161                        return commaExpr;
  • src/InitTweak/GenInit.cc

    r4dfa562 ra2d4d1c  
    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 );
     
    9692        };
    9793
    98         class HoistArrayDimension final : public GenPoly::DeclMutator {
    99           public:
    100                 typedef GenPoly::DeclMutator Parent;
    101 
     94        struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards {
    10295                /// hoist dimension from array types in object declaration so that it uses a single
    10396                /// const variable of type size_t, so that side effecting array dimensions are only
     
    10598                static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
    10699
    107           private:
    108                 using Parent::mutate;
    109 
    110                 virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override;
    111                 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
     100                void premutate( ObjectDecl * objectDecl );
     101                DeclarationWithType * postmutate( ObjectDecl * objectDecl );
     102                void premutate( FunctionDecl *functionDecl );
    112103                // should not traverse into any of these declarations to find objects
    113104                // 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; }
     105                void premutate( AggregateDecl * ) { visit_children = false; }
     106                void premutate( NamedTypeDecl * ) { visit_children = false; }
     107                void premutate( FunctionType * ) { visit_children = false; }
    122108
    123109                void hoist( Type * type );
     
    128114
    129115        void genInit( std::list< Declaration * > & translationUnit ) {
    130                 ReturnFixer::makeReturnTemp( translationUnit );
     116                fixReturnStatements( translationUnit );
    131117                HoistArrayDimension::hoistArrayDimension( translationUnit );
    132118                CtorDtor::generateCtorDtor( translationUnit );
    133119        }
    134120
    135         void ReturnFixer::makeReturnTemp( std::list< Declaration * > & translationUnit ) {
     121        void fixReturnStatements( std::list< Declaration * > & translationUnit ) {
    136122                PassVisitor<ReturnFixer> fixer;
    137123                mutateAll( translationUnit, fixer );
     
    143129                // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address
    144130                // is being returned
    145                 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) {
     131                if ( returnStmt->get_expr() && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) {
    146132                        // explicitly construct the return value using the return expression and the retVal object
    147133                        assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
     
    158144                GuardValue( funcName );
    159145
    160                 ftype = functionDecl->get_functionType();
    161                 funcName = functionDecl->get_name();
     146                ftype = functionDecl->type;
     147                funcName = functionDecl->name;
    162148        }
    163149
     
    165151        // which would be incorrect if it is a side-effecting computation.
    166152        void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
    167                 HoistArrayDimension hoister;
    168                 hoister.mutateDeclarationList( translationUnit );
    169         }
    170 
    171         DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {
     153                PassVisitor<HoistArrayDimension> hoister;
     154                mutateAll( translationUnit, hoister );
     155        }
     156
     157        void HoistArrayDimension::premutate( ObjectDecl * objectDecl ) {
     158                GuardValue( storageClasses );
    172159                storageClasses = objectDecl->get_storageClasses();
    173                 DeclarationWithType * temp = Parent::mutate( objectDecl );
     160        }
     161
     162        DeclarationWithType * HoistArrayDimension::postmutate( ObjectDecl * objectDecl ) {
    174163                hoist( objectDecl->get_type() );
    175                 return temp;
     164                return objectDecl;
    176165        }
    177166
     
    194183
    195184                        arrayType->set_dimension( new VariableExpr( arrayDimension ) );
    196                         addDeclaration( arrayDimension );
     185                        declsToAddBefore.push_back( arrayDimension );
    197186
    198187                        hoist( arrayType->get_base() );
     
    201190        }
    202191
    203         DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
    204                 ValueGuard< bool > oldInFunc( inFunction );
    205                 inFunction = true;
    206                 DeclarationWithType * decl = Parent::mutate( functionDecl );
    207                 return decl;
     192        void HoistArrayDimension::premutate( FunctionDecl * ) {
     193                GuardValue( inFunction );
    208194        }
    209195
     
    214200
    215201        bool CtorDtor::isManaged( Type * type ) const {
    216                 // at least for now, references are never constructed
     202                // references are never constructed
    217203                if ( dynamic_cast< ReferenceType * >( type ) ) return false;
    218204                // need to clear and reset qualifiers when determining if a type is managed
     
    221207                if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
    222208                        // 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 ); }) ) {
     209                        if ( std::any_of( tupleType->types.begin(), tupleType->types.end(), [&](Type * type) { return isManaged( type ); }) ) {
    224210                                return true;
    225211                        }
     
    305291
    306292        void CtorDtor::previsit( FunctionDecl *functionDecl ) {
     293                visit_children = false;  // do not try and construct parameters or forall parameters
    307294                GuardValue( inFunction );
    308295                inFunction = true;
     
    318305                }
    319306
    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
     307                maybeAccept( functionDecl->get_statements(), *visitor );
    324308        }
    325309
     
    340324        }
    341325
    342         void CtorDtor::previsit( __attribute__((unused)) CompoundStmt * compoundStmt ) {
     326        void CtorDtor::previsit( CompoundStmt * ) {
    343327                GuardScope( managedTypes );
    344328        }
  • src/InitTweak/GenInit.h

    r4dfa562 ra2d4d1c  
    2525        void genInit( std::list< Declaration * > & translationUnit );
    2626
    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 );
     27        /// Converts return statements into copy constructor calls on the hidden return variable
     28        void fixReturnStatements( std::list< Declaration * > & translationUnit );
     29
     30        /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
     31        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr );
    2932
    3033        /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
  • src/InitTweak/InitTweak.cc

    r4dfa562 ra2d4d1c  
    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;
     
    184184                        callExpr->get_args().splice( callExpr->get_args().end(), args );
    185185
    186                         *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );
     186                        *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), nullptr );
    187187
    188188                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
     
    250250        // To accomplish this, generate switch statement, consuming all of expander's elements
    251251        Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    252                 if ( ! init ) return NULL;
     252                if ( ! init ) return nullptr;
    253253                CompoundStmt * block = new CompoundStmt( noLabels );
    254254                build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
    255255                if ( block->get_kids().empty() ) {
    256256                        delete block;
    257                         return NULL;
     257                        return nullptr;
    258258                } else {
    259                         init = NULL; // init was consumed in creating the list init
     259                        init = nullptr; // init was consumed in creating the list init
    260260                        return block;
    261261                }
    262262        }
    263263
    264         Statement * ExprImpl::buildListInit( __attribute((unused)) UntypedExpr * dst, __attribute((unused)) std::list< Expression * > & indices ) {
    265                 return NULL;
     264        Statement * ExprImpl::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
     265                return nullptr;
    266266        }
    267267
     
    270270        }
    271271
    272         bool tryConstruct( ObjectDecl * objDecl ) {
     272        bool tryConstruct( DeclarationWithType * dwt ) {
     273                ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt );
     274                if ( ! objDecl ) return false;
    273275                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;
     276                        (objDecl->get_init() == nullptr ||
     277                                ( objDecl->get_init() != nullptr && objDecl->get_init()->get_maybeConstructed() ))
     278                        && ! objDecl->get_storageClasses().is_extern
     279                        && isConstructable( objDecl->type );
     280        }
     281
     282        bool isConstructable( Type * type ) {
     283                return ! dynamic_cast< VarArgsType * >( type ) && ! dynamic_cast< ReferenceType * >( type ) && ! dynamic_cast< FunctionType * >( type ) && ! Tuples::isTtype( type );
    277284        }
    278285
     
    314321                collectCtorDtorCalls( stmt, matches );
    315322                assert( matches.size() <= 1 );
    316                 return matches.size() == 1 ? matches.front() : NULL;
     323                return matches.size() == 1 ? matches.front() : nullptr;
    317324        }
    318325
     
    359366        ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
    360367                ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
    361                 if ( ! appExpr ) return NULL;
     368                if ( ! appExpr ) return nullptr;
    362369                DeclarationWithType * function = getCalledFunction( appExpr->get_function() );
    363370                assertf( function, "getCalledFunction returned nullptr: %s", toString( appExpr->get_function() ).c_str() );
    364371                // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
    365372                // will call all member dtors, and some members may have a user defined dtor.
    366                 return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;
     373                return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : nullptr;
    367374        }
    368375
     
    482489                        return refType->get_base();
    483490                } else {
    484                         return NULL;
     491                        return nullptr;
    485492                }
    486493        }
     
    488495        Type * isPointerType( Type * type ) {
    489496                if ( getPointerBase( type ) ) return type;
    490                 else return NULL;
     497                else return nullptr;
    491498        }
    492499
  • src/InitTweak/InitTweak.h

    r4dfa562 ra2d4d1c  
    3333        std::list< Expression * > makeInitList( Initializer * init );
    3434
    35         /// True if the resolver should try to construct objDecl
    36         bool tryConstruct( ObjectDecl * objDecl );
     35        /// True if the resolver should try to construct dwt
     36        bool tryConstruct( DeclarationWithType * dwt );
     37
     38        /// True if the type can have a user-defined constructor
     39        bool isConstructable( Type * t );
    3740
    3841        /// True if the Initializer contains designations
Note: See TracChangeset for help on using the changeset viewer.