Changes in src/ResolvExpr/Resolver.cc [c6b4432:4894239]
- File:
-
- 1 edited
-
src/ResolvExpr/Resolver.cc (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
rc6b4432 r4894239 19 19 #include <vector> // for vector 20 20 21 #include "Alternative.h" // for Alternative, AltList 22 #include "AlternativeFinder.h" // for AlternativeFinder, resolveIn... 21 23 #include "Candidate.hpp" 22 24 #include "CandidateFinder.hpp" … … 38 40 #include "Common/Eval.h" // for eval 39 41 #include "Common/Iterate.hpp" // for group_iterate 42 #include "Common/PassVisitor.h" // for PassVisitor 40 43 #include "Common/SemanticError.h" // for SemanticError 41 44 #include "Common/Stats/ResolveTime.h" // for ResolveTime::start(), ResolveTime::stop() 42 45 #include "Common/ToString.hpp" // for toCString 43 #include "Common/UniqueName.h" // for UniqueName44 46 #include "InitTweak/GenInit.h" 45 47 #include "InitTweak/InitTweak.h" // for isIntrinsicSingleArgCallStmt 48 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 49 #include "SymTab/Autogen.h" // for SizeType 50 #include "SymTab/Indexer.h" // for Indexer 46 51 #include "SymTab/Mangler.h" // for Mangler 52 #include "SynTree/Declaration.h" // for ObjectDecl, TypeDecl, Declar... 53 #include "SynTree/Expression.h" // for Expression, CastExpr, InitExpr 54 #include "SynTree/Initializer.h" // for ConstructorInit, SingleInit 55 #include "SynTree/Statement.h" // for ForStmt, Statement, BranchStmt 56 #include "SynTree/Type.h" // for Type, BasicType, PointerType 57 #include "SynTree/TypeSubstitution.h" // for TypeSubstitution 58 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 47 59 #include "Tuples/Tuples.h" 48 60 #include "Validate/FindSpecialDecls.h" // for SizeType … … 51 63 52 64 namespace ResolvExpr { 65 struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd { 66 Resolver_old() {} 67 Resolver_old( const SymTab::Indexer & other ) { 68 indexer = other; 69 } 70 71 void previsit( FunctionDecl * functionDecl ); 72 void postvisit( FunctionDecl * functionDecl ); 73 void previsit( ObjectDecl * objectDecll ); 74 void previsit( EnumDecl * enumDecl ); 75 void previsit( StaticAssertDecl * assertDecl ); 76 77 void previsit( ArrayType * at ); 78 void previsit( PointerType * at ); 79 80 void previsit( ExprStmt * exprStmt ); 81 void previsit( AsmExpr * asmExpr ); 82 void previsit( AsmStmt * asmStmt ); 83 void previsit( IfStmt * ifStmt ); 84 void previsit( WhileDoStmt * whileDoStmt ); 85 void previsit( ForStmt * forStmt ); 86 void previsit( SwitchStmt * switchStmt ); 87 void previsit( CaseStmt * caseStmt ); 88 void previsit( BranchStmt * branchStmt ); 89 void previsit( ReturnStmt * returnStmt ); 90 void previsit( ThrowStmt * throwStmt ); 91 void previsit( CatchStmt * catchStmt ); 92 void postvisit( CatchStmt * catchStmt ); 93 void previsit( WaitForStmt * stmt ); 94 95 void previsit( SingleInit * singleInit ); 96 void previsit( ListInit * listInit ); 97 void previsit( ConstructorInit * ctorInit ); 98 private: 99 typedef std::list< Initializer * >::iterator InitIterator; 100 101 template< typename PtrType > 102 void handlePtrType( PtrType * type ); 103 104 void fallbackInit( ConstructorInit * ctorInit ); 105 106 Type * functionReturn = nullptr; 107 CurrentObject currentObject = nullptr; 108 bool inEnumDecl = false; 109 }; 110 111 struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd { 112 void previsit( FunctionDecl * ); 113 void previsit( WithStmt * ); 114 115 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ); 116 }; 117 118 void resolve( std::list< Declaration * > translationUnit ) { 119 PassVisitor<Resolver_old> resolver; 120 acceptAll( translationUnit, resolver ); 121 } 122 123 void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) { 124 PassVisitor<Resolver_old> resolver( indexer ); 125 maybeAccept( decl, resolver ); 126 } 127 128 namespace { 129 struct DeleteFinder_old : public WithShortCircuiting { 130 DeletedExpr * delExpr = nullptr; 131 void previsit( DeletedExpr * expr ) { 132 if ( delExpr ) visit_children = false; 133 else delExpr = expr; 134 } 135 136 void previsit( Expression * ) { 137 if ( delExpr ) visit_children = false; 138 } 139 }; 140 } 141 142 DeletedExpr * findDeletedExpr( Expression * expr ) { 143 PassVisitor<DeleteFinder_old> finder; 144 expr->accept( finder ); 145 return finder.pass.delExpr; 146 } 147 148 namespace { 149 struct StripCasts_old { 150 Expression * postmutate( CastExpr * castExpr ) { 151 if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) { 152 // generated cast is to the same type as its argument, so it's unnecessary -- remove it 153 Expression * expr = castExpr->arg; 154 castExpr->arg = nullptr; 155 std::swap( expr->env, castExpr->env ); 156 return expr; 157 } 158 return castExpr; 159 } 160 161 static void strip( Expression *& expr ) { 162 PassVisitor<StripCasts_old> stripper; 163 expr = expr->acceptMutator( stripper ); 164 } 165 }; 166 167 void finishExpr( Expression *& expr, const TypeEnvironment & env, TypeSubstitution * oldenv = nullptr ) { 168 expr->env = oldenv ? oldenv->clone() : new TypeSubstitution; 169 env.makeSubstitution( *expr->env ); 170 StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression 171 } 172 173 void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) { 174 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 175 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) { 176 // cast is to the same type as its argument, so it's unnecessary -- remove it 177 expr = castExpr->arg; 178 castExpr->arg = nullptr; 179 std::swap( expr->env, castExpr->env ); 180 delete castExpr; 181 } 182 } 183 } 184 } // namespace 185 186 namespace { 187 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) { 188 assertf( untyped, "expected a non-null expression." ); 189 190 // xxx - this isn't thread-safe, but should work until we parallelize the resolver 191 static unsigned recursion_level = 0; 192 193 ++recursion_level; 194 TypeEnvironment env; 195 AlternativeFinder finder( indexer, env ); 196 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 197 --recursion_level; 198 199 #if 0 200 if ( finder.get_alternatives().size() != 1 ) { 201 std::cerr << "untyped expr is "; 202 untyped->print( std::cerr ); 203 std::cerr << std::endl << "alternatives are:"; 204 for ( const Alternative & alt : finder.get_alternatives() ) { 205 alt.print( std::cerr ); 206 } // for 207 } // if 208 #endif 209 210 // produce filtered list of alternatives 211 AltList candidates; 212 for ( Alternative & alt : finder.get_alternatives() ) { 213 if ( pred( alt ) ) { 214 candidates.push_back( std::move( alt ) ); 215 } 216 } 217 218 // produce invalid error if no candidates 219 if ( candidates.empty() ) { 220 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 221 } 222 223 // search for cheapest candidate 224 AltList winners; 225 bool seen_undeleted = false; 226 for ( unsigned i = 0; i < candidates.size(); ++i ) { 227 int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost ); 228 229 if ( c > 0 ) continue; // skip more expensive than winner 230 231 if ( c < 0 ) { 232 // reset on new cheapest 233 seen_undeleted = ! findDeletedExpr( candidates[i].expr ); 234 winners.clear(); 235 } else /* if ( c == 0 ) */ { 236 if ( findDeletedExpr( candidates[i].expr ) ) { 237 // skip deleted expression if already seen one equivalent-cost not 238 if ( seen_undeleted ) continue; 239 } else if ( ! seen_undeleted ) { 240 // replace list of equivalent-cost deleted expressions with one non-deleted 241 winners.clear(); 242 seen_undeleted = true; 243 } 244 } 245 246 winners.emplace_back( std::move( candidates[i] ) ); 247 } 248 249 // promote alternative.cvtCost to .cost 250 // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost 251 for ( Alternative& winner : winners ) { 252 winner.cost = winner.cvtCost; 253 } 254 255 // produce ambiguous errors, if applicable 256 if ( winners.size() != 1 ) { 257 std::ostringstream stream; 258 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n"; 259 untyped->print( stream ); 260 stream << " Alternatives are:\n"; 261 printAlts( winners, stream, 1 ); 262 SemanticError( untyped->location, stream.str() ); 263 } 264 265 // single selected choice 266 Alternative& choice = winners.front(); 267 268 // fail on only expression deleted 269 if ( ! seen_undeleted ) { 270 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " ); 271 } 272 273 // xxx - check for ambiguous expressions 274 275 // output selected choice 276 alt = std::move( choice ); 277 } 278 279 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 280 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) { 281 if ( ! untyped ) return; 282 Alternative choice; 283 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode ); 284 finishExpr( choice.expr, choice.env, untyped->env ); 285 delete untyped; 286 untyped = choice.expr; 287 choice.expr = nullptr; 288 } 289 290 bool standardAlternativeFilter( const Alternative & ) { 291 // currently don't need to filter, under normal circumstances. 292 // in the future, this may be useful for removing deleted expressions 293 return true; 294 } 295 } // namespace 296 297 // used in resolveTypeof 298 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ) { 299 TypeEnvironment env; 300 return resolveInVoidContext( expr, indexer, env ); 301 } 302 303 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment & env ) { 304 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0 305 // interpretations, an exception has already been thrown. 306 assertf( expr, "expected a non-null expression." ); 307 308 CastExpr * untyped = new CastExpr( expr ); // cast to void 309 untyped->location = expr->location; 310 311 // set up and resolve expression cast to void 312 Alternative choice; 313 findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() ); 314 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr ); 315 assert( castExpr ); 316 env = std::move( choice.env ); 317 318 // clean up resolved expression 319 Expression * ret = castExpr->arg; 320 castExpr->arg = nullptr; 321 322 // unlink the arg so that it isn't deleted twice at the end of the program 323 untyped->arg = nullptr; 324 return ret; 325 } 326 327 void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) { 328 resetTyVarRenaming(); 329 TypeEnvironment env; 330 Expression * newExpr = resolveInVoidContext( untyped, indexer, env ); 331 finishExpr( newExpr, env, untyped->env ); 332 delete untyped; 333 untyped = newExpr; 334 } 335 336 void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ) { 337 findKindExpression( untyped, indexer, "", standardAlternativeFilter ); 338 } 339 340 void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) { 341 assert( untyped && type ); 342 // transfer location to generated cast for error purposes 343 CodeLocation location = untyped->location; 344 untyped = new CastExpr( untyped, type ); 345 untyped->location = location; 346 findSingleExpression( untyped, indexer ); 347 removeExtraneousCast( untyped, indexer ); 348 } 349 350 namespace { 351 bool isIntegralType( const Alternative & alt ) { 352 Type * type = alt.expr->result; 353 if ( dynamic_cast< EnumInstType * >( type ) ) { 354 return true; 355 } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) { 356 return bt->isInteger(); 357 } else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) { 358 return true; 359 } else { 360 return false; 361 } // if 362 } 363 364 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) { 365 findKindExpression( untyped, indexer, "condition", isIntegralType ); 366 } 367 } 368 369 370 bool isStructOrUnion( const Alternative & alt ) { 371 Type * t = alt.expr->result->stripReferences(); 372 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t ); 373 } 374 375 void resolveWithExprs( std::list< Declaration * > & translationUnit ) { 376 PassVisitor<ResolveWithExprs> resolver; 377 acceptAll( translationUnit, resolver ); 378 } 379 380 void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) { 381 for ( Expression *& expr : withExprs ) { 382 // only struct- and union-typed expressions are viable candidates 383 findKindExpression( expr, indexer, "with statement", isStructOrUnion ); 384 385 // if with expression might be impure, create a temporary so that it is evaluated once 386 if ( Tuples::maybeImpure( expr ) ) { 387 static UniqueName tmpNamer( "_with_tmp_" ); 388 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) ); 389 expr = new VariableExpr( tmp ); 390 newStmts.push_back( new DeclStmt( tmp ) ); 391 if ( InitTweak::isConstructable( tmp->type ) ) { 392 // generate ctor/dtor and resolve them 393 tmp->init = InitTweak::genCtorInit( tmp ); 394 tmp->accept( *visitor ); 395 } 396 } 397 } 398 } 399 400 void ResolveWithExprs::previsit( WithStmt * withStmt ) { 401 resolveWithExprs( withStmt->exprs, stmtsToAddBefore ); 402 } 403 404 void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) { 405 { 406 // resolve with-exprs with parameters in scope and add any newly generated declarations to the 407 // front of the function body. 408 auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } ); 409 indexer.addFunctionType( functionDecl->type ); 410 std::list< Statement * > newStmts; 411 resolveWithExprs( functionDecl->withExprs, newStmts ); 412 if ( functionDecl->statements ) { 413 functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts ); 414 } else { 415 assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() ); 416 } 417 } 418 } 419 420 void Resolver_old::previsit( ObjectDecl * objectDecl ) { 421 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 422 // class-variable initContext is changed multiple time because the LHS is analysed twice. 423 // The second analysis changes initContext because of a function type can contain object 424 // declarations in the return and parameter types. So each value of initContext is 425 // retained, so the type on the first analysis is preserved and used for selecting the RHS. 426 GuardValue( currentObject ); 427 currentObject = CurrentObject( objectDecl->get_type() ); 428 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) { 429 // enumerator initializers should not use the enum type to initialize, since 430 // the enum type is still incomplete at this point. Use signed int instead. 431 // TODO: BasicType::SignedInt may not longer be true 432 currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 433 } 434 } 435 436 template< typename PtrType > 437 void Resolver_old::handlePtrType( PtrType * type ) { 438 if ( type->get_dimension() ) { 439 findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer ); 440 } 441 } 442 443 void Resolver_old::previsit( ArrayType * at ) { 444 handlePtrType( at ); 445 } 446 447 void Resolver_old::previsit( PointerType * pt ) { 448 handlePtrType( pt ); 449 } 450 451 void Resolver_old::previsit( FunctionDecl * functionDecl ) { 452 #if 0 453 std::cerr << "resolver visiting functiondecl "; 454 functionDecl->print( std::cerr ); 455 std::cerr << std::endl; 456 #endif 457 GuardValue( functionReturn ); 458 functionReturn = ResolvExpr::extractResultType( functionDecl->type ); 459 } 460 461 void Resolver_old::postvisit( FunctionDecl * functionDecl ) { 462 // default value expressions have an environment which shouldn't be there and trips up 463 // later passes. 464 // xxx - it might be necessary to somehow keep the information from this environment, but I 465 // can't currently see how it's useful. 466 for ( Declaration * d : functionDecl->type->parameters ) { 467 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) { 468 if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->init ) ) { 469 delete init->value->env; 470 init->value->env = nullptr; 471 } 472 } 473 } 474 } 475 476 void Resolver_old::previsit( EnumDecl * ) { 477 // in case we decide to allow nested enums 478 GuardValue( inEnumDecl ); 479 inEnumDecl = true; 480 } 481 482 void Resolver_old::previsit( StaticAssertDecl * assertDecl ) { 483 findIntegralExpression( assertDecl->condition, indexer ); 484 } 485 486 void Resolver_old::previsit( ExprStmt * exprStmt ) { 487 visit_children = false; 488 assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" ); 489 findVoidExpression( exprStmt->expr, indexer ); 490 } 491 492 void Resolver_old::previsit( AsmExpr * asmExpr ) { 493 visit_children = false; 494 findVoidExpression( asmExpr->operand, indexer ); 495 } 496 497 void Resolver_old::previsit( AsmStmt * asmStmt ) { 498 visit_children = false; 499 acceptAll( asmStmt->get_input(), *visitor ); 500 acceptAll( asmStmt->get_output(), *visitor ); 501 } 502 503 void Resolver_old::previsit( IfStmt * ifStmt ) { 504 findIntegralExpression( ifStmt->condition, indexer ); 505 } 506 507 void Resolver_old::previsit( WhileDoStmt * whileDoStmt ) { 508 findIntegralExpression( whileDoStmt->condition, indexer ); 509 } 510 511 void Resolver_old::previsit( ForStmt * forStmt ) { 512 if ( forStmt->condition ) { 513 findIntegralExpression( forStmt->condition, indexer ); 514 } // if 515 516 if ( forStmt->increment ) { 517 findVoidExpression( forStmt->increment, indexer ); 518 } // if 519 } 520 521 void Resolver_old::previsit( SwitchStmt * switchStmt ) { 522 GuardValue( currentObject ); 523 findIntegralExpression( switchStmt->condition, indexer ); 524 525 currentObject = CurrentObject( switchStmt->condition->result ); 526 } 527 528 void Resolver_old::previsit( CaseStmt * caseStmt ) { 529 if ( caseStmt->condition ) { 530 std::list< InitAlternative > initAlts = currentObject.getOptions(); 531 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." ); 532 // must remove cast from case statement because RangeExpr cannot be cast. 533 Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() ); 534 findSingleExpression( newExpr, indexer ); 535 // case condition cannot have a cast in C, so it must be removed, regardless of whether it performs a conversion. 536 // Ideally we would perform the conversion internally here. 537 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( newExpr ) ) { 538 newExpr = castExpr->arg; 539 castExpr->arg = nullptr; 540 std::swap( newExpr->env, castExpr->env ); 541 delete castExpr; 542 } 543 caseStmt->condition = newExpr; 544 } 545 } 546 547 void Resolver_old::previsit( BranchStmt * branchStmt ) { 548 visit_children = false; 549 // must resolve the argument for a computed goto 550 if ( branchStmt->get_type() == BranchStmt::Goto ) { // check for computed goto statement 551 if ( branchStmt->computedTarget ) { 552 // computed goto argument is void * 553 findSingleExpression( branchStmt->computedTarget, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), indexer ); 554 } // if 555 } // if 556 } 557 558 void Resolver_old::previsit( ReturnStmt * returnStmt ) { 559 visit_children = false; 560 if ( returnStmt->expr ) { 561 findSingleExpression( returnStmt->expr, functionReturn->clone(), indexer ); 562 } // if 563 } 564 565 void Resolver_old::previsit( ThrowStmt * throwStmt ) { 566 visit_children = false; 567 // TODO: Replace *exception type with &exception type. 568 if ( throwStmt->get_expr() ) { 569 const StructDecl * exception_decl = indexer.lookupStruct( "__cfaehm_base_exception_t" ); 570 assert( exception_decl ); 571 Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) ); 572 findSingleExpression( throwStmt->expr, exceptType, indexer ); 573 } 574 } 575 576 void Resolver_old::previsit( CatchStmt * catchStmt ) { 577 // Until we are very sure this invarent (ifs that move between passes have then) 578 // holds, check it. This allows a check for when to decode the mangling. 579 if ( IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body ) ) { 580 assert( ifStmt->then ); 581 } 582 // Encode the catchStmt so the condition can see the declaration. 583 if ( catchStmt->cond ) { 584 IfStmt * ifStmt = new IfStmt( catchStmt->cond, nullptr, catchStmt->body ); 585 catchStmt->cond = nullptr; 586 catchStmt->body = ifStmt; 587 } 588 } 589 590 void Resolver_old::postvisit( CatchStmt * catchStmt ) { 591 // Decode the catchStmt so everything is stored properly. 592 IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body ); 593 if ( nullptr != ifStmt && nullptr == ifStmt->then ) { 594 assert( ifStmt->condition ); 595 assert( ifStmt->else_ ); 596 catchStmt->cond = ifStmt->condition; 597 catchStmt->body = ifStmt->else_; 598 ifStmt->condition = nullptr; 599 ifStmt->else_ = nullptr; 600 delete ifStmt; 601 } 602 } 603 53 604 template< typename iterator_t > 54 605 inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) { … … 59 610 return it != end; 60 611 } 612 613 void Resolver_old::previsit( WaitForStmt * stmt ) { 614 visit_children = false; 615 616 // Resolve all clauses first 617 for( auto& clause : stmt->clauses ) { 618 619 TypeEnvironment env; 620 AlternativeFinder funcFinder( indexer, env ); 621 622 // Find all alternatives for a function in canonical form 623 funcFinder.findWithAdjustment( clause.target.function ); 624 625 if ( funcFinder.get_alternatives().empty() ) { 626 stringstream ss; 627 ss << "Use of undeclared indentifier '"; 628 ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name; 629 ss << "' in call to waitfor"; 630 SemanticError( stmt->location, ss.str() ); 631 } 632 633 if(clause.target.arguments.empty()) { 634 SemanticError( stmt->location, "Waitfor clause must have at least one mutex parameter"); 635 } 636 637 // Find all alternatives for all arguments in canonical form 638 std::vector< AlternativeFinder > argAlternatives; 639 funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) ); 640 641 // List all combinations of arguments 642 std::vector< AltList > possibilities; 643 combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) ); 644 645 AltList func_candidates; 646 std::vector< AltList > args_candidates; 647 648 // For every possible function : 649 // try matching the arguments to the parameters 650 // not the other way around because we have more arguments than parameters 651 SemanticErrorException errors; 652 for ( Alternative & func : funcFinder.get_alternatives() ) { 653 try { 654 PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() ); 655 if( !pointer ) { 656 SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" ); 657 } 658 659 FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() ); 660 if( !function ) { 661 SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" ); 662 } 663 664 665 { 666 auto param = function->parameters.begin(); 667 auto param_end = function->parameters.end(); 668 669 if( !advance_to_mutex( param, param_end ) ) { 670 SemanticError(function, "candidate function not viable: no mutex parameters\n"); 671 } 672 } 673 674 Alternative newFunc( func ); 675 // Strip reference from function 676 referenceToRvalueConversion( newFunc.expr, newFunc.cost ); 677 678 // For all the set of arguments we have try to match it with the parameter of the current function alternative 679 for ( auto & argsList : possibilities ) { 680 681 try { 682 // Declare data structures need for resolution 683 OpenVarSet openVars; 684 AssertionSet resultNeed, resultHave; 685 TypeEnvironment resultEnv( func.env ); 686 makeUnifiableVars( function, openVars, resultNeed ); 687 // add all type variables as open variables now so that those not used in the parameter 688 // list are still considered open. 689 resultEnv.add( function->forall ); 690 691 // Load type variables from arguemnts into one shared space 692 simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv ); 693 694 // Make sure we don't widen any existing bindings 695 resultEnv.forbidWidening(); 696 697 // Find any unbound type variables 698 resultEnv.extractOpenVars( openVars ); 699 700 auto param = function->parameters.begin(); 701 auto param_end = function->parameters.end(); 702 703 int n_mutex_param = 0; 704 705 // For every arguments of its set, check if it matches one of the parameter 706 // The order is important 707 for( auto & arg : argsList ) { 708 709 // Ignore non-mutex arguments 710 if( !advance_to_mutex( param, param_end ) ) { 711 // We ran out of parameters but still have arguments 712 // this function doesn't match 713 SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" )); 714 } 715 716 n_mutex_param++; 717 718 // Check if the argument matches the parameter type in the current scope 719 if( ! unify( arg.expr->get_result(), (*param)->get_type(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) { 720 // Type doesn't match 721 stringstream ss; 722 ss << "candidate function not viable: no known convertion from '"; 723 (*param)->get_type()->print( ss ); 724 ss << "' to '"; 725 arg.expr->get_result()->print( ss ); 726 ss << "' with env '"; 727 resultEnv.print(ss); 728 ss << "'\n"; 729 SemanticError( function, ss.str() ); 730 } 731 732 param++; 733 } 734 735 // All arguments match ! 736 737 // Check if parameters are missing 738 if( advance_to_mutex( param, param_end ) ) { 739 do { 740 n_mutex_param++; 741 param++; 742 } while( advance_to_mutex( param, param_end ) ); 743 744 // We ran out of arguments but still have parameters left 745 // this function doesn't match 746 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" )); 747 } 748 749 // All parameters match ! 750 751 // Finish the expressions to tie in the proper environments 752 finishExpr( newFunc.expr, resultEnv ); 753 for( Alternative & alt : argsList ) { 754 finishExpr( alt.expr, resultEnv ); 755 } 756 757 // This is a match store it and save it for later 758 func_candidates.push_back( newFunc ); 759 args_candidates.push_back( argsList ); 760 761 } 762 catch( SemanticErrorException & e ) { 763 errors.append( e ); 764 } 765 } 766 } 767 catch( SemanticErrorException & e ) { 768 errors.append( e ); 769 } 770 } 771 772 // Make sure we got the right number of arguments 773 if( func_candidates.empty() ) { SemanticErrorException top( stmt->location, "No alternatives for function in call to waitfor" ); top.append( errors ); throw top; } 774 if( args_candidates.empty() ) { SemanticErrorException top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; } 775 if( func_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous function in call to waitfor" ); top.append( errors ); throw top; } 776 if( args_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous arguments in call to waitfor" ); top.append( errors ); throw top; } 777 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used. 778 779 // Swap the results from the alternative with the unresolved values. 780 // Alternatives will handle deletion on destruction 781 std::swap( clause.target.function, func_candidates.front().expr ); 782 for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) { 783 std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr ); 784 } 785 786 // Resolve the conditions as if it were an IfStmt 787 // Resolve the statments normally 788 findSingleExpression( clause.condition, this->indexer ); 789 clause.statement->accept( *visitor ); 790 } 791 792 793 if( stmt->timeout.statement ) { 794 // Resolve the timeout as an size_t for now 795 // Resolve the conditions as if it were an IfStmt 796 // Resolve the statments normally 797 findSingleExpression( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer ); 798 findSingleExpression( stmt->timeout.condition, this->indexer ); 799 stmt->timeout.statement->accept( *visitor ); 800 } 801 802 if( stmt->orelse.statement ) { 803 // Resolve the conditions as if it were an IfStmt 804 // Resolve the statments normally 805 findSingleExpression( stmt->orelse.condition, this->indexer ); 806 stmt->orelse.statement->accept( *visitor ); 807 } 808 } 809 810 bool isCharType( Type * t ) { 811 if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) { 812 return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar || 813 bt->get_kind() == BasicType::UnsignedChar; 814 } 815 return false; 816 } 817 818 void Resolver_old::previsit( SingleInit * singleInit ) { 819 visit_children = false; 820 // resolve initialization using the possibilities as determined by the currentObject cursor 821 Expression * newExpr = new UntypedInitExpr( singleInit->value, currentObject.getOptions() ); 822 findSingleExpression( newExpr, indexer ); 823 InitExpr * initExpr = strict_dynamic_cast< InitExpr * >( newExpr ); 824 825 // move cursor to the object that is actually initialized 826 currentObject.setNext( initExpr->get_designation() ); 827 828 // discard InitExpr wrapper and retain relevant pieces 829 newExpr = initExpr->expr; 830 initExpr->expr = nullptr; 831 std::swap( initExpr->env, newExpr->env ); 832 // InitExpr may have inferParams in the case where the expression specializes a function 833 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not 834 // sufficient. 835 newExpr->spliceInferParams( initExpr ); 836 delete initExpr; 837 838 // get the actual object's type (may not exactly match what comes back from the resolver 839 // due to conversions) 840 Type * initContext = currentObject.getCurrentType(); 841 842 removeExtraneousCast( newExpr, indexer ); 843 844 // check if actual object's type is char[] 845 if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) { 846 if ( isCharType( at->get_base() ) ) { 847 // check if the resolved type is char * 848 if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) { 849 if ( isCharType( pt->get_base() ) ) { 850 if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) { 851 // strip cast if we're initializing a char[] with a char *, 852 // e.g. char x[] = "hello"; 853 newExpr = ce->get_arg(); 854 ce->set_arg( nullptr ); 855 std::swap( ce->env, newExpr->env ); 856 delete ce; 857 } 858 } 859 } 860 } 861 } 862 863 // set initializer expr to resolved express 864 singleInit->value = newExpr; 865 866 // move cursor to next object in preparation for next initializer 867 currentObject.increment(); 868 } 869 870 void Resolver_old::previsit( ListInit * listInit ) { 871 visit_children = false; 872 // move cursor into brace-enclosed initializer-list 873 currentObject.enterListInit(); 874 // xxx - fix this so that the list isn't copied, iterator should be used to change current 875 // element 876 std::list<Designation *> newDesignations; 877 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 878 // iterate designations and initializers in pairs, moving the cursor to the current 879 // designated object and resolving the initializer against that object. 880 Designation * des = std::get<0>(p); 881 Initializer * init = std::get<1>(p); 882 newDesignations.push_back( currentObject.findNext( des ) ); 883 init->accept( *visitor ); 884 } 885 // set the set of 'resolved' designations and leave the brace-enclosed initializer-list 886 listInit->get_designations() = newDesignations; // xxx - memory management 887 currentObject.exitListInit(); 888 889 // xxx - this part has not be folded into CurrentObject yet 890 // } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) { 891 // Type * base = tt->get_baseType()->get_base(); 892 // if ( base ) { 893 // // know the implementation type, so try using that as the initContext 894 // ObjectDecl tmpObj( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, base->clone(), nullptr ); 895 // currentObject = &tmpObj; 896 // visit( listInit ); 897 // } else { 898 // // missing implementation type -- might be an unknown type variable, so try proceeding with the current init context 899 // Parent::visit( listInit ); 900 // } 901 // } else { 902 } 903 904 // ConstructorInit - fall back on C-style initializer 905 void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) { 906 // could not find valid constructor, or found an intrinsic constructor 907 // fall back on C-style initializer 908 delete ctorInit->get_ctor(); 909 ctorInit->set_ctor( nullptr ); 910 delete ctorInit->get_dtor(); 911 ctorInit->set_dtor( nullptr ); 912 maybeAccept( ctorInit->get_init(), *visitor ); 913 } 914 915 // needs to be callable from outside the resolver, so this is a standalone function 916 void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) { 917 assert( ctorInit ); 918 PassVisitor<Resolver_old> resolver( indexer ); 919 ctorInit->accept( resolver ); 920 } 921 922 void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) { 923 assert( stmtExpr ); 924 PassVisitor<Resolver_old> resolver( indexer ); 925 stmtExpr->accept( resolver ); 926 stmtExpr->computeResult(); 927 // xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead? 928 } 929 930 void Resolver_old::previsit( ConstructorInit * ctorInit ) { 931 visit_children = false; 932 // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit 933 maybeAccept( ctorInit->ctor, *visitor ); 934 maybeAccept( ctorInit->dtor, *visitor ); 935 936 // found a constructor - can get rid of C-style initializer 937 delete ctorInit->init; 938 ctorInit->init = nullptr; 939 940 // intrinsic single parameter constructors and destructors do nothing. Since this was 941 // implicitly generated, there's no way for it to have side effects, so get rid of it 942 // to clean up generated code. 943 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) { 944 delete ctorInit->ctor; 945 ctorInit->ctor = nullptr; 946 } 947 948 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) { 949 delete ctorInit->dtor; 950 ctorInit->dtor = nullptr; 951 } 952 953 // xxx - todo -- what about arrays? 954 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) { 955 // // can reduce the constructor down to a SingleInit using the 956 // // second argument from the ctor call, since 957 // delete ctorInit->get_ctor(); 958 // ctorInit->set_ctor( nullptr ); 959 960 // Expression * arg = 961 // ctorInit->set_init( new SingleInit( arg ) ); 962 // } 963 } 964 965 /////////////////////////////////////////////////////////////////////////// 966 // 967 // *** NEW RESOLVER *** 968 // 969 /////////////////////////////////////////////////////////////////////////// 61 970 62 971 namespace {
Note:
See TracChangeset
for help on using the changeset viewer.