Changes in src/ResolvExpr/Resolver.cc [8fd52e90:2a08c25]
- File:
-
- 1 edited
-
src/ResolvExpr/Resolver.cc (modified) (45 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
r8fd52e90 r2a08c25 7 7 // Resolver.cc -- 8 8 // 9 // Author : Aaron B. Moss9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Aaron B. Moss12 // Last Modified On : Wed May 29 11:00:00 201913 // Update Count : 2 4111 // 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 16 #include <stddef.h> // for NULL 16 17 #include <cassert> // for strict_dynamic_cast, assert 17 18 #include <memory> // for allocator, allocator_traits<... 18 19 #include <tuple> // for get 19 #include <vector> // for vector20 #include <vector> 20 21 21 22 #include "Alternative.h" // for Alternative, AltList 22 23 #include "AlternativeFinder.h" // for AlternativeFinder, resolveIn... 23 #include "Candidate.hpp"24 #include "CandidateFinder.hpp"25 #include "CurrentObject.h" // for CurrentObject26 #include "RenameVars.h" // for RenameVars, global_renamer27 #include "Resolver.h"28 #include "ResolvMode.h" // for ResolvMode29 #include "typeops.h" // for extractResultType30 #include "Unify.h" // for unify31 #include "AST/Chain.hpp"32 #include "AST/Decl.hpp"33 #include "AST/Init.hpp"34 #include "AST/Pass.hpp"35 #include "AST/Print.hpp"36 #include "AST/SymbolTable.hpp"37 #include "AST/Type.hpp"38 24 #include "Common/PassVisitor.h" // for PassVisitor 39 25 #include "Common/SemanticError.h" // for SemanticError 40 26 #include "Common/utility.h" // for ValueGuard, group_iterate 27 #include "CurrentObject.h" // for CurrentObject 41 28 #include "InitTweak/GenInit.h" 42 29 #include "InitTweak/InitTweak.h" // for isIntrinsicSingleArgCallStmt 30 #include "RenameVars.h" // for RenameVars, global_renamer 43 31 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 32 #include "ResolveTypeof.h" // for resolveTypeof 33 #include "Resolver.h" 44 34 #include "SymTab/Autogen.h" // for SizeType 45 35 #include "SymTab/Indexer.h" // for Indexer … … 52 42 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 53 43 #include "Tuples/Tuples.h" 54 #include "Validate/FindSpecialDecls.h" // for SizeType 44 #include "typeops.h" // for extractResultType 45 #include "Unify.h" // for unify 55 46 56 47 using namespace std; 57 48 58 49 namespace ResolvExpr { 59 struct Resolver _old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd {60 Resolver _old() {}61 Resolver _old( const SymTab::Indexer & other ) {50 struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting, public WithStmtsToAdd { 51 Resolver() {} 52 Resolver( const SymTab::Indexer & other ) { 62 53 indexer = other; 63 54 } 64 55 65 void previsit( FunctionDecl * functionDecl ); 66 void postvisit( FunctionDecl * functionDecl ); 67 void previsit( ObjectDecl * objectDecll ); 56 void previsit( FunctionDecl *functionDecl ); 57 void postvisit( FunctionDecl *functionDecl ); 58 void previsit( ObjectDecl *objectDecll ); 59 void previsit( TypeDecl *typeDecl ); 68 60 void previsit( EnumDecl * enumDecl ); 69 61 void previsit( StaticAssertDecl * assertDecl ); … … 72 64 void previsit( PointerType * at ); 73 65 74 void previsit( ExprStmt * exprStmt );75 void previsit( AsmExpr * asmExpr );76 void previsit( AsmStmt * asmStmt );77 void previsit( IfStmt * ifStmt );78 void previsit( WhileStmt * whileStmt );79 void previsit( ForStmt * forStmt );80 void previsit( SwitchStmt * switchStmt );81 void previsit( CaseStmt * caseStmt );82 void previsit( BranchStmt * branchStmt );83 void previsit( ReturnStmt * returnStmt );84 void previsit( ThrowStmt * throwStmt );85 void previsit( CatchStmt * catchStmt );66 void previsit( ExprStmt *exprStmt ); 67 void previsit( AsmExpr *asmExpr ); 68 void previsit( AsmStmt *asmStmt ); 69 void previsit( IfStmt *ifStmt ); 70 void previsit( WhileStmt *whileStmt ); 71 void previsit( ForStmt *forStmt ); 72 void previsit( SwitchStmt *switchStmt ); 73 void previsit( CaseStmt *caseStmt ); 74 void previsit( BranchStmt *branchStmt ); 75 void previsit( ReturnStmt *returnStmt ); 76 void previsit( ThrowStmt *throwStmt ); 77 void previsit( CatchStmt *catchStmt ); 86 78 void previsit( WaitForStmt * stmt ); 87 88 void previsit( SingleInit * singleInit ); 89 void previsit( ListInit * listInit ); 90 void previsit( ConstructorInit * ctorInit ); 79 void previsit( WithStmt * withStmt ); 80 81 void previsit( SingleInit *singleInit ); 82 void previsit( ListInit *listInit ); 83 void previsit( ConstructorInit *ctorInit ); 91 84 private: 92 85 typedef std::list< Initializer * >::iterator InitIterator; … … 95 88 void handlePtrType( PtrType * type ); 96 89 90 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ); 97 91 void fallbackInit( ConstructorInit * ctorInit ); 98 92 … … 102 96 }; 103 97 104 struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {105 void previsit( FunctionDecl * );106 void previsit( WithStmt * );107 108 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );109 };110 111 98 void resolve( std::list< Declaration * > translationUnit ) { 112 PassVisitor<Resolver _old> resolver;99 PassVisitor<Resolver> resolver; 113 100 acceptAll( translationUnit, resolver ); 114 101 } 115 102 116 void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {117 PassVisitor<Resolver _old> resolver( indexer );103 void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) { 104 PassVisitor<Resolver> resolver( indexer ); 118 105 maybeAccept( decl, resolver ); 119 106 } 120 107 121 108 namespace { 122 struct DeleteFinder _old: public WithShortCircuiting {109 struct DeleteFinder : public WithShortCircuiting { 123 110 DeletedExpr * delExpr = nullptr; 124 111 void previsit( DeletedExpr * expr ) { … … 134 121 135 122 DeletedExpr * findDeletedExpr( Expression * expr ) { 136 PassVisitor<DeleteFinder _old> finder;123 PassVisitor<DeleteFinder> finder; 137 124 expr->accept( finder ); 138 125 return finder.pass.delExpr; … … 140 127 141 128 namespace { 142 struct StripCasts _old{129 struct StripCasts { 143 130 Expression * postmutate( CastExpr * castExpr ) { 144 131 if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) { … … 153 140 154 141 static void strip( Expression *& expr ) { 155 PassVisitor<StripCasts _old> stripper;142 PassVisitor<StripCasts> stripper; 156 143 expr = expr->acceptMutator( stripper ); 157 144 } 158 145 }; 159 146 160 void finishExpr( Expression *& expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {147 void finishExpr( Expression *&expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) { 161 148 expr->env = oldenv ? oldenv->clone() : new TypeSubstitution; 162 149 env.makeSubstitution( *expr->env ); 163 StripCasts _old::strip( expr ); // remove unnecessary casts that may be buried in an expression150 StripCasts::strip( expr ); // remove unnecessary casts that may be buried in an expression 164 151 } 165 152 166 153 void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) { 167 154 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 168 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {155 if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) { 169 156 // cast is to the same type as its argument, so it's unnecessary -- remove it 170 157 expr = castExpr->arg; … … 178 165 179 166 namespace { 180 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {167 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) { 181 168 assertf( untyped, "expected a non-null expression." ); 182 183 // xxx - this isn't thread-safe, but should work until we parallelize the resolver184 static unsigned recursion_level = 0;185 186 ++recursion_level;187 169 TypeEnvironment env; 188 170 AlternativeFinder finder( indexer, env ); 189 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 190 --recursion_level; 171 finder.find( untyped, adjust, prune, failFast ); 191 172 192 173 #if 0 … … 201 182 #endif 202 183 203 // produce filtered list of alternatives204 184 AltList candidates; 205 185 for ( Alternative & alt : finder.get_alternatives() ) { … … 209 189 } 210 190 211 // produce invalid error if no candidates 212 if ( candidates.empty() ) { 191 // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining 192 // choose the lowest cost expression among the candidates 193 AltList winners; 194 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 195 if ( winners.size() == 0 ) { 213 196 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 214 } 215 216 // search for cheapest candidate 217 AltList winners; 218 bool seen_undeleted = false; 219 for ( unsigned i = 0; i < candidates.size(); ++i ) { 220 int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost ); 221 222 if ( c > 0 ) continue; // skip more expensive than winner 223 224 if ( c < 0 ) { 225 // reset on new cheapest 226 seen_undeleted = ! findDeletedExpr( candidates[i].expr ); 227 winners.clear(); 228 } else /* if ( c == 0 ) */ { 229 if ( findDeletedExpr( candidates[i].expr ) ) { 230 // skip deleted expression if already seen one equivalent-cost not 231 if ( seen_undeleted ) continue; 232 } else if ( ! seen_undeleted ) { 233 // replace list of equivalent-cost deleted expressions with one non-deleted 234 winners.clear(); 235 seen_undeleted = true; 236 } 237 } 238 239 winners.emplace_back( std::move( candidates[i] ) ); 240 } 241 242 // promote alternative.cvtCost to .cost 243 // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost 244 for ( Alternative& winner : winners ) { 245 winner.cost = winner.cvtCost; 246 } 247 248 // produce ambiguous errors, if applicable 249 if ( winners.size() != 1 ) { 197 } else if ( winners.size() != 1 ) { 250 198 std::ostringstream stream; 251 199 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n"; … … 256 204 } 257 205 258 // single selected choice 259 Alternative& choice = winners.front(); 260 261 // fail on only expression deleted 262 if ( ! seen_undeleted ) { 206 // there is one unambiguous interpretation - move the expression into the with statement 207 Alternative & choice = winners.front(); 208 if ( findDeletedExpr( choice.expr ) ) { 263 209 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " ); 264 210 } 265 266 // xxx - check for ambiguous expressions267 268 // output selected choice269 211 alt = std::move( choice ); 270 212 } 271 213 272 214 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 273 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {215 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) { 274 216 if ( ! untyped ) return; 275 217 Alternative choice; 276 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode);218 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast ); 277 219 finishExpr( choice.expr, choice.env, untyped->env ); 278 220 delete untyped; … … 289 231 290 232 // used in resolveTypeof 291 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer &indexer ) {233 Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) { 292 234 TypeEnvironment env; 293 235 return resolveInVoidContext( expr, indexer, env ); 294 236 } 295 237 296 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment &env ) {238 Expression * resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) { 297 239 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0 298 240 // interpretations, an exception has already been thrown. 299 241 assertf( expr, "expected a non-null expression." ); 300 242 301 CastExpr * untyped = new CastExpr( expr ); // cast to void302 untyped ->location = expr->location;243 static CastExpr untyped( nullptr ); // cast to void 244 untyped.location = expr->location; 303 245 304 246 // set up and resolve expression cast to void 247 untyped.arg = expr; 305 248 Alternative choice; 306 findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment());249 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true ); 307 250 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr ); 308 assert( castExpr );309 251 env = std::move( choice.env ); 310 252 … … 314 256 315 257 // unlink the arg so that it isn't deleted twice at the end of the program 316 untyped ->arg = nullptr;258 untyped.arg = nullptr; 317 259 return ret; 318 260 } 319 261 320 void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {262 void findVoidExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 321 263 resetTyVarRenaming(); 322 264 TypeEnvironment env; … … 327 269 } 328 270 329 void findSingleExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {271 void findSingleExpression( Expression *&untyped, const SymTab::Indexer &indexer ) { 330 272 findKindExpression( untyped, indexer, "", standardAlternativeFilter ); 331 273 } … … 346 288 if ( dynamic_cast< EnumInstType * >( type ) ) { 347 289 return true; 348 } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) {290 } else if ( BasicType *bt = dynamic_cast< BasicType * >( type ) ) { 349 291 return bt->isInteger(); 350 292 } else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) { … … 355 297 } 356 298 357 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {299 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 358 300 findKindExpression( untyped, indexer, "condition", isIntegralType ); 359 301 } 360 302 } 361 303 362 363 bool isStructOrUnion( const Alternative & alt ) { 364 Type * t = alt.expr->result->stripReferences(); 365 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t ); 366 } 367 368 void resolveWithExprs( std::list< Declaration * > & translationUnit ) { 369 PassVisitor<ResolveWithExprs> resolver; 370 acceptAll( translationUnit, resolver ); 371 } 372 373 void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) { 374 for ( Expression *& expr : withExprs ) { 375 // only struct- and union-typed expressions are viable candidates 376 findKindExpression( expr, indexer, "with statement", isStructOrUnion ); 377 378 // if with expression might be impure, create a temporary so that it is evaluated once 379 if ( Tuples::maybeImpure( expr ) ) { 380 static UniqueName tmpNamer( "_with_tmp_" ); 381 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) ); 382 expr = new VariableExpr( tmp ); 383 newStmts.push_back( new DeclStmt( tmp ) ); 384 if ( InitTweak::isConstructable( tmp->type ) ) { 385 // generate ctor/dtor and resolve them 386 tmp->init = InitTweak::genCtorInit( tmp ); 387 tmp->accept( *visitor ); 388 } 389 } 390 } 391 } 392 393 void ResolveWithExprs::previsit( WithStmt * withStmt ) { 394 resolveWithExprs( withStmt->exprs, stmtsToAddBefore ); 395 } 396 397 void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) { 304 void Resolver::previsit( ObjectDecl *objectDecl ) { 305 Type *new_type = resolveTypeof( objectDecl->get_type(), indexer ); 306 objectDecl->set_type( new_type ); 307 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable 308 // initContext is changed multiple time because the LHS is analysed twice. The second analysis changes 309 // initContext because of a function type can contain object declarations in the return and parameter types. So 310 // each value of initContext is retained, so the type on the first analysis is preserved and used for selecting 311 // the RHS. 312 GuardValue( currentObject ); 313 currentObject = CurrentObject( objectDecl->get_type() ); 314 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) { 315 // enumerator initializers should not use the enum type to initialize, since 316 // the enum type is still incomplete at this point. Use signed int instead. 317 currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 318 } 319 } 320 321 template< typename PtrType > 322 void Resolver::handlePtrType( PtrType * type ) { 323 if ( type->get_dimension() ) { 324 findSingleExpression( type->dimension, SymTab::SizeType->clone(), indexer ); 325 } 326 } 327 328 void Resolver::previsit( ArrayType * at ) { 329 handlePtrType( at ); 330 } 331 332 void Resolver::previsit( PointerType * pt ) { 333 handlePtrType( pt ); 334 } 335 336 void Resolver::previsit( TypeDecl *typeDecl ) { 337 if ( typeDecl->get_base() ) { 338 Type *new_type = resolveTypeof( typeDecl->get_base(), indexer ); 339 typeDecl->set_base( new_type ); 340 } // if 341 } 342 343 void Resolver::previsit( FunctionDecl *functionDecl ) { 344 #if 0 345 std::cerr << "resolver visiting functiondecl "; 346 functionDecl->print( std::cerr ); 347 std::cerr << std::endl; 348 #endif 349 Type *new_type = resolveTypeof( functionDecl->type, indexer ); 350 functionDecl->set_type( new_type ); 351 GuardValue( functionReturn ); 352 functionReturn = ResolvExpr::extractResultType( functionDecl->type ); 353 398 354 { 399 355 // resolve with-exprs with parameters in scope and add any newly generated declarations to the … … 411 367 } 412 368 413 void Resolver_old::previsit( ObjectDecl * objectDecl ) { 414 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 415 // class-variable initContext is changed multiple time because the LHS is analysed twice. 416 // The second analysis changes initContext because of a function type can contain object 417 // declarations in the return and parameter types. So each value of initContext is 418 // retained, so the type on the first analysis is preserved and used for selecting the RHS. 419 GuardValue( currentObject ); 420 currentObject = CurrentObject( objectDecl->get_type() ); 421 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) { 422 // enumerator initializers should not use the enum type to initialize, since 423 // the enum type is still incomplete at this point. Use signed int instead. 424 currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 425 } 426 } 427 428 template< typename PtrType > 429 void Resolver_old::handlePtrType( PtrType * type ) { 430 if ( type->get_dimension() ) { 431 findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer ); 432 } 433 } 434 435 void Resolver_old::previsit( ArrayType * at ) { 436 handlePtrType( at ); 437 } 438 439 void Resolver_old::previsit( PointerType * pt ) { 440 handlePtrType( pt ); 441 } 442 443 void Resolver_old::previsit( FunctionDecl * functionDecl ) { 444 #if 0 445 std::cerr << "resolver visiting functiondecl "; 446 functionDecl->print( std::cerr ); 447 std::cerr << std::endl; 448 #endif 449 GuardValue( functionReturn ); 450 functionReturn = ResolvExpr::extractResultType( functionDecl->type ); 451 } 452 453 void Resolver_old::postvisit( FunctionDecl * functionDecl ) { 454 // default value expressions have an environment which shouldn't be there and trips up 455 // later passes. 456 // xxx - it might be necessary to somehow keep the information from this environment, but I 457 // can't currently see how it's useful. 369 void Resolver::postvisit( FunctionDecl *functionDecl ) { 370 // default value expressions have an environment which shouldn't be there and trips up later passes. 371 // xxx - it might be necessary to somehow keep the information from this environment, but I can't currently 372 // see how it's useful. 458 373 for ( Declaration * d : functionDecl->type->parameters ) { 459 374 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) { … … 466 381 } 467 382 468 void Resolver _old::previsit( EnumDecl * ) {383 void Resolver::previsit( EnumDecl * ) { 469 384 // in case we decide to allow nested enums 470 385 GuardValue( inEnumDecl ); … … 472 387 } 473 388 474 void Resolver _old::previsit( StaticAssertDecl * assertDecl ) {389 void Resolver::previsit( StaticAssertDecl * assertDecl ) { 475 390 findIntegralExpression( assertDecl->condition, indexer ); 476 391 } 477 392 478 void Resolver _old::previsit( ExprStmt *exprStmt ) {393 void Resolver::previsit( ExprStmt *exprStmt ) { 479 394 visit_children = false; 480 395 assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" ); … … 482 397 } 483 398 484 void Resolver _old::previsit( AsmExpr *asmExpr ) {399 void Resolver::previsit( AsmExpr *asmExpr ) { 485 400 visit_children = false; 486 401 findVoidExpression( asmExpr->operand, indexer ); … … 490 405 } 491 406 492 void Resolver _old::previsit( AsmStmt *asmStmt ) {407 void Resolver::previsit( AsmStmt *asmStmt ) { 493 408 visit_children = false; 494 409 acceptAll( asmStmt->get_input(), *visitor ); … … 496 411 } 497 412 498 void Resolver _old::previsit( IfStmt *ifStmt ) {413 void Resolver::previsit( IfStmt *ifStmt ) { 499 414 findIntegralExpression( ifStmt->condition, indexer ); 500 415 } 501 416 502 void Resolver _old::previsit( WhileStmt *whileStmt ) {417 void Resolver::previsit( WhileStmt *whileStmt ) { 503 418 findIntegralExpression( whileStmt->condition, indexer ); 504 419 } 505 420 506 void Resolver _old::previsit( ForStmt *forStmt ) {421 void Resolver::previsit( ForStmt *forStmt ) { 507 422 if ( forStmt->condition ) { 508 423 findIntegralExpression( forStmt->condition, indexer ); … … 514 429 } 515 430 516 void Resolver _old::previsit( SwitchStmt *switchStmt ) {431 void Resolver::previsit( SwitchStmt *switchStmt ) { 517 432 GuardValue( currentObject ); 518 433 findIntegralExpression( switchStmt->condition, indexer ); … … 521 436 } 522 437 523 void Resolver _old::previsit( CaseStmt *caseStmt ) {438 void Resolver::previsit( CaseStmt *caseStmt ) { 524 439 if ( caseStmt->condition ) { 525 440 std::list< InitAlternative > initAlts = currentObject.getOptions(); … … 540 455 } 541 456 542 void Resolver _old::previsit( BranchStmt *branchStmt ) {457 void Resolver::previsit( BranchStmt *branchStmt ) { 543 458 visit_children = false; 544 459 // must resolve the argument for a computed goto … … 551 466 } 552 467 553 void Resolver _old::previsit( ReturnStmt *returnStmt ) {468 void Resolver::previsit( ReturnStmt *returnStmt ) { 554 469 visit_children = false; 555 470 if ( returnStmt->expr ) { … … 558 473 } 559 474 560 void Resolver _old::previsit( ThrowStmt *throwStmt ) {475 void Resolver::previsit( ThrowStmt *throwStmt ) { 561 476 visit_children = false; 562 477 // TODO: Replace *exception type with &exception type. 563 478 if ( throwStmt->get_expr() ) { 564 const StructDecl * exception_decl = indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" ); 479 StructDecl * exception_decl = 480 indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" ); 565 481 assert( exception_decl ); 566 Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl)) );482 Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, exception_decl ) ); 567 483 findSingleExpression( throwStmt->expr, exceptType, indexer ); 568 484 } 569 485 } 570 486 571 void Resolver _old::previsit( CatchStmt *catchStmt ) {487 void Resolver::previsit( CatchStmt *catchStmt ) { 572 488 if ( catchStmt->cond ) { 573 489 findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer ); … … 584 500 } 585 501 586 void Resolver _old::previsit( WaitForStmt * stmt ) {502 void Resolver::previsit( WaitForStmt * stmt ) { 587 503 visit_children = false; 588 504 … … 666 582 667 583 // Make sure we don't widen any existing bindings 668 resultEnv.forbidWidening(); 584 for ( auto & i : resultEnv ) { 585 i.allowWidening = false; 586 } 669 587 670 588 // Find any unbound type variables … … 674 592 auto param_end = function->parameters.end(); 675 593 676 int n_mutex_ param= 0;594 int n_mutex_arg = 0; 677 595 678 596 // For every arguments of its set, check if it matches one of the parameter … … 684 602 // We ran out of parameters but still have arguments 685 603 // this function doesn't match 686 SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_ param, "\n" ));604 SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_arg, "\n" )); 687 605 } 688 606 689 n_mutex_ param++;607 n_mutex_arg++; 690 608 691 609 // Check if the argument matches the parameter type in the current scope … … 710 628 // Check if parameters are missing 711 629 if( advance_to_mutex( param, param_end ) ) { 712 do {713 n_mutex_param++;714 param++;715 } while( advance_to_mutex( param, param_end ) );716 717 630 // We ran out of arguments but still have parameters left 718 631 // this function doesn't match 719 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_ param, "\n" ));632 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_arg, "\n" )); 720 633 } 721 634 … … 733 646 734 647 } 735 catch( SemanticErrorException & e ) {648 catch( SemanticErrorException &e ) { 736 649 errors.append( e ); 737 650 } 738 651 } 739 652 } 740 catch( SemanticErrorException & e ) {653 catch( SemanticErrorException &e ) { 741 654 errors.append( e ); 742 655 } … … 781 694 } 782 695 783 bool isCharType( Type * t ) { 696 bool isStructOrUnion( const Alternative & alt ) { 697 Type * t = alt.expr->result->stripReferences(); 698 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t ); 699 } 700 701 void Resolver::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) { 702 for ( Expression *& expr : withExprs ) { 703 // only struct- and union-typed expressions are viable candidates 704 findKindExpression( expr, indexer, "with statement", isStructOrUnion ); 705 706 // if with expression might be impure, create a temporary so that it is evaluated once 707 if ( Tuples::maybeImpure( expr ) ) { 708 static UniqueName tmpNamer( "_with_tmp_" ); 709 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) ); 710 expr = new VariableExpr( tmp ); 711 newStmts.push_back( new DeclStmt( tmp ) ); 712 if ( InitTweak::isConstructable( tmp->type ) ) { 713 // generate ctor/dtor and resolve them 714 tmp->init = InitTweak::genCtorInit( tmp ); 715 tmp->accept( *visitor ); 716 } 717 } 718 } 719 } 720 721 void Resolver::previsit( WithStmt * withStmt ) { 722 resolveWithExprs( withStmt->exprs, stmtsToAddBefore ); 723 } 724 725 template< typename T > 726 bool isCharType( T t ) { 784 727 if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) { 785 728 return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar || … … 789 732 } 790 733 791 void Resolver _old::previsit( SingleInit *singleInit ) {734 void Resolver::previsit( SingleInit *singleInit ) { 792 735 visit_children = false; 793 736 // resolve initialization using the possibilities as determined by the currentObject cursor … … 803 746 initExpr->expr = nullptr; 804 747 std::swap( initExpr->env, newExpr->env ); 805 // InitExpr may have inferParams in the case where the expression specializes a function 806 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not 807 // sufficient. 748 // InitExpr may have inferParams in the case where the expression specializes a function pointer, 749 // and newExpr may already have inferParams of its own, so a simple swap is not sufficient. 808 750 newExpr->spliceInferParams( initExpr ); 809 751 delete initExpr; 810 752 811 // get the actual object's type (may not exactly match what comes back from the resolver 812 // due to conversions) 753 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions) 813 754 Type * initContext = currentObject.getCurrentType(); 814 755 … … 821 762 if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) { 822 763 if ( isCharType( pt->get_base() ) ) { 823 if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) { 824 // strip cast if we're initializing a char[] with a char *, 825 // e.g. char x[] = "hello"; 764 if ( CastExpr *ce = dynamic_cast< CastExpr * >( newExpr ) ) { 765 // strip cast if we're initializing a char[] with a char *, e.g. char x[] = "hello"; 826 766 newExpr = ce->get_arg(); 827 767 ce->set_arg( nullptr ); … … 841 781 } 842 782 843 void Resolver _old::previsit( ListInit * listInit ) {783 void Resolver::previsit( ListInit * listInit ) { 844 784 visit_children = false; 845 785 // move cursor into brace-enclosed initializer-list 846 786 currentObject.enterListInit(); 847 // xxx - fix this so that the list isn't copied, iterator should be used to change current 848 // element 787 // xxx - fix this so that the list isn't copied, iterator should be used to change current element 849 788 std::list<Designation *> newDesignations; 850 789 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 851 // iterate designations and initializers in pairs, moving the cursor to the current 852 // designated object and resolvingthe initializer against that object.790 // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving 791 // the initializer against that object. 853 792 Designation * des = std::get<0>(p); 854 793 Initializer * init = std::get<1>(p); … … 876 815 877 816 // ConstructorInit - fall back on C-style initializer 878 void Resolver _old::fallbackInit( ConstructorInit * ctorInit ) {817 void Resolver::fallbackInit( ConstructorInit * ctorInit ) { 879 818 // could not find valid constructor, or found an intrinsic constructor 880 819 // fall back on C-style initializer 881 820 delete ctorInit->get_ctor(); 882 ctorInit->set_ctor( nullptr);821 ctorInit->set_ctor( NULL ); 883 822 delete ctorInit->get_dtor(); 884 ctorInit->set_dtor( nullptr);823 ctorInit->set_dtor( NULL ); 885 824 maybeAccept( ctorInit->get_init(), *visitor ); 886 825 } … … 889 828 void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) { 890 829 assert( ctorInit ); 891 PassVisitor<Resolver _old> resolver( indexer );830 PassVisitor<Resolver> resolver( indexer ); 892 831 ctorInit->accept( resolver ); 893 832 } … … 895 834 void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) { 896 835 assert( stmtExpr ); 897 PassVisitor<Resolver _old> resolver( indexer );836 PassVisitor<Resolver> resolver( indexer ); 898 837 stmtExpr->accept( resolver ); 899 838 stmtExpr->computeResult(); … … 901 840 } 902 841 903 void Resolver _old::previsit( ConstructorInit *ctorInit ) {842 void Resolver::previsit( ConstructorInit *ctorInit ) { 904 843 visit_children = false; 905 844 // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit … … 925 864 926 865 // xxx - todo -- what about arrays? 927 // if ( dtor == nullptr&& InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {866 // if ( dtor == NULL && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) { 928 867 // // can reduce the constructor down to a SingleInit using the 929 868 // // second argument from the ctor call, since 930 869 // delete ctorInit->get_ctor(); 931 // ctorInit->set_ctor( nullptr);870 // ctorInit->set_ctor( NULL ); 932 871 933 872 // Expression * arg = … … 935 874 // } 936 875 } 937 938 ///////////////////////////////////////////////////////////////////////////939 //940 // *** NEW RESOLVER ***941 //942 ///////////////////////////////////////////////////////////////////////////943 944 namespace {945 /// Finds deleted expressions in an expression tree946 struct DeleteFinder_new final : public ast::WithShortCircuiting {947 const ast::DeletedExpr * delExpr = nullptr;948 949 void previsit( const ast::DeletedExpr * expr ) {950 if ( delExpr ) { visit_children = false; }951 else { delExpr = expr; }952 }953 954 void previsit( const ast::Expr * ) {955 if ( delExpr ) { visit_children = false; }956 }957 };958 } // anonymous namespace959 960 /// Check if this expression is or includes a deleted expression961 const ast::DeletedExpr * findDeletedExpr( const ast::Expr * expr ) {962 ast::Pass<DeleteFinder_new> finder;963 expr->accept( finder );964 return finder.pass.delExpr;965 }966 967 namespace {968 /// always-accept candidate filter969 bool anyCandidate( const Candidate & ) { return true; }970 971 /// Calls the CandidateFinder and finds the single best candidate972 CandidateRef findUnfinishedKindExpression(973 const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,974 std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}975 ) {976 if ( ! untyped ) return nullptr;977 978 // xxx - this isn't thread-safe, but should work until we parallelize the resolver979 static unsigned recursion_level = 0;980 981 ++recursion_level;982 ast::TypeEnvironment env;983 CandidateFinder finder{ symtab, env };984 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );985 --recursion_level;986 987 // produce a filtered list of candidates988 CandidateList candidates;989 for ( auto & cand : finder.candidates ) {990 if ( pred( *cand ) ) { candidates.emplace_back( cand ); }991 }992 993 // produce invalid error if no candidates994 if ( candidates.empty() ) {995 SemanticError( untyped,996 toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""),997 "expression: ") );998 }999 1000 // search for cheapest candidate1001 CandidateList winners;1002 bool seen_undeleted = false;1003 for ( CandidateRef & cand : candidates ) {1004 int c = winners.empty() ? -1 : cand->cost.compare( winners.front()->cost );1005 1006 if ( c > 0 ) continue; // skip more expensive than winner1007 1008 if ( c < 0 ) {1009 // reset on new cheapest1010 seen_undeleted = ! findDeletedExpr( cand->expr );1011 winners.clear();1012 } else /* if ( c == 0 ) */ {1013 if ( findDeletedExpr( cand->expr ) ) {1014 // skip deleted expression if already seen one equivalent-cost not1015 if ( seen_undeleted ) continue;1016 } else if ( ! seen_undeleted ) {1017 // replace list of equivalent-cost deleted expressions with one non-deleted1018 winners.clear();1019 seen_undeleted = true;1020 }1021 }1022 1023 winners.emplace_back( std::move( cand ) );1024 }1025 1026 // promote candidate.cvtCost to .cost1027 promoteCvtCost( winners );1028 1029 // produce ambiguous errors, if applicable1030 if ( winners.size() != 1 ) {1031 std::ostringstream stream;1032 stream << "Cannot choose between " << winners.size() << " alternatives for "1033 << kind << (kind != "" ? " " : "") << "expression\n";1034 ast::print( stream, untyped );1035 stream << " Alternatives are:\n";1036 print( stream, winners, 1 );1037 SemanticError( untyped->location, stream.str() );1038 }1039 1040 // single selected choice1041 CandidateRef & choice = winners.front();1042 1043 // fail on only expression deleted1044 if ( ! seen_undeleted ) {1045 SemanticError( untyped->location, choice->expr.get(), "Unique best alternative "1046 "includes deleted identifier in " );1047 }1048 1049 return std::move( choice );1050 }1051 1052 /// Strips extraneous casts out of an expression1053 struct StripCasts_new final {1054 const ast::Expr * postmutate( const ast::CastExpr * castExpr ) {1055 if (1056 castExpr->isGenerated1057 && typesCompatible( castExpr->arg->result, castExpr->result )1058 ) {1059 // generated cast is the same type as its argument, remove it after keeping env1060 return ast::mutate_field(1061 castExpr->arg.get(), &ast::Expr::env, castExpr->env );1062 }1063 return castExpr;1064 }1065 1066 static void strip( ast::ptr< ast::Expr > & expr ) {1067 ast::Pass< StripCasts_new > stripper;1068 expr = expr->accept( stripper );1069 }1070 };1071 1072 /// Swaps argument into expression pointer, saving original environment1073 void swap_and_save_env( ast::ptr< ast::Expr > & expr, const ast::Expr * newExpr ) {1074 ast::ptr< ast::TypeSubstitution > env = expr->env;1075 expr.set_and_mutate( newExpr )->env = env;1076 }1077 1078 /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)1079 void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) {1080 if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {1081 if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) {1082 // cast is to the same type as its argument, remove it1083 swap_and_save_env( expr, castExpr->arg );1084 }1085 }1086 }1087 1088 /// Establish post-resolver invariants for expressions1089 void finishExpr(1090 ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env,1091 const ast::TypeSubstitution * oldenv = nullptr1092 ) {1093 // set up new type substitution for expression1094 ast::ptr< ast::TypeSubstitution > newenv =1095 oldenv ? oldenv : new ast::TypeSubstitution{};1096 env.writeToSubstitution( *newenv.get_and_mutate() );1097 expr.get_and_mutate()->env = std::move( newenv );1098 // remove unncecessary casts1099 StripCasts_new::strip( expr );1100 }1101 } // anonymous namespace1102 1103 1104 ast::ptr< ast::Expr > resolveInVoidContext(1105 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env1106 ) {1107 assertf( expr, "expected a non-null expression" );1108 1109 // set up and resolve expression cast to void1110 ast::CastExpr * untyped = new ast::CastExpr{ expr };1111 CandidateRef choice = findUnfinishedKindExpression(1112 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );1113 1114 // a cast expression has either 0 or 1 interpretations (by language rules);1115 // if 0, an exception has already been thrown, and this code will not run1116 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();1117 env = std::move( choice->env );1118 1119 return castExpr->arg;1120 }1121 1122 namespace {1123 /// Resolve `untyped` to the expression whose candidate is the best match for a `void`1124 /// context.1125 ast::ptr< ast::Expr > findVoidExpression(1126 const ast::Expr * untyped, const ast::SymbolTable & symtab1127 ) {1128 resetTyVarRenaming();1129 ast::TypeEnvironment env;1130 ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );1131 finishExpr( newExpr, env, untyped->env );1132 return newExpr;1133 }1134 1135 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the1136 /// lowest cost, returning the resolved version1137 ast::ptr< ast::Expr > findKindExpression(1138 const ast::Expr * untyped, const ast::SymbolTable & symtab,1139 std::function<bool(const Candidate &)> pred = anyCandidate,1140 const std::string & kind = "", ResolvMode mode = {}1141 ) {1142 if ( ! untyped ) return {};1143 CandidateRef choice =1144 findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );1145 finishExpr( choice->expr, choice->env, untyped->env );1146 return std::move( choice->expr );1147 }1148 1149 /// Resolve `untyped` to the single expression whose candidate is the best match1150 ast::ptr< ast::Expr > findSingleExpression(1151 const ast::Expr * untyped, const ast::SymbolTable & symtab1152 ) {1153 return findKindExpression( untyped, symtab );1154 }1155 } // anonymous namespace1156 1157 ast::ptr< ast::Expr > findSingleExpression(1158 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab1159 ) {1160 assert( untyped && type );1161 ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };1162 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );1163 removeExtraneousCast( newExpr, symtab );1164 return newExpr;1165 }1166 1167 namespace {1168 /// Predicate for "Candidate has integral type"1169 bool hasIntegralType( const Candidate & i ) {1170 const ast::Type * type = i.expr->result;1171 1172 if ( auto bt = dynamic_cast< const ast::BasicType * >( type ) ) {1173 return bt->isInteger();1174 } else if (1175 dynamic_cast< const ast::EnumInstType * >( type )1176 || dynamic_cast< const ast::ZeroType * >( type )1177 || dynamic_cast< const ast::OneType * >( type )1178 ) {1179 return true;1180 } else return false;1181 }1182 1183 /// Resolve `untyped` as an integral expression, returning the resolved version1184 ast::ptr< ast::Expr > findIntegralExpression(1185 const ast::Expr * untyped, const ast::SymbolTable & symtab1186 ) {1187 return findKindExpression( untyped, symtab, hasIntegralType, "condition" );1188 }1189 1190 /// check if a type is a character type1191 bool isCharType( const ast::Type * t ) {1192 if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) {1193 return bt->kind == ast::BasicType::Char1194 || bt->kind == ast::BasicType::SignedChar1195 || bt->kind == ast::BasicType::UnsignedChar;1196 }1197 return false;1198 }1199 1200 /// Advance a type itertor to the next mutex parameter1201 template<typename Iter>1202 inline bool nextMutex( Iter & it, const Iter & end ) {1203 while ( it != end && ! (*it)->get_type()->is_mutex() ) { ++it; }1204 return it != end;1205 }1206 }1207 1208 class Resolver_new final1209 : public ast::WithSymbolTable, public ast::WithGuards,1210 public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting,1211 public ast::WithStmtsToAdd<> {1212 1213 ast::ptr< ast::Type > functionReturn = nullptr;1214 ast::CurrentObject currentObject;1215 bool inEnumDecl = false;1216 1217 public:1218 Resolver_new() = default;1219 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }1220 1221 void previsit( const ast::FunctionDecl * );1222 const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );1223 void previsit( const ast::ObjectDecl * );1224 void previsit( const ast::EnumDecl * );1225 const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );1226 1227 const ast::ArrayType * previsit( const ast::ArrayType * );1228 const ast::PointerType * previsit( const ast::PointerType * );1229 1230 const ast::ExprStmt * previsit( const ast::ExprStmt * );1231 const ast::AsmExpr * previsit( const ast::AsmExpr * );1232 const ast::AsmStmt * previsit( const ast::AsmStmt * );1233 const ast::IfStmt * previsit( const ast::IfStmt * );1234 const ast::WhileStmt * previsit( const ast::WhileStmt * );1235 const ast::ForStmt * previsit( const ast::ForStmt * );1236 const ast::SwitchStmt * previsit( const ast::SwitchStmt * );1237 const ast::CaseStmt * previsit( const ast::CaseStmt * );1238 const ast::BranchStmt * previsit( const ast::BranchStmt * );1239 const ast::ReturnStmt * previsit( const ast::ReturnStmt * );1240 const ast::ThrowStmt * previsit( const ast::ThrowStmt * );1241 const ast::CatchStmt * previsit( const ast::CatchStmt * );1242 const ast::WaitForStmt * previsit( const ast::WaitForStmt * );1243 1244 const ast::SingleInit * previsit( const ast::SingleInit * );1245 const ast::ListInit * previsit( const ast::ListInit * );1246 const ast::ConstructorInit * previsit( const ast::ConstructorInit * );1247 };1248 1249 void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {1250 ast::Pass< Resolver_new > resolver;1251 accept_all( translationUnit, resolver );1252 }1253 1254 ast::ptr< ast::Init > resolveCtorInit(1255 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab1256 ) {1257 assert( ctorInit );1258 ast::Pass< Resolver_new > resolver{ symtab };1259 return ctorInit->accept( resolver );1260 }1261 1262 ast::ptr< ast::Expr > resolveStmtExpr(1263 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab1264 ) {1265 assert( stmtExpr );1266 ast::Pass< Resolver_new > resolver{ symtab };1267 ast::ptr< ast::Expr > ret = stmtExpr;1268 ret = ret->accept( resolver );1269 strict_dynamic_cast< ast::StmtExpr * >( ret.get_and_mutate() )->computeResult();1270 return ret;1271 }1272 1273 void Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {1274 GuardValue( functionReturn );1275 functionReturn = extractResultType( functionDecl->type );1276 }1277 1278 const ast::FunctionDecl * Resolver_new::postvisit( const ast::FunctionDecl * functionDecl ) {1279 // default value expressions have an environment which shouldn't be there and trips up1280 // later passes.1281 ast::ptr< ast::FunctionDecl > ret = functionDecl;1282 for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {1283 const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];1284 1285 if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {1286 if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) {1287 if ( init->value->env == nullptr ) continue;1288 // clone initializer minus the initializer environment1289 ast::chain_mutate( ret )1290 ( &ast::FunctionDecl::type )1291 ( &ast::FunctionType::params )[i]1292 ( &ast::ObjectDecl::init )1293 ( &ast::SingleInit::value )->env = nullptr;1294 1295 assert( functionDecl != ret.get() || functionDecl->unique() );1296 assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env );1297 }1298 }1299 }1300 return ret.get();1301 }1302 1303 void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {1304 // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],1305 // class-variable `initContext` is changed multiple times because the LHS is analyzed1306 // twice. The second analysis changes `initContext` because a function type can contain1307 // object declarations in the return and parameter types. Therefore each value of1308 // `initContext` is retained so the type on the first analysis is preserved and used for1309 // selecting the RHS.1310 GuardValue( currentObject );1311 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };1312 if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {1313 // enumerator initializers should not use the enum type to initialize, since the1314 // enum type is still incomplete at this point. Use `int` instead.1315 currentObject = ast::CurrentObject{1316 objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };1317 }1318 }1319 1320 void Resolver_new::previsit( const ast::EnumDecl * ) {1321 // in case we decide to allow nested enums1322 GuardValue( inEnumDecl );1323 inEnumDecl = false;1324 }1325 1326 const ast::StaticAssertDecl * Resolver_new::previsit(1327 const ast::StaticAssertDecl * assertDecl1328 ) {1329 return ast::mutate_field(1330 assertDecl, &ast::StaticAssertDecl::cond,1331 findIntegralExpression( assertDecl->cond, symtab ) );1332 }1333 1334 template< typename PtrType >1335 const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {1336 if ( type->dimension ) {1337 #warning should use new equivalent to Validate::SizeType rather than sizeType here1338 ast::ptr< ast::Type > sizeType = new ast::BasicType{ ast::BasicType::LongUnsignedInt };1339 ast::mutate_field(1340 type, &PtrType::dimension,1341 findSingleExpression( type->dimension, sizeType, symtab ) );1342 }1343 return type;1344 }1345 1346 const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) {1347 return handlePtrType( at, symtab );1348 }1349 1350 const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) {1351 return handlePtrType( pt, symtab );1352 }1353 1354 const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {1355 visit_children = false;1356 assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );1357 1358 return ast::mutate_field(1359 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) );1360 }1361 1362 const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {1363 visit_children = false;1364 1365 asmExpr = ast::mutate_field(1366 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) );1367 1368 if ( asmExpr->inout ) {1369 asmExpr = ast::mutate_field(1370 asmExpr, &ast::AsmExpr::inout, findVoidExpression( asmExpr->inout, symtab ) );1371 }1372 1373 return asmExpr;1374 }1375 1376 const ast::AsmStmt * Resolver_new::previsit( const ast::AsmStmt * asmStmt ) {1377 visitor->maybe_accept( asmStmt, &ast::AsmStmt::input );1378 visitor->maybe_accept( asmStmt, &ast::AsmStmt::output );1379 visit_children = false;1380 return asmStmt;1381 }1382 1383 const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {1384 return ast::mutate_field(1385 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) );1386 }1387 1388 const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {1389 return ast::mutate_field(1390 whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) );1391 }1392 1393 const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) {1394 if ( forStmt->cond ) {1395 forStmt = ast::mutate_field(1396 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) );1397 }1398 1399 if ( forStmt->inc ) {1400 forStmt = ast::mutate_field(1401 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) );1402 }1403 1404 return forStmt;1405 }1406 1407 const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {1408 GuardValue( currentObject );1409 switchStmt = ast::mutate_field(1410 switchStmt, &ast::SwitchStmt::cond,1411 findIntegralExpression( switchStmt->cond, symtab ) );1412 currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };1413 return switchStmt;1414 }1415 1416 const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {1417 if ( caseStmt->cond ) {1418 std::deque< ast::InitAlternative > initAlts = currentObject.getOptions();1419 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral "1420 "expression." );1421 1422 ast::ptr< ast::Expr > untyped =1423 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };1424 ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab );1425 1426 // case condition cannot have a cast in C, so it must be removed here, regardless of1427 // whether it would perform a conversion.1428 if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) {1429 swap_and_save_env( newExpr, castExpr->arg );1430 }1431 1432 caseStmt = ast::mutate_field( caseStmt, &ast::CaseStmt::cond, newExpr );1433 }1434 return caseStmt;1435 }1436 1437 const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {1438 visit_children = false;1439 // must resolve the argument of a computed goto1440 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {1441 // computed goto argument is void*1442 ast::ptr< ast::Type > target = new ast::PointerType{ new ast::VoidType{} };1443 branchStmt = ast::mutate_field(1444 branchStmt, &ast::BranchStmt::computedTarget,1445 findSingleExpression( branchStmt->computedTarget, target, symtab ) );1446 }1447 return branchStmt;1448 }1449 1450 const ast::ReturnStmt * Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) {1451 visit_children = false;1452 if ( returnStmt->expr ) {1453 returnStmt = ast::mutate_field(1454 returnStmt, &ast::ReturnStmt::expr,1455 findSingleExpression( returnStmt->expr, functionReturn, symtab ) );1456 }1457 return returnStmt;1458 }1459 1460 const ast::ThrowStmt * Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) {1461 visit_children = false;1462 if ( throwStmt->expr ) {1463 const ast::StructDecl * exceptionDecl =1464 symtab.lookupStruct( "__cfaabi_ehm__base_exception_t" );1465 assert( exceptionDecl );1466 ast::ptr< ast::Type > exceptType =1467 new ast::PointerType{ new ast::StructInstType{ exceptionDecl } };1468 throwStmt = ast::mutate_field(1469 throwStmt, &ast::ThrowStmt::expr,1470 findSingleExpression( throwStmt->expr, exceptType, symtab ) );1471 }1472 return throwStmt;1473 }1474 1475 const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {1476 if ( catchStmt->cond ) {1477 ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool };1478 catchStmt = ast::mutate_field(1479 catchStmt, &ast::CatchStmt::cond,1480 findSingleExpression( catchStmt->cond, boolType, symtab ) );1481 }1482 return catchStmt;1483 }1484 1485 const ast::WaitForStmt * Resolver_new::previsit( const ast::WaitForStmt * stmt ) {1486 visit_children = false;1487 1488 // Resolve all clauses first1489 for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) {1490 const ast::WaitForStmt::Clause & clause = stmt->clauses[i];1491 1492 ast::TypeEnvironment env;1493 CandidateFinder funcFinder{ symtab, env };1494 1495 // Find all candidates for a function in canonical form1496 funcFinder.find( clause.target.func, ResolvMode::withAdjustment() );1497 1498 if ( funcFinder.candidates.empty() ) {1499 stringstream ss;1500 ss << "Use of undeclared indentifier '";1501 ss << clause.target.func.strict_as< ast::NameExpr >()->name;1502 ss << "' in call to waitfor";1503 SemanticError( stmt->location, ss.str() );1504 }1505 1506 if ( clause.target.args.empty() ) {1507 SemanticError( stmt->location,1508 "Waitfor clause must have at least one mutex parameter");1509 }1510 1511 // Find all alternatives for all arguments in canonical form1512 std::vector< CandidateFinder > argFinders =1513 funcFinder.findSubExprs( clause.target.args );1514 1515 // List all combinations of arguments1516 std::vector< CandidateList > possibilities;1517 combos( argFinders.begin(), argFinders.end(), back_inserter( possibilities ) );1518 1519 // For every possible function:1520 // * try matching the arguments to the parameters, not the other way around because1521 // more arguments than parameters1522 CandidateList funcCandidates;1523 std::vector< CandidateList > argsCandidates;1524 SemanticErrorException errors;1525 for ( CandidateRef & func : funcFinder.candidates ) {1526 try {1527 auto pointerType = dynamic_cast< const ast::PointerType * >(1528 func->expr->result->stripReferences() );1529 if ( ! pointerType ) {1530 SemanticError( stmt->location, func->expr->result.get(),1531 "candidate not viable: not a pointer type\n" );1532 }1533 1534 auto funcType = pointerType->base.as< ast::FunctionType >();1535 if ( ! funcType ) {1536 SemanticError( stmt->location, func->expr->result.get(),1537 "candidate not viable: not a function type\n" );1538 }1539 1540 {1541 auto param = funcType->params.begin();1542 auto paramEnd = funcType->params.end();1543 1544 if( ! nextMutex( param, paramEnd ) ) {1545 SemanticError( stmt->location, funcType,1546 "candidate function not viable: no mutex parameters\n");1547 }1548 }1549 1550 CandidateRef func2{ new Candidate{ *func } };1551 // strip reference from function1552 func2->expr = referenceToRvalueConversion( func->expr, func2->cost );1553 1554 // Each argument must be matched with a parameter of the current candidate1555 for ( auto & argsList : possibilities ) {1556 try {1557 // Declare data structures needed for resolution1558 ast::OpenVarSet open;1559 ast::AssertionSet need, have;1560 ast::TypeEnvironment resultEnv{ func->env };1561 // Add all type variables as open so that those not used in the1562 // parameter list are still considered open1563 resultEnv.add( funcType->forall );1564 1565 // load type variables from arguments into one shared space1566 for ( auto & arg : argsList ) {1567 resultEnv.simpleCombine( arg->env );1568 }1569 1570 // Make sure we don't widen any existing bindings1571 resultEnv.forbidWidening();1572 1573 // Find any unbound type variables1574 resultEnv.extractOpenVars( open );1575 1576 auto param = funcType->params.begin();1577 auto paramEnd = funcType->params.end();1578 1579 unsigned n_mutex_param = 0;1580 1581 // For every argument of its set, check if it matches one of the1582 // parameters. The order is important1583 for ( auto & arg : argsList ) {1584 // Ignore non-mutex arguments1585 if ( ! nextMutex( param, paramEnd ) ) {1586 // We ran out of parameters but still have arguments.1587 // This function doesn't match1588 SemanticError( stmt->location, funcType,1589 toString("candidate function not viable: too many mutex "1590 "arguments, expected ", n_mutex_param, "\n" ) );1591 }1592 1593 ++n_mutex_param;1594 1595 // Check if the argument matches the parameter type in the current1596 // scope1597 ast::ptr< ast::Type > paramType = (*param)->get_type();1598 if (1599 ! unify(1600 arg->expr->result, paramType, resultEnv, need, have, open,1601 symtab )1602 ) {1603 // Type doesn't match1604 stringstream ss;1605 ss << "candidate function not viable: no known conversion "1606 "from '";1607 ast::print( ss, (*param)->get_type() );1608 ss << "' to '";1609 ast::print( ss, arg->expr->result );1610 ss << "' with env '";1611 ast::print( ss, resultEnv );1612 ss << "'\n";1613 SemanticError( stmt->location, funcType, ss.str() );1614 }1615 1616 ++param;1617 }1618 1619 // All arguments match!1620 1621 // Check if parameters are missing1622 if ( nextMutex( param, paramEnd ) ) {1623 do {1624 ++n_mutex_param;1625 ++param;1626 } while ( nextMutex( param, paramEnd ) );1627 1628 // We ran out of arguments but still have parameters left; this1629 // function doesn't match1630 SemanticError( stmt->location, funcType,1631 toString( "candidate function not viable: too few mutex "1632 "arguments, expected ", n_mutex_param, "\n" ) );1633 }1634 1635 // All parameters match!1636 1637 // Finish the expressions to tie in proper environments1638 finishExpr( func2->expr, resultEnv );1639 for ( CandidateRef & arg : argsList ) {1640 finishExpr( arg->expr, resultEnv );1641 }1642 1643 // This is a match, store it and save it for later1644 funcCandidates.emplace_back( std::move( func2 ) );1645 argsCandidates.emplace_back( std::move( argsList ) );1646 1647 } catch ( SemanticErrorException & e ) {1648 errors.append( e );1649 }1650 }1651 } catch ( SemanticErrorException & e ) {1652 errors.append( e );1653 }1654 }1655 1656 // Make sure correct number of arguments1657 if( funcCandidates.empty() ) {1658 SemanticErrorException top( stmt->location,1659 "No alternatives for function in call to waitfor" );1660 top.append( errors );1661 throw top;1662 }1663 1664 if( argsCandidates.empty() ) {1665 SemanticErrorException top( stmt->location,1666 "No alternatives for arguments in call to waitfor" );1667 top.append( errors );1668 throw top;1669 }1670 1671 if( funcCandidates.size() > 1 ) {1672 SemanticErrorException top( stmt->location,1673 "Ambiguous function in call to waitfor" );1674 top.append( errors );1675 throw top;1676 }1677 if( argsCandidates.size() > 1 ) {1678 SemanticErrorException top( stmt->location,1679 "Ambiguous arguments in call to waitfor" );1680 top.append( errors );1681 throw top;1682 }1683 // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.1684 1685 // build new clause1686 ast::WaitForStmt::Clause clause2;1687 1688 clause2.target.func = funcCandidates.front()->expr;1689 1690 clause2.target.args.reserve( clause.target.args.size() );1691 for ( auto arg : argsCandidates.front() ) {1692 clause2.target.args.emplace_back( std::move( arg->expr ) );1693 }1694 1695 // Resolve the conditions as if it were an IfStmt, statements normally1696 clause2.cond = findSingleExpression( clause.cond, symtab );1697 clause2.stmt = clause.stmt->accept( *visitor );1698 1699 // set results into stmt1700 auto n = mutate( stmt );1701 n->clauses[i] = std::move( clause2 );1702 stmt = n;1703 }1704 1705 if ( stmt->timeout.stmt ) {1706 // resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally1707 ast::WaitForStmt::Timeout timeout2;1708 1709 ast::ptr< ast::Type > target =1710 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };1711 timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab );1712 timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab );1713 timeout2.stmt = stmt->timeout.stmt->accept( *visitor );1714 1715 // set results into stmt1716 auto n = mutate( stmt );1717 n->timeout = std::move( timeout2 );1718 stmt = n;1719 }1720 1721 if ( stmt->orElse.stmt ) {1722 // resolve the condition like IfStmt, stmts normally1723 ast::WaitForStmt::OrElse orElse2;1724 1725 orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab );1726 orElse2.stmt = stmt->orElse.stmt->accept( *visitor );1727 1728 // set results into stmt1729 auto n = mutate( stmt );1730 n->orElse = std::move( orElse2 );1731 stmt = n;1732 }1733 1734 return stmt;1735 }1736 1737 1738 1739 const ast::SingleInit * Resolver_new::previsit( const ast::SingleInit * singleInit ) {1740 visit_children = false;1741 // resolve initialization using the possibilities as determined by the `currentObject`1742 // cursor.1743 ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{1744 singleInit->location, singleInit->value, currentObject.getOptions() };1745 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab );1746 const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();1747 1748 // move cursor to the object that is actually initialized1749 currentObject.setNext( initExpr->designation );1750 1751 // discard InitExpr wrapper and retain relevant pieces.1752 // `initExpr` may have inferred params in the case where the expression specialized a1753 // function pointer, and newExpr may already have inferParams of its own, so a simple1754 // swap is not sufficient1755 ast::Expr::InferUnion inferred = initExpr->inferred;1756 swap_and_save_env( newExpr, initExpr->expr );1757 newExpr.get_and_mutate()->inferred.splice( std::move(inferred) );1758 1759 // get the actual object's type (may not exactly match what comes back from the resolver1760 // due to conversions)1761 const ast::Type * initContext = currentObject.getCurrentType();1762 1763 removeExtraneousCast( newExpr, symtab );1764 1765 // check if actual object's type is char[]1766 if ( auto at = dynamic_cast< const ast::ArrayType * >( initContext ) ) {1767 if ( isCharType( at->base ) ) {1768 // check if the resolved type is char*1769 if ( auto pt = newExpr->result.as< ast::PointerType >() ) {1770 if ( isCharType( pt->base ) ) {1771 // strip cast if we're initializing a char[] with a char*1772 // e.g. char x[] = "hello"1773 if ( auto ce = newExpr.as< ast::CastExpr >() ) {1774 swap_and_save_env( newExpr, ce->arg );1775 }1776 }1777 }1778 }1779 }1780 1781 // move cursor to next object in preparation for next initializer1782 currentObject.increment();1783 1784 // set initializer expression to resolved expression1785 return ast::mutate_field( singleInit, &ast::SingleInit::value, std::move(newExpr) );1786 }1787 1788 const ast::ListInit * Resolver_new::previsit( const ast::ListInit * listInit ) {1789 // move cursor into brace-enclosed initializer-list1790 currentObject.enterListInit( listInit->location );1791 1792 assert( listInit->designations.size() == listInit->initializers.size() );1793 for ( unsigned i = 0; i < listInit->designations.size(); ++i ) {1794 // iterate designations and initializers in pairs, moving the cursor to the current1795 // designated object and resolving the initializer against that object1796 listInit = ast::mutate_field_index(1797 listInit, &ast::ListInit::designations, i,1798 currentObject.findNext( listInit->designations[i] ) );1799 listInit = ast::mutate_field_index(1800 listInit, &ast::ListInit::initializers, i,1801 listInit->initializers[i]->accept( *visitor ) );1802 }1803 1804 // move cursor out of brace-enclosed initializer-list1805 currentObject.exitListInit();1806 1807 visit_children = false;1808 return listInit;1809 }1810 1811 const ast::ConstructorInit * Resolver_new::previsit( const ast::ConstructorInit * ctorInit ) {1812 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::ctor );1813 visitor->maybe_accept( ctorInit, &ast::ConstructorInit::dtor );1814 1815 // found a constructor - can get rid of C-style initializer1816 // xxx - Rob suggests this field is dead code1817 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr );1818 1819 // intrinsic single-parameter constructors and destructors do nothing. Since this was1820 // implicitly generated, there's no way for it to have side effects, so get rid of it to1821 // clean up generated code1822 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {1823 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::ctor, nullptr );1824 }1825 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {1826 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::dtor, nullptr );1827 }1828 1829 return ctorInit;1830 }1831 1832 876 } // namespace ResolvExpr 1833 877
Note:
See TracChangeset
for help on using the changeset viewer.