Changeset 90152a4 for src/InitTweak


Ignore:
Timestamp:
Aug 27, 2018, 4:40:34 PM (6 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
b7c89aa
Parents:
f9feab8 (diff), 305581d (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' into cleanup-dtors

Location:
src/InitTweak
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixGlobalInit.cc

    rf9feab8 r90152a4  
    2121
    2222#include "Common/PassVisitor.h"
    23 #include "Common/SemanticError.h"  // for SemanticError
    2423#include "Common/UniqueName.h"     // for UniqueName
    2524#include "InitTweak.h"             // for isIntrinsicSingleArgCallStmt
     
    3837        class GlobalFixer : public WithShortCircuiting {
    3938          public:
    40                 GlobalFixer( const std::string & name, bool inLibrary );
     39                GlobalFixer( bool inLibrary );
    4140
    4241                void previsit( ObjectDecl *objDecl );
     
    5352        };
    5453
    55         void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) {
    56                 PassVisitor<GlobalFixer> visitor( name, inLibrary );
     54        void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary ) {
     55                PassVisitor<GlobalFixer> visitor( inLibrary );
    5756                acceptAll( translationUnit, visitor );
    5857                GlobalFixer & fixer = visitor.pass;
     
    7170        }
    7271
    73   std::string globalFunctionName( const std::string & name ) {
    74         // get basename
    75         std::string ret = name.substr( 0, name.find( '.' ) );
    76         // replace invalid characters with _
    77                 static std::string invalid = "/-";
    78         replace_if( ret.begin(), ret.end(), []( char c ) { return invalid.find(c) != std::string::npos; }, '_' );
    79         return ret;
    80   }
    81 
    82         GlobalFixer::GlobalFixer( const std::string & name, bool inLibrary ) : tempNamer( "_global_init" ) {
    83                 std::string fixedName = globalFunctionName( name );
     72        GlobalFixer::GlobalFixer( bool inLibrary ) : tempNamer( "_global_init" ) {
    8473                std::list< Expression * > ctorParameters;
    8574                std::list< Expression * > dtorParameters;
     
    9180                        // for library code are run before constructors and destructors for user code,
    9281                        // specify a priority when building the library. Priorities 0-100 are reserved by gcc.
    93                         ctorParameters.push_back( new ConstantExpr( Constant::from_int( 102 ) ) );
    94                         dtorParameters.push_back( new ConstantExpr( Constant::from_int( 102 ) ) );
     82                        // Priorities 101-200 are reserved by cfa, so use priority 200 for CFA library globals,
     83                        // allowing room for overriding with a higher priority.
     84                        ctorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) );
     85                        dtorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) );
    9586                }
    96                 initFunction = new FunctionDecl( "_init_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
     87                initFunction = new FunctionDecl( "__global_init__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
    9788                initFunction->get_attributes().push_back( new Attribute( "constructor", ctorParameters ) );
    98                 destroyFunction = new FunctionDecl( "_destroy_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
     89                destroyFunction = new FunctionDecl( "__global_destroy__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
    9990                destroyFunction->get_attributes().push_back( new Attribute( "destructor", dtorParameters ) );
    10091        }
     
    111102                if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
    112103                        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
    113                         assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
     104                        assert( ! ctorInit->ctor || ! ctorInit->init );
    114105
    115                         Statement * dtor = ctorInit->get_dtor();
     106                        Statement * dtor = ctorInit->dtor;
    116107                        if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    117108                                // don't need to call intrinsic dtor, because it does nothing, but
    118109                                // non-intrinsic dtors must be called
    119110                                destroyStatements.push_front( dtor );
    120                                 ctorInit->set_dtor( NULL );
     111                                ctorInit->dtor = nullptr;
    121112                        } // if
    122                         if ( Statement * ctor = ctorInit->get_ctor() ) {
     113                        if ( Statement * ctor = ctorInit->ctor ) {
    123114                                initStatements.push_back( ctor );
    124                                 objDecl->set_init( NULL );
    125                                 ctorInit->set_ctor( NULL );
    126                         } else if ( Initializer * init = ctorInit->get_init() ) {
    127                                 objDecl->set_init( init );
    128                                 ctorInit->set_init( NULL );
     115                                objDecl->init = nullptr;
     116                                ctorInit->ctor = nullptr;
     117                        } else if ( Initializer * init = ctorInit->init ) {
     118                                objDecl->init = init;
     119                                ctorInit->init = nullptr;
    129120                        } else {
    130121                                // no constructor and no initializer, which is okay
    131                                 objDecl->set_init( NULL );
     122                                objDecl->init = nullptr;
    132123                        } // if
    133124                        delete ctorInit;
  • src/InitTweak/FixGlobalInit.h

    rf9feab8 r90152a4  
    2222
    2323namespace InitTweak {
    24   /// Moves global initialization into an _init function that is unique to the translation unit.
    25   /// Sets the priority of the initialization function depending on whether the initialization
    26   /// function is for library code.
    27   void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary );
    28 
    29   /// Apply transformations to a file name to get a valid C identifier which will be used as
    30   /// the name of the generated initializer function.
    31   std::string globalFunctionName( const std::string & name );
     24        /// Moves global initialization into an _init function that is unique to the translation unit.
     25        /// Sets the priority of the initialization function depending on whether the initialization
     26        /// function is for library code.
     27        void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary );
    3228} // namespace
    3329
  • src/InitTweak/FixInit.cc

    rf9feab8 r90152a4  
    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
     56#include "SynTree/DeclReplacer.h"      // for DeclReplacer
    5757#include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    5858
     
    6868        namespace {
    6969                typedef std::unordered_map< int, int > UnqCount;
     70
     71                struct SelfAssignChecker {
     72                        void previsit( ApplicationExpr * appExpr );
     73                };
    7074
    7175                struct InsertImplicitCalls : public WithTypeSubstitution {
     
    180184                };
    181185
    182                 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {
     186                class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>, public WithTypeSubstitution {
    183187                  public:
    184188                        FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
     
    194198                };
    195199
    196                 struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer {
     200                struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer, public WithVisitorRef<GenStructMemberCalls> {
    197201                        /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors
    198202                        /// for any member that is missing a corresponding ctor/dtor call.
     
    200204                        static void generate( std::list< Declaration * > & translationUnit );
    201205
    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;
     206                        void premutate( StructDecl * structDecl );
     207
     208                        void premutate( FunctionDecl * funcDecl );
     209                        DeclarationWithType * postmutate( FunctionDecl * funcDecl );
     210
     211                        void premutate( MemberExpr * memberExpr );
     212                        void premutate( ApplicationExpr * appExpr );
     213
     214                        /// Note: this post mutate used to be in a separate visitor. If this pass breaks, one place to examine is whether it is
     215                        /// okay for this part of the recursion to occur alongside the rest.
     216                        Expression * postmutate( UntypedExpr * expr );
     217
     218                        SemanticErrorException errors;
    211219                  private:
    212220                        template< typename... Params >
     
    225233                };
    226234
    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;
    240                 };
    241 
    242235                struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer {
    243236                        /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
     
    248241        } // namespace
    249242
    250         void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) {
     243        void fix( std::list< Declaration * > & translationUnit, bool inLibrary ) {
     244                PassVisitor<SelfAssignChecker> checker;
     245                acceptAll( translationUnit, checker );
     246
    251247                // fixes ConstructorInit for global variables. should happen before fixInitializers.
    252                 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary );
     248                InitTweak::fixGlobalInit( translationUnit, inLibrary );
    253249
    254250                UnqCount unqCount;
     
    290286                        // can't use mutateAll, because need to insert declarations at top-level
    291287                        // can't use DeclMutator, because sometimes need to insert IfStmt, etc.
    292                         SemanticError errors;
     288                        SemanticErrorException errors;
    293289                        for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    294290                                try {
    295291                                        maybeMutate( *i, fixer );
    296292                                        translationUnit.splice( i, fixer.pass.staticDtorDecls );
    297                                 } catch( SemanticError &e ) {
    298                                         e.set_location( (*i)->location );
     293                                } catch( SemanticErrorException &e ) {
    299294                                        errors.append( e );
    300295                                } // try
     
    318313                void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) {
    319314                        PassVisitor<GenStructMemberCalls> warner;
    320                         acceptAll( translationUnit, warner );
     315                        mutateAll( translationUnit, warner );
    321316                }
    322317
     
    324319                        PassVisitor<FixCtorExprs> fixer;
    325320                        mutateAll( translationUnit, fixer );
     321                }
     322
     323                namespace {
     324                        // Relatively simple structural comparison for expressions, needed to determine
     325                        // if two expressions are "the same" (used to determine if self assignment occurs)
     326                        struct StructuralChecker {
     327                                Expression * stripCasts( Expression * expr ) {
     328                                        // this might be too permissive. It's possible that only particular casts are relevant.
     329                                        while ( CastExpr * cast = dynamic_cast< CastExpr * >( expr ) ) {
     330                                                expr = cast->arg;
     331                                        }
     332                                        return expr;
     333                                }
     334
     335                                void previsit( Expression * ) {
     336                                        // anything else does not qualify
     337                                        isSimilar = false;
     338                                }
     339
     340                                template<typename T>
     341                                T * cast( Expression * node ) {
     342                                        // all expressions need to ignore casts, so this bit has been factored out
     343                                        return dynamic_cast< T * >( stripCasts( node ) );
     344                                }
     345
     346                                // ignore casts
     347                                void previsit( CastExpr * ) {}
     348
     349                                void previsit( MemberExpr * memExpr ) {
     350                                        if ( MemberExpr * otherMember = cast< MemberExpr >( other ) ) {
     351                                                if ( otherMember->member == memExpr->member ) {
     352                                                        other = otherMember->aggregate;
     353                                                        return;
     354                                                }
     355                                        }
     356                                        isSimilar = false;
     357                                }
     358
     359                                void previsit( VariableExpr * varExpr ) {
     360                                        if ( VariableExpr * otherVar = cast< VariableExpr >( other ) ) {
     361                                                if ( otherVar->var == varExpr->var ) {
     362                                                        return;
     363                                                }
     364                                        }
     365                                        isSimilar = false;
     366                                }
     367
     368                                void previsit( AddressExpr * ) {
     369                                        if ( AddressExpr * addrExpr = cast< AddressExpr >( other ) ) {
     370                                                other = addrExpr->arg;
     371                                                return;
     372                                        }
     373                                        isSimilar = false;
     374                                }
     375
     376                                Expression * other = nullptr;
     377                                bool isSimilar = true;
     378                        };
     379
     380                        bool structurallySimilar( Expression * e1, Expression * e2 ) {
     381                                PassVisitor<StructuralChecker> checker;
     382                                checker.pass.other = e2;
     383                                e1->accept( checker );
     384                                return checker.pass.isSimilar;
     385                        }
     386                }
     387
     388                void SelfAssignChecker::previsit( ApplicationExpr * appExpr ) {
     389                        DeclarationWithType * function = getFunction( appExpr );
     390                        if ( function->name == "?=?" ) { // doesn't use isAssignment, because ?+=?, etc. should not count as self-assignment
     391                                if ( appExpr->args.size() == 2 ) {
     392                                        // check for structural similarity (same variable use, ignore casts, etc. - but does not look too deeply, anything looking like a function is off limits)
     393                                        if ( structurallySimilar( appExpr->args.front(), appExpr->args.back() ) ) {
     394                                                SemanticWarning( appExpr->location, Warning::SelfAssignment, toCString( appExpr->args.front() ) );
     395                                        }
     396                                }
     397                        }
    326398                }
    327399
     
    368440                        // arrays are not copy constructed, so this should always be an ExprStmt
    369441                        ImplicitCtorDtorStmt * stmt = genCtorDtor( fname, var, cpArg );
    370                         ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->get_callStmt() );
     442                        assertf( stmt, "ResolveCopyCtors: genCtorDtor returned nullptr: %s / %s / %s", fname.c_str(), toString( var ).c_str(), toString( cpArg ).c_str() );
     443                        ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->callStmt );
    371444                        Expression * resolved = exprStmt->expr;
    372445                        exprStmt->expr = nullptr; // take ownership of expr
     
    378451                        ResolvExpr::findVoidExpression( resolved, indexer );
    379452                        assert( resolved );
    380                         if ( resolved->get_env() ) {
     453                        if ( resolved->env ) {
    381454                                // 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 );
     455                                env->add( *resolved->env );
     456                                delete resolved->env;
     457                                resolved->env = nullptr;
    385458                        } // if
    386459                        delete stmt;
     460                        if ( TupleAssignExpr * assign = dynamic_cast< TupleAssignExpr * >( resolved ) ) {
     461                                // fix newly generated StmtExpr
     462                                postvisit( assign->stmtExpr );
     463                        }
    387464                        return resolved;
    388465                }
     
    478555                                static UniqueName retNamer("_tmp_stmtexpr_ret");
    479556
    480                                 // create variable that will hold the result of the stmt expr
    481557                                result = result->clone();
    482558                                env->apply( result );
     559                                if ( ! InitTweak::isConstructable( result ) ) {
     560                                        delete result;
     561                                        return;
     562                                }
     563
     564                                // create variable that will hold the result of the stmt expr
    483565                                ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
    484                                 ret->get_type()->set_const( false );
    485                                 stmtExpr->get_returnDecls().push_front( ret );
     566                                ret->type->set_const( false );
     567                                stmtExpr->returnDecls.push_front( ret );
    486568
    487569                                // must have a non-empty body, otherwise it wouldn't have a result
    488                                 CompoundStmt * body = stmtExpr->get_statements();
     570                                CompoundStmt * body = stmtExpr->statements;
    489571                                assert( ! body->get_kids().empty() );
    490572                                // must be an ExprStmt, otherwise it wouldn't have a result
    491573                                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 ) );
     574                                last->expr = makeCtorDtor( "?{}", ret, last->get_expr() );
     575
     576                                stmtExpr->dtors.push_front( makeCtorDtor( "^?{}", ret ) );
    495577                        } // if
    496578                }
     
    555637                        // add destructors after current statement
    556638                        for ( Expression * dtor : dtors ) {
     639                                // take relevant bindings from environment
     640                                assert( ! dtor->env );
     641                                dtor->env =  maybeClone( env );
    557642                                stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
    558643                        } // for
     
    593678                        // to the outer context, rather than inside of the statement expression.
    594679                        visit_children = false;
    595                         std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
     680                        std::list< Statement * > & stmts = stmtExpr->statements->get_kids();
    596681                        for ( Statement *& stmt : stmts ) {
    597682                                stmt = stmt->acceptMutator( *visitor );
    598683                        } // for
    599                         assert( stmtExpr->get_result() );
    600                         Type * result = stmtExpr->get_result();
     684                        assert( stmtExpr->result );
     685                        Type * result = stmtExpr->result;
    601686                        if ( ! result->isVoid() ) {
    602                                 for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
     687                                for ( ObjectDecl * obj : stmtExpr->returnDecls ) {
    603688                                        stmtsToAddBefore.push_back( new DeclStmt( obj ) );
    604689                                } // for
    605690                                // add destructors after current statement
    606                                 for ( Expression * dtor : stmtExpr->get_dtors() ) {
     691                                for ( Expression * dtor : stmtExpr->dtors ) {
    607692                                        stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
    608693                                } // for
    609694                                // must have a non-empty body, otherwise it wouldn't have a result
    610695                                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() );
     696                                assertf( ! stmtExpr->returnDecls.empty() || stmtExpr->dtors.empty(), "StmtExpr returns non-void, but no return decls: %s", toString( stmtExpr ).c_str() );
     697                                // if there is a return decl, add a use as the last statement; will not have return decl on non-constructable returns
     698                                if ( ! stmtExpr->returnDecls.empty() ) {
     699                                        stmts.push_back( new ExprStmt( new VariableExpr( stmtExpr->returnDecls.front() ) ) );
     700                                }
     701                                stmtExpr->returnDecls.clear();
     702                                stmtExpr->dtors.clear();
     703                        }
     704                        assert( stmtExpr->returnDecls.empty() );
     705                        assert( stmtExpr->dtors.empty() );
    618706                }
    619707
     
    692780                                replacement = new CastExpr( replacement, base->clone() );
    693781                        }
    694                         VarExprReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } );
    695                         dtorFunc->statements->push_back( dtor );
     782                        DeclReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } );
     783                        dtorFunc->statements->push_back( strict_dynamic_cast<Statement *>( dtor ) );
    696784
    697785                        return dtorFunc;
     
    905993                        )
    906994                        if ( ! diff.empty() ) {
    907                                 throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt );
     995                                SemanticError( stmt, std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " " );
    908996                        } // if
    909997                }
     
    9311019                }
    9321020
    933                 void GenStructMemberCalls::previsit( StructDecl * structDecl ) {
     1021                void GenStructMemberCalls::premutate( StructDecl * structDecl ) {
    9341022                        if ( ! dtorStruct && structDecl->name == "__Destructor" ) {
    9351023                                dtorStruct = structDecl;
     
    9371025                }
    9381026
    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
     
    9771065                }
    9781066
    979                 void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) {
     1067                DeclarationWithType * GenStructMemberCalls::postmutate( FunctionDecl * funcDecl ) {
    9801068                        // remove the unhandled objects from usedUninit, because a call is inserted
    9811069                        // to handle them - only objects that are later constructed are used uninitialized.
     
    10311119                                                Statement * callStmt = stmt.front();
    10321120
    1033                                                 MutatingResolver resolver( indexer );
    10341121                                                try {
    1035                                                         callStmt->acceptMutator( resolver );
     1122                                                        callStmt->acceptMutator( *visitor );
    10361123                                                        if ( isCtor ) {
    10371124                                                                function->statements->push_front( callStmt );
     
    10611148                                                                function->statements->kids.splice( function->statements->kids.begin(), stmtsToAdd );
    10621149                                                        }
    1063                                                 } catch ( SemanticError & error ) {
     1150                                                } catch ( SemanticErrorException & error ) {
    10641151                                                        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" );
    10651152                                                }
     
    10701157                                throw errors;
    10711158                        }
     1159                        return funcDecl;
    10721160                }
    10731161
     
    10951183                }
    10961184
    1097                 void GenStructMemberCalls::previsit( ApplicationExpr * appExpr ) {
     1185                void GenStructMemberCalls::premutate( ApplicationExpr * appExpr ) {
    10981186                        if ( ! checkWarnings( function ) ) {
    10991187                                visit_children = false;
     
    11021190
    11031191                        std::string fname = getFunctionName( appExpr );
    1104                         if ( fname == function->get_name() ) {
     1192                        if ( fname == function->name ) {
    11051193                                // call to same kind of function
    1106                                 Expression * firstParam = appExpr->get_args().front();
     1194                                Expression * firstParam = appExpr->args.front();
    11071195
    11081196                                if ( isThisExpression( firstParam, thisParam ) ) {
     
    11131201                                        // if first parameter is a member expression on the this parameter,
    11141202                                        // then remove the member from unhandled set.
    1115                                         if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
    1116                                                 unhandled.erase( memberExpr->get_member() );
     1203                                        if ( isThisExpression( memberExpr->aggregate, thisParam ) ) {
     1204                                                unhandled.erase( memberExpr->member );
    11171205                                        }
    11181206                                }
     
    11201208                }
    11211209
    1122                 void GenStructMemberCalls::previsit( MemberExpr * memberExpr ) {
     1210                void GenStructMemberCalls::premutate( MemberExpr * memberExpr ) {
    11231211                        if ( ! checkWarnings( function ) || ! isCtor ) {
    11241212                                visit_children = false;
     
    11361224                template< typename Visitor, typename... Params >
    11371225                void error( Visitor & v, CodeLocation loc, const Params &... params ) {
    1138                         SemanticError err( toString( params... ) );
    1139                         err.set_location( loc );
     1226                        SemanticErrorException err( loc, toString( params... ) );
    11401227                        v.errors.append( err );
    11411228                }
     
    11481235                }
    11491236
    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 ) {
     1237                Expression * GenStructMemberCalls::postmutate( UntypedExpr * untypedExpr ) {
    11591238                        Expression * newExpr = untypedExpr;
    11601239                        ResolvExpr::findVoidExpression( newExpr, indexer );
  • src/InitTweak/FixInit.h

    rf9feab8 r90152a4  
    2424  /// replace constructor initializers with expression statements
    2525  /// and unwrap basic C-style initializers
    26         void fix( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary );
     26        void fix( std::list< Declaration * > & translationUnit, bool inLibrary );
    2727} // namespace
    2828
  • src/InitTweak/GenInit.cc

    rf9feab8 r90152a4  
    3030#include "InitTweak.h"             // for isConstExpr, InitExpander, checkIn...
    3131#include "Parser/LinkageSpec.h"    // for isOverridable, C
     32#include "ResolvExpr/Resolver.h"
    3233#include "SymTab/Autogen.h"        // for genImplicitCall, SizeType
    3334#include "SymTab/Mangler.h"        // for Mangler
     
    4041#include "SynTree/Type.h"          // for Type, ArrayType, Type::Qualifiers
    4142#include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
     43#include "Tuples/Tuples.h"         // for maybeImpure
    4244
    4345namespace InitTweak {
     
    8991        };
    9092
    91         struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards {
     93        struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards, public WithIndexer {
    9294                /// hoist dimension from array types in object declaration so that it uses a single
    9395                /// const variable of type size_t, so that side effecting array dimensions are only
     
    104106                void premutate( FunctionType * ) { visit_children = false; }
    105107
     108                // need this so that enumerators are added to the indexer, due to premutate(AggregateDecl *)
     109                void premutate( EnumDecl * ) {}
     110
    106111                void hoist( Type * type );
    107112
     
    135140                                if ( varExpr->var == retVal ) return;
    136141                        }
    137                         stmtsToAddBefore.push_back( genCtorDtor( "?{}", retVal, returnStmt->get_expr() ) );
     142                        Statement * stmt = genCtorDtor( "?{}", retVal, returnStmt->expr );
     143                        assertf( stmt, "ReturnFixer: genCtorDtor returned nullptr: %s / %s", toString( retVal ).c_str(), toString( returnStmt->expr ).c_str() );
     144                        stmtsToAddBefore.push_back( stmt );
    138145
    139146                        // return the retVal object
     
    178185                        if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
    179186
    180                         // don't need to hoist dimension if it's a constexpr - only need to if there's potential for side effects.
    181                         if ( isConstExpr( arrayType->get_dimension() ) ) return;
     187                        // need to resolve array dimensions in order to accurately determine if constexpr
     188                        ResolvExpr::findSingleExpression( arrayType->dimension, SymTab::SizeType->clone(), indexer );
     189                        // array is variable-length when the dimension is not constexpr
     190                        arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
     191                        // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
     192                        if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
    182193
    183194                        ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, SymTab::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
     
    194205        void HoistArrayDimension::premutate( FunctionDecl * ) {
    195206                GuardValue( inFunction );
     207                inFunction = true;
    196208        }
    197209
     
    220232                Type * type = objDecl->get_type();
    221233                while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
     234                        // must always construct VLAs with an initializer, since this is an error in C
     235                        if ( at->isVarLen && objDecl->init ) return true;
    222236                        type = at->get_base();
    223237                }
     
    303317                if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {
    304318                        // constructed objects cannot be designated
    305                         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 );
     319                        if ( isDesignated( objDecl->get_init() ) ) SemanticError( objDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
    306320                        // constructed objects should not have initializers nested too deeply
    307                         if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl );
     321                        if ( ! checkInitDepth( objDecl ) ) SemanticError( objDecl, "Managed object's initializer is too deep " );
    308322
    309323                        objDecl->set_init( genCtorInit( objDecl ) );
  • src/InitTweak/InitTweak.cc

    rf9feab8 r90152a4  
    225225                                        // xxx - this shouldn't be an error, but need a way to
    226226                                        // terminate without creating output, so should catch this error
    227                                         throw SemanticError( "unbalanced list initializers" );
     227                                        SemanticError( init->location, "unbalanced list initializers" );
    228228                                }
    229229
     
    296296                ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt );
    297297                if ( ! objDecl ) return false;
    298                 return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
    299                         (objDecl->get_init() == nullptr ||
     298                return (objDecl->get_init() == nullptr ||
    300299                                ( objDecl->get_init() != nullptr && objDecl->get_init()->get_maybeConstructed() ))
    301300                        && ! objDecl->get_storageClasses().is_extern
     
    409408                return allofCtorDtor( stmt, []( Expression * callExpr ){
    410409                        if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
    411                                 FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_result() );
     410                                FunctionType *funcType = GenPoly::getFunctionType( appExpr->function->result );
    412411                                assert( funcType );
    413412                                return funcType->get_parameters().size() == 1;
     
    529528                }
    530529                if ( dynamic_cast< ReferenceType * >( dst->result ) ) {
    531                         dst = new AddressExpr( dst );
     530                        for (int depth = dst->result->referenceDepth(); depth > 0; depth--) {
     531                                dst = new AddressExpr( dst );
     532                        }
    532533                } else {
    533534                        dst = new CastExpr( dst, new ReferenceType( noQualifiers, dst->result->clone() ) );
    534535                }
    535536                if ( dynamic_cast< ReferenceType * >( src->result ) ) {
    536                         src = new CastExpr( src, new ReferenceType( noQualifiers, src->result->stripReferences()->clone() ) );
     537                        for (int depth = src->result->referenceDepth(); depth > 0; depth--) {
     538                                src = new AddressExpr( src );
     539                        }
     540                        // src = new CastExpr( src, new ReferenceType( noQualifiers, src->result->stripReferences()->clone() ) );
    537541                }
    538542                return new ApplicationExpr( VariableExpr::functionPointer( assign ), { dst, src } );
     
    564568                void previsit( ConstantExpr * ) {}
    565569
     570                void previsit( VariableExpr * varExpr ) {
     571                        visit_children = false;
     572
     573                        if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( varExpr->result ) ) {
     574                                long long int value;
     575                                if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
     576                                        // enumerators are const expr
     577                                        return;
     578                                }
     579                        }
     580                        isConstExpr = false;
     581                }
     582
    566583                bool isConstExpr = true;
    567584        };
Note: See TracChangeset for help on using the changeset viewer.