Changeset 90152a4 for src/ResolvExpr
- Timestamp:
- Aug 27, 2018, 4:40:34 PM (8 years ago)
- 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. - Location:
- src/ResolvExpr
- Files:
-
- 1 added
- 1 deleted
- 25 edited
-
AdjustExprType.cc (modified) (5 diffs)
-
Alternative.cc (modified) (3 diffs)
-
Alternative.h (modified) (1 diff)
-
AlternativeFinder.cc (modified) (73 diffs)
-
AlternativeFinder.h (modified) (3 diffs)
-
CastCost.cc (modified) (3 diffs)
-
CommonType.cc (modified) (16 diffs)
-
ConversionCost.cc (modified) (21 diffs)
-
ConversionCost.h (modified) (3 diffs)
-
CurrentObject.cc (modified) (9 diffs)
-
ExplodedActual.h (modified) (1 diff)
-
FindOpenVars.cc (modified) (3 diffs)
-
Occurs.cc (modified) (3 diffs)
-
PolyCost.cc (modified) (1 diff)
-
PtrsAssignable.cc (modified) (6 diffs)
-
PtrsCastable.cc (modified) (9 diffs)
-
RenameVars.cc (modified) (2 diffs)
-
RenameVars.h (modified) (1 diff)
-
Resolver.cc (modified) (33 diffs)
-
Resolver.h (modified) (1 diff)
-
TypeEnvironment.cc (modified) (11 diffs)
-
TypeEnvironment.h (modified) (6 diffs)
-
TypeMap.h (deleted)
-
Unify.cc (modified) (18 diffs)
-
Unify.h (modified) (3 diffs)
-
WidenMode.h (added)
-
typeops.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/AdjustExprType.cc
rf9feab8 r90152a4 24 24 class AdjustExprType : public WithShortCircuiting { 25 25 public: 26 AdjustExprType( const TypeEnvironment & env, const SymTab::Indexer &indexer );26 AdjustExprType( const TypeEnvironment & env, const SymTab::Indexer & indexer ); 27 27 void premutate( VoidType * ) { visit_children = false; } 28 28 void premutate( BasicType * ) { visit_children = false; } … … 45 45 46 46 private: 47 const TypeEnvironment & env;48 const SymTab::Indexer & indexer;47 const TypeEnvironment & env; 48 const SymTab::Indexer & indexer; 49 49 }; 50 50 … … 55 55 } 56 56 57 void adjustExprType( Type *& type ) { 58 TypeEnvironment env; 59 SymTab::Indexer indexer; 60 adjustExprType( type, env, indexer ); 61 } 62 57 63 AdjustExprType::AdjustExprType( const TypeEnvironment &env, const SymTab::Indexer &indexer ) 58 64 : env( env ), indexer( indexer ) { … … 60 66 61 67 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 }; 63 69 arrayType->base = nullptr; 64 70 delete arrayType; … … 67 73 68 74 Type * AdjustExprType::postmutate( FunctionType * functionType ) { 69 return new PointerType ( Type::Qualifiers(), functionType );75 return new PointerType{ Type::Qualifiers(), functionType }; 70 76 } 71 77 72 78 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 }; 78 82 } 79 83 } else if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) { 80 84 if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) { 81 85 if ( tyDecl->get_kind() == TypeDecl::Ftype ) { 82 PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst ); 83 return pointerType; 86 return new PointerType{ Type::Qualifiers(), typeInst }; 84 87 } // if 85 88 } // if -
src/ResolvExpr/Alternative.cc
rf9feab8 r90152a4 27 27 28 28 namespace ResolvExpr { 29 Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( 0) {}29 Alternative::Alternative() : cost( Cost::zero ), cvtCost( Cost::zero ), expr( nullptr ) {} 30 30 31 31 Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost ) … … 48 48 } 49 49 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 ) ) { 51 51 other.expr = nullptr; 52 52 } … … 58 58 cvtCost = other.cvtCost; 59 59 expr = other.expr; 60 env = other.env;60 env = std::move( other.env ); 61 61 other.expr = nullptr; 62 62 return *this; -
src/ResolvExpr/Alternative.h
rf9feab8 r90152a4 57 57 /// Moves all elements from src to the beginning of dst 58 58 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 } 59 64 } // namespace ResolvExpr 60 65 -
src/ResolvExpr/AlternativeFinder.cc
rf9feab8 r90152a4 10 10 // Created On : Sat May 16 23:52:08 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Aug 28 13:47:24 201713 // Update Count : 3 212 // Last Modified On : Sat Feb 17 11:19:39 2018 13 // Update Count : 33 14 14 // 15 15 … … 25 25 #include <vector> // for vector 26 26 27 #include "CompilationState.h" // for resolvep 27 28 #include "Alternative.h" // for AltList, Alternative 28 29 #include "AlternativeFinder.h" … … 49 50 #include "typeops.h" // for adjustExprType, polyCost, castCost 50 51 51 extern bool resolvep;52 52 #define PRINT( text ) if ( resolvep ) { text } 53 53 //#define DEBUG_COST … … 60 60 61 61 namespace 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 }; 76 125 77 126 Cost sumCost( const AltList &in ) { … … 127 176 selected[ mangleName ] = current; 128 177 } 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 } 133 192 } else { 134 193 PRINT( … … 152 211 153 212 void renameTypes( Expression *expr ) { 154 expr->get_result()->accept( global_renamer);213 renameTyVars( expr->result ); 155 214 } 156 215 } // namespace 157 216 158 void referenceToRvalueConversion( Expression *& expr ) {217 void referenceToRvalueConversion( Expression *& expr, Cost & cost ) { 159 218 if ( dynamic_cast< ReferenceType * >( expr->get_result() ) ) { 160 219 // cast away reference from expr 161 220 expr = new CastExpr( expr, expr->get_result()->stripReferences()->clone() ); 221 cost.incReference(); 162 222 } 163 223 } … … 185 245 186 246 void AlternativeFinder::find( Expression *expr, bool adjust, bool prune, bool failFast ) { 187 expr->accept( *this ); 247 PassVisitor<Finder> finder( *this ); 248 expr->accept( finder ); 188 249 if ( failFast && alternatives.empty() ) { 189 250 PRINT( 190 251 std::cerr << "No reasonable alternatives for expression " << expr << std::endl; 191 252 ) 192 throw SemanticError( "No reasonable alternatives for expression ", expr);253 SemanticError( expr, "No reasonable alternatives for expression " ); 193 254 } 194 255 if ( prune ) { … … 206 267 stream << "Cannot choose between " << winners.size() << " alternatives for expression\n"; 207 268 expr->print( stream ); 208 stream << " Alternatives are:\n";269 stream << " Alternatives are:\n"; 209 270 printAlts( winners, stream, 1 ); 210 throw SemanticError(stream.str() );271 SemanticError( expr->location, stream.str() ); 211 272 } 212 273 alternatives = move(pruned); … … 244 305 } 245 306 246 void AlternativeFinder:: addAnonConversions( const Alternative & alt ) {307 void AlternativeFinder::Finder::addAnonConversions( const Alternative & alt ) { 247 308 // adds anonymous member interpretations whenever an aggregate value type is seen. 248 309 // 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 249 310 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; 252 313 if ( dynamic_cast< ReferenceType * >( aggrType ) ) { 253 314 aggrType = aggrType->stripReferences(); … … 255 316 } 256 317 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, "" ); 263 322 } // if 264 323 } 265 324 266 325 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 ) { 272 327 std::list< Declaration* > members; 273 328 aggInst->lookup( name, members ); 274 329 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) ); 280 338 } else { 281 339 assert( false ); … … 284 342 } 285 343 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 ) { 287 345 if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) { 288 346 // 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(); 293 348 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 ) ); 298 351 } // if 299 } else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {300 // xxx - temporary hack until 0/1 are int constants301 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 }307 352 } // if 308 353 } 309 354 310 void AlternativeFinder:: visit( ApplicationExpr *applicationExpr ) {355 void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) { 311 356 alternatives.push_back( Alternative( applicationExpr->clone(), env, Cost::zero ) ); 312 357 } … … 386 431 PRINT( std::cerr << "end of formals with varargs function: inc unsafe: " << convCost << std::endl; ; ) 387 432 // convert reference-typed expressions to value-typed expressions 388 referenceToRvalueConversion( *actualExpr );433 referenceToRvalueConversion( *actualExpr, convCost ); 389 434 continue; 390 435 } else { … … 392 437 } 393 438 } 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 } 394 446 Type * formalType = (*formal)->get_type(); 395 447 convCost += computeExpressionConversionCost( *actualExpr, formalType, indexer, alt.env ); … … 409 461 /// Adds type variables to the open variable set and marks their assertions 410 462 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 ) { 412 464 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 ) { 414 466 needAssertions[ *assert ].isUsed = true; 415 467 } … … 418 470 } 419 471 420 // /// Map of declaration uniqueIds (intended to be the assertions in an AssertionSet) to their parents and the number of times they've been included421 //typedef std::unordered_map< UniqueId, std::unordered_map< UniqueId, unsigned > > AssertionParentSet;422 423 472 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 itself425 473 426 474 void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) { … … 433 481 434 482 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 437 485 if ( begin == end ) { 438 486 if ( newNeed.empty() ) { … … 445 493 return; 446 494 } else if ( level >= recursionLimit ) { 447 throw SemanticError("Too many recursive assertions" );495 SemanticError( newAlt.expr->location, "Too many recursive assertions" ); 448 496 } else { 449 497 AssertionSet newerNeed; … … 452 500 printAssertionSet( newNeed, std::cerr, 8 ); 453 501 ) 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 ); 455 503 return; 456 504 } … … 459 507 ForwardIterator cur = begin++; 460 508 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 ); 462 510 return; // xxx - should this continue? previously this wasn't here, and it looks like it should be 463 511 } … … 485 533 Type *adjType = candidate->get_type()->clone(); 486 534 adjustExprType( adjType, newEnv, indexer ); 487 adjType->accept( global_renamer);535 renameTyVars( adjType ); 488 536 PRINT( 489 537 std::cerr << "unifying "; … … 512 560 } 513 561 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 ); 519 563 delete varExpr->get_result(); 520 564 varExpr->set_result( adjType->clone() ); … … 533 577 // XXX: this is a memory leak, but adjType can't be deleted because it might contain assertions 534 578 (*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 ); 536 580 } else { 537 581 delete adjType; … … 541 585 542 586 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 ) { 544 588 // PRINT( 545 589 // std::cerr << "inferParameters: assertions needed are" << std::endl; … … 555 599 addToIndexer( have, decls ); 556 600 AssertionSet newNeed; 557 //AssertionParentSet needParents;558 601 PRINT( 559 602 std::cerr << "env is: " << std::endl; … … 562 605 ) 563 606 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 ); 565 608 // PRINT( 566 609 // std::cerr << "declaration 14 is "; … … 573 616 ConstantExpr* getDefaultValue( Initializer* init ) { 574 617 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 ); 577 622 } 578 623 } … … 596 641 ArgPack() 597 642 : parent(0), expr(), cost(Cost::zero), env(), need(), have(), openVars(), nextArg(0), 598 599 643 tupleStart(0), nextExpl(0), explAlt(0) {} 600 644 … … 648 692 const ExplodedArgs& args, std::vector<ArgPack>& results, std::size_t& genStart, 649 693 const SymTab::Indexer& indexer, unsigned nTuples = 0 ) { 650 if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) {694 if ( TupleType * tupleType = dynamic_cast<TupleType*>( formalType ) ) { 651 695 // formalType is a TupleType - group actuals into a TupleExpr 652 696 ++nTuples; 653 697 for ( Type* type : *tupleType ) { 654 698 // xxx - dropping initializer changes behaviour from previous, but seems correct 699 // ^^^ need to handle the case where a tuple has a default argument 655 700 if ( ! instantiateArgument( 656 701 type, nullptr, args, results, genStart, indexer, nTuples ) ) … … 663 708 } 664 709 return true; 665 } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) {710 } else if ( TypeInstType * ttype = Tuples::isTtype( formalType ) ) { 666 711 // formalType is a ttype, consumes all remaining arguments 667 712 // xxx - mixing default arguments with variadic?? … … 706 751 Type* argType; 707 752 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 710 756 newResult.parent = i; 711 757 std::list<Expression*> emptyList; … … 834 880 indexer ) ) { 835 881 results.emplace_back( 836 i, cnstExpr, move(env), move(need), move(have),882 i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have), 837 883 move(openVars), nextArg, nTuples ); 838 884 } … … 865 911 // consider only first exploded actual 866 912 Expression* expr = expl.exprs.front().get(); 867 Type* actualType = expr-> get_result()->clone();913 Type* actualType = expr->result->clone(); 868 914 869 915 PRINT( … … 892 938 893 939 template<typename OutputIterator> 894 void AlternativeFinder:: validateFunctionAlternative( const Alternative &func, ArgPack& result,940 void AlternativeFinder::Finder::validateFunctionAlternative( const Alternative &func, ArgPack& result, 895 941 const std::vector<ArgPack>& results, OutputIterator out ) { 896 942 ApplicationExpr *appExpr = new ApplicationExpr( func.expr->clone() ); 897 943 // sum cost and accumulate actuals 898 std::list<Expression*>& args = appExpr-> get_args();944 std::list<Expression*>& args = appExpr->args; 899 945 Cost cost = func.cost; 900 946 const ArgPack* pack = &result; … … 915 961 916 962 template<typename OutputIterator> 917 void AlternativeFinder:: makeFunctionAlternatives( const Alternative &func,963 void AlternativeFinder::Finder::makeFunctionAlternatives( const Alternative &func, 918 964 FunctionType *funcType, const ExplodedArgs &args, OutputIterator out ) { 919 965 OpenVarSet funcOpenVars; … … 923 969 // add all type variables as open variables now so that those not used in the parameter 924 970 // 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() ) { 928 974 // 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(); 930 976 if ( ! unify( returnType, targetType, funcEnv, funcNeed, funcHave, funcOpenVars, 931 977 indexer ) ) { … … 940 986 std::size_t genStart = 0; 941 987 942 for ( DeclarationWithType* formal : funcType-> get_parameters()) {988 for ( DeclarationWithType* formal : funcType->parameters ) { 943 989 ObjectDecl* obj = strict_dynamic_cast< ObjectDecl* >( formal ); 944 990 if ( ! instantiateArgument( 945 obj-> get_type(), obj->get_init(), args, results, genStart, indexer ) )991 obj->type, obj->init, args, results, genStart, indexer ) ) 946 992 return; 947 993 } … … 1022 1068 } 1023 1069 1024 void AlternativeFinder:: visit( UntypedExpr *untypedExpr ) {1070 void AlternativeFinder::Finder::postvisit( UntypedExpr *untypedExpr ) { 1025 1071 AlternativeFinder funcFinder( indexer, env ); 1026 funcFinder.findWithAdjustment( untypedExpr-> get_function());1072 funcFinder.findWithAdjustment( untypedExpr->function ); 1027 1073 // 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. 1028 1075 if ( funcFinder.alternatives.empty() ) return; 1029 1076 1030 1077 std::vector< AlternativeFinder > argAlternatives; 1031 findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(),1078 altFinder.findSubExprs( untypedExpr->begin_args(), untypedExpr->end_args(), 1032 1079 back_inserter( argAlternatives ) ); 1033 1080 1034 1081 // take care of possible tuple assignments 1035 1082 // 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 ); 1037 1084 1038 1085 // find function operators … … 1040 1087 AlternativeFinder funcOpFinder( indexer, env ); 1041 1088 // it's ok if there aren't any defined function ops 1042 funcOpFinder.maybeFind( opExpr );1089 funcOpFinder.maybeFind( opExpr ); 1043 1090 PRINT( 1044 1091 std::cerr << "known function ops:" << std::endl; … … 1053 1100 argExpansions.emplace_back(); 1054 1101 auto& argE = argExpansions.back(); 1055 argE.reserve( arg.alternatives.size() );1102 // argE.reserve( arg.alternatives.size() ); 1056 1103 1057 1104 for ( const Alternative& actual : arg ) { … … 1061 1108 1062 1109 AltList candidates; 1063 SemanticError errors;1110 SemanticErrorException errors; 1064 1111 for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) { 1065 1112 try { … … 1069 1116 ) 1070 1117 // 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 ) ) { 1073 1120 Alternative newFunc( *func ); 1074 referenceToRvalueConversion( newFunc.expr );1121 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); 1075 1122 makeFunctionAlternatives( newFunc, function, argExpansions, 1076 1123 std::back_inserter( candidates ) ); 1077 1124 } 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 ) ) { 1082 1128 Alternative newFunc( *func ); 1083 referenceToRvalueConversion( newFunc.expr );1129 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); 1084 1130 makeFunctionAlternatives( newFunc, function, argExpansions, 1085 1131 std::back_inserter( candidates ) ); … … 1087 1133 } // if 1088 1134 } 1089 } catch ( SemanticError &e ) {1135 } catch ( SemanticErrorException &e ) { 1090 1136 errors.append( e ); 1091 1137 } … … 1107 1153 // check if type is a pointer to function 1108 1154 if ( PointerType* pointer = dynamic_cast<PointerType*>( 1109 funcOp->expr-> get_result()->stripReferences() ) ) {1155 funcOp->expr->result->stripReferences() ) ) { 1110 1156 if ( FunctionType* function = 1111 dynamic_cast<FunctionType*>( pointer-> get_base()) ) {1157 dynamic_cast<FunctionType*>( pointer->base ) ) { 1112 1158 Alternative newFunc( *funcOp ); 1113 referenceToRvalueConversion( newFunc.expr );1159 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); 1114 1160 makeFunctionAlternatives( newFunc, function, argExpansions, 1115 1161 std::back_inserter( candidates ) ); 1116 1162 } 1117 1163 } 1118 } catch ( SemanticError &e ) {1164 } catch ( SemanticErrorException &e ) { 1119 1165 errors.append( e ); 1120 1166 } … … 1131 1177 PRINT( 1132 1178 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; 1136 1182 std::cerr << "formals are:" << std::endl; 1137 printAll( function-> get_parameters(), std::cerr, 8 );1183 printAll( function->parameters, std::cerr, 8 ); 1138 1184 std::cerr << "actuals are:" << std::endl; 1139 printAll( appExpr-> get_args(), std::cerr, 8 );1185 printAll( appExpr->args, std::cerr, 8 ); 1140 1186 std::cerr << "bindings are:" << std::endl; 1141 1187 withFunc.env.print( std::cerr, 8 ); 1188 std::cerr << "cost is: " << withFunc.cost << std::endl; 1142 1189 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1143 1190 ) … … 1172 1219 // fix this issue in a more robust way. 1173 1220 targetType = nullptr; 1174 visit( untypedExpr );1221 postvisit( untypedExpr ); 1175 1222 } 1176 1223 } … … 1178 1225 bool isLvalue( Expression *expr ) { 1179 1226 // 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 ) { 1184 1231 AlternativeFinder finder( indexer, env ); 1185 1232 finder.find( addressExpr->get_arg() ); … … 1192 1239 } 1193 1240 1194 void AlternativeFinder:: visit( LabelAddressExpr * expr ) {1241 void AlternativeFinder::Finder::postvisit( LabelAddressExpr * expr ) { 1195 1242 alternatives.push_back( Alternative{ expr->clone(), env, Cost::zero } ); 1196 1243 } 1197 1244 1198 Expression * restructureCast( Expression * argExpr, Type * toType ) {1245 Expression * restructureCast( Expression * argExpr, Type * toType, bool isGenerated ) { 1199 1246 if ( argExpr->get_result()->size() > 1 && ! toType->isVoid() && ! dynamic_cast<ReferenceType *>( toType ) ) { 1200 1247 // Argument expression is a tuple and the target type is not void and not a reference type. … … 1211 1258 // cast each component 1212 1259 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 ) ); 1214 1261 } 1215 1262 delete argExpr; … … 1219 1266 } else { 1220 1267 // 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 ) { 1226 1275 Type *& toType = castExpr->get_result(); 1227 1276 assert( toType ); … … 1232 1281 AlternativeFinder finder( indexer, env ); 1233 1282 finder.targetType = toType; 1234 finder.findWithAdjustment( castExpr-> get_arg());1283 finder.findWithAdjustment( castExpr->arg ); 1235 1284 1236 1285 AltList candidates; … … 1239 1288 OpenVarSet openVars; 1240 1289 1290 alt.env.extractOpenVars( openVars ); 1291 1241 1292 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1242 1293 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1243 1294 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1244 1295 // to. 1245 int discardedValues = alt.expr-> get_result()->size() - castExpr->get_result()->size();1296 int discardedValues = alt.expr->result->size() - castExpr->result->size(); 1246 1297 if ( discardedValues < 0 ) continue; 1247 1298 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1248 1299 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1249 1300 // 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, 1251 1302 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, 1253 1304 alt.env ); 1254 1305 PRINT( … … 1263 1314 // count one safe conversion for each value that is thrown away 1264 1315 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, 1266 1317 alt.cost, thisCost ); 1267 1318 inferParameters( needAssertions, haveAssertions, newAlt, openVars, … … 1278 1329 } 1279 1330 1280 void AlternativeFinder:: visit( VirtualCastExpr * castExpr ) {1331 void AlternativeFinder::Finder::postvisit( VirtualCastExpr * castExpr ) { 1281 1332 assertf( castExpr->get_result(), "Implicate virtual cast targets not yet supported." ); 1282 1333 AlternativeFinder finder( indexer, env ); … … 1290 1341 } 1291 1342 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 ) { 1293 1353 AlternativeFinder funcFinder( indexer, env ); 1294 1354 funcFinder.findWithAdjustment( memberExpr->get_aggregate() ); 1295 1355 for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) { 1296 1356 // 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 1303 1362 // find member of the given type 1304 1363 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) ); 1306 1365 } 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) ); 1308 1367 } 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() ); 1310 1369 } // if 1311 1370 } // for 1312 1371 } 1313 1372 1314 void AlternativeFinder:: visit( MemberExpr *memberExpr ) {1373 void AlternativeFinder::Finder::postvisit( MemberExpr *memberExpr ) { 1315 1374 alternatives.push_back( Alternative( memberExpr->clone(), env, Cost::zero ) ); 1316 1375 } 1317 1376 1318 void AlternativeFinder:: visit( NameExpr *nameExpr ) {1377 void AlternativeFinder::Finder::postvisit( NameExpr *nameExpr ) { 1319 1378 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; ) 1322 1381 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 ); 1326 1388 PRINT( 1327 1389 std::cerr << "decl is "; … … 1332 1394 std::cerr << std::endl; 1333 1395 ) 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) ); 1336 1399 } // for 1337 1400 } 1338 1401 1339 void AlternativeFinder:: visit( VariableExpr *variableExpr ) {1402 void AlternativeFinder::Finder::postvisit( VariableExpr *variableExpr ) { 1340 1403 // not sufficient to clone here, because variable's type may have changed 1341 1404 // 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 ) { 1346 1409 alternatives.push_back( Alternative( constantExpr->clone(), env, Cost::zero ) ); 1347 1410 } 1348 1411 1349 void AlternativeFinder:: visit( SizeofExpr *sizeofExpr ) {1412 void AlternativeFinder::Finder::postvisit( SizeofExpr *sizeofExpr ) { 1350 1413 if ( sizeofExpr->get_isType() ) { 1351 1414 Type * newType = sizeofExpr->get_type()->clone(); … … 1359 1422 findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) ); 1360 1423 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: " ); 1362 1425 } // if 1363 1426 // return the lowest cost alternative for the argument 1364 1427 Alternative &choice = winners.front(); 1365 referenceToRvalueConversion( choice.expr );1428 referenceToRvalueConversion( choice.expr, choice.cost ); 1366 1429 alternatives.push_back( Alternative( new SizeofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1367 1430 } // if 1368 1431 } 1369 1432 1370 void AlternativeFinder:: visit( AlignofExpr *alignofExpr ) {1433 void AlternativeFinder::Finder::postvisit( AlignofExpr *alignofExpr ) { 1371 1434 if ( alignofExpr->get_isType() ) { 1372 1435 Type * newType = alignofExpr->get_type()->clone(); … … 1380 1443 findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) ); 1381 1444 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: " ); 1383 1446 } // if 1384 1447 // return the lowest cost alternative for the argument 1385 1448 Alternative &choice = winners.front(); 1386 referenceToRvalueConversion( choice.expr );1449 referenceToRvalueConversion( choice.expr, choice.cost ); 1387 1450 alternatives.push_back( Alternative( new AlignofExpr( choice.expr->clone() ), choice.env, Cost::zero ) ); 1388 1451 } // if … … 1390 1453 1391 1454 template< typename StructOrUnionType > 1392 void AlternativeFinder:: addOffsetof( StructOrUnionType *aggInst, const std::string &name ) {1455 void AlternativeFinder::Finder::addOffsetof( StructOrUnionType *aggInst, const std::string &name ) { 1393 1456 std::list< Declaration* > members; 1394 1457 aggInst->lookup( name, members ); … … 1403 1466 } 1404 1467 1405 void AlternativeFinder:: visit( UntypedOffsetofExpr *offsetofExpr ) {1468 void AlternativeFinder::Finder::postvisit( UntypedOffsetofExpr *offsetofExpr ) { 1406 1469 AlternativeFinder funcFinder( indexer, env ); 1407 1470 // xxx - resolveTypeof? 1408 1471 if ( StructInstType *structInst = dynamic_cast< StructInstType* >( offsetofExpr->get_type() ) ) { 1409 addOffsetof( structInst, offsetofExpr-> get_member());1472 addOffsetof( structInst, offsetofExpr->member ); 1410 1473 } 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 ) { 1416 1479 alternatives.push_back( Alternative( offsetofExpr->clone(), env, Cost::zero ) ); 1417 1480 } 1418 1481 1419 void AlternativeFinder:: visit( OffsetPackExpr *offsetPackExpr ) {1482 void AlternativeFinder::Finder::postvisit( OffsetPackExpr *offsetPackExpr ) { 1420 1483 alternatives.push_back( Alternative( offsetPackExpr->clone(), env, Cost::zero ) ); 1421 1484 } … … 1436 1499 AltList & alternatives = finder.get_alternatives(); 1437 1500 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 ) ); 1439 1504 for ( DeclarationWithType * retVal : function->returnVals ) { 1440 1505 alternatives.back().expr->result = retVal->get_type()->clone(); … … 1444 1509 } 1445 1510 1446 void AlternativeFinder:: visit( AttrExpr *attrExpr ) {1511 void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) { 1447 1512 // assume no 'pointer-to-attribute' 1448 1513 NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() ); … … 1458 1523 if ( function->get_parameters().size() == 1 ) { 1459 1524 if ( attrExpr->get_isType() ) { 1460 resolveAttr( data, function, attrExpr->get_type(), env, *this);1525 resolveAttr( data, function, attrExpr->get_type(), env, altFinder); 1461 1526 } else { 1462 1527 AlternativeFinder finder( indexer, env ); … … 1464 1529 for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) { 1465 1530 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 ); 1467 1532 } // fi 1468 1533 } // for … … 1473 1538 } else { 1474 1539 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 ) ); 1476 1543 renameTypes( alternatives.back().expr ); 1477 1544 } // for … … 1479 1546 } 1480 1547 1481 void AlternativeFinder:: visit( LogicalExpr *logicalExpr ) {1548 void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) { 1482 1549 AlternativeFinder firstFinder( indexer, env ); 1483 1550 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 ) { 1495 1568 // find alternatives for condition 1496 1569 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 1507 1588 // unify true and false types, then infer parameters to produce new alternatives 1508 1589 OpenVarSet openVars; 1509 1590 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 ); 1511 1592 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(); 1515 1596 // convert both options to the conditional result type 1516 1597 newAlt.cost += computeExpressionConversionCost( newExpr->arg2, newExpr->result, indexer, newAlt.env ); … … 1524 1605 } 1525 1606 1526 void AlternativeFinder:: visit( CommaExpr *commaExpr ) {1607 void AlternativeFinder::Finder::postvisit( CommaExpr *commaExpr ) { 1527 1608 TypeEnvironment newEnv( env ); 1528 1609 Expression *newFirstArg = resolveInVoidContext( commaExpr->get_arg1(), indexer, newEnv ); 1529 1610 AlternativeFinder secondFinder( indexer, newEnv ); 1530 1611 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 ) ); 1533 1614 } // for 1534 1615 delete newFirstArg; 1535 1616 } 1536 1617 1537 void AlternativeFinder:: visit( RangeExpr * rangeExpr ) {1618 void AlternativeFinder::Finder::postvisit( RangeExpr * rangeExpr ) { 1538 1619 // resolve low and high, accept alternatives whose low and high types unify 1539 1620 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 ); 1545 1631 OpenVarSet openVars; 1546 1632 AssertionSet needAssertions, haveAssertions; 1547 Alternative newAlt( 0, second->env, first->cost + second->cost );1633 Alternative newAlt( 0, compositeEnv, first.cost + second.cost ); 1548 1634 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(); 1552 1638 newAlt.expr = newExpr; 1553 1639 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) ); … … 1557 1643 } 1558 1644 1559 void AlternativeFinder:: visit( UntypedTupleExpr *tupleExpr ) {1645 void AlternativeFinder::Finder::postvisit( UntypedTupleExpr *tupleExpr ) { 1560 1646 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(), 1562 1648 back_inserter( subExprAlternatives ) ); 1563 1649 std::vector< AltList > possibilities; … … 1575 1661 } 1576 1662 1577 void AlternativeFinder:: visit( TupleExpr *tupleExpr ) {1663 void AlternativeFinder::Finder::postvisit( TupleExpr *tupleExpr ) { 1578 1664 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1579 1665 } 1580 1666 1581 void AlternativeFinder:: visit( ImplicitCopyCtorExpr * impCpCtorExpr ) {1667 void AlternativeFinder::Finder::postvisit( ImplicitCopyCtorExpr * impCpCtorExpr ) { 1582 1668 alternatives.push_back( Alternative( impCpCtorExpr->clone(), env, Cost::zero ) ); 1583 1669 } 1584 1670 1585 void AlternativeFinder:: visit( ConstructorExpr * ctorExpr ) {1671 void AlternativeFinder::Finder::postvisit( ConstructorExpr * ctorExpr ) { 1586 1672 AlternativeFinder finder( indexer, env ); 1587 1673 // don't prune here, since it's guaranteed all alternatives will have the same type … … 1593 1679 } 1594 1680 1595 void AlternativeFinder:: visit( TupleIndexExpr *tupleExpr ) {1681 void AlternativeFinder::Finder::postvisit( TupleIndexExpr *tupleExpr ) { 1596 1682 alternatives.push_back( Alternative( tupleExpr->clone(), env, Cost::zero ) ); 1597 1683 } 1598 1684 1599 void AlternativeFinder:: visit( TupleAssignExpr *tupleAssignExpr ) {1685 void AlternativeFinder::Finder::postvisit( TupleAssignExpr *tupleAssignExpr ) { 1600 1686 alternatives.push_back( Alternative( tupleAssignExpr->clone(), env, Cost::zero ) ); 1601 1687 } 1602 1688 1603 void AlternativeFinder:: visit( UniqueExpr *unqExpr ) {1689 void AlternativeFinder::Finder::postvisit( UniqueExpr *unqExpr ) { 1604 1690 AlternativeFinder finder( indexer, env ); 1605 1691 finder.findWithAdjustment( unqExpr->get_expr() ); … … 1611 1697 } 1612 1698 1613 void AlternativeFinder:: visit( StmtExpr *stmtExpr ) {1699 void AlternativeFinder::Finder::postvisit( StmtExpr *stmtExpr ) { 1614 1700 StmtExpr * newStmtExpr = stmtExpr->clone(); 1615 1701 ResolvExpr::resolveStmtExpr( newStmtExpr, indexer ); … … 1618 1704 } 1619 1705 1620 void AlternativeFinder:: visit( UntypedInitExpr *initExpr ) {1706 void AlternativeFinder::Finder::postvisit( UntypedInitExpr *initExpr ) { 1621 1707 // handle each option like a cast 1622 1708 AltList candidates; 1623 PRINT( std::cerr << "untyped init expr: " << initExpr << std::endl; ) 1709 PRINT( 1710 std::cerr << "untyped init expr: " << initExpr << std::endl; 1711 ) 1624 1712 // O(N^2) checks of d-types with e-types 1625 1713 for ( InitAlternative & initAlt : initExpr->get_initAlts() ) { … … 1632 1720 AlternativeFinder finder( indexer, env ); 1633 1721 finder.targetType = toType; 1634 finder.findWithAdjustment( initExpr-> get_expr());1722 finder.findWithAdjustment( initExpr->expr ); 1635 1723 for ( Alternative & alt : finder.get_alternatives() ) { 1636 1724 TypeEnvironment newEnv( alt.env ); 1637 1725 AssertionSet needAssertions, haveAssertions; 1638 1726 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 ) 1640 1730 // It's possible that a cast can throw away some values in a multiply-valued expression. (An example is a 1641 1731 // cast-to-void, which casts from one value to zero.) Figure out the prefix of the subexpression results 1642 1732 // that are cast directly. The candidate is invalid if it has fewer results than there are types to cast 1643 1733 // to. 1644 int discardedValues = alt.expr-> get_result()->size() - toType->size();1734 int discardedValues = alt.expr->result->size() - toType->size(); 1645 1735 if ( discardedValues < 0 ) continue; 1646 1736 // xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not 1647 1737 // allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3])) 1648 1738 // 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 ); 1652 1742 if ( thisCost != Cost::infinity ) { 1653 1743 // count one safe conversion for each value that is thrown away 1654 1744 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 ); 1656 1746 inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( candidates ) ); 1657 1747 } … … 1666 1756 findMinCost( minArgCost.begin(), minArgCost.end(), std::back_inserter( alternatives ) ); 1667 1757 } 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 } 1668 1770 } // namespace ResolvExpr 1669 1771 -
src/ResolvExpr/AlternativeFinder.h
rf9feab8 r90152a4 38 38 using ExplodedArgs = std::vector< std::vector< ExplodedActual > >; 39 39 40 class AlternativeFinder : public Visitor{40 class AlternativeFinder { 41 41 public: 42 42 AlternativeFinder( const SymTab::Indexer &indexer, const TypeEnvironment &env ); … … 94 94 void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out ); 95 95 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; 145 97 const SymTab::Indexer &indexer; 146 98 AltList alternatives; … … 174 126 void printAlts( const AltList &list, std::ostream &os, unsigned int indentAmt = 0 ); 175 127 128 /// Adds type variables to the open variable set and marks their assertions 129 void makeUnifiableVars( Type *type, OpenVarSet &unifiableVars, AssertionSet &needAssertions ); 130 176 131 template< typename InputIterator > 177 132 void simpleCombineEnvironments( InputIterator begin, InputIterator end, TypeEnvironment &result ) { -
src/ResolvExpr/CastCost.cc
rf9feab8 r90152a4 31 31 32 32 namespace ResolvExpr { 33 classCastCost : public ConversionCost {33 struct CastCost : public ConversionCost { 34 34 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 ); 36 36 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 ); 39 41 }; 40 42 41 43 Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { 42 44 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 ); 48 48 } else { 49 49 return Cost::infinity; 50 50 } 51 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name()) ) ) {51 } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) { 52 52 // all typedefs should be gone by this point 53 53 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; 56 56 } // if 57 57 } // if … … 74 74 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 75 75 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 ) { 77 77 return ptrsCastable( t1, t2, env, indexer ); 78 78 }); 79 79 } else { 80 CastCost converter( dest, indexer, env);80 PassVisitor<CastCost> converter( dest, indexer, env, castCost ); 81 81 src->accept( converter ); 82 if ( converter. get_cost() == Cost::infinity ) {82 if ( converter.pass.get_cost() == Cost::infinity ) { 83 83 return Cost::infinity; 84 84 } else { 85 85 // xxx - why are we adding cost 0 here? 86 return converter. get_cost() + Cost::zero;86 return converter.pass.get_cost() + Cost::zero; 87 87 } // if 88 88 } // if 89 89 } 90 90 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 ) { 93 93 } 94 94 95 void CastCost:: visit( BasicType *basicType ) {95 void CastCost::postvisit( BasicType *basicType ) { 96 96 PointerType *destAsPointer = dynamic_cast< PointerType* >( dest ); 97 97 if ( destAsPointer && basicType->isInteger() ) { … … 103 103 } 104 104 105 void CastCost:: visit( PointerType *pointerType ) {105 void CastCost::postvisit( PointerType *pointerType ) { 106 106 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 ) ) { 108 108 cost = Cost::safe; 109 109 } else { 110 110 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 ); 114 114 if ( castResult > 0 ) { 115 115 cost = Cost::safe; -
src/ResolvExpr/CommonType.cc
rf9feab8 r90152a4 18 18 #include <utility> // for pair 19 19 20 #include "Common/PassVisitor.h" 20 21 #include "ResolvExpr/TypeEnvironment.h" // for OpenVarSet, AssertionSet 21 22 #include "SymTab/Indexer.h" // for Indexer … … 23 24 #include "SynTree/Type.h" // for BasicType, BasicType::Kind::... 24 25 #include "SynTree/Visitor.h" // for Visitor 25 #include "Unify.h" // for unifyExact, bindVar,WidenMode26 #include "Unify.h" // for unifyExact, WidenMode 26 27 #include "typeops.h" // for isFtype 27 28 28 29 // #define DEBUG 30 #ifdef DEBUG 31 #define PRINT(x) x 32 #else 33 #define PRINT(x) 34 #endif 29 35 30 36 namespace ResolvExpr { 31 class CommonType : public Visitor { 32 public: 37 struct CommonType : public WithShortCircuiting { 33 38 CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ); 34 39 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 35 59 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 52 60 template< typename Pointer > void getCommonWithVoidPointer( Pointer* voidPointer, Pointer* otherPointer ); 53 61 template< typename RefType > void handleRefType( RefType *inst, Type *other ); … … 67 75 // need unify to bind type variables 68 76 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 ) 70 80 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 ) 72 84 common->get_qualifiers() |= t1->get_qualifiers(); 73 85 common->get_qualifiers() |= t2->get_qualifiers(); … … 75 87 } 76 88 } 77 // std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl; 89 PRINT( 90 std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl; 91 ) 78 92 return nullptr; 79 93 } 80 94 81 95 Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) { 82 CommonTypevisitor( type2, widenFirst, widenSecond, indexer, env, openVars );96 PassVisitor<CommonType> visitor( type2, widenFirst, widenSecond, indexer, env, openVars ); 83 97 84 98 int depth1 = type1->referenceDepth(); … … 87 101 int diff = depth1-depth2; 88 102 // 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; 90 104 91 105 // special case where one type has a reference depth of 1 larger than the other 92 106 if ( diff > 0 || diff < 0 ) { 107 PRINT( 108 std::cerr << "reference depth diff: " << diff << std::endl; 109 ) 93 110 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 ); 96 116 result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars ); 97 if ( result ) result = new ReferenceType( ref1->get_qualifiers(), result );98 117 } else { 99 // formal is value, so result should be value100 ReferenceType * ref2 = strict_dynamic_cast< ReferenceType * > ( type2 );118 // deeper on the right 119 assert( ref2 ); 101 120 result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars ); 102 121 } 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 ) 104 132 return result; 105 133 } … … 108 136 109 137 type1->accept( visitor ); 110 Type *result = visitor. get_result();138 Type *result = visitor.pass.get_result(); 111 139 if ( ! result ) { 112 140 // this appears to be handling for opaque type declarations … … 148 176 } 149 177 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 ] = 151 179 { 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 }, 176 206 }; 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 ); 177 211 178 212 CommonType::CommonType( Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) … … 180 214 } 181 215 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 ) { 185 219 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 186 220 BasicType::Kind newType = combinedType[ basicType->get_kind() ][ otherBasic->get_kind() ]; … … 204 238 AssertionSet need, have; 205 239 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; 207 241 } 208 242 } … … 211 245 } 212 246 213 void CommonType:: visit( PointerType *pointerType ) {247 void CommonType::postvisit( PointerType *pointerType ) { 214 248 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 215 249 // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl; … … 233 267 result = otherPointer->clone(); 234 268 } // if 235 result->get_qualifiers() = tq1 | tq2;269 strict_dynamic_cast<PointerType*>(result)->base->get_qualifiers() = tq1 | tq2; 236 270 } else { 237 271 /// std::cerr << "place for ptr-to-type" << std::endl; … … 246 280 } 247 281 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 ) { 251 285 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 252 286 // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl; … … 270 304 result = otherRef->clone(); 271 305 } // if 272 result->get_qualifiers() = tq1 | tq2;306 strict_dynamic_cast<ReferenceType*>(result)->base->get_qualifiers() = tq1 | tq2; 273 307 } else { 274 308 /// std::cerr << "place for ptr-to-type" << std::endl; … … 283 317 } 284 318 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 ) { 290 324 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType* >( type2 ) || dynamic_cast< OneType* >( type2 ) ) { 291 325 // 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 ) { 302 334 if ( widenFirst ) { 303 335 NamedTypeDecl *nt = indexer.lookupType( inst->get_name() ); … … 321 353 } 322 354 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 ) { 327 359 if ( widenFirst ) { 328 360 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< PointerType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { … … 338 370 } 339 371 340 void CommonType:: visit( OneType *oneType ) {372 void CommonType::postvisit( OneType *oneType ) { 341 373 if ( widenFirst ) { 342 374 if ( dynamic_cast< BasicType* >( type2 ) || dynamic_cast< EnumInstType* >( type2 ) ) { -
src/ResolvExpr/ConversionCost.cc
rf9feab8 r90152a4 42 42 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { 43 43 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 ); 50 48 } else { 51 49 return Cost::infinity; 52 50 } 53 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() )) ) {51 } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->name ) ) { 54 52 PRINT( std::cerr << " found" << std::endl; ) 55 53 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 56 54 // all typedefs should be gone by this point 57 55 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; 60 58 } // if 61 59 } // if … … 77 75 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 78 76 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 ){ 80 78 return ptrsAssignable( t1, t2, env ); 81 79 }); 82 80 } else { 83 ConversionCost converter( dest, indexer, env);81 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 84 82 src->accept( converter ); 85 if ( converter. get_cost() == Cost::infinity ) {83 if ( converter.pass.get_cost() == Cost::infinity ) { 86 84 return Cost::infinity; 87 85 } else { 88 return converter. get_cost() + Cost::zero;86 return converter.pass.get_cost() + Cost::zero; 89 87 } // if 90 88 } // if … … 92 90 93 91 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; ) 95 93 if ( diff > 0 ) { 96 94 // 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 ); 98 96 cost.incReference(); 99 97 return cost; 100 98 } else if ( diff < -1 ) { 101 99 // 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 ); 103 101 cost.incReference(); 104 102 return cost; … … 108 106 if ( srcAsRef && destAsRef ) { // pointer-like conversions between references 109 107 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 } 112 119 } 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 ); 114 121 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 115 122 if ( assignResult > 0 ) { … … 121 128 } else { 122 129 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; ) 123 ConversionCost converter( dest, indexer, env);130 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 124 131 src->accept( converter ); 125 return converter. get_cost();132 return converter.pass.get_cost(); 126 133 } // if 127 134 } else { … … 129 136 assert( diff == -1 && destAsRef ); 130 137 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 ) ) { 132 139 PRINT( std::cerr << "converting compatible base type" << std::endl; ) 133 140 if ( src->get_lvalue() ) { … … 137 144 ) 138 145 // 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() ) { 140 147 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() ) { 142 149 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 143 150 } else { 144 151 return Cost::unsafe; 145 152 } // if 146 } else if ( destAsRef-> get_base()->get_const() ) {153 } else if ( destAsRef->base->get_const() ) { 147 154 PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; ) 148 155 // rvalue-to-const-reference conversion: T => const T & … … 161 168 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) { 162 169 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 ) { 168 177 } 169 178 … … 219 228 */ 220 229 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}, 248 260 }; 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 * ) { 251 268 cost = Cost::infinity; 252 269 } 253 270 254 void ConversionCost:: visit(BasicType *basicType) {271 void ConversionCost::postvisit(BasicType *basicType) { 255 272 if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { 256 273 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ]; … … 264 281 // xxx - not positive this is correct, but appears to allow casting int => enum 265 282 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 ) { 272 288 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; ) 277 294 if ( tq1 == tq2 ) { 278 295 // types are the same … … 280 297 } else { 281 298 // types are the same, except otherPointer has more qualifiers 282 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )283 299 cost = Cost::safe; 284 300 } 285 } else { // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?301 } else { 286 302 int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env ); 287 303 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 } 290 311 } else if ( assignResult < 0 ) { 291 312 cost = Cost::unsafe; … … 293 314 // assignResult == 0 means Cost::Infinity 294 315 } // 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 ) { 303 323 // Note: dest can never be a reference, since it would have been caught in an earlier check 304 324 assert( ! dynamic_cast< ReferenceType * >( dest ) ); … … 306 326 // recursively compute conversion cost from T1 to T2. 307 327 // cv can be safely dropped because of 'implicit dereference' behavior. 308 refType->base->accept( *this);328 cost = costFunc( refType->base, dest, indexer, env ); 309 329 if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) { 310 330 cost.incReference(); // prefer exact qualifiers … … 317 337 } 318 338 319 void ConversionCost:: visit( FunctionType * ) {}320 321 void ConversionCost:: visit( StructInstType * inst ) {339 void ConversionCost::postvisit( FunctionType * ) {} 340 341 void ConversionCost::postvisit( StructInstType * inst ) { 322 342 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) { 323 343 if ( inst->name == destAsInst->name ) { … … 327 347 } 328 348 329 void ConversionCost:: visit( UnionInstType * inst ) {349 void ConversionCost::postvisit( UnionInstType * inst ) { 330 350 if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) { 331 351 if ( inst->name == destAsInst->name ) { … … 335 355 } 336 356 337 void ConversionCost:: visit( EnumInstType * ) {357 void ConversionCost::postvisit( EnumInstType * ) { 338 358 static Type::Qualifiers q; 339 359 static BasicType integer( q, BasicType::SignedInt ); 340 integer.accept( *this); // safe if dest >= int360 cost = costFunc( &integer, dest, indexer, env ); // safe if dest >= int 341 361 if ( cost < Cost::unsafe ) { 342 362 cost.incSafe(); … … 344 364 } 345 365 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 ); 353 371 } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) { 354 if ( inst-> get_name() == destAsInst->get_name()) {372 if ( inst->name == destAsInst->name ) { 355 373 cost = Cost::zero; 356 374 } 357 } else if ( ( namedType = indexer.lookupType( inst->get_name() )) ) {375 } else if ( NamedTypeDecl *namedType = indexer.lookupType( inst->name ) ) { 358 376 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 359 377 // all typedefs should be gone by this point 360 378 assert( type ); 361 if ( type-> get_base()) {362 cost = co nversionCost( 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 ) { 368 386 Cost c = Cost::zero; 369 387 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 = co nversionCost( *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 ); 374 392 if ( newCost == Cost::infinity ) { 375 393 return; … … 377 395 c += newCost; 378 396 } // while 379 if ( destIt != destAsTuple-> get_types().end() ) {397 if ( destIt != destAsTuple->types.end() ) { 380 398 cost = Cost::infinity; 381 399 } else { … … 385 403 } 386 404 387 void ConversionCost:: visit( VarArgsType * ) {405 void ConversionCost::postvisit( VarArgsType * ) { 388 406 if ( dynamic_cast< VarArgsType* >( dest ) ) { 389 407 cost = Cost::zero; … … 391 409 } 392 410 393 void ConversionCost:: visit( ZeroType * ) {411 void ConversionCost::postvisit( ZeroType * ) { 394 412 if ( dynamic_cast< ZeroType * >( dest ) ) { 395 413 cost = Cost::zero; … … 408 426 } 409 427 410 void ConversionCost:: visit( OneType * ) {428 void ConversionCost::postvisit( OneType * ) { 411 429 if ( dynamic_cast< OneType * >( dest ) ) { 412 430 cost = Cost::zero; -
src/ResolvExpr/ConversionCost.h
rf9feab8 r90152a4 19 19 20 20 #include "Cost.h" // for Cost 21 22 #include "Common/PassVisitor.h" 21 23 #include "SynTree/Visitor.h" // for Visitor 22 24 #include "SynTree/SynTree.h" // for Visitor Nodes … … 29 31 class TypeEnvironment; 30 32 31 class ConversionCost : public Visitor { 33 typedef std::function<Cost(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> CostFunction; 34 struct ConversionCost : public WithShortCircuiting { 32 35 public: 33 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );36 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction ); 34 37 35 38 Cost get_cost() const { return cost; } 36 39 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 ); 52 57 protected: 53 58 Type *dest; … … 55 60 Cost cost; 56 61 const TypeEnvironment &env; 62 CostFunction costFunc; 57 63 }; 58 64 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; 60 66 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ); 61 67 } // namespace ResolvExpr -
src/ResolvExpr/CurrentObject.cc
rf9feab8 r90152a4 38 38 39 39 namespace 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 error46 }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 error53 }54 }55 56 40 template< typename AggrInst > 57 41 TypeSubstitution makeGenericSubstitution( AggrInst * inst ) { … … 78 62 virtual ~MemberIterator() {} 79 63 64 /// walks the current object using the given designators as a guide 80 65 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 81 68 virtual std::list<InitAlternative> operator*() const = 0; 69 70 /// true if the iterator is not currently at the end 82 71 virtual operator bool() const = 0; 72 73 /// moves the iterator by one member in the current object 83 74 virtual MemberIterator & bigStep() = 0; 75 76 /// moves the iterator by one member in the current subobject 84 77 virtual MemberIterator & smallStep() = 0; 78 79 /// the type of the current object 85 80 virtual Type * getType() = 0; 81 82 /// the type of the current subobject 86 83 virtual Type * getNext() = 0; 87 84 85 /// printing for debug 88 86 virtual void print( std::ostream & out, Indenter indent ) const = 0; 89 87 88 /// helper for operator*; aggregates must add designator to each init alternative, but 89 /// adding designators in operator* creates duplicates. 90 90 virtual std::list<InitAlternative> first() const = 0; // should be protected 91 91 }; … … 139 139 ArrayIterator( ArrayType * at ) : array( at ) { 140 140 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) 141 base = at-> get_base();141 base = at->base; 142 142 memberIter = createMemberIterator( base ); 143 setSize( at->get_dimension() ); 143 if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=: " ); 144 setSize( at->dimension ); 144 145 } 145 146 … … 149 150 150 151 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; 157 156 } 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 this157 SemanticError( expr->location, toString("Array designator must be a constant expression: ", expr) ); 159 158 } 160 159 } … … 164 163 // need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions 165 164 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 } 167 170 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 168 171 setPosition( castExpr->get_arg() ); 169 172 } 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 } 172 179 } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) { 173 180 index = 0; // xxx - get actual sizeof/alignof value? … … 350 357 } 351 358 } 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 ) { 354 360 // xxx - what about case of empty struct?? 355 361 // only add self if at the very beginning of the structure … … 385 391 return *this; 386 392 } 387 virtual std::list<InitAlternative> first() const { return std::list<InitAlternative>{}; }388 393 }; 389 394 … … 439 444 return new UnionIterator( uit ); 440 445 } 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() ); 442 447 return new SimpleIterator( type ); 443 448 } … … 514 519 } // for 515 520 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: ") ); 517 522 } else if ( desigAlts.size() == 0 ) { 518 throw SemanticError( "No reasonable alternatives for designation: ", designation);523 SemanticError( designation, "No reasonable alternatives for designation: " ); 519 524 } 520 525 DesignatorChain & d = desigAlts.back(); -
src/ResolvExpr/ExplodedActual.h
rf9feab8 r90152a4 32 32 33 33 ExplodedActual() : env(), cost(Cost::zero), exprs() {} 34 35 34 ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer ); 35 ExplodedActual(ExplodedActual&&) = default; 36 ExplodedActual& operator= (ExplodedActual&&) = default; 36 37 }; 37 38 } -
src/ResolvExpr/FindOpenVars.cc
rf9feab8 r90152a4 19 19 #include <map> // for map<>::mapped_type 20 20 21 #include "Common/PassVisitor.h" 21 22 #include "SynTree/Declaration.h" // for TypeDecl, DeclarationWithType (ptr ... 22 23 #include "SynTree/Type.h" // for Type, Type::ForallList, ArrayType 23 #include "SynTree/Visitor.h" // for Visitor24 24 25 25 namespace ResolvExpr { 26 class FindOpenVars : public Visitor { 27 public: 26 struct FindOpenVars : public WithGuards { 28 27 FindOpenVars( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ); 29 28 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 ); 35 33 36 34 void common_action( Type *type ); … … 42 40 43 41 void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) { 44 FindOpenVarsfinder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );42 PassVisitor<FindOpenVars> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen ); 45 43 type->accept( finder ); 46 44 } … … 70 68 } // for 71 69 } // if 72 /// std::c out<< "type is ";73 /// type->print( std::c out);74 /// std::c out<< std::endl << "need is" << std::endl;75 /// printAssertionSet( needAssertions, std::c out);76 /// std::c out<< std::endl << "have is" << std::endl;77 /// printAssertionSet( haveAssertions, std::c out);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 ); 78 76 } 79 77 80 void FindOpenVars:: visit(PointerType *pointerType) {78 void FindOpenVars::previsit(PointerType *pointerType) { 81 79 common_action( pointerType ); 82 Visitor::visit( pointerType );83 80 } 84 81 85 void FindOpenVars:: visit(ArrayType *arrayType) {82 void FindOpenVars::previsit(ArrayType *arrayType) { 86 83 common_action( arrayType ); 87 Visitor::visit( arrayType );88 84 } 89 85 90 void FindOpenVars:: visit(FunctionType *functionType) {86 void FindOpenVars::previsit(FunctionType *functionType) { 91 87 common_action( functionType ); 92 88 nextIsOpen = ! nextIsOpen; 93 Visitor::visit( functionType ); 94 nextIsOpen = ! nextIsOpen; 89 GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } ); 95 90 } 96 91 97 void FindOpenVars:: visit(TupleType *tupleType) {92 void FindOpenVars::previsit(TupleType *tupleType) { 98 93 common_action( tupleType ); 99 Visitor::visit( tupleType );100 94 } 101 95 } // namespace ResolvExpr -
src/ResolvExpr/Occurs.cc
rf9feab8 r90152a4 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Occurs.cc -- 7 // Occurs.cc -- 8 8 // 9 9 // Author : Richard C. Bilson … … 17 17 #include <string> // for string 18 18 19 #include "Common/PassVisitor.h" 19 20 #include "SynTree/Type.h" // for TypeInstType, Type 20 #include "SynTree/Visitor.h" // for Visitor21 21 #include "TypeEnvironment.h" // for EqvClass, TypeEnvironment 22 22 23 23 namespace ResolvExpr { 24 class Occurs : public Visitor { 25 public: 24 struct Occurs : public WithVisitorRef<Occurs> { 26 25 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 30 28 bool result; 31 29 std::set< std::string > eqvVars; 32 const TypeEnvironment & env;30 const TypeEnvironment &tenv; 33 31 }; 34 32 35 33 bool occurs( Type *type, std::string varName, const TypeEnvironment &env ) { 36 Occursoccur( varName, env );34 PassVisitor<Occurs> occur( varName, env ); 37 35 type->accept( occur ); 38 return occur. get_result();36 return occur.pass.result; 39 37 } 40 38 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; 45 42 } else { 46 43 eqvVars.insert( varName ); … … 48 45 } 49 46 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; 55 51 if ( eqvVars.find( typeInst->get_name() ) != eqvVars.end() ) { 56 52 result = true; 57 } else if ( env.lookup( typeInst->get_name(), eqvClass) ) {58 if ( eqvClass .type ) {59 /// std::c out<< typeInst->get_name() << " is bound to";60 /// eqvClass.type->print( std::c out);61 /// std::c out<< 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 ); 63 59 } // if 64 60 } // if -
src/ResolvExpr/PolyCost.cc
rf9feab8 r90152a4 14 14 // 15 15 16 #include "Common/PassVisitor.h" 16 17 #include "SymTab/Indexer.h" // for Indexer 17 18 #include "SynTree/Type.h" // for TypeInstType, Type 18 #include "SynTree/Visitor.h" // for Visitor19 19 #include "TypeEnvironment.h" // for EqvClass, TypeEnvironment 20 20 21 21 namespace ResolvExpr { 22 class PolyCost : public Visitor { 23 public: 22 struct PolyCost { 24 23 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 ); 28 26 int result; 29 const TypeEnvironment & env;27 const TypeEnvironment &tenv; 30 28 const SymTab::Indexer &indexer; 31 29 }; 32 30 33 31 int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) { 34 P olyCostcoster( env, indexer );32 PassVisitor<PolyCost> coster( env, indexer ); 35 33 type->accept( coster ); 36 return coster. get_result();34 return coster.pass.result; 37 35 } 38 36 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 ) { 40 38 } 41 39 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 ) ) { 47 44 if ( indexer.lookupType( otherTypeInst->name ) ) { 48 45 // bound to opaque type -
src/ResolvExpr/PtrsAssignable.cc
rf9feab8 r90152a4 14 14 // 15 15 16 #include "Common/PassVisitor.h" 16 17 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass, TypeEnvironment 17 18 #include "SynTree/Type.h" // for TypeInstType, Type, BasicType … … 20 21 21 22 namespace ResolvExpr { 22 class PtrsAssignable : public Visitor { 23 public: 23 struct PtrsAssignable : public WithShortCircuiting { 24 24 PtrsAssignable( Type *dest, const TypeEnvironment &env ); 25 25 26 26 int get_result() const { return result; } 27 27 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 ); 42 44 private: 43 45 Type *dest; … … 49 51 // std::cerr << "assignable: " << src << " | " << dest << std::endl; 50 52 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 ); 54 55 } // if 55 56 } // if … … 59 60 return -1; 60 61 } else { 61 P trsAssignableptrs( dest, env );62 PassVisitor<PtrsAssignable> ptrs( dest, env ); 62 63 src->accept( ptrs ); 63 return ptrs. get_result();64 return ptrs.pass.get_result(); 64 65 } // if 65 66 } … … 67 68 PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {} 68 69 69 void PtrsAssignable:: visit( __attribute((unused)) VoidType *voidType) {70 void PtrsAssignable::postvisit( VoidType * ) { 70 71 // T * = void * is disallowed - this is a change from C, where any 71 72 // void * can be assigned or passed to a non-void pointer without a cast. 72 73 } 73 74 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 ) {} 78 79 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 ) {} 81 82 82 void PtrsAssignable:: visit( EnumInstType * ) {83 void PtrsAssignable::postvisit( EnumInstType * ) { 83 84 if ( dynamic_cast< BasicType* >( dest ) ) { 84 85 // int * = E *, etc. is safe. This isn't technically correct, as each … … 91 92 } 92 93 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 } 99 101 } // if 100 102 } 101 103 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 ) {} 106 108 107 109 } // namespace ResolvExpr -
src/ResolvExpr/PtrsCastable.cc
rf9feab8 r90152a4 14 14 // 15 15 16 #include "Common/PassVisitor.h" 16 17 #include "ResolvExpr/TypeEnvironment.h" // for EqvClass, TypeEnvironment 17 18 #include "SymTab/Indexer.h" // for Indexer … … 21 22 #include "typeops.h" // for ptrsAssignable 22 23 23 24 24 namespace ResolvExpr { 25 class PtrsCastable : public Visitor{25 struct PtrsCastable : public WithShortCircuiting { 26 26 public: 27 27 PtrsCastable( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ); … … 29 29 int get_result() const { return result; } 30 30 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 ); 45 47 private: 46 48 Type *dest; … … 55 57 return -1; 56 58 } else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( src ) ) { 57 EqvClass eqvClass;58 59 if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) { 59 60 if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) { … … 62 63 } // if 63 64 } //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 ) { 66 67 return -1; 67 68 } // if … … 77 78 int ptrsCastable( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { 78 79 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 ); 82 83 } // if 83 84 } // if … … 85 86 return objectCast( src, env, indexer ); 86 87 } else { 87 P trsCastableptrs( dest, env, indexer );88 PassVisitor<PtrsCastable> ptrs( dest, env, indexer ); 88 89 src->accept( ptrs ); 89 return ptrs. get_result();90 return ptrs.pass.get_result(); 90 91 } // if 91 92 } … … 95 96 } 96 97 97 void PtrsCastable:: visit( VoidType * ) {98 void PtrsCastable::postvisit( VoidType * ) { 98 99 result = objectCast( dest, env, indexer ); 99 100 } 100 101 101 void PtrsCastable:: visit( BasicType * ) {102 void PtrsCastable::postvisit( BasicType * ) { 102 103 result = objectCast( dest, env, indexer ); 103 104 } 104 105 105 void PtrsCastable:: visit( PointerType * ) {106 void PtrsCastable::postvisit( PointerType * ) { 106 107 result = objectCast( dest, env, indexer ); 107 108 } 108 109 109 void PtrsCastable:: visit( ArrayType * ) {110 void PtrsCastable::postvisit( ArrayType * ) { 110 111 result = objectCast( dest, env, indexer ); 111 112 } 112 113 113 void PtrsCastable:: visit( FunctionType * ) {114 void PtrsCastable::postvisit( FunctionType * ) { 114 115 // result = -1; 115 116 result = functionCast( dest, env, indexer ); 116 117 } 117 118 118 void PtrsCastable:: visit( StructInstType * ) {119 void PtrsCastable::postvisit( StructInstType * ) { 119 120 result = objectCast( dest, env, indexer ); 120 121 } 121 122 122 void PtrsCastable:: visit( UnionInstType * ) {123 void PtrsCastable::postvisit( UnionInstType * ) { 123 124 result = objectCast( dest, env, indexer ); 124 125 } 125 126 126 void PtrsCastable:: visit( EnumInstType * ) {127 void PtrsCastable::postvisit( EnumInstType * ) { 127 128 if ( dynamic_cast< EnumInstType* >( dest ) ) { 128 129 result = 1; … … 138 139 } 139 140 140 void PtrsCastable:: visit( TraitInstType * ) {}141 void PtrsCastable::postvisit( TraitInstType * ) {} 141 142 142 void PtrsCastable:: visit(TypeInstType *inst) {143 void PtrsCastable::postvisit(TypeInstType *inst) { 143 144 //result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1; 144 145 result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1; 145 146 } 146 147 147 void PtrsCastable:: visit( TupleType * ) {148 void PtrsCastable::postvisit( TupleType * ) { 148 149 result = objectCast( dest, env, indexer ); 149 150 } 150 151 151 void PtrsCastable:: visit( VarArgsType * ) {152 void PtrsCastable::postvisit( VarArgsType * ) { 152 153 result = objectCast( dest, env, indexer ); 153 154 } 154 155 155 void PtrsCastable:: visit( ZeroType * ) {156 void PtrsCastable::postvisit( ZeroType * ) { 156 157 result = objectCast( dest, env, indexer ); 157 158 } 158 159 159 void PtrsCastable:: visit( OneType * ) {160 void PtrsCastable::postvisit( OneType * ) { 160 161 result = objectCast( dest, env, indexer ); 161 162 } -
src/ResolvExpr/RenameVars.cc
rf9feab8 r90152a4 19 19 #include <utility> // for pair 20 20 21 #include "Common/PassVisitor.h" 21 22 #include "Common/SemanticError.h" // for SemanticError 22 23 #include "RenameVars.h" … … 27 28 28 29 namespace ResolvExpr { 29 RenameVars global_renamer; 30 namespace { 31 struct RenameVars { 32 RenameVars(); 33 void reset(); 30 34 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 ); 33 49 } 34 50 35 void RenameVars::reset() { 36 level = 0; 37 resetCount++; 51 void resetTyVarRenaming() { 52 global_renamer.pass.reset(); 38 53 } 39 54 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 } 44 59 45 void RenameVars::visit( BasicType *basicType) {46 typeBefore( basicType );47 typeAfter( basicType );48 }60 void RenameVars::reset() { 61 level = 0; 62 resetCount++; 63 } 49 64 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 } 55 72 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 } 62 90 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 151 98 } // namespace ResolvExpr 152 99 -
src/ResolvExpr/RenameVars.h
rf9feab8 r90152a4 24 24 25 25 namespace 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 * ); 26 28 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(); 55 31 } // namespace ResolvExpr 56 32 -
src/ResolvExpr/Resolver.cc
rf9feab8 r90152a4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Tus Aug 8 16:06:00 201713 // Update Count : 21 211 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Feb 17 11:19:40 2018 13 // Update Count : 213 14 14 // 15 15 … … 30 30 #include "RenameVars.h" // for RenameVars, global_renamer 31 31 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 32 #include "ResolveTypeof.h" // for resolveTypeof33 32 #include "Resolver.h" 34 33 #include "SymTab/Autogen.h" // for SizeType … … 57 56 void postvisit( FunctionDecl *functionDecl ); 58 57 void previsit( ObjectDecl *objectDecll ); 59 void previsit( TypeDecl *typeDecl );60 58 void previsit( EnumDecl * enumDecl ); 59 void previsit( StaticAssertDecl * assertDecl ); 61 60 62 61 void previsit( ArrayType * at ); … … 76 75 void previsit( CatchStmt *catchStmt ); 77 76 void previsit( WaitForStmt * stmt ); 78 void previsit( WithStmt * withStmt );79 77 80 78 void previsit( SingleInit *singleInit ); … … 82 80 void previsit( ConstructorInit *ctorInit ); 83 81 private: 84 typedef std::list< Initializer * >::iterator InitIterator;82 typedef std::list< Initializer * >::iterator InitIterator; 85 83 86 84 template< typename PtrType > 87 85 void handlePtrType( PtrType * type ); 88 86 89 void resolveAggrInit( ReferenceToType *, InitIterator &, InitIterator & ); 90 void resolveSingleAggrInit( Declaration *, InitIterator &, InitIterator &, TypeSubstitution sub ); 91 void fallbackInit( ConstructorInit * ctorInit ); 87 void fallbackInit( ConstructorInit * ctorInit ); 92 88 93 89 Type * functionReturn = nullptr; … … 96 92 }; 97 93 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 98 101 void resolve( std::list< Declaration * > translationUnit ) { 99 102 PassVisitor<Resolver> resolver; … … 106 109 } 107 110 108 // used in resolveTypeof109 Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {110 TypeEnvironment env;111 return resolveInVoidContext( expr, indexer, env );112 }113 114 111 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 ) { 116 151 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 118 154 } 119 155 … … 131 167 } // namespace 132 168 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 133 265 void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 134 global_renamer.reset();266 resetTyVarRenaming(); 135 267 TypeEnvironment env; 136 Expression * newExpr = resolveInVoidContext( untyped, indexer, env );268 Expression * newExpr = resolveInVoidContext( untyped, indexer, env ); 137 269 finishExpr( newExpr, env, untyped->env ); 138 270 delete untyped; … … 141 273 142 274 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 ); 163 276 } 164 277 165 278 void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) { 166 279 assert( untyped && type ); 280 // transfer location to generated cast for error purposes 281 CodeLocation location = untyped->location; 167 282 untyped = new CastExpr( untyped, type ); 283 untyped->location = location; 168 284 findSingleExpression( untyped, indexer ); 169 285 removeExtraneousCast( untyped, indexer ); … … 171 287 172 288 namespace { 173 bool isIntegralType( Type *type ) { 289 bool isIntegralType( const Alternative & alt ) { 290 Type * type = alt.expr->result; 174 291 if ( dynamic_cast< EnumInstType * >( type ) ) { 175 292 return true; … … 184 301 185 302 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 } 219 356 } 220 357 221 358 void Resolver::previsit( ObjectDecl *objectDecl ) { 222 Type *new_type = resolveTypeof( objectDecl->get_type(), indexer );223 objectDecl->set_type( new_type );224 359 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable 225 360 // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes … … 251 386 } 252 387 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 } // if258 }259 260 388 void Resolver::previsit( FunctionDecl *functionDecl ) { 261 389 #if 0 … … 264 392 std::cerr << std::endl; 265 393 #endif 266 Type *new_type = resolveTypeof( functionDecl->get_type(), indexer );267 functionDecl->set_type( new_type );268 394 GuardValue( functionReturn ); 269 functionReturn = ResolvExpr::extractResultType( functionDecl-> get_functionType());395 functionReturn = ResolvExpr::extractResultType( functionDecl->type ); 270 396 } 271 397 … … 274 400 // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently 275 401 // see how it's useful. 276 for ( Declaration * d : functionDecl-> get_functionType()->get_parameters()) {402 for ( Declaration * d : functionDecl->type->parameters ) { 277 403 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; 281 407 } 282 408 } … … 290 416 } 291 417 418 void Resolver::previsit( StaticAssertDecl * assertDecl ) { 419 findIntegralExpression( assertDecl->condition, indexer ); 420 } 421 292 422 void Resolver::previsit( ExprStmt *exprStmt ) { 293 423 visit_children = false; … … 311 441 312 442 void Resolver::previsit( IfStmt *ifStmt ) { 313 find SingleExpression( ifStmt->condition, indexer );443 findIntegralExpression( ifStmt->condition, indexer ); 314 444 } 315 445 316 446 void Resolver::previsit( WhileStmt *whileStmt ) { 317 find SingleExpression( whileStmt->condition, indexer );447 findIntegralExpression( whileStmt->condition, indexer ); 318 448 } 319 449 320 450 void Resolver::previsit( ForStmt *forStmt ) { 321 451 if ( forStmt->condition ) { 322 find SingleExpression( forStmt->condition, indexer );452 findIntegralExpression( forStmt->condition, indexer ); 323 453 } // if 324 454 … … 336 466 337 467 void Resolver::previsit( CaseStmt *caseStmt ) { 338 if ( caseStmt-> get_condition()) {468 if ( caseStmt->condition ) { 339 469 std::list< InitAlternative > initAlts = currentObject.getOptions(); 340 470 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." ); … … 342 472 Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() ); 343 473 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; 348 483 } 349 484 } … … 411 546 ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name; 412 547 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"); 414 553 } 415 554 … … 428 567 // try matching the arguments to the parameters 429 568 // not the other way around because we have more arguments than parameters 430 SemanticError errors;569 SemanticErrorException errors; 431 570 for ( Alternative & func : funcFinder.get_alternatives() ) { 432 571 try { 433 572 PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() ); 434 573 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" ); 436 575 } 437 576 438 577 FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() ); 439 578 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" ); 441 580 } 442 581 … … 447 586 448 587 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"); 450 589 } 451 590 } … … 453 592 Alternative newFunc( func ); 454 593 // Strip reference from function 455 referenceToRvalueConversion( newFunc.expr );594 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); 456 595 457 596 // For all the set of arguments we have try to match it with the parameter of the current function alternative … … 462 601 OpenVarSet openVars; 463 602 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 ); 465 608 466 609 // Load type variables from arguemnts into one shared space … … 468 611 469 612 // Make sure we don't widen any existing bindings 470 for ( auto & i : resultEnv ) { 471 i.allowWidening = false; 472 } 613 resultEnv.forbidWidening(); 473 614 474 615 // Find any unbound type variables … … 477 618 auto param = function->parameters.begin(); 478 619 auto param_end = function->parameters.end(); 620 621 int n_mutex_param = 0; 479 622 480 623 // For every arguments of its set, check if it matches one of the parameter … … 486 629 // We ran out of parameters but still have arguments 487 630 // 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" )); 489 632 } 490 633 634 n_mutex_param++; 635 491 636 // 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 ) ) { 493 638 // Type doesn't match 494 639 stringstream ss; 495 640 ss << "candidate function not viable: no known convertion from '"; 641 (*param)->get_type()->print( ss ); 642 ss << "' to '"; 496 643 arg.expr->get_result()->print( ss ); 497 ss << "' to'";498 (*param)->get_type()->print( ss);644 ss << "' with env '"; 645 resultEnv.print(ss); 499 646 ss << "'\n"; 500 throw SemanticError(ss.str(), function);647 SemanticError( function, ss.str() ); 501 648 } 502 649 … … 508 655 // Check if parameters are missing 509 656 if( advance_to_mutex( param, param_end ) ) { 657 do { 658 n_mutex_param++; 659 param++; 660 } while( advance_to_mutex( param, param_end ) ); 661 510 662 // We ran out of arguments but still have parameters left 511 663 // 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" )); 513 665 } 514 666 … … 526 678 527 679 } 528 catch( SemanticError &e ) {680 catch( SemanticErrorException &e ) { 529 681 errors.append( e ); 530 682 } 531 683 } 532 684 } 533 catch( SemanticError &e ) {685 catch( SemanticErrorException &e ) { 534 686 errors.append( e ); 535 687 } … … 537 689 538 690 // 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. 544 696 545 697 // Swap the results from the alternative with the unresolved values. … … 574 726 } 575 727 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 candidates588 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 candidates596 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 statement610 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 once617 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 them624 tmp->init = InitTweak::genCtorInit( tmp );625 tmp->accept( *visitor );626 }627 }628 }629 }630 631 728 template< typename T > 632 729 bool isCharType( T t ) { … … 652 749 initExpr->expr = nullptr; 653 750 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 ); 655 754 delete initExpr; 656 755 … … 740 839 PassVisitor<Resolver> resolver( indexer ); 741 840 stmtExpr->accept( resolver ); 841 stmtExpr->computeResult(); 842 // xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead? 742 843 } 743 844 … … 745 846 visit_children = false; 746 847 // 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 ); 749 850 750 851 // 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; 753 854 754 855 // intrinsic single parameter constructors and destructors do nothing. Since this was 755 856 // implicitly generated, there's no way for it to have side effects, so get rid of it 756 857 // 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; 765 866 } 766 867 -
src/ResolvExpr/Resolver.h
rf9feab8 r90152a4 33 33 void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ); 34 34 void findSingleExpression( Expression *& untyped, const SymTab::Indexer &indexer ); 35 void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer &indexer ); 35 36 void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ); 36 37 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 ); 37 42 } // namespace ResolvExpr 38 43 -
src/ResolvExpr/TypeEnvironment.cc
rf9feab8 r90152a4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:19:47 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sun May 17 12:23:36 201513 // Update Count : 311 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 18 11:58:00 2018 13 // Update Count : 4 14 14 // 15 15 … … 17 17 #include <algorithm> // for copy, set_intersection 18 18 #include <iterator> // for ostream_iterator, insert_iterator 19 #include <utility> // for pair 19 #include <memory> // for unique_ptr 20 #include <utility> // for pair, move 20 21 21 22 #include "Common/utility.h" // for maybeClone 22 23 #include "SynTree/Type.h" // for Type, FunctionType, Type::Fora... 23 24 #include "SynTree/TypeSubstitution.h" // for TypeSubstitution 25 #include "Tuples/Tuples.h" // for isTtype 24 26 #include "TypeEnvironment.h" 27 #include "typeops.h" // for occurs 28 #include "Unify.h" // for unifyInexact 25 29 26 30 namespace ResolvExpr { … … 44 48 45 49 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 ) { 46 54 dest.vars = src.vars; 47 dest.type = maybeClone( src.type);55 dest.type = maybeClone( ty ); 48 56 dest.allowWidening = src.allowWidening; 49 57 dest.data = src.data; 50 58 } 51 59 52 EqvClass::EqvClass() : type( 0), allowWidening( true ) {60 EqvClass::EqvClass() : type( nullptr ), allowWidening( true ) { 53 61 } 54 62 55 63 EqvClass::EqvClass( const EqvClass &other ) { 56 64 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; 57 75 } 58 76 … … 64 82 } 65 83 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 66 97 EqvClass::~EqvClass() { 67 98 delete type; 99 } 100 101 void EqvClass::set_type( Type* ty ) { 102 if ( ty == type ) return; 103 delete type; 104 type = ty; 68 105 } 69 106 … … 82 119 } 83 120 84 bool TypeEnvironment::lookup( const std::string &var, EqvClass &eqvClass) const {121 const EqvClass* TypeEnvironment::lookup( const std::string &var ) const { 85 122 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 ); } 108 137 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) ); 111 144 } 112 145 … … 116 149 newClass.vars.insert( (*i)->get_name() ); 117 150 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 } 120 167 } 121 168 … … 123 170 for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) { 124 171 for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) { 125 /// std::cerr << "adding " << *theVar;126 172 if ( theClass->type ) { 127 /// std::cerr << " bound to ";128 /// theClass->type->print( std::cerr );129 /// std::cerr << std::endl;130 173 sub.add( *theVar, theClass->type ); 131 174 } else if ( theVar != theClass->vars.begin() ) { 132 175 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;134 176 sub.add( *theVar, newTypeInst ); 135 177 delete newTypeInst; … … 137 179 } // for 138 180 } // 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 );143 181 sub.normalize(); 144 182 } 145 183 146 184 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 ); 149 187 } // for 150 188 } … … 152 190 std::list< EqvClass >::iterator TypeEnvironment::internal_lookup( const std::string &var ) { 153 191 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; 157 193 } // for 158 194 return env.end(); … … 161 197 void TypeEnvironment::simpleCombine( const TypeEnvironment &second ) { 162 198 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 } // if184 } // if185 secondCopy.env.erase( secondClass );186 } // if187 } // for188 newClass.vars.insert( newVars.begin(), newVars.end() );189 } // for190 for ( std::list< EqvClass >::iterator secondClass = secondCopy.env.begin(); secondClass != secondCopy.env.end(); ++secondClass ) {191 env.push_back( *secondClass );192 } // for193 199 } 194 200 … … 212 218 } 213 219 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 214 370 std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env ) { 215 371 env.print( out ); -
src/ResolvExpr/TypeEnvironment.h
rf9feab8 r90152a4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:24:58 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:35:45 201713 // Update Count : 311 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 18 11:58:00 2018 13 // Update Count : 4 14 14 // 15 15 … … 21 21 #include <set> // for set 22 22 #include <string> // for string 23 #include <utility> // for move, swap 24 25 #include "WidenMode.h" // for WidenMode 23 26 24 27 #include "SynTree/Declaration.h" // for TypeDecl::Data, DeclarationWit... … … 37 40 // 38 41 // 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. 39 51 struct AssertCompare { 40 52 bool operator()( DeclarationWithType * d1, DeclarationWithType * d2 ) const { … … 64 76 65 77 void initialize( const EqvClass &src, EqvClass &dest ); 78 void initialize( const EqvClass &src, EqvClass &dest, const Type *ty ); 66 79 EqvClass(); 67 80 EqvClass( const EqvClass &other ); 81 EqvClass( const EqvClass &other, const Type *ty ); 82 EqvClass( EqvClass &&other ); 68 83 EqvClass &operator=( const EqvClass &other ); 84 EqvClass &operator=( EqvClass &&other ); 69 85 ~EqvClass(); 70 86 void print( std::ostream &os, Indenter indent = {} ) const; 87 88 /// Takes ownership of `ty`, freeing old `type` 89 void set_type(Type* ty); 71 90 }; 72 91 73 92 class TypeEnvironment { 74 93 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: 77 98 void add( const Type::ForallList &tyDecls ); 99 void add( const TypeSubstitution & sub ); 78 100 template< typename SynTreeClass > int apply( SynTreeClass *&type ) const; 79 101 template< typename SynTreeClass > int applyFree( SynTreeClass *&type ) const; … … 81 103 bool isEmpty() const { return env.empty(); } 82 104 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* ) ); 84 106 void simpleCombine( const TypeEnvironment &second ); 85 107 void extractOpenVars( OpenVarSet &openVars ) const; … … 90 112 void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars ); 91 113 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 98 129 private: 99 130 std::list< EqvClass > env; 131 100 132 std::list< EqvClass >::iterator internal_lookup( const std::string &var ); 101 133 }; -
src/ResolvExpr/Unify.cc
rf9feab8 r90152a4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:27:10 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Thu Mar 16 16:22:54 201713 // Update Count : 4 211 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 18 11:58:00 2018 13 // Update Count : 43 14 14 // 15 15 … … 20 20 #include <set> // for set 21 21 #include <string> // for string, operator==, operator!=, bas... 22 #include <utility> // for pair 22 #include <utility> // for pair, move 23 23 24 24 #include "Common/PassVisitor.h" // for PassVisitor … … 44 44 namespace ResolvExpr { 45 45 46 class Unify : public Visitor { 47 public: 46 struct Unify : public WithShortCircuiting { 48 47 Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ); 49 48 50 49 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 51 69 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 68 70 template< typename RefType > void handleRefType( RefType *inst, Type *other ); 69 71 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other ); … … 127 129 } 128 130 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 } // if135 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 incoming143 // type must also be complete144 // 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 type150 return dynamic_cast< TupleType * >( type ) || Tuples::isTtype( type );151 } // switch152 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 types157 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 } // if163 if ( occurs( other, typeInst->get_name(), env ) ) {164 return false;165 } // if166 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 to171 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 } // if180 return true;181 } else {182 return false;183 } // if184 } 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 } // if190 } 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 } // if199 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 } // if215 type1 = class1.type->clone();216 } // if217 widen1 = widenMode.widenFirst && class1.allowWidening;218 } // if219 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 } // if225 type2 = class2.type->clone();226 } // if227 widen2 = widenMode.widenSecond && class2.allowWidening;228 } // if229 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 } // if242 env.add( class1 );243 } else {244 result = false;245 } // if246 } 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 } // if256 } 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 } // if272 delete type1;273 delete type2;274 return result;275 }276 277 131 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) { 278 132 OpenVarSet closedVars; … … 319 173 320 174 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 ); 322 176 } 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 ); 326 180 } else { 327 Unifycomparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );181 PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 328 182 type1->accept( comparator ); 329 result = comparator. get_result();183 result = comparator.pass.get_result(); 330 184 } // if 331 185 #ifdef DEBUG … … 404 258 } 405 259 406 void Unify:: visit( __attribute__((unused)) VoidType *voidType) {260 void Unify::postvisit( __attribute__((unused)) VoidType *voidType) { 407 261 result = dynamic_cast< VoidType* >( type2 ); 408 262 } 409 263 410 void Unify:: visit(BasicType *basicType) {264 void Unify::postvisit(BasicType *basicType) { 411 265 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 412 266 result = basicType->get_kind() == otherBasic->get_kind(); … … 436 290 } 437 291 438 void Unify:: visit(PointerType *pointerType) {292 void Unify::postvisit(PointerType *pointerType) { 439 293 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 440 294 result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 444 298 } 445 299 446 void Unify:: visit(ReferenceType *refType) {300 void Unify::postvisit(ReferenceType *refType) { 447 301 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 448 302 result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 452 306 } 453 307 454 void Unify:: visit(ArrayType *arrayType) {308 void Unify::postvisit(ArrayType *arrayType) { 455 309 ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 ); 456 310 // to unify, array types must both be VLA or both not VLA … … 537 391 void premutate( TypeInstType * ) { visit_children = false; } 538 392 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(); 547 398 } 548 399 } … … 561 412 flatten( dcl->get_type(), back_inserter( types ) ); 562 413 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 563 418 dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) ); 564 419 } … … 567 422 } 568 423 569 void Unify:: visit(FunctionType *functionType) {424 void Unify::postvisit(FunctionType *functionType) { 570 425 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 571 426 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { … … 578 433 579 434 // 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 ) ) { 583 438 584 439 // the original types must be used in mark assertions, since pointer comparisons are used … … 597 452 // check that other type is compatible and named the same 598 453 RefType *otherStruct = dynamic_cast< RefType* >( other ); 599 result = otherStruct && inst-> get_name() == otherStruct->get_name();454 result = otherStruct && inst->name == otherStruct->name; 600 455 } 601 456 … … 606 461 if ( ! result ) return; 607 462 // 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; 610 465 611 466 std::list< Expression* >::const_iterator it = params.begin(), jt = otherParams.begin(); … … 669 524 } 670 525 671 void Unify:: visit(StructInstType *structInst) {526 void Unify::postvisit(StructInstType *structInst) { 672 527 handleGenericRefType( structInst, type2 ); 673 528 } 674 529 675 void Unify:: visit(UnionInstType *unionInst) {530 void Unify::postvisit(UnionInstType *unionInst) { 676 531 handleGenericRefType( unionInst, type2 ); 677 532 } 678 533 679 void Unify:: visit(EnumInstType *enumInst) {534 void Unify::postvisit(EnumInstType *enumInst) { 680 535 handleRefType( enumInst, type2 ); 681 536 } 682 537 683 void Unify:: visit(TraitInstType *contextInst) {538 void Unify::postvisit(TraitInstType *contextInst) { 684 539 handleRefType( contextInst, type2 ); 685 540 } 686 541 687 void Unify:: visit(TypeInstType *typeInst) {542 void Unify::postvisit(TypeInstType *typeInst) { 688 543 assert( openVars.find( typeInst->get_name() ) == openVars.end() ); 689 544 TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 ); … … 740 595 } 741 596 742 void Unify:: visit(TupleType *tupleType) {597 void Unify::postvisit(TupleType *tupleType) { 743 598 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) { 744 599 std::unique_ptr<TupleType> flat1( tupleType->clone() ); … … 757 612 } 758 613 759 void Unify:: visit( __attribute__((unused)) VarArgsType *varArgsType ) {614 void Unify::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) { 760 615 result = dynamic_cast< VarArgsType* >( type2 ); 761 616 } 762 617 763 void Unify:: visit( __attribute__((unused)) ZeroType *zeroType ) {618 void Unify::postvisit( __attribute__((unused)) ZeroType *zeroType ) { 764 619 result = dynamic_cast< ZeroType* >( type2 ); 765 620 } 766 621 767 void Unify:: visit( __attribute__((unused)) OneType *oneType ) {622 void Unify::postvisit( __attribute__((unused)) OneType *oneType ) { 768 623 result = dynamic_cast< OneType* >( type2 ); 769 624 } -
src/ResolvExpr/Unify.h
rf9feab8 r90152a4 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 13:09:04 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Jul 21 23:09:34 201713 // Update Count : 311 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Mon Jun 18 11:58:00 2018 13 // Update Count : 4 14 14 // 15 15 … … 21 21 #include "SynTree/Declaration.h" // for TypeDecl, TypeDecl::Data 22 22 #include "TypeEnvironment.h" // for AssertionSet, OpenVarSet 23 #include "WidenMode.h" // for WidenMode 23 24 24 25 class Type; … … 29 30 30 31 namespace 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 );43 32 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ); 44 33 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType ); 45 34 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 ); 46 36 47 37 template< typename Iterator1, typename Iterator2 > -
src/ResolvExpr/typeops.h
rf9feab8 r90152a4 56 56 void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ); 57 57 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 58 61 template< typename ForwardIterator > 59 62 void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment &env, const SymTab::Indexer &indexer ) { … … 103 106 104 107 // in AlternativeFinder.cc 105 void referenceToRvalueConversion( Expression *& expr );108 void referenceToRvalueConversion( Expression *& expr, Cost & cost ); 106 109 107 110 // flatten tuple type into list of types
Note:
See TracChangeset
for help on using the changeset viewer.