Changeset 2583407
- Timestamp:
- Mar 15, 2024, 2:18:42 PM (9 months ago)
- Branches:
- master
- Children:
- 3ad5c50
- Parents:
- 223b631
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Parser/DeclarationNode.cc
r223b631 r2583407 502 502 } 503 503 504 // This code handles a special issue with the attribute transparent_union. 505 // 506 // typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union )) 507 // 508 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are 509 // aligned. However, the attribute transparent_union must be moved from the typedef_name to 510 // alias union U. Currently, this is the only know attribute that must be moved from typedef to 511 // alias. 512 static void moveUnionAttribute( DeclarationNode * decl, DeclarationNode * unionDecl ) { 513 assert( decl->type->kind == TypeData::Symbolic ); 514 assert( decl->type->symbolic.isTypedef ); 515 assert( unionDecl->type->kind == TypeData::Aggregate ); 516 517 if ( unionDecl->type->aggregate.kind != ast::AggregateDecl::Union ) return; 518 519 // Ignore the Aggregate_t::attributes. Why did we add that before the rework? 520 for ( auto attr = decl->attributes.begin() ; attr != decl->attributes.end() ; ) { 521 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) { 522 unionDecl->attributes.emplace_back( attr->release() ); 523 attr = decl->attributes.erase( attr ); 524 } else { 525 ++attr; 526 } 527 } 528 } 529 530 // Helper for addTypedef, handles the case where the typedef wraps an 531 // aggregate declaration (not a type), returns a chain of nodes. 532 static DeclarationNode * addTypedefAggr( 533 DeclarationNode * olddecl, TypeData * newtype ) { 534 TypeData *& oldaggr = olddecl->type->aggInst.aggregate; 535 536 // Handle anonymous aggregates: typedef struct { int i; } foo 537 // Give the typedefed type a consistent name across translation units. 538 if ( oldaggr->aggregate.anon ) { 539 delete oldaggr->aggregate.name; 540 oldaggr->aggregate.name = new string( "__anonymous_" + *olddecl->name ); 541 oldaggr->aggregate.anon = false; 542 oldaggr->qualifiers.reset(); 543 } 544 545 // Replace the wrapped TypeData with a forward declaration. 546 TypeData * newaggr = new TypeData( TypeData::Aggregate ); 547 newaggr->aggregate.kind = oldaggr->aggregate.kind; 548 newaggr->aggregate.name = oldaggr->aggregate.name ? new string( *oldaggr->aggregate.name ) : nullptr; 549 newaggr->aggregate.body = false; 550 newaggr->aggregate.anon = oldaggr->aggregate.anon; 551 newaggr->aggregate.tagged = oldaggr->aggregate.tagged; 552 swap( newaggr, oldaggr ); 553 554 newtype->base = olddecl->type; 555 olddecl->type = newtype; 556 DeclarationNode * newdecl = new DeclarationNode; 557 newdecl->type = newaggr; 558 newdecl->next = olddecl; 559 560 moveUnionAttribute( olddecl, newdecl ); 561 562 return newdecl; 563 } 564 565 // Helper for addTypedef, handles the case where the typedef wraps an 566 // enumeration declaration (not a type), returns a chain of nodes. 567 static DeclarationNode * addTypedefEnum( 568 DeclarationNode * olddecl, TypeData * newtype ) { 569 TypeData *& oldenum = olddecl->type->aggInst.aggregate; 570 571 // Handle anonymous enumeration: typedef enum { A, B, C } foo 572 // Give the typedefed type a consistent name across translation units. 573 if ( oldenum->enumeration.anon ) { 574 delete oldenum->enumeration.name; 575 oldenum->enumeration.name = new string( "__anonymous_" + *olddecl->name ); 576 oldenum->enumeration.anon = false; 577 oldenum->qualifiers.reset(); 578 } 579 580 // Replace the wrapped TypeData with a forward declaration. 581 TypeData * newenum = new TypeData( TypeData::Enum ); 582 newenum->enumeration.name = oldenum->enumeration.name ? new string( *oldenum->enumeration.name ) : nullptr; 583 newenum->enumeration.body = false; 584 newenum->enumeration.anon = oldenum->enumeration.anon; 585 newenum->enumeration.typed = oldenum->enumeration.typed; 586 newenum->enumeration.hiding = oldenum->enumeration.hiding; 587 swap( newenum, oldenum ); 588 589 newtype->base = olddecl->type; 590 olddecl->type = newtype; 591 DeclarationNode * newdecl = new DeclarationNode; 592 newdecl->type = newenum; 593 newdecl->next = olddecl; 594 595 return newdecl; 596 } 597 504 598 DeclarationNode * DeclarationNode::addTypedef() { 505 599 TypeData * newtype = new TypeData( TypeData::Symbolic ); … … 507 601 newtype->symbolic.isTypedef = true; 508 602 newtype->symbolic.name = name ? new string( *name ) : nullptr; 509 newtype->base = type; 510 type = newtype; 511 return this; 603 // If this typedef is wrapping an aggregate, separate them out. 604 if ( TypeData::AggregateInst == type->kind 605 && TypeData::Aggregate == type->aggInst.aggregate->kind 606 && type->aggInst.aggregate->aggregate.body ) { 607 return addTypedefAggr( this, newtype ); 608 // If this typedef is wrapping an enumeration, separate them out. 609 } else if ( TypeData::AggregateInst == type->kind 610 && TypeData::Enum == type->aggInst.aggregate->kind 611 && type->aggInst.aggregate->enumeration.body ) { 612 return addTypedefEnum( this, newtype ); 613 // There is no internal declaration, just a type. 614 } else { 615 newtype->base = type; 616 type = newtype; 617 return this; 618 } 512 619 } 513 620 … … 711 818 } 712 819 713 // If a typedef wraps an anonymous declaration, name the inner declaration so it has a consistent name across714 // translation units.715 static void nameTypedefedDecl(716 DeclarationNode * innerDecl,717 const DeclarationNode * outerDecl ) {718 TypeData * outer = outerDecl->type;719 assert( outer );720 // First make sure this is a typedef:721 if ( outer->kind != TypeData::Symbolic || !outer->symbolic.isTypedef ) {722 return;723 }724 TypeData * inner = innerDecl->type;725 assert( inner );726 // Always clear any CVs associated with the aggregate:727 inner->qualifiers.reset();728 // Handle anonymous aggregates: typedef struct { int i; } foo729 if ( inner->kind == TypeData::Aggregate && inner->aggregate.anon ) {730 delete inner->aggregate.name;731 inner->aggregate.name = new string( "__anonymous_" + *outerDecl->name );732 inner->aggregate.anon = false;733 assert( outer->base );734 delete outer->base->aggInst.aggregate->aggregate.name;735 outer->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *outerDecl->name );736 outer->base->aggInst.aggregate->aggregate.anon = false;737 outer->base->aggInst.aggregate->qualifiers.reset();738 // Handle anonymous enumeration: typedef enum { A, B, C } foo739 } else if ( inner->kind == TypeData::Enum && inner->enumeration.anon ) {740 delete inner->enumeration.name;741 inner->enumeration.name = new string( "__anonymous_" + *outerDecl->name );742 inner->enumeration.anon = false;743 assert( outer->base );744 delete outer->base->aggInst.aggregate->enumeration.name;745 outer->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *outerDecl->name );746 outer->base->aggInst.aggregate->enumeration.anon = false;747 // No qualifiers.reset() here.748 }749 }750 751 // This code handles a special issue with the attribute transparent_union.752 //753 // typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union ))754 //755 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are756 // aligned. However, the attribute transparent_union must be moved from the typedef_name to757 // alias union U. Currently, this is the only know attribute that must be moved from typedef to758 // alias.759 static void moveUnionAttribute( ast::Decl * decl, ast::UnionDecl * unionDecl ) {760 if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) {761 // Is the typedef alias a union aggregate?762 if ( nullptr == unionDecl ) return;763 764 // If typedef is an alias for a union, then its alias type was hoisted above and remembered.765 if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) {766 auto instType = ast::mutate( unionInstType );767 // Remove all transparent_union attributes from typedef and move to alias union.768 for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) {769 assert( *attr );770 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) {771 unionDecl->attributes.emplace_back( attr->release() );772 attr = instType->attributes.erase( attr );773 } else {774 attr++;775 }776 }777 typedefDecl->base = instType;778 }779 }780 }781 782 820 // Get the non-anonymous name of the instance type of the declaration, 783 821 // if one exists. … … 800 838 try { 801 839 bool extracted_named = false; 802 ast::UnionDecl * unionDecl = nullptr;803 840 804 841 if ( DeclarationNode * extr = cur->extractAggregate() ) { 805 842 assert( cur->type ); 806 nameTypedefedDecl( extr, cur );807 843 808 844 if ( ast::Decl * decl = extr->build() ) { 809 // Remember the declaration if it is a union aggregate ?810 unionDecl = dynamic_cast<ast::UnionDecl *>( decl );811 812 845 *out++ = decl; 813 846 … … 828 861 829 862 if ( ast::Decl * decl = cur->build() ) { 830 moveUnionAttribute( decl, unionDecl );831 832 863 if ( "" == decl->name && !cur->get_inLine() ) { 833 864 // Don't include anonymous declaration for named aggregates,
Note: See TracChangeset
for help on using the changeset viewer.