Changeset ef5b828 for src/SymTab
- Timestamp:
- Jul 12, 2019, 1:35:58 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:
- fce4e31
- Parents:
- 7870799
- Location:
- src/SymTab
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Indexer.cc
r7870799 ref5b828 74 74 } 75 75 76 Indexer::Indexer() 77 : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(), 78 prevScope(), scope( 0 ), repScope( 0 ) { ++* stats().count; }76 Indexer::Indexer() 77 : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(), 78 prevScope(), scope( 0 ), repScope( 0 ) { ++* stats().count; } 79 79 80 80 Indexer::~Indexer() { … … 84 84 void Indexer::lazyInitScope() { 85 85 if ( repScope < scope ) { 86 ++* stats().lazy_scopes;86 ++* stats().lazy_scopes; 87 87 // create rollback 88 prevScope = std::make_shared<Indexer>( * this );88 prevScope = std::make_shared<Indexer>( * this ); 89 89 // update repScope 90 90 repScope = scope; … … 95 95 ++scope; 96 96 97 ++* stats().new_scopes;97 ++* stats().new_scopes; 98 98 stats().avg_scope_depth->push( scope ); 99 99 stats().max_scope_depth->push( scope ); … … 103 103 if ( repScope == scope ) { 104 104 Ptr prev = prevScope; // make sure prevScope stays live 105 * this = std::move(*prevScope); // replace with previous scope105 * this = std::move(* prevScope); // replace with previous scope 106 106 } 107 107 … … 109 109 } 110 110 111 void Indexer::lookupId( const std::string & id, std::list< IdData > &out ) const {112 ++* stats().lookup_calls;111 void Indexer::lookupId( const std::string & id, std::list< IdData > &out ) const { 112 ++* stats().lookup_calls; 113 113 if ( ! idTable ) return; 114 114 115 ++* stats().map_lookups;115 ++* stats().map_lookups; 116 116 auto decls = idTable->find( id ); 117 117 if ( decls == idTable->end() ) return; … … 122 122 } 123 123 124 NamedTypeDecl *Indexer::lookupType( const std::string &id ) const { 125 ++*stats().lookup_calls; 124 const NamedTypeDecl * Indexer::lookupType( const std::string & id ) const { return lookupMutableType(id); } 125 NamedTypeDecl * Indexer::lookupMutableType( const std::string & id ) const { 126 ++* stats().lookup_calls; 126 127 if ( ! typeTable ) return nullptr; 127 ++* stats().map_lookups;128 ++* stats().map_lookups; 128 129 auto it = typeTable->find( id ); 129 130 return it == typeTable->end() ? nullptr : it->second.decl; 130 131 } 131 132 132 StructDecl *Indexer::lookupStruct( const std::string &id ) const { 133 ++*stats().lookup_calls; 133 const StructDecl * Indexer::lookupStruct( const std::string & id ) const { return lookupMutableStruct(id); } 134 StructDecl * Indexer::lookupMutableStruct( const std::string & id ) const { 135 ++* stats().lookup_calls; 134 136 if ( ! structTable ) return nullptr; 135 ++* stats().map_lookups;137 ++* stats().map_lookups; 136 138 auto it = structTable->find( id ); 137 139 return it == structTable->end() ? nullptr : it->second.decl; 138 140 } 139 141 140 EnumDecl *Indexer::lookupEnum( const std::string &id ) const { 141 ++*stats().lookup_calls; 142 const EnumDecl * Indexer::lookupEnum( const std::string & id ) const { return lookupMutableEnum(id); } 143 EnumDecl * Indexer::lookupMutableEnum( const std::string & id ) const { 144 ++* stats().lookup_calls; 142 145 if ( ! enumTable ) return nullptr; 143 ++* stats().map_lookups;146 ++* stats().map_lookups; 144 147 auto it = enumTable->find( id ); 145 148 return it == enumTable->end() ? nullptr : it->second.decl; 146 149 } 147 150 148 UnionDecl *Indexer::lookupUnion( const std::string &id ) const { 149 ++*stats().lookup_calls; 151 const UnionDecl * Indexer::lookupUnion( const std::string & id ) const { return lookupMutableUnion(id); } 152 UnionDecl * Indexer::lookupMutableUnion( const std::string & id ) const { 153 ++* stats().lookup_calls; 150 154 if ( ! unionTable ) return nullptr; 151 ++* stats().map_lookups;155 ++* stats().map_lookups; 152 156 auto it = unionTable->find( id ); 153 157 return it == unionTable->end() ? nullptr : it->second.decl; 154 158 } 155 159 156 TraitDecl *Indexer::lookupTrait( const std::string &id ) const { 157 ++*stats().lookup_calls; 160 const TraitDecl * Indexer::lookupTrait( const std::string & id ) const { return lookupMutableTrait(id); } 161 TraitDecl * Indexer::lookupMutableTrait( const std::string & id ) const { 162 ++* stats().lookup_calls; 158 163 if ( ! traitTable ) return nullptr; 159 ++* stats().map_lookups;164 ++* stats().map_lookups; 160 165 auto it = traitTable->find( id ); 161 166 return it == traitTable->end() ? nullptr : it->second.decl; 162 167 } 163 168 164 const Indexer * Indexer::atScope( unsigned long target ) const {169 const Indexer * Indexer::atScope( unsigned long target ) const { 165 170 // by lazy construction, final indexer in list has repScope 0, cannot be > target 166 171 // otherwise, will find first scope representing the target 167 const Indexer * indexer = this;172 const Indexer * indexer = this; 168 173 while ( indexer->repScope > target ) { 169 174 indexer = indexer->prevScope.get(); … … 172 177 } 173 178 174 NamedTypeDecl *Indexer::globalLookupType( const std::string &id ) const {179 const NamedTypeDecl * Indexer::globalLookupType( const std::string & id ) const { 175 180 return atScope( 0 )->lookupType( id ); 176 181 } 177 182 178 StructDecl *Indexer::globalLookupStruct( const std::string &id ) const {183 const StructDecl * Indexer::globalLookupStruct( const std::string & id ) const { 179 184 return atScope( 0 )->lookupStruct( id ); 180 185 } 181 186 182 UnionDecl *Indexer::globalLookupUnion( const std::string &id ) const {187 const UnionDecl * Indexer::globalLookupUnion( const std::string & id ) const { 183 188 return atScope( 0 )->lookupUnion( id ); 184 189 } 185 190 186 EnumDecl *Indexer::globalLookupEnum( const std::string &id ) const {191 const EnumDecl * Indexer::globalLookupEnum( const std::string & id ) const { 187 192 return atScope( 0 )->lookupEnum( id ); 188 193 } … … 207 212 } 208 213 209 210 bool Indexer::addedIdConflicts( 211 const Indexer::IdData & existing, DeclarationWithType * added,214 215 bool Indexer::addedIdConflicts( 216 const Indexer::IdData & existing, DeclarationWithType * added, 212 217 Indexer::OnConflict handleConflicts, BaseSyntaxNode * deleteStmt ) { 213 // if we're giving the same name mangling to things of different types then there is 218 // if we're giving the same name mangling to things of different types then there is 214 219 // something wrong 215 220 assert( (isObject( added ) && isObject( existing.id ) ) … … 219 224 // new definition shadows the autogenerated one, even at the same scope 220 225 return false; 221 } else if ( LinkageSpec::isMangled( added->linkage ) 222 || ResolvExpr::typesCompatible( 226 } else if ( LinkageSpec::isMangled( added->linkage ) 227 || ResolvExpr::typesCompatible( 223 228 added->get_type(), existing.id->get_type(), Indexer() ) ) { 224 229 … … 238 243 if ( isDefinition( added ) && isDefinition( existing.id ) ) { 239 244 if ( handleConflicts.mode == OnConflict::Error ) { 240 SemanticError( added, 241 isFunction( added ) ? 242 "duplicate function definition for " : 245 SemanticError( added, 246 isFunction( added ) ? 247 "duplicate function definition for " : 243 248 "duplicate object definition for " ); 244 249 } … … 255 260 } 256 261 257 bool Indexer::hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const {262 bool Indexer::hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const { 258 263 if ( ! idTable ) return false; 259 264 260 ++* stats().map_lookups;265 ++* stats().map_lookups; 261 266 auto decls = idTable->find( id ); 262 267 if ( decls == idTable->end() ) return false; … … 270 275 } 271 276 } 272 277 273 278 return false; 274 279 } 275 280 276 bool Indexer::hasIncompatibleCDecl( 277 const std::string & id, const std::string &mangleName ) const {281 bool Indexer::hasIncompatibleCDecl( 282 const std::string & id, const std::string &mangleName ) const { 278 283 if ( ! idTable ) return false; 279 284 280 ++* stats().map_lookups;285 ++* stats().map_lookups; 281 286 auto decls = idTable->find( id ); 282 287 if ( decls == idTable->end() ) return false; … … 295 300 296 301 /// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function 297 std::string getOtypeKey( FunctionDecl * function ) {302 std::string getOtypeKey( FunctionDecl * function ) { 298 303 auto& params = function->type->parameters; 299 304 assert( ! params.empty() ); 300 305 // use base type of pointer, so that qualifiers on the pointer type aren't considered. 301 Type * base = InitTweak::getPointerBase( params.front()->get_type() );306 Type * base = InitTweak::getPointerBase( params.front()->get_type() ); 302 307 assert( base ); 303 308 return Mangler::mangle( base ); 304 309 } 305 310 306 /// gets the declaration for the function acting on a type specified by otype key, 311 /// gets the declaration for the function acting on a type specified by otype key, 307 312 /// nullptr if none such 308 313 FunctionDecl * getFunctionForOtype( DeclarationWithType * decl, const std::string& otypeKey ) { … … 312 317 } 313 318 314 bool Indexer::removeSpecialOverrides( 319 bool Indexer::removeSpecialOverrides( 315 320 Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) { 316 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which 317 // determinethe set of ctor/dtor/assign that can be used by the requester. In particular, 318 // if the user defines a default ctor, then the generated default ctor is unavailable, 319 // likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated 320 // field ctors are available. If the user defines any ctor then the generated default ctor 321 // is unavailable (intrinsic default ctor must be overridden exactly). If the user defines 322 // anything that looks like a copy constructor, then the generated copy constructor is 321 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which 322 // determinethe set of ctor/dtor/assign that can be used by the requester. In particular, 323 // if the user defines a default ctor, then the generated default ctor is unavailable, 324 // likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated 325 // field ctors are available. If the user defines any ctor then the generated default ctor 326 // is unavailable (intrinsic default ctor must be overridden exactly). If the user defines 327 // anything that looks like a copy constructor, then the generated copy constructor is 323 328 // unavailable, and likewise for the assignment operator. 324 329 … … 340 345 std::vector< MangleTable::value_type > deleted; 341 346 bool alreadyUserDefinedFunc = false; 342 343 for ( const auto& entry : * mangleTable ) {347 348 for ( const auto& entry : * mangleTable ) { 344 349 // skip decls that aren't functions or are for the wrong type 345 350 FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); … … 368 373 // perform removals from mangle table, and deletions if necessary 369 374 for ( const auto& key : removed ) { 370 ++* stats().map_mutations;375 ++* stats().map_mutations; 371 376 mangleTable = mangleTable->erase( key ); 372 377 } 373 378 if ( ! alreadyUserDefinedFunc ) for ( const auto& entry : deleted ) { 374 ++* stats().map_mutations;379 ++* stats().map_mutations; 375 380 mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } ); 376 381 } … … 379 384 // if this is the first user-defined function, delete non-user-defined overloads 380 385 std::vector< MangleTable::value_type > deleted; 381 382 for ( const auto& entry : * mangleTable ) {386 387 for ( const auto& entry : * mangleTable ) { 383 388 // skip decls that aren't functions or are for the wrong type 384 389 FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); … … 402 407 // this needs to be a separate loop because of iterator invalidation 403 408 for ( const auto& entry : deleted ) { 404 ++* stats().map_mutations;409 ++* stats().map_mutations; 405 410 mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } ); 406 411 } … … 408 413 // this is an overridable generated function 409 414 // if there already exists a matching user-defined function, delete this appropriately 410 for ( const auto& entry : * mangleTable ) {415 for ( const auto& entry : * mangleTable ) { 411 416 // skip decls that aren't functions or are for the wrong type 412 417 FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); … … 418 423 if ( dataIsCopyFunc ) { 419 424 // remove current function if exists a user-defined copy function 420 // since the signatures for copy functions don't need to match exactly, using 425 // since the signatures for copy functions don't need to match exactly, using 421 426 // a delete statement is the wrong approach 422 427 if ( InitTweak::isCopyFunction( decl, decl->name ) ) return false; … … 428 433 } 429 434 } 430 435 431 436 // nothing (more) to fix, return true 432 437 return true; 433 438 } 434 439 435 void Indexer::addId( 436 DeclarationWithType * decl, OnConflict handleConflicts, Expression * baseExpr,440 void Indexer::addId( 441 DeclarationWithType * decl, OnConflict handleConflicts, Expression * baseExpr, 437 442 BaseSyntaxNode * deleteStmt ) { 438 ++* stats().add_calls;443 ++* stats().add_calls; 439 444 const std::string &name = decl->name; 440 445 if ( name == "" ) return; 441 446 442 447 std::string mangleName; 443 448 if ( LinkageSpec::isOverridable( decl->linkage ) ) { 444 // mangle the name without including the appropriate suffix, so overridable routines 449 // mangle the name without including the appropriate suffix, so overridable routines 445 450 // are placed into the same "bucket" as their user defined versions. 446 451 mangleName = Mangler::mangle( decl, false ); … … 449 454 } // if 450 455 451 // this ensures that no two declarations with the same unmangled name at the same scope 456 // this ensures that no two declarations with the same unmangled name at the same scope 452 457 // both have C linkage 453 458 if ( LinkageSpec::isMangled( decl->linkage ) ) { … … 457 462 } 458 463 } else { 459 // NOTE: only correct if name mangling is completely isomorphic to C 464 // NOTE: only correct if name mangling is completely isomorphic to C 460 465 // type-compatibility, which it may not be. 461 466 if ( hasIncompatibleCDecl( name, mangleName ) ) { … … 470 475 mangleTable = MangleTable::new_ptr(); 471 476 } else { 472 ++* stats().map_lookups;477 ++* stats().map_lookups; 473 478 auto decls = idTable->find( name ); 474 479 if ( decls == idTable->end() ) { … … 477 482 mangleTable = decls->second; 478 483 // skip in-scope repeat declarations of same identifier 479 ++* stats().map_lookups;484 ++* stats().map_lookups; 480 485 auto existing = mangleTable->find( mangleName ); 481 486 if ( existing != mangleTable->end() … … 486 491 // set delete expression for conflicting identifier 487 492 lazyInitScope(); 488 * stats().map_mutations += 2;493 * stats().map_mutations += 2; 489 494 idTable = idTable->set( 490 495 name, 491 mangleTable->set( 492 mangleName, 496 mangleTable->set( 497 mangleName, 493 498 IdData{ existing->second, handleConflicts.deleteStmt } ) ); 494 499 } … … 504 509 // Ensure that auto-generated ctor/dtor/assignment are deleted if necessary 505 510 if ( ! removeSpecialOverrides( data, mangleTable ) ) return; 506 * stats().map_mutations += 2;511 * stats().map_mutations += 2; 507 512 idTable = idTable->set( name, mangleTable->set( mangleName, std::move(data) ) ); 508 513 } … … 518 523 } 519 524 520 bool addedTypeConflicts( NamedTypeDecl * existing, NamedTypeDecl *added ) {525 bool addedTypeConflicts( NamedTypeDecl * existing, NamedTypeDecl * added ) { 521 526 if ( existing->base == nullptr ) { 522 527 return false; … … 530 535 } 531 536 } 532 // does not need to be added to the table if both existing and added have a base that are 537 // does not need to be added to the table if both existing and added have a base that are 533 538 // the same 534 539 return true; 535 540 } 536 541 537 void Indexer::addType( NamedTypeDecl * decl ) {538 ++* stats().add_calls;539 const std::string & id = decl->name;540 541 if ( ! typeTable ) { 542 void Indexer::addType( NamedTypeDecl * decl ) { 543 ++* stats().add_calls; 544 const std::string & id = decl->name; 545 546 if ( ! typeTable ) { 542 547 typeTable = TypeTable::new_ptr(); 543 548 } else { 544 ++* stats().map_lookups;549 ++* stats().map_lookups; 545 550 auto existing = typeTable->find( id ); 546 if ( existing != typeTable->end() 547 && existing->second.scope == scope 551 if ( existing != typeTable->end() 552 && existing->second.scope == scope 548 553 && addedTypeConflicts( existing->second.decl, decl ) ) return; 549 554 } 550 555 551 556 lazyInitScope(); 552 ++* stats().map_mutations;557 ++* stats().map_mutations; 553 558 typeTable = typeTable->set( id, Scoped<NamedTypeDecl>{ decl, scope } ); 554 559 } 555 560 556 bool addedDeclConflicts( AggregateDecl * existing, AggregateDecl *added ) {561 bool addedDeclConflicts( AggregateDecl * existing, AggregateDecl * added ) { 557 562 if ( ! existing->body ) { 558 563 return false; … … 563 568 } 564 569 565 void Indexer::addStruct( const std::string & id ) {570 void Indexer::addStruct( const std::string & id ) { 566 571 addStruct( new StructDecl( id ) ); 567 572 } 568 573 569 void Indexer::addStruct( StructDecl * decl ) {570 ++* stats().add_calls;571 const std::string & id = decl->name;574 void Indexer::addStruct( StructDecl * decl ) { 575 ++* stats().add_calls; 576 const std::string & id = decl->name; 572 577 573 578 if ( ! structTable ) { 574 579 structTable = StructTable::new_ptr(); 575 580 } else { 576 ++* stats().map_lookups;581 ++* stats().map_lookups; 577 582 auto existing = structTable->find( id ); 578 if ( existing != structTable->end() 579 && existing->second.scope == scope 583 if ( existing != structTable->end() 584 && existing->second.scope == scope 580 585 && addedDeclConflicts( existing->second.decl, decl ) ) return; 581 586 } 582 587 583 588 lazyInitScope(); 584 ++* stats().map_mutations;589 ++* stats().map_mutations; 585 590 structTable = structTable->set( id, Scoped<StructDecl>{ decl, scope } ); 586 591 } 587 592 588 void Indexer::addEnum( EnumDecl * decl ) {589 ++* stats().add_calls;590 const std::string & id = decl->name;593 void Indexer::addEnum( EnumDecl * decl ) { 594 ++* stats().add_calls; 595 const std::string & id = decl->name; 591 596 592 597 if ( ! enumTable ) { 593 598 enumTable = EnumTable::new_ptr(); 594 599 } else { 595 ++* stats().map_lookups;600 ++* stats().map_lookups; 596 601 auto existing = enumTable->find( id ); 597 if ( existing != enumTable->end() 598 && existing->second.scope == scope 602 if ( existing != enumTable->end() 603 && existing->second.scope == scope 599 604 && addedDeclConflicts( existing->second.decl, decl ) ) return; 600 605 } 601 606 602 607 lazyInitScope(); 603 ++* stats().map_mutations;608 ++* stats().map_mutations; 604 609 enumTable = enumTable->set( id, Scoped<EnumDecl>{ decl, scope } ); 605 610 } 606 611 607 void Indexer::addUnion( const std::string & id ) {612 void Indexer::addUnion( const std::string & id ) { 608 613 addUnion( new UnionDecl( id ) ); 609 614 } 610 615 611 void Indexer::addUnion( UnionDecl * decl ) {612 ++* stats().add_calls;613 const std::string & id = decl->name;616 void Indexer::addUnion( UnionDecl * decl ) { 617 ++* stats().add_calls; 618 const std::string & id = decl->name; 614 619 615 620 if ( ! unionTable ) { 616 621 unionTable = UnionTable::new_ptr(); 617 622 } else { 618 ++* stats().map_lookups;623 ++* stats().map_lookups; 619 624 auto existing = unionTable->find( id ); 620 if ( existing != unionTable->end() 621 && existing->second.scope == scope 625 if ( existing != unionTable->end() 626 && existing->second.scope == scope 622 627 && addedDeclConflicts( existing->second.decl, decl ) ) return; 623 628 } 624 629 625 630 lazyInitScope(); 626 ++* stats().map_mutations;631 ++* stats().map_mutations; 627 632 unionTable = unionTable->set( id, Scoped<UnionDecl>{ decl, scope } ); 628 633 } 629 634 630 void Indexer::addTrait( TraitDecl * decl ) {631 ++* stats().add_calls;632 const std::string & id = decl->name;635 void Indexer::addTrait( TraitDecl * decl ) { 636 ++* stats().add_calls; 637 const std::string & id = decl->name; 633 638 634 639 if ( ! traitTable ) { 635 640 traitTable = TraitTable::new_ptr(); 636 641 } else { 637 ++* stats().map_lookups;642 ++* stats().map_lookups; 638 643 auto existing = traitTable->find( id ); 639 if ( existing != traitTable->end() 640 && existing->second.scope == scope 644 if ( existing != traitTable->end() 645 && existing->second.scope == scope 641 646 && addedDeclConflicts( existing->second.decl, decl ) ) return; 642 647 } 643 648 644 649 lazyInitScope(); 645 ++* stats().map_mutations;650 ++* stats().map_mutations; 646 651 traitTable = traitTable->set( id, Scoped<TraitDecl>{ decl, scope } ); 647 652 } 648 653 649 void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, 654 void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, 650 655 OnConflict handleConflicts ) { 651 656 for ( Declaration * decl : aggr->members ) { … … 654 659 if ( dwt->name == "" ) { 655 660 Type * t = dwt->get_type()->stripReferences(); 656 if ( dynamic_cast<StructInstType *>( t ) || dynamic_cast<UnionInstType*>( t ) ) {661 if ( dynamic_cast<StructInstType *>( t ) || dynamic_cast<UnionInstType *>( t ) ) { 657 662 Expression * base = expr->clone(); 658 663 ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost? -
src/SymTab/Indexer.h
r7870799 ref5b828 34 34 virtual ~Indexer(); 35 35 36 // when using an indexer manually (e.g., within a mutator traversal), it is necessary to 36 // when using an indexer manually (e.g., within a mutator traversal), it is necessary to 37 37 // tell the indexer explicitly when scopes begin and end 38 38 void enterScope(); … … 50 50 // NOTE: shouldn't need either of these constructors, but gcc-4 does not properly support initializer lists with default members. 51 51 IdData() = default; 52 IdData( 52 IdData( 53 53 DeclarationWithType * id, Expression * baseExpr, BaseSyntaxNode * deleteStmt, 54 unsigned long scope ) 54 unsigned long scope ) 55 55 : id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ), scope( scope ) {} 56 56 IdData( const IdData& o, BaseSyntaxNode * deleteStmt ) … … 61 61 62 62 /// Gets all declarations with the given ID 63 void lookupId( const std::string & id, std::list< IdData > &out ) const;63 void lookupId( const std::string & id, std::list< IdData > &out ) const; 64 64 /// Gets the top-most type declaration with the given ID 65 NamedTypeDecl *lookupType( const std::string &id ) const; 65 const NamedTypeDecl * lookupType( const std::string & id ) const; 66 NamedTypeDecl * lookupMutableType( const std::string & id ) const; 66 67 /// Gets the top-most struct declaration with the given ID 67 StructDecl *lookupStruct( const std::string &id ) const; 68 const StructDecl * lookupStruct( const std::string & id ) const; 69 StructDecl * lookupMutableStruct( const std::string & id ) const; 68 70 /// Gets the top-most enum declaration with the given ID 69 EnumDecl *lookupEnum( const std::string &id ) const; 71 const EnumDecl * lookupEnum( const std::string & id ) const; 72 EnumDecl * lookupMutableEnum( const std::string & id ) const; 70 73 /// Gets the top-most union declaration with the given ID 71 UnionDecl *lookupUnion( const std::string &id ) const; 74 const UnionDecl * lookupUnion( const std::string & id ) const; 75 UnionDecl * lookupMutableUnion( const std::string & id ) const; 72 76 /// Gets the top-most trait declaration with the given ID 73 TraitDecl *lookupTrait( const std::string &id ) const; 77 const TraitDecl * lookupTrait( const std::string & id ) const; 78 TraitDecl * lookupMutableTrait( const std::string & id ) const; 74 79 75 80 /// Gets the type declaration with the given ID at global scope 76 NamedTypeDecl *globalLookupType( const std::string &id ) const;81 const NamedTypeDecl * globalLookupType( const std::string & id ) const; 77 82 /// Gets the struct declaration with the given ID at global scope 78 StructDecl *globalLookupStruct( const std::string &id ) const;83 const StructDecl * globalLookupStruct( const std::string & id ) const; 79 84 /// Gets the union declaration with the given ID at global scope 80 UnionDecl *globalLookupUnion( const std::string &id ) const;85 const UnionDecl * globalLookupUnion( const std::string & id ) const; 81 86 /// Gets the enum declaration with the given ID at global scope 82 EnumDecl *globalLookupEnum( const std::string &id ) const;87 const EnumDecl * globalLookupEnum( const std::string & id ) const; 83 88 84 89 void addId( DeclarationWithType * decl, Expression * baseExpr = nullptr ); 85 90 void addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ); 86 91 87 void addType( NamedTypeDecl * decl );88 void addStruct( const std::string & id );89 void addStruct( StructDecl * decl );90 void addEnum( EnumDecl * decl );91 void addUnion( const std::string & id );92 void addUnion( UnionDecl * decl );93 void addTrait( TraitDecl * decl );92 void addType( NamedTypeDecl * decl ); 93 void addStruct( const std::string & id ); 94 void addStruct( StructDecl * decl ); 95 void addEnum( EnumDecl * decl ); 96 void addUnion( const std::string & id ); 97 void addUnion( UnionDecl * decl ); 98 void addTrait( TraitDecl * decl ); 94 99 95 100 /// adds all of the IDs from WithStmt exprs … … 106 111 107 112 private: 108 /// Wraps a Decl * with a scope113 /// Wraps a Decl * with a scope 109 114 template<typename Decl> 110 115 struct Scoped { 111 Decl * decl; ///< declaration116 Decl * decl; ///< declaration 112 117 unsigned long scope; ///< scope of this declaration 113 118 114 Scoped(Decl * d, unsigned long s) : decl(d), scope(s) {}119 Scoped(Decl * d, unsigned long s) : decl(d), scope(s) {} 115 120 }; 116 121 … … 140 145 141 146 /// Gets the indexer at the given scope 142 const Indexer * atScope( unsigned long scope ) const;147 const Indexer * atScope( unsigned long scope ) const; 143 148 144 /// Removes matching autogenerated constructors and destructors so that they will not be 149 /// Removes matching autogenerated constructors and destructors so that they will not be 145 150 /// selected. If returns false, passed decl should not be added. 146 151 bool removeSpecialOverrides( IdData& decl, MangleTable::Ptr& mangleTable ); … … 166 171 /// true if the existing identifier conflicts with the added identifier 167 172 bool addedIdConflicts( 168 const IdData& existing, DeclarationWithType * added, OnConflict handleConflicts, 173 const IdData& existing, DeclarationWithType * added, OnConflict handleConflicts, 169 174 BaseSyntaxNode * deleteStmt ); 170 175 171 176 /// common code for addId, addDeletedId, etc. 172 void addId( 173 DeclarationWithType * decl, OnConflict handleConflicts, 177 void addId( 178 DeclarationWithType * decl, OnConflict handleConflicts, 174 179 Expression * baseExpr = nullptr, BaseSyntaxNode * deleteStmt = nullptr ); 175 180 … … 178 183 179 184 /// returns true if there exists a declaration with C linkage and the given name with the same mangled name 180 bool hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const;185 bool hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const; 181 186 /// returns true if there exists a declaration with C linkage and the given name with a different mangled name 182 bool hasIncompatibleCDecl( const std::string & id, const std::string &mangleName ) const;187 bool hasIncompatibleCDecl( const std::string & id, const std::string &mangleName ) const; 183 188 }; 184 189 } // namespace SymTab -
src/SymTab/Validate.cc
r7870799 ref5b828 119 119 120 120 private: 121 template< typename AggDecl > void handleAggregate( AggDecl * aggregateDecl );121 template< typename AggDecl > void handleAggregate( AggDecl * aggregateDecl ); 122 122 123 123 AggregateDecl * parentAggr = nullptr; … … 134 134 /// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers. 135 135 struct EnumAndPointerDecay_old { 136 void previsit( EnumDecl * aggregateDecl );137 void previsit( FunctionType * func );136 void previsit( EnumDecl * aggregateDecl ); 137 void previsit( FunctionType * func ); 138 138 }; 139 139 140 140 /// Associates forward declarations of aggregates with their definitions 141 141 struct LinkReferenceToTypes_old final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes_old>, public WithShortCircuiting { 142 LinkReferenceToTypes_old( const Indexer * indexer );143 void postvisit( TypeInstType * typeInst );144 145 void postvisit( EnumInstType * enumInst );146 void postvisit( StructInstType * structInst );147 void postvisit( UnionInstType * unionInst );148 void postvisit( TraitInstType * traitInst );142 LinkReferenceToTypes_old( const Indexer * indexer ); 143 void postvisit( TypeInstType * typeInst ); 144 145 void postvisit( EnumInstType * enumInst ); 146 void postvisit( StructInstType * structInst ); 147 void postvisit( UnionInstType * unionInst ); 148 void postvisit( TraitInstType * traitInst ); 149 149 void previsit( QualifiedType * qualType ); 150 150 void postvisit( QualifiedType * qualType ); 151 151 152 void postvisit( EnumDecl * enumDecl );153 void postvisit( StructDecl * structDecl );154 void postvisit( UnionDecl * unionDecl );152 void postvisit( EnumDecl * enumDecl ); 153 void postvisit( StructDecl * structDecl ); 154 void postvisit( UnionDecl * unionDecl ); 155 155 void postvisit( TraitDecl * traitDecl ); 156 156 157 void previsit( StructDecl * structDecl );158 void previsit( UnionDecl * unionDecl );157 void previsit( StructDecl * structDecl ); 158 void previsit( UnionDecl * unionDecl ); 159 159 160 160 void renameGenericParams( std::list< TypeDecl * > & params ); 161 161 162 162 private: 163 const Indexer * local_indexer;163 const Indexer * local_indexer; 164 164 165 165 typedef std::map< std::string, std::list< EnumInstType * > > ForwardEnumsType; … … 239 239 240 240 template<typename AggDecl> 241 void handleAggregate( AggDecl * aggregateDecl );241 void handleAggregate( AggDecl * aggregateDecl ); 242 242 243 243 void previsit( StructDecl * aggregateDecl ); … … 252 252 static void verify( std::list< Declaration * > &translationUnit ); 253 253 254 void previsit( FunctionDecl * funcDecl );254 void previsit( FunctionDecl * funcDecl ); 255 255 }; 256 256 … … 287 287 Type::StorageClasses storageClasses; 288 288 289 void premutate( ObjectDecl * objectDecl );290 Expression * postmutate( CompoundLiteralExpr * compLitExpr );289 void premutate( ObjectDecl * objectDecl ); 290 Expression * postmutate( CompoundLiteralExpr * compLitExpr ); 291 291 }; 292 292 … … 393 393 } 394 394 395 void validateType( Type * type, const Indexer *indexer ) {395 void validateType( Type * type, const Indexer * indexer ) { 396 396 PassVisitor<EnumAndPointerDecay_old> epc; 397 397 PassVisitor<LinkReferenceToTypes_old> lrt( indexer ); … … 496 496 } 497 497 498 bool shouldHoist( Declaration * decl ) {498 bool shouldHoist( Declaration * decl ) { 499 499 return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl ) || dynamic_cast< StaticAssertDecl * >( decl ); 500 500 } … … 515 515 516 516 template< typename AggDecl > 517 void HoistStruct::handleAggregate( AggDecl * aggregateDecl ) {517 void HoistStruct::handleAggregate( AggDecl * aggregateDecl ) { 518 518 if ( parentAggr ) { 519 519 aggregateDecl->parent = parentAggr; … … 560 560 561 561 562 bool isTypedef( Declaration * decl ) {562 bool isTypedef( Declaration * decl ) { 563 563 return dynamic_cast< TypedefDecl * >( decl ); 564 564 } … … 571 571 572 572 template< typename AggDecl > 573 void EliminateTypedef::handleAggregate( AggDecl * aggregateDecl ) {573 void EliminateTypedef::handleAggregate( AggDecl * aggregateDecl ) { 574 574 filter( aggregateDecl->members, isTypedef, true ); 575 575 } … … 586 586 // remove and delete decl stmts 587 587 filter( compoundStmt->kids, [](Statement * stmt) { 588 if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {588 if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) { 589 589 if ( dynamic_cast< TypedefDecl * >( declStmt->decl ) ) { 590 590 return true; … … 595 595 } 596 596 597 void EnumAndPointerDecay_old::previsit( EnumDecl * enumDecl ) {597 void EnumAndPointerDecay_old::previsit( EnumDecl * enumDecl ) { 598 598 // Set the type of each member of the enumeration to be EnumConstant 599 599 for ( std::list< Declaration * >::iterator i = enumDecl->members.begin(); i != enumDecl->members.end(); ++i ) { 600 ObjectDecl * obj = dynamic_cast< ObjectDecl * >( * i );600 ObjectDecl * obj = dynamic_cast< ObjectDecl * >( * i ); 601 601 assert( obj ); 602 602 obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->name ) ); … … 627 627 } 628 628 629 void EnumAndPointerDecay_old::previsit( FunctionType * func ) {629 void EnumAndPointerDecay_old::previsit( FunctionType * func ) { 630 630 // Fix up parameters and return types 631 631 fixFunctionList( func->parameters, func->isVarArgs, func ); … … 633 633 } 634 634 635 LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) {635 LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) { 636 636 if ( other_indexer ) { 637 637 local_indexer = other_indexer; … … 641 641 } 642 642 643 void LinkReferenceToTypes_old::postvisit( EnumInstType * enumInst ) {644 EnumDecl * st = local_indexer->lookupEnum( enumInst->name );643 void LinkReferenceToTypes_old::postvisit( EnumInstType * enumInst ) { 644 EnumDecl * st = local_indexer->lookupMutableEnum( enumInst->name ); 645 645 // it's not a semantic error if the enum is not found, just an implicit forward declaration 646 646 if ( st ) { … … 661 661 } 662 662 663 void LinkReferenceToTypes_old::postvisit( StructInstType * structInst ) {664 StructDecl * st = local_indexer->lookupStruct( structInst->name );663 void LinkReferenceToTypes_old::postvisit( StructInstType * structInst ) { 664 StructDecl * st = local_indexer->lookupMutableStruct( structInst->name ); 665 665 // it's not a semantic error if the struct is not found, just an implicit forward declaration 666 666 if ( st ) { … … 674 674 } 675 675 676 void LinkReferenceToTypes_old::postvisit( UnionInstType * unionInst ) {677 UnionDecl * un = local_indexer->lookupUnion( unionInst->name );676 void LinkReferenceToTypes_old::postvisit( UnionInstType * unionInst ) { 677 UnionDecl * un = local_indexer->lookupMutableUnion( unionInst->name ); 678 678 // it's not a semantic error if the union is not found, just an implicit forward declaration 679 679 if ( un ) { … … 693 693 void LinkReferenceToTypes_old::postvisit( QualifiedType * qualType ) { 694 694 // linking only makes sense for the 'oldest ancestor' of the qualified type 695 qualType->parent->accept( * visitor );695 qualType->parent->accept( * visitor ); 696 696 } 697 697 … … 762 762 void LinkReferenceToTypes_old::postvisit( TraitInstType * traitInst ) { 763 763 // handle other traits 764 TraitDecl * traitDecl = local_indexer->lookupTrait( traitInst->name );764 TraitDecl * traitDecl = local_indexer->lookupMutableTrait( traitInst->name ); 765 765 if ( ! traitDecl ) { 766 766 SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name ); … … 786 786 } 787 787 788 void LinkReferenceToTypes_old::postvisit( EnumDecl * enumDecl ) {788 void LinkReferenceToTypes_old::postvisit( EnumDecl * enumDecl ) { 789 789 // visit enum members first so that the types of self-referencing members are updated properly 790 790 if ( enumDecl->body ) { … … 792 792 if ( fwds != forwardEnums.end() ) { 793 793 for ( std::list< EnumInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) { 794 (* inst)->baseEnum = enumDecl;794 (* inst)->baseEnum = enumDecl; 795 795 } // for 796 796 forwardEnums.erase( fwds ); … … 834 834 } 835 835 836 void LinkReferenceToTypes_old::postvisit( StructDecl * structDecl ) {836 void LinkReferenceToTypes_old::postvisit( StructDecl * structDecl ) { 837 837 // visit struct members first so that the types of self-referencing members are updated properly 838 838 // xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and their defaults) … … 841 841 if ( fwds != forwardStructs.end() ) { 842 842 for ( std::list< StructInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) { 843 (* inst)->baseStruct = structDecl;843 (* inst)->baseStruct = structDecl; 844 844 } // for 845 845 forwardStructs.erase( fwds ); … … 848 848 } 849 849 850 void LinkReferenceToTypes_old::postvisit( UnionDecl * unionDecl ) {850 void LinkReferenceToTypes_old::postvisit( UnionDecl * unionDecl ) { 851 851 if ( unionDecl->body ) { 852 852 ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->name ); 853 853 if ( fwds != forwardUnions.end() ) { 854 854 for ( std::list< UnionInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) { 855 (* inst)->baseUnion = unionDecl;855 (* inst)->baseUnion = unionDecl; 856 856 } // for 857 857 forwardUnions.erase( fwds ); … … 860 860 } 861 861 862 void LinkReferenceToTypes_old::postvisit( TypeInstType * typeInst ) {862 void LinkReferenceToTypes_old::postvisit( TypeInstType * typeInst ) { 863 863 // ensure generic parameter instances are renamed like the base type 864 864 if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name; 865 if ( NamedTypeDecl *namedTypeDecl = local_indexer->lookupType( typeInst->name ) ) {866 if ( TypeDecl *typeDecl = dynamic_cast<TypeDecl * >( namedTypeDecl ) ) {867 typeInst->set_isFtype( typeDecl-> get_kind()== TypeDecl::Ftype );865 if ( const NamedTypeDecl * namedTypeDecl = local_indexer->lookupType( typeInst->name ) ) { 866 if ( const TypeDecl * typeDecl = dynamic_cast< const TypeDecl * >( namedTypeDecl ) ) { 867 typeInst->set_isFtype( typeDecl->kind == TypeDecl::Ftype ); 868 868 } // if 869 869 } // if … … 877 877 // expand trait instances into their members 878 878 for ( DeclarationWithType * assertion : asserts ) { 879 if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {879 if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) { 880 880 // expand trait instance into all of its members 881 881 expandAssertions( traitInst, back_inserter( type->assertions ) ); … … 897 897 } 898 898 899 void ForallPointerDecay_old::previsit( ObjectDecl * object ) {899 void ForallPointerDecay_old::previsit( ObjectDecl * object ) { 900 900 // ensure that operator names only apply to functions or function pointers 901 901 if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) { … … 905 905 } 906 906 907 void ForallPointerDecay_old::previsit( FunctionDecl * func ) {907 void ForallPointerDecay_old::previsit( FunctionDecl * func ) { 908 908 func->fixUniqueId(); 909 909 } … … 961 961 Type * ReplaceTypedef::postmutate( QualifiedType * qualType ) { 962 962 // replacing typedefs only makes sense for the 'oldest ancestor' of the qualified type 963 qualType->parent = qualType->parent->acceptMutator( * visitor );963 qualType->parent = qualType->parent->acceptMutator( * visitor ); 964 964 return qualType; 965 965 } … … 970 970 TypedefMap::const_iterator def = typedefNames.find( typeInst->name ); 971 971 if ( def != typedefNames.end() ) { 972 Type * ret = def->second.first->base->clone();972 Type * ret = def->second.first->base->clone(); 973 973 ret->location = typeInst->location; 974 974 ret->get_qualifiers() |= typeInst->get_qualifiers(); … … 982 982 // place instance parameters on the typedef'd type 983 983 if ( ! typeInst->parameters.empty() ) { 984 ReferenceToType * rtt = dynamic_cast<ReferenceToType*>(ret);984 ReferenceToType * rtt = dynamic_cast<ReferenceToType *>(ret); 985 985 if ( ! rtt ) { 986 986 SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name ); … … 988 988 rtt->parameters.clear(); 989 989 cloneAll( typeInst->parameters, rtt->parameters ); 990 mutateAll( rtt->parameters, * visitor ); // recursively fix typedefs on parameters990 mutateAll( rtt->parameters, * visitor ); // recursively fix typedefs on parameters 991 991 } // if 992 992 delete typeInst; … … 1043 1043 // struct screen; 1044 1044 // because the expansion of the typedef is: 1045 // void rtn( SCREEN * p ) => void rtn( struct screen *p )1045 // void rtn( SCREEN * p ) => void rtn( struct screen * p ) 1046 1046 // hence the type-name "screen" must be defined. 1047 1047 // Note, qualifiers on the typedef are superfluous for the forward declaration. 1048 1048 1049 Type * designatorType = tyDecl->base->stripDeclarator();1050 if ( StructInstType * aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) {1049 Type * designatorType = tyDecl->base->stripDeclarator(); 1050 if ( StructInstType * aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) { 1051 1051 declsToAddBefore.push_back( new StructDecl( aggDecl->name, DeclarationNode::Struct, noAttributes, tyDecl->linkage ) ); 1052 } else if ( UnionInstType * aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) {1052 } else if ( UnionInstType * aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) { 1053 1053 declsToAddBefore.push_back( new UnionDecl( aggDecl->name, noAttributes, tyDecl->linkage ) ); 1054 } else if ( EnumInstType * enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) {1054 } else if ( EnumInstType * enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) { 1055 1055 declsToAddBefore.push_back( new EnumDecl( enumDecl->name, noAttributes, tyDecl->linkage ) ); 1056 1056 } // if … … 1078 1078 1079 1079 DeclarationWithType * ReplaceTypedef::postmutate( ObjectDecl * objDecl ) { 1080 if ( FunctionType * funtype = dynamic_cast<FunctionType *>( objDecl->type ) ) { // function type?1080 if ( FunctionType * funtype = dynamic_cast<FunctionType *>( objDecl->type ) ) { // function type? 1081 1081 // replace the current object declaration with a function declaration 1082 1082 FunctionDecl * newDecl = new FunctionDecl( objDecl->name, objDecl->get_storageClasses(), objDecl->linkage, funtype, 0, objDecl->attributes, objDecl->get_funcSpec() ); … … 1104 1104 void ReplaceTypedef::addImplicitTypedef( AggDecl * aggDecl ) { 1105 1105 if ( typedefNames.count( aggDecl->get_name() ) == 0 ) { 1106 Type * type = nullptr;1106 Type * type = nullptr; 1107 1107 if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( aggDecl ) ) { 1108 1108 type = new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ); … … 1130 1130 GuardScope( typedefNames ); 1131 1131 GuardScope( typedeclNames ); 1132 mutateAll( aggr->parameters, * visitor );1132 mutateAll( aggr->parameters, * visitor ); 1133 1133 1134 1134 // unroll mutateAll for aggr->members so that implicit typedefs for nested types are added to the aggregate body. … … 1137 1137 1138 1138 try { 1139 * i = maybeMutate( *i, *visitor );1139 * i = maybeMutate( * i, * visitor ); 1140 1140 } catch ( SemanticErrorException &e ) { 1141 1141 errors.append( e ); … … 1217 1217 for ( size_t i = 0; paramIter != params->end(); ++paramIter, ++i ) { 1218 1218 if ( i < args.size() ) { 1219 TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( * std::next( args.begin(), i ) );1220 sub.add( (* paramIter)->get_name(), expr->get_type()->clone() );1219 TypeExpr * expr = strict_dynamic_cast< TypeExpr * >( * std::next( args.begin(), i ) ); 1220 sub.add( (* paramIter)->get_name(), expr->get_type()->clone() ); 1221 1221 } else if ( i == args.size() ) { 1222 Type * defaultType = (* paramIter)->get_init();1222 Type * defaultType = (* paramIter)->get_init(); 1223 1223 if ( defaultType ) { 1224 1224 args.push_back( new TypeExpr( defaultType->clone() ) ); 1225 sub.add( (* paramIter)->get_name(), defaultType->clone() );1225 sub.add( (* paramIter)->get_name(), defaultType->clone() ); 1226 1226 } 1227 1227 } … … 1242 1242 } 1243 1243 1244 void CompoundLiteral::premutate( ObjectDecl * objectDecl ) {1244 void CompoundLiteral::premutate( ObjectDecl * objectDecl ) { 1245 1245 storageClasses = objectDecl->get_storageClasses(); 1246 1246 } 1247 1247 1248 Expression * CompoundLiteral::postmutate( CompoundLiteralExpr *compLitExpr ) {1248 Expression * CompoundLiteral::postmutate( CompoundLiteralExpr * compLitExpr ) { 1249 1249 // transform [storage_class] ... (struct S){ 3, ... }; 1250 1250 // into [storage_class] struct S temp = { 3, ... }; 1251 1251 static UniqueName indexName( "_compLit" ); 1252 1252 1253 ObjectDecl * tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );1253 ObjectDecl * tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() ); 1254 1254 compLitExpr->set_result( nullptr ); 1255 1255 compLitExpr->set_initializer( nullptr ); … … 1289 1289 TupleType * tupleType = strict_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) ); 1290 1290 // ensure return value is not destructed by explicitly creating an empty ListInit node wherein maybeConstruct is false. 1291 ObjectDecl * newRet = new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer *>(), noDesignators, false ) );1291 ObjectDecl * newRet = new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer *>(), noDesignators, false ) ); 1292 1292 deleteAll( retVals ); 1293 1293 retVals.clear(); … … 1302 1302 1303 1303 void FixObjectType::previsit( ObjectDecl * objDecl ) { 1304 Type * new_type = ResolvExpr::resolveTypeof( objDecl->get_type(), indexer );1304 Type * new_type = ResolvExpr::resolveTypeof( objDecl->get_type(), indexer ); 1305 1305 new_type->get_qualifiers() -= Type::Lvalue; // even if typeof is lvalue, variable can never have lvalue-qualified type 1306 1306 objDecl->set_type( new_type ); … … 1308 1308 1309 1309 void FixObjectType::previsit( FunctionDecl * funcDecl ) { 1310 Type * new_type = ResolvExpr::resolveTypeof( funcDecl->type, indexer );1310 Type * new_type = ResolvExpr::resolveTypeof( funcDecl->type, indexer ); 1311 1311 new_type->get_qualifiers() -= Type::Lvalue; // even if typeof is lvalue, variable can never have lvalue-qualified type 1312 1312 funcDecl->set_type( new_type ); 1313 1313 } 1314 1314 1315 void FixObjectType::previsit( TypeDecl * typeDecl ) {1315 void FixObjectType::previsit( TypeDecl * typeDecl ) { 1316 1316 if ( typeDecl->get_base() ) { 1317 Type * new_type = ResolvExpr::resolveTypeof( typeDecl->get_base(), indexer );1317 Type * new_type = ResolvExpr::resolveTypeof( typeDecl->get_base(), indexer ); 1318 1318 new_type->get_qualifiers() -= Type::Lvalue; // even if typeof is lvalue, variable can never have lvalue-qualified type 1319 1319 typeDecl->set_base( new_type ); … … 1378 1378 1379 1379 namespace { 1380 /// Replaces enum types by int, and function/array types in function parameter and return 1380 /// Replaces enum types by int, and function/array types in function parameter and return 1381 1381 /// lists by appropriate pointers 1382 1382 struct EnumAndPointerDecay_new { … … 1385 1385 for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) { 1386 1386 // build new version of object with EnumConstant 1387 ast::ptr< ast::ObjectDecl > obj = 1387 ast::ptr< ast::ObjectDecl > obj = 1388 1388 enumDecl->members[i].strict_as< ast::ObjectDecl >(); 1389 obj.get_and_mutate()->type = 1389 obj.get_and_mutate()->type = 1390 1390 new ast::EnumInstType{ enumDecl->name, ast::CV::Const }; 1391 1391 1392 1392 // set into decl 1393 1393 ast::EnumDecl * mut = mutate( enumDecl ); … … 1399 1399 1400 1400 static const ast::FunctionType * fixFunctionList( 1401 const ast::FunctionType * func, 1401 const ast::FunctionType * func, 1402 1402 std::vector< ast::ptr< ast::DeclWithType > > ast::FunctionType::* field, 1403 1403 ast::ArgumentFlag isVarArgs = ast::FixedArgs 1404 1404 ) { 1405 const auto & dwts = func->* field;1405 const auto & dwts = func->* field; 1406 1406 unsigned nvals = dwts.size(); 1407 1407 bool hasVoid = false; … … 1409 1409 func = ast::mutate_field_index( func, field, i, fixFunction( dwts[i], hasVoid ) ); 1410 1410 } 1411 1411 1412 1412 // the only case in which "void" is valid is where it is the only one in the list 1413 1413 if ( hasVoid && ( nvals > 1 || isVarArgs ) ) { 1414 SemanticError( 1414 SemanticError( 1415 1415 dwts.front()->location, func, "invalid type void in function type" ); 1416 1416 } … … 1418 1418 // one void is the only thing in the list, remove it 1419 1419 if ( hasVoid ) { 1420 func = ast::mutate_field( 1420 func = ast::mutate_field( 1421 1421 func, field, std::vector< ast::ptr< ast::DeclWithType > >{} ); 1422 1422 } … … 1432 1432 1433 1433 /// expand assertions from a trait instance, performing appropriate type variable substitutions 1434 void expandAssertions( 1435 const ast::TraitInstType * inst, std::vector< ast::ptr< ast::DeclWithType > > & out 1434 void expandAssertions( 1435 const ast::TraitInstType * inst, std::vector< ast::ptr< ast::DeclWithType > > & out 1436 1436 ) { 1437 1437 assertf( inst->base, "Trait instance not linked to base trait: %s", toCString( inst ) ); 1438 1438 1439 1439 // build list of trait members, substituting trait decl parameters for instance parameters 1440 ast::TypeSubstitution sub{ 1440 ast::TypeSubstitution sub{ 1441 1441 inst->base->params.begin(), inst->base->params.end(), inst->params.begin() }; 1442 1442 // deliberately take ast::ptr by-value to ensure this does not mutate inst->base … … 1449 1449 1450 1450 /// Associates forward declarations of aggregates with their definitions 1451 class LinkReferenceToTypes_new final 1452 : public ast::WithSymbolTable, public ast::WithGuards, public 1451 class LinkReferenceToTypes_new final 1452 : public ast::WithSymbolTable, public ast::WithGuards, public 1453 1453 ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting { 1454 1455 // these maps of uses of forward declarations of types need to have the actual type 1456 // declaration switched in * after* they have been traversed. To enable this in the1457 // ast::Pass framework, any node that needs to be so mutated has mutate() called on it 1458 // before it is placed in the map, properly updating its parents in the usual traversal, 1454 1455 // these maps of uses of forward declarations of types need to have the actual type 1456 // declaration switched in * after * they have been traversed. To enable this in the 1457 // ast::Pass framework, any node that needs to be so mutated has mutate() called on it 1458 // before it is placed in the map, properly updating its parents in the usual traversal, 1459 1459 // then can have the actual mutation applied later 1460 1460 using ForwardEnumsType = std::unordered_multimap< std::string, ast::EnumInstType * >; 1461 1461 using ForwardStructsType = std::unordered_multimap< std::string, ast::StructInstType * >; 1462 1462 using ForwardUnionsType = std::unordered_multimap< std::string, ast::UnionInstType * >; 1463 1463 1464 1464 const CodeLocation & location; 1465 1465 const ast::SymbolTable * localSymtab; 1466 1466 1467 1467 ForwardEnumsType forwardEnums; 1468 1468 ForwardStructsType forwardStructs; 1469 1469 ForwardUnionsType forwardUnions; 1470 1470 1471 /// true if currently in a generic type body, so that type parameter instances can be 1471 /// true if currently in a generic type body, so that type parameter instances can be 1472 1472 /// renamed appropriately 1473 1473 bool inGeneric = false; … … 1475 1475 public: 1476 1476 /// contstruct using running symbol table 1477 LinkReferenceToTypes_new( const CodeLocation & loc ) 1477 LinkReferenceToTypes_new( const CodeLocation & loc ) 1478 1478 : location( loc ), localSymtab( &symtab ) {} 1479 1479 1480 1480 /// construct using provided symbol table 1481 LinkReferenceToTypes_new( const CodeLocation & loc, const ast::SymbolTable & syms ) 1481 LinkReferenceToTypes_new( const CodeLocation & loc, const ast::SymbolTable & syms ) 1482 1482 : location( loc ), localSymtab( &syms ) {} 1483 1483 … … 1485 1485 // ensure generic parameter instances are renamed like the base type 1486 1486 if ( inGeneric && typeInst->base ) { 1487 typeInst = ast::mutate_field( 1487 typeInst = ast::mutate_field( 1488 1488 typeInst, &ast::TypeInstType::name, typeInst->base->name ); 1489 1489 } 1490 1490 1491 if ( 1492 auto typeDecl = dynamic_cast< const ast::TypeDecl * >( 1493 localSymtab->lookupType( typeInst->name ) ) 1491 if ( 1492 auto typeDecl = dynamic_cast< const ast::TypeDecl * >( 1493 localSymtab->lookupType( typeInst->name ) ) 1494 1494 ) { 1495 1495 typeInst = ast::mutate_field( typeInst, &ast::TypeInstType::kind, typeDecl->kind ); … … 1517 1517 for ( const ast::Expr * param : inst->params ) { 1518 1518 if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) { 1519 SemanticError( 1519 SemanticError( 1520 1520 location, inst, "Expression parameters for generic types are currently " 1521 1521 "unsupported: " ); … … 1571 1571 auto expr = traitInst->params[i].as< ast::TypeExpr >(); 1572 1572 if ( ! expr ) { 1573 SemanticError( 1573 SemanticError( 1574 1574 traitInst->params[i].get(), "Expression parameters for trait instances " 1575 1575 "are currently unsupported: " ); … … 1593 1593 return traitInst; 1594 1594 } 1595 1595 1596 1596 void previsit( const ast::QualifiedType * ) { visit_children = false; } 1597 1597 1598 1598 const ast::Type * postvisit( const ast::QualifiedType * qualType ) { 1599 1599 // linking only makes sense for the "oldest ancestor" of the qualified type 1600 return ast::mutate_field( 1601 qualType, &ast::QualifiedType::parent, qualType->parent->accept( * visitor ) );1600 return ast::mutate_field( 1601 qualType, &ast::QualifiedType::parent, qualType->parent->accept( * visitor ) ); 1602 1602 } 1603 1603 1604 1604 const ast::Decl * postvisit( const ast::EnumDecl * enumDecl ) { 1605 // visit enum members first so that the types of self-referencing members are updated 1605 // visit enum members first so that the types of self-referencing members are updated 1606 1606 // properly 1607 1607 if ( ! enumDecl->body ) return enumDecl; … … 1612 1612 auto inst = fwds.first; 1613 1613 do { 1614 // forward decl is stored * mutably* in map, can thus be updated1614 // forward decl is stored * mutably * in map, can thus be updated 1615 1615 inst->second->base = enumDecl; 1616 1616 } while ( ++inst != fwds.second ); 1617 1617 forwardEnums.erase( fwds.first, fwds.second ); 1618 1618 } 1619 1619 1620 1620 // ensure that enumerator initializers are properly set 1621 1621 for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) { 1622 1622 auto field = enumDecl->members[i].strict_as< ast::ObjectDecl >(); 1623 1623 if ( field->init ) { 1624 // need to resolve enumerator initializers early so that other passes that 1624 // need to resolve enumerator initializers early so that other passes that 1625 1625 // determine if an expression is constexpr have appropriate information 1626 1626 auto init = field->init.strict_as< ast::SingleInit >(); 1627 1628 enumDecl = ast::mutate_field_index( 1629 enumDecl, &ast::EnumDecl::members, i, 1630 ast::mutate_field( field, &ast::ObjectDecl::init, 1627 1628 enumDecl = ast::mutate_field_index( 1629 enumDecl, &ast::EnumDecl::members, i, 1630 ast::mutate_field( field, &ast::ObjectDecl::init, 1631 1631 ast::mutate_field( init, &ast::SingleInit::value, 1632 ResolvExpr::findSingleExpression( 1632 ResolvExpr::findSingleExpression( 1633 1633 init->value, new ast::BasicType{ ast::BasicType::SignedInt }, 1634 1634 symtab ) ) ) ); … … 1639 1639 } 1640 1640 1641 /// rename generic type parameters uniquely so that they do not conflict with user defined 1641 /// rename generic type parameters uniquely so that they do not conflict with user defined 1642 1642 /// function forall parameters, e.g. the T in Box and the T in f, below 1643 1643 /// forall(otype T) … … 1657 1657 const ast::TypeDecl * td = aggr->params[i]; 1658 1658 1659 aggr = ast::mutate_field_index( 1660 aggr, &AggrDecl::params, i, 1659 aggr = ast::mutate_field_index( 1660 aggr, &AggrDecl::params, i, 1661 1661 ast::mutate_field( td, &ast::TypeDecl::name, "__" + td->name + "_generic_" ) ); 1662 1662 } … … 1669 1669 1670 1670 void postvisit( const ast::StructDecl * structDecl ) { 1671 // visit struct members first so that the types of self-referencing members are 1671 // visit struct members first so that the types of self-referencing members are 1672 1672 // updated properly 1673 1673 if ( ! structDecl->body ) return; … … 1678 1678 auto inst = fwds.first; 1679 1679 do { 1680 // forward decl is stored * mutably* in map, can thus be updated1680 // forward decl is stored * mutably * in map, can thus be updated 1681 1681 inst->second->base = structDecl; 1682 1682 } while ( ++inst != fwds.second ); … … 1690 1690 1691 1691 void postvisit( const ast::UnionDecl * unionDecl ) { 1692 // visit union members first so that the types of self-referencing members are updated 1692 // visit union members first so that the types of self-referencing members are updated 1693 1693 // properly 1694 1694 if ( ! unionDecl->body ) return; … … 1699 1699 auto inst = fwds.first; 1700 1700 do { 1701 // forward decl is stored * mutably* in map, can thus be updated1701 // forward decl is stored * mutably * in map, can thus be updated 1702 1702 inst->second->base = unionDecl; 1703 1703 } while ( ++inst != fwds.second ); … … 1712 1712 "number of parameters: %zd", traitDecl->params.size() ); 1713 1713 1714 traitDecl = ast::mutate_field_index( 1715 traitDecl, &ast::TraitDecl::params, 0, 1716 ast::mutate_field( 1714 traitDecl = ast::mutate_field_index( 1715 traitDecl, &ast::TraitDecl::params, 0, 1716 ast::mutate_field( 1717 1717 traitDecl->params.front().get(), &ast::TypeDecl::sized, true ) ); 1718 1718 } … … 1737 1737 traitDecl = mut; 1738 1738 } 1739 1739 1740 1740 return traitDecl; 1741 1741 } 1742 1742 }; 1743 1743 1744 /// Replaces array and function types in forall lists by appropriate pointer type and assigns 1744 /// Replaces array and function types in forall lists by appropriate pointer type and assigns 1745 1745 /// each object and function declaration a unique ID 1746 1746 class ForallPointerDecay_new { … … 1751 1751 const ast::ObjectDecl * previsit( const ast::ObjectDecl * obj ) { 1752 1752 // ensure that operator names only apply to functions or function pointers 1753 if ( 1754 CodeGen::isOperator( obj->name ) 1753 if ( 1754 CodeGen::isOperator( obj->name ) 1755 1755 && ! dynamic_cast< const ast::FunctionType * >( obj->type->stripDeclarator() ) 1756 1756 ) { … … 1776 1776 /// Fix up assertions -- flattens assertion lists, removing all trait instances 1777 1777 template< typename node_t, typename parent_t > 1778 static const node_t * forallFixer( 1779 const CodeLocation & loc, const node_t * node, 1778 static const node_t * forallFixer( 1779 const CodeLocation & loc, const node_t * node, 1780 1780 ast::ParameterizedType::ForallList parent_t::* forallField 1781 1781 ) { 1782 for ( unsigned i = 0; i < (node->* forallField).size(); ++i ) {1783 const ast::TypeDecl * type = (node->* forallField)[i];1782 for ( unsigned i = 0; i < (node->* forallField).size(); ++i ) { 1783 const ast::TypeDecl * type = (node->* forallField)[i]; 1784 1784 if ( type->assertions.empty() ) continue; 1785 1785 … … 1789 1789 // expand trait instances into their members 1790 1790 for ( const ast::DeclWithType * assn : type->assertions ) { 1791 auto traitInst = 1792 dynamic_cast< const ast::TraitInstType * >( assn->get_type() ); 1791 auto traitInst = 1792 dynamic_cast< const ast::TraitInstType * >( assn->get_type() ); 1793 1793 if ( traitInst ) { 1794 1794 // expand trait instance to all its members … … 1831 1831 } // anonymous namespace 1832 1832 1833 const ast::Type * validateType( 1833 const ast::Type * validateType( 1834 1834 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) { 1835 1835 ast::Pass< EnumAndPointerDecay_new > epc;
Note:
See TracChangeset
for help on using the changeset viewer.