Changeset b067d9b for src/ResolvExpr/Resolver.cc
- Timestamp:
- Oct 29, 2019, 4:01:24 PM (6 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 773db65, 9421f3d8
- Parents:
- 7951100 (diff), 8364209 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
r7951100 rb067d9b 7 7 // Resolver.cc -- 8 8 // 9 // Author : Richard C. Bilson9 // Author : Aaron B. Moss 10 10 // Created On : Sun May 17 12:17:01 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Feb 17 11:19:40 201813 // Update Count : 2 1311 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Wed May 29 11:00:00 2019 13 // Update Count : 241 14 14 // 15 15 16 #include <stddef.h> // for NULL17 16 #include <cassert> // for strict_dynamic_cast, assert 18 17 #include <memory> // for allocator, allocator_traits<... 19 18 #include <tuple> // for get 20 #include <vector> 19 #include <vector> // for vector 21 20 22 21 #include "Alternative.h" // for Alternative, AltList 23 22 #include "AlternativeFinder.h" // for AlternativeFinder, resolveIn... 23 #include "Candidate.hpp" 24 #include "CandidateFinder.hpp" 25 #include "CurrentObject.h" // for CurrentObject 26 #include "RenameVars.h" // for RenameVars, global_renamer 27 #include "Resolver.h" 28 #include "ResolvMode.h" // for ResolvMode 29 #include "typeops.h" // for extractResultType 30 #include "Unify.h" // for unify 31 #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" 24 38 #include "Common/PassVisitor.h" // for PassVisitor 25 39 #include "Common/SemanticError.h" // for SemanticError 26 40 #include "Common/utility.h" // for ValueGuard, group_iterate 27 #include "CurrentObject.h" // for CurrentObject28 41 #include "InitTweak/GenInit.h" 29 42 #include "InitTweak/InitTweak.h" // for isIntrinsicSingleArgCallStmt 30 #include "RenameVars.h" // for RenameVars, global_renamer31 43 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 32 #include "ResolveTypeof.h" // for resolveTypeof33 #include "Resolver.h"34 44 #include "SymTab/Autogen.h" // for SizeType 35 45 #include "SymTab/Indexer.h" // for Indexer … … 42 52 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 43 53 #include "Tuples/Tuples.h" 44 #include "typeops.h" // for extractResultType 45 #include "Unify.h" // for unify 54 #include "Validate/FindSpecialDecls.h" // for SizeType 46 55 47 56 using namespace std; 48 57 49 58 namespace ResolvExpr { 50 struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting, public WithStmtsToAdd {51 Resolver () {}52 Resolver ( const SymTab::Indexer & other ) {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 ) { 53 62 indexer = other; 54 63 } 55 64 56 void previsit( FunctionDecl *functionDecl ); 57 void postvisit( FunctionDecl *functionDecl ); 58 void previsit( ObjectDecl *objectDecll ); 59 void previsit( TypeDecl *typeDecl ); 65 void previsit( FunctionDecl * functionDecl ); 66 void postvisit( FunctionDecl * functionDecl ); 67 void previsit( ObjectDecl * objectDecll ); 60 68 void previsit( EnumDecl * enumDecl ); 61 69 void previsit( StaticAssertDecl * assertDecl ); … … 64 72 void previsit( PointerType * at ); 65 73 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 );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 ); 78 86 void previsit( WaitForStmt * stmt ); 79 void previsit( WithStmt * withStmt ); 80 81 void previsit( SingleInit *singleInit ); 82 void previsit( ListInit *listInit ); 83 void previsit( ConstructorInit *ctorInit ); 87 88 void previsit( SingleInit * singleInit ); 89 void previsit( ListInit * listInit ); 90 void previsit( ConstructorInit * ctorInit ); 84 91 private: 85 92 typedef std::list< Initializer * >::iterator InitIterator; … … 88 95 void handlePtrType( PtrType * type ); 89 96 90 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );91 97 void fallbackInit( ConstructorInit * ctorInit ); 92 98 … … 96 102 }; 97 103 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 98 111 void resolve( std::list< Declaration * > translationUnit ) { 99 PassVisitor<Resolver > resolver;112 PassVisitor<Resolver_old> resolver; 100 113 acceptAll( translationUnit, resolver ); 101 114 } 102 115 103 void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {104 PassVisitor<Resolver > resolver( indexer );116 void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) { 117 PassVisitor<Resolver_old> resolver( indexer ); 105 118 maybeAccept( decl, resolver ); 106 119 } 107 120 108 121 namespace { 109 struct DeleteFinder : public WithShortCircuiting {122 struct DeleteFinder_old : public WithShortCircuiting { 110 123 DeletedExpr * delExpr = nullptr; 111 124 void previsit( DeletedExpr * expr ) { … … 121 134 122 135 DeletedExpr * findDeletedExpr( Expression * expr ) { 123 PassVisitor<DeleteFinder > finder;136 PassVisitor<DeleteFinder_old> finder; 124 137 expr->accept( finder ); 125 138 return finder.pass.delExpr; … … 127 140 128 141 namespace { 129 struct StripCasts {142 struct StripCasts_old { 130 143 Expression * postmutate( CastExpr * castExpr ) { 131 144 if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) { … … 140 153 141 154 static void strip( Expression *& expr ) { 142 PassVisitor<StripCasts > stripper;155 PassVisitor<StripCasts_old> stripper; 143 156 expr = expr->acceptMutator( stripper ); 144 157 } 145 158 }; 146 159 147 void finishExpr( Expression *& expr, const TypeEnvironment &env, TypeSubstitution * oldenv = nullptr ) {160 void finishExpr( Expression *& expr, const TypeEnvironment & env, TypeSubstitution * oldenv = nullptr ) { 148 161 expr->env = oldenv ? oldenv->clone() : new TypeSubstitution; 149 162 env.makeSubstitution( *expr->env ); 150 StripCasts ::strip( expr ); // remove unnecessary casts that may be buried in an expression163 StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression 151 164 } 152 165 153 166 void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) { 154 167 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 155 if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {168 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) { 156 169 // cast is to the same type as its argument, so it's unnecessary -- remove it 157 170 expr = castExpr->arg; … … 165 178 166 179 namespace { 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) {180 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) { 168 181 assertf( untyped, "expected a non-null expression." ); 182 183 // xxx - this isn't thread-safe, but should work until we parallelize the resolver 184 static unsigned recursion_level = 0; 185 186 ++recursion_level; 169 187 TypeEnvironment env; 170 188 AlternativeFinder finder( indexer, env ); 171 finder.find( untyped, adjust, prune, failFast ); 189 finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode ); 190 --recursion_level; 172 191 173 192 #if 0 … … 182 201 #endif 183 202 203 // produce filtered list of alternatives 184 204 AltList candidates; 185 205 for ( Alternative & alt : finder.get_alternatives() ) { … … 189 209 } 190 210 191 // xxx - if > 1 alternative with same cost, ignore deleted and pick from remaining 192 // choose the lowest cost expression among the candidates 211 // produce invalid error if no candidates 212 if ( candidates.empty() ) { 213 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 214 } 215 216 // search for cheapest candidate 193 217 AltList winners; 194 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 195 if ( winners.size() == 0 ) { 196 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") ); 197 } else if ( winners.size() != 1 ) { 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 ) { 198 250 std::ostringstream stream; 199 251 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n"; … … 204 256 } 205 257 206 // there is one unambiguous interpretation - move the expression into the with statement 207 Alternative & choice = winners.front(); 208 if ( findDeletedExpr( choice.expr ) ) { 258 // single selected choice 259 Alternative& choice = winners.front(); 260 261 // fail on only expression deleted 262 if ( ! seen_undeleted ) { 209 263 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " ); 210 264 } 265 266 // xxx - check for ambiguous expressions 267 268 // output selected choice 211 269 alt = std::move( choice ); 212 270 } 213 271 214 272 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 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) {273 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) { 216 274 if ( ! untyped ) return; 217 275 Alternative choice; 218 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast);276 findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode ); 219 277 finishExpr( choice.expr, choice.env, untyped->env ); 220 278 delete untyped; … … 231 289 232 290 // used in resolveTypeof 233 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer &indexer ) {291 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ) { 234 292 TypeEnvironment env; 235 293 return resolveInVoidContext( expr, indexer, env ); 236 294 } 237 295 238 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer &indexer, TypeEnvironment &env ) {296 Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment & env ) { 239 297 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0 240 298 // interpretations, an exception has already been thrown. 241 299 assertf( expr, "expected a non-null expression." ); 242 300 243 static CastExpr untyped( nullptr ); // cast to void244 untyped .location = expr->location;301 CastExpr * untyped = new CastExpr( expr ); // cast to void 302 untyped->location = expr->location; 245 303 246 304 // set up and resolve expression cast to void 247 untyped.arg = expr;248 305 Alternative choice; 249 findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true);306 findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() ); 250 307 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr ); 308 assert( castExpr ); 251 309 env = std::move( choice.env ); 252 310 … … 256 314 257 315 // unlink the arg so that it isn't deleted twice at the end of the program 258 untyped .arg = nullptr;316 untyped->arg = nullptr; 259 317 return ret; 260 318 } 261 319 262 void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {320 void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) { 263 321 resetTyVarRenaming(); 264 322 TypeEnvironment env; … … 269 327 } 270 328 271 void findSingleExpression( Expression *& untyped, const SymTab::Indexer &indexer ) {329 void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ) { 272 330 findKindExpression( untyped, indexer, "", standardAlternativeFilter ); 273 331 } … … 288 346 if ( dynamic_cast< EnumInstType * >( type ) ) { 289 347 return true; 290 } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) {348 } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) { 291 349 return bt->isInteger(); 292 350 } else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) { … … 297 355 } 298 356 299 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {357 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) { 300 358 findKindExpression( untyped, indexer, "condition", isIntegralType ); 301 359 } 302 360 } 303 361 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 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 ) { 354 398 { 355 399 // resolve with-exprs with parameters in scope and add any newly generated declarations to the … … 367 411 } 368 412 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. 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. 373 458 for ( Declaration * d : functionDecl->type->parameters ) { 374 459 if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) { … … 381 466 } 382 467 383 void Resolver ::previsit( EnumDecl * ) {468 void Resolver_old::previsit( EnumDecl * ) { 384 469 // in case we decide to allow nested enums 385 470 GuardValue( inEnumDecl ); … … 387 472 } 388 473 389 void Resolver ::previsit( StaticAssertDecl * assertDecl ) {474 void Resolver_old::previsit( StaticAssertDecl * assertDecl ) { 390 475 findIntegralExpression( assertDecl->condition, indexer ); 391 476 } 392 477 393 void Resolver ::previsit( ExprStmt *exprStmt ) {478 void Resolver_old::previsit( ExprStmt * exprStmt ) { 394 479 visit_children = false; 395 480 assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" ); … … 397 482 } 398 483 399 void Resolver ::previsit( AsmExpr *asmExpr ) {484 void Resolver_old::previsit( AsmExpr * asmExpr ) { 400 485 visit_children = false; 401 486 findVoidExpression( asmExpr->operand, indexer ); … … 405 490 } 406 491 407 void Resolver ::previsit( AsmStmt *asmStmt ) {492 void Resolver_old::previsit( AsmStmt * asmStmt ) { 408 493 visit_children = false; 409 494 acceptAll( asmStmt->get_input(), *visitor ); … … 411 496 } 412 497 413 void Resolver ::previsit( IfStmt *ifStmt ) {498 void Resolver_old::previsit( IfStmt * ifStmt ) { 414 499 findIntegralExpression( ifStmt->condition, indexer ); 415 500 } 416 501 417 void Resolver ::previsit( WhileStmt *whileStmt ) {502 void Resolver_old::previsit( WhileStmt * whileStmt ) { 418 503 findIntegralExpression( whileStmt->condition, indexer ); 419 504 } 420 505 421 void Resolver ::previsit( ForStmt *forStmt ) {506 void Resolver_old::previsit( ForStmt * forStmt ) { 422 507 if ( forStmt->condition ) { 423 508 findIntegralExpression( forStmt->condition, indexer ); … … 429 514 } 430 515 431 void Resolver ::previsit( SwitchStmt *switchStmt ) {516 void Resolver_old::previsit( SwitchStmt * switchStmt ) { 432 517 GuardValue( currentObject ); 433 518 findIntegralExpression( switchStmt->condition, indexer ); … … 436 521 } 437 522 438 void Resolver ::previsit( CaseStmt *caseStmt ) {523 void Resolver_old::previsit( CaseStmt * caseStmt ) { 439 524 if ( caseStmt->condition ) { 440 525 std::list< InitAlternative > initAlts = currentObject.getOptions(); … … 455 540 } 456 541 457 void Resolver ::previsit( BranchStmt *branchStmt ) {542 void Resolver_old::previsit( BranchStmt * branchStmt ) { 458 543 visit_children = false; 459 544 // must resolve the argument for a computed goto … … 466 551 } 467 552 468 void Resolver ::previsit( ReturnStmt *returnStmt ) {553 void Resolver_old::previsit( ReturnStmt * returnStmt ) { 469 554 visit_children = false; 470 555 if ( returnStmt->expr ) { … … 473 558 } 474 559 475 void Resolver ::previsit( ThrowStmt *throwStmt ) {560 void Resolver_old::previsit( ThrowStmt * throwStmt ) { 476 561 visit_children = false; 477 562 // TODO: Replace *exception type with &exception type. 478 563 if ( throwStmt->get_expr() ) { 479 StructDecl * exception_decl = 480 indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" ); 564 const StructDecl * exception_decl = indexer.lookupStruct( "__cfaabi_ehm__base_exception_t" ); 481 565 assert( exception_decl ); 482 Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, exception_decl) );566 Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) ); 483 567 findSingleExpression( throwStmt->expr, exceptType, indexer ); 484 568 } 485 569 } 486 570 487 void Resolver ::previsit( CatchStmt *catchStmt ) {571 void Resolver_old::previsit( CatchStmt * catchStmt ) { 488 572 if ( catchStmt->cond ) { 489 573 findSingleExpression( catchStmt->cond, new BasicType( noQualifiers, BasicType::Bool ), indexer ); … … 500 584 } 501 585 502 void Resolver ::previsit( WaitForStmt * stmt ) {586 void Resolver_old::previsit( WaitForStmt * stmt ) { 503 587 visit_children = false; 504 588 … … 582 666 583 667 // Make sure we don't widen any existing bindings 584 for ( auto & i : resultEnv ) { 585 i.allowWidening = false; 586 } 668 resultEnv.forbidWidening(); 587 669 588 670 // Find any unbound type variables … … 592 674 auto param_end = function->parameters.end(); 593 675 594 int n_mutex_ arg= 0;676 int n_mutex_param = 0; 595 677 596 678 // For every arguments of its set, check if it matches one of the parameter … … 602 684 // We ran out of parameters but still have arguments 603 685 // this function doesn't match 604 SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_ arg, "\n" ));686 SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" )); 605 687 } 606 688 607 n_mutex_ arg++;689 n_mutex_param++; 608 690 609 691 // Check if the argument matches the parameter type in the current scope … … 628 710 // Check if parameters are missing 629 711 if( advance_to_mutex( param, param_end ) ) { 712 do { 713 n_mutex_param++; 714 param++; 715 } while( advance_to_mutex( param, param_end ) ); 716 630 717 // We ran out of arguments but still have parameters left 631 718 // this function doesn't match 632 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_ arg, "\n" ));719 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" )); 633 720 } 634 721 … … 646 733 647 734 } 648 catch( SemanticErrorException & e ) {735 catch( SemanticErrorException & e ) { 649 736 errors.append( e ); 650 737 } 651 738 } 652 739 } 653 catch( SemanticErrorException & e ) {740 catch( SemanticErrorException & e ) { 654 741 errors.append( e ); 655 742 } … … 694 781 } 695 782 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 ) { 783 bool isCharType( Type * t ) { 727 784 if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) { 728 785 return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar || … … 732 789 } 733 790 734 void Resolver ::previsit( SingleInit *singleInit ) {791 void Resolver_old::previsit( SingleInit * singleInit ) { 735 792 visit_children = false; 736 793 // resolve initialization using the possibilities as determined by the currentObject cursor … … 746 803 initExpr->expr = nullptr; 747 804 std::swap( initExpr->env, newExpr->env ); 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. 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. 750 808 newExpr->spliceInferParams( initExpr ); 751 809 delete initExpr; 752 810 753 // get the actual object's type (may not exactly match what comes back from the resolver due to conversions) 811 // get the actual object's type (may not exactly match what comes back from the resolver 812 // due to conversions) 754 813 Type * initContext = currentObject.getCurrentType(); 755 814 … … 762 821 if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) { 763 822 if ( isCharType( pt->get_base() ) ) { 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"; 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"; 766 826 newExpr = ce->get_arg(); 767 827 ce->set_arg( nullptr ); … … 781 841 } 782 842 783 void Resolver ::previsit( ListInit * listInit ) {843 void Resolver_old::previsit( ListInit * listInit ) { 784 844 visit_children = false; 785 845 // move cursor into brace-enclosed initializer-list 786 846 currentObject.enterListInit(); 787 // xxx - fix this so that the list isn't copied, iterator should be used to change current element 847 // xxx - fix this so that the list isn't copied, iterator should be used to change current 848 // element 788 849 std::list<Designation *> newDesignations; 789 850 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) { 790 // iterate designations and initializers in pairs, moving the cursor to the current designated object and resolving791 // the initializer against that object.851 // iterate designations and initializers in pairs, moving the cursor to the current 852 // designated object and resolving the initializer against that object. 792 853 Designation * des = std::get<0>(p); 793 854 Initializer * init = std::get<1>(p); … … 815 876 816 877 // ConstructorInit - fall back on C-style initializer 817 void Resolver ::fallbackInit( ConstructorInit * ctorInit ) {878 void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) { 818 879 // could not find valid constructor, or found an intrinsic constructor 819 880 // fall back on C-style initializer 820 881 delete ctorInit->get_ctor(); 821 ctorInit->set_ctor( NULL);882 ctorInit->set_ctor( nullptr ); 822 883 delete ctorInit->get_dtor(); 823 ctorInit->set_dtor( NULL);884 ctorInit->set_dtor( nullptr ); 824 885 maybeAccept( ctorInit->get_init(), *visitor ); 825 886 } … … 828 889 void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) { 829 890 assert( ctorInit ); 830 PassVisitor<Resolver > resolver( indexer );891 PassVisitor<Resolver_old> resolver( indexer ); 831 892 ctorInit->accept( resolver ); 832 893 } … … 834 895 void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) { 835 896 assert( stmtExpr ); 836 PassVisitor<Resolver > resolver( indexer );897 PassVisitor<Resolver_old> resolver( indexer ); 837 898 stmtExpr->accept( resolver ); 838 899 stmtExpr->computeResult(); … … 840 901 } 841 902 842 void Resolver ::previsit( ConstructorInit *ctorInit ) {903 void Resolver_old::previsit( ConstructorInit * ctorInit ) { 843 904 visit_children = false; 844 905 // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit … … 864 925 865 926 // xxx - todo -- what about arrays? 866 // if ( dtor == NULL&& InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {927 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) { 867 928 // // can reduce the constructor down to a SingleInit using the 868 929 // // second argument from the ctor call, since 869 930 // delete ctorInit->get_ctor(); 870 // ctorInit->set_ctor( NULL);931 // ctorInit->set_ctor( nullptr ); 871 932 872 933 // Expression * arg = … … 874 935 // } 875 936 } 937 938 /////////////////////////////////////////////////////////////////////////// 939 // 940 // *** NEW RESOLVER *** 941 // 942 /////////////////////////////////////////////////////////////////////////// 943 944 namespace { 945 /// Finds deleted expressions in an expression tree 946 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 namespace 959 960 /// Check if this expression is or includes a deleted expression 961 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 filter 969 bool anyCandidate( const Candidate & ) { return true; } 970 971 /// Calls the CandidateFinder and finds the single best candidate 972 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 resolver 979 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 candidates 988 CandidateList candidates; 989 for ( auto & cand : finder.candidates ) { 990 if ( pred( *cand ) ) { candidates.emplace_back( cand ); } 991 } 992 993 // produce invalid error if no candidates 994 if ( candidates.empty() ) { 995 SemanticError( untyped, 996 toString( "No reasonable alternatives for ", kind, (kind != "" ? " " : ""), 997 "expression: ") ); 998 } 999 1000 // search for cheapest candidate 1001 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 winner 1007 1008 if ( c < 0 ) { 1009 // reset on new cheapest 1010 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 not 1015 if ( seen_undeleted ) continue; 1016 } else if ( ! seen_undeleted ) { 1017 // replace list of equivalent-cost deleted expressions with one non-deleted 1018 winners.clear(); 1019 seen_undeleted = true; 1020 } 1021 } 1022 1023 winners.emplace_back( std::move( cand ) ); 1024 } 1025 1026 // promote candidate.cvtCost to .cost 1027 promoteCvtCost( winners ); 1028 1029 // produce ambiguous errors, if applicable 1030 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 choice 1041 CandidateRef & choice = winners.front(); 1042 1043 // fail on only expression deleted 1044 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 expression 1053 struct StripCasts_new final { 1054 const ast::Expr * postmutate( const ast::CastExpr * castExpr ) { 1055 if ( 1056 castExpr->isGenerated 1057 && typesCompatible( castExpr->arg->result, castExpr->result ) 1058 ) { 1059 // generated cast is the same type as its argument, remove it after keeping env 1060 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 environment 1073 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 it 1083 swap_and_save_env( expr, castExpr->arg ); 1084 } 1085 } 1086 } 1087 1088 /// Establish post-resolver invariants for expressions 1089 void finishExpr( 1090 ast::ptr< ast::Expr > & expr, const ast::TypeEnvironment & env, 1091 const ast::TypeSubstitution * oldenv = nullptr 1092 ) { 1093 // set up new type substitution for expression 1094 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 casts 1099 StripCasts_new::strip( expr ); 1100 } 1101 } // anonymous namespace 1102 1103 1104 ast::ptr< ast::Expr > resolveInVoidContext( 1105 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env 1106 ) { 1107 assertf( expr, "expected a non-null expression" ); 1108 1109 // set up and resolve expression cast to void 1110 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 run 1116 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 & symtab 1127 ) { 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 the 1136 /// lowest cost, returning the resolved version 1137 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 match 1150 ast::ptr< ast::Expr > findSingleExpression( 1151 const ast::Expr * untyped, const ast::SymbolTable & symtab 1152 ) { 1153 return findKindExpression( untyped, symtab ); 1154 } 1155 } // anonymous namespace 1156 1157 ast::ptr< ast::Expr > findSingleExpression( 1158 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab 1159 ) { 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 version 1184 ast::ptr< ast::Expr > findIntegralExpression( 1185 const ast::Expr * untyped, const ast::SymbolTable & symtab 1186 ) { 1187 return findKindExpression( untyped, symtab, hasIntegralType, "condition" ); 1188 } 1189 1190 /// check if a type is a character type 1191 bool isCharType( const ast::Type * t ) { 1192 if ( auto bt = dynamic_cast< const ast::BasicType * >( t ) ) { 1193 return bt->kind == ast::BasicType::Char 1194 || bt->kind == ast::BasicType::SignedChar 1195 || bt->kind == ast::BasicType::UnsignedChar; 1196 } 1197 return false; 1198 } 1199 1200 /// Advance a type itertor to the next mutex parameter 1201 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 final 1209 : 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 & symtab 1256 ) { 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 & symtab 1264 ) { 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 up 1280 // 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 environment 1289 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 analyzed 1306 // twice. The second analysis changes `initContext` because a function type can contain 1307 // object declarations in the return and parameter types. Therefore each value of 1308 // `initContext` is retained so the type on the first analysis is preserved and used for 1309 // 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 the 1314 // 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 enums 1322 GuardValue( inEnumDecl ); 1323 inEnumDecl = false; 1324 } 1325 1326 const ast::StaticAssertDecl * Resolver_new::previsit( 1327 const ast::StaticAssertDecl * assertDecl 1328 ) { 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 here 1338 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 of 1427 // 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 goto 1440 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 first 1489 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 form 1496 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 form 1512 std::vector< CandidateFinder > argFinders = 1513 funcFinder.findSubExprs( clause.target.args ); 1514 1515 // List all combinations of arguments 1516 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 because 1521 // more arguments than parameters 1522 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 function 1552 func2->expr = referenceToRvalueConversion( func->expr, func2->cost ); 1553 1554 // Each argument must be matched with a parameter of the current candidate 1555 for ( auto & argsList : possibilities ) { 1556 try { 1557 // Declare data structures needed for resolution 1558 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 the 1562 // parameter list are still considered open 1563 resultEnv.add( funcType->forall ); 1564 1565 // load type variables from arguments into one shared space 1566 for ( auto & arg : argsList ) { 1567 resultEnv.simpleCombine( arg->env ); 1568 } 1569 1570 // Make sure we don't widen any existing bindings 1571 resultEnv.forbidWidening(); 1572 1573 // Find any unbound type variables 1574 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 the 1582 // parameters. The order is important 1583 for ( auto & arg : argsList ) { 1584 // Ignore non-mutex arguments 1585 if ( ! nextMutex( param, paramEnd ) ) { 1586 // We ran out of parameters but still have arguments. 1587 // This function doesn't match 1588 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 current 1596 // scope 1597 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 match 1604 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 missing 1622 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; this 1629 // function doesn't match 1630 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 environments 1638 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 later 1644 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 arguments 1657 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 clause 1686 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 normally 1696 clause2.cond = findSingleExpression( clause.cond, symtab ); 1697 clause2.stmt = clause.stmt->accept( *visitor ); 1698 1699 // set results into stmt 1700 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 normally 1707 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 stmt 1716 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 normally 1723 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 stmt 1729 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 initialized 1749 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 a 1753 // function pointer, and newExpr may already have inferParams of its own, so a simple 1754 // swap is not sufficient 1755 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 resolver 1760 // 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 initializer 1782 currentObject.increment(); 1783 1784 // set initializer expression to resolved expression 1785 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-list 1790 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 current 1795 // designated object and resolving the initializer against that object 1796 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-list 1805 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 initializer 1816 // xxx - Rob suggests this field is dead code 1817 ctorInit = ast::mutate_field( ctorInit, &ast::ConstructorInit::init, nullptr ); 1818 1819 // intrinsic single-parameter constructors and destructors do nothing. Since this was 1820 // implicitly generated, there's no way for it to have side effects, so get rid of it to 1821 // clean up generated code 1822 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 876 1832 } // namespace ResolvExpr 877 1833
Note:
See TracChangeset
for help on using the changeset viewer.