Changeset 90152a4 for src/ResolvExpr


Ignore:
Timestamp:
Aug 27, 2018, 4:40:34 PM (8 years ago)
Author:
Rob Schluntz <rschlunt@…>
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, stuck-waitfor-destruct
Children:
b7c89aa
Parents:
f9feab8 (diff), 305581d (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

Location:
src/ResolvExpr
Files:
1 added
1 deleted
25 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/AdjustExprType.cc

    rf9feab8 r90152a4  
    2424        class AdjustExprType : public WithShortCircuiting {
    2525          public:
    26                 AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer );
     26                AdjustExprType( const TypeEnvironment & env, const SymTab::Indexer & indexer );
    2727                void premutate( VoidType * ) { visit_children = false; }
    2828                void premutate( BasicType * ) { visit_children = false; }
     
    4545
    4646          private:
    47                 const TypeEnvironment &env;
    48                 const SymTab::Indexer &indexer;
     47                const TypeEnvironment & env;
     48                const SymTab::Indexer & indexer;
    4949        };
    5050
     
    5555        }
    5656
     57        void adjustExprType( Type *& type ) {
     58                TypeEnvironment env;
     59                SymTab::Indexer indexer;
     60                adjustExprType( type, env, indexer );
     61        }
     62
    5763        AdjustExprType::AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer )
    5864                : env( env ), indexer( indexer ) {
     
    6066
    6167        Type * AdjustExprType::postmutate( ArrayType * arrayType ) {
    62                 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base );
     68                PointerType *pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };
    6369                arrayType->base = nullptr;
    6470                delete arrayType;
     
    6773
    6874        Type * AdjustExprType::postmutate( FunctionType * functionType ) {
    69                 return new PointerType( Type::Qualifiers(), functionType );
     75                return new PointerType{ Type::Qualifiers(), functionType };
    7076        }
    7177
    7278        Type * AdjustExprType::postmutate( TypeInstType * typeInst ) {
    73                 EqvClass eqvClass;
    74                 if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
    75                         if ( eqvClass.data.kind == TypeDecl::Ftype ) {
    76                                 PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst );
    77                                 return pointerType;
     79                if ( const EqvClass* eqvClass = env.lookup( typeInst->get_name() ) ) {
     80                        if ( eqvClass->data.kind == TypeDecl::Ftype ) {
     81                                return new PointerType{ Type::Qualifiers(), typeInst };
    7882                        }
    7983                } else if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
    8084                        if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {
    8185                                if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
    82                                         PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst );
    83                                         return pointerType;
     86                                        return new PointerType{ Type::Qualifiers(), typeInst };
    8487                                } // if
    8588                        } // if
  • src/ResolvExpr/Alternative.cc

    rf9feab8 r90152a4  
    2727
    2828namespace ResolvExpr {
    29         Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( 0 ) {}
     29        Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ) {}
    3030
    3131        Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost )
     
    4848        }
    4949
    50         Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( other.env ) {
     50        Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( std::move( other.env ) ) {
    5151                other.expr = nullptr;
    5252        }
     
    5858                cvtCost = other.cvtCost;
    5959                expr = other.expr;
    60                 env = other.env;
     60                env = std::move( other.env );
    6161                other.expr = nullptr;
    6262                return *this;
  • src/ResolvExpr/Alternative.h

    rf9feab8 r90152a4  
    5757        /// Moves all elements from src to the beginning of dst
    5858        void spliceBegin( AltList& dst, AltList& src );
     59
     60        static inline std::ostream & operator<<(std::ostream & os, const ResolvExpr::Alternative & alt) {
     61                alt.print( os );
     62                return os;
     63        }
    5964} // namespace ResolvExpr
    6065
  • src/ResolvExpr/AlternativeFinder.cc

    rf9feab8 r90152a4  
    1010// Created On       : Sat May 16 23:52:08 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Aug 28 13:47:24 2017
    13 // Update Count     : 32
     12// Last Modified On : Sat Feb 17 11:19:39 2018
     13// Update Count     : 33
    1414//
    1515
     
    2525#include <vector>                  // for vector
    2626
     27#include "CompilationState.h"      // for resolvep
    2728#include "Alternative.h"           // for AltList, Alternative
    2829#include "AlternativeFinder.h"
     
    4950#include "typeops.h"               // for adjustExprType, polyCost, castCost
    5051
    51 extern bool resolvep;
    5252#define PRINT( text ) if ( resolvep ) { text }
    5353//#define DEBUG_COST
     
    6060
    6161namespace ResolvExpr {
    62         Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
    63                 CastExpr *castToVoid = new CastExpr( expr );
    64 
    65                 AlternativeFinder finder( indexer, env );
    66                 finder.findWithAdjustment( castToVoid );
    67 
    68                 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
    69                 // interpretations, an exception has already been thrown.
    70                 assert( finder.get_alternatives().size() == 1 );
    71                 CastExpr *newExpr = dynamic_cast< CastExpr* >( finder.get_alternatives().front().expr );
    72                 assert( newExpr );
    73                 env = finder.get_alternatives().front().env;
    74                 return newExpr->get_arg()->clone();
    75         }
     62        struct AlternativeFinder::Finder : public WithShortCircuiting {
     63                Finder( AlternativeFinder & altFinder ) : altFinder( altFinder ), indexer( altFinder.indexer ), alternatives( altFinder.alternatives ), env( altFinder.env ), targetType( altFinder.targetType )  {}
     64
     65                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     66
     67                void postvisit( ApplicationExpr * applicationExpr );
     68                void postvisit( UntypedExpr * untypedExpr );
     69                void postvisit( AddressExpr * addressExpr );
     70                void postvisit( LabelAddressExpr * labelExpr );
     71                void postvisit( CastExpr * castExpr );
     72                void postvisit( VirtualCastExpr * castExpr );
     73                void postvisit( UntypedMemberExpr * memberExpr );
     74                void postvisit( MemberExpr * memberExpr );
     75                void postvisit( NameExpr * variableExpr );
     76                void postvisit( VariableExpr * variableExpr );
     77                void postvisit( ConstantExpr * constantExpr );
     78                void postvisit( SizeofExpr * sizeofExpr );
     79                void postvisit( AlignofExpr * alignofExpr );
     80                void postvisit( UntypedOffsetofExpr * offsetofExpr );
     81                void postvisit( OffsetofExpr * offsetofExpr );
     82                void postvisit( OffsetPackExpr * offsetPackExpr );
     83                void postvisit( AttrExpr * attrExpr );
     84                void postvisit( LogicalExpr * logicalExpr );
     85                void postvisit( ConditionalExpr * conditionalExpr );
     86                void postvisit( CommaExpr * commaExpr );
     87                void postvisit( ImplicitCopyCtorExpr  * impCpCtorExpr );
     88                void postvisit( ConstructorExpr  * ctorExpr );
     89                void postvisit( RangeExpr  * rangeExpr );
     90                void postvisit( UntypedTupleExpr * tupleExpr );
     91                void postvisit( TupleExpr * tupleExpr );
     92                void postvisit( TupleIndexExpr * tupleExpr );
     93                void postvisit( TupleAssignExpr * tupleExpr );
     94                void postvisit( UniqueExpr * unqExpr );
     95                void postvisit( StmtExpr * stmtExpr );
     96                void postvisit( UntypedInitExpr * initExpr );
     97                void postvisit( InitExpr * initExpr );
     98                void postvisit( DeletedExpr * delExpr );
     99                void postvisit( GenericExpr * genExpr );
     100
     101                /// Adds alternatives for anonymous members
     102                void addAnonConversions( const Alternative & alt );
     103                /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
     104                template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );
     105                /// Adds alternatives for member expressions where the left side has tuple type
     106                void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
     107                /// Adds alternatives for offsetof expressions, given the base type and name of the member
     108                template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
     109                /// Takes a final result and checks if its assertions can be satisfied
     110                template<typename OutputIterator>
     111                void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out );
     112                /// Finds matching alternatives for a function, given a set of arguments
     113                template<typename OutputIterator>
     114                void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
     115                /// Checks if assertion parameters match for a new alternative
     116                template< typename OutputIterator >
     117                void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
     118        private:
     119                AlternativeFinder & altFinder;
     120                const SymTab::Indexer &indexer;
     121                AltList & alternatives;
     122                const TypeEnvironment &env;
     123                Type *& targetType;
     124        };
    76125
    77126        Cost sumCost( const AltList &in ) {
     
    127176                                                selected[ mangleName ] = current;
    128177                                        } else if ( candidate->cost == mapPlace->second.candidate->cost ) {
    129                                                 PRINT(
    130                                                         std::cerr << "marking ambiguous" << std::endl;
    131                                                 )
    132                                                 mapPlace->second.isAmbiguous = true;
     178                                                // if one of the candidates contains a deleted identifier, can pick the other, since
     179                                                // deleted expressions should not be ambiguous if there is another option that is at least as good
     180                                                if ( findDeletedExpr( candidate->expr ) ) {
     181                                                        // do nothing
     182                                                        PRINT( std::cerr << "candidate is deleted" << std::endl; )
     183                                                } else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) {
     184                                                        PRINT( std::cerr << "current is deleted" << std::endl; )
     185                                                        selected[ mangleName ] = current;
     186                                                } else {
     187                                                        PRINT(
     188                                                                std::cerr << "marking ambiguous" << std::endl;
     189                                                        )
     190                                                        mapPlace->second.isAmbiguous = true;
     191                                                }
    133192                                        } else {
    134193                                                PRINT(
     
    152211
    153212                void renameTypes( Expression *expr ) {
    154                         expr->get_result()->accept( global_renamer );
     213                        renameTyVars( expr->result );
    155214                }
    156215        } // namespace
    157216
    158         void referenceToRvalueConversion( Expression *& expr ) {
     217        void referenceToRvalueConversion( Expression *& expr, Cost & cost ) {
    159218                if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) {
    160219                        // cast away reference from expr
    161220                        expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() );
     221                        cost.incReference();
    162222                }
    163223        }
     
    185245
    186246        void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) {
    187                 expr->accept( *this );
     247                PassVisitor<Finder> finder( *this );
     248                expr->accept( finder );
    188249                if ( failFast && alternatives.empty() ) {
    189250                        PRINT(
    190251                                std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
    191252                        )
    192                         throw SemanticError( "No reasonable alternatives for expression ", expr );
     253                        SemanticError( expr, "No reasonable alternatives for expression " );
    193254                }
    194255                if ( prune ) {
     
    206267                                stream << "Cannot choose between " << winners.size() << " alternatives for expression\n";
    207268                                expr->print( stream );
    208                                 stream << "Alternatives are:\n";
     269                                stream << " Alternatives are:\n";
    209270                                printAlts( winners, stream, 1 );
    210                                 throw SemanticError( stream.str() );
     271                                SemanticError( expr->location, stream.str() );
    211272                        }
    212273                        alternatives = move(pruned);
     
    244305        }
    245306
    246         void AlternativeFinder::addAnonConversions( const Alternative & alt ) {
     307        void AlternativeFinder::Finder::addAnonConversions( const Alternative & alt ) {
    247308                // adds anonymous member interpretations whenever an aggregate value type is seen.
    248309                // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
    249310                std::unique_ptr<Expression> aggrExpr( alt.expr->clone() );
    250                 alt.env.apply( aggrExpr->get_result() );
    251                 Type * aggrType = aggrExpr->get_result();
     311                alt.env.apply( aggrExpr->result );
     312                Type * aggrType = aggrExpr->result;
    252313                if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
    253314                        aggrType = aggrType->stripReferences();
     
    255316                }
    256317
    257                 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    258                         NameExpr nameExpr( "" );
    259                         addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
    260                 } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    261                         NameExpr nameExpr( "" );
    262                         addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
     318                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
     319                        addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
     320                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
     321                        addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, "" );
    263322                } // if
    264323        }
    265324
    266325        template< typename StructOrUnionType >
    267         void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    268                 // by this point, member must be a name expr
    269                 NameExpr * nameExpr = dynamic_cast< NameExpr * >( member );
    270                 if ( ! nameExpr ) return;
    271                 const std::string & name = nameExpr->get_name();
     326        void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {
    272327                std::list< Declaration* > members;
    273328                aggInst->lookup( name, members );
    274329
    275                 for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
    276                         if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
    277                                 alternatives.push_back( Alternative( new MemberExpr( dwt, expr->clone() ), env, newCost ) );
    278                                 renameTypes( alternatives.back().expr );
    279                                 addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     330                for ( Declaration * decl : members ) {
     331                        if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
     332                                // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
     333                                // can't construct in place and use vector::back
     334                                Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
     335                                renameTypes( newAlt.expr );
     336                                addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
     337                                alternatives.push_back( std::move(newAlt) );
    280338                        } else {
    281339                                assert( false );
     
    284342        }
    285343
    286         void AlternativeFinder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
     344        void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
    287345                if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
    288346                        // get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
    289                         // xxx - this should be improved by memoizing the value of constant exprs
    290                         // during parsing and reusing that information here.
    291                         std::stringstream ss( constantExpr->get_constant()->get_value() );
    292                         int val = 0;
     347                        auto val = constantExpr->intValue();
    293348                        std::string tmp;
    294                         if ( ss >> val && ! (ss >> tmp) ) {
    295                                 if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
    296                                         alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    297                                 } // if
     349                        if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
     350                                alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    298351                        } // if
    299                 } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {
    300                         // xxx - temporary hack until 0/1 are int constants
    301                         if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {
    302                                 std::stringstream ss( nameExpr->get_name() );
    303                                 int val;
    304                                 ss >> val;
    305                                 alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
    306                         }
    307352                } // if
    308353        }
    309354
    310         void AlternativeFinder::visit( ApplicationExpr *applicationExpr ) {
     355        void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) {
    311356                alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) );
    312357        }
     
    386431                                        PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; )
    387432                                        // convert reference-typed expressions to value-typed expressions
    388                                         referenceToRvalueConversion( *actualExpr );
     433                                        referenceToRvalueConversion( *actualExpr, convCost );
    389434                                        continue;
    390435                                } else {
     
    392437                                }
    393438                        }
     439                        if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {
     440                                // default arguments should be free - don't include conversion cost.
     441                                // Unwrap them here because they are not relevant to the rest of the system.
     442                                *actualExpr = def->expr;
     443                                ++formal;
     444                                continue;
     445                        }
    394446                        Type * formalType = (*formal)->get_type();
    395447                        convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env );
     
    409461        /// Adds type variables to the open variable set and marks their assertions
    410462        void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions ) {
    411                 for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
     463                for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
    412464                        unifiableVars[ (*tyvar)->get_name() ] = TypeDecl::Data{ *tyvar };
    413                         for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
     465                        for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->assertions.begin(); assert != (*tyvar)->assertions.end(); ++assert ) {
    414466                                needAssertions[ *assert ].isUsed = true;
    415467                        }
     
    418470        }
    419471
    420         // /// Map of declaration uniqueIds (intended to be the assertions in an AssertionSet) to their parents and the number of times they've been included
    421         //typedef std::unordered_map< UniqueId, std::unordered_map< UniqueId, unsigned > > AssertionParentSet;
    422 
    423472        static const int recursionLimit = /*10*/ 4;  ///< Limit to depth of recursion satisfaction
    424         //static const unsigned recursionParentLimit = 1;  ///< Limit to the number of times an assertion can recursively use itself
    425473
    426474        void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
     
    433481
    434482        template< typename ForwardIterator, typename OutputIterator >
    435         void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, /*const AssertionParentSet &needParents,*/
    436                                                  int level, const SymTab::Indexer &indexer, OutputIterator out ) {
     483        void inferRecursive( ForwardIterator begin, ForwardIterator end, const Alternative &newAlt, OpenVarSet &openVars, const SymTab::Indexer &decls, const AssertionSet &newNeed, int level, const SymTab::Indexer &indexer, OutputIterator out ) {
     484                if ( newAlt.cost == Cost::infinity ) return; // don't proceed down this dead end
    437485                if ( begin == end ) {
    438486                        if ( newNeed.empty() ) {
     
    445493                                return;
    446494                        } else if ( level >= recursionLimit ) {
    447                                 throw SemanticError( "Too many recursive assertions" );
     495                                SemanticError( newAlt.expr->location, "Too many recursive assertions" );
    448496                        } else {
    449497                                AssertionSet newerNeed;
     
    452500                                        printAssertionSet( newNeed, std::cerr, 8 );
    453501                                )
    454                                 inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, /*needParents,*/ level+1, indexer, out );
     502                                inferRecursive( newNeed.begin(), newNeed.end(), newAlt, openVars, decls, newerNeed, level+1, indexer, out );
    455503                                return;
    456504                        }
     
    459507                ForwardIterator cur = begin++;
    460508                if ( ! cur->second.isUsed ) {
    461                         inferRecursive( begin, end, newAlt, openVars, decls, newNeed, /*needParents,*/ level, indexer, out );
     509                        inferRecursive( begin, end, newAlt, openVars, decls, newNeed, level, indexer, out );
    462510                        return; // xxx - should this continue? previously this wasn't here, and it looks like it should be
    463511                }
     
    485533                        Type *adjType = candidate->get_type()->clone();
    486534                        adjustExprType( adjType, newEnv, indexer );
    487                         adjType->accept( global_renamer );
     535                        renameTyVars( adjType );
    488536                        PRINT(
    489537                                std::cerr << "unifying ";
     
    512560                                }
    513561
    514                                 //AssertionParentSet newNeedParents( needParents );
    515                                 // skip repeatingly-self-recursive assertion satisfaction
    516                                 // DOESN'T WORK: grandchild nodes conflict with their cousins
    517                                 //if ( newNeedParents[ curDecl->get_uniqueId() ][ candDecl->get_uniqueId() ]++ > recursionParentLimit ) continue;
    518                                 Expression *varExpr = data.combine();
     562                                Expression *varExpr = data.combine( newerAlt.cvtCost );
    519563                                delete varExpr->get_result();
    520564                                varExpr->set_result( adjType->clone() );
     
    533577                                // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions
    534578                                (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
    535                                 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, /*newNeedParents,*/ level, indexer, out );
     579                                inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, level, indexer, out );
    536580                        } else {
    537581                                delete adjType;
     
    541585
    542586        template< typename OutputIterator >
    543         void AlternativeFinder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
     587        void AlternativeFinder::Finder::inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out ) {
    544588//      PRINT(
    545589//          std::cerr << "inferParameters: assertions needed are" << std::endl;
     
    555599                addToIndexer( have, decls );
    556600                AssertionSet newNeed;
    557                 //AssertionParentSet needParents;
    558601                PRINT(
    559602                        std::cerr << "env is: " << std::endl;
     
    562605                )
    563606
    564                 inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, /*needParents,*/ 0, indexer, out );
     607                inferRecursive( need.begin(), need.end(), newAlt, openVars, decls, newNeed, 0, indexer, out );
    565608//      PRINT(
    566609//          std::cerr << "declaration 14 is ";
     
    573616        ConstantExpr* getDefaultValue( Initializer* init ) {
    574617                if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) {
    575                         if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) {
    576                                 return dynamic_cast<ConstantExpr*>( ce->get_arg() );
     618                        if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) {
     619                                return dynamic_cast<ConstantExpr*>( ce->arg );
     620                        } else {
     621                                return dynamic_cast<ConstantExpr*>( si->value );
    577622                        }
    578623                }
     
    596641                ArgPack()
    597642                        : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0),
    598 
    599643                          tupleStart(0), nextExpl(0), explAlt(0) {}
    600644
     
    648692                        const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart,
    649693                        const SymTab::Indexer& indexer, unsigned nTuples = 0 ) {
    650                 if ( TupleType* tupleType = dynamic_cast<TupleType*>( formalType ) ) {
     694                if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {
    651695                        // formalType is a TupleType - group actuals into a TupleExpr
    652696                        ++nTuples;
    653697                        for ( Type* type : *tupleType ) {
    654698                                // xxx - dropping initializer changes behaviour from previous, but seems correct
     699                                // ^^^ need to handle the case where a tuple has a default argument
    655700                                if ( ! instantiateArgument(
    656701                                                type, nullptr, args, results, genStart, indexer, nTuples ) )
     
    663708                        }
    664709                        return true;
    665                 } else if ( TypeInstType* ttype = Tuples::isTtype( formalType ) ) {
     710                } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) {
    666711                        // formalType is a ttype, consumes all remaining arguments
    667712                        // xxx - mixing default arguments with variadic??
     
    706751                                                Type* argType;
    707752
    708                                                 if ( nTuples > 0 ) {
    709                                                         // first iteration, push empty tuple expression
     753                                                if ( nTuples > 0 || ! results[i].expr ) {
     754                                                        // first iteration or no expression to clone,
     755                                                        // push empty tuple expression
    710756                                                        newResult.parent = i;
    711757                                                        std::list<Expression*> emptyList;
     
    834880                                                                indexer ) ) {
    835881                                                        results.emplace_back(
    836                                                                 i, cnstExpr, move(env), move(need), move(have),
     882                                                                i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have),
    837883                                                                move(openVars), nextArg, nTuples );
    838884                                                }
     
    865911                                // consider only first exploded actual
    866912                                Expression* expr = expl.exprs.front().get();
    867                                 Type* actualType = expr->get_result()->clone();
     913                                Type* actualType = expr->result->clone();
    868914
    869915                                PRINT(
     
    892938
    893939        template<typename OutputIterator>
    894         void AlternativeFinder::validateFunctionAlternative( const Alternative &func, ArgPack& result,
     940        void AlternativeFinder::Finder::validateFunctionAlternative( const Alternative &func, ArgPack& result,
    895941                        const std::vector<ArgPack>& results, OutputIterator out ) {
    896942                ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() );
    897943                // sum cost and accumulate actuals
    898                 std::list<Expression*>& args = appExpr->get_args();
     944                std::list<Expression*>& args = appExpr->args;
    899945                Cost cost = func.cost;
    900946                const ArgPack* pack = &result;
     
    915961
    916962        template<typename OutputIterator>
    917         void AlternativeFinder::makeFunctionAlternatives( const Alternative &func,
     963        void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func,
    918964                        FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) {
    919965                OpenVarSet funcOpenVars;
     
    923969                // add all type variables as open variables now so that those not used in the parameter
    924970                // list are still considered open.
    925                 funcEnv.add( funcType->get_forall() );
    926 
    927                 if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) {
     971                funcEnv.add( funcType->forall );
     972
     973                if ( targetType && ! targetType->isVoid() && ! funcType->returnVals.empty() ) {
    928974                        // attempt to narrow based on expected target type
    929                         Type * returnType = funcType->get_returnVals().front()->get_type();
     975                        Type * returnType = funcType->returnVals.front()->get_type();
    930976                        if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars,
    931977                                        indexer ) ) {
     
    940986                std::size_t genStart = 0;
    941987
    942                 for ( DeclarationWithType* formal : funcType->get_parameters() ) {
     988                for ( DeclarationWithType* formal : funcType->parameters ) {
    943989                        ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal );
    944990                        if ( ! instantiateArgument(
    945                                         obj->get_type(), obj->get_init(), args, results, genStart, indexer ) )
     991                                        obj->type, obj->init, args, results, genStart, indexer ) )
    946992                                return;
    947993                }
     
    10221068        }
    10231069
    1024         void AlternativeFinder::visit( UntypedExpr *untypedExpr ) {
     1070        void AlternativeFinder::Finder::postvisit( UntypedExpr *untypedExpr ) {
    10251071                AlternativeFinder funcFinder( indexer, env );
    1026                 funcFinder.findWithAdjustment( untypedExpr->get_function() );
     1072                funcFinder.findWithAdjustment( untypedExpr->function );
    10271073                // if there are no function alternatives, then proceeding is a waste of time.
     1074                // xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary.
    10281075                if ( funcFinder.alternatives.empty() ) return;
    10291076
    10301077                std::vector< AlternativeFinder > argAlternatives;
    1031                 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),
     1078                altFinder.findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),
    10321079                        back_inserter( argAlternatives ) );
    10331080
    10341081                // take care of possible tuple assignments
    10351082                // if not tuple assignment, assignment is taken care of as a normal function call
    1036                 Tuples::handleTupleAssignment( *this, untypedExpr, argAlternatives );
     1083                Tuples::handleTupleAssignment( altFinder, untypedExpr, argAlternatives );
    10371084
    10381085                // find function operators
     
    10401087                AlternativeFinder funcOpFinder( indexer, env );
    10411088                // it's ok if there aren't any defined function ops
    1042                 funcOpFinder.maybeFind( opExpr);
     1089                funcOpFinder.maybeFind( opExpr );
    10431090                PRINT(
    10441091                        std::cerr << "known function ops:" << std::endl;
     
    10531100                        argExpansions.emplace_back();
    10541101                        auto& argE = argExpansions.back();
    1055                         argE.reserve( arg.alternatives.size() );
     1102                        // argE.reserve( arg.alternatives.size() );
    10561103
    10571104                        for ( const Alternative& actual : arg ) {
     
    10611108
    10621109                AltList candidates;
    1063                 SemanticError errors;
     1110                SemanticErrorException errors;
    10641111                for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
    10651112                        try {
     
    10691116                                )
    10701117                                // check if the type is pointer to function
    1071                                 if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) {
    1072                                         if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
     1118                                if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->result->stripReferences() ) ) {
     1119                                        if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->base ) ) {
    10731120                                                Alternative newFunc( *func );
    1074                                                 referenceToRvalueConversion( newFunc.expr );
     1121                                                referenceToRvalueConversion( newFunc.expr, newFunc.cost );
    10751122                                                makeFunctionAlternatives( newFunc, function, argExpansions,
    10761123                                                        std::back_inserter( candidates ) );
    10771124                                        }
    1078                                 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
    1079                                         EqvClass eqvClass;
    1080                                         if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
    1081                                                 if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
     1125                                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->result->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
     1126                                        if ( const EqvClass *eqvClass = func->env.lookup( typeInst->name ) ) {
     1127                                                if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass->type ) ) {
    10821128                                                        Alternative newFunc( *func );
    1083                                                         referenceToRvalueConversion( newFunc.expr );
     1129                                                        referenceToRvalueConversion( newFunc.expr, newFunc.cost );
    10841130                                                        makeFunctionAlternatives( newFunc, function, argExpansions,
    10851131                                                                std::back_inserter( candidates ) );
     
    10871133                                        } // if
    10881134                                }
    1089                         } catch ( SemanticError &e ) {
     1135                        } catch ( SemanticErrorException &e ) {
    10901136                                errors.append( e );
    10911137                        }
     
    11071153                                        // check if type is a pointer to function
    11081154                                        if ( PointerType* pointer = dynamic_cast<PointerType*>(
    1109                                                         funcOp->expr->get_result()->stripReferences() ) ) {
     1155                                                        funcOp->expr->result->stripReferences() ) ) {
    11101156                                                if ( FunctionType* function =
    1111                                                                 dynamic_cast<FunctionType*>( pointer->get_base() ) ) {
     1157                                                                dynamic_cast<FunctionType*>( pointer->base ) ) {
    11121158                                                        Alternative newFunc( *funcOp );
    1113                                                         referenceToRvalueConversion( newFunc.expr );
     1159                                                        referenceToRvalueConversion( newFunc.expr, newFunc.cost );
    11141160                                                        makeFunctionAlternatives( newFunc, function, argExpansions,
    11151161                                                                std::back_inserter( candidates ) );
    11161162                                                }
    11171163                                        }
    1118                                 } catch ( SemanticError &e ) {
     1164                                } catch ( SemanticErrorException &e ) {
    11191165                                        errors.append( e );
    11201166                                }
     
    11311177                        PRINT(
    11321178                                ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc.expr );
    1133                                 PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
    1134                                 FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() );
    1135                                 std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl;
     1179                                PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
     1180                                FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
     1181                                std::cerr << "Case +++++++++++++ " << appExpr->function << std::endl;
    11361182                                std::cerr << "formals are:" << std::endl;
    1137                                 printAll( function->get_parameters(), std::cerr, 8 );
     1183                                printAll( function->parameters, std::cerr, 8 );
    11381184                                std::cerr << "actuals are:" << std::endl;
    1139                                 printAll( appExpr->get_args(), std::cerr, 8 );
     1185                                printAll( appExpr->args, std::cerr, 8 );
    11401186                                std::cerr << "bindings are:" << std::endl;
    11411187                                withFunc.env.print( std::cerr, 8 );
     1188                                std::cerr << "cost is: " << withFunc.cost << std::endl;
    11421189                                std::cerr << "cost of conversion is:" << cvtCost << std::endl;
    11431190                        )
     
    11721219                        // fix this issue in a more robust way.
    11731220                        targetType = nullptr;
    1174                         visit( untypedExpr );
     1221                        postvisit( untypedExpr );
    11751222                }
    11761223        }
     
    11781225        bool isLvalue( Expression *expr ) {
    11791226                // xxx - recurse into tuples?
    1180                 return expr->result && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
    1181         }
    1182 
    1183         void AlternativeFinder::visit( AddressExpr *addressExpr ) {
     1227                return expr->result && ( expr->result->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );
     1228        }
     1229
     1230        void AlternativeFinder::Finder::postvisit( AddressExpr *addressExpr ) {
    11841231                AlternativeFinder finder( indexer, env );
    11851232                finder.find( addressExpr->get_arg() );
     
    11921239        }
    11931240
    1194         void AlternativeFinder::visit( LabelAddressExpr * expr ) {
     1241        void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) {
    11951242                alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } );
    11961243        }
    11971244
    1198         Expression * restructureCast( Expression * argExpr, Type * toType ) {
     1245        Expression * restructureCast( Expression * argExpr, Type * toType, bool isGenerated ) {
    11991246                if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) {
    12001247                        // Argument expression is a tuple and the target type is not void and not a reference type.
     
    12111258                                // cast each component
    12121259                                TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i );
    1213                                 componentExprs.push_back( restructureCast( idx, toType->getComponent( i ) ) );
     1260                                componentExprs.push_back( restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    12141261                        }
    12151262                        delete argExpr;
     
    12191266                } else {
    12201267                        // handle normally
    1221                         return new CastExpr( argExpr, toType->clone() );
    1222                 }
    1223         }
    1224 
    1225         void AlternativeFinder::visit( CastExpr *castExpr ) {
     1268                        CastExpr * ret = new CastExpr( argExpr, toType->clone() );
     1269                        ret->isGenerated = isGenerated;
     1270                        return ret;
     1271                }
     1272        }
     1273
     1274        void AlternativeFinder::Finder::postvisit( CastExpr *castExpr ) {
    12261275                Type *& toType = castExpr->get_result();
    12271276                assert( toType );
     
    12321281                AlternativeFinder finder( indexer, env );
    12331282                finder.targetType = toType;
    1234                 finder.findWithAdjustment( castExpr->get_arg() );
     1283                finder.findWithAdjustment( castExpr->arg );
    12351284
    12361285                AltList candidates;
     
    12391288                        OpenVarSet openVars;
    12401289
     1290                        alt.env.extractOpenVars( openVars );
     1291
    12411292                        // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    12421293                        // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    12431294                        // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    12441295                        // to.
    1245                         int discardedValues = alt.expr->get_result()->size() - castExpr->get_result()->size();
     1296                        int discardedValues = alt.expr->result->size() - castExpr->result->size();
    12461297                        if ( discardedValues < 0 ) continue;
    12471298                        // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    12481299                        // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    12491300                        // unification run for side-effects
    1250                         unify( castExpr->get_result(), alt.expr->get_result(), alt.env, needAssertions,
     1301                        unify( castExpr->result, alt.expr->result, alt.env, needAssertions,
    12511302                                haveAssertions, openVars, indexer );
    1252                         Cost thisCost = castCost( alt.expr->get_result(), castExpr->get_result(), indexer,
     1303                        Cost thisCost = castCost( alt.expr->result, castExpr->result, indexer,
    12531304                                alt.env );
    12541305                        PRINT(
     
    12631314                                // count one safe conversion for each value that is thrown away
    12641315                                thisCost.incSafe( discardedValues );
    1265                                 Alternative newAlt( restructureCast( alt.expr->clone(), toType ), alt.env,
     1316                                Alternative newAlt( restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), alt.env,
    12661317                                        alt.cost, thisCost );
    12671318                                inferParameters( needAssertions, haveAssertions, newAlt, openVars,
     
    12781329        }
    12791330
    1280         void AlternativeFinder::visit( VirtualCastExpr * castExpr ) {
     1331        void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) {
    12811332                assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." );
    12821333                AlternativeFinder finder( indexer, env );
     
    12901341        }
    12911342
    1292         void AlternativeFinder::visit( UntypedMemberExpr *memberExpr ) {
     1343        namespace {
     1344                /// Gets name from untyped member expression (member must be NameExpr)
     1345                const std::string& get_member_name( UntypedMemberExpr *memberExpr ) {
     1346                        NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() );
     1347                        assert( nameExpr );
     1348                        return nameExpr->get_name();
     1349                }
     1350        }
     1351
     1352        void AlternativeFinder::Finder::postvisit( UntypedMemberExpr *memberExpr ) {
    12931353                AlternativeFinder funcFinder( indexer, env );
    12941354                funcFinder.findWithAdjustment( memberExpr->get_aggregate() );
    12951355                for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
    12961356                        // it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
    1297                         std::unique_ptr<Expression> aggrExpr( agg->expr->clone() );
    1298                         Type * aggrType = aggrExpr->get_result();
    1299                         if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
    1300                                 aggrType = aggrType->stripReferences();
    1301                                 aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) );
    1302                         }
     1357                        Cost cost = agg->cost;
     1358                        Expression * aggrExpr = agg->expr->clone();
     1359                        referenceToRvalueConversion( aggrExpr, cost );
     1360                        std::unique_ptr<Expression> guard( aggrExpr );
     1361
    13031362                        // find member of the given type
    13041363                        if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
    1305                                 addAggMembers( structInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     1364                                addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
    13061365                        } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
    1307                                 addAggMembers( unionInst, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     1366                                addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
    13081367                        } else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
    1309                                 addTupleMembers( tupleType, aggrExpr.get(), agg->cost, agg->env, memberExpr->get_member() );
     1368                                addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
    13101369                        } // if
    13111370                } // for
    13121371        }
    13131372
    1314         void AlternativeFinder::visit( MemberExpr *memberExpr ) {
     1373        void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) {
    13151374                alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) );
    13161375        }
    13171376
    1318         void AlternativeFinder::visit( NameExpr *nameExpr ) {
     1377        void AlternativeFinder::Finder::postvisit( NameExpr *nameExpr ) {
    13191378                std::list< SymTab::Indexer::IdData > declList;
    1320                 indexer.lookupId( nameExpr->get_name(), declList );
    1321                 PRINT( std::cerr << "nameExpr is " << nameExpr->get_name() << std::endl; )
     1379                indexer.lookupId( nameExpr->name, declList );
     1380                PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
    13221381                for ( auto & data : declList ) {
    1323                         Expression * newExpr = data.combine();
    1324                         // xxx - add in extra cost for with-statement exprs?
    1325                         alternatives.push_back( Alternative( newExpr, env, Cost::zero ) );
     1382                        Cost cost = Cost::zero;
     1383                        Expression * newExpr = data.combine( cost );
     1384
     1385                        // addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
     1386                        // can't construct in place and use vector::back
     1387                        Alternative newAlt( newExpr, env, Cost::zero, cost );
    13261388                        PRINT(
    13271389                                std::cerr << "decl is ";
     
    13321394                                std::cerr << std::endl;
    13331395                        )
    1334                         renameTypes( alternatives.back().expr );
    1335                         addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression.
     1396                        renameTypes( newAlt.expr );
     1397                        addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression.
     1398                        alternatives.push_back( std::move(newAlt) );
    13361399                } // for
    13371400        }
    13381401
    1339         void AlternativeFinder::visit( VariableExpr *variableExpr ) {
     1402        void AlternativeFinder::Finder::postvisit( VariableExpr *variableExpr ) {
    13401403                // not sufficient to clone here, because variable's type may have changed
    13411404                // since the VariableExpr was originally created.
    1342                 alternatives.push_back( Alternative( new VariableExpr( variableExpr->get_var() ), env, Cost::zero ) );
    1343         }
    1344 
    1345         void AlternativeFinder::visit( ConstantExpr *constantExpr ) {
     1405                alternatives.push_back( Alternative( new VariableExpr( variableExpr->var ), env, Cost::zero ) );
     1406        }
     1407
     1408        void AlternativeFinder::Finder::postvisit( ConstantExpr *constantExpr ) {
    13461409                alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) );
    13471410        }
    13481411
    1349         void AlternativeFinder::visit( SizeofExpr *sizeofExpr ) {
     1412        void AlternativeFinder::Finder::postvisit( SizeofExpr *sizeofExpr ) {
    13501413                if ( sizeofExpr->get_isType() ) {
    13511414                        Type * newType = sizeofExpr->get_type()->clone();
     
    13591422                        findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
    13601423                        if ( winners.size() != 1 ) {
    1361                                 throw SemanticError( "Ambiguous expression in sizeof operand: ", sizeofExpr->get_expr() );
     1424                                SemanticError( sizeofExpr->get_expr(), "Ambiguous expression in sizeof operand: " );
    13621425                        } // if
    13631426                        // return the lowest cost alternative for the argument
    13641427                        Alternative &choice = winners.front();
    1365                         referenceToRvalueConversion( choice.expr );
     1428                        referenceToRvalueConversion( choice.expr, choice.cost );
    13661429                        alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    13671430                } // if
    13681431        }
    13691432
    1370         void AlternativeFinder::visit( AlignofExpr *alignofExpr ) {
     1433        void AlternativeFinder::Finder::postvisit( AlignofExpr *alignofExpr ) {
    13711434                if ( alignofExpr->get_isType() ) {
    13721435                        Type * newType = alignofExpr->get_type()->clone();
     
    13801443                        findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
    13811444                        if ( winners.size() != 1 ) {
    1382                                 throw SemanticError( "Ambiguous expression in alignof operand: ", alignofExpr->get_expr() );
     1445                                SemanticError( alignofExpr->get_expr(), "Ambiguous expression in alignof operand: " );
    13831446                        } // if
    13841447                        // return the lowest cost alternative for the argument
    13851448                        Alternative &choice = winners.front();
    1386                         referenceToRvalueConversion( choice.expr );
     1449                        referenceToRvalueConversion( choice.expr, choice.cost );
    13871450                        alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) );
    13881451                } // if
     
    13901453
    13911454        template< typename StructOrUnionType >
    1392         void AlternativeFinder::addOffsetof( StructOrUnionType *aggInst, const std::string &name ) {
     1455        void AlternativeFinder::Finder::addOffsetof( StructOrUnionType *aggInst, const std::string &name ) {
    13931456                std::list< Declaration* > members;
    13941457                aggInst->lookup( name, members );
     
    14031466        }
    14041467
    1405         void AlternativeFinder::visit( UntypedOffsetofExpr *offsetofExpr ) {
     1468        void AlternativeFinder::Finder::postvisit( UntypedOffsetofExpr *offsetofExpr ) {
    14061469                AlternativeFinder funcFinder( indexer, env );
    14071470                // xxx - resolveTypeof?
    14081471                if ( StructInstType *structInst = dynamic_cast< StructInstType* >( offsetofExpr->get_type() ) ) {
    1409                         addOffsetof( structInst, offsetofExpr->get_member() );
     1472                        addOffsetof( structInst, offsetofExpr->member );
    14101473                } else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( offsetofExpr->get_type() ) ) {
    1411                         addOffsetof( unionInst, offsetofExpr->get_member() );
    1412                 }
    1413         }
    1414 
    1415         void AlternativeFinder::visit( OffsetofExpr *offsetofExpr ) {
     1474                        addOffsetof( unionInst, offsetofExpr->member );
     1475                }
     1476        }
     1477
     1478        void AlternativeFinder::Finder::postvisit( OffsetofExpr *offsetofExpr ) {
    14161479                alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) );
    14171480        }
    14181481
    1419         void AlternativeFinder::visit( OffsetPackExpr *offsetPackExpr ) {
     1482        void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) {
    14201483                alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) );
    14211484        }
     
    14361499                        AltList & alternatives = finder.get_alternatives();
    14371500                        if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) {
    1438                                 alternatives.push_back( Alternative( new AttrExpr( data.combine(), argType->clone() ), env, Cost::zero ) );
     1501                                Cost cost = Cost::zero;
     1502                                Expression * newExpr = data.combine( cost );
     1503                                alternatives.push_back( Alternative( new AttrExpr( newExpr, argType->clone() ), env, Cost::zero, cost ) );
    14391504                                for ( DeclarationWithType * retVal : function->returnVals ) {
    14401505                                        alternatives.back().expr->result = retVal->get_type()->clone();
     
    14441509        }
    14451510
    1446         void AlternativeFinder::visit( AttrExpr *attrExpr ) {
     1511        void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) {
    14471512                // assume no 'pointer-to-attribute'
    14481513                NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );
     
    14581523                                        if ( function->get_parameters().size() == 1 ) {
    14591524                                                if ( attrExpr->get_isType() ) {
    1460                                                         resolveAttr( data, function, attrExpr->get_type(), env, *this );
     1525                                                        resolveAttr( data, function, attrExpr->get_type(), env, altFinder);
    14611526                                                } else {
    14621527                                                        AlternativeFinder finder( indexer, env );
     
    14641529                                                        for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
    14651530                                                                if ( choice->expr->get_result()->size() == 1 ) {
    1466                                                                         resolveAttr(data, function, choice->expr->get_result(), choice->env, *this );
     1531                                                                        resolveAttr(data, function, choice->expr->get_result(), choice->env, altFinder );
    14671532                                                                } // fi
    14681533                                                        } // for
     
    14731538                } else {
    14741539                        for ( auto & data : attrList ) {
    1475                                 alternatives.push_back( Alternative( data.combine(), env, Cost::zero ) );
     1540                                Cost cost = Cost::zero;
     1541                                Expression * newExpr = data.combine( cost );
     1542                                alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
    14761543                                renameTypes( alternatives.back().expr );
    14771544                        } // for
     
    14791546        }
    14801547
    1481         void AlternativeFinder::visit( LogicalExpr *logicalExpr ) {
     1548        void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) {
    14821549                AlternativeFinder firstFinder( indexer, env );
    14831550                firstFinder.findWithAdjustment( logicalExpr->get_arg1() );
    1484                 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
    1485                         AlternativeFinder secondFinder( indexer, first->env );
    1486                         secondFinder.findWithAdjustment( logicalExpr->get_arg2() );
    1487                         for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
    1488                                 LogicalExpr *newExpr = new LogicalExpr( first->expr->clone(), second->expr->clone(), logicalExpr->get_isAnd() );
    1489                                 alternatives.push_back( Alternative( newExpr, second->env, first->cost + second->cost ) );
    1490                         }
    1491                 }
    1492         }
    1493 
    1494         void AlternativeFinder::visit( ConditionalExpr *conditionalExpr ) {
     1551                if ( firstFinder.alternatives.empty() ) return;
     1552                AlternativeFinder secondFinder( indexer, env );
     1553                secondFinder.findWithAdjustment( logicalExpr->get_arg2() );
     1554                if ( secondFinder.alternatives.empty() ) return;
     1555                for ( const Alternative & first : firstFinder.alternatives ) {
     1556                        for ( const Alternative & second : secondFinder.alternatives ) {
     1557                                TypeEnvironment compositeEnv;
     1558                                compositeEnv.simpleCombine( first.env );
     1559                                compositeEnv.simpleCombine( second.env );
     1560
     1561                                LogicalExpr *newExpr = new LogicalExpr( first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() );
     1562                                alternatives.push_back( Alternative( newExpr, compositeEnv, first.cost + second.cost ) );
     1563                        }
     1564                }
     1565        }
     1566
     1567        void AlternativeFinder::Finder::postvisit( ConditionalExpr *conditionalExpr ) {
    14951568                // find alternatives for condition
    14961569                AlternativeFinder firstFinder( indexer, env );
    1497                 firstFinder.findWithAdjustment( conditionalExpr->get_arg1() );
    1498                 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
    1499                         // find alternatives for true expression
    1500                         AlternativeFinder secondFinder( indexer, first->env );
    1501                         secondFinder.findWithAdjustment( conditionalExpr->get_arg2() );
    1502                         for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
    1503                                 // find alterantives for false expression
    1504                                 AlternativeFinder thirdFinder( indexer, second->env );
    1505                                 thirdFinder.findWithAdjustment( conditionalExpr->get_arg3() );
    1506                                 for ( AltList::const_iterator third = thirdFinder.alternatives.begin(); third != thirdFinder.alternatives.end(); ++third ) {
     1570                firstFinder.findWithAdjustment( conditionalExpr->arg1 );
     1571                if ( firstFinder.alternatives.empty() ) return;
     1572                // find alternatives for true expression
     1573                AlternativeFinder secondFinder( indexer, env );
     1574                secondFinder.findWithAdjustment( conditionalExpr->arg2 );
     1575                if ( secondFinder.alternatives.empty() ) return;
     1576                // find alterantives for false expression
     1577                AlternativeFinder thirdFinder( indexer, env );
     1578                thirdFinder.findWithAdjustment( conditionalExpr->arg3 );
     1579                if ( thirdFinder.alternatives.empty() ) return;
     1580                for ( const Alternative & first : firstFinder.alternatives ) {
     1581                        for ( const Alternative & second : secondFinder.alternatives ) {
     1582                                for ( const Alternative & third : thirdFinder.alternatives ) {
     1583                                        TypeEnvironment compositeEnv;
     1584                                        compositeEnv.simpleCombine( first.env );
     1585                                        compositeEnv.simpleCombine( second.env );
     1586                                        compositeEnv.simpleCombine( third.env );
     1587
    15071588                                        // unify true and false types, then infer parameters to produce new alternatives
    15081589                                        OpenVarSet openVars;
    15091590                                        AssertionSet needAssertions, haveAssertions;
    1510                                         Alternative newAlt( 0, third->env, first->cost + second->cost + third->cost );
     1591                                        Alternative newAlt( 0, compositeEnv, first.cost + second.cost + third.cost );
    15111592                                        Type* commonType = nullptr;
    1512                                         if ( unify( second->expr->get_result(), third->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1513                                                 ConditionalExpr *newExpr = new ConditionalExpr( first->expr->clone(), second->expr->clone(), third->expr->clone() );
    1514                                                 newExpr->set_result( commonType ? commonType : second->expr->get_result()->clone() );
     1593                                        if ( unify( second.expr->result, third.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     1594                                                ConditionalExpr *newExpr = new ConditionalExpr( first.expr->clone(), second.expr->clone(), third.expr->clone() );
     1595                                                newExpr->result = commonType ? commonType : second.expr->result->clone();
    15151596                                                // convert both options to the conditional result type
    15161597                                                newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env );
     
    15241605        }
    15251606
    1526         void AlternativeFinder::visit( CommaExpr *commaExpr ) {
     1607        void AlternativeFinder::Finder::postvisit( CommaExpr *commaExpr ) {
    15271608                TypeEnvironment newEnv( env );
    15281609                Expression *newFirstArg = resolveInVoidContext( commaExpr->get_arg1(), indexer, newEnv );
    15291610                AlternativeFinder secondFinder( indexer, newEnv );
    15301611                secondFinder.findWithAdjustment( commaExpr->get_arg2() );
    1531                 for ( AltList::const_iterator alt = secondFinder.alternatives.begin(); alt != secondFinder.alternatives.end(); ++alt ) {
    1532                         alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt->expr->clone() ), alt->env, alt->cost ) );
     1612                for ( const Alternative & alt : secondFinder.alternatives ) {
     1613                        alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
    15331614                } // for
    15341615                delete newFirstArg;
    15351616        }
    15361617
    1537         void AlternativeFinder::visit( RangeExpr * rangeExpr ) {
     1618        void AlternativeFinder::Finder::postvisit( RangeExpr * rangeExpr ) {
    15381619                // resolve low and high, accept alternatives whose low and high types unify
    15391620                AlternativeFinder firstFinder( indexer, env );
    1540                 firstFinder.findWithAdjustment( rangeExpr->get_low() );
    1541                 for ( AltList::const_iterator first = firstFinder.alternatives.begin(); first != firstFinder.alternatives.end(); ++first ) {
    1542                         AlternativeFinder secondFinder( indexer, first->env );
    1543                         secondFinder.findWithAdjustment( rangeExpr->get_high() );
    1544                         for ( AltList::const_iterator second = secondFinder.alternatives.begin(); second != secondFinder.alternatives.end(); ++second ) {
     1621                firstFinder.findWithAdjustment( rangeExpr->low );
     1622                if ( firstFinder.alternatives.empty() ) return;
     1623                AlternativeFinder secondFinder( indexer, env );
     1624                secondFinder.findWithAdjustment( rangeExpr->high );
     1625                if ( secondFinder.alternatives.empty() ) return;
     1626                for ( const Alternative & first : firstFinder.alternatives ) {
     1627                        for ( const Alternative & second : secondFinder.alternatives ) {
     1628                                TypeEnvironment compositeEnv;
     1629                                compositeEnv.simpleCombine( first.env );
     1630                                compositeEnv.simpleCombine( second.env );
    15451631                                OpenVarSet openVars;
    15461632                                AssertionSet needAssertions, haveAssertions;
    1547                                 Alternative newAlt( 0, second->env, first->cost + second->cost );
     1633                                Alternative newAlt( 0, compositeEnv, first.cost + second.cost );
    15481634                                Type* commonType = nullptr;
    1549                                 if ( unify( first->expr->get_result(), second->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    1550                                         RangeExpr *newExpr = new RangeExpr( first->expr->clone(), second->expr->clone() );
    1551                                         newExpr->set_result( commonType ? commonType : first->expr->get_result()->clone() );
     1635                                if ( unify( first.expr->result, second.expr->result, newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     1636                                        RangeExpr * newExpr = new RangeExpr( first.expr->clone(), second.expr->clone() );
     1637                                        newExpr->result = commonType ? commonType : first.expr->result->clone();
    15521638                                        newAlt.expr = newExpr;
    15531639                                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
     
    15571643        }
    15581644
    1559         void AlternativeFinder::visit( UntypedTupleExpr *tupleExpr ) {
     1645        void AlternativeFinder::Finder::postvisit( UntypedTupleExpr *tupleExpr ) {
    15601646                std::vector< AlternativeFinder > subExprAlternatives;
    1561                 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(),
     1647                altFinder.findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(),
    15621648                        back_inserter( subExprAlternatives ) );
    15631649                std::vector< AltList > possibilities;
     
    15751661        }
    15761662
    1577         void AlternativeFinder::visit( TupleExpr *tupleExpr ) {
     1663        void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) {
    15781664                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    15791665        }
    15801666
    1581         void AlternativeFinder::visit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
     1667        void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) {
    15821668                alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) );
    15831669        }
    15841670
    1585         void AlternativeFinder::visit( ConstructorExpr * ctorExpr ) {
     1671        void AlternativeFinder::Finder::postvisit( ConstructorExpr * ctorExpr ) {
    15861672                AlternativeFinder finder( indexer, env );
    15871673                // don't prune here, since it's guaranteed all alternatives will have the same type
     
    15931679        }
    15941680
    1595         void AlternativeFinder::visit( TupleIndexExpr *tupleExpr ) {
     1681        void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) {
    15961682                alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) );
    15971683        }
    15981684
    1599         void AlternativeFinder::visit( TupleAssignExpr *tupleAssignExpr ) {
     1685        void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) {
    16001686                alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) );
    16011687        }
    16021688
    1603         void AlternativeFinder::visit( UniqueExpr *unqExpr ) {
     1689        void AlternativeFinder::Finder::postvisit( UniqueExpr *unqExpr ) {
    16041690                AlternativeFinder finder( indexer, env );
    16051691                finder.findWithAdjustment( unqExpr->get_expr() );
     
    16111697        }
    16121698
    1613         void AlternativeFinder::visit( StmtExpr *stmtExpr ) {
     1699        void AlternativeFinder::Finder::postvisit( StmtExpr *stmtExpr ) {
    16141700                StmtExpr * newStmtExpr = stmtExpr->clone();
    16151701                ResolvExpr::resolveStmtExpr( newStmtExpr, indexer );
     
    16181704        }
    16191705
    1620         void AlternativeFinder::visit( UntypedInitExpr *initExpr ) {
     1706        void AlternativeFinder::Finder::postvisit( UntypedInitExpr *initExpr ) {
    16211707                // handle each option like a cast
    16221708                AltList candidates;
    1623                 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; )
     1709                PRINT(
     1710                        std::cerr << "untyped init expr: " << initExpr << std::endl;
     1711                )
    16241712                // O(N^2) checks of d-types with e-types
    16251713                for ( InitAlternative & initAlt : initExpr->get_initAlts() ) {
     
    16321720                        AlternativeFinder finder( indexer, env );
    16331721                        finder.targetType = toType;
    1634                         finder.findWithAdjustment( initExpr->get_expr() );
     1722                        finder.findWithAdjustment( initExpr->expr );
    16351723                        for ( Alternative & alt : finder.get_alternatives() ) {
    16361724                                TypeEnvironment newEnv( alt.env );
    16371725                                AssertionSet needAssertions, haveAssertions;
    16381726                                OpenVarSet openVars;  // find things in env that don't have a "representative type" and claim those are open vars?
    1639                                 PRINT( std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl; )
     1727                                PRINT(
     1728                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
     1729                                )
    16401730                                // It's possible that a cast can throw away some values in a multiply-valued expression.  (An example is a
    16411731                                // cast-to-void, which casts from one value to zero.)  Figure out the prefix of the subexpression results
    16421732                                // that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
    16431733                                // to.
    1644                                 int discardedValues = alt.expr->get_result()->size() - toType->size();
     1734                                int discardedValues = alt.expr->result->size() - toType->size();
    16451735                                if ( discardedValues < 0 ) continue;
    16461736                                // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
    16471737                                // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
    16481738                                // unification run for side-effects
    1649                                 unify( toType, alt.expr->get_result(), newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type??
    1650 
    1651                                 Cost thisCost = castCost( alt.expr->get_result(), toType, indexer, newEnv );
     1739                                unify( toType, alt.expr->result, newEnv, needAssertions, haveAssertions, openVars, indexer ); // xxx - do some inspecting on this line... why isn't result bound to initAlt.type??
     1740
     1741                                Cost thisCost = castCost( alt.expr->result, toType, indexer, newEnv );
    16521742                                if ( thisCost != Cost::infinity ) {
    16531743                                        // count one safe conversion for each value that is thrown away
    16541744                                        thisCost.incSafe( discardedValues );
    1655                                         Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
     1745                                        Alternative newAlt( new InitExpr( restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost );
    16561746                                        inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) );
    16571747                                }
     
    16661756                findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) );
    16671757        }
     1758
     1759        void AlternativeFinder::Finder::postvisit( InitExpr * ) {
     1760                assertf( false, "AlternativeFinder should never see a resolved InitExpr." );
     1761        }
     1762
     1763        void AlternativeFinder::Finder::postvisit( DeletedExpr * ) {
     1764                assertf( false, "AlternativeFinder should never see a DeletedExpr." );
     1765        }
     1766
     1767        void AlternativeFinder::Finder::postvisit( GenericExpr * ) {
     1768                assertf( false, "_Generic is not yet supported." );
     1769        }
    16681770} // namespace ResolvExpr
    16691771
  • src/ResolvExpr/AlternativeFinder.h

    rf9feab8 r90152a4  
    3838        using ExplodedArgs = std::vector< std::vector< ExplodedActual > >;
    3939
    40         class AlternativeFinder : public Visitor {
     40        class AlternativeFinder {
    4141          public:
    4242                AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env );
     
    9494                void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
    9595          private:
    96                 virtual void visit( ApplicationExpr *applicationExpr );
    97                 virtual void visit( UntypedExpr *untypedExpr );
    98                 virtual void visit( AddressExpr *addressExpr );
    99                 virtual void visit( LabelAddressExpr *labelExpr );
    100                 virtual void visit( CastExpr *castExpr );
    101                 virtual void visit( VirtualCastExpr *castExpr );
    102                 virtual void visit( UntypedMemberExpr *memberExpr );
    103                 virtual void visit( MemberExpr *memberExpr );
    104                 virtual void visit( NameExpr *variableExpr );
    105                 virtual void visit( VariableExpr *variableExpr );
    106                 virtual void visit( ConstantExpr *constantExpr );
    107                 virtual void visit( SizeofExpr *sizeofExpr );
    108                 virtual void visit( AlignofExpr *alignofExpr );
    109                 virtual void visit( UntypedOffsetofExpr *offsetofExpr );
    110                 virtual void visit( OffsetofExpr *offsetofExpr );
    111                 virtual void visit( OffsetPackExpr *offsetPackExpr );
    112                 virtual void visit( AttrExpr *attrExpr );
    113                 virtual void visit( LogicalExpr *logicalExpr );
    114                 virtual void visit( ConditionalExpr *conditionalExpr );
    115                 virtual void visit( CommaExpr *commaExpr );
    116                 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr );
    117                 virtual void visit( ConstructorExpr * ctorExpr );
    118                 virtual void visit( RangeExpr * rangeExpr );
    119                 virtual void visit( UntypedTupleExpr *tupleExpr );
    120                 virtual void visit( TupleExpr *tupleExpr );
    121                 virtual void visit( TupleIndexExpr *tupleExpr );
    122                 virtual void visit( TupleAssignExpr *tupleExpr );
    123                 virtual void visit( UniqueExpr *unqExpr );
    124                 virtual void visit( StmtExpr *stmtExpr );
    125                 virtual void visit( UntypedInitExpr *initExpr );
    126 
    127                 /// Adds alternatives for anonymous members
    128                 void addAnonConversions( const Alternative & alt );
    129                 /// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
    130                 template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
    131                 /// Adds alternatives for member expressions where the left side has tuple type
    132                 void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
    133                 /// Adds alternatives for offsetof expressions, given the base type and name of the member
    134                 template< typename StructOrUnionType > void addOffsetof( StructOrUnionType *aggInst, const std::string &name );
    135                 /// Takes a final result and checks if its assertions can be satisfied
    136                 template<typename OutputIterator>
    137                 void validateFunctionAlternative( const Alternative &func, ArgPack& result, const std::vector<ArgPack>& results, OutputIterator out );
    138                 /// Finds matching alternatives for a function, given a set of arguments
    139                 template<typename OutputIterator>
    140                 void makeFunctionAlternatives( const Alternative &func, FunctionType *funcType, const ExplodedArgs& args, OutputIterator out );
    141                 /// Checks if assertion parameters match for a new alternative
    142                 template< typename OutputIterator >
    143                 void inferParameters( const AssertionSet &need, AssertionSet &have, const Alternative &newAlt, OpenVarSet &openVars, OutputIterator out );
    144 
     96                struct Finder;
    14597                const SymTab::Indexer &indexer;
    14698                AltList alternatives;
     
    174126        void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt = 0 );
    175127
     128        /// Adds type variables to the open variable set and marks their assertions
     129        void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions );
     130
    176131        template< typename InputIterator >
    177132        void simpleCombineEnvironments( InputIterator begin, InputIterator end, TypeEnvironment &result ) {
  • src/ResolvExpr/CastCost.cc

    rf9feab8 r90152a4  
    3131
    3232namespace ResolvExpr {
    33         class CastCost : public ConversionCost {
     33        struct CastCost : public ConversionCost {
    3434          public:
    35                 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
     35                CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
    3636
    37                 virtual void visit( BasicType *basicType );
    38                 virtual void visit( PointerType *pointerType );
     37                using ConversionCost::previsit;
     38                using ConversionCost::postvisit;
     39                void postvisit( BasicType * basicType );
     40                void postvisit( PointerType * pointerType );
    3941        };
    4042
    4143        Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    4244                if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
    43                         EqvClass eqvClass;
    44                         NamedTypeDecl *namedType;
    45                         if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
    46                                 if ( eqvClass.type ) {
    47                                         return castCost( src, eqvClass.type, indexer, env );
     45                        if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
     46                                if ( eqvClass->type ) {
     47                                        return castCost( src, eqvClass->type, indexer, env );
    4848                                } else {
    4949                                        return Cost::infinity;
    5050                                }
    51                         } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) {
     51                        } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) {
    5252                                // all typedefs should be gone by this point
    5353                                TypeDecl *type = strict_dynamic_cast< TypeDecl* >( namedType );
    54                                 if ( type->get_base() ) {
    55                                         return castCost( src, type->get_base(), indexer, env ) + Cost::safe;
     54                                if ( type->base ) {
     55                                        return castCost( src, type->base, indexer, env ) + Cost::safe;
    5656                                } // if
    5757                        } // if
     
    7474                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
    7575                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    76                         return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer & indexer) {
     76                        return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
    7777                                return ptrsCastable( t1, t2, env, indexer );
    7878                        });
    7979                } else {
    80                         CastCost converter( dest, indexer, env );
     80                        PassVisitor<CastCost> converter( dest, indexer, env, castCost );
    8181                        src->accept( converter );
    82                         if ( converter.get_cost() == Cost::infinity ) {
     82                        if ( converter.pass.get_cost() == Cost::infinity ) {
    8383                                return Cost::infinity;
    8484                        } else {
    8585                                // xxx - why are we adding cost 0 here?
    86                                 return converter.get_cost() + Cost::zero;
     86                                return converter.pass.get_cost() + Cost::zero;
    8787                        } // if
    8888                } // if
    8989        }
    9090
    91         CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )
    92                 : ConversionCost( dest, indexer, env ) {
     91        CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
     92                : ConversionCost( dest, indexer, env, costFunc ) {
    9393        }
    9494
    95         void CastCost::visit( BasicType *basicType ) {
     95        void CastCost::postvisit( BasicType *basicType ) {
    9696                PointerType *destAsPointer = dynamic_cast< PointerType* >( dest );
    9797                if ( destAsPointer && basicType->isInteger() ) {
     
    103103        }
    104104
    105         void CastCost::visit( PointerType *pointerType ) {
     105        void CastCost::postvisit( PointerType *pointerType ) {
    106106                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    107                         if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
     107                        if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
    108108                                cost = Cost::safe;
    109109                        } else {
    110110                                TypeEnvironment newEnv( env );
    111                                 newEnv.add( pointerType->get_forall() );
    112                                 newEnv.add( pointerType->get_base()->get_forall() );
    113                                 int castResult = ptrsCastable( pointerType->get_base(), destAsPtr->get_base(), newEnv, indexer );
     111                                newEnv.add( pointerType->forall );
     112                                newEnv.add( pointerType->base->forall );
     113                                int castResult = ptrsCastable( pointerType->base, destAsPtr->base, newEnv, indexer );
    114114                                if ( castResult > 0 ) {
    115115                                        cost = Cost::safe;
  • src/ResolvExpr/CommonType.cc

    rf9feab8 r90152a4  
    1818#include <utility>                       // for pair
    1919
     20#include "Common/PassVisitor.h"
    2021#include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
    2122#include "SymTab/Indexer.h"              // for Indexer
     
    2324#include "SynTree/Type.h"                // for BasicType, BasicType::Kind::...
    2425#include "SynTree/Visitor.h"             // for Visitor
    25 #include "Unify.h"                       // for unifyExact, bindVar, WidenMode
     26#include "Unify.h"                       // for unifyExact, WidenMode
    2627#include "typeops.h"                     // for isFtype
    2728
    2829// #define DEBUG
     30#ifdef DEBUG
     31#define PRINT(x) x
     32#else
     33#define PRINT(x)
     34#endif
    2935
    3036namespace ResolvExpr {
    31         class CommonType : public Visitor {
    32           public:
     37        struct CommonType : public WithShortCircuiting {
    3338                CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    3439                Type *get_result() const { return result; }
     40
     41                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     42
     43                void postvisit( VoidType * voidType );
     44                void postvisit( BasicType * basicType );
     45                void postvisit( PointerType * pointerType );
     46                void postvisit( ArrayType * arrayType );
     47                void postvisit( ReferenceType * refType );
     48                void postvisit( FunctionType * functionType );
     49                void postvisit( StructInstType * aggregateUseType );
     50                void postvisit( UnionInstType * aggregateUseType );
     51                void postvisit( EnumInstType * aggregateUseType );
     52                void postvisit( TraitInstType * aggregateUseType );
     53                void postvisit( TypeInstType * aggregateUseType );
     54                void postvisit( TupleType * tupleType );
     55                void postvisit( VarArgsType * varArgsType );
     56                void postvisit( ZeroType * zeroType );
     57                void postvisit( OneType * oneType );
     58
    3559          private:
    36                 virtual void visit( VoidType *voidType );
    37                 virtual void visit( BasicType *basicType );
    38                 virtual void visit( PointerType *pointerType );
    39                 virtual void visit( ArrayType *arrayType );
    40                 virtual void visit( ReferenceType *refType );
    41                 virtual void visit( FunctionType *functionType );
    42                 virtual void visit( StructInstType *aggregateUseType );
    43                 virtual void visit( UnionInstType *aggregateUseType );
    44                 virtual void visit( EnumInstType *aggregateUseType );
    45                 virtual void visit( TraitInstType *aggregateUseType );
    46                 virtual void visit( TypeInstType *aggregateUseType );
    47                 virtual void visit( TupleType *tupleType );
    48                 virtual void visit( VarArgsType *varArgsType );
    49                 virtual void visit( ZeroType *zeroType );
    50                 virtual void visit( OneType *oneType );
    51 
    5260                template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer );
    5361                template< typename RefType > void handleRefType( RefType *inst, Type *other );
     
    6775                // need unify to bind type variables
    6876                if ( unify( t1, t2, env, have, need, newOpen, indexer, common ) ) {
    69                         // std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
     77                        PRINT(
     78                                std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
     79                        )
    7080                        if ( (widenFirst || t2->get_qualifiers() <= t1->get_qualifiers()) && (widenSecond || t1->get_qualifiers() <= t2->get_qualifiers()) ) {
    71                                 // std::cerr << "widen okay" << std::endl;
     81                                PRINT(
     82                                        std::cerr << "widen okay" << std::endl;
     83                                )
    7284                                common->get_qualifiers() |= t1->get_qualifiers();
    7385                                common->get_qualifiers() |= t2->get_qualifiers();
     
    7587                        }
    7688                }
    77                 // std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
     89                PRINT(
     90                        std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
     91                )
    7892                return nullptr;
    7993        }
    8094
    8195        Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    82                 CommonType visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
     96                PassVisitor<CommonType> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
    8397
    8498                int depth1 = type1->referenceDepth();
     
    87101                        int diff = depth1-depth2;
    88102                        // TODO: should it be possible for commonType to generate complicated conversions? I would argue no, only conversions that involve types of the same reference level or a difference of 1 should be allowed.
    89                         if ( diff > 1 || diff < -1 ) return nullptr;
     103                        // if ( diff > 1 || diff < -1 ) return nullptr;
    90104
    91105                        // special case where one type has a reference depth of 1 larger than the other
    92106                        if ( diff > 0 || diff < 0 ) {
     107                                PRINT(
     108                                        std::cerr << "reference depth diff: " << diff << std::endl;
     109                                )
    93110                                Type * result = nullptr;
    94                                 if ( ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 ) ) {
    95                                         // formal is reference, so result should be reference
     111                                ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 );
     112                                ReferenceType * ref2 = dynamic_cast< ReferenceType * >( type2 );
     113                                if ( diff > 0 ) {
     114                                        // deeper on the left
     115                                        assert( ref1 );
    96116                                        result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars );
    97                                         if ( result ) result = new ReferenceType( ref1->get_qualifiers(), result );
    98117                                } else {
    99                                         // formal is value, so result should be value
    100                                         ReferenceType * ref2 = strict_dynamic_cast< ReferenceType * > ( type2 );
     118                                        // deeper on the right
     119                                        assert( ref2 );
    101120                                        result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars );
    102121                                }
    103                                 // std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl;
     122                                if ( result && ref1 ) {
     123                                        // formal is reference, so result should be reference
     124                                        PRINT(
     125                                                std::cerr << "formal is reference; result should be reference" << std::endl;
     126                                        )
     127                                        result = new ReferenceType( ref1->get_qualifiers(), result );
     128                                }
     129                                PRINT(
     130                                        std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl;
     131                                )
    104132                                return result;
    105133                        }
     
    108136
    109137                type1->accept( visitor );
    110                 Type *result = visitor.get_result();
     138                Type *result = visitor.pass.get_result();
    111139                if ( ! result ) {
    112140                        // this appears to be handling for opaque type declarations
     
    148176        }
    149177
    150         static const BasicType::Kind combinedType[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] =
     178        static const BasicType::Kind combinedType[][ BasicType::NUMBER_OF_BASIC_TYPES ] =
    151179        {
    152 /*              Bool            Char    SignedChar      UnsignedChar    ShortSignedInt  ShortUnsignedInt        SignedInt       UnsignedInt     LongSignedInt   LongUnsignedInt LongLongSignedInt       LongLongUnsignedInt     Float   Double  LongDouble      FloatComplex    DoubleComplex   LongDoubleComplex       FloatImaginary  DoubleImaginary LongDoubleImaginary   SignedInt128   UnsignedInt128 */
    153                 /* Bool */      { BasicType::Bool,              BasicType::Char,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    154                 /* Char */      { BasicType::Char,              BasicType::Char,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    155                 /* SignedChar */        { BasicType::SignedChar,        BasicType::UnsignedChar,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    156                 /* UnsignedChar */      { BasicType::UnsignedChar,      BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    157                 /* ShortSignedInt */    { BasicType::ShortSignedInt,    BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    158                 /* ShortUnsignedInt */  { BasicType::ShortUnsignedInt,  BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    159                 /* SignedInt */         { BasicType::SignedInt,         BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    160                 /* UnsignedInt */       { BasicType::UnsignedInt,               BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    161                 /* LongSignedInt */     { BasicType::LongSignedInt,             BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    162                 /* LongUnsignedInt */   { BasicType::LongUnsignedInt,   BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    163                 /* LongLongSignedInt */         { BasicType::LongLongSignedInt, BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    164                 /* LongLongUnsignedInt */       { BasicType::LongLongUnsignedInt,       BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    165                 /* Float */     { BasicType::Float,     BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Float,       BasicType::Float, },
    166                 /* Double */    { BasicType::Double,    BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::LongDouble,  BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Double,      BasicType::Double, },
    167                 /* LongDouble */        { BasicType::LongDouble,                BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDouble,  BasicType::LongDouble, },
    168                 /* FloatComplex */      { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::FloatComplex, },
    169                 /* DoubleComplex */     { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex, },
    170                 /* LongDoubleComplex */         { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex, },
    171                 /* FloatImaginary */    { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatImaginary,      BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::FloatImaginary,      BasicType::FloatImaginary, },
    172                 /* DoubleImaginary */   { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleImaginary,     BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::DoubleImaginary,     BasicType::DoubleImaginary, },
    173                 /* LongDoubleImaginary */       { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary },
    174                 /* SignedInt128 */      { BasicType::SignedInt128,      BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, },
    175                 /* UnsignedInt128 */    { BasicType::UnsignedInt128,    BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::UnsignedInt128,      BasicType::UnsignedInt128, },
     180/*              Bool            Char    SignedChar      UnsignedChar    ShortSignedInt  ShortUnsignedInt        SignedInt       UnsignedInt     LongSignedInt   LongUnsignedInt LongLongSignedInt       LongLongUnsignedInt     Float   Double  LongDouble      FloatComplex    DoubleComplex   LongDoubleComplex       FloatImaginary  DoubleImaginary LongDoubleImaginary   SignedInt128   UnsignedInt128   Float80   Float128 */
     181                /* Bool */      { BasicType::Bool,              BasicType::Char,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     182                /* Char */      { BasicType::Char,              BasicType::Char,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     183                /* SignedChar */        { BasicType::SignedChar,        BasicType::UnsignedChar,        BasicType::SignedChar,  BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     184                /* UnsignedChar */      { BasicType::UnsignedChar,      BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::UnsignedChar,        BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     185                /* ShortSignedInt */    { BasicType::ShortSignedInt,    BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortSignedInt,      BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     186                /* ShortUnsignedInt */  { BasicType::ShortUnsignedInt,  BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::ShortUnsignedInt,    BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     187                /* SignedInt */         { BasicType::SignedInt,         BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::SignedInt,   BasicType::UnsignedInt, BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     188                /* UnsignedInt */       { BasicType::UnsignedInt,               BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::UnsignedInt, BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     189                /* LongSignedInt */     { BasicType::LongSignedInt,             BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongSignedInt,       BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     190                /* LongUnsignedInt */   { BasicType::LongUnsignedInt,   BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongUnsignedInt,     BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     191                /* LongLongSignedInt */         { BasicType::LongLongSignedInt, BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongSignedInt,   BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     192                /* LongLongUnsignedInt */       { BasicType::LongLongUnsignedInt,       BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128 },
     193                /* Float */     { BasicType::Float,     BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Float,       BasicType::Float, BasicType::Float80, BasicType::Float128 },
     194                /* Double */    { BasicType::Double,    BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::Double,      BasicType::LongDouble,  BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::Double,      BasicType::Double, BasicType::Float80, BasicType::Float128 },
     195                /* LongDouble */        { BasicType::LongDouble,                BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDouble,  BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDouble,  BasicType::LongDouble, BasicType::BasicType::LongDouble, BasicType::Float128 },
     196                /* FloatComplex */      { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::FloatComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, },
     197                /* DoubleComplex */     { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex },
     198                /* LongDoubleComplex */         { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, BasicType::LongDoubleComplex, },
     199                /* FloatImaginary */    { BasicType::FloatComplex,      BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatImaginary,      BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::FloatImaginary,      BasicType::FloatImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, },
     200                /* DoubleImaginary */   { BasicType::DoubleComplex,     BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleComplex,       BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::DoubleImaginary,     BasicType::DoubleImaginary,     BasicType::LongDoubleImaginary, BasicType::DoubleImaginary,     BasicType::DoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, },
     201                /* LongDoubleImaginary */       { BasicType::LongDoubleComplex, BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, BasicType::LongDoubleImaginary, },
     202                /* SignedInt128 */      { BasicType::SignedInt128,      BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::SignedInt128,        BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::SignedInt128,        BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128, },
     203                /* UnsignedInt128 */    { BasicType::UnsignedInt128,    BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::UnsignedInt128,      BasicType::Float,       BasicType::Double,      BasicType::LongDouble,  BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::FloatComplex,        BasicType::DoubleComplex,       BasicType::LongDoubleComplex,   BasicType::UnsignedInt128,      BasicType::UnsignedInt128, BasicType::Float80, BasicType::Float128, },
     204                /* Float80 */   { BasicType::Float80,   BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::Float80,     BasicType::LongDouble,  BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::Float80,     BasicType::Float80, BasicType::Float80, BasicType::Float128 },
     205                /* Float128 */  { BasicType::Float128,  BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::Float128,    BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::LongDoubleComplex,   BasicType::Float128,    BasicType::Float128, BasicType::Float128, BasicType::Float128 },
    176206        };
     207        static_assert(
     208                sizeof(combinedType)/sizeof(combinedType[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES,
     209                "Each basic type kind should have a corresponding row in the combined type matrix"
     210        );
    177211
    178212        CommonType::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
     
    180214        }
    181215
    182         void CommonType::visit( __attribute((unused)) VoidType *voidType ) {}
    183 
    184         void CommonType::visit( BasicType *basicType ) {
     216        void CommonType::postvisit( VoidType * ) {}
     217
     218        void CommonType::postvisit( BasicType *basicType ) {
    185219                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    186220                        BasicType::Kind newType = combinedType[ basicType->get_kind() ][ otherBasic->get_kind() ];
     
    204238                                AssertionSet need, have;
    205239                                WidenMode widen( widenFirst, widenSecond );
    206                                 if ( entry != openVars.end() && ! bindVar(var, voidPointer->get_base(), entry->second, env, need, have, openVars, widen, indexer ) ) return;
     240                                if ( entry != openVars.end() && ! env.bindVar(var, voidPointer->get_base(), entry->second, need, have, openVars, widen, indexer ) ) return;
    207241                        }
    208242                }
     
    211245        }
    212246
    213         void CommonType::visit( PointerType *pointerType ) {
     247        void CommonType::postvisit( PointerType *pointerType ) {
    214248                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    215249                        // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
     
    233267                                                result = otherPointer->clone();
    234268                                        } // if
    235                                         result->get_qualifiers() = tq1 | tq2;
     269                                        strict_dynamic_cast<PointerType*>(result)->base->get_qualifiers() = tq1 | tq2;
    236270                                } else {
    237271                                        /// std::cerr << "place for ptr-to-type" << std::endl;
     
    246280        }
    247281
    248         void CommonType::visit( __attribute((unused)) ArrayType *arrayType ) {}
    249 
    250         void CommonType::visit( ReferenceType *refType ) {
     282        void CommonType::postvisit( ArrayType * ) {}
     283
     284        void CommonType::postvisit( ReferenceType *refType ) {
    251285                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    252286                        // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
     
    270304                                                result = otherRef->clone();
    271305                                        } // if
    272                                         result->get_qualifiers() = tq1 | tq2;
     306                                        strict_dynamic_cast<ReferenceType*>(result)->base->get_qualifiers() = tq1 | tq2;
    273307                                } else {
    274308                                        /// std::cerr << "place for ptr-to-type" << std::endl;
     
    283317        }
    284318
    285         void CommonType::visit( __attribute((unused)) FunctionType *functionType ) {}
    286         void CommonType::visit( __attribute((unused)) StructInstType *aggregateUseType ) {}
    287         void CommonType::visit( __attribute((unused)) UnionInstType *aggregateUseType ) {}
    288 
    289         void CommonType::visit( EnumInstType *enumInstType ) {
     319        void CommonType::postvisit( FunctionType * ) {}
     320        void CommonType::postvisit( StructInstType * ) {}
     321        void CommonType::postvisit( UnionInstType * ) {}
     322
     323        void CommonType::postvisit( EnumInstType *enumInstType ) {
    290324                if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) {
    291325                        // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
    292                         ValueGuard< Type * > temp( type2 );
    293                         type2 = enumInstType;
    294                         temp.old->accept( *this );
    295                 } // if
    296         }
    297 
    298         void CommonType::visit( __attribute((unused)) TraitInstType *aggregateUseType ) {
    299         }
    300 
    301         void CommonType::visit( TypeInstType *inst ) {
     326                        result = commonType( type2, enumInstType, widenSecond, widenFirst, indexer, env, openVars );
     327                } // if
     328        }
     329
     330        void CommonType::postvisit( TraitInstType * ) {
     331        }
     332
     333        void CommonType::postvisit( TypeInstType *inst ) {
    302334                if ( widenFirst ) {
    303335                        NamedTypeDecl *nt = indexer.lookupType( inst->get_name() );
     
    321353        }
    322354
    323         void CommonType::visit( __attribute((unused)) TupleType *tupleType ) {}
    324         void CommonType::visit( __attribute((unused)) VarArgsType *varArgsType ) {}
    325 
    326         void CommonType::visit( ZeroType *zeroType ) {
     355        void CommonType::postvisit( TupleType * ) {}
     356        void CommonType::postvisit( VarArgsType * ) {}
     357
     358        void CommonType::postvisit( ZeroType *zeroType ) {
    327359                if ( widenFirst ) {
    328360                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
     
    338370        }
    339371
    340         void CommonType::visit( OneType *oneType ) {
     372        void CommonType::postvisit( OneType *oneType ) {
    341373                if ( widenFirst ) {
    342374                        if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) {
  • src/ResolvExpr/ConversionCost.cc

    rf9feab8 r90152a4  
    4242        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    4343                if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
    44                         EqvClass eqvClass;
    45                         NamedTypeDecl *namedType;
    46                         PRINT( std::cerr << "type inst " << destAsTypeInst->get_name(); )
    47                         if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
    48                                 if ( eqvClass.type ) {
    49                                         return conversionCost( src, eqvClass.type, indexer, env );
     44                        PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
     45                        if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->name ) ) {
     46                                if ( eqvClass->type ) {
     47                                        return conversionCost( src, eqvClass->type, indexer, env );
    5048                                } else {
    5149                                        return Cost::infinity;
    5250                                }
    53                         } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) {
     51                        } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->name ) ) {
    5452                                PRINT( std::cerr << " found" << std::endl; )
    5553                                TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    5654                                // all typedefs should be gone by this point
    5755                                assert( type );
    58                                 if ( type->get_base() ) {
    59                                         return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe;
     56                                if ( type->base ) {
     57                                        return conversionCost( src, type->base, indexer, env ) + Cost::safe;
    6058                                } // if
    6159                        } // if
     
    7775                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
    7876                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    79                         return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer &){
     77                        return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
    8078                                return ptrsAssignable( t1, t2, env );
    8179                        });
    8280                } else {
    83                         ConversionCost converter( dest, indexer, env );
     81                        PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
    8482                        src->accept( converter );
    85                         if ( converter.get_cost() == Cost::infinity ) {
     83                        if ( converter.pass.get_cost() == Cost::infinity ) {
    8684                                return Cost::infinity;
    8785                        } else {
    88                                 return converter.get_cost() + Cost::zero;
     86                                return converter.pass.get_cost() + Cost::zero;
    8987                        } // if
    9088                } // if
     
    9290
    9391        Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    94                 PRINT( std::cerr << "convert to reference cost... diff " << diff << std::endl; )
     92                PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
    9593                if ( diff > 0 ) {
    9694                        // TODO: document this
    97                         Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env, func );
     95                        Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->base, dest, diff-1, indexer, env, func );
    9896                        cost.incReference();
    9997                        return cost;
    10098                } else if ( diff < -1 ) {
    10199                        // TODO: document this
    102                         Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env, func );
     100                        Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->base, diff+1, indexer, env, func );
    103101                        cost.incReference();
    104102                        return cost;
     
    108106                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
    109107                                PRINT( std::cerr << "converting between references" << std::endl; )
    110                                 if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) {
    111                                         return Cost::safe;
     108                                Type::Qualifiers tq1 = srcAsRef->base->get_qualifiers();
     109                                Type::Qualifiers tq2 = destAsRef->base->get_qualifiers();
     110                                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
     111                                        PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
     112                                        if ( tq1 == tq2 ) {
     113                                                // types are the same
     114                                                return Cost::zero;
     115                                        } else {
     116                                                // types are the same, except otherPointer has more qualifiers
     117                                                return Cost::safe;
     118                                        }
    112119                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    113                                         int assignResult = func( srcAsRef->get_base(), destAsRef->get_base(), env, indexer );
     120                                        int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env );
    114121                                        PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
    115122                                        if ( assignResult > 0 ) {
     
    121128                        } else {
    122129                                PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
    123                                 ConversionCost converter( dest, indexer, env );
     130                                PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
    124131                                src->accept( converter );
    125                                 return converter.get_cost();
     132                                return converter.pass.get_cost();
    126133                        } // if
    127134                } else {
     
    129136                        assert( diff == -1 && destAsRef );
    130137                        PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
    131                         if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
     138                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
    132139                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
    133140                                if ( src->get_lvalue() ) {
     
    137144                                        )
    138145                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
    139                                         if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) {
     146                                        if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) {
    140147                                                return Cost::reference; // cost needs to be non-zero to add cast
    141                                         } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) {
     148                                        } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) {
    142149                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
    143150                                        } else {
    144151                                                return Cost::unsafe;
    145152                                        } // if
    146                                 } else if ( destAsRef->get_base()->get_const() ) {
     153                                } else if ( destAsRef->base->get_const() ) {
    147154                                        PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
    148155                                        // rvalue-to-const-reference conversion: T => const T &
     
    161168        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    162169                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
    163                 return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env, func );
    164         }
    165 
    166         ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )
    167                 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ) {
     170                Cost cost = convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env, func );
     171                PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; )
     172                return cost;
     173        }
     174
     175        ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
     176                : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
    168177        }
    169178
     
    219228*/
    220229
    221         static const int costMatrix[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] = {
    222         /* Src \ Dest:  Bool    Char    SChar   UChar   Short   UShort  Int     UInt    Long    ULong   LLong   ULLong  Float   Double  LDbl    FCplex  DCplex  LDCplex FImag   DImag   LDImag  I128,   U128 */
    223                 /* Bool */      { 0,    1,              1,              2,              3,              4,              5,              6,              6,              7,              8,              9,              12,             13,             14,             12,             13,             14,             -1,             -1,             -1,             10,             11,     },
    224                 /* Char */      { -1,   0,              -1,             1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,     },
    225                 /* SChar */ { -1,       -1,             0,              1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,     },
    226                 /* UChar */ { -1,       -1,             -1,             0,              1,              2,              3,              4,              4,              5,              6,              7,              10,             11,             12,             10,             11,             12,             -1,             -1,             -1,             8,              9,      },
    227                 /* Short */ { -1,       -1,             -1,             -1,             0,              1,              2,              3,              3,              4,              5,              6,              9,              10,             11,             9,              10,             11,             -1,             -1,             -1,             7,              8,      },
    228                 /* UShort */{ -1,       -1,             -1,             -1,             -1,             0,              1,              2,              2,              3,              4,              5,              8,              9,              10,             8,              9,              10,             -1,             -1,             -1,             6,              7,      },
    229                 /* Int */       { -1,   -1,             -1,             -1,             -1,             -1,             0,              1,              1,              2,              3,              4,              7,              8,              9,              7,              8,              9,              -1,             -1,             -1,             5,              6,      },
    230                 /* UInt */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,      },
    231                 /* Long */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,      },
    232                 /* ULong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              5,              6,              7,              5,              6,              7,              -1,             -1,             -1,             3,              4,      },
    233                 /* LLong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              4,              5,              6,              4,              5,              6,              -1,             -1,             -1,             2,              3,      },
    234                 /* ULLong */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              3,              4,              5,              3,              4,              5,              -1,             -1,             -1,             1,              2,      },
    235 
    236                 /* Float */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              1,              2,              3,              -1,             -1,             -1,             -1,             -1,     },
    237                 /* Double */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             1,              2,              -1,             -1,             -1,             -1,             -1,     },
    238                 /* LDbl */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,     },
    239                 /* FCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              -1,             -1,             -1,             -1,             -1,     },
    240                 /* DCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             -1,             -1,             -1,             -1,     },
    241                 /* LDCplex */{ -1,      -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             -1,             -1,             -1,     },
    242                 /* FImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              0,              1,              2,              -1,             -1,     },
    243                 /* DImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              -1,             0,              1,              -1,             -1,     },
    244                 /* LDImag */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             0,              -1,             -1,     },
    245 
    246                 /* I128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             2,              3,              4,              3,              4,              5,              -1,             -1,             -1,             0,              1,      },
    247                 /* U128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              2,              3,              4,              -1,             -1,             -1,             -1,             0,      },
     230        static const int costMatrix[][ BasicType::NUMBER_OF_BASIC_TYPES ] = {
     231        /* Src \ Dest:  Bool    Char    SChar   UChar   Short   UShort  Int     UInt    Long    ULong   LLong   ULLong  Float   Double  LDbl    FCplex  DCplex  LDCplex FImag   DImag   LDImag  I128,   U128, F80, F128 */
     232                /* Bool */      { 0,    1,              1,              2,              3,              4,              5,              6,              6,              7,              8,              9,              12,             13,             14,             12,             13,             14,             -1,             -1,             -1,             10,             11,       14,   15},
     233                /* Char */      { -1,   0,              -1,             1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,       13,   14},
     234                /* SChar */ { -1,       -1,             0,              1,              2,              3,              4,              5,              5,              6,              7,              8,              11,             12,             13,             11,             12,             13,             -1,             -1,             -1,             9,              10,       13,   14},
     235                /* UChar */ { -1,       -1,             -1,             0,              1,              2,              3,              4,              4,              5,              6,              7,              10,             11,             12,             10,             11,             12,             -1,             -1,             -1,             8,              9,        12,   13},
     236                /* Short */ { -1,       -1,             -1,             -1,             0,              1,              2,              3,              3,              4,              5,              6,              9,              10,             11,             9,              10,             11,             -1,             -1,             -1,             7,              8,        11,   12},
     237                /* UShort */{ -1,       -1,             -1,             -1,             -1,             0,              1,              2,              2,              3,              4,              5,              8,              9,              10,             8,              9,              10,             -1,             -1,             -1,             6,              7,        10,   11},
     238                /* Int */       { -1,   -1,             -1,             -1,             -1,             -1,             0,              1,              1,              2,              3,              4,              7,              8,              9,              7,              8,              9,              -1,             -1,             -1,             5,              6,        9,    10},
     239                /* UInt */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,        8,    9},
     240                /* Long */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              6,              7,              8,              6,              7,              8,              -1,             -1,             -1,             4,              5,        8,    9},
     241                /* ULong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              5,              6,              7,              5,              6,              7,              -1,             -1,             -1,             3,              4,        7,    8},
     242                /* LLong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              4,              5,              6,              4,              5,              6,              -1,             -1,             -1,             2,              3,        6,    7},
     243                /* ULLong */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              3,              4,              5,              3,              4,              5,              -1,             -1,             -1,             1,              2,        5,    6},
     244
     245                /* Float */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              1,              2,              3,              -1,             -1,             -1,             -1,             -1,       2,    3},
     246                /* Double */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             1,              2,              -1,             -1,             -1,             -1,             -1,       1,    2},
     247                /* LDbl */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,       -1,   1},
     248                /* FCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              -1,             -1,             -1,             -1,             -1,       -1,   -1},
     249                /* DCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             -1,             -1,             -1,             -1,       -1,   -1},
     250                /* LDCplex */{ -1,      -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             -1,             -1,             -1,       -1,   -1},
     251                /* FImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              0,              1,              2,              -1,             -1,       -1,   -1},
     252                /* DImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              -1,             0,              1,              -1,             -1,       -1,   -1},
     253                /* LDImag */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             0,              -1,             -1,       -1,   -1},
     254
     255                /* I128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             2,              3,              4,              3,              4,              5,              -1,             -1,             -1,             0,              1,        4,    4},
     256                /* U128 */  { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              2,              3,              4,              -1,             -1,             -1,             -1,             0,        3,    3},
     257
     258                /* F80 */       { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,       0,    1},
     259                /* F128 */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             -1,             -1,             -1,       -1,   0},
    248260        };
    249 
    250         void ConversionCost::visit( __attribute((unused)) VoidType *voidType ) {
     261        static_assert(
     262                sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES,
     263                "Each basic type kind should have a corresponding row in the cost matrix"
     264        );
     265
     266
     267        void ConversionCost::postvisit( VoidType * ) {
    251268                cost = Cost::infinity;
    252269        }
    253270
    254         void ConversionCost::visit(BasicType *basicType) {
     271        void ConversionCost::postvisit(BasicType *basicType) {
    255272                if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
    256273                        int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
     
    264281                        // xxx - not positive this is correct, but appears to allow casting int => enum
    265282                        cost = Cost::unsafe;
    266                 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
    267                         cost = Cost::unsafe;
    268                 } // if
    269         }
    270 
    271         void ConversionCost::visit( PointerType * pointerType ) {
     283                } // if
     284                // no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
     285        }
     286
     287        void ConversionCost::postvisit( PointerType * pointerType ) {
    272288                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    273                         PRINT( std::cerr << pointerType << " ===> " << destAsPtr; )
    274                         Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers();
    275                         Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers();
    276                         if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
     289                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
     290                        Type::Qualifiers tq1 = pointerType->base->get_qualifiers();
     291                        Type::Qualifiers tq2 = destAsPtr->base->get_qualifiers();
     292                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
     293                                PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    277294                                if ( tq1 == tq2 ) {
    278295                                        // types are the same
     
    280297                                } else {
    281298                                        // types are the same, except otherPointer has more qualifiers
    282                                         PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    283299                                        cost = Cost::safe;
    284300                                }
    285                         } else {  // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
     301                        } else {
    286302                                int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
    287303                                PRINT( std::cerr << " :: " << assignResult << std::endl; )
    288                                 if ( assignResult > 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {
    289                                         cost = Cost::safe;
     304                                if ( assignResult > 0 && tq1 <= tq2 ) {
     305                                        // xxx - want the case where qualifiers are added to be more expensive than the case where qualifiers are the same. Is 1 safe vs. 2 safe correct?
     306                                        if ( tq1 == tq2 ) {
     307                                                cost = Cost::safe;
     308                                        } else if ( tq1 < tq2 ) {
     309                                                cost = Cost::safe+Cost::safe;
     310                                        }
    290311                                } else if ( assignResult < 0 ) {
    291312                                        cost = Cost::unsafe;
     
    293314                                // assignResult == 0 means Cost::Infinity
    294315                        } // if
    295                 } else if ( dynamic_cast< ZeroType * >( dest ) ) {
    296                         cost = Cost::unsafe;
    297                 } // if
    298         }
    299 
    300         void ConversionCost::visit( ArrayType * ) {}
    301 
    302         void ConversionCost::visit( ReferenceType * refType ) {
     316                        // case case for zero_t because it should not be possible to convert pointers to zero_t.
     317                } // if
     318        }
     319
     320        void ConversionCost::postvisit( ArrayType * ) {}
     321
     322        void ConversionCost::postvisit( ReferenceType * refType ) {
    303323                // Note: dest can never be a reference, since it would have been caught in an earlier check
    304324                assert( ! dynamic_cast< ReferenceType * >( dest ) );
     
    306326                // recursively compute conversion cost from T1 to T2.
    307327                // cv can be safely dropped because of 'implicit dereference' behavior.
    308                 refType->base->accept( *this );
     328                cost = costFunc( refType->base, dest, indexer, env );
    309329                if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) {
    310330                        cost.incReference();  // prefer exact qualifiers
     
    317337        }
    318338
    319         void ConversionCost::visit( FunctionType * ) {}
    320 
    321         void ConversionCost::visit( StructInstType * inst ) {
     339        void ConversionCost::postvisit( FunctionType * ) {}
     340
     341        void ConversionCost::postvisit( StructInstType * inst ) {
    322342                if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
    323343                        if ( inst->name == destAsInst->name ) {
     
    327347        }
    328348
    329         void ConversionCost::visit( UnionInstType * inst ) {
     349        void ConversionCost::postvisit( UnionInstType * inst ) {
    330350                if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) {
    331351                        if ( inst->name == destAsInst->name ) {
     
    335355        }
    336356
    337         void ConversionCost::visit( EnumInstType * ) {
     357        void ConversionCost::postvisit( EnumInstType * ) {
    338358                static Type::Qualifiers q;
    339359                static BasicType integer( q, BasicType::SignedInt );
    340                 integer.accept( *this );  // safe if dest >= int
     360                cost = costFunc( &integer, dest, indexer, env );  // safe if dest >= int
    341361                if ( cost < Cost::unsafe ) {
    342362                        cost.incSafe();
     
    344364        }
    345365
    346         void ConversionCost::visit( TraitInstType * ) {}
    347 
    348         void ConversionCost::visit( TypeInstType *inst ) {
    349                 EqvClass eqvClass;
    350                 NamedTypeDecl *namedType;
    351                 if ( env.lookup( inst->get_name(), eqvClass ) ) {
    352                         cost = conversionCost( eqvClass.type, dest, indexer, env );
     366        void ConversionCost::postvisit( TraitInstType * ) {}
     367
     368        void ConversionCost::postvisit( TypeInstType *inst ) {
     369                if ( const EqvClass *eqvClass = env.lookup( inst->name ) ) {
     370                        cost = costFunc( eqvClass->type, dest, indexer, env );
    353371                } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) {
    354                         if ( inst->get_name() == destAsInst->get_name() ) {
     372                        if ( inst->name == destAsInst->name ) {
    355373                                cost = Cost::zero;
    356374                        }
    357                 } else if ( ( namedType = indexer.lookupType( inst->get_name() ) ) ) {
     375                } else if ( NamedTypeDecl *namedType = indexer.lookupType( inst->name ) ) {
    358376                        TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
    359377                        // all typedefs should be gone by this point
    360378                        assert( type );
    361                         if ( type->get_base() ) {
    362                                 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;
    363                         } // if
    364                 } // if
    365         }
    366 
    367         void ConversionCost::visit( TupleType * tupleType ) {
     379                        if ( type->base ) {
     380                                cost = costFunc( type->base, dest, indexer, env ) + Cost::safe;
     381                        } // if
     382                } // if
     383        }
     384
     385        void ConversionCost::postvisit( TupleType * tupleType ) {
    368386                Cost c = Cost::zero;
    369387                if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) {
    370                         std::list< Type * >::const_iterator srcIt = tupleType->get_types().begin();
    371                         std::list< Type * >::const_iterator destIt = destAsTuple->get_types().begin();
    372                         while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) {
    373                                 Cost newCost = conversionCost( *srcIt++, *destIt++, indexer, env );
     388                        std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
     389                        std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
     390                        while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
     391                                Cost newCost = costFunc( *srcIt++, *destIt++, indexer, env );
    374392                                if ( newCost == Cost::infinity ) {
    375393                                        return;
     
    377395                                c += newCost;
    378396                        } // while
    379                         if ( destIt != destAsTuple->get_types().end() ) {
     397                        if ( destIt != destAsTuple->types.end() ) {
    380398                                cost = Cost::infinity;
    381399                        } else {
     
    385403        }
    386404
    387         void ConversionCost::visit( VarArgsType * ) {
     405        void ConversionCost::postvisit( VarArgsType * ) {
    388406                if ( dynamic_cast< VarArgsType* >( dest ) ) {
    389407                        cost = Cost::zero;
     
    391409        }
    392410
    393         void ConversionCost::visit( ZeroType * ) {
     411        void ConversionCost::postvisit( ZeroType * ) {
    394412                if ( dynamic_cast< ZeroType * >( dest ) ) {
    395413                        cost = Cost::zero;
     
    408426        }
    409427
    410         void ConversionCost::visit( OneType * ) {
     428        void ConversionCost::postvisit( OneType * ) {
    411429                if ( dynamic_cast< OneType * >( dest ) ) {
    412430                        cost = Cost::zero;
  • src/ResolvExpr/ConversionCost.h

    rf9feab8 r90152a4  
    1919
    2020#include "Cost.h"             // for Cost
     21
     22#include "Common/PassVisitor.h"
    2123#include "SynTree/Visitor.h"  // for Visitor
    2224#include "SynTree/SynTree.h"  // for Visitor Nodes
     
    2931        class TypeEnvironment;
    3032
    31         class ConversionCost : public Visitor {
     33        typedef std::function<Cost(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> CostFunction;
     34        struct ConversionCost : public WithShortCircuiting {
    3235          public:
    33                 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
     36                ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction );
    3437
    3538                Cost get_cost() const { return cost; }
    3639
    37                 virtual void visit(VoidType *voidType);
    38                 virtual void visit(BasicType *basicType);
    39                 virtual void visit(PointerType *pointerType);
    40                 virtual void visit(ArrayType *arrayType);
    41                 virtual void visit(ReferenceType *refType);
    42                 virtual void visit(FunctionType *functionType);
    43                 virtual void visit(StructInstType *aggregateUseType);
    44                 virtual void visit(UnionInstType *aggregateUseType);
    45                 virtual void visit(EnumInstType *aggregateUseType);
    46                 virtual void visit(TraitInstType *aggregateUseType);
    47                 virtual void visit(TypeInstType *aggregateUseType);
    48                 virtual void visit(TupleType *tupleType);
    49                 virtual void visit(VarArgsType *varArgsType);
    50                 virtual void visit(ZeroType *zeroType);
    51                 virtual void visit(OneType *oneType);
     40                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     41
     42                void postvisit( VoidType * voidType );
     43                void postvisit( BasicType * basicType );
     44                void postvisit( PointerType * pointerType );
     45                void postvisit( ArrayType * arrayType );
     46                void postvisit( ReferenceType * refType );
     47                void postvisit( FunctionType * functionType );
     48                void postvisit( StructInstType * aggregateUseType );
     49                void postvisit( UnionInstType * aggregateUseType );
     50                void postvisit( EnumInstType * aggregateUseType );
     51                void postvisit( TraitInstType * aggregateUseType );
     52                void postvisit( TypeInstType * aggregateUseType );
     53                void postvisit( TupleType * tupleType );
     54                void postvisit( VarArgsType * varArgsType );
     55                void postvisit( ZeroType * zeroType );
     56                void postvisit( OneType * oneType );
    5257          protected:
    5358                Type *dest;
     
    5560                Cost cost;
    5661                const TypeEnvironment &env;
     62                CostFunction costFunc;
    5763        };
    5864
    59         typedef std::function<int(Type *, Type *, const TypeEnvironment &, const SymTab::Indexer &)> PtrsFunction;
     65        typedef std::function<int(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction;
    6066        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
    6167} // namespace ResolvExpr
  • src/ResolvExpr/CurrentObject.cc

    rf9feab8 r90152a4  
    3838
    3939namespace ResolvExpr {
    40         long long int getConstValue( ConstantExpr * constExpr ) {
    41                 if ( BasicType * basicType = dynamic_cast< BasicType * >( constExpr->get_result() ) ) {
    42                         if ( basicType->isInteger() ) {
    43                                 return constExpr->get_constant()->get_ival();
    44                         } else {
    45                                 assertf( false, "Non-integer constant expression in getConstValue %s", toString( constExpr ).c_str() ); // xxx - might be semantic error
    46                         }
    47                 } else if ( dynamic_cast< OneType * >( constExpr->get_result() ) ) {
    48                         return 1;
    49                 } else if ( dynamic_cast< ZeroType * >( constExpr->get_result() ) ) {
    50                         return 0;
    51                 } else {
    52                         assertf( false, "unhandled type on getConstValue %s", toString( constExpr->get_result() ).c_str() ); // xxx - might be semantic error
    53                 }
    54         }
    55 
    5640        template< typename AggrInst >
    5741        TypeSubstitution makeGenericSubstitution( AggrInst * inst ) {
     
    7862                virtual ~MemberIterator() {}
    7963
     64                /// walks the current object using the given designators as a guide
    8065                virtual void setPosition( std::list< Expression * > & designators ) = 0;
     66
     67                /// retrieve the list of possible Type/Designaton pairs for the current position in the currect object
    8168                virtual std::list<InitAlternative> operator*() const = 0;
     69
     70                /// true if the iterator is not currently at the end
    8271                virtual operator bool() const = 0;
     72
     73                /// moves the iterator by one member in the current object
    8374                virtual MemberIterator & bigStep() = 0;
     75
     76                /// moves the iterator by one member in the current subobject
    8477                virtual MemberIterator & smallStep() = 0;
     78
     79                /// the type of the current object
    8580                virtual Type * getType() = 0;
     81
     82                /// the type of the current subobject
    8683                virtual Type * getNext() = 0;
    8784
     85                /// printing for debug
    8886                virtual void print( std::ostream & out, Indenter indent ) const = 0;
    8987
     88                /// helper for operator*; aggregates must add designator to each init alternative, but
     89                /// adding designators in operator* creates duplicates.
    9090                virtual std::list<InitAlternative> first() const = 0; // should be protected
    9191        };
     
    139139                ArrayIterator( ArrayType * at ) : array( at ) {
    140140                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    141                         base = at->get_base();
     141                        base = at->base;
    142142                        memberIter = createMemberIterator( base );
    143                         setSize( at->get_dimension() );
     143                        if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=: " );
     144                        setSize( at->dimension );
    144145                }
    145146
     
    149150
    150151        private:
    151                 void setSize( Expression * expr ) {
    152                         if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
    153                                 size = getConstValue( constExpr );
    154                                 PRINT( std::cerr << "array type with size: " << size << std::endl; )
    155                         }       else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    156                                 setSize( castExpr->get_arg() ); // xxx - need to perform the conversion specified by the cast
     152                void setSize( Expression * expr ) { // replace this logic with an eval call
     153                        auto res = eval(expr);
     154                        if (res.second) {
     155                                size = res.first;
    157156                        } else {
    158                                 assertf( false, "unhandled expression in setSize: %s", toString( expr ).c_str() ); // xxx - if not a constant expression, it's not simple to determine how long the array actually is, which is necessary for initialization to be done correctly -- fix this
     157                                SemanticError( expr->location, toString("Array designator must be a constant expression: ", expr) );
    159158                        }
    160159                }
     
    164163                        // need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions
    165164                        if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
    166                                 index = getConstValue( constExpr );
     165                                try {
     166                                        index = constExpr->intValue();
     167                                } catch( SemanticErrorException & ) {
     168                                        SemanticError( expr, "Constant expression of non-integral type in array designator: " );
     169                                }
    167170                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    168171                                setPosition( castExpr->get_arg() );
    169172                        } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
    170                                 assertf( dynamic_cast<EnumInstType *> ( varExpr->get_result() ), "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() );
    171                                 index = 0; // xxx - get actual value of enum constant
     173                                EnumInstType * inst = dynamic_cast<EnumInstType *>( varExpr->get_result() );
     174                                assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() );
     175                                long long int value;
     176                                if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
     177                                        index = value;
     178                                }
    172179                        } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) {
    173180                                index = 0; // xxx - get actual sizeof/alignof value?
     
    350357                                }
    351358                        }
    352                         // if ( curMember == std::next( decl->get_members().begin(), 1 ) ) { // xxx - this never triggers because curMember is incremented immediately on construction
    353                         if ( atbegin ) { // xxx - this never triggers because curMember is incremented immediately on construction
     359                        if ( atbegin ) {
    354360                                // xxx - what about case of empty struct??
    355361                                // only add self if at the very beginning of the structure
     
    385391                        return *this;
    386392                }
    387                 virtual std::list<InitAlternative> first() const { return std::list<InitAlternative>{}; }
    388393        };
    389394
     
    439444                                return new UnionIterator( uit );
    440445                        } else {
    441                                 assertf( dynamic_cast< TypeInstType * >( type ), "some other reftotype" );
     446                                assertf( dynamic_cast< EnumInstType * >( type ) || dynamic_cast< TypeInstType * >( type ), "Encountered unhandled ReferenceToType in createMemberIterator: %s", toString( type ).c_str() );
    442447                                return new SimpleIterator( type );
    443448                        }
     
    514519                } // for
    515520                if ( desigAlts.size() > 1 ) {
    516                         throw SemanticError( toString("Too many alternatives (", desigAlts.size(), ") for designation: "), designation );
     521                        SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
    517522                } else if ( desigAlts.size() == 0 ) {
    518                         throw SemanticError( "No reasonable alternatives for designation: ", designation );
     523                        SemanticError( designation, "No reasonable alternatives for designation: " );
    519524                }
    520525                DesignatorChain & d = desigAlts.back();
  • src/ResolvExpr/ExplodedActual.h

    rf9feab8 r90152a4  
    3232
    3333                ExplodedActual() : env(), cost(Cost::zero), exprs() {}
    34 
    3534                ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer );
     35                ExplodedActual(ExplodedActual&&) = default;
     36                ExplodedActual& operator= (ExplodedActual&&) = default;
    3637        };
    3738}
  • src/ResolvExpr/FindOpenVars.cc

    rf9feab8 r90152a4  
    1919#include <map>                    // for map<>::mapped_type
    2020
     21#include "Common/PassVisitor.h"
    2122#include "SynTree/Declaration.h"  // for TypeDecl, DeclarationWithType (ptr ...
    2223#include "SynTree/Type.h"         // for Type, Type::ForallList, ArrayType
    23 #include "SynTree/Visitor.h"      // for Visitor
    2424
    2525namespace ResolvExpr {
    26         class FindOpenVars : public Visitor {
    27           public:
     26        struct FindOpenVars : public WithGuards {
    2827                FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    2928
    30           private:
    31                 virtual void visit(PointerType *pointerType);
    32                 virtual void visit(ArrayType *arrayType);
    33                 virtual void visit(FunctionType *functionType);
    34                 virtual void visit(TupleType *tupleType);
     29                void previsit( PointerType * pointerType );
     30                void previsit( ArrayType * arrayType );
     31                void previsit( FunctionType * functionType );
     32                void previsit( TupleType * tupleType );
    3533
    3634                void common_action( Type *type );
     
    4240
    4341        void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
    44                 FindOpenVars finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
     42                PassVisitor<FindOpenVars> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
    4543                type->accept( finder );
    4644        }
     
    7068                        } // for
    7169                } // if
    72 ///   std::cout << "type is ";
    73 ///   type->print( std::cout );
    74 ///   std::cout << std::endl << "need is" << std::endl;
    75 ///   printAssertionSet( needAssertions, std::cout );
    76 ///   std::cout << std::endl << "have is" << std::endl;
    77 ///   printAssertionSet( haveAssertions, std::cout );
     70///   std::cerr << "type is ";
     71///   type->print( std::cerr );
     72///   std::cerr << std::endl << "need is" << std::endl;
     73///   printAssertionSet( needAssertions, std::cerr );
     74///   std::cerr << std::endl << "have is" << std::endl;
     75///   printAssertionSet( haveAssertions, std::cerr );
    7876        }
    7977
    80         void FindOpenVars::visit(PointerType *pointerType) {
     78        void FindOpenVars::previsit(PointerType *pointerType) {
    8179                common_action( pointerType );
    82                 Visitor::visit( pointerType );
    8380        }
    8481
    85         void FindOpenVars::visit(ArrayType *arrayType) {
     82        void FindOpenVars::previsit(ArrayType *arrayType) {
    8683                common_action( arrayType );
    87                 Visitor::visit( arrayType );
    8884        }
    8985
    90         void FindOpenVars::visit(FunctionType *functionType) {
     86        void FindOpenVars::previsit(FunctionType *functionType) {
    9187                common_action( functionType );
    9288                nextIsOpen = ! nextIsOpen;
    93                 Visitor::visit( functionType );
    94                 nextIsOpen = ! nextIsOpen;
     89                GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } );
    9590        }
    9691
    97         void FindOpenVars::visit(TupleType *tupleType) {
     92        void FindOpenVars::previsit(TupleType *tupleType) {
    9893                common_action( tupleType );
    99                 Visitor::visit( tupleType );
    10094        }
    10195} // namespace ResolvExpr
  • src/ResolvExpr/Occurs.cc

    rf9feab8 r90152a4  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Occurs.cc -- 
     7// Occurs.cc --
    88//
    99// Author           : Richard C. Bilson
     
    1717#include <string>             // for string
    1818
     19#include "Common/PassVisitor.h"
    1920#include "SynTree/Type.h"     // for TypeInstType, Type
    20 #include "SynTree/Visitor.h"  // for Visitor
    2121#include "TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    2222
    2323namespace ResolvExpr {
    24         class Occurs : public Visitor {
    25           public:
     24        struct Occurs : public WithVisitorRef<Occurs> {
    2625                Occurs( std::string varName, const TypeEnvironment &env );
    27                 bool get_result() const { return result; }
    28                 virtual void visit( TypeInstType *typeInst );
    29           private:
     26                void previsit( TypeInstType * typeInst );
     27
    3028                bool result;
    3129                std::set< std::string > eqvVars;
    32                 const TypeEnvironment &env;
     30                const TypeEnvironment &tenv;
    3331        };
    3432
    3533        bool occurs( Type *type, std::string varName, const TypeEnvironment &env ) {
    36                 Occurs occur( varName, env );
     34                PassVisitor<Occurs> occur( varName, env );
    3735                type->accept( occur );
    38                 return occur.get_result();
     36                return occur.pass.result;
    3937        }
    4038
    41         Occurs::Occurs( std::string varName, const TypeEnvironment &env ) : result( false ), env( env ) {
    42                 EqvClass eqvClass;
    43                 if ( env.lookup( varName, eqvClass ) ) {
    44                         eqvVars = eqvClass.vars;
     39        Occurs::Occurs( std::string varName, const TypeEnvironment & env ) : result( false ), tenv( env ) {
     40                if ( const EqvClass *eqvClass = tenv.lookup( varName ) ) {
     41                        eqvVars = eqvClass->vars;
    4542                } else {
    4643                        eqvVars.insert( varName );
     
    4845        }
    4946
    50         void Occurs::visit( TypeInstType *typeInst ) {
    51                 EqvClass eqvClass;
    52 ///   std::cout << "searching for vars: ";
    53 ///   std::copy( eqvVars.begin(), eqvVars.end(), std::ostream_iterator< std::string >( std::cout, " " ) );
    54 ///   std::cout << std::endl;
     47        void Occurs::previsit( TypeInstType * typeInst ) {
     48                ///   std::cerr << "searching for vars: ";
     49///   std::copy( eqvVars.begin(), eqvVars.end(), std::ostream_iterator< std::string >( std::cerr, " " ) );
     50///   std::cerr << std::endl;
    5551                if ( eqvVars.find( typeInst->get_name() ) != eqvVars.end() ) {
    5652                        result = true;
    57                 } else if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
    58                         if ( eqvClass.type ) {
    59 ///       std::cout << typeInst->get_name() << " is bound to";
    60 ///       eqvClass.type->print( std::cout );
    61 ///       std::cout << std::endl;
    62                                 eqvClass.type->accept( *this );
     53                } else if ( const EqvClass *eqvClass = tenv.lookup( typeInst->get_name() ) ) {
     54                        if ( eqvClass->type ) {
     55///       std::cerr << typeInst->get_name() << " is bound to";
     56///       eqvClass.type->print( std::cerr );
     57///       std::cerr << std::endl;
     58                                eqvClass->type->accept( *visitor );
    6359                        } // if
    6460                } // if
  • src/ResolvExpr/PolyCost.cc

    rf9feab8 r90152a4  
    1414//
    1515
     16#include "Common/PassVisitor.h"
    1617#include "SymTab/Indexer.h"   // for Indexer
    1718#include "SynTree/Type.h"     // for TypeInstType, Type
    18 #include "SynTree/Visitor.h"  // for Visitor
    1919#include "TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    2020
    2121namespace ResolvExpr {
    22         class PolyCost : public Visitor {
    23           public:
     22        struct PolyCost {
    2423                PolyCost( const TypeEnvironment &env, const SymTab::Indexer &indexer );
    25                 int get_result() const { return result; }
    26           private:
    27                 virtual void visit(TypeInstType *aggregateUseType);
     24
     25                void previsit( TypeInstType * aggregateUseType );
    2826                int result;
    29                 const TypeEnvironment &env;
     27                const TypeEnvironment &tenv;
    3028                const SymTab::Indexer &indexer;
    3129        };
    3230
    3331        int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) {
    34                 PolyCost coster( env, indexer );
     32                PassVisitor<PolyCost> coster( env, indexer );
    3533                type->accept( coster );
    36                 return coster.get_result();
     34                return coster.pass.result;
    3735        }
    3836
    39         PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), env( env ), indexer( indexer ) {
     37        PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), tenv( env ), indexer( indexer ) {
    4038        }
    4139
    42         void PolyCost::visit(TypeInstType * typeInst) {
    43                 EqvClass eqvClass;
    44                 if ( env.lookup( typeInst->name, eqvClass ) ) {
    45                         if ( eqvClass.type ) {
    46                                 if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass.type ) ) {
     40        void PolyCost::previsit(TypeInstType * typeInst) {
     41                if ( const EqvClass *eqvClass = tenv.lookup( typeInst->name ) ) {
     42                        if ( eqvClass->type ) {
     43                                if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass->type ) ) {
    4744                                        if ( indexer.lookupType( otherTypeInst->name ) ) {
    4845                                                // bound to opaque type
  • src/ResolvExpr/PtrsAssignable.cc

    rf9feab8 r90152a4  
    1414//
    1515
     16#include "Common/PassVisitor.h"
    1617#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    1718#include "SynTree/Type.h"                // for TypeInstType, Type, BasicType
     
    2021
    2122namespace ResolvExpr {
    22         class PtrsAssignable : public Visitor {
    23           public:
     23        struct PtrsAssignable : public WithShortCircuiting {
    2424                PtrsAssignable( Type *dest, const TypeEnvironment &env );
    2525
    2626                int get_result() const { return result; }
    2727
    28                 virtual void visit( VoidType *voidType );
    29                 virtual void visit( BasicType *basicType );
    30                 virtual void visit( PointerType *pointerType );
    31                 virtual void visit( ArrayType *arrayType );
    32                 virtual void visit( FunctionType *functionType );
    33                 virtual void visit( StructInstType *inst );
    34                 virtual void visit( UnionInstType *inst );
    35                 virtual void visit( EnumInstType *inst );
    36                 virtual void visit( TraitInstType *inst );
    37                 virtual void visit( TypeInstType *inst );
    38                 virtual void visit( TupleType *tupleType );
    39                 virtual void visit( VarArgsType *varArgsType );
    40                 virtual void visit( ZeroType *zeroType );
    41                 virtual void visit( OneType *oneType );
     28                void previsit( Type * ) { visit_children = false; }
     29
     30                void postvisit( VoidType * voidType );
     31                void postvisit( BasicType * basicType );
     32                void postvisit( PointerType * pointerType );
     33                void postvisit( ArrayType * arrayType );
     34                void postvisit( FunctionType * functionType );
     35                void postvisit( StructInstType * inst );
     36                void postvisit( UnionInstType * inst );
     37                void postvisit( EnumInstType * inst );
     38                void postvisit( TraitInstType * inst );
     39                void postvisit( TypeInstType * inst );
     40                void postvisit( TupleType * tupleType );
     41                void postvisit( VarArgsType * varArgsType );
     42                void postvisit( ZeroType * zeroType );
     43                void postvisit( OneType * oneType );
    4244          private:
    4345                Type *dest;
     
    4951                // std::cerr << "assignable: " << src << " | " << dest << std::endl;
    5052                if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
    51                         EqvClass eqvClass;
    52                         if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
    53                                 return ptrsAssignable( src, eqvClass.type, env );
     53                        if ( const EqvClass *eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
     54                                return ptrsAssignable( src, eqvClass->type, env );
    5455                        } // if
    5556                } // if
     
    5960                        return -1;
    6061                } else {
    61                         PtrsAssignable ptrs( dest, env );
     62                        PassVisitor<PtrsAssignable> ptrs( dest, env );
    6263                        src->accept( ptrs );
    63                         return ptrs.get_result();
     64                        return ptrs.pass.get_result();
    6465                } // if
    6566        }
     
    6768        PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
    6869
    69         void PtrsAssignable::visit( __attribute((unused)) VoidType *voidType ) {
     70        void PtrsAssignable::postvisit( VoidType * ) {
    7071                // T * = void * is disallowed - this is a change from C, where any
    7172                // void * can be assigned or passed to a non-void pointer without a cast.
    7273        }
    7374
    74         void PtrsAssignable::visit( __attribute__((unused)) BasicType *basicType ) {}
    75         void PtrsAssignable::visit( __attribute__((unused)) PointerType *pointerType ) {}
    76         void PtrsAssignable::visit( __attribute__((unused)) ArrayType *arrayType ) {}
    77         void PtrsAssignable::visit( __attribute__((unused)) FunctionType *functionType ) {}
     75        void PtrsAssignable::postvisit( __attribute__((unused)) BasicType *basicType ) {}
     76        void PtrsAssignable::postvisit( __attribute__((unused)) PointerType *pointerType ) {}
     77        void PtrsAssignable::postvisit( __attribute__((unused)) ArrayType *arrayType ) {}
     78        void PtrsAssignable::postvisit( __attribute__((unused)) FunctionType *functionType ) {}
    7879
    79         void PtrsAssignable::visit(  __attribute__((unused)) StructInstType *inst ) {}
    80         void PtrsAssignable::visit(  __attribute__((unused)) UnionInstType *inst ) {}
     80        void PtrsAssignable::postvisit(  __attribute__((unused)) StructInstType *inst ) {}
     81        void PtrsAssignable::postvisit(  __attribute__((unused)) UnionInstType *inst ) {}
    8182
    82         void PtrsAssignable::visit( EnumInstType * ) {
     83        void PtrsAssignable::postvisit( EnumInstType * ) {
    8384                if ( dynamic_cast< BasicType* >( dest ) ) {
    8485                        // int * = E *, etc. is safe. This isn't technically correct, as each
     
    9192        }
    9293
    93         void PtrsAssignable::visit(  __attribute__((unused)) TraitInstType *inst ) {}
    94         void PtrsAssignable::visit( TypeInstType *inst ) {
    95                 EqvClass eqvClass;
    96                 if ( env.lookup( inst->get_name(), eqvClass ) && eqvClass.type ) {
    97                         // T * = S * for any S depends on the type bound to T
    98                         result = ptrsAssignable( eqvClass.type, dest, env );
     94        void PtrsAssignable::postvisit(  __attribute__((unused)) TraitInstType *inst ) {}
     95        void PtrsAssignable::postvisit( TypeInstType *inst ) {
     96                if ( const EqvClass *eqvClass = env.lookup( inst->get_name() ) ) {
     97                        if ( eqvClass->type ) {
     98                                // T * = S * for any S depends on the type bound to T
     99                                result = ptrsAssignable( eqvClass->type, dest, env );
     100                        }
    99101                } // if
    100102        }
    101103
    102         void PtrsAssignable::visit(  __attribute__((unused)) TupleType *tupleType ) {}
    103         void PtrsAssignable::visit(  __attribute__((unused)) VarArgsType *varArgsType ) {}
    104         void PtrsAssignable::visit(  __attribute__((unused)) ZeroType *zeroType ) {}
    105         void PtrsAssignable::visit(  __attribute__((unused)) OneType *oneType ) {}
     104        void PtrsAssignable::postvisit(  __attribute__((unused)) TupleType *tupleType ) {}
     105        void PtrsAssignable::postvisit(  __attribute__((unused)) VarArgsType *varArgsType ) {}
     106        void PtrsAssignable::postvisit(  __attribute__((unused)) ZeroType *zeroType ) {}
     107        void PtrsAssignable::postvisit(  __attribute__((unused)) OneType *oneType ) {}
    106108
    107109} // namespace ResolvExpr
  • src/ResolvExpr/PtrsCastable.cc

    rf9feab8 r90152a4  
    1414//
    1515
     16#include "Common/PassVisitor.h"
    1617#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    1718#include "SymTab/Indexer.h"              // for Indexer
     
    2122#include "typeops.h"                     // for ptrsAssignable
    2223
    23 
    2424namespace ResolvExpr {
    25         class PtrsCastable : public Visitor {
     25        struct PtrsCastable : public WithShortCircuiting {
    2626          public:
    2727                PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
     
    2929                int get_result() const { return result; }
    3030
    31                 virtual void visit(VoidType *voidType);
    32                 virtual void visit(BasicType *basicType);
    33                 virtual void visit(PointerType *pointerType);
    34                 virtual void visit(ArrayType *arrayType);
    35                 virtual void visit(FunctionType *functionType);
    36                 virtual void visit(StructInstType *inst);
    37                 virtual void visit(UnionInstType *inst);
    38                 virtual void visit(EnumInstType *inst);
    39                 virtual void visit(TraitInstType *inst);
    40                 virtual void visit(TypeInstType *inst);
    41                 virtual void visit(TupleType *tupleType);
    42                 virtual void visit(VarArgsType *varArgsType);
    43                 virtual void visit(ZeroType *zeroType);
    44                 virtual void visit(OneType *oneType);
     31                void previsit( Type * ) { visit_children = false; }
     32
     33                void postvisit( VoidType * voidType );
     34                void postvisit( BasicType * basicType );
     35                void postvisit( PointerType * pointerType );
     36                void postvisit( ArrayType * arrayType );
     37                void postvisit( FunctionType * functionType );
     38                void postvisit( StructInstType * inst );
     39                void postvisit( UnionInstType * inst );
     40                void postvisit( EnumInstType * inst );
     41                void postvisit( TraitInstType * inst );
     42                void postvisit( TypeInstType * inst );
     43                void postvisit( TupleType * tupleType );
     44                void postvisit( VarArgsType * varArgsType );
     45                void postvisit( ZeroType * zeroType );
     46                void postvisit( OneType * oneType );
    4547          private:
    4648                Type *dest;
     
    5557                                return -1;
    5658                        } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( src ) ) {
    57                                 EqvClass eqvClass;
    5859                                if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
    5960                                        if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {
     
    6263                                                } // if
    6364                                        } //if
    64                                 } else if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
    65                                         if ( eqvClass.data.kind == TypeDecl::Ftype ) {
     65                                } else if ( const EqvClass *eqvClass = env.lookup( typeInst->get_name() ) ) {
     66                                        if ( eqvClass->data.kind == TypeDecl::Ftype ) {
    6667                                                return -1;
    6768                                        } // if
     
    7778        int ptrsCastable( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    7879                if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
    79                         EqvClass eqvClass;
    80                         if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
    81                                 return ptrsAssignable( src, eqvClass.type, env );
     80                        if ( const EqvClass *eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
     81                                // xxx - should this be ptrsCastable?
     82                                return ptrsAssignable( src, eqvClass->type, env );
    8283                        } // if
    8384                } // if
     
    8586                        return objectCast( src, env, indexer );
    8687                } else {
    87                         PtrsCastable ptrs( dest, env, indexer );
     88                        PassVisitor<PtrsCastable> ptrs( dest, env, indexer );
    8889                        src->accept( ptrs );
    89                         return ptrs.get_result();
     90                        return ptrs.pass.get_result();
    9091                } // if
    9192        }
     
    9596        }
    9697
    97         void PtrsCastable::visit( VoidType * ) {
     98        void PtrsCastable::postvisit( VoidType * ) {
    9899                result = objectCast( dest, env, indexer );
    99100        }
    100101
    101         void PtrsCastable::visit( BasicType * ) {
     102        void PtrsCastable::postvisit( BasicType * ) {
    102103                result = objectCast( dest, env, indexer );
    103104        }
    104105
    105         void PtrsCastable::visit( PointerType * ) {
     106        void PtrsCastable::postvisit( PointerType * ) {
    106107                result = objectCast( dest, env, indexer );
    107108        }
    108109
    109         void PtrsCastable::visit( ArrayType * ) {
     110        void PtrsCastable::postvisit( ArrayType * ) {
    110111                result = objectCast( dest, env, indexer );
    111112        }
    112113
    113         void PtrsCastable::visit( FunctionType * ) {
     114        void PtrsCastable::postvisit( FunctionType * ) {
    114115                // result = -1;
    115116                result = functionCast( dest, env, indexer );
    116117        }
    117118
    118         void PtrsCastable::visit( StructInstType * ) {
     119        void PtrsCastable::postvisit( StructInstType * ) {
    119120                result = objectCast( dest, env, indexer );
    120121        }
    121122
    122         void PtrsCastable::visit( UnionInstType * ) {
     123        void PtrsCastable::postvisit( UnionInstType * ) {
    123124                result = objectCast( dest, env, indexer );
    124125        }
    125126
    126         void PtrsCastable::visit( EnumInstType * ) {
     127        void PtrsCastable::postvisit( EnumInstType * ) {
    127128                if ( dynamic_cast< EnumInstType* >( dest ) ) {
    128129                        result = 1;
     
    138139        }
    139140
    140         void PtrsCastable::visit( TraitInstType * ) {}
     141        void PtrsCastable::postvisit( TraitInstType * ) {}
    141142
    142         void PtrsCastable::visit(TypeInstType *inst) {
     143        void PtrsCastable::postvisit(TypeInstType *inst) {
    143144                //result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1;
    144145                result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1;
    145146        }
    146147
    147         void PtrsCastable::visit( TupleType * ) {
     148        void PtrsCastable::postvisit( TupleType * ) {
    148149                result = objectCast( dest, env, indexer );
    149150        }
    150151
    151         void PtrsCastable::visit( VarArgsType * ) {
     152        void PtrsCastable::postvisit( VarArgsType * ) {
    152153                result = objectCast( dest, env, indexer );
    153154        }
    154155
    155         void PtrsCastable::visit( ZeroType * ) {
     156        void PtrsCastable::postvisit( ZeroType * ) {
    156157                result = objectCast( dest, env, indexer );
    157158        }
    158159
    159         void PtrsCastable::visit( OneType * ) {
     160        void PtrsCastable::postvisit( OneType * ) {
    160161                result = objectCast( dest, env, indexer );
    161162        }
  • src/ResolvExpr/RenameVars.cc

    rf9feab8 r90152a4  
    1919#include <utility>                 // for pair
    2020
     21#include "Common/PassVisitor.h"
    2122#include "Common/SemanticError.h"  // for SemanticError
    2223#include "RenameVars.h"
     
    2728
    2829namespace ResolvExpr {
    29         RenameVars global_renamer;
     30        namespace {
     31                struct RenameVars {
     32                        RenameVars();
     33                        void reset();
    3034
    31         RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) {
    32                 mapStack.push_front( std::map< std::string, std::string >() );
     35                        void previsit( TypeInstType * instType );
     36                        void previsit( Type * );
     37                        void postvisit( Type * );
     38
     39                  private:
     40                        int level, resetCount;
     41                        std::list< std::map< std::string, std::string > > mapStack;
     42                };
     43
     44                PassVisitor<RenameVars> global_renamer;
     45        } // namespace
     46
     47        void renameTyVars( Type * t ) {
     48                t->accept( global_renamer );
    3349        }
    3450
    35         void RenameVars::reset() {
    36                 level = 0;
    37                 resetCount++;
     51        void resetTyVarRenaming() {
     52                global_renamer.pass.reset();
    3853        }
    3954
    40         void RenameVars::visit( VoidType *voidType ) {
    41                 typeBefore( voidType );
    42                 typeAfter( voidType );
    43         }
     55        namespace {
     56                RenameVars::RenameVars() : level( 0 ), resetCount( 0 ) {
     57                        mapStack.push_front( std::map< std::string, std::string >() );
     58                }
    4459
    45         void RenameVars::visit( BasicType *basicType ) {
    46                 typeBefore( basicType );
    47                 typeAfter( basicType );
    48         }
     60                void RenameVars::reset() {
     61                        level = 0;
     62                        resetCount++;
     63                }
    4964
    50         void RenameVars::visit( PointerType *pointerType ) {
    51                 typeBefore( pointerType );
    52                 maybeAccept( pointerType->get_base(), *this );
    53                 typeAfter( pointerType );
    54         }
     65                void RenameVars::previsit( TypeInstType * instType ) {
     66                        previsit( (Type *)instType );
     67                        std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->name );
     68                        if ( i != mapStack.front().end() ) {
     69                                instType->name = i->second;
     70                        } // if
     71                }
    5572
    56         void RenameVars::visit( ArrayType *arrayType ) {
    57                 typeBefore( arrayType );
    58                 maybeAccept( arrayType->get_dimension(), *this );
    59                 maybeAccept( arrayType->get_base(), *this );
    60                 typeAfter( arrayType );
    61         }
     73                void RenameVars::previsit( Type * type ) {
     74                        if ( ! type->forall.empty() ) {
     75                                // copies current name mapping into new mapping
     76                                mapStack.push_front( mapStack.front() );
     77                                // renames all "forall" type names to `_${level}_${name}'
     78                                for ( auto td : type->forall ) {
     79                                        std::ostringstream output;
     80                                        output << "_" << resetCount << "_" << level << "_" << td->name;
     81                                        std::string newname( output.str() );
     82                                        mapStack.front()[ td->get_name() ] = newname;
     83                                        td->name = newname;
     84                                        // ditto for assertion names, the next level in
     85                                        level++;
     86                                        // acceptAll( td->assertions, *this );
     87                                } // for
     88                        } // if
     89                }
    6290
    63         void RenameVars::visit( FunctionType *functionType ) {
    64                 typeBefore( functionType );
    65                 acceptAll( functionType->get_returnVals(), *this );
    66                 acceptAll( functionType->get_parameters(), *this );
    67                 typeAfter( functionType );
    68         }
    69 
    70         void RenameVars::visit( StructInstType *aggregateUseType ) {
    71                 typeBefore( aggregateUseType );
    72                 acceptAll( aggregateUseType->get_parameters(), *this );
    73                 typeAfter( aggregateUseType );
    74         }
    75 
    76         void RenameVars::visit( UnionInstType *aggregateUseType ) {
    77                 typeBefore( aggregateUseType );
    78                 acceptAll( aggregateUseType->get_parameters(), *this );
    79                 typeAfter( aggregateUseType );
    80         }
    81 
    82         void RenameVars::visit( EnumInstType *aggregateUseType ) {
    83                 typeBefore( aggregateUseType );
    84                 acceptAll( aggregateUseType->get_parameters(), *this );
    85                 typeAfter( aggregateUseType );
    86         }
    87 
    88         void RenameVars::visit( TraitInstType *aggregateUseType ) {
    89                 typeBefore( aggregateUseType );
    90                 acceptAll( aggregateUseType->get_parameters(), *this );
    91                 typeAfter( aggregateUseType );
    92         }
    93 
    94         void RenameVars::visit( TypeInstType *instType ) {
    95                 typeBefore( instType );
    96                 std::map< std::string, std::string >::const_iterator i = mapStack.front().find( instType->get_name() );
    97                 if ( i != mapStack.front().end() ) {
    98                         instType->set_name( i->second );
    99                 } else {
    100                 } // if
    101                 acceptAll( instType->get_parameters(), *this );
    102                 typeAfter( instType );
    103         }
    104 
    105         void RenameVars::visit( TupleType *tupleType ) {
    106                 typeBefore( tupleType );
    107                 acceptAll( tupleType->get_types(), *this );
    108                 typeAfter( tupleType );
    109         }
    110 
    111         void RenameVars::visit( VarArgsType *varArgsType ) {
    112                 typeBefore( varArgsType );
    113                 typeAfter( varArgsType );
    114         }
    115 
    116         void RenameVars::visit( ZeroType *zeroType ) {
    117                 typeBefore( zeroType );
    118                 typeAfter( zeroType );
    119         }
    120 
    121         void RenameVars::visit( OneType *oneType ) {
    122                 typeBefore( oneType );
    123                 typeAfter( oneType );
    124         }
    125 
    126         void RenameVars::typeBefore( Type *type ) {
    127                 if ( ! type->get_forall().empty() ) {
    128                         // copies current name mapping into new mapping
    129                         mapStack.push_front( mapStack.front() );
    130                         // renames all "forall" type names to `_${level}_${name}'
    131                         for ( Type::ForallList::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
    132                                 std::ostringstream output;
    133                                 output << "_" << resetCount << "_" << level << "_" << (*i)->get_name();
    134                                 std::string newname( output.str() );
    135                                 mapStack.front()[ (*i)->get_name() ] = newname;
    136                                 (*i)->set_name( newname );
    137                                 // ditto for assertion names, the next level in
    138                                 level++;
    139                                 acceptAll( (*i)->get_assertions(), *this );
    140                         } // for
    141                 } // if
    142         }
    143 
    144         void RenameVars::typeAfter( Type *type ) {
    145                 // clears name mapping added by typeBefore()
    146                 if ( ! type->get_forall().empty() ) {
    147                         mapStack.pop_front();
    148                 } // if
    149         }
    150 
     91                void RenameVars::postvisit( Type * type ) {
     92                        // clears name mapping added by typeBefore()
     93                        if ( ! type->forall.empty() ) {
     94                                mapStack.pop_front();
     95                        } // if
     96                }
     97        } // namespace
    15198} // namespace ResolvExpr
    15299
  • src/ResolvExpr/RenameVars.h

    rf9feab8 r90152a4  
    2424
    2525namespace ResolvExpr {
     26        /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID
     27        void renameTyVars( Type * );
    2628
    27         /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID
    28         class RenameVars : public Visitor {
    29           public:
    30                 RenameVars();
    31                 void reset();
    32           private:
    33                 virtual void visit( VoidType *basicType );
    34                 virtual void visit( BasicType *basicType );
    35                 virtual void visit( PointerType *pointerType );
    36                 virtual void visit( ArrayType *arrayType );
    37                 virtual void visit( FunctionType *functionType );
    38                 virtual void visit( StructInstType *aggregateUseType );
    39                 virtual void visit( UnionInstType *aggregateUseType );
    40                 virtual void visit( EnumInstType *aggregateUseType );
    41                 virtual void visit( TraitInstType *aggregateUseType );
    42                 virtual void visit( TypeInstType *aggregateUseType );
    43                 virtual void visit( TupleType *tupleType );
    44                 virtual void visit( VarArgsType *varArgsType );
    45                 virtual void visit( ZeroType *zeroType );
    46                 virtual void visit( OneType *oneType );
    47 
    48                 void typeBefore( Type *type );
    49                 void typeAfter( Type *type );
    50                 int level, resetCount;
    51                 std::list< std::map< std::string, std::string > > mapStack;
    52         };
    53 
    54         extern RenameVars global_renamer;
     29        /// resets internal state of renamer to avoid overflow
     30        void resetTyVarRenaming();
    5531} // namespace ResolvExpr
    5632
  • src/ResolvExpr/Resolver.cc

    rf9feab8 r90152a4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tus Aug  8 16:06:00 2017
    13 // Update Count     : 212
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sat Feb 17 11:19:40 2018
     13// Update Count     : 213
    1414//
    1515
     
    3030#include "RenameVars.h"                  // for RenameVars, global_renamer
    3131#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    32 #include "ResolveTypeof.h"               // for resolveTypeof
    3332#include "Resolver.h"
    3433#include "SymTab/Autogen.h"              // for SizeType
     
    5756                void postvisit( FunctionDecl *functionDecl );
    5857                void previsit( ObjectDecl *objectDecll );
    59                 void previsit( TypeDecl *typeDecl );
    6058                void previsit( EnumDecl * enumDecl );
     59                void previsit( StaticAssertDecl * assertDecl );
    6160
    6261                void previsit( ArrayType * at );
     
    7675                void previsit( CatchStmt *catchStmt );
    7776                void previsit( WaitForStmt * stmt );
    78                 void previsit( WithStmt * withStmt );
    7977
    8078                void previsit( SingleInit *singleInit );
     
    8280                void previsit( ConstructorInit *ctorInit );
    8381          private:
    84         typedef std::list< Initializer * >::iterator InitIterator;
     82                typedef std::list< Initializer * >::iterator InitIterator;
    8583
    8684                template< typename PtrType >
    8785                void handlePtrType( PtrType * type );
    8886
    89           void resolveAggrInit( ReferenceToType *, InitIterator &, InitIterator & );
    90           void resolveSingleAggrInit( Declaration *, InitIterator &, InitIterator &, TypeSubstitution sub );
    91           void fallbackInit( ConstructorInit * ctorInit );
     87                void fallbackInit( ConstructorInit * ctorInit );
    9288
    9389                Type * functionReturn = nullptr;
     
    9692        };
    9793
     94        struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {
     95                void previsit( FunctionDecl * );
     96                void previsit( WithStmt * );
     97
     98                void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
     99        };
     100
    98101        void resolve( std::list< Declaration * > translationUnit ) {
    99102                PassVisitor<Resolver> resolver;
     
    106109        }
    107110
    108         // used in resolveTypeof
    109         Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
    110                 TypeEnvironment env;
    111                 return resolveInVoidContext( expr, indexer, env );
    112         }
    113 
    114111        namespace {
    115                 void finishExpr( Expression *expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
     112                struct DeleteFinder : public WithShortCircuiting        {
     113                        DeletedExpr * delExpr = nullptr;
     114                        void previsit( DeletedExpr * expr ) {
     115                                if ( delExpr ) visit_children = false;
     116                                else delExpr = expr;
     117                        }
     118
     119                        void previsit( Expression * ) {
     120                                if ( delExpr ) visit_children = false;
     121                        }
     122                };
     123        }
     124
     125        DeletedExpr * findDeletedExpr( Expression * expr ) {
     126                PassVisitor<DeleteFinder> finder;
     127                expr->accept( finder );
     128                return finder.pass.delExpr;
     129        }
     130
     131        namespace {
     132                struct StripCasts {
     133                        Expression * postmutate( CastExpr * castExpr ) {
     134                                if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
     135                                        // generated cast is to the same type as its argument, so it's unnecessary -- remove it
     136                                        Expression * expr = castExpr->arg;
     137                                        castExpr->arg = nullptr;
     138                                        std::swap( expr->env, castExpr->env );
     139                                        return expr;
     140                                }
     141                                return castExpr;
     142                        }
     143
     144                        static void strip( Expression *& expr ) {
     145                                PassVisitor<StripCasts> stripper;
     146                                expr = expr->acceptMutator( stripper );
     147                        }
     148                };
     149
     150                void finishExpr( Expression *&expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {
    116151                        expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
    117                         env.makeSubstitution( *expr->get_env() );
     152                        env.makeSubstitution( *expr->env );
     153                        StripCasts::strip( expr ); // remove unnecessary casts that may be buried in an expression
    118154                }
    119155
     
    131167        } // namespace
    132168
     169        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                        assertf( untyped, "expected a non-null expression." );
     172                        TypeEnvironment env;
     173                        AlternativeFinder finder( indexer, env );
     174                        finder.find( untyped, adjust, prune, failFast );
     175
     176                        #if 0
     177                        if ( finder.get_alternatives().size() != 1 ) {
     178                                std::cerr << "untyped expr is ";
     179                                untyped->print( std::cerr );
     180                                std::cerr << std::endl << "alternatives are:";
     181                                for ( const Alternative & alt : finder.get_alternatives() ) {
     182                                        alt.print( std::cerr );
     183                                } // for
     184                        } // if
     185                        #endif
     186
     187                        AltList candidates;
     188                        for ( Alternative & alt : finder.get_alternatives() ) {
     189                                if ( pred( alt ) ) {
     190                                        candidates.push_back( std::move( alt ) );
     191                                }
     192                        }
     193
     194                        // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining
     195                        // choose the lowest cost expression among the candidates
     196                        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 ) {
     201                                std::ostringstream stream;
     202                                stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
     203                                untyped->print( stream );
     204                                stream << " Alternatives are:\n";
     205                                printAlts( winners, stream, 1 );
     206                                SemanticError( untyped->location, stream.str() );
     207                        }
     208
     209                        // there is one unambiguous interpretation - move the expression into the with statement
     210                        Alternative & choice = winners.front();
     211                        if ( findDeletedExpr( choice.expr ) ) {
     212                                SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
     213                        }
     214                        alt = std::move( choice );
     215                }
     216
     217                /// 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) {
     219                        if ( ! untyped ) return;
     220                        Alternative choice;
     221                        findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
     222                        finishExpr( choice.expr, choice.env, untyped->env );
     223                        delete untyped;
     224                        untyped = choice.expr;
     225                        choice.expr = nullptr;
     226                }
     227
     228                bool standardAlternativeFilter( const Alternative & ) {
     229                        // currently don't need to filter, under normal circumstances.
     230                        // in the future, this may be useful for removing deleted expressions
     231                        return true;
     232                }
     233        } // namespace
     234
     235        // used in resolveTypeof
     236        Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
     237                TypeEnvironment env;
     238                return resolveInVoidContext( expr, indexer, env );
     239        }
     240
     241        Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {
     242                // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
     243                // interpretations, an exception has already been thrown.
     244                assertf( expr, "expected a non-null expression." );
     245
     246                static CastExpr untyped( nullptr ); // cast to void
     247                untyped.location = expr->location;
     248
     249                // set up and resolve expression cast to void
     250                untyped.arg = expr;
     251                Alternative choice;
     252                findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
     253                CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
     254                env = std::move( choice.env );
     255
     256                // clean up resolved expression
     257                Expression * ret = castExpr->arg;
     258                castExpr->arg = nullptr;
     259
     260                // unlink the arg so that it isn't deleted twice at the end of the program
     261                untyped.arg = nullptr;
     262                return ret;
     263        }
     264
    133265        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    134                 global_renamer.reset();
     266                resetTyVarRenaming();
    135267                TypeEnvironment env;
    136                 Expression *newExpr = resolveInVoidContext( untyped, indexer, env );
     268                Expression * newExpr = resolveInVoidContext( untyped, indexer, env );
    137269                finishExpr( newExpr, env, untyped->env );
    138270                delete untyped;
     
    141273
    142274        void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) {
    143                 if ( ! untyped ) return;
    144                 TypeEnvironment env;
    145                 AlternativeFinder finder( indexer, env );
    146                 finder.find( untyped );
    147                 #if 0
    148                 if ( finder.get_alternatives().size() != 1 ) {
    149                         std::cerr << "untyped expr is ";
    150                         untyped->print( std::cerr );
    151                         std::cerr << std::endl << "alternatives are:";
    152                         for ( const Alternative & alt : finder.get_alternatives() ) {
    153                                 alt.print( std::cerr );
    154                         } // for
    155                 } // if
    156                 #endif
    157                 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end." );
    158                 Alternative &choice = finder.get_alternatives().front();
    159                 Expression *newExpr = choice.expr->clone();
    160                 finishExpr( newExpr, choice.env, untyped->env );
    161                 delete untyped;
    162                 untyped = newExpr;
     275                findKindExpression( untyped, indexer, "", standardAlternativeFilter );
    163276        }
    164277
    165278        void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) {
    166279                assert( untyped && type );
     280                // transfer location to generated cast for error purposes
     281                CodeLocation location = untyped->location;
    167282                untyped = new CastExpr( untyped, type );
     283                untyped->location = location;
    168284                findSingleExpression( untyped, indexer );
    169285                removeExtraneousCast( untyped, indexer );
     
    171287
    172288        namespace {
    173                 bool isIntegralType( Type *type ) {
     289                bool isIntegralType( const Alternative & alt ) {
     290                        Type * type = alt.expr->result;
    174291                        if ( dynamic_cast< EnumInstType * >( type ) ) {
    175292                                return true;
     
    184301
    185302                void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {
    186                         TypeEnvironment env;
    187                         AlternativeFinder finder( indexer, env );
    188                         finder.find( untyped );
    189 #if 0
    190                         if ( finder.get_alternatives().size() != 1 ) {
    191                                 std::cout << "untyped expr is ";
    192                                 untyped->print( std::cout );
    193                                 std::cout << std::endl << "alternatives are:";
    194                                 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    195                                         i->print( std::cout );
    196                                 } // for
    197                         } // if
    198 #endif
    199                         Expression *newExpr = 0;
    200                         const TypeEnvironment *newEnv = 0;
    201                         for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
    202                                 if ( i->expr->get_result()->size() == 1 && isIntegralType( i->expr->get_result() ) ) {
    203                                         if ( newExpr ) {
    204                                                 throw SemanticError( "Too many interpretations for case control expression", untyped );
    205                                         } else {
    206                                                 newExpr = i->expr->clone();
    207                                                 newEnv = &i->env;
    208                                         } // if
    209                                 } // if
    210                         } // for
    211                         if ( ! newExpr ) {
    212                                 throw SemanticError( "No interpretations for case control expression", untyped );
    213                         } // if
    214                         finishExpr( newExpr, *newEnv, untyped->env );
    215                         delete untyped;
    216                         untyped = newExpr;
    217                 }
    218 
     303                        findKindExpression( untyped, indexer, "condition", isIntegralType );
     304                }
     305        }
     306
     307
     308        bool isStructOrUnion( const Alternative & alt ) {
     309                Type * t = alt.expr->result->stripReferences();
     310                return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
     311        }
     312
     313        void resolveWithExprs( std::list< Declaration * > & translationUnit ) {
     314                PassVisitor<ResolveWithExprs> resolver;
     315                acceptAll( translationUnit, resolver );
     316        }
     317
     318        void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
     319                for ( Expression *& expr : withExprs )  {
     320                        // only struct- and union-typed expressions are viable candidates
     321                        findKindExpression( expr, indexer, "with statement", isStructOrUnion );
     322
     323                        // if with expression might be impure, create a temporary so that it is evaluated once
     324                        if ( Tuples::maybeImpure( expr ) ) {
     325                                static UniqueName tmpNamer( "_with_tmp_" );
     326                                ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
     327                                expr = new VariableExpr( tmp );
     328                                newStmts.push_back( new DeclStmt( tmp ) );
     329                                if ( InitTweak::isConstructable( tmp->type ) ) {
     330                                        // generate ctor/dtor and resolve them
     331                                        tmp->init = InitTweak::genCtorInit( tmp );
     332                                        tmp->accept( *visitor );
     333                                }
     334                        }
     335                }
     336        }
     337
     338        void ResolveWithExprs::previsit( WithStmt * withStmt ) {
     339                resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
     340        }
     341
     342        void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) {
     343                {
     344                        // resolve with-exprs with parameters in scope and add any newly generated declarations to the
     345                        // front of the function body.
     346                        auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } );
     347                        indexer.addFunctionType( functionDecl->type );
     348                        std::list< Statement * > newStmts;
     349                        resolveWithExprs( functionDecl->withExprs, newStmts );
     350                        if ( functionDecl->statements ) {
     351                                functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
     352                        } else {
     353                                assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
     354                        }
     355                }
    219356        }
    220357
    221358        void Resolver::previsit( ObjectDecl *objectDecl ) {
    222                 Type *new_type = resolveTypeof( objectDecl->get_type(), indexer );
    223                 objectDecl->set_type( new_type );
    224359                // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable
    225360                // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes
     
    251386        }
    252387
    253         void Resolver::previsit( TypeDecl *typeDecl ) {
    254                 if ( typeDecl->get_base() ) {
    255                         Type *new_type = resolveTypeof( typeDecl->get_base(), indexer );
    256                         typeDecl->set_base( new_type );
    257                 } // if
    258         }
    259 
    260388        void Resolver::previsit( FunctionDecl *functionDecl ) {
    261389#if 0
     
    264392                std::cerr << std::endl;
    265393#endif
    266                 Type *new_type = resolveTypeof( functionDecl->get_type(), indexer );
    267                 functionDecl->set_type( new_type );
    268394                GuardValue( functionReturn );
    269                 functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() );
     395                functionReturn = ResolvExpr::extractResultType( functionDecl->type );
    270396        }
    271397
     
    274400                // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently
    275401                // see how it's useful.
    276                 for ( Declaration * d : functionDecl->get_functionType()->get_parameters() ) {
     402                for ( Declaration * d : functionDecl->type->parameters ) {
    277403                        if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
    278                                 if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->get_init() ) ) {
    279                                         delete init->get_value()->get_env();
    280                                         init->get_value()->set_env( nullptr );
     404                                if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->init ) ) {
     405                                        delete init->value->env;
     406                                        init->value->env = nullptr;
    281407                                }
    282408                        }
     
    290416        }
    291417
     418        void Resolver::previsit( StaticAssertDecl * assertDecl ) {
     419                findIntegralExpression( assertDecl->condition, indexer );
     420        }
     421
    292422        void Resolver::previsit( ExprStmt *exprStmt ) {
    293423                visit_children = false;
     
    311441
    312442        void Resolver::previsit( IfStmt *ifStmt ) {
    313                 findSingleExpression( ifStmt->condition, indexer );
     443                findIntegralExpression( ifStmt->condition, indexer );
    314444        }
    315445
    316446        void Resolver::previsit( WhileStmt *whileStmt ) {
    317                 findSingleExpression( whileStmt->condition, indexer );
     447                findIntegralExpression( whileStmt->condition, indexer );
    318448        }
    319449
    320450        void Resolver::previsit( ForStmt *forStmt ) {
    321451                if ( forStmt->condition ) {
    322                         findSingleExpression( forStmt->condition, indexer );
     452                        findIntegralExpression( forStmt->condition, indexer );
    323453                } // if
    324454
     
    336466
    337467        void Resolver::previsit( CaseStmt *caseStmt ) {
    338                 if ( caseStmt->get_condition() ) {
     468                if ( caseStmt->condition ) {
    339469                        std::list< InitAlternative > initAlts = currentObject.getOptions();
    340470                        assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
     
    342472                        Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() );
    343473                        findSingleExpression( newExpr, indexer );
    344                         CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( newExpr );
    345                         caseStmt->condition = castExpr->arg;
    346                         castExpr->arg = nullptr;
    347                         delete castExpr;
     474                        // case condition cannot have a cast in C, so it must be removed, regardless of whether it performs a conversion.
     475                        // Ideally we would perform the conversion internally here.
     476                        if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( newExpr ) ) {
     477                                newExpr = castExpr->arg;
     478                                castExpr->arg = nullptr;
     479                                std::swap( newExpr->env, castExpr->env );
     480                                delete castExpr;
     481                        }
     482                        caseStmt->condition = newExpr;
    348483                }
    349484        }
     
    411546                                ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
    412547                                ss << "' in call to waitfor";
    413                                 throw SemanticError( ss.str() );
     548                                SemanticError( stmt->location, ss.str() );
     549                        }
     550
     551                        if(clause.target.arguments.empty()) {
     552                                SemanticError( stmt->location, "Waitfor clause must have at least one mutex parameter");
    414553                        }
    415554
     
    428567                        //      try matching the arguments to the parameters
    429568                        //      not the other way around because we have more arguments than parameters
    430                         SemanticError errors;
     569                        SemanticErrorException errors;
    431570                        for ( Alternative & func : funcFinder.get_alternatives() ) {
    432571                                try {
    433572                                        PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
    434573                                        if( !pointer ) {
    435                                                 throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() );
     574                                                SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" );
    436575                                        }
    437576
    438577                                        FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
    439578                                        if( !function ) {
    440                                                 throw SemanticError( "candidate not viable: not a function type\n", pointer->get_base() );
     579                                                SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
    441580                                        }
    442581
     
    447586
    448587                                                if( !advance_to_mutex( param, param_end ) ) {
    449                                                         throw SemanticError("candidate function not viable: no mutex parameters\n", function);
     588                                                        SemanticError(function, "candidate function not viable: no mutex parameters\n");
    450589                                                }
    451590                                        }
     
    453592                                        Alternative newFunc( func );
    454593                                        // Strip reference from function
    455                                         referenceToRvalueConversion( newFunc.expr );
     594                                        referenceToRvalueConversion( newFunc.expr, newFunc.cost );
    456595
    457596                                        // For all the set of arguments we have try to match it with the parameter of the current function alternative
     
    462601                                                        OpenVarSet openVars;
    463602                                                        AssertionSet resultNeed, resultHave;
    464                                                         TypeEnvironment resultEnv;
     603                                                        TypeEnvironment resultEnv( func.env );
     604                                                        makeUnifiableVars( function, openVars, resultNeed );
     605                                                        // add all type variables as open variables now so that those not used in the parameter
     606                                                        // list are still considered open.
     607                                                        resultEnv.add( function->forall );
    465608
    466609                                                        // Load type variables from arguemnts into one shared space
     
    468611
    469612                                                        // Make sure we don't widen any existing bindings
    470                                                         for ( auto & i : resultEnv ) {
    471                                                                 i.allowWidening = false;
    472                                                         }
     613                                                        resultEnv.forbidWidening();
    473614
    474615                                                        // Find any unbound type variables
     
    477618                                                        auto param     = function->parameters.begin();
    478619                                                        auto param_end = function->parameters.end();
     620
     621                                                        int n_mutex_param = 0;
    479622
    480623                                                        // For every arguments of its set, check if it matches one of the parameter
     
    486629                                                                        // We ran out of parameters but still have arguments
    487630                                                                        // this function doesn't match
    488                                                                         throw SemanticError("candidate function not viable: too many mutex arguments\n", function);
     631                                                                        SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" ));
    489632                                                                }
    490633
     634                                                                n_mutex_param++;
     635
    491636                                                                // Check if the argument matches the parameter type in the current scope
    492                                                                 if( ! unify( (*param)->get_type(), arg.expr->get_result(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
     637                                                                if( ! unify( arg.expr->get_result(), (*param)->get_type(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
    493638                                                                        // Type doesn't match
    494639                                                                        stringstream ss;
    495640                                                                        ss << "candidate function not viable: no known convertion from '";
     641                                                                        (*param)->get_type()->print( ss );
     642                                                                        ss << "' to '";
    496643                                                                        arg.expr->get_result()->print( ss );
    497                                                                         ss << "' to '";
    498                                                                         (*param)->get_type()->print( ss );
     644                                                                        ss << "' with env '";
     645                                                                        resultEnv.print(ss);
    499646                                                                        ss << "'\n";
    500                                                                         throw SemanticError(ss.str(), function);
     647                                                                        SemanticError( function, ss.str() );
    501648                                                                }
    502649
     
    508655                                                        // Check if parameters are missing
    509656                                                        if( advance_to_mutex( param, param_end ) ) {
     657                                                                do {
     658                                                                        n_mutex_param++;
     659                                                                        param++;
     660                                                                } while( advance_to_mutex( param, param_end ) );
     661
    510662                                                                // We ran out of arguments but still have parameters left
    511663                                                                // this function doesn't match
    512                                                                 throw SemanticError("candidate function not viable: too few mutex arguments\n", function);
     664                                                                SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" ));
    513665                                                        }
    514666
     
    526678
    527679                                                }
    528                                                 catch( SemanticError &e ) {
     680                                                catch( SemanticErrorException &e ) {
    529681                                                        errors.append( e );
    530682                                                }
    531683                                        }
    532684                                }
    533                                 catch( SemanticError &e ) {
     685                                catch( SemanticErrorException &e ) {
    534686                                        errors.append( e );
    535687                                }
     
    537689
    538690                        // Make sure we got the right number of arguments
    539                         if( func_candidates.empty() )    { SemanticError top( "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
    540                         if( args_candidates.empty() )    { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
    541                         if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
    542                         if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
    543 
     691                        if( func_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
     692                        if( args_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
     693                        if( func_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
     694                        if( args_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
     695                        // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
    544696
    545697                        // Swap the results from the alternative with the unresolved values.
     
    574726        }
    575727
    576         bool isStructOrUnion( Type * t ) {
    577                 t = t->stripReferences();
    578                 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
    579         }
    580 
    581         void Resolver::previsit( WithStmt * withStmt ) {
    582                 for ( Expression *& expr : withStmt->exprs )  {
    583                         TypeEnvironment env;
    584                         AlternativeFinder finder( indexer, env );
    585                         finder.findWithAdjustment( expr );
    586 
    587                         // only struct- and union-typed expressions are viable candidates
    588                         AltList candidates;
    589                         for ( Alternative & alt : finder.get_alternatives() ) {
    590                                 if ( isStructOrUnion( alt.expr->result ) ) {
    591                                         candidates.push_back( std::move( alt ) );
    592                                 }
    593                         }
    594 
    595                         // choose the lowest cost expression among the candidates
    596                         AltList winners;
    597                         findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
    598                         if ( winners.size() == 0 ) {
    599                                 throw SemanticError( "No reasonable alternatives for with statement expression: ", expr );
    600                         } else if ( winners.size() != 1 ) {
    601                                 std::ostringstream stream;
    602                                 stream << "Cannot choose between " << winners.size() << " alternatives for with statement expression\n";
    603                                 expr->print( stream );
    604                                 stream << "Alternatives are:\n";
    605                                 printAlts( winners, stream, 1 );
    606                                 throw SemanticError( stream.str() );
    607                         }
    608 
    609                         // there is one unambiguous interpretation - move the expression into the with statement
    610                         Alternative & alt = winners.front();
    611                         finishExpr( alt.expr, alt.env, expr->env );
    612                         delete expr;
    613                         expr = alt.expr;
    614                         alt.expr = nullptr;
    615 
    616                         // if with expression might be impure, create a temporary so that it is evaluated once
    617                         if ( Tuples::maybeImpure( expr ) ) {
    618                                 static UniqueName tmpNamer( "_with_tmp_" );
    619                                 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
    620                                 expr = new VariableExpr( tmp );
    621                                 stmtsToAddBefore.push_back( new DeclStmt( tmp ) );
    622                                 if ( InitTweak::isConstructable( tmp->type ) ) {
    623                                         // generate ctor/dtor and resolve them
    624                                         tmp->init = InitTweak::genCtorInit( tmp );
    625                                         tmp->accept( *visitor );
    626                                 }
    627                         }
    628                 }
    629         }
    630 
    631728        template< typename T >
    632729        bool isCharType( T t ) {
     
    652749                initExpr->expr = nullptr;
    653750                std::swap( initExpr->env, newExpr->env );
    654                 std::swap( initExpr->inferParams, newExpr->inferParams ) ;
     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.
     753                newExpr->spliceInferParams( initExpr );
    655754                delete initExpr;
    656755
     
    740839                PassVisitor<Resolver> resolver( indexer );
    741840                stmtExpr->accept( resolver );
     841                stmtExpr->computeResult();
     842                // xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead?
    742843        }
    743844
     
    745846                visit_children = false;
    746847                // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
    747                 maybeAccept( ctorInit->get_ctor(), *visitor );
    748                 maybeAccept( ctorInit->get_dtor(), *visitor );
     848                maybeAccept( ctorInit->ctor, *visitor );
     849                maybeAccept( ctorInit->dtor, *visitor );
    749850
    750851                // found a constructor - can get rid of C-style initializer
    751                 delete ctorInit->get_init();
    752                 ctorInit->set_init( NULL );
     852                delete ctorInit->init;
     853                ctorInit->init = nullptr;
    753854
    754855                // intrinsic single parameter constructors and destructors do nothing. Since this was
    755856                // implicitly generated, there's no way for it to have side effects, so get rid of it
    756857                // to clean up generated code.
    757                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_ctor() ) ) {
    758                         delete ctorInit->get_ctor();
    759                         ctorInit->set_ctor( NULL );
    760                 }
    761 
    762                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->get_dtor() ) ) {
    763                         delete ctorInit->get_dtor();
    764                         ctorInit->set_dtor( NULL );
     858                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
     859                        delete ctorInit->ctor;
     860                        ctorInit->ctor = nullptr;
     861                }
     862
     863                if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
     864                        delete ctorInit->dtor;
     865                        ctorInit->dtor = nullptr;
    765866                }
    766867
  • src/ResolvExpr/Resolver.h

    rf9feab8 r90152a4  
    3333        void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer );
    3434        void findSingleExpression( Expression *& untyped, const SymTab::Indexer &indexer );
     35        void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer &indexer );
    3536        void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
    3637        void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
     38        /// Searches expr and returns the first DeletedExpr found, otherwise nullptr
     39        DeletedExpr * findDeletedExpr( Expression * expr );
     40        /// Resolves with-stmts and with-clauses on functions
     41        void resolveWithExprs( std::list< Declaration * > & translationUnit );
    3742} // namespace ResolvExpr
    3843
  • src/ResolvExpr/TypeEnvironment.cc

    rf9feab8 r90152a4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:19:47 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun May 17 12:23:36 2015
    13 // Update Count     : 3
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 18 11:58:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    1717#include <algorithm>                   // for copy, set_intersection
    1818#include <iterator>                    // for ostream_iterator, insert_iterator
    19 #include <utility>                     // for pair
     19#include <memory>                      // for unique_ptr
     20#include <utility>                     // for pair, move
    2021
    2122#include "Common/utility.h"            // for maybeClone
    2223#include "SynTree/Type.h"              // for Type, FunctionType, Type::Fora...
    2324#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
     25#include "Tuples/Tuples.h"             // for isTtype
    2426#include "TypeEnvironment.h"
     27#include "typeops.h"                   // for occurs
     28#include "Unify.h"                     // for unifyInexact
    2529
    2630namespace ResolvExpr {
     
    4448
    4549        void EqvClass::initialize( const EqvClass &src, EqvClass &dest ) {
     50                initialize( src, dest, src.type );
     51        }
     52
     53        void EqvClass::initialize( const EqvClass &src, EqvClass &dest, const Type *ty ) {
    4654                dest.vars = src.vars;
    47                 dest.type = maybeClone( src.type );
     55                dest.type = maybeClone( ty );
    4856                dest.allowWidening = src.allowWidening;
    4957                dest.data = src.data;
    5058        }
    5159
    52         EqvClass::EqvClass() : type( 0 ), allowWidening( true ) {
     60        EqvClass::EqvClass() : type( nullptr ), allowWidening( true ) {
    5361        }
    5462
    5563        EqvClass::EqvClass( const EqvClass &other ) {
    5664                initialize( other, *this );
     65        }
     66
     67        EqvClass::EqvClass( const EqvClass &other, const Type *ty ) {
     68                initialize( other, *this, ty );
     69        }
     70
     71        EqvClass::EqvClass( EqvClass &&other )
     72        : vars{std::move(other.vars)}, type{other.type},
     73          allowWidening{std::move(other.allowWidening)}, data{std::move(other.data)} {
     74                  other.type = nullptr;
    5775        }
    5876
     
    6482        }
    6583
     84        EqvClass &EqvClass::operator=( EqvClass &&other ) {
     85                if ( this == &other ) return *this;
     86                delete type;
     87
     88                vars = std::move(other.vars);
     89                type = other.type;
     90                other.type = nullptr;
     91                allowWidening = std::move(other.allowWidening);
     92                data = std::move(other.data);
     93
     94                return *this;
     95        }
     96
    6697        EqvClass::~EqvClass() {
    6798                delete type;
     99        }
     100
     101        void EqvClass::set_type( Type* ty ) {
     102                if ( ty == type ) return;
     103                delete type;
     104                type = ty;
    68105        }
    69106
     
    82119        }
    83120
    84         bool TypeEnvironment::lookup( const std::string &var, EqvClass &eqvClass ) const {
     121        const EqvClass* TypeEnvironment::lookup( const std::string &var ) const {
    85122                for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
    86                         if ( i->vars.find( var ) != i->vars.end() ) {
    87 ///       std::cout << var << " is in class ";
    88 ///       i->print( std::cout );
    89                                 eqvClass = *i;
    90                                 return true;
    91                         }
    92 ///     std::cout << var << " is not in class ";
    93 ///     i->print( std::cout );
    94                 } // for
    95                 return false;
    96         }
    97 
    98         void TypeEnvironment::add( const EqvClass &eqvClass ) {
    99                 std::list< EqvClass >::iterator i = env.begin();
    100                 while ( i != env.end() ) {
    101                         std::list< EqvClass >::iterator next = i;
    102                         next++;
    103                         std::set< std::string > intersection;
    104                         std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(), std::inserter( intersection, intersection.begin() ) );
    105                         if ( ! intersection.empty() ) {
    106                                 env.erase( i );
    107                         } // if
     123                        if ( i->vars.find( var ) != i->vars.end() ) return &*i;
     124                } // for
     125                return nullptr;
     126        }
     127
     128        /// Removes any class from env that intersects eqvClass
     129        void filterOverlappingClasses( std::list<EqvClass> &env, const EqvClass &eqvClass ) {
     130                for ( auto i = env.begin(); i != env.end(); ) {
     131                        auto next = i;
     132                        ++next;
     133                        std::set<std::string> intersection;
     134                        std::set_intersection( i->vars.begin(), i->vars.end(), eqvClass.vars.begin(), eqvClass.vars.end(),
     135                                std::inserter( intersection, intersection.begin() ) );
     136                        if ( ! intersection.empty() ) { env.erase( i ); }
    108137                        i = next;
    109                 } // while
    110                 env.insert( env.end(), eqvClass );
     138                }
     139        }
     140
     141        void TypeEnvironment::add( EqvClass &&eqvClass ) {
     142                filterOverlappingClasses( env, eqvClass );
     143                env.push_back( std::move(eqvClass) );
    111144        }
    112145
     
    116149                        newClass.vars.insert( (*i)->get_name() );
    117150                        newClass.data = TypeDecl::Data{ (*i) };
    118                         env.push_back( newClass );
    119                 } // for
     151                        env.push_back( std::move(newClass) );
     152                } // for
     153        }
     154
     155        void TypeEnvironment::add( const TypeSubstitution & sub ) {
     156                EqvClass newClass;
     157                for ( auto p : sub ) {
     158                        newClass.vars.insert( p.first );
     159                        newClass.type = p.second->clone();
     160                        newClass.allowWidening = false;
     161                        // Minimal assumptions. Not technically correct, but might be good enough, and
     162                        // is the best we can do at the moment since information is lost in the
     163                        // transition to TypeSubstitution
     164                        newClass.data = TypeDecl::Data{ TypeDecl::Dtype, false };
     165                        add( std::move(newClass) );
     166                }
    120167        }
    121168
     
    123170                for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
    124171                        for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
    125 ///       std::cerr << "adding " << *theVar;
    126172                                if ( theClass->type ) {
    127 ///         std::cerr << " bound to ";
    128 ///         theClass->type->print( std::cerr );
    129 ///         std::cerr << std::endl;
    130173                                        sub.add( *theVar, theClass->type );
    131174                                } else if ( theVar != theClass->vars.begin() ) {
    132175                                        TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype );
    133 ///         std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl;
    134176                                        sub.add( *theVar, newTypeInst );
    135177                                        delete newTypeInst;
     
    137179                        } // for
    138180                } // for
    139 ///   std::cerr << "input env is:" << std::endl;
    140 ///   print( std::cerr, 8 );
    141 ///   std::cerr << "sub is:" << std::endl;
    142 ///   sub.print( std::cerr, 8 );
    143181                sub.normalize();
    144182        }
    145183
    146184        void TypeEnvironment::print( std::ostream &os, Indenter indent ) const {
    147                 for ( std::list< EqvClass >::const_iterator i = env.begin(); i != env.end(); ++i ) {
    148                         i->print( os, indent );
     185                for ( const EqvClass & theClass : env ) {
     186                        theClass.print( os, indent );
    149187                } // for
    150188        }
     
    152190        std::list< EqvClass >::iterator TypeEnvironment::internal_lookup( const std::string &var ) {
    153191                for ( std::list< EqvClass >::iterator i = env.begin(); i != env.end(); ++i ) {
    154                         if ( i->vars.find( var ) == i->vars.end() ) {
    155                                 return i;
    156                         } // if
     192                        if ( i->vars.count( var ) ) return i;
    157193                } // for
    158194                return env.end();
     
    161197        void TypeEnvironment::simpleCombine( const TypeEnvironment &second ) {
    162198                env.insert( env.end(), second.env.begin(), second.env.end() );
    163         }
    164 
    165         void TypeEnvironment::combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) ) {
    166                 TypeEnvironment secondCopy( second );
    167                 for ( std::list< EqvClass >::iterator firstClass = env.begin(); firstClass != env.end(); ++firstClass ) {
    168                         EqvClass &newClass = *firstClass;
    169                         std::set< std::string > newVars;
    170                         for ( std::set< std::string >::const_iterator var = firstClass->vars.begin(); var != firstClass->vars.end(); ++var ) {
    171                                 std::list< EqvClass >::iterator secondClass = secondCopy.internal_lookup( *var );
    172                                 if ( secondClass != secondCopy.env.end() ) {
    173                                         newVars.insert( secondClass->vars.begin(), secondClass->vars.end() );
    174                                         if ( secondClass->type ) {
    175                                                 if ( newClass.type ) {
    176                                                         Type *newType = combineFunc( newClass.type, secondClass->type );
    177                                                         delete newClass.type;
    178                                                         newClass.type = newType;
    179                                                         newClass.allowWidening = newClass.allowWidening && secondClass->allowWidening;
    180                                                 } else {
    181                                                         newClass.type = secondClass->type->clone();
    182                                                         newClass.allowWidening = secondClass->allowWidening;
    183                                                 } // if
    184                                         } // if
    185                                         secondCopy.env.erase( secondClass );
    186                                 } // if
    187                         } // for
    188                         newClass.vars.insert( newVars.begin(), newVars.end() );
    189                 } // for
    190                 for ( std::list< EqvClass >::iterator secondClass = secondCopy.env.begin(); secondClass != secondCopy.env.end(); ++secondClass ) {
    191                         env.push_back( *secondClass );
    192                 } // for
    193199        }
    194200
     
    212218        }
    213219
     220        bool isFtype( Type *type ) {
     221                if ( dynamic_cast< FunctionType* >( type ) ) {
     222                        return true;
     223                } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
     224                        return typeInst->get_isFtype();
     225                } // if
     226                return false;
     227        }
     228
     229        bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) {
     230                switch ( data.kind ) {
     231                  case TypeDecl::Dtype:
     232                        // to bind to an object type variable, the type must not be a function type.
     233                        // if the type variable is specified to be a complete type then the incoming
     234                        // type must also be complete
     235                        // xxx - should this also check that type is not a tuple type and that it's not a ttype?
     236                        return ! isFtype( type ) && (! data.isComplete || type->isComplete() );
     237                  case TypeDecl::Ftype:
     238                        return isFtype( type );
     239                  case TypeDecl::Ttype:
     240                        // ttype unifies with any tuple type
     241                        return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );
     242                  default:
     243                        assertf(false, "Unhandled tyvar kind: %d", data.kind);
     244                } // switch
     245                return false;
     246        }
     247
     248        bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     249
     250                // remove references from other, so that type variables can only bind to value types
     251                bindTo = bindTo->stripReferences();
     252                OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
     253                assert( tyvar != openVars.end() );
     254                if ( ! tyVarCompatible( tyvar->second, bindTo ) ) {
     255                        return false;
     256                } // if
     257                if ( occurs( bindTo, typeInst->get_name(), *this ) ) {
     258                        return false;
     259                } // if
     260                auto curClass = internal_lookup( typeInst->get_name() );
     261                if ( curClass != env.end() ) {
     262                        if ( curClass->type ) {
     263                                Type *common = 0;
     264                                // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
     265                                std::unique_ptr< Type > newType( curClass->type->clone() );
     266                                newType->get_qualifiers() = typeInst->get_qualifiers();
     267                                if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {
     268                                        if ( common ) {
     269                                                common->get_qualifiers() = Type::Qualifiers{};
     270                                                curClass->set_type( common );
     271                                        } // if
     272                                } else return false;
     273                        } else {
     274                                Type* newType = bindTo->clone();
     275                                newType->get_qualifiers() = Type::Qualifiers{};
     276                                curClass->set_type( newType );
     277                                curClass->allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     278                        } // if
     279                } else {
     280                        EqvClass newClass;
     281                        newClass.vars.insert( typeInst->get_name() );
     282                        newClass.type = bindTo->clone();
     283                        newClass.type->get_qualifiers() = Type::Qualifiers();
     284                        newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
     285                        newClass.data = data;
     286                        env.push_back( std::move(newClass) );
     287                } // if
     288                return true;
     289        }
     290
     291        bool TypeEnvironment::bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
     292
     293                auto class1 = internal_lookup( var1->get_name() );
     294                auto class2 = internal_lookup( var2->get_name() );
     295
     296                // exit early if variables already bound together
     297                if ( class1 != env.end() && class1 == class2 ) {
     298                        class1->allowWidening &= widenMode;
     299                        return true;
     300                }
     301
     302                bool widen1 = false, widen2 = false;
     303                const Type *type1 = nullptr, *type2 = nullptr;
     304
     305                // check for existing bindings, perform occurs check
     306                if ( class1 != env.end() ) {
     307                        if ( class1->type ) {
     308                                if ( occurs( class1->type, var2->get_name(), *this ) ) return false;
     309                                type1 = class1->type;
     310                        } // if
     311                        widen1 = widenMode.widenFirst && class1->allowWidening;
     312                } // if
     313                if ( class2 != env.end() ) {
     314                        if ( class2->type ) {
     315                                if ( occurs( class2->type, var1->get_name(), *this ) ) return false;
     316                                type2 = class2->type;
     317                        } // if
     318                        widen2 = widenMode.widenSecond && class2->allowWidening;
     319                } // if
     320
     321                if ( type1 && type2 ) {
     322                        // both classes bound, merge if bound types can be unified
     323                        std::unique_ptr<Type> newType1{ type1->clone() }, newType2{ type2->clone() };
     324                        WidenMode newWidenMode{ widen1, widen2 };
     325                        Type *common = 0;
     326                        if ( unifyInexact( newType1.get(), newType2.get(), *this, need, have, openVars, newWidenMode, indexer, common ) ) {
     327                                class1->vars.insert( class2->vars.begin(), class2->vars.end() );
     328                                class1->allowWidening = widen1 && widen2;
     329                                if ( common ) {
     330                                        common->get_qualifiers() = Type::Qualifiers{};
     331                                        class1->set_type( common );
     332                                }
     333                                env.erase( class2 );
     334                        } else return false;
     335                } else if ( class1 != env.end() && class2 != env.end() ) {
     336                        // both classes exist, at least one unbound, merge unconditionally
     337                        if ( type1 ) {
     338                                class1->vars.insert( class2->vars.begin(), class2->vars.end() );
     339                                class1->allowWidening = widen1;
     340                                env.erase( class2 );
     341                        } else {
     342                                class2->vars.insert( class1->vars.begin(), class1->vars.end() );
     343                                class2->allowWidening = widen2;
     344                                env.erase( class1 );
     345                        } // if
     346                } else if ( class1 != env.end() ) {
     347                        // var2 unbound, add to class1
     348                        class1->vars.insert( var2->get_name() );
     349                        class1->allowWidening = widen1;
     350                } else if ( class2 != env.end() ) {
     351                        // var1 unbound, add to class2
     352                        class2->vars.insert( var1->get_name() );
     353                        class2->allowWidening = widen2;
     354                } else {
     355                        // neither var bound, create new class
     356                        EqvClass newClass;
     357                        newClass.vars.insert( var1->get_name() );
     358                        newClass.vars.insert( var2->get_name() );
     359                        newClass.allowWidening = widen1 && widen2;
     360                        newClass.data = data;
     361                        env.push_back( std::move(newClass) );
     362                } // if
     363                return true;
     364        }
     365
     366        void TypeEnvironment::forbidWidening() {
     367                for ( EqvClass& c : env ) c.allowWidening = false;
     368        }
     369
    214370        std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ) {
    215371                env.print( out );
  • src/ResolvExpr/TypeEnvironment.h

    rf9feab8 r90152a4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:24:58 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:35:45 2017
    13 // Update Count     : 3
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 18 11:58:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    2121#include <set>                         // for set
    2222#include <string>                      // for string
     23#include <utility>                     // for move, swap
     24
     25#include "WidenMode.h"                 // for WidenMode
    2326
    2427#include "SynTree/Declaration.h"       // for TypeDecl::Data, DeclarationWit...
     
    3740        //
    3841        // I've seen a TU go from 54 minutes to 1 minute 34 seconds with the addition of this comparator.
     42        //
     43        // Note: since this compares pointers for position, minor changes in the source file that affect
     44        // memory layout can alter compilation time in unpredictable ways. For example, the placement
     45        // of a line directive can reorder type pointers with respect to each other so that assertions
     46        // are seen in different orders, causing a potentially different number of unification calls when
     47        // resolving assertions. I've seen a TU go from 36 seconds to 27 seconds by reordering line directives
     48        // alone, so it would be nice to fix this comparison so that assertions compare more consistently.
     49        // I've tried to modify this to compare on mangle name instead of type as the second comparator, but
     50        // this causes some assertions to never be recorded. More investigation is needed.
    3951        struct AssertCompare {
    4052                bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const {
     
    6476
    6577                void initialize( const EqvClass &src, EqvClass &dest );
     78                void initialize( const EqvClass &src, EqvClass &dest, const Type *ty );
    6679                EqvClass();
    6780                EqvClass( const EqvClass &other );
     81                EqvClass( const EqvClass &other, const Type *ty );
     82                EqvClass( EqvClass &&other );
    6883                EqvClass &operator=( const EqvClass &other );
     84                EqvClass &operator=( EqvClass &&other );
    6985                ~EqvClass();
    7086                void print( std::ostream &os, Indenter indent = {} ) const;
     87
     88                /// Takes ownership of `ty`, freeing old `type`
     89                void set_type(Type* ty);
    7190        };
    7291
    7392        class TypeEnvironment {
    7493          public:
    75                 bool lookup( const std::string &var, EqvClass &eqvClass ) const;
    76                 void add( const EqvClass &eqvClass );
     94                const EqvClass* lookup( const std::string &var ) const;
     95          private:
     96                void add( EqvClass &&eqvClass  );
     97          public:
    7798                void add( const Type::ForallList &tyDecls );
     99                void add( const TypeSubstitution & sub );
    78100                template< typename SynTreeClass > int apply( SynTreeClass *&type ) const;
    79101                template< typename SynTreeClass > int applyFree( SynTreeClass *&type ) const;
     
    81103                bool isEmpty() const { return env.empty(); }
    82104                void print( std::ostream &os, Indenter indent = {} ) const;
    83                 void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
     105                // void combine( const TypeEnvironment &second, Type *(*combineFunc)( Type*, Type* ) );
    84106                void simpleCombine( const TypeEnvironment &second );
    85107                void extractOpenVars( OpenVarSet &openVars ) const;
     
    90112                void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars );
    91113
    92                 typedef std::list< EqvClass >::iterator iterator;
    93                 iterator begin() { return env.begin(); }
    94                 iterator end() { return env.end(); }
    95                 typedef std::list< EqvClass >::const_iterator const_iterator;
    96                 const_iterator begin() const { return env.begin(); }
    97                 const_iterator end() const { return env.end(); }
     114                /// Binds the type class represented by `typeInst` to the type `bindTo`; will add
     115                /// the class if needed. Returns false on failure.
     116                bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     117               
     118                /// Binds the type classes represented by `var1` and `var2` together; will add
     119                /// one or both classes if needed. Returns false on failure.
     120                bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
     121
     122                /// Disallows widening for all bindings in the environment
     123                void forbidWidening();
     124
     125                using iterator = std::list< EqvClass >::const_iterator;
     126                iterator begin() const { return env.begin(); }
     127                iterator end() const { return env.end(); }
     128
    98129          private:
    99130                std::list< EqvClass > env;
     131               
    100132                std::list< EqvClass >::iterator internal_lookup( const std::string &var );
    101133        };
  • src/ResolvExpr/Unify.cc

    rf9feab8 r90152a4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:27:10 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 16 16:22:54 2017
    13 // Update Count     : 42
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 18 11:58:00 2018
     13// Update Count     : 43
    1414//
    1515
     
    2020#include <set>                    // for set
    2121#include <string>                 // for string, operator==, operator!=, bas...
    22 #include <utility>                // for pair
     22#include <utility>                // for pair, move
    2323
    2424#include "Common/PassVisitor.h"   // for PassVisitor
     
    4444namespace ResolvExpr {
    4545
    46         class Unify : public Visitor {
    47           public:
     46        struct Unify : public WithShortCircuiting {
    4847                Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
    4948
    5049                bool get_result() const { return result; }
     50
     51                void previsit( BaseSyntaxNode * ) { visit_children = false; }
     52
     53                void postvisit( VoidType * voidType );
     54                void postvisit( BasicType * basicType );
     55                void postvisit( PointerType * pointerType );
     56                void postvisit( ArrayType * arrayType );
     57                void postvisit( ReferenceType * refType );
     58                void postvisit( FunctionType * functionType );
     59                void postvisit( StructInstType * aggregateUseType );
     60                void postvisit( UnionInstType * aggregateUseType );
     61                void postvisit( EnumInstType * aggregateUseType );
     62                void postvisit( TraitInstType * aggregateUseType );
     63                void postvisit( TypeInstType * aggregateUseType );
     64                void postvisit( TupleType * tupleType );
     65                void postvisit( VarArgsType * varArgsType );
     66                void postvisit( ZeroType * zeroType );
     67                void postvisit( OneType * oneType );
     68
    5169          private:
    52                 virtual void visit(VoidType *voidType);
    53                 virtual void visit(BasicType *basicType);
    54                 virtual void visit(PointerType *pointerType);
    55                 virtual void visit(ArrayType *arrayType);
    56                 virtual void visit(ReferenceType *refType);
    57                 virtual void visit(FunctionType *functionType);
    58                 virtual void visit(StructInstType *aggregateUseType);
    59                 virtual void visit(UnionInstType *aggregateUseType);
    60                 virtual void visit(EnumInstType *aggregateUseType);
    61                 virtual void visit(TraitInstType *aggregateUseType);
    62                 virtual void visit(TypeInstType *aggregateUseType);
    63                 virtual void visit(TupleType *tupleType);
    64                 virtual void visit(VarArgsType *varArgsType);
    65                 virtual void visit(ZeroType *zeroType);
    66                 virtual void visit(OneType *oneType);
    67 
    6870                template< typename RefType > void handleRefType( RefType *inst, Type *other );
    6971                template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );
     
    127129        }
    128130
    129         bool isFtype( Type *type ) {
    130                 if ( dynamic_cast< FunctionType* >( type ) ) {
    131                         return true;
    132                 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
    133                         return typeInst->get_isFtype();
    134                 } // if
    135                 return false;
    136         }
    137 
    138         bool tyVarCompatible( const TypeDecl::Data & data, Type *type ) {
    139                 switch ( data.kind ) {
    140                   case TypeDecl::Dtype:
    141                         // to bind to an object type variable, the type must not be a function type.
    142                         // if the type variable is specified to be a complete type then the incoming
    143                         // type must also be complete
    144                         // xxx - should this also check that type is not a tuple type and that it's not a ttype?
    145                         return ! isFtype( type ) && (! data.isComplete || type->isComplete() );
    146                   case TypeDecl::Ftype:
    147                         return isFtype( type );
    148                   case TypeDecl::Ttype:
    149                         // ttype unifies with any tuple type
    150                         return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );
    151                 } // switch
    152                 return false;
    153         }
    154 
    155         bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
    156                 // remove references from other, so that type variables can only bind to value types
    157                 other = other->stripReferences();
    158                 OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
    159                 assert( tyvar != openVars.end() );
    160                 if ( ! tyVarCompatible( tyvar->second, other ) ) {
    161                         return false;
    162                 } // if
    163                 if ( occurs( other, typeInst->get_name(), env ) ) {
    164                         return false;
    165                 } // if
    166                 EqvClass curClass;
    167                 if ( env.lookup( typeInst->get_name(), curClass ) ) {
    168                         if ( curClass.type ) {
    169                                 Type *common = 0;
    170                                 // attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
    171                                 std::unique_ptr< Type > newType( curClass.type->clone() );
    172                                 newType->get_qualifiers() = typeInst->get_qualifiers();
    173                                 if ( unifyInexact( newType.get(), other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass.allowWidening, true ), indexer, common ) ) {
    174                                         if ( common ) {
    175                                                 common->get_qualifiers() = Type::Qualifiers();
    176                                                 delete curClass.type;
    177                                                 curClass.type = common;
    178                                                 env.add( curClass );
    179                                         } // if
    180                                         return true;
    181                                 } else {
    182                                         return false;
    183                                 } // if
    184                         } else {
    185                                 curClass.type = other->clone();
    186                                 curClass.type->get_qualifiers() = Type::Qualifiers();
    187                                 curClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    188                                 env.add( curClass );
    189                         } // if
    190                 } else {
    191                         EqvClass newClass;
    192                         newClass.vars.insert( typeInst->get_name() );
    193                         newClass.type = other->clone();
    194                         newClass.type->get_qualifiers() = Type::Qualifiers();
    195                         newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
    196                         newClass.data = data;
    197                         env.add( newClass );
    198                 } // if
    199                 return true;
    200         }
    201 
    202         bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
    203                 bool result = true;
    204                 EqvClass class1, class2;
    205                 bool hasClass1 = false, hasClass2 = false;
    206                 bool widen1 = false, widen2 = false;
    207                 Type *type1 = 0, *type2 = 0;
    208 
    209                 if ( env.lookup( var1->get_name(), class1 ) ) {
    210                         hasClass1 = true;
    211                         if ( class1.type ) {
    212                                 if ( occurs( class1.type, var2->get_name(), env ) ) {
    213                                         return false;
    214                                 } // if
    215                                 type1 = class1.type->clone();
    216                         } // if
    217                         widen1 = widenMode.widenFirst && class1.allowWidening;
    218                 } // if
    219                 if ( env.lookup( var2->get_name(), class2 ) ) {
    220                         hasClass2 = true;
    221                         if ( class2.type ) {
    222                                 if ( occurs( class2.type, var1->get_name(), env ) ) {
    223                                         return false;
    224                                 } // if
    225                                 type2 = class2.type->clone();
    226                         } // if
    227                         widen2 = widenMode.widenSecond && class2.allowWidening;
    228                 } // if
    229 
    230                 if ( type1 && type2 ) {
    231 //    std::cerr << "has type1 && type2" << std::endl;
    232                         WidenMode newWidenMode ( widen1, widen2 );
    233                         Type *common = 0;
    234                         if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) {
    235                                 class1.vars.insert( class2.vars.begin(), class2.vars.end() );
    236                                 class1.allowWidening = widen1 && widen2;
    237                                 if ( common ) {
    238                                         common->get_qualifiers() = Type::Qualifiers();
    239                                         delete class1.type;
    240                                         class1.type = common;
    241                                 } // if
    242                                 env.add( class1 );
    243                         } else {
    244                                 result = false;
    245                         } // if
    246                 } else if ( hasClass1 && hasClass2 ) {
    247                         if ( type1 ) {
    248                                 class1.vars.insert( class2.vars.begin(), class2.vars.end() );
    249                                 class1.allowWidening = widen1;
    250                                 env.add( class1 );
    251                         } else {
    252                                 class2.vars.insert( class1.vars.begin(), class1.vars.end() );
    253                                 class2.allowWidening = widen2;
    254                                 env.add( class2 );
    255                         } // if
    256                 } else if ( hasClass1 ) {
    257                         class1.vars.insert( var2->get_name() );
    258                         class1.allowWidening = widen1;
    259                         env.add( class1 );
    260                 } else if ( hasClass2 ) {
    261                         class2.vars.insert( var1->get_name() );
    262                         class2.allowWidening = widen2;
    263                         env.add( class2 );
    264                 } else {
    265                         EqvClass newClass;
    266                         newClass.vars.insert( var1->get_name() );
    267                         newClass.vars.insert( var2->get_name() );
    268                         newClass.allowWidening = widen1 && widen2;
    269                         newClass.data = data;
    270                         env.add( newClass );
    271                 } // if
    272                 delete type1;
    273                 delete type2;
    274                 return result;
    275         }
    276 
    277131        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    278132                OpenVarSet closedVars;
     
    319173
    320174                if ( isopen1 && isopen2 && entry1->second == entry2->second ) {
    321                         result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     175                        result = env.bindVarToVar( var1, var2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
    322176                } else if ( isopen1 ) {
    323                         result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    324                 } else if ( isopen2 ) {
    325                         result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     177                        result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
     178                } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped?
     179                        result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer );
    326180                } else {
    327                         Unify comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
     181                        PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
    328182                        type1->accept( comparator );
    329                         result = comparator.get_result();
     183                        result = comparator.pass.get_result();
    330184                } // if
    331185#ifdef DEBUG
     
    404258        }
    405259
    406         void Unify::visit( __attribute__((unused)) VoidType *voidType) {
     260        void Unify::postvisit( __attribute__((unused)) VoidType *voidType) {
    407261                result = dynamic_cast< VoidType* >( type2 );
    408262        }
    409263
    410         void Unify::visit(BasicType *basicType) {
     264        void Unify::postvisit(BasicType *basicType) {
    411265                if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    412266                        result = basicType->get_kind() == otherBasic->get_kind();
     
    436290        }
    437291
    438         void Unify::visit(PointerType *pointerType) {
     292        void Unify::postvisit(PointerType *pointerType) {
    439293                if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    440294                        result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    444298        }
    445299
    446         void Unify::visit(ReferenceType *refType) {
     300        void Unify::postvisit(ReferenceType *refType) {
    447301                if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    448302                        result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
     
    452306        }
    453307
    454         void Unify::visit(ArrayType *arrayType) {
     308        void Unify::postvisit(ArrayType *arrayType) {
    455309                ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
    456310                // to unify, array types must both be VLA or both not VLA
     
    537391                void premutate( TypeInstType * ) { visit_children = false; }
    538392                Type * postmutate( TypeInstType * typeInst ) {
    539                         EqvClass eqvClass;
    540                         if ( tenv.lookup( typeInst->get_name(), eqvClass ) ) {
    541                                 if ( eqvClass.data.kind == TypeDecl::Ttype ) {
    542                                         // expand ttype parameter into its actual type
    543                                         if ( eqvClass.type ) {
    544                                                 delete typeInst;
    545                                                 return eqvClass.type->clone();
    546                                         }
     393                        if ( const EqvClass *eqvClass = tenv.lookup( typeInst->get_name() ) ) {
     394                                // expand ttype parameter into its actual type
     395                                if ( eqvClass->data.kind == TypeDecl::Ttype && eqvClass->type ) {
     396                                        delete typeInst;
     397                                        return eqvClass->type->clone();
    547398                                }
    548399                        }
     
    561412                        flatten( dcl->get_type(), back_inserter( types ) );
    562413                        for ( Type * t : types ) {
     414                                // outermost const, volatile, _Atomic qualifiers in parameters should not play a role in the unification of function types, since they do not determine whether a function is callable.
     415                                // Note: MUST consider at least mutex qualifier, since functions can be overloaded on outermost mutex and a mutex function has different requirements than a non-mutex function.
     416                                t->get_qualifiers() -= Type::Qualifiers(Type::Const | Type::Volatile | Type::Atomic);
     417
    563418                                dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) );
    564419                        }
     
    567422        }
    568423
    569         void Unify::visit(FunctionType *functionType) {
     424        void Unify::postvisit(FunctionType *functionType) {
    570425                FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
    571426                if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
     
    578433
    579434                        // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors
    580                         if ( (flatFunc->get_parameters().size() == flatOther->get_parameters().size() && flatFunc->get_returnVals().size() == flatOther->get_returnVals().size()) || flatFunc->isTtype() || flatOther->isTtype() ) {
    581                                 if ( unifyDeclList( flatFunc->get_parameters().begin(), flatFunc->get_parameters().end(), flatOther->get_parameters().begin(), flatOther->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    582                                         if ( unifyDeclList( flatFunc->get_returnVals().begin(), flatFunc->get_returnVals().end(), flatOther->get_returnVals().begin(), flatOther->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     435                        if ( (flatFunc->parameters.size() == flatOther->parameters.size() && flatFunc->returnVals.size() == flatOther->returnVals.size()) || flatFunc->isTtype() || flatOther->isTtype() ) {
     436                                if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
     437                                        if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    583438
    584439                                                // the original types must be used in mark assertions, since pointer comparisons are used
     
    597452                // check that other type is compatible and named the same
    598453                RefType *otherStruct = dynamic_cast< RefType* >( other );
    599                 result = otherStruct && inst->get_name() == otherStruct->get_name();
     454                result = otherStruct && inst->name == otherStruct->name;
    600455        }
    601456
     
    606461                if ( ! result ) return;
    607462                // Check that parameters of types unify, if any
    608                 std::list< Expression* > params = inst->get_parameters();
    609                 std::list< Expression* > otherParams = ((RefType*)other)->get_parameters();
     463                std::list< Expression* > params = inst->parameters;
     464                std::list< Expression* > otherParams = ((RefType*)other)->parameters;
    610465
    611466                std::list< Expression* >::const_iterator it = params.begin(), jt = otherParams.begin();
     
    669524        }
    670525
    671         void Unify::visit(StructInstType *structInst) {
     526        void Unify::postvisit(StructInstType *structInst) {
    672527                handleGenericRefType( structInst, type2 );
    673528        }
    674529
    675         void Unify::visit(UnionInstType *unionInst) {
     530        void Unify::postvisit(UnionInstType *unionInst) {
    676531                handleGenericRefType( unionInst, type2 );
    677532        }
    678533
    679         void Unify::visit(EnumInstType *enumInst) {
     534        void Unify::postvisit(EnumInstType *enumInst) {
    680535                handleRefType( enumInst, type2 );
    681536        }
    682537
    683         void Unify::visit(TraitInstType *contextInst) {
     538        void Unify::postvisit(TraitInstType *contextInst) {
    684539                handleRefType( contextInst, type2 );
    685540        }
    686541
    687         void Unify::visit(TypeInstType *typeInst) {
     542        void Unify::postvisit(TypeInstType *typeInst) {
    688543                assert( openVars.find( typeInst->get_name() ) == openVars.end() );
    689544                TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 );
     
    740595        }
    741596
    742         void Unify::visit(TupleType *tupleType) {
     597        void Unify::postvisit(TupleType *tupleType) {
    743598                if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
    744599                        std::unique_ptr<TupleType> flat1( tupleType->clone() );
     
    757612        }
    758613
    759         void Unify::visit( __attribute__((unused)) VarArgsType *varArgsType ) {
     614        void Unify::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
    760615                result = dynamic_cast< VarArgsType* >( type2 );
    761616        }
    762617
    763         void Unify::visit( __attribute__((unused)) ZeroType *zeroType ) {
     618        void Unify::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
    764619                result = dynamic_cast< ZeroType* >( type2 );
    765620        }
    766621
    767         void Unify::visit( __attribute__((unused)) OneType *oneType ) {
     622        void Unify::postvisit( __attribute__((unused)) OneType *oneType ) {
    768623                result = dynamic_cast< OneType* >( type2 );
    769624        }
  • src/ResolvExpr/Unify.h

    rf9feab8 r90152a4  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 13:09:04 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 21 23:09:34 2017
    13 // Update Count     : 3
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Mon Jun 18 11:58:00 2018
     13// Update Count     : 4
    1414//
    1515
     
    2121#include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data
    2222#include "TypeEnvironment.h"      // for AssertionSet, OpenVarSet
     23#include "WidenMode.h"            // for WidenMode
    2324
    2425class Type;
     
    2930
    3031namespace ResolvExpr {
    31         struct WidenMode {
    32                 WidenMode( bool widenFirst, bool widenSecond ): widenFirst( widenFirst ), widenSecond( widenSecond ) {}
    33                 WidenMode &operator|=( const WidenMode &other ) { widenFirst |= other.widenFirst; widenSecond |= other.widenSecond; return *this; }
    34                 WidenMode &operator&=( const WidenMode &other ) { widenFirst &= other.widenFirst; widenSecond &= other.widenSecond; return *this; }
    35                 WidenMode operator|( const WidenMode &other ) { WidenMode newWM( *this ); newWM |= other; return newWM; }
    36                 WidenMode operator&( const WidenMode &other ) { WidenMode newWM( *this ); newWM &= other; return newWM; }
    37                 operator bool() { return widenFirst && widenSecond; }
    38 
    39                 bool widenFirst : 1, widenSecond : 1;
    40         };
    41 
    42         bool bindVar( TypeInstType *typeInst, Type *other, const TypeDecl::Data & data, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
    4332        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    4433        bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    4534        bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
     35        bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common );
    4636
    4737        template< typename Iterator1, typename Iterator2 >
  • src/ResolvExpr/typeops.h

    rf9feab8 r90152a4  
    5656        void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    5757
     58        /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer
     59        void adjustExprType( Type *& type );
     60
    5861        template< typename ForwardIterator >
    5962        void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
     
    103106
    104107        // in AlternativeFinder.cc
    105         void referenceToRvalueConversion( Expression *& expr );
     108        void referenceToRvalueConversion( Expression *& expr, Cost & cost );
    106109
    107110        // flatten tuple type into list of types
Note: See TracChangeset for help on using the changeset viewer.