Ignore:
Timestamp:
Jan 14, 2019, 3:38:28 PM (3 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, no_list, persistent-indexer
Children:
fd73248
Parents:
07ec1a2 (diff), 52ffa30 (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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r07ec1a2 r276a55b2  
    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
    3333#include "SymTab/Autogen.h"              // for SizeType
    3434#include "SymTab/Indexer.h"              // for Indexer
     
    168168
    169169        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) {
     170                void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
    171171                        assertf( untyped, "expected a non-null expression." );
     172
     173                        // xxx - this isn't thread-safe, but should work until we parallelize the resolver
     174                        static unsigned recursion_level = 0;
     175
     176                        ++recursion_level;
    172177                        TypeEnvironment env;
    173178                        AlternativeFinder finder( indexer, env );
    174                         finder.find( untyped, adjust, prune, failFast );
     179                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
     180                        --recursion_level;
    175181
    176182                        #if 0
     
    185191                        #endif
    186192
     193                        // produce filtered list of alternatives
    187194                        AltList candidates;
    188195                        for ( Alternative & alt : finder.get_alternatives() ) {
     
    192199                        }
    193200
    194                         // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
    195                         // choose the lowest cost expression among the candidates
     201                        // produce invalid error if no candidates
     202                        if ( candidates.empty() ) {
     203                                SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
     204                        }
     205
     206                        // search for cheapest candidate
    196207                        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 ) {
     208                        bool seen_undeleted = false;
     209                        for ( unsigned i = 0; i < candidates.size(); ++i ) {
     210                                int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
     211
     212                                if ( c > 0 ) continue; // skip more expensive than winner
     213
     214                                if ( c < 0 ) {
     215                                        // reset on new cheapest
     216                                        seen_undeleted = ! findDeletedExpr( candidates[i].expr );
     217                                        winners.clear();
     218                                } else /* if ( c == 0 ) */ {
     219                                        if ( findDeletedExpr( candidates[i].expr ) ) {
     220                                                // skip deleted expression if already seen one equivalent-cost not
     221                                                if ( seen_undeleted ) continue;
     222                                        } else if ( ! seen_undeleted ) {
     223                                                // replace list of equivalent-cost deleted expressions with one non-deleted
     224                                                winners.clear();
     225                                                seen_undeleted = true;
     226                                        }
     227                                }
     228
     229                                winners.emplace_back( std::move( candidates[i] ) );
     230                        }
     231
     232                        // promote alternative.cvtCost to .cost
     233                        // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
     234                        for ( Alternative& winner : winners ) {
     235                                winner.cost = winner.cvtCost;
     236                        }
     237                       
     238                        // produce ambiguous errors, if applicable
     239                        if ( winners.size() != 1 ) {
    201240                                std::ostringstream stream;
    202241                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     
    207246                        }
    208247
    209                         // there is one unambiguous interpretation - move the expression into the with statement
    210                         Alternative & choice = winners.front();
    211                         if ( findDeletedExpr( choice.expr ) ) {
     248                        // single selected choice
     249                        Alternative& choice = winners.front();
     250
     251                        // fail on only expression deleted
     252                        if ( ! seen_undeleted ) {
    212253                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    213254                        }
     255
     256                        // xxx - check for ambiguous expressions
     257                       
     258                        // output selected choice
    214259                        alt = std::move( choice );
    215260                }
    216261
    217262                /// 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) {
     263                void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
    219264                        if ( ! untyped ) return;
    220265                        Alternative choice;
    221                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
     266                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
    222267                        finishExpr( choice.expr, choice.env, untyped->env );
    223268                        delete untyped;
     
    250295                untyped.arg = expr;
    251296                Alternative choice;
    252                 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
     297                findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
    253298                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
    254299                env = std::move( choice.env );
     
    357402
    358403        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.
     404                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
     405                // class-variable initContext is changed multiple time because the LHS is analysed twice.
     406                // The second analysis changes initContext because of a function type can contain object
     407                // declarations in the return and parameter types. So each value of initContext is
     408                // retained, so the type on the first analysis is preserved and used for selecting the RHS.
    364409                GuardValue( currentObject );
    365410                currentObject = CurrentObject( objectDecl->get_type() );
     
    397442
    398443        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.
     444                // default value expressions have an environment which shouldn't be there and trips up
     445                // later passes.
     446                // xxx - it might be necessary to somehow keep the information from this environment, but I
     447                // can't currently see how it's useful.
    402448                for ( Declaration * d : functionDecl->type->parameters ) {
    403449                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
     
    749795                initExpr->expr = nullptr;
    750796                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.
     797                // InitExpr may have inferParams in the case where the expression specializes a function
     798                // pointer, and newExpr may already have inferParams of its own, so a simple swap is not
     799                // sufficient.
    753800                newExpr->spliceInferParams( initExpr );
    754801                delete initExpr;
    755802
    756                 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
     803                // get the actual object's type (may not exactly match what comes back from the resolver
     804                // due to conversions)
    757805                Type * initContext = currentObject.getCurrentType();
    758806
     
    766814                                        if ( isCharType( pt->get_base() ) ) {
    767815                                                if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) {
    768                                                         // strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
     816                                                        // strip cast if we're initializing a char[] with a char *,
     817                                                        // e.g.  char x[] = "hello";
    769818                                                        newExpr = ce->get_arg();
    770819                                                        ce->set_arg( nullptr );
     
    788837                // move cursor into brace-enclosed initializer-list
    789838                currentObject.enterListInit();
    790                 // xxx - fix this so that the list isn't copied, iterator should be used to change current element
     839                // xxx - fix this so that the list isn't copied, iterator should be used to change current
     840                // element
    791841                std::list<Designation *> newDesignations;
    792842                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.
     843                        // iterate designations and initializers in pairs, moving the cursor to the current
     844                        // designated object and resolving the initializer against that object.
    795845                        Designation * des = std::get<0>(p);
    796846                        Initializer * init = std::get<1>(p);
     
    822872                // fall back on C-style initializer
    823873                delete ctorInit->get_ctor();
    824                 ctorInit->set_ctor( NULL );
     874                ctorInit->set_ctor( nullptr );
    825875                delete ctorInit->get_dtor();
    826                 ctorInit->set_dtor( NULL );
     876                ctorInit->set_dtor( nullptr );
    827877                maybeAccept( ctorInit->get_init(), *visitor );
    828878        }
     
    867917
    868918                // xxx - todo -- what about arrays?
    869                 // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
     919                // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
    870920                //      // can reduce the constructor down to a SingleInit using the
    871921                //      // second argument from the ctor call, since
    872922                //      delete ctorInit->get_ctor();
    873                 //      ctorInit->set_ctor( NULL );
     923                //      ctorInit->set_ctor( nullptr );
    874924
    875925                //      Expression * arg =
Note: See TracChangeset for help on using the changeset viewer.