Changeset 2162c2c for src/ResolvExpr
- Timestamp:
- Jan 11, 2017, 4:11:02 PM (9 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 075734f
- Parents:
- bb82c03 (diff), d3a85240 (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. - Location:
- src/ResolvExpr
- Files:
-
- 8 edited
-
AdjustExprType.cc (modified) (1 diff)
-
AlternativeFinder.cc (modified) (12 diffs)
-
AlternativeFinder.h (modified) (1 diff)
-
FindOpenVars.cc (modified) (2 diffs)
-
TypeEnvironment.cc (modified) (1 diff)
-
TypeEnvironment.h (modified) (1 diff)
-
Unify.cc (modified) (5 diffs)
-
typeops.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AdjustExprType.cc
rbb82c03 r2162c2c 22 22 class AdjustExprType : public Mutator { 23 23 typedef Mutator Parent; 24 using Parent::mutate; 24 25 public: 25 26 AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer ); -
src/ResolvExpr/AlternativeFinder.cc
rbb82c03 r2162c2c 267 267 std::list< Expression* >& actuals = appExpr->get_args(); 268 268 269 std::list< Type * > formalTypes;270 std::list< Type * >::iterator formalType = formalTypes.end();271 272 269 for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) { 273 270 Type * actualType = (*actualExpr)->get_result(); 274 271 PRINT( 275 272 std::cerr << "actual expression:" << std::endl; 276 273 (*actualExpr)->print( std::cerr, 8 ); 277 274 std::cerr << "--- results are" << std::endl; 278 (*actualExpr)->get_result()->print( std::cerr, 8 ); 279 ) 280 std::list< DeclarationWithType* >::iterator startFormal = formal; 275 actualType->print( std::cerr, 8 ); 276 ) 281 277 Cost actualCost; 282 std::list< Type * > flatActualTypes; 283 flatten( (*actualExpr)->get_result(), back_inserter( flatActualTypes ) ); 284 for ( std::list< Type* >::iterator actualType = flatActualTypes.begin(); actualType != flatActualTypes.end(); ++actualType ) { 285 286 287 // tuple handling code 288 if ( formalType == formalTypes.end() ) { 289 // the type of the formal parameter may be a tuple type. To make this easier to work with, 290 // flatten the tuple type and traverse the resulting list of types, incrementing the formal 291 // iterator once its types have been extracted. Once a particular formal parameter's type has 292 // been exhausted load the next formal parameter's type. 293 if ( formal == formals.end() ) { 294 if ( function->get_isVarArgs() ) { 295 convCost += Cost( 1, 0, 0 ); 296 break; 297 } else { 298 return Cost::infinity; 299 } 300 } 301 formalTypes.clear(); 302 flatten( (*formal)->get_type(), back_inserter( formalTypes ) ); 303 formalType = formalTypes.begin(); 304 ++formal; 278 if ( formal == formals.end() ) { 279 if ( function->get_isVarArgs() ) { 280 convCost += Cost( 1, 0, 0 ); 281 continue; 282 } else { 283 return Cost::infinity; 305 284 } 306 307 PRINT( 308 std::cerr << std::endl << "converting "; 309 (*actualType)->print( std::cerr, 8 ); 310 std::cerr << std::endl << " to "; 311 (*formalType)->print( std::cerr, 8 ); 312 ) 313 Cost newCost = conversionCost( *actualType, *formalType, indexer, alt.env ); 314 PRINT( 315 std::cerr << std::endl << "cost is" << newCost << std::endl; 316 ) 317 318 if ( newCost == Cost::infinity ) { 319 return newCost; 320 } 321 convCost += newCost; 322 actualCost += newCost; 323 324 convCost += Cost( 0, polyCost( *formalType, alt.env, indexer ) + polyCost( *actualType, alt.env, indexer ), 0 ); 325 326 formalType++; 327 } 285 } 286 Type * formalType = (*formal)->get_type(); 287 PRINT( 288 std::cerr << std::endl << "converting "; 289 actualType->print( std::cerr, 8 ); 290 std::cerr << std::endl << " to "; 291 formalType->print( std::cerr, 8 ); 292 ) 293 Cost newCost = conversionCost( actualType, formalType, indexer, alt.env ); 294 PRINT( 295 std::cerr << std::endl << "cost is" << newCost << std::endl; 296 ) 297 298 if ( newCost == Cost::infinity ) { 299 return newCost; 300 } 301 convCost += newCost; 302 actualCost += newCost; 328 303 if ( actualCost != Cost( 0, 0, 0 ) ) { 329 std::list< DeclarationWithType* >::iterator startFormalPlusOne = startFormal; 330 startFormalPlusOne++; 331 if ( formal == startFormalPlusOne ) { 332 // not a tuple type 333 Type *newType = (*startFormal)->get_type()->clone(); 334 alt.env.apply( newType ); 335 *actualExpr = new CastExpr( *actualExpr, newType ); 336 } else { 337 TupleType *newType = new TupleType( Type::Qualifiers() ); 338 for ( std::list< DeclarationWithType* >::iterator i = startFormal; i != formal; ++i ) { 339 newType->get_types().push_back( (*i)->get_type()->clone() ); 340 } 341 alt.env.apply( newType ); 342 *actualExpr = new CastExpr( *actualExpr, newType ); 343 } 344 } 345 304 Type *newType = formalType->clone(); 305 alt.env.apply( newType ); 306 *actualExpr = new CastExpr( *actualExpr, newType ); 307 } 308 convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0 ); 309 ++formal; // can't be in for-loop update because of the continue 346 310 } 347 311 if ( formal != formals.end() ) { … … 364 328 } 365 329 convCost += newCost; 366 367 330 convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0 ); 368 331 } … … 376 339 unifiableVars[ (*tyvar)->get_name() ] = TypeDecl::Data{ *tyvar }; 377 340 for ( std::list< DeclarationWithType* >::iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) { 378 needAssertions[ *assert ] = true;341 needAssertions[ *assert ].isUsed = true; 379 342 } 380 343 /// needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() ); … … 388 351 if ( TupleType * tupleType = dynamic_cast< TupleType * >( formalType ) ) { 389 352 // formalType is a TupleType - group actuals into a TupleExpr whose type unifies with the TupleType 390 TupleExpr * tupleExpr = new TupleExpr();353 std::list< Expression * > exprs; 391 354 for ( Type * type : *tupleType ) { 392 if ( ! instantiateArgument( type, defaultValue, actualIt, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( tupleExpr->get_exprs()) ) ) {393 delete tupleExpr;355 if ( ! instantiateArgument( type, defaultValue, actualIt, actualEnd, openVars, resultEnv, resultNeed, resultHave, indexer, cost, back_inserter( exprs ) ) ) { 356 deleteAll( exprs ); 394 357 return false; 395 358 } 396 359 } 397 tupleExpr->set_result( Tuples::makeTupleType( tupleExpr->get_exprs() ) ); 398 *out++ = tupleExpr; 360 *out++ = new TupleExpr( exprs ); 361 } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) { 362 // xxx - mixing default arguments with variadic?? 363 std::list< Expression * > exprs; 364 for ( ; actualIt != actualEnd; ++actualIt ) { 365 exprs.push_back( actualIt->expr->clone() ); 366 cost += actualIt->cost; 367 } 368 Expression * arg = nullptr; 369 if ( exprs.size() == 1 && Tuples::isTtype( exprs.front()->get_result() ) ) { 370 // the case where a ttype value is passed directly is special, e.g. for argument forwarding purposes 371 // xxx - what if passing multiple arguments, last of which is ttype? 372 // xxx - what would happen if unify was changed so that unifying tuple types flattened both before unifying lists? then pass in TupleType(ttype) below. 373 arg = exprs.front(); 374 } else { 375 arg = new TupleExpr( exprs ); 376 } 377 assert( arg && arg->get_result() ); 378 if ( ! unify( ttype, arg->get_result(), resultEnv, resultNeed, resultHave, openVars, indexer ) ) { 379 return false; 380 } 381 *out++ = arg; 399 382 } else if ( actualIt != actualEnd ) { 400 383 // both actualType and formalType are atomic (non-tuple) types - if they unify … … 483 466 void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) { 484 467 for ( AssertionSet::iterator i = assertSet.begin(); i != assertSet.end(); ++i ) { 485 if ( i->second == true) {468 if ( i->second.isUsed ) { 486 469 i->first->accept( indexer ); 487 470 } … … 494 477 if ( begin == end ) { 495 478 if ( newNeed.empty() ) { 479 PRINT( 480 std::cerr << "all assertions satisfied, output alternative: "; 481 newAlt.print( std::cerr ); 482 std::cerr << std::endl; 483 ); 496 484 *out++ = newAlt; 497 485 return; … … 510 498 511 499 ForwardIterator cur = begin++; 512 if ( ! cur->second ) {500 if ( ! cur->second.isUsed ) { 513 501 inferRecursive( begin, end, newAlt, openVars, decls, newNeed, /*needParents,*/ level, indexer, out ); 514 502 return; // xxx - should this continue? previously this wasn't here, and it looks like it should be … … 554 542 assert( (*candidate)->get_uniqueId() ); 555 543 DeclarationWithType *candDecl = static_cast< DeclarationWithType* >( Declaration::declFromId( (*candidate)->get_uniqueId() ) ); 544 545 // everything with an empty idChain was pulled in by the current assertion. 546 // add current assertion's idChain + current assertion's ID so that the correct inferParameters can be found. 547 for ( auto & a : newerNeed ) { 548 if ( a.second.idChain.empty() ) { 549 a.second.idChain = cur->second.idChain; 550 a.second.idChain.push_back( curDecl->get_uniqueId() ); 551 } 552 } 553 556 554 //AssertionParentSet newNeedParents( needParents ); 557 555 // skip repeatingly-self-recursive assertion satisfaction … … 569 567 ) 570 568 ApplicationExpr *appExpr = static_cast< ApplicationExpr* >( newerAlt.expr ); 569 // follow the current assertion's ID chain to find the correct set of inferred parameters to add the candidate to (i.e. the set of inferred parameters belonging to the entity which requested the assertion parameter). 570 InferredParams * inferParameters = &appExpr->get_inferParams(); 571 for ( UniqueId id : cur->second.idChain ) { 572 inferParameters = (*inferParameters)[ id ].inferParams.get(); 573 } 571 574 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions 572 appExpr->get_inferParams()[ curDecl->get_uniqueId() ] = ParamEntry( (*candidate)->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );575 (*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( (*candidate)->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr ); 573 576 inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, /*newNeedParents,*/ level, indexer, out ); 574 577 } else { … … 609 612 makeUnifiableVars( funcType, openVars, resultNeed ); 610 613 AltList instantiatedActuals; // filled by instantiate function 611 if ( targetType && ! targetType->isVoid() ) {614 if ( targetType && ! targetType->isVoid() && ! funcType->get_returnVals().empty() ) { 612 615 // attempt to narrow based on expected target type 613 616 Type * returnType = funcType->get_returnVals().front()->get_type(); … … 1075 1078 } 1076 1079 1077 void AlternativeFinder::visit( TupleExpr *tupleExpr ) {1080 void AlternativeFinder::visit( UntypedTupleExpr *tupleExpr ) { 1078 1081 std::list< AlternativeFinder > subExprAlternatives; 1079 1082 findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), back_inserter( subExprAlternatives ) ); … … 1081 1084 combos( subExprAlternatives.begin(), subExprAlternatives.end(), back_inserter( possibilities ) ); 1082 1085 for ( std::list< AltList >::const_iterator i = possibilities.begin(); i != possibilities.end(); ++i ) { 1083 TupleExpr *newExpr = new TupleExpr; 1084 makeExprList( *i, newExpr->get_exprs() ); 1085 newExpr->set_result( Tuples::makeTupleType( newExpr->get_exprs() ) ); 1086 std::list< Expression * > exprs; 1087 makeExprList( *i, exprs ); 1086 1088 1087 1089 TypeEnvironment compositeEnv; 1088 1090 simpleCombineEnvironments( i->begin(), i->end(), compositeEnv ); 1089 alternatives.push_back( Alternative( new Expr, compositeEnv, sumCost( *i ) ) );1091 alternatives.push_back( Alternative( new TupleExpr( exprs ) , compositeEnv, sumCost( *i ) ) ); 1090 1092 } // for 1093 } 1094 1095 void AlternativeFinder::visit( TupleExpr *tupleExpr ) { 1096 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1091 1097 } 1092 1098 -
src/ResolvExpr/AlternativeFinder.h
rbb82c03 r2162c2c 64 64 virtual void visit( ConditionalExpr *conditionalExpr ); 65 65 virtual void visit( CommaExpr *commaExpr ); 66 virtual void visit( TupleExpr *tupleExpr );67 66 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ); 68 67 virtual void visit( ConstructorExpr * ctorExpr ); 68 virtual void visit( UntypedTupleExpr *tupleExpr ); 69 virtual void visit( TupleExpr *tupleExpr ); 69 70 virtual void visit( TupleIndexExpr *tupleExpr ); 70 71 virtual void visit( TupleAssignExpr *tupleExpr ); -
src/ResolvExpr/FindOpenVars.cc
rbb82c03 r2162c2c 50 50 openVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) }; 51 51 for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) { 52 needAssertions[ *assert ] = false;52 needAssertions[ *assert ].isUsed = false; 53 53 } 54 54 /// cloneAll( (*i)->get_assertions(), needAssertions ); … … 59 59 closedVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) }; 60 60 for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) { 61 haveAssertions[ *assert ] = false;61 haveAssertions[ *assert ].isUsed = false; 62 62 } 63 63 /// cloneAll( (*i)->get_assertions(), haveAssertions ); -
src/ResolvExpr/TypeEnvironment.cc
rbb82c03 r2162c2c 75 75 for ( AssertionSet::const_iterator i = assertions.begin(); i != assertions.end(); ++i ) { 76 76 i->first->print( os, indent ); 77 if ( i->second ) {77 if ( i->second.isUsed ) { 78 78 os << "(used)"; 79 79 } else { -
src/ResolvExpr/TypeEnvironment.h
rbb82c03 r2162c2c 31 31 bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const; 32 32 }; 33 typedef std::map< DeclarationWithType*, bool, AssertCompare > AssertionSet; 33 struct AssertionSetValue { 34 bool isUsed; 35 // chain of Unique IDs of the assertion declarations. The first ID in the chain is the ID of an assertion on the current type, 36 // with each successive ID being the ID of an assertion pulled in by the previous ID. The last ID in the chain is 37 // the ID of the assertion that pulled in the current assertion. 38 std::list< UniqueId > idChain; 39 }; 40 typedef std::map< DeclarationWithType*, AssertionSetValue, AssertCompare > AssertionSet; 34 41 typedef std::map< std::string, TypeDecl::Data > OpenVarSet; 35 42 -
src/ResolvExpr/Unify.cc
rbb82c03 r2162c2c 26 26 #include "SymTab/Indexer.h" 27 27 #include "Common/utility.h" 28 28 #include "Tuples/Tuples.h" 29 29 30 30 // #define DEBUG … … 157 157 // if the type variable is specified to be a complete type then the incoming 158 158 // type must also be complete 159 // xxx - should this also check that type is not a tuple type and that it's not a ttype? 159 160 return ! isFtype( type, indexer ) && (! data.isComplete || isComplete( type )); 160 161 case TypeDecl::Ftype: 161 162 return isFtype( type, indexer ); 163 case TypeDecl::Ttype: 164 // ttype unifies with any tuple type 165 return dynamic_cast< TupleType * >( type ); 162 166 } // switch 163 assert( false );164 167 return false; 165 168 } … … 431 434 if ( i != assertions.end() ) { 432 435 /// std::cerr << "found it!" << std::endl; 433 i->second = true;436 i->second.isUsed = true; 434 437 } // if 435 438 } … … 485 488 } 486 489 490 template< typename Iterator > 491 std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end ) { 492 std::list< Type * > types; 493 for ( ; begin != end; ++begin ) { 494 // it's guaranteed that a ttype variable will be bound to a flat tuple, so ensure that this results in a flat tuple 495 flatten( (*begin)->get_type(), back_inserter( types ) ); 496 } 497 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) ); 498 } 499 487 500 template< typename Iterator1, typename Iterator2 > 488 501 bool unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 489 502 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) { 490 // Type * commonType; 491 // if ( ! unifyInexact( (*list1Begin)->get_type(), (*list2Begin)->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) { 492 if ( ! unifyExact( (*list1Begin)->get_type(), (*list2Begin)->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 503 Type * t1 = (*list1Begin)->get_type(); 504 Type * t2 = (*list2Begin)->get_type(); 505 bool isTtype1 = Tuples::isTtype( t1 ); 506 bool isTtype2 = Tuples::isTtype( t2 ); 507 // xxx - assumes ttype must be last parameter 508 // xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases. 509 if ( isTtype1 && ! isTtype2 ) { 510 // combine all of the things in list2, then unify 511 return unifyExact( t1, combineTypes( list2Begin, list2End ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 512 } else if ( isTtype2 && ! isTtype1 ) { 513 // combine all of the things in list1, then unify 514 return unifyExact( combineTypes( list1Begin, list1End ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 515 } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) { 493 516 return false; 494 517 } // if 495 518 } // for 496 if ( list1Begin != list1End || list2Begin != list2End ) { 497 return false; 519 // may get to the end of one argument list before the end of the other. This is only okay when the other is a ttype 520 if ( list1Begin != list1End ) { 521 // try unifying empty tuple type with ttype 522 Type * t1 = (*list1Begin)->get_type(); 523 if ( Tuples::isTtype( t1 ) ) { 524 return unifyExact( t1, combineTypes( list2Begin, list2End ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 525 } else return false; 526 } else if ( list2Begin != list2End ) { 527 // try unifying empty tuple type with ttype 528 Type * t2 = (*list2Begin)->get_type(); 529 if ( Tuples::isTtype( t2 ) ) { 530 return unifyExact( combineTypes( list1Begin, list1End ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); 531 } else return false; 498 532 } else { 499 533 return true; 500 534 } // if 535 } 536 537 /// Finds ttypes and replaces them with their expansion, if known. 538 /// This needs to be done so that satisfying ttype assertions is easier. 539 /// If this isn't done then argument lists can have wildly different 540 /// size and structure, when they should be compatible. 541 struct TtypeExpander : public Mutator { 542 TypeEnvironment & env; 543 TtypeExpander( TypeEnvironment & env ) : env( env ) {} 544 Type * mutate( TypeInstType * typeInst ) { 545 EqvClass eqvClass; 546 if ( env.lookup( typeInst->get_name(), eqvClass ) ) { 547 if ( eqvClass.data.kind == TypeDecl::Ttype ) { 548 // expand ttype parameter into its actual type 549 if ( eqvClass.type ) { 550 delete typeInst; 551 return eqvClass.type->clone(); 552 } 553 } 554 } 555 return typeInst; 556 } 557 }; 558 559 /// flattens a list of declarations, so that each tuple type has a single declaration. 560 /// makes use of TtypeExpander to ensure ttypes are flat as well. 561 void flattenList( std::list< DeclarationWithType * > src, std::list< DeclarationWithType * > & dst, TypeEnvironment & env ) { 562 dst.clear(); 563 for ( DeclarationWithType * dcl : src ) { 564 TtypeExpander expander( env ); 565 dcl->acceptMutator( expander ); 566 std::list< Type * > types; 567 flatten( dcl->get_type(), back_inserter( types ) ); 568 for ( Type * t : types ) { 569 dst.push_back( new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, t, nullptr ) ); 570 } 571 delete dcl; 572 } 501 573 } 502 574 … … 504 576 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 505 577 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { 506 if ( functionType->get_parameters().size() == otherFunction->get_parameters().size() && functionType->get_returnVals().size() == otherFunction->get_returnVals().size() ) { 507 if ( unifyDeclList( functionType->get_parameters().begin(), functionType->get_parameters().end(), otherFunction->get_parameters().begin(), otherFunction->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 508 if ( unifyDeclList( functionType->get_returnVals().begin(), functionType->get_returnVals().end(), otherFunction->get_returnVals().begin(), otherFunction->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 509 578 // flatten the parameter lists for both functions so that tuple structure 579 // doesn't affect unification. Must be a clone so that the types don't change. 580 std::unique_ptr<FunctionType> flatFunc( functionType->clone() ); 581 std::unique_ptr<FunctionType> flatOther( otherFunction->clone() ); 582 flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env ); 583 flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env ); 584 585 // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors 586 if ( (flatFunc->get_parameters().size() == flatOther->get_parameters().size() && flatFunc->get_returnVals().size() == flatOther->get_returnVals().size()) || flatFunc->isTtype() || flatOther->isTtype() ) { 587 if ( unifyDeclList( flatFunc->get_parameters().begin(), flatFunc->get_parameters().end(), flatOther->get_parameters().begin(), flatOther->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 588 if ( unifyDeclList( flatFunc->get_returnVals().begin(), flatFunc->get_returnVals().end(), flatOther->get_returnVals().begin(), flatOther->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 589 590 // the original types must be used in mark assertions, since pointer comparisons are used 510 591 markAssertions( haveAssertions, needAssertions, functionType ); 511 592 markAssertions( haveAssertions, needAssertions, otherFunction ); -
src/ResolvExpr/typeops.h
rbb82c03 r2162c2c 164 164 } 165 165 } else { 166 *out++ = type ;166 *out++ = type->clone(); 167 167 } 168 168 }
Note:
See TracChangeset
for help on using the changeset viewer.