Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r615a096 r64ac636  
    1010// Created On       : Wed Jan 13 16:29:30 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 17 09:13:47 2017
    13 // Update Count     : 71
     12// Last Modified On : Thu Mar 16 08:08:04 2017
     13// Update Count     : 67
    1414//
    1515
     
    232232                        void handleFirstParam( Expression * firstParam );
    233233                        template< typename... Params >
    234                         void emit( const Params &... params );
     234                        void emit( CodeLocation, const Params &... params );
    235235
    236236                        FunctionDecl * function = 0;
    237                         std::set< DeclarationWithType * > unhandled, usedUninit;
     237                        std::set< DeclarationWithType * > unhandled;
     238                        std::map< DeclarationWithType *, CodeLocation > usedUninit;
    238239                        ObjectDecl * thisParam = 0;
    239240                        bool isCtor = false; // true if current function is a constructor
     
    336337                        GenStructMemberCalls warner;
    337338                        acceptAll( translationUnit, warner );
    338 
    339                         // visitor doesn't throw so that it can collect all errors
    340                         if ( ! warner.errors.isEmpty() ) {
    341                                 throw warner.errors;
    342                         }
    343339                }
    344340
     
    438434                        env->apply( result );
    439435                        ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
    440                         tmp->get_type()->set_const( false );
     436                        tmp->get_type()->set_isConst( false );
    441437
    442438                        // create and resolve copy constructor
     
    484480                                env->apply( result );
    485481                                ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
    486                                 ret->get_type()->set_const( false );
     482                                ret->get_type()->set_isConst( false );
    487483                                impCpCtorExpr->get_returnDecls().push_back( ret );
    488484                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    489                                 if ( ! result->get_lvalue() ) {
     485                                if ( ! result->get_isLvalue() ) {
    490486                                        // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    491487                                        destructRet( ret, impCpCtorExpr );
     
    507503                                env->apply( result );
    508504                                ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
    509                                 ret->get_type()->set_const( false );
     505                                ret->get_type()->set_isConst( false );
    510506                                stmtExpr->get_returnDecls().push_front( ret );
    511507
     
    588584
    589585                                Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    590                                 if ( callExpr->get_result()->get_lvalue() ) {
     586                                if ( callExpr->get_result()->get_isLvalue() ) {
    591587                                        // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning
    592588                                        // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the
     
    940936                        ValueGuard< FunctionDecl * > oldFunction( funcDecl );
    941937                        ValueGuard< std::set< DeclarationWithType * > > oldUnhandled( unhandled );
    942                         ValueGuard< std::set< DeclarationWithType * > > oldUsedUninit( usedUninit );
     938                        ValueGuard< std::map< DeclarationWithType *, CodeLocation > > oldUsedUninit( usedUninit );
    943939                        ValueGuard< ObjectDecl * > oldThisParam( thisParam );
    944940                        ValueGuard< bool > oldIsCtor( isCtor );
    945941                        ValueGuard< StructDecl * > oldStructDecl( structDecl );
     942                        errors = SemanticError();  // clear previous errors
    946943
    947944                        // need to start with fresh sets
     
    972969                        // remove the unhandled objects from usedUninit, because a call is inserted
    973970                        // to handle them - only objects that are later constructed are used uninitialized.
    974                         std::set< DeclarationWithType * > diff;
    975                         std::set_difference( usedUninit.begin(), usedUninit.end(), unhandled.begin(), unhandled.end(), std::inserter( diff, diff.begin() ) );
    976                         for ( DeclarationWithType * member : diff ) {
    977                                 emit( "in ", CodeGen::genPrettyType( function->get_functionType(), function->get_name() ), ", field ", member->get_name(), " used before being constructed" );
     971                        std::map< DeclarationWithType *, CodeLocation > diff;
     972                        // need the comparator since usedUninit and unhandled have different types
     973                        struct comp_t {
     974                                typedef decltype(usedUninit)::value_type usedUninit_t;
     975                                typedef decltype(unhandled)::value_type unhandled_t;
     976                                bool operator()(usedUninit_t x, unhandled_t y) { return x.first < y; }
     977                                bool operator()(unhandled_t x, usedUninit_t y) { return x < y.first; }
     978                        } comp;
     979                        std::set_difference( usedUninit.begin(), usedUninit.end(), unhandled.begin(), unhandled.end(), std::inserter( diff, diff.begin() ), comp );
     980                        for ( auto p : diff ) {
     981                                DeclarationWithType * member = p.first;
     982                                CodeLocation loc = p.second;
     983                                // xxx - make error message better by also tracking the location that the object is constructed at?
     984                                emit( loc, "in ", CodeGen::genPrettyType( function->get_functionType(), function->get_name() ), ", field ", member->get_name(), " used before being constructed" );
    978985                        }
    979986
     
    10201027                                                        }
    10211028                                                } catch ( SemanticError & error ) {
    1022                                                         emit( "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" );
     1029                                                        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" );
    10231030                                                }
    10241031                                        }
    10251032                                }
    10261033                                leaveScope();
     1034                        }
     1035                        if (! errors.isEmpty()) {
     1036                                throw errors;
    10271037                        }
    10281038                }
     
    10791089                                                        if ( unhandled.count( memberExpr->get_member() ) ) {
    10801090                                                                // emit a warning because a member was used before it was constructed
    1081                                                                 usedUninit.insert( memberExpr->get_member() );
     1091                                                                usedUninit.insert( { memberExpr->get_member(), memberExpr->location } );
    10821092                                                        }
    10831093                                                }
     
    10891099
    10901100                template< typename Visitor, typename... Params >
    1091                 void error( Visitor & v, const Params &... params ) {
    1092                         v.errors.append( toString( params... ) );
     1101                void error( Visitor & v, CodeLocation loc, const Params &... params ) {
     1102                        SemanticError err( toString( params... ) );
     1103                        err.set_location( loc );
     1104                        v.errors.append( err );
    10931105                }
    10941106
    10951107                template< typename... Params >
    1096                 void GenStructMemberCalls::emit( const Params &... params ) {
     1108                void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) {
    10971109                        // toggle warnings vs. errors here.
    10981110                        // warn( params... );
    1099                         error( *this, params... );
     1111                        error( *this, loc, params... );
    11001112                }
    11011113
Note: See TracChangeset for help on using the changeset viewer.