Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Resolver.cc

    r36982fc r882ad37  
    7474                void previsit( CatchStmt *catchStmt );
    7575                void previsit( WaitForStmt * stmt );
     76                void previsit( WithStmt * withStmt );
    7677
    7778                void previsit( SingleInit *singleInit );
     
    369370                if ( throwStmt->get_expr() ) {
    370371                        StructDecl * exception_decl =
    371                                 indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" );
     372                                indexer.lookupStruct( "__cfaehm__base_exception_t" );
    372373                        assert( exception_decl );
    373374                        Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, exception_decl ) );
     
    568569                        findSingleExpression( stmt->orelse.condition, this->indexer );
    569570                        stmt->orelse.statement->accept( *visitor );
     571                }
     572        }
     573
     574        bool isStructOrUnion( Type * t ) {
     575                t = t->stripReferences();
     576                return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
     577        }
     578
     579        void Resolver::previsit( WithStmt * withStmt ) {
     580                for ( Expression *& expr : withStmt->exprs )  {
     581                        TypeEnvironment env;
     582                        AlternativeFinder finder( indexer, env );
     583                        finder.findWithAdjustment( expr );
     584
     585                        // only struct- and union-typed expressions are viable candidates
     586                        AltList candidates;
     587                        for ( Alternative & alt : finder.get_alternatives() ) {
     588                                if ( isStructOrUnion( alt.expr->result ) ) {
     589                                        candidates.push_back( std::move( alt ) );
     590                                }
     591                        }
     592
     593                        // choose the lowest cost expression among the candidates
     594                        AltList winners;
     595                        findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
     596                        if ( winners.size() == 0 ) {
     597                                throw SemanticError( "No reasonable alternatives for with statement expression: ", expr );
     598                        } else if ( winners.size() != 1 ) {
     599                                std::ostringstream stream;
     600                                stream << "Cannot choose between " << winners.size() << " alternatives for with statement expression\n";
     601                                expr->print( stream );
     602                                stream << "Alternatives are:\n";
     603                                printAlts( winners, stream, 1 );
     604                                throw SemanticError( stream.str() );
     605                        }
     606
     607                        // there is one unambiguous interpretation - move the expression into the with statement
     608                        Alternative & alt = winners.front();
     609                        finishExpr( alt.expr, alt.env, expr->env );
     610                        delete expr;
     611                        expr = alt.expr;
     612                        alt.expr = nullptr;
    570613                }
    571614        }
Note: See TracChangeset for help on using the changeset viewer.