Changes in src/Parser/DeclarationNode.cc [2583407:a3525c4]
- File:
-
- 1 edited
-
src/Parser/DeclarationNode.cc (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Parser/DeclarationNode.cc
r2583407 ra3525c4 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 are509 // aligned. However, the attribute transparent_union must be moved from the typedef_name to510 // alias union U. Currently, this is the only know attribute that must be moved from typedef to511 // 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 an531 // 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; } foo537 // 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 an566 // 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 } foo572 // 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 598 504 DeclarationNode * DeclarationNode::addTypedef() { 599 505 TypeData * newtype = new TypeData( TypeData::Symbolic ); … … 601 507 newtype->symbolic.isTypedef = true; 602 508 newtype->symbolic.name = name ? new string( *name ) : nullptr; 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 } 509 newtype->base = type; 510 type = newtype; 511 return this; 619 512 } 620 513 … … 818 711 } 819 712 713 // If a typedef wraps an anonymous declaration, name the inner declaration so it has a consistent name across 714 // 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; } foo 729 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 } foo 739 } 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 are 756 // aligned. However, the attribute transparent_union must be moved from the typedef_name to 757 // alias union U. Currently, this is the only know attribute that must be moved from typedef to 758 // 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 820 782 // Get the non-anonymous name of the instance type of the declaration, 821 783 // if one exists. … … 838 800 try { 839 801 bool extracted_named = false; 802 ast::UnionDecl * unionDecl = nullptr; 840 803 841 804 if ( DeclarationNode * extr = cur->extractAggregate() ) { 842 805 assert( cur->type ); 806 nameTypedefedDecl( extr, cur ); 843 807 844 808 if ( ast::Decl * decl = extr->build() ) { 809 // Remember the declaration if it is a union aggregate ? 810 unionDecl = dynamic_cast<ast::UnionDecl *>( decl ); 811 845 812 *out++ = decl; 846 813 … … 861 828 862 829 if ( ast::Decl * decl = cur->build() ) { 830 moveUnionAttribute( decl, unionDecl ); 831 863 832 if ( "" == decl->name && !cur->get_inLine() ) { 864 833 // Don't include anonymous declaration for named aggregates,
Note:
See TracChangeset
for help on using the changeset viewer.