Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    rf9feab8 r1be845b  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // FixInit.h --
     7// FixInit.cc --
    88//
    99// Author           : Rob Schluntz
     
    5454#include "SynTree/Type.h"              // for Type, Type::StorageClasses
    5555#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
    56 #include "SynTree/VarExprReplacer.h"   // for VarExprReplacer
    5756#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    5857
     
    6867        namespace {
    6968                typedef std::unordered_map< int, int > UnqCount;
     69
     70                struct SelfAssignChecker {
     71                        void previsit( ApplicationExpr * appExpr );
     72                };
    7073
    7174                struct InsertImplicitCalls : public WithTypeSubstitution {
     
    159162                        using Parent::previsit;
    160163
     164                        void previsit( ObjectDecl * objDecl );
    161165                        void previsit( FunctionDecl * funcDecl );
    162166
     167                        void previsit( CompoundStmt * compoundStmt );
     168                        void postvisit( CompoundStmt * compoundStmt );
     169                        void previsit( ReturnStmt * returnStmt );
    163170                        void previsit( BranchStmt * stmt );
    164171                private:
     
    180187                };
    181188
    182                 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {
     189                class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public WithTypeSubstitution {
    183190                  public:
    184191                        FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
     
    194201                };
    195202
    196                 struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer {
     203                struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer, public WithVisitorRef<GenStructMemberCalls> {
    197204                        /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors
    198205                        /// for any member that is missing a corresponding ctor/dtor call.
     
    200207                        static void generate( std::list< Declaration * > & translationUnit );
    201208
    202                         void previsit( StructDecl * structDecl );
    203 
    204                         void previsit( FunctionDecl * funcDecl );
    205                         void postvisit( FunctionDecl * funcDecl );
    206 
    207                         void previsit( MemberExpr * memberExpr );
    208                         void previsit( ApplicationExpr * appExpr );
    209 
    210                         SemanticError errors;
     209                        void premutate( FunctionDecl * funcDecl );
     210                        DeclarationWithType * postmutate( FunctionDecl * funcDecl );
     211
     212                        void premutate( MemberExpr * memberExpr );
     213                        void premutate( ApplicationExpr * appExpr );
     214
     215                        /// Note: this post mutate used to be in a separate visitor. If this pass breaks, one place to examine is whether it is
     216                        /// okay for this part of the recursion to occur alongside the rest.
     217                        Expression * postmutate( UntypedExpr * expr );
     218
     219                        SemanticErrorException errors;
    211220                  private:
    212221                        template< typename... Params >
     
    219228                        bool isCtor = false; // true if current function is a constructor
    220229                        StructDecl * structDecl = nullptr;
    221 
    222                         // special built-in functions necessary for this to work
    223                         StructDecl * dtorStruct = nullptr;
    224                         FunctionDecl * dtorStructDestroy = nullptr;
    225                 };
    226 
    227                 // very simple resolver-like mutator class - used to
    228                 // resolve UntypedExprs that are found within newly
    229                 // generated constructor/destructor calls
    230                 class MutatingResolver final : public Mutator {
    231                   public:
    232                         MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}
    233 
    234                         using Mutator::mutate;
    235                         virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ) override;
    236                         virtual Expression* mutate( UntypedExpr *untypedExpr ) override;
    237 
    238                   private:
    239                         SymTab::Indexer & indexer;
    240230                };
    241231
     
    248238        } // namespace
    249239
    250         void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
     240        void fix( std::list< Declaration * > & translationUnit, bool inLibrary ) {
     241                PassVisitor<SelfAssignChecker> checker;
     242                acceptAll( translationUnit, checker );
     243
    251244                // fixes ConstructorInit for global variables. should happen before fixInitializers.
    252                 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
     245                InitTweak::fixGlobalInit( translationUnit, inLibrary );
    253246
    254247                UnqCount unqCount;
     
    290283                        // can't use mutateAll, because need to insert declarations at top-level
    291284                        // can't use DeclMutator, because sometimes need to insert IfStmt, etc.
    292                         SemanticError errors;
     285                        SemanticErrorException errors;
    293286                        for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    294287                                try {
    295288                                        maybeMutate( *i, fixer );
    296289                                        translationUnit.splice( i, fixer.pass.staticDtorDecls );
    297                                 } catch( SemanticError &e ) {
    298                                         e.set_location( (*i)->location );
     290                                } catch( SemanticErrorException &e ) {
    299291                                        errors.append( e );
    300292                                } // try
     
    318310                void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
    319311                        PassVisitor<GenStructMemberCalls> warner;
    320                         acceptAll( translationUnit, warner );
     312                        mutateAll( translationUnit, warner );
    321313                }
    322314
     
    324316                        PassVisitor<FixCtorExprs> fixer;
    325317                        mutateAll( translationUnit, fixer );
     318                }
     319
     320                namespace {
     321                        // Relatively simple structural comparison for expressions, needed to determine
     322                        // if two expressions are "the same" (used to determine if self assignment occurs)
     323                        struct StructuralChecker {
     324                                Expression * stripCasts( Expression * expr ) {
     325                                        // this might be too permissive. It's possible that only particular casts are relevant.
     326                                        while ( CastExpr * cast = dynamic_cast< CastExpr * >( expr ) ) {
     327                                                expr = cast->arg;
     328                                        }
     329                                        return expr;
     330                                }
     331
     332                                void previsit( Expression * ) {
     333                                        // anything else does not qualify
     334                                        isSimilar = false;
     335                                }
     336
     337                                template<typename T>
     338                                T * cast( Expression * node ) {
     339                                        // all expressions need to ignore casts, so this bit has been factored out
     340                                        return dynamic_cast< T * >( stripCasts( node ) );
     341                                }
     342
     343                                // ignore casts
     344                                void previsit( CastExpr * ) {}
     345
     346                                void previsit( MemberExpr * memExpr ) {
     347                                        if ( MemberExpr * otherMember = cast< MemberExpr >( other ) ) {
     348                                                if ( otherMember->member == memExpr->member ) {
     349                                                        other = otherMember->aggregate;
     350                                                        return;
     351                                                }
     352                                        }
     353                                        isSimilar = false;
     354                                }
     355
     356                                void previsit( VariableExpr * varExpr ) {
     357                                        if ( VariableExpr * otherVar = cast< VariableExpr >( other ) ) {
     358                                                if ( otherVar->var == varExpr->var ) {
     359                                                        return;
     360                                                }
     361                                        }
     362                                        isSimilar = false;
     363                                }
     364
     365                                void previsit( AddressExpr * ) {
     366                                        if ( AddressExpr * addrExpr = cast< AddressExpr >( other ) ) {
     367                                                other = addrExpr->arg;
     368                                                return;
     369                                        }
     370                                        isSimilar = false;
     371                                }
     372
     373                                Expression * other = nullptr;
     374                                bool isSimilar = true;
     375                        };
     376
     377                        bool structurallySimilar( Expression * e1, Expression * e2 ) {
     378                                PassVisitor<StructuralChecker> checker;
     379                                checker.pass.other = e2;
     380                                e1->accept( checker );
     381                                return checker.pass.isSimilar;
     382                        }
     383                }
     384
     385                void SelfAssignChecker::previsit( ApplicationExpr * appExpr ) {
     386                        DeclarationWithType * function = getFunction( appExpr );
     387                        if ( function->name == "?=?" ) { // doesn't use isAssignment, because ?+=?, etc. should not count as self-assignment
     388                                if ( appExpr->args.size() == 2 ) {
     389                                        // check for structural similarity (same variable use, ignore casts, etc. - but does not look too deeply, anything looking like a function is off limits)
     390                                        if ( structurallySimilar( appExpr->args.front(), appExpr->args.back() ) ) {
     391                                                SemanticWarning( appExpr->location, Warning::SelfAssignment, toCString( appExpr->args.front() ) );
     392                                        }
     393                                }
     394                        }
    326395                }
    327396
     
    368437                        // arrays are not copy constructed, so this should always be an ExprStmt
    369438                        ImplicitCtorDtorStmt * stmt = genCtorDtor( fname, var, cpArg );
    370                         ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->get_callStmt() );
     439                        assertf( stmt, "ResolveCopyCtors: genCtorDtor returned nullptr: %s / %s / %s", fname.c_str(), toString( var ).c_str(), toString( cpArg ).c_str() );
     440                        ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->callStmt );
    371441                        Expression * resolved = exprStmt->expr;
    372442                        exprStmt->expr = nullptr; // take ownership of expr
     
    378448                        ResolvExpr::findVoidExpression( resolved, indexer );
    379449                        assert( resolved );
    380                         if ( resolved->get_env() ) {
     450                        if ( resolved->env ) {
    381451                                // Extract useful information and discard new environments. Keeping them causes problems in PolyMutator passes.
    382                                 env->add( *resolved->get_env() );
    383                                 delete resolved->get_env();
    384                                 resolved->set_env( nullptr );
     452                                env->add( *resolved->env );
     453                                delete resolved->env;
     454                                resolved->env = nullptr;
    385455                        } // if
    386456                        delete stmt;
     457                        if ( TupleAssignExpr * assign = dynamic_cast< TupleAssignExpr * >( resolved ) ) {
     458                                // fix newly generated StmtExpr
     459                                postvisit( assign->stmtExpr );
     460                        }
    387461                        return resolved;
    388462                }
     
    478552                                static UniqueName retNamer("_tmp_stmtexpr_ret");
    479553
    480                                 // create variable that will hold the result of the stmt expr
    481554                                result = result->clone();
    482555                                env->apply( result );
     556                                if ( ! InitTweak::isConstructable( result ) ) {
     557                                        delete result;
     558                                        return;
     559                                }
     560
     561                                // create variable that will hold the result of the stmt expr
    483562                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    484                                 ret->get_type()->set_const( false );
    485                                 stmtExpr->get_returnDecls().push_front( ret );
     563                                ret->type->set_const( false );
     564                                stmtExpr->returnDecls.push_front( ret );
    486565
    487566                                // must have a non-empty body, otherwise it wouldn't have a result
    488                                 CompoundStmt * body = stmtExpr->get_statements();
     567                                CompoundStmt * body = stmtExpr->statements;
    489568                                assert( ! body->get_kids().empty() );
    490569                                // must be an ExprStmt, otherwise it wouldn't have a result
    491570                                ExprStmt * last = strict_dynamic_cast< ExprStmt * >( body->get_kids().back() );
    492                                 last->set_expr( makeCtorDtor( "?{}", ret, last->get_expr() ) );
    493 
    494                                 stmtExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
     571                                last->expr = makeCtorDtor( "?{}", ret, last->get_expr() );
     572
     573                                stmtExpr->dtors.push_front( makeCtorDtor( "^?{}", ret ) );
    495574                        } // if
    496575                }
     
    555634                        // add destructors after current statement
    556635                        for ( Expression * dtor : dtors ) {
     636                                // take relevant bindings from environment
     637                                assert( ! dtor->env );
     638                                dtor->env =  maybeClone( env );
    557639                                stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
    558640                        } // for
     
    593675                        // to the outer context, rather than inside of the statement expression.
    594676                        visit_children = false;
    595                         std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
     677                        std::list< Statement * > & stmts = stmtExpr->statements->get_kids();
    596678                        for ( Statement *& stmt : stmts ) {
    597679                                stmt = stmt->acceptMutator( *visitor );
    598680                        } // for
    599                         assert( stmtExpr->get_result() );
    600                         Type * result = stmtExpr->get_result();
     681                        assert( stmtExpr->result );
     682                        Type * result = stmtExpr->result;
    601683                        if ( ! result->isVoid() ) {
    602                                 for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
     684                                for ( ObjectDecl * obj : stmtExpr->returnDecls ) {
    603685                                        stmtsToAddBefore.push_back( new DeclStmt( obj ) );
    604686                                } // for
    605687                                // add destructors after current statement
    606                                 for ( Expression * dtor : stmtExpr->get_dtors() ) {
     688                                for ( Expression * dtor : stmtExpr->dtors ) {
    607689                                        stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
    608690                                } // for
    609691                                // must have a non-empty body, otherwise it wouldn't have a result
    610692                                assert( ! stmts.empty() );
    611                                 assert( ! stmtExpr->get_returnDecls().empty() );
    612                                 stmts.push_back( new ExprStmt( new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
    613                                 stmtExpr->get_returnDecls().clear();
    614                                 stmtExpr->get_dtors().clear();
    615                         }
    616                         assert( stmtExpr->get_returnDecls().empty() );
    617                         assert( stmtExpr->get_dtors().empty() );
     693                                assertf( ! stmtExpr->returnDecls.empty() || stmtExpr->dtors.empty(), "StmtExpr returns non-void, but no return decls: %s", toString( stmtExpr ).c_str() );
     694                                // if there is a return decl, add a use as the last statement; will not have return decl on non-constructable returns
     695                                if ( ! stmtExpr->returnDecls.empty() ) {
     696                                        stmts.push_back( new ExprStmt( new VariableExpr( stmtExpr->returnDecls.front() ) ) );
     697                                }
     698                                stmtExpr->returnDecls.clear();
     699                                stmtExpr->dtors.clear();
     700                        }
     701                        assert( stmtExpr->returnDecls.empty() );
     702                        assert( stmtExpr->dtors.empty() );
    618703                }
    619704
     
    645730                        }
    646731                        return;
    647                 }
    648 
    649                 DeclarationWithType * getDtorFunc( ObjectDecl * objDecl, Statement * input, std::list< Statement * > & stmtsToAdd ) {
    650                         // unwrap implicit statement wrapper
    651                         Statement * dtor = input;
    652                         if ( ImplicitCtorDtorStmt * implicit = dynamic_cast< ImplicitCtorDtorStmt * >( input ) ) {
    653                                 // dtor = implicit->callStmt;
    654                                 // implicit->callStmt = nullptr;
    655                         }
    656                         assert( dtor );
    657                         std::list< Expression * > matches;
    658                         collectCtorDtorCalls( dtor, matches );
    659 
    660                         if ( dynamic_cast< ExprStmt * >( dtor ) ) {
    661                                 // only one destructor call in the expression
    662                                 if ( matches.size() == 1 ) {
    663                                         DeclarationWithType * func = getFunction( matches.front() );
    664                                         assertf( func, "getFunction failed to find function in %s", toString( matches.front() ).c_str() );
    665 
    666                                         // cleanup argument must be a function, not an object (including function pointer)
    667                                         if ( FunctionDecl * dtorFunc = dynamic_cast< FunctionDecl * > ( func ) ) {
    668                                                 if ( dtorFunc->type->forall.empty() ) {
    669                                                         // simple case where the destructor is a monomorphic function call - can simply
    670                                                         // use that function as the cleanup function.
    671                                                         delete dtor;
    672                                                         return func;
    673                                                 }
    674                                         }
    675                                 }
    676                         }
    677 
    678                         // otherwise the cleanup is more complicated - need to build a single argument cleanup function that
    679                         // wraps the more complicated code.
    680                         static UniqueName dtorNamer( "__cleanup_dtor" );
    681                         FunctionDecl * dtorFunc = FunctionDecl::newFunction( dtorNamer.newName(), SymTab::genDefaultType( objDecl->type->stripReferences(), false ), new CompoundStmt() );
    682                         stmtsToAdd.push_back( new DeclStmt( dtorFunc ) );
    683 
    684                         // the original code contains uses of objDecl - replace them with the newly generated 'this' parameter.
    685                         ObjectDecl * thisParam = getParamThis( dtorFunc->type );
    686                         Expression * replacement = new VariableExpr( thisParam );
    687 
    688                         Type * base = replacement->result->stripReferences();
    689                         if ( dynamic_cast< ArrayType * >( base ) || dynamic_cast< TupleType * > ( base ) ) {
    690                                 // need to cast away reference for array types, since the destructor is generated without the reference type,
    691                                 // and for tuple types since tuple indexing does not work directly on a reference
    692                                 replacement = new CastExpr( replacement, base->clone() );
    693                         }
    694                         VarExprReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } );
    695                         dtorFunc->statements->push_back( dtor );
    696 
    697                         return dtorFunc;
    698732                }
    699733
     
    810844                                                        ctorInit->ctor = nullptr;
    811845                                                }
    812 
    813                                                 Statement * dtor = ctorInit->dtor;
    814                                                 if ( dtor ) {
    815                                                         ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * >( dtor );
    816                                                         Statement * dtorStmt = implicit->callStmt;
    817 
    818                                                         // don't need to call intrinsic dtor, because it does nothing, but
    819                                                         // non-intrinsic dtors must be called
    820                                                         if ( ! isIntrinsicSingleArgCallStmt( dtorStmt ) ) {
    821                                                                 // set dtor location to the object's location for error messages
    822                                                                 DeclarationWithType * dtorFunc = getDtorFunc( objDecl, dtorStmt, stmtsToAddBefore );
    823                                                                 objDecl->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorFunc ) } ) );
    824                                                                 ctorInit->dtor = nullptr;
    825                                                         } // if
    826                                                 }
    827846                                        } // if
    828847                                } else if ( Initializer * init = ctorInit->init ) {
     
    867886
    868887
     888                template<typename Iterator, typename OutputIterator>
     889                void insertDtors( Iterator begin, Iterator end, OutputIterator out ) {
     890                        for ( Iterator it = begin ; it != end ; ++it ) {
     891                                // extract destructor statement from the object decl and insert it into the output. Note that this is
     892                                // only called on lists of non-static objects with implicit non-intrinsic dtors, so if the user manually
     893                                // calls an intrinsic dtor then the call must (and will) still be generated since the argument may
     894                                // contain side effects.
     895                                ObjectDecl * objDecl = *it;
     896                                ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() );
     897                                assert( ctorInit && ctorInit->get_dtor() );
     898                                *out++ = ctorInit->get_dtor()->clone();
     899                        } // for
     900                }
     901
     902                void InsertDtors::previsit( ObjectDecl * objDecl ) {
     903                        // remember non-static destructed objects so that their destructors can be inserted later
     904                        if ( ! objDecl->get_storageClasses().is_static ) {
     905                                if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
     906                                        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
     907                                        assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
     908                                        Statement * dtor = ctorInit->get_dtor();
     909                                        // don't need to call intrinsic dtor, because it does nothing, but
     910                                        // non-intrinsic dtors must be called
     911                                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
     912                                                // set dtor location to the object's location for error messages
     913                                                ctorInit->dtor->location = objDecl->location;
     914                                                reverseDeclOrder.front().push_front( objDecl );
     915                                        } // if
     916                                } // if
     917                        } // if
     918                }
     919
    869920                void InsertDtors::previsit( FunctionDecl * funcDecl ) {
    870921                        // each function needs to have its own set of labels
     
    879930                }
    880931
     932                void InsertDtors::previsit( CompoundStmt * compoundStmt ) {
     933                        // visit statements - this will also populate reverseDeclOrder list.  don't want to dump all destructors
     934                        // when block is left, just the destructors associated with variables defined in this block, so push a new
     935                        // list to the top of the stack so that we can differentiate scopes
     936                        reverseDeclOrder.push_front( OrderedDecls() );
     937                        Parent::previsit( compoundStmt );
     938                }
     939
     940                void InsertDtors::postvisit( CompoundStmt * compoundStmt ) {
     941                        // add destructors for the current scope that we're exiting, unless the last statement is a return, which
     942                        // causes unreachable code warnings
     943                        std::list< Statement * > & statements = compoundStmt->get_kids();
     944                        if ( ! statements.empty() && ! dynamic_cast< ReturnStmt * >( statements.back() ) ) {
     945                                insertDtors( reverseDeclOrder.front().begin(), reverseDeclOrder.front().end(), back_inserter( statements ) );
     946                        }
     947                        reverseDeclOrder.pop_front();
     948                }
     949
     950                void InsertDtors::previsit( ReturnStmt * ) {
     951                        // return exits all scopes, so dump destructors for all scopes
     952                        for ( OrderedDecls & od : reverseDeclOrder ) {
     953                                insertDtors( od.begin(), od.end(), back_inserter( stmtsToAddBefore ) );
     954                        } // for
     955                }
     956
    881957                // Handle break/continue/goto in the same manner as C++.  Basic idea: any objects that are in scope at the
    882958                // BranchStmt but not at the labelled (target) statement must be destructed.  If there are any objects in scope
     
    905981                        )
    906982                        if ( ! diff.empty() ) {
    907                                 throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt );
     983                                SemanticError( stmt, std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " " );
     984                        } // if
     985                        // S_G-S_L results in set of objects that must be destructed
     986                        diff.clear();
     987                        std::set_difference( curVars.begin(), curVars.end(), lvars.begin(), lvars.end(), std::inserter( diff, diff.end() ) );
     988                        DTOR_PRINT(
     989                                std::cerr << "S_G-S_L = " << printSet( diff ) << std::endl;
     990                        )
     991                        if ( ! diff.empty() ) {
     992                                // create an auxilliary set for fast lookup -- can't make diff a set, because diff ordering should be consistent for error messages.
     993                                std::unordered_set<ObjectDecl *> needsDestructor( diff.begin(), diff.end() );
     994
     995                                // go through decl ordered list of objectdecl. for each element that occurs in diff, output destructor
     996                                OrderedDecls ordered;
     997                                for ( OrderedDecls & rdo : reverseDeclOrder ) {
     998                                        // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order.
     999                                        copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return needsDestructor.count( objDecl ); } );
     1000                                } // for
     1001                                insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAddBefore ) );
    9081002                        } // if
    9091003                }
     
    9311025                }
    9321026
    933                 void GenStructMemberCalls::previsit( StructDecl * structDecl ) {
    934                         if ( ! dtorStruct && structDecl->name == "__Destructor" ) {
    935                                 dtorStruct = structDecl;
    936                         }
    937                 }
    938 
    939                 void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) {
     1027                void GenStructMemberCalls::premutate( FunctionDecl * funcDecl ) {
    9401028                        GuardValue( function );
    9411029                        GuardValue( unhandled );
     
    9441032                        GuardValue( isCtor );
    9451033                        GuardValue( structDecl );
    946                         errors = SemanticError();  // clear previous errors
     1034                        errors = SemanticErrorException();  // clear previous errors
    9471035
    9481036                        // need to start with fresh sets
    9491037                        unhandled.clear();
    9501038                        usedUninit.clear();
    951 
    952                         if ( ! dtorStructDestroy && funcDecl->name == "__destroy_Destructor" ) {
    953                                 dtorStructDestroy = funcDecl;
    954                                 return;
    955                         }
    9561039
    9571040                        function = funcDecl;
     
    9651048                                if ( structType ) {
    9661049                                        structDecl = structType->get_baseStruct();
    967                                         if ( structDecl == dtorStruct ) return;
    9681050                                        for ( Declaration * member : structDecl->get_members() ) {
    9691051                                                if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
     
    9771059                }
    9781060
    979                 void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) {
     1061                DeclarationWithType * GenStructMemberCalls::postmutate( FunctionDecl * funcDecl ) {
    9801062                        // remove the unhandled objects from usedUninit, because a call is inserted
    9811063                        // to handle them - only objects that are later constructed are used uninitialized.
     
    10311113                                                Statement * callStmt = stmt.front();
    10321114
    1033                                                 MutatingResolver resolver( indexer );
    10341115                                                try {
    1035                                                         callStmt->acceptMutator( resolver );
     1116                                                        callStmt->acceptMutator( *visitor );
    10361117                                                        if ( isCtor ) {
    1037                                                                 function->statements->push_front( callStmt );
     1118                                                                function->get_statements()->push_front( callStmt );
    10381119                                                        } else {
    10391120                                                                // destructor statements should be added at the end
    1040                                                                 // function->get_statements()->push_back( callStmt );
    1041 
    1042                                                                 // Destructor _dtor0 = { &b.a1, (void (*)(void *)_destroy_A };
    1043                                                                 std::list< Statement * > stmtsToAdd;
    1044 
    1045                                                                 static UniqueName memberDtorNamer = { "__memberDtor" };
    1046                                                                 assertf( dtorStruct, "builtin __Destructor not found." );
    1047                                                                 assertf( dtorStructDestroy, "builtin __destroy_Destructor not found." );
    1048 
    1049                                                                 Expression * thisExpr = new AddressExpr( new VariableExpr( thisParam ) );
    1050                                                                 Expression * dtorExpr = new VariableExpr( getDtorFunc( thisParam, callStmt, stmtsToAdd ) );
    1051 
    1052                                                                 // cast destructor pointer to void (*)(void *), to silence GCC incompatible pointer warnings
    1053                                                                 FunctionType * dtorFtype = new FunctionType( Type::Qualifiers(), false );
    1054                                                                 dtorFtype->parameters.push_back( ObjectDecl::newObject( "", new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), nullptr ) );
    1055                                                                 Type * dtorType = new PointerType( Type::Qualifiers(), dtorFtype );
    1056 
    1057                                                                 ObjectDecl * destructor = ObjectDecl::newObject( memberDtorNamer.newName(), new StructInstType( Type::Qualifiers(), dtorStruct ), new ListInit( { new SingleInit( thisExpr ), new SingleInit( new CastExpr( dtorExpr, dtorType ) ) } ) );
    1058                                                                 function->statements->push_front( new DeclStmt( destructor ) );
    1059                                                                 destructor->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorStructDestroy ) } ) );
    1060 
    1061                                                                 function->statements->kids.splice( function->statements->kids.begin(), stmtsToAdd );
     1121                                                                function->get_statements()->push_back( callStmt );
    10621122                                                        }
    1063                                                 } catch ( SemanticError & error ) {
     1123                                                } catch ( SemanticErrorException & error ) {
    10641124                                                        emit( funcDecl->location, "in ", CodeGen::genPrettyType( function->get_functionType(), function->get_name() ), ", field ", field->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed",  " and no ", isCtor ? "default constructor" : "destructor", " found" );
    10651125                                                }
     
    10701130                                throw errors;
    10711131                        }
     1132                        return funcDecl;
    10721133                }
    10731134
     
    10951156                }
    10961157
    1097                 void GenStructMemberCalls::previsit( ApplicationExpr * appExpr ) {
     1158                void GenStructMemberCalls::premutate( ApplicationExpr * appExpr ) {
    10981159                        if ( ! checkWarnings( function ) ) {
    10991160                                visit_children = false;
     
    11021163
    11031164                        std::string fname = getFunctionName( appExpr );
    1104                         if ( fname == function->get_name() ) {
     1165                        if ( fname == function->name ) {
    11051166                                // call to same kind of function
    1106                                 Expression * firstParam = appExpr->get_args().front();
     1167                                Expression * firstParam = appExpr->args.front();
    11071168
    11081169                                if ( isThisExpression( firstParam, thisParam ) ) {
     
    11131174                                        // if first parameter is a member expression on the this parameter,
    11141175                                        // then remove the member from unhandled set.
    1115                                         if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
    1116                                                 unhandled.erase( memberExpr->get_member() );
     1176                                        if ( isThisExpression( memberExpr->aggregate, thisParam ) ) {
     1177                                                unhandled.erase( memberExpr->member );
    11171178                                        }
    11181179                                }
     
    11201181                }
    11211182
    1122                 void GenStructMemberCalls::previsit( MemberExpr * memberExpr ) {
     1183                void GenStructMemberCalls::premutate( MemberExpr * memberExpr ) {
    11231184                        if ( ! checkWarnings( function ) || ! isCtor ) {
    11241185                                visit_children = false;
     
    11361197                template< typename Visitor, typename... Params >
    11371198                void error( Visitor & v, CodeLocation loc, const Params &... params ) {
    1138                         SemanticError err( toString( params... ) );
    1139                         err.set_location( loc );
     1199                        SemanticErrorException err( loc, toString( params... ) );
    11401200                        v.errors.append( err );
    11411201                }
     
    11481208                }
    11491209
    1150                 DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) {
    1151                         // add object to the indexer assumes that there will be no name collisions
    1152                         // in generated code. If this changes, add mutate methods for entities with
    1153                         // scope and call {enter,leave}Scope explicitly.
    1154                         indexer.addId( objectDecl );
    1155                         return objectDecl;
    1156                 }
    1157 
    1158                 Expression * MutatingResolver::mutate( UntypedExpr * untypedExpr ) {
     1210                Expression * GenStructMemberCalls::postmutate( UntypedExpr * untypedExpr ) {
    11591211                        Expression * newExpr = untypedExpr;
    11601212                        ResolvExpr::findVoidExpression( newExpr, indexer );
Note: See TracChangeset for help on using the changeset viewer.