Changeset 221c542e for src


Ignore:
Timestamp:
Jan 24, 2024, 8:19:18 AM (20 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master
Children:
64c4b4d
Parents:
bad9c8f (diff), 71b5aad5 (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
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Decl.hpp

    rbad9c8f r221c542e  
    312312        ptr<Type> base;
    313313        enum class EnumHiding { Visible, Hide } hide;
    314 
    315314        EnumDecl( const CodeLocation& loc, const std::string& name, bool isTyped = false,
    316315                std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall,
  • src/CodeGen/CodeGenerator.cpp

    rbad9c8f r221c542e  
    11351135                if ( clause->when_cond ) {
    11361136                        output << "when(";
    1137                         stmt->timeout_cond->accept( *visitor );
     1137                        clause->when_cond->accept( *visitor );
    11381138                        output << ") ";
    11391139                }
  • src/InitTweak/FixInit.cpp

    rbad9c8f r221c542e  
    4949        if ( auto inst = dynamic_cast<const ast::StructInstType *>( t ) ) {
    5050                return inst->base->params;
    51         }
    52         if ( auto inst = dynamic_cast<const ast::UnionInstType *>( t ) ) {
     51        } else if ( auto inst = dynamic_cast<const ast::UnionInstType *>( t ) ) {
    5352                return inst->base->params;
    5453        }
     
    245244const ast::DeclWithType * getDtorFunc( const ast::ObjectDecl * objDecl, const ast::Stmt * input, std::list< ast::ptr<ast::Stmt> > & stmtsToAdd ) {
    246245        const CodeLocation loc = input->location;
    247         // unwrap implicit statement wrapper
    248         // Statement * dtor = input;
    249246        assert( input );
    250         // std::list< const ast::Expr * > matches;
    251247        auto matches = collectCtorDtorCalls( input );
    252248
    253         if ( dynamic_cast< const ast::ExprStmt * >( input ) ) {
    254                 // only one destructor call in the expression
    255                 if ( matches.size() == 1 ) {
    256                         auto func = getFunction( matches.front() );
    257                         assertf( func, "getFunction failed to find function in %s", toString( matches.front() ).c_str() );
    258 
    259                         // cleanup argument must be a function, not an object (including function pointer)
    260                         if ( auto dtorFunc = dynamic_cast< const ast::FunctionDecl * > ( func ) ) {
    261                                 if ( dtorFunc->type->forall.empty() ) {
    262                                         // simple case where the destructor is a monomorphic function call - can simply
    263                                         // use that function as the cleanup function.
    264                                         return func;
    265                                 }
     249        // The simple case requires a direct call and only one destructor call.
     250        if ( dynamic_cast< const ast::ExprStmt * >( input ) && matches.size() == 1 ) {
     251                auto func = getFunction( matches.front() );
     252                assertf( func, "getFunction failed to find function in %s", toString( matches.front() ).c_str() );
     253
     254                // cleanup argument must be a function, not an object (including function pointer)
     255                if ( auto dtorFunc = dynamic_cast< const ast::FunctionDecl * > ( func ) ) {
     256                        if ( dtorFunc->type->forall.empty() ) {
     257                                // simple case where the destructor is a monomorphic function call - can simply
     258                                // use that function as the cleanup function.
     259                                return func;
    266260                        }
    267261                }
     
    301295        for ( auto i = translationUnit.decls.begin(); i != translationUnit.decls.end(); ++i ) {
    302296                try {
    303                         // maybeAccept( *i, fixer ); translationUnit should never contain null
    304297                        *i = (*i)->accept(fixer);
    305298                        translationUnit.decls.splice( i, fixer.core.staticDtorDecls );
     
    314307
    315308const ast::StmtExpr * StmtExprResult::previsit( const ast::StmtExpr * stmtExpr ) {
    316         // we might loose the result expression here so add a pointer to trace back
    317309        assert( stmtExpr->result );
    318         const ast::Type * result = stmtExpr->result;
    319         if ( ! result->isVoid() ) {
    320                 auto mutExpr = mutate(stmtExpr);
    321                 const ast::CompoundStmt * body = mutExpr->stmts;
    322                 assert( ! body->kids.empty() );
    323                 mutExpr->resultExpr = body->kids.back().strict_as<ast::ExprStmt>();
    324                 return mutExpr;
    325         }
    326         return stmtExpr;
     310        if ( stmtExpr->result->isVoid() ) return stmtExpr;
     311
     312        auto mutExpr = mutate( stmtExpr );
     313        const ast::CompoundStmt * body = mutExpr->stmts;
     314        assert( !body->kids.empty() );
     315        mutExpr->resultExpr = body->kids.back().strict_as<ast::ExprStmt>();
     316        return mutExpr;
    327317}
    328318
     
    330320        // wrap each top-level ExprStmt in a block so that destructors for argument and return temporaries are destroyed
    331321        // in the correct places
    332         ast::CompoundStmt * ret = new ast::CompoundStmt( stmt->location, { stmt } );
    333         return ret;
     322        return new ast::CompoundStmt( stmt->location, { stmt } );
    334323}
    335324
     
    556545        arg = cpCtor;
    557546        return destructRet( tmp, arg );
    558 
    559         // impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) );
    560547}
    561548
     
    608595        }
    609596        return nullptr;
    610         // impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
    611597}
    612598
     
    625611        for ( auto & arg : appExpr->args ) {
    626612                const ast::Type * formal = nullptr;
    627                 if ( iter != params.end() ) { // does not copy construct C-style variadic arguments
    628                         // DeclarationWithType * param = *iter++;
     613                // Do not copy construct C-style variadic arguments.
     614                if ( iter != params.end() ) {
    629615                        formal = *iter++;
    630616                }
     
    659645        // deletion of wrapper should be handled by pass template now
    660646
    661         // impCpCtorExpr->callExpr = nullptr;
    662647        assert (appExpr->env == nullptr);
    663648        appExpr->env = impCpCtorExpr->env;
    664         // std::swap( impCpCtorExpr->env, appExpr->env );
    665         // assert( impCpCtorExpr->env == nullptr );
    666         // delete impCpCtorExpr;
    667649
    668650        if ( returnDecl ) {
     
    676658                }
    677659                // move env from appExpr to retExpr
    678                 // std::swap( assign->env, appExpr->env );
    679660                assign->env = appExpr->env;
    680661                // actual env is handled by common routine that replaces WithTypeSubstitution
     
    716697
    717698        assert( stmtExpr->result );
    718         // const ast::Type * result = stmtExpr->result;
    719         if ( ! stmtExpr->result->isVoid() ) {
    720                 static UniqueName retNamer("_tmp_stmtexpr_ret");
    721 
    722                 // result = result->clone();
    723                 auto result = env->apply( stmtExpr->result.get() ).node;
    724                 if ( ! InitTweak::isConstructable( result ) ) {
    725                         // delete result;
    726                         return stmtExpr;
    727                 }
    728                 auto mutResult = result.get_and_mutate();
    729                 mutResult->set_const(false);
    730 
    731                 // create variable that will hold the result of the stmt expr
    732                 auto ret = new ast::ObjectDecl(loc, retNamer.newName(), mutResult, nullptr );
    733                 stmtsToAddBefore.push_back( new ast::DeclStmt(loc, ret ) );
    734 
    735                 assertf(
    736                         stmtExpr->resultExpr,
    737                         "Statement-Expression should have a resulting expression at %s:%d",
    738                         stmtExpr->location.filename.c_str(),
    739                         stmtExpr->location.first_line
    740                 );
    741 
    742                 const ast::ExprStmt * last = stmtExpr->resultExpr;
    743                 // xxx - if this is non-unique, need to copy while making resultExpr ref
    744                 assertf(last->unique(), "attempt to modify weakly shared statement");
    745                 auto mutLast = mutate(last);
    746                 // above assertion means in-place mutation is OK
    747                 try {
    748                         mutLast->expr = makeCtorDtor( "?{}", ret, mutLast->expr );
    749                 } catch(...) {
    750                         std::cerr << "*CFA internal error: ";
    751                         std::cerr << "can't resolve implicit constructor";
    752                         std::cerr << " at " << stmtExpr->location.filename;
    753                         std::cerr << ":" << stmtExpr->location.first_line << std::endl;
    754 
    755                         abort();
    756                 }
    757 
    758                 // add destructors after current statement
    759                 stmtsToAddAfter.push_back( new ast::ExprStmt(loc, makeCtorDtor( "^?{}", ret ) ) );
    760 
    761                 // must have a non-empty body, otherwise it wouldn't have a result
    762                 assert( ! stmts.empty() );
    763 
    764                 // if there is a return decl, add a use as the last statement; will not have return decl on non-constructable returns
    765                 stmts.push_back( new ast::ExprStmt(loc, new ast::VariableExpr(loc, ret ) ) );
    766         } // if
     699        if ( stmtExpr->result->isVoid() ) {
     700                assert( stmtExpr->returnDecls.empty() );
     701                assert( stmtExpr->dtors.empty() );
     702
     703                return stmtExpr;
     704        }
     705
     706        static UniqueName retNamer("_tmp_stmtexpr_ret");
     707
     708        auto result = env->apply( stmtExpr->result.get() ).node;
     709        if ( ! InitTweak::isConstructable( result ) ) {
     710                return stmtExpr;
     711        }
     712        auto mutResult = result.get_and_mutate();
     713        mutResult->set_const(false);
     714
     715        // create variable that will hold the result of the stmt expr
     716        auto ret = new ast::ObjectDecl(loc, retNamer.newName(), mutResult, nullptr );
     717        stmtsToAddBefore.push_back( new ast::DeclStmt(loc, ret ) );
     718
     719        assertf(
     720                stmtExpr->resultExpr,
     721                "Statement-Expression should have a resulting expression at %s:%d",
     722                stmtExpr->location.filename.c_str(),
     723                stmtExpr->location.first_line
     724        );
     725
     726        const ast::ExprStmt * last = stmtExpr->resultExpr;
     727        // xxx - if this is non-unique, need to copy while making resultExpr ref
     728        assertf(last->unique(), "attempt to modify weakly shared statement");
     729        auto mutLast = mutate(last);
     730        // above assertion means in-place mutation is OK
     731        try {
     732                mutLast->expr = makeCtorDtor( "?{}", ret, mutLast->expr );
     733        } catch(...) {
     734                std::cerr << "*CFA internal error: ";
     735                std::cerr << "can't resolve implicit constructor";
     736                std::cerr << " at " << stmtExpr->location.filename;
     737                std::cerr << ":" << stmtExpr->location.first_line << std::endl;
     738
     739                abort();
     740        }
     741
     742        // add destructors after current statement
     743        stmtsToAddAfter.push_back( new ast::ExprStmt(loc, makeCtorDtor( "^?{}", ret ) ) );
     744
     745        // must have a non-empty body, otherwise it wouldn't have a result
     746        assert( ! stmts.empty() );
     747
     748        // if there is a return decl, add a use as the last statement; will not have return decl on non-constructable returns
     749        stmts.push_back( new ast::ExprStmt(loc, new ast::VariableExpr(loc, ret ) ) );
    767750
    768751        assert( stmtExpr->returnDecls.empty() );
     
    798781        auto mutExpr = mutate(unqExpr);
    799782        if ( ! unqMap.count( unqExpr->id ) ) {
    800                 // resolve expr and find its
    801 
    802783                auto impCpCtorExpr = mutExpr->expr.as<ast::ImplicitCopyCtorExpr>();
    803                 // PassVisitor<ResolveCopyCtors> fixer;
    804 
    805784                mutExpr->expr = mutExpr->expr->accept( *visitor );
    806785                // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought
     
    820799        } else {
    821800                // take data from other UniqueExpr to ensure consistency
    822                 // delete unqExpr->get_expr();
    823801                mutExpr->expr = unqMap[mutExpr->id]->expr;
    824                 // delete unqExpr->result;
    825802                mutExpr->result = mutExpr->expr->result;
    826803        }
     
    832809
    833810        // since this removes the init field from objDecl, it must occur after children are mutated (i.e. postvisit)
    834         if ( ast::ptr<ast::ConstructorInit> ctorInit = _objDecl->init.as<ast::ConstructorInit>() ) {
    835                 auto objDecl = mutate(_objDecl);
    836 
    837                 // could this be non-unique?
    838                 if (objDecl != _objDecl) {
    839                         std::cerr << "FixInit: non-unique object decl " << objDecl->location << objDecl->name << std::endl;
    840                 }
    841                 // a decision should have been made by the resolver, so ctor and init are not both non-NULL
    842                 assert( ! ctorInit->ctor || ! ctorInit->init );
    843                 if ( const ast::Stmt * ctor = ctorInit->ctor ) {
    844                         if ( objDecl->storage.is_static ) {
    845                                 addDataSectionAttribute(objDecl);
    846                                 // originally wanted to take advantage of gcc nested functions, but
    847                                 // we get memory errors with this approach. To remedy this, the static
    848                                 // variable is hoisted when the destructor needs to be called.
    849                                 //
    850                                 // generate:
    851                                 // static T __objName_static_varN;
    852                                 // void __objName_dtor_atexitN() {
    853                                 //   __dtor__...;
    854                                 // }
    855                                 // int f(...) {
    856                                 //   ...
    857                                 //   static bool __objName_uninitialized = true;
    858                                 //   if (__objName_uninitialized) {
    859                                 //     __ctor(__objName);
    860                                 //     __objName_uninitialized = false;
    861                                 //     atexit(__objName_dtor_atexitN);
    862                                 //   }
    863                                 //   ...
    864                                 // }
    865 
    866                                 static UniqueName dtorCallerNamer( "_dtor_atexit" );
    867 
    868                                 // static bool __objName_uninitialized = true
    869                                 auto boolType = new ast::BasicType( ast::BasicType::Kind::Bool );
    870                                 auto boolInitExpr = new ast::SingleInit(loc, ast::ConstantExpr::from_int(loc, 1 ) );
    871                                 auto isUninitializedVar = new ast::ObjectDecl(loc, objDecl->mangleName + "_uninitialized", boolType, boolInitExpr, ast::Storage::Static, ast::Linkage::Cforall);
    872                                 isUninitializedVar->fixUniqueId();
    873 
    874                                 // __objName_uninitialized = false;
    875                                 auto setTrue = new ast::UntypedExpr(loc, new ast::NameExpr(loc, "?=?" ) );
    876                                 setTrue->args.push_back( new ast::VariableExpr(loc, isUninitializedVar ) );
    877                                 setTrue->args.push_back( ast::ConstantExpr::from_int(loc, 0 ) );
    878 
    879                                 // generate body of if
    880                                 auto initStmts = new ast::CompoundStmt(loc);
    881                                 auto & body = initStmts->kids;
    882                                 body.push_back( ctor );
    883                                 body.push_back( new ast::ExprStmt(loc, setTrue ) );
    884 
    885                                 // put it all together
    886                                 auto ifStmt = new ast::IfStmt(loc, new ast::VariableExpr(loc, isUninitializedVar ), initStmts, 0 );
    887                                 stmtsToAddAfter.push_back( new ast::DeclStmt(loc, isUninitializedVar ) );
    888                                 stmtsToAddAfter.push_back( ifStmt );
    889 
    890                                 const ast::Stmt * dtor = ctorInit->dtor;
    891 
    892                                 // these should be automatically managed once reassigned
    893                                 // objDecl->set_init( nullptr );
    894                                 // ctorInit->set_ctor( nullptr );
    895                                 // ctorInit->set_dtor( nullptr );
    896                                 if ( dtor ) {
    897                                         // if the object has a non-trivial destructor, have to
    898                                         // hoist it and the object into the global space and
    899                                         // call the destructor function with atexit.
    900 
    901                                         // Statement * dtorStmt = dtor->clone();
    902 
    903                                         // void __objName_dtor_atexitN(...) {...}
    904                                         ast::FunctionDecl * dtorCaller = new ast::FunctionDecl(loc, objDecl->mangleName + dtorCallerNamer.newName(), {}, {}, {}, {}, new ast::CompoundStmt(loc, {dtor}), ast::Storage::Static, ast::Linkage::C );
    905                                         dtorCaller->fixUniqueId();
    906                                         // dtorCaller->stmts->push_back( dtor );
    907 
    908                                         // atexit(dtor_atexit);
    909                                         auto callAtexit = new ast::UntypedExpr(loc, new ast::NameExpr(loc, "atexit" ) );
    910                                         callAtexit->args.push_back( new ast::VariableExpr(loc, dtorCaller ) );
    911 
    912                                         body.push_back( new ast::ExprStmt(loc, callAtexit ) );
    913 
    914                                         // hoist variable and dtor caller decls to list of decls that will be added into global scope
    915                                         staticDtorDecls.push_back( objDecl );
    916                                         staticDtorDecls.push_back( dtorCaller );
    917 
    918                                         // need to rename object uniquely since it now appears
    919                                         // at global scope and there could be multiple function-scoped
    920                                         // static variables with the same name in different functions.
    921                                         // Note: it isn't sufficient to modify only the mangleName, because
    922                                         // then subsequent SymbolTable passes can choke on seeing the object's name
    923                                         // if another object has the same name and type. An unfortunate side-effect
    924                                         // of renaming the object is that subsequent NameExprs may fail to resolve,
    925                                         // but there shouldn't be any remaining past this point.
    926                                         static UniqueName staticNamer( "_static_var" );
    927                                         objDecl->name = objDecl->name + staticNamer.newName();
    928                                         objDecl->mangleName = Mangle::mangle( objDecl );
    929                                         objDecl->init = nullptr;
    930 
    931                                         // xxx - temporary hack: need to return a declaration, but want to hoist the current object out of this scope
    932                                         // create a new object which is never used
    933                                         static UniqueName dummyNamer( "_dummy" );
    934                                         auto dummy = new ast::ObjectDecl(loc, dummyNamer.newName(), new ast::PointerType(new ast::VoidType()), nullptr, ast::Storage::Static, ast::Linkage::Cforall, 0, { new ast::Attribute("unused") } );
    935                                         // delete ctorInit;
    936                                         return dummy;
    937                                 } else {
    938                                         objDecl->init = nullptr;
    939                                         return objDecl;
    940                                 }
     811        ast::ptr<ast::ConstructorInit> ctorInit = _objDecl->init.as<ast::ConstructorInit>();
     812
     813        if ( nullptr == ctorInit ) return _objDecl;
     814
     815        auto objDecl = mutate(_objDecl);
     816
     817        // could this be non-unique?
     818        if (objDecl != _objDecl) {
     819                std::cerr << "FixInit: non-unique object decl " << objDecl->location << objDecl->name << std::endl;
     820        }
     821        // a decision should have been made by the resolver, so ctor and init are not both non-NULL
     822        assert( ! ctorInit->ctor || ! ctorInit->init );
     823        if ( const ast::Stmt * ctor = ctorInit->ctor ) {
     824                if ( objDecl->storage.is_static ) {
     825                        addDataSectionAttribute(objDecl);
     826                        // originally wanted to take advantage of gcc nested functions, but
     827                        // we get memory errors with this approach. To remedy this, the static
     828                        // variable is hoisted when the destructor needs to be called.
     829                        //
     830                        // generate:
     831                        // static T __objName_static_varN;
     832                        // void __objName_dtor_atexitN() {
     833                        //   __dtor__...;
     834                        // }
     835                        // int f(...) {
     836                        //   ...
     837                        //   static bool __objName_uninitialized = true;
     838                        //   if (__objName_uninitialized) {
     839                        //     __ctor(__objName);
     840                        //     __objName_uninitialized = false;
     841                        //     atexit(__objName_dtor_atexitN);
     842                        //   }
     843                        //   ...
     844                        // }
     845
     846                        static UniqueName dtorCallerNamer( "_dtor_atexit" );
     847
     848                        // static bool __objName_uninitialized = true
     849                        auto boolType = new ast::BasicType( ast::BasicType::Kind::Bool );
     850                        auto boolInitExpr = new ast::SingleInit(loc, ast::ConstantExpr::from_int(loc, 1 ) );
     851                        auto isUninitializedVar = new ast::ObjectDecl(loc, objDecl->mangleName + "_uninitialized", boolType, boolInitExpr, ast::Storage::Static, ast::Linkage::Cforall);
     852                        isUninitializedVar->fixUniqueId();
     853
     854                        // __objName_uninitialized = false;
     855                        auto setTrue = new ast::UntypedExpr(loc, new ast::NameExpr(loc, "?=?" ) );
     856                        setTrue->args.push_back( new ast::VariableExpr(loc, isUninitializedVar ) );
     857                        setTrue->args.push_back( ast::ConstantExpr::from_int(loc, 0 ) );
     858
     859                        // generate body of if
     860                        auto initStmts = new ast::CompoundStmt(loc);
     861                        auto & body = initStmts->kids;
     862                        body.push_back( ctor );
     863                        body.push_back( new ast::ExprStmt(loc, setTrue ) );
     864
     865                        // put it all together
     866                        auto ifStmt = new ast::IfStmt(loc, new ast::VariableExpr(loc, isUninitializedVar ), initStmts, 0 );
     867                        stmtsToAddAfter.push_back( new ast::DeclStmt(loc, isUninitializedVar ) );
     868                        stmtsToAddAfter.push_back( ifStmt );
     869
     870                        const ast::Stmt * dtor = ctorInit->dtor;
     871                        if ( dtor ) {
     872                                // if the object has a non-trivial destructor, have to
     873                                // hoist it and the object into the global space and
     874                                // call the destructor function with atexit.
     875
     876                                // void __objName_dtor_atexitN(...) {...}
     877                                ast::FunctionDecl * dtorCaller = new ast::FunctionDecl(loc, objDecl->mangleName + dtorCallerNamer.newName(), {}, {}, {}, {}, new ast::CompoundStmt(loc, {dtor}), ast::Storage::Static, ast::Linkage::C );
     878                                dtorCaller->fixUniqueId();
     879
     880                                // atexit(dtor_atexit);
     881                                auto callAtexit = new ast::UntypedExpr(loc, new ast::NameExpr(loc, "atexit" ) );
     882                                callAtexit->args.push_back( new ast::VariableExpr(loc, dtorCaller ) );
     883
     884                                body.push_back( new ast::ExprStmt(loc, callAtexit ) );
     885
     886                                // hoist variable and dtor caller decls to list of decls that will be added into global scope
     887                                staticDtorDecls.push_back( objDecl );
     888                                staticDtorDecls.push_back( dtorCaller );
     889
     890                                // need to rename object uniquely since it now appears
     891                                // at global scope and there could be multiple function-scoped
     892                                // static variables with the same name in different functions.
     893                                // Note: it isn't sufficient to modify only the mangleName, because
     894                                // then subsequent SymbolTable passes can choke on seeing the object's name
     895                                // if another object has the same name and type. An unfortunate side-effect
     896                                // of renaming the object is that subsequent NameExprs may fail to resolve,
     897                                // but there shouldn't be any remaining past this point.
     898                                static UniqueName staticNamer( "_static_var" );
     899                                objDecl->name = objDecl->name + staticNamer.newName();
     900                                objDecl->mangleName = Mangle::mangle( objDecl );
     901                                objDecl->init = nullptr;
     902
     903                                // xxx - temporary hack: need to return a declaration, but want to hoist the current object out of this scope
     904                                // create a new object which is never used
     905                                static UniqueName dummyNamer( "_dummy" );
     906                                auto dummy = new ast::ObjectDecl(loc, dummyNamer.newName(), new ast::PointerType(new ast::VoidType()), nullptr, ast::Storage::Static, ast::Linkage::Cforall, 0, { new ast::Attribute("unused") } );
     907                                return dummy;
    941908                        } else {
    942                                 auto implicit = strict_dynamic_cast< const ast::ImplicitCtorDtorStmt * > ( ctor );
    943                                 auto ctorStmt = implicit->callStmt.as<ast::ExprStmt>();
    944                                 const ast::ApplicationExpr * ctorCall = nullptr;
    945                                 if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->expr )) && ctorCall->args.size() == 2 ) {
    946                                         // clean up intrinsic copy constructor calls by making them into SingleInits
    947                                         const ast::Expr * ctorArg = ctorCall->args.back();
    948                                         // ctorCall should be gone afterwards
    949                                         auto mutArg = mutate(ctorArg);
    950                                         mutArg->env = ctorCall->env;
    951                                         // std::swap( ctorArg->env, ctorCall->env );
    952                                         objDecl->init = new ast::SingleInit(loc, mutArg );
    953 
    954                                         // ctorCall->args.pop_back();
    955                                 } else {
    956                                         stmtsToAddAfter.push_back( ctor );
    957                                         objDecl->init = nullptr;
    958                                         // ctorInit->ctor = nullptr;
    959                                 }
    960 
    961                                 const ast::Stmt * dtor = ctorInit->dtor;
    962                                 if ( dtor ) {
    963                                         auto implicit = strict_dynamic_cast< const ast::ImplicitCtorDtorStmt * >( dtor );
    964                                         const ast::Stmt * dtorStmt = implicit->callStmt;
    965 
    966                                         // don't need to call intrinsic dtor, because it does nothing, but
    967                                         // non-intrinsic dtors must be called
    968                                         if ( ! isIntrinsicSingleArgCallStmt( dtorStmt ) ) {
    969                                                 // set dtor location to the object's location for error messages
    970                                                 auto dtorFunc = getDtorFunc( objDecl, dtorStmt, stmtsToAddBefore );
    971                                                 objDecl->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, dtorFunc ) } ) );
    972                                                 // ctorInit->dtor = nullptr;
    973                                         } // if
    974                                 }
    975                         } // if
    976                 } else if ( const ast::Init * init = ctorInit->init ) {
    977                         objDecl->init = init;
    978                         // ctorInit->init = nullptr;
     909                                objDecl->init = nullptr;
     910                                return objDecl;
     911                        }
    979912                } else {
    980                         // no constructor and no initializer, which is okay
    981                         objDecl->init = nullptr;
     913                        auto implicit = strict_dynamic_cast< const ast::ImplicitCtorDtorStmt * > ( ctor );
     914                        auto ctorStmt = implicit->callStmt.as<ast::ExprStmt>();
     915                        const ast::ApplicationExpr * ctorCall = nullptr;
     916                        if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->expr )) && ctorCall->args.size() == 2 ) {
     917                                // clean up intrinsic copy constructor calls by making them into SingleInits
     918                                const ast::Expr * ctorArg = ctorCall->args.back();
     919                                // ctorCall should be gone afterwards
     920                                auto mutArg = mutate(ctorArg);
     921                                mutArg->env = ctorCall->env;
     922                                objDecl->init = new ast::SingleInit(loc, mutArg );
     923                        } else {
     924                                stmtsToAddAfter.push_back( ctor );
     925                                objDecl->init = nullptr;
     926                        }
     927
     928                        const ast::Stmt * dtor = ctorInit->dtor;
     929                        if ( dtor ) {
     930                                auto implicit = strict_dynamic_cast< const ast::ImplicitCtorDtorStmt * >( dtor );
     931                                const ast::Stmt * dtorStmt = implicit->callStmt;
     932
     933                                // don't need to call intrinsic dtor, because it does nothing, but
     934                                // non-intrinsic dtors must be called
     935                                if ( ! isIntrinsicSingleArgCallStmt( dtorStmt ) ) {
     936                                        // set dtor location to the object's location for error messages
     937                                        auto dtorFunc = getDtorFunc( objDecl, dtorStmt, stmtsToAddBefore );
     938                                        objDecl->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, dtorFunc ) } ) );
     939                                } // if
     940                        }
    982941                } // if
    983                 // delete ctorInit;
    984                 return objDecl;
     942        } else if ( const ast::Init * init = ctorInit->init ) {
     943                objDecl->init = init;
     944        } else {
     945                // no constructor and no initializer, which is okay
     946                objDecl->init = nullptr;
    985947        } // if
    986         return _objDecl;
     948        return objDecl;
    987949}
    988950
     
    1006968
    1007969void LabelFinder::previsit( const ast::CompoundStmt * stmt ) {
    1008         previsit( (const ast::Stmt *) stmt );
     970        previsit( (const ast::Stmt *)stmt );
    1009971        Parent::previsit( stmt );
    1010972}
     
    1022984        // its children manually.
    1023985        if (funcDecl->type) funcDecl->type->accept(finder);
    1024         // maybeAccept( funcDecl->type, finder );
    1025         if (funcDecl->stmts) funcDecl->stmts->accept(finder) ;
     986        if (funcDecl->stmts) funcDecl->stmts->accept(finder);
    1026987
    1027988        // all labels for this function have been collected, insert destructors as appropriate via implicit recursion.
     
    10781039}
    10791040
     1041/// Should we check for warnings? (The function is user-defined constrctor or destructor.)
    10801042bool checkWarnings( const ast::FunctionDecl * funcDecl ) {
    1081         // only check for warnings if the current function is a user-defined constructor or destructor
    10821043        if ( ! funcDecl ) return false;
    10831044        if ( ! funcDecl->stmts ) return false;
     
    11051066
    11061067        isCtor = CodeGen::isConstructor( function->name );
    1107         if ( checkWarnings( function ) ) {
    1108                 // const ast::FunctionType * type = function->type;
    1109                 // assert( ! type->params.empty() );
    1110                 thisParam = function->params.front().strict_as<ast::ObjectDecl>();
    1111                 auto thisType = getPointerBase( thisParam->get_type() );
    1112                 auto structType = dynamic_cast< const ast::StructInstType * >( thisType );
    1113                 if ( structType ) {
    1114                         structDecl = structType->base;
    1115                         for ( auto & member : structDecl->members ) {
    1116                                 if ( auto field = member.as<ast::ObjectDecl>() ) {
    1117                                         // record all of the struct type's members that need to be constructed or
    1118                                         // destructed by the end of the function
    1119                                         unhandled.insert( field );
    1120                                 }
     1068
     1069        // Remaining code is only for warnings.
     1070        if ( ! checkWarnings( function ) ) return;
     1071        thisParam = function->params.front().strict_as<ast::ObjectDecl>();
     1072        auto thisType = getPointerBase( thisParam->get_type() );
     1073        auto structType = dynamic_cast< const ast::StructInstType * >( thisType );
     1074        if ( structType ) {
     1075                structDecl = structType->base;
     1076                for ( auto & member : structDecl->members ) {
     1077                        if ( auto field = member.as<ast::ObjectDecl>() ) {
     1078                                // record all of the struct type's members that need to be constructed or
     1079                                // destructed by the end of the function
     1080                                unhandled.insert( field );
    11211081                        }
    11221082                }
     
    11641124
    11651125                        // insert and resolve default/copy constructor call for each field that's unhandled
    1166                         // std::list< const ast::Stmt * > stmt;
    11671126                        ast::Expr * arg2 = nullptr;
    11681127                        if ( function->name == "?{}" && isCopyFunction( function ) ) {
    11691128                                // if copy ctor, need to pass second-param-of-this-function.field
    1170                                 // std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters();
    11711129                                assert( function->params.size() == 2 );
    11721130                                arg2 = new ast::MemberExpr(funcDecl->location, field, new ast::VariableExpr(funcDecl->location, function->params.back() ) );
     
    11791137
    11801138                        if ( callStmt ) {
    1181                                 // auto & callStmt = stmt.front();
    1182 
    11831139                                try {
    11841140                                        callStmt = callStmt->accept( *visitor );
     
    11861142                                                mutStmts->push_front( callStmt );
    11871143                                        } else { // TODO: don't generate destructor function/object for intrinsic calls
    1188                                                 // destructor statements should be added at the end
    1189                                                 // function->get_statements()->push_back( callStmt );
    11901144
    11911145                                                // Optimization: do not need to call intrinsic destructors on members
     
    12221176                throw errors;
    12231177        }
    1224         // return funcDecl;
    12251178        return function;
    12261179}
     
    12561209
    12571210        std::string fname = getFunctionName( appExpr );
    1258         if ( fname == function->name ) {
    1259                 // call to same kind of function
    1260                 const ast::Expr * firstParam = appExpr->args.front();
    1261 
    1262                 if ( isThisExpression( firstParam, thisParam ) ) {
    1263                         // if calling another constructor on thisParam, assume that function handles
    1264                         // all members - if it doesn't a warning will appear in that function.
    1265                         unhandled.clear();
    1266                 } else if ( auto memberExpr = isThisMemberExpr( firstParam, thisParam ) ) {
    1267                         // if first parameter is a member expression on the this parameter,
    1268                         // then remove the member from unhandled set.
    1269                         if ( isThisExpression( memberExpr->aggregate, thisParam ) ) {
    1270                                 unhandled.erase( memberExpr->member );
    1271                         }
     1211        if ( fname != function->name ) return;
     1212
     1213        // call to same kind of function
     1214        const ast::Expr * firstParam = appExpr->args.front();
     1215        if ( isThisExpression( firstParam, thisParam ) ) {
     1216                // if calling another constructor on thisParam, assume that function handles
     1217                // all members - if it doesn't a warning will appear in that function.
     1218                unhandled.clear();
     1219        } else if ( auto memberExpr = isThisMemberExpr( firstParam, thisParam ) ) {
     1220                // if first parameter is a member expression on the this parameter,
     1221                // then remove the member from unhandled set.
     1222                if ( isThisExpression( memberExpr->aggregate, thisParam ) ) {
     1223                        unhandled.erase( memberExpr->member );
    12721224                }
    12731225        }
     
    13151267        ast::ptr<ast::ApplicationExpr> callExpr = ctorExpr->callExpr.strict_as<ast::ApplicationExpr>();
    13161268        ast::ptr<ast::TypeSubstitution> env = ctorExpr->env;
    1317         // ctorExpr->set_callExpr( nullptr );
    1318         // ctorExpr->set_env( nullptr );
    13191269
    13201270        // 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.
  • src/Parser/ExpressionNode.cc

    rbad9c8f r221c542e  
    673673                ast::LogicalFlag flag ) {
    674674        return new ast::LogicalExpr( location,
    675                 notZeroExpr( maybeMoveBuild( expr_node1 ) ),
    676                 notZeroExpr( maybeMoveBuild( expr_node2 ) ),
     675                maybeMoveBuild( expr_node1 ),
     676                maybeMoveBuild( expr_node2 ),
    677677                flag
    678678        );
     
    713713                ExpressionNode * expr_node3 ) {
    714714        return new ast::ConditionalExpr( location,
    715                 notZeroExpr( maybeMoveBuild( expr_node1 ) ),
     715                maybeMoveBuild( expr_node1 ),
    716716                maybeMoveBuild( expr_node2 ),
    717717                maybeMoveBuild( expr_node3 )
  • src/Parser/parserutility.cc

    rbad9c8f r221c542e  
    2727//    if ( (int)(x != 0) ) ...
    2828
    29 ast::Expr * notZeroExpr( ast::Expr * orig ) {
     29ast::Expr * notZeroExpr( const ast::Expr * orig ) {
    3030        return ( !orig ) ? nullptr : new ast::CastExpr( orig->location,
    3131                ast::UntypedExpr::createCall( orig->location,
  • src/Parser/parserutility.h

    rbad9c8f r221c542e  
    2121}
    2222
    23 ast::Expr * notZeroExpr( ast::Expr *orig );
     23ast::Expr * notZeroExpr( const ast::Expr *orig );
    2424
    2525template< typename T >
  • src/ResolvExpr/CandidateFinder.cpp

    rbad9c8f r221c542e  
    4646#include "AST/Type.hpp"
    4747#include "Common/utility.h"       // for move, copy
     48#include "Parser/parserutility.h" // for notZeroExpr
    4849#include "SymTab/Mangler.h"
    4950#include "Tuples/Tuples.h"        // for handleTupleAssignment
     
    15021503        void Finder::postvisit( const ast::LogicalExpr * logicalExpr ) {
    15031504                CandidateFinder finder1( context, tenv );
    1504                 finder1.find( logicalExpr->arg1, ResolveMode::withAdjustment() );
     1505                ast::ptr<ast::Expr> arg1 = notZeroExpr( logicalExpr->arg1 );
     1506                finder1.find( arg1, ResolveMode::withAdjustment() );
    15051507                if ( finder1.candidates.empty() ) return;
    15061508
    15071509                CandidateFinder finder2( context, tenv );
    1508                 finder2.find( logicalExpr->arg2, ResolveMode::withAdjustment() );
     1510                ast::ptr<ast::Expr> arg2 = notZeroExpr( logicalExpr->arg2 );
     1511                finder2.find( arg2, ResolveMode::withAdjustment() );
    15091512                if ( finder2.candidates.empty() ) return;
    15101513
     
    15321535                // candidates for condition
    15331536                CandidateFinder finder1( context, tenv );
    1534                 finder1.find( conditionalExpr->arg1, ResolveMode::withAdjustment() );
     1537                ast::ptr<ast::Expr> arg1 = notZeroExpr( conditionalExpr->arg1 );
     1538                finder1.find( arg1, ResolveMode::withAdjustment() );
    15351539                if ( finder1.candidates.empty() ) return;
    15361540
  • src/Validate/Autogen.cpp

    rbad9c8f r221c542e  
    803803}
    804804
    805 struct PseudoFuncGenerateRoutine final :
    806                 public ast::WithDeclsToAdd<>,
    807                 public ast::WithShortCircuiting {
    808         void previsit( const ast::EnumDecl * enumDecl );
    809 };
    810 
    811 void PseudoFuncGenerateRoutine::previsit( const ast::EnumDecl * enumDecl ) {
    812         const CodeLocation& location = enumDecl->location;
    813         if ( enumDecl->members.size() == 0 || !enumDecl->base || enumDecl->name == "" ) return;
    814 
    815         std::vector<ast::ptr<ast::Init>> inits;
    816         std::vector<ast::ptr<ast::Init>> labels;
    817         for ( const ast::Decl * mem: enumDecl->members ) {
    818                 auto memAsObjectDecl = dynamic_cast< const ast::ObjectDecl * >( mem );
    819                 inits.emplace_back( memAsObjectDecl->init );
    820                 labels.emplace_back( new ast::SingleInit(
    821                         location, ast::ConstantExpr::from_string(location, mem->name) ) );
    822         }
    823         auto init = new ast::ListInit( location, std::move( inits ) );
    824         auto label_strings = new ast::ListInit( location, std::move(labels) );
    825         auto values = new ast::ObjectDecl(
    826                 location,
    827                 "__enum_values_"+enumDecl->name,
    828                 new ast::ArrayType(
    829                         // new ast::PointerType( new ast::BasicType{ ast::BasicType::Char} ),
    830                         enumDecl->base,
    831                         ast::ConstantExpr::from_int( location, enumDecl->members.size() ),
    832                         ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim
    833                 )
    834                 ,init
    835                 ,
    836                 ast::Storage::Static,
    837                 ast::Linkage::AutoGen
    838         );
    839         auto label_arr = new ast::ObjectDecl(
    840                 location,
    841                 "__enum_labels_"+enumDecl->name,
    842                 new ast::ArrayType(
    843                         new ast::PointerType( new ast::BasicType{ ast::BasicType::Char} ),
    844                         ast::ConstantExpr::from_int( location, enumDecl->members.size() ),
    845                         ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim
    846                 ),
    847                 label_strings,
    848                 ast::Storage::Static,
    849                 ast::Linkage::AutoGen
    850         );
    851 
    852         declsToAddAfter.push_back( values );
    853         declsToAddAfter.push_back( label_arr );
    854 }
    855 
    856805} // namespace
    857806
    858807void autogenerateRoutines( ast::TranslationUnit & translationUnit ) {
    859808        ast::Pass<AutogenerateRoutines>::run( translationUnit );
    860         // ast::Pass<PseudoFuncGenerateRoutine>::run( translationUnit );
    861809}
    862810
  • src/Validate/ReplacePseudoFunc.cpp

    rbad9c8f r221c542e  
     1#include "ReplacePseudoFunc.hpp"
     2
     3#include <set>
     4
    15#include "AST/Decl.hpp"
     6#include "AST/Inspect.hpp"
    27#include "AST/Pass.hpp"
    38#include "AST/Stmt.hpp"
    4 #include "AST/Inspect.hpp"
    59#include "Common/utility.h"
    6 #include "ReplacePseudoFunc.hpp"
    7 
     10#include "ResolvExpr/Resolver.h"
     11#include "SymTab/Mangler.h"  // for Mangler
    812namespace Validate {
    913
    1014namespace {
    1115
    12 struct ReplacePseudoFuncCore {
    13     ast::Expr const * postvisit( ast::ApplicationExpr const * decl );
     16std::set<std::string> queryLabels;
     17std::set<std::string> queryValues;
     18
     19struct FindGenEnumArray final : public ast::WithShortCircuiting {
     20    void previsit(const ast::ApplicationExpr* enumDecl);
    1421};
     22
     23void FindGenEnumArray::previsit(const ast::ApplicationExpr* expr) {
     24    auto fname = ast::getFunctionName(expr);
     25    if (fname == "labelE" || fname == "valueE") {
     26        if (expr->args.size() != 1) {
     27            SemanticError(expr, "Position Expression only take one parameter");
     28        }
     29        const ast::VariableExpr* arg =
     30            expr->args.front().as<const ast::VariableExpr>();
     31        if (!arg) {
     32            SemanticError(expr, "Unimplement Pseudo Function Cases");
     33        }
     34        const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
     35        const std::string referredName = argAsVar->name;
     36        const ast::EnumInstType* argType =
     37            argAsVar->type.as<const ast::EnumInstType>();
     38        if (!argType) {
     39            SemanticError(
     40                argAsVar,
     41                "Position can only be used on an enumeration instance");
     42        }
     43        ast::ptr<ast::EnumDecl> base = argType->base;
     44        assert(base);
     45        if (fname == "labelE") queryLabels.insert(base->name);
     46        if (fname == "valueE") queryValues.insert(base->name);
     47    }
    1548}
    1649
    17 ast::Expr const * ReplacePseudoFuncCore::postvisit( ast::ApplicationExpr const * expr) {
    18     auto fname = ast::getFunctionName( expr );
    19     if ( fname == "posE" ) {
    20         // std::cerr << "Found App in ReplacePseudoFunc" << std::endl;
    21         if ( expr->args.size() != 1 ) {
    22             SemanticError( expr, "Position Expression only take one parameter" );
     50struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,
     51                                         public ast::WithSymbolTable,
     52                                         public ast::WithShortCircuiting {
     53    void previsit(const ast::EnumDecl* enumDecl);
     54};
     55
     56void PseudoFuncGenerateRoutine::previsit(const ast::EnumDecl* enumDecl) {
     57    visit_children = false;
     58    const CodeLocation& location = enumDecl->location;
     59    if (enumDecl->members.size() == 0 || !enumDecl->base) return;
     60
     61    std::vector<ast::ptr<ast::Init>> inits;
     62    std::vector<ast::ptr<ast::Init>> labels;
     63    for (const ast::Decl* mem : enumDecl->members) {
     64        auto memAsObjectDecl = dynamic_cast<const ast::ObjectDecl*>(mem);
     65        inits.emplace_back(memAsObjectDecl->init);
     66        labels.emplace_back(new ast::SingleInit(
     67            location, ast::ConstantExpr::from_string(location, mem->name)));
     68    }
     69    if (queryValues.count(enumDecl->name)) {
     70        auto init = new ast::ListInit(location, std::move(inits));
     71        auto values = new ast::ObjectDecl(
     72            location, "values_" + enumDecl->name,
     73            new ast::ArrayType(
     74                enumDecl->base,
     75                ast::ConstantExpr::from_int(location, enumDecl->members.size()),
     76                ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),
     77            init, ast::Storage::Static, ast::Linkage::AutoGen);
     78        symtab.addId(values);
     79        values->mangleName = Mangle::mangle(values);
     80        declsToAddAfter.push_back(values);
     81    }
     82    if (queryLabels.count(enumDecl->name)) {
     83        auto label_strings = new ast::ListInit(location, std::move(labels));
     84        auto label_arr = new ast::ObjectDecl(
     85            location, "labels_" + enumDecl->name,
     86            new ast::ArrayType(
     87                new ast::PointerType(new ast::BasicType{ast::BasicType::Char}),
     88                ast::ConstantExpr::from_int(location, enumDecl->members.size()),
     89                ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),
     90            label_strings, ast::Storage::Static, ast::Linkage::AutoGen);
     91        symtab.addId(label_arr);
     92        label_arr->mangleName = Mangle::mangle(label_arr);
     93        declsToAddAfter.push_back(label_arr);
     94    }
     95}
     96
     97struct ReplacePseudoFuncCore : public ast::WithShortCircuiting,
     98                               public ast::WithSymbolTable,
     99                               public ast::WithConstTranslationUnit {
     100    ast::Expr const* postvisit(ast::ApplicationExpr const* decl);
     101};
     102
     103ast::Expr const* ReplacePseudoFuncCore::postvisit(
     104    ast::ApplicationExpr const* expr) {
     105    auto fname = ast::getFunctionName(expr);
     106    auto location = expr->location;
     107    if (fname == "posE" || fname == "valueE" || fname == "labelE") {
     108        if (expr->args.size() != 1) {
     109            SemanticError(expr,
     110                          "Pseudo Enum Expression only take one parameter");
    23111        }
    24         const ast::VariableExpr * arg = expr->args.front().as<const ast::VariableExpr>();
    25         if ( !arg ) {
    26             SemanticError( expr, "Unimplement Pseudo Function Cases" );
     112        ast::ptr<ast::VariableExpr> arg =
     113            expr->args.front().as<const ast::VariableExpr>();
     114        if (!arg) {
     115            SemanticError(expr, "Unimplement Pseudo Function Cases");
    27116        }
    28         const ast::ObjectDecl * argAsVar = arg->var.as<const ast::ObjectDecl>();
     117        const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
    29118        const std::string referredName = argAsVar->name;
    30         const ast::EnumInstType * argType = argAsVar->type.as<const ast::EnumInstType>();
    31         if ( !argType ) {
    32             SemanticError( argAsVar, "Position can only be used on an enumeration instance" );
     119        const ast::EnumInstType* argType =
     120            argAsVar->type.as<const ast::EnumInstType>();
     121        if (!argType) {
     122            SemanticError(argAsVar,
     123                          "Pseudo Enum Expression can only be used on an "
     124                          "enumeration instance");
    33125        }
    34         const ast::EnumDecl * base = argType->base;
    35         for ( size_t i = 0; i < base->members.size(); i++ ) {
    36             if ( base->members[i]->name == referredName ) {
    37                 return ast::ConstantExpr::from_int( expr->location, i );
     126        const ast::EnumDecl* base = argType->base;
     127        for (size_t i = 0; i < base->members.size(); i++) {
     128            if (base->members[i]->name == referredName) {
     129                if (fname == "posE")
     130                    return ast::ConstantExpr::from_int(expr->location, i);
     131                else if (fname == "labelE")
     132                    return ast::ConstantExpr::from_string(expr->location,
     133                                                          referredName);
     134                else
     135                    return new ast::TypeExpr(expr->location, argType);
     136            }
     137        }
     138
     139        ResolvExpr::ResolveContext context{symtab, transUnit().global};
     140
     141        if (fname == "labelE") {
     142            ast::Expr* toResolve =
     143                new ast::NameExpr(expr->location, "labels_" + base->name);
     144            auto result = ResolvExpr::findVoidExpression(toResolve, context);
     145            if (result.get()) {
     146                auto arrAsVar = result.strict_as<ast::VariableExpr>();
     147                auto untyped = new ast::UntypedExpr(
     148                    location, new ast::NameExpr(location, "?[?]"),
     149                    {new ast::VariableExpr(*arrAsVar),
     150                     ast::ConstantExpr::from_int(
     151                         location,
     152                         0)});  /// TODO: dummy value.
     153                                /// To make it works need to change the unifier
     154
     155                auto typedResult =
     156                    ResolvExpr::findVoidExpression(untyped, context);
     157                if (result.get()) {
     158                    ast::ptr<ast::ApplicationExpr> ret =
     159                        typedResult.strict_as<ast::ApplicationExpr>();
     160                    return new ast::ApplicationExpr(*ret);
     161                }
     162            }
     163        }
     164       
     165        if (fname == "valueE") {
     166            ast::Expr* toResolve =
     167                new ast::NameExpr(expr->location, "values_" + base->name);
     168            auto result = ResolvExpr::findVoidExpression(toResolve, context);
     169            if (result.get()) {
     170                auto arrAsVar = result.strict_as<ast::VariableExpr>();
     171                auto untyped = new ast::UntypedExpr(
     172                    location, new ast::NameExpr(location, "?[?]"),
     173                    {new ast::VariableExpr(*arrAsVar),
     174                     ast::ConstantExpr::from_int(
     175                         location,
     176                         0)});  /// TODO: dummy value.
     177                                /// To make it works need to change the unifier
     178
     179                auto typedResult =
     180                    ResolvExpr::findVoidExpression(untyped, context);
     181                if (result.get()) {
     182                    ast::ptr<ast::ApplicationExpr> ret =
     183                        typedResult.strict_as<ast::ApplicationExpr>();
     184                    return new ast::ApplicationExpr(*ret);
     185                }
    38186            }
    39187        }
     
    42190}
    43191
     192}  // namespace
    44193
    45 
    46 void replacePseudoFunc( ast::TranslationUnit & translationUnit ) {
    47     ast::Pass<ReplacePseudoFuncCore>::run( translationUnit );
     194void replacePseudoFunc(ast::TranslationUnit& translationUnit) {
     195    ast::Pass<FindGenEnumArray>::run(translationUnit);
     196    ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
     197    ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
    48198}
    49 
    50 }
     199}  // namespace Validate
  • src/main.cc

    rbad9c8f r221c542e  
    8282#include "Validate/ReturnCheck.hpp"         // for checkReturnStatements
    8383#include "Validate/VerifyCtorDtorAssign.hpp" // for verifyCtorDtorAssign
    84 #include "Validate/ReplacePseudoFunc.hpp"
     84#include "Validate/ReplacePseudoFunc.hpp"   // for replacePseudoFunc
    8585#include "Virtual/ExpandCasts.h"            // for expandCasts
    8686#include "Virtual/VirtualDtor.hpp"          // for implementVirtDtors
Note: See TracChangeset for help on using the changeset viewer.