Ignore:
Timestamp:
Jan 23, 2019, 4:52:16 PM (5 years ago)
Author:
Thierry Delisle <tdelisle@…>
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:
a200795
Parents:
9b086ca (diff), 1d832f4 (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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r9b086ca rcde3891  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Feb 17 11:19:40 2018
    13 // Update Count     : 213
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Oct 05 09:43:00 2018
     13// Update Count     : 214
    1414//
    1515
    16 #include <stddef.h>                      // for NULL
    1716#include <cassert>                       // for strict_dynamic_cast, assert
    1817#include <memory>                        // for allocator, allocator_traits<...
    1918#include <tuple>                         // for get
    20 #include <vector>
     19#include <vector>                        // for vector
    2120
    2221#include "Alternative.h"                 // for Alternative, AltList
     
    3130#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    3231#include "Resolver.h"
     32#include "ResolvMode.h"                  // for ResolvMode
     33#include "SymTab/Autogen.h"              // for SizeType
    3334#include "SymTab/Indexer.h"              // for Indexer
    3435#include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
     
    168169
    169170        namespace {
    170                 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
     171                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
    171172                        assertf( untyped, "expected a non-null expression." );
     173
     174                        // xxx - this isn't thread-safe, but should work until we parallelize the resolver
     175                        static unsigned recursion_level = 0;
     176
     177                        ++recursion_level;
    172178                        TypeEnvironment env;
    173179                        AlternativeFinder finder( indexer, env );
    174                         finder.find( untyped, adjust, prune, failFast );
     180                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
     181                        --recursion_level;
    175182
    176183                        #if 0
     
    185192                        #endif
    186193
     194                        // produce filtered list of alternatives
    187195                        AltList candidates;
    188196                        for ( Alternative & alt : finder.get_alternatives() ) {
     
    192200                        }
    193201
    194                         // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
    195                         // choose the lowest cost expression among the candidates
     202                        // produce invalid error if no candidates
     203                        if ( candidates.empty() ) {
     204                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
     205                        }
     206
     207                        // search for cheapest candidate
    196208                        AltList winners;
    197                         findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    198                         if ( winners.size() == 0 ) {
    199                                 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
    200                         } else if ( winners.size() != 1 ) {
     209                        bool seen_undeleted = false;
     210                        for ( unsigned i = 0; i < candidates.size(); ++i ) {
     211                                int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
     212
     213                                if ( c > 0 ) continue; // skip more expensive than winner
     214
     215                                if ( c < 0 ) {
     216                                        // reset on new cheapest
     217                                        seen_undeleted = ! findDeletedExpr( candidates[i].expr );
     218                                        winners.clear();
     219                                } else /* if ( c == 0 ) */ {
     220                                        if ( findDeletedExpr( candidates[i].expr ) ) {
     221                                                // skip deleted expression if already seen one equivalent-cost not
     222                                                if ( seen_undeleted ) continue;
     223                                        } else if ( ! seen_undeleted ) {
     224                                                // replace list of equivalent-cost deleted expressions with one non-deleted
     225                                                winners.clear();
     226                                                seen_undeleted = true;
     227                                        }
     228                                }
     229
     230                                winners.emplace_back( std::move( candidates[i] ) );
     231                        }
     232
     233                        // promote alternative.cvtCost to .cost
     234                        // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
     235                        for ( Alternative& winner : winners ) {
     236                                winner.cost = winner.cvtCost;
     237                        }
     238
     239                        // produce ambiguous errors, if applicable
     240                        if ( winners.size() != 1 ) {
    201241                                std::ostringstream stream;
    202242                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     
    207247                        }
    208248
    209                         // there is one unambiguous interpretation - move the expression into the with statement
    210                         Alternative & choice = winners.front();
    211                         if ( findDeletedExpr( choice.expr ) ) {
     249                        // single selected choice
     250                        Alternative& choice = winners.front();
     251
     252                        // fail on only expression deleted
     253                        if ( ! seen_undeleted ) {
    212254                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    213255                        }
     256
     257                        // xxx - check for ambiguous expressions
     258
     259                        // output selected choice
    214260                        alt = std::move( choice );
    215261                }
    216262
    217263                /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
    218                 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
     264                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
    219265                        if ( ! untyped ) return;
    220266                        Alternative choice;
    221                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
     267                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
    222268                        finishExpr( choice.expr, choice.env, untyped->env );
    223269                        delete untyped;
     
    250296                untyped.arg = expr;
    251297                Alternative choice;
    252                 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
     298                findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
    253299                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
    254300                env = std::move( choice.env );
     
    357403
    358404        void Resolver::previsit( ObjectDecl *objectDecl ) {
    359                 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable
    360                 // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes
    361                 // initContext because of a function type can contain object declarations in the return and parameter types. So
    362                 // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting
    363                 // the RHS.
     405                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
     406                // class-variable initContext is changed multiple time because the LHS is analysed twice.
     407                // The second analysis changes initContext because of a function type can contain object
     408                // declarations in the return and parameter types. So each value of initContext is
     409                // retained, so the type on the first analysis is preserved and used for selecting the RHS.
    364410                GuardValue( currentObject );
    365411                currentObject = CurrentObject( objectDecl->get_type() );
     
    397443
    398444        void Resolver::postvisit( FunctionDecl *functionDecl ) {
    399                 // default value expressions have an environment which shouldn't be there and trips up later passes.
    400                 // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently
    401                 // see how it's useful.
     445                // default value expressions have an environment which shouldn't be there and trips up
     446                // later passes.
     447                // xxx - it might be necessary to somehow keep the information from this environment, but I
     448                // can't currently see how it's useful.
    402449                for ( Declaration * d : functionDecl->type->parameters ) {
    403450                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
     
    749796                initExpr->expr = nullptr;
    750797                std::swap( initExpr->env, newExpr->env );
    751                 // InitExpr may have inferParams in the case where the expression specializes a function pointer,
    752                 // and newExpr may already have inferParams of its own, so a simple swap is not sufficient.
     798                // InitExpr may have inferParams in the case where the expression specializes a function
     799                // pointer, and newExpr may already have inferParams of its own, so a simple swap is not
     800                // sufficient.
    753801                newExpr->spliceInferParams( initExpr );
    754802                delete initExpr;
    755803
    756                 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
     804                // get the actual object's type (may not exactly match what comes back from the resolver
     805                // due to conversions)
    757806                Type * initContext = currentObject.getCurrentType();
    758807
     
    766815                                        if ( isCharType( pt->get_base() ) ) {
    767816                                                if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) {
    768                                                         // strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
     817                                                        // strip cast if we're initializing a char[] with a char *,
     818                                                        // e.g.  char x[] = "hello";
    769819                                                        newExpr = ce->get_arg();
    770820                                                        ce->set_arg( nullptr );
     
    788838                // move cursor into brace-enclosed initializer-list
    789839                currentObject.enterListInit();
    790                 // xxx - fix this so that the list isn't copied, iterator should be used to change current element
     840                // xxx - fix this so that the list isn't copied, iterator should be used to change current
     841                // element
    791842                std::list<Designation *> newDesignations;
    792843                for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
    793                         // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving
    794                         // the initializer against that object.
     844                        // iterate designations and initializers in pairs, moving the cursor to the current
     845                        // designated object and resolving the initializer against that object.
    795846                        Designation * des = std::get<0>(p);
    796847                        Initializer * init = std::get<1>(p);
     
    822873                // fall back on C-style initializer
    823874                delete ctorInit->get_ctor();
    824                 ctorInit->set_ctor( NULL );
     875                ctorInit->set_ctor( nullptr );
    825876                delete ctorInit->get_dtor();
    826                 ctorInit->set_dtor( NULL );
     877                ctorInit->set_dtor( nullptr );
    827878                maybeAccept( ctorInit->get_init(), *visitor );
    828879        }
     
    867918
    868919                // xxx - todo -- what about arrays?
    869                 // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
     920                // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
    870921                //      // can reduce the constructor down to a SingleInit using the
    871922                //      // second argument from the ctor call, since
    872923                //      delete ctorInit->get_ctor();
    873                 //      ctorInit->set_ctor( NULL );
     924                //      ctorInit->set_ctor( nullptr );
    874925
    875926                //      Expression * arg =
Note: See TracChangeset for help on using the changeset viewer.