Changes in src/Parser/DeclarationNode.cc [a3525c4:bf050c5]
- File:
-
- 1 edited
-
src/Parser/DeclarationNode.cc (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Parser/DeclarationNode.cc
ra3525c4 rbf050c5 185 185 newnode->type->aggregate.fields = fields; 186 186 newnode->type->aggregate.body = body; 187 newnode->type->aggregate.tagged = false;188 newnode->type->aggregate.parent = nullptr;189 187 return newnode; 190 188 } // DeclarationNode::newAggregate … … 199 197 newnode->type->enumeration.typed = typed; 200 198 newnode->type->enumeration.hiding = hiding; 201 if ( base && base->type ) { 199 if ( base ) { 200 assert( typed ); 201 assert( base->type ); 202 202 newnode->type->base = base->type; 203 base->type = nullptr; 204 delete base; 203 205 } // if 204 206 … … 220 222 221 223 DeclarationNode * DeclarationNode::newEnumValueGeneric( const string * name, InitializerNode * init ) { 222 if ( init ) { 223 if ( init->get_expression() ) { 224 return newEnumConstant( name, init->get_expression() ); 225 } else { 226 DeclarationNode * newnode = newName( name ); 227 newnode->initializer = init; 228 return newnode; 229 } // if 224 if ( nullptr == init ) { 225 return newName( name ); 226 } else if ( init->get_expression() ) { 227 return newEnumConstant( name, init->get_expression() ); 230 228 } else { 231 return newName( name ); 229 DeclarationNode * newnode = newName( name ); 230 newnode->initializer = init; 231 return newnode; 232 232 } // if 233 233 } // DeclarationNode::newEnumValueGeneric … … 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 swap( newaggr, oldaggr ); 552 553 newtype->base = olddecl->type; 554 olddecl->type = newtype; 555 DeclarationNode * newdecl = new DeclarationNode; 556 newdecl->type = newaggr; 557 newdecl->next = olddecl; 558 559 moveUnionAttribute( olddecl, newdecl ); 560 561 return newdecl; 562 } 563 564 // Helper for addTypedef, handles the case where the typedef wraps an 565 // enumeration declaration (not a type), returns a chain of nodes. 566 static DeclarationNode * addTypedefEnum( 567 DeclarationNode * olddecl, TypeData * newtype ) { 568 TypeData *& oldenum = olddecl->type->aggInst.aggregate; 569 570 // Handle anonymous enumeration: typedef enum { A, B, C } foo 571 // Give the typedefed type a consistent name across translation units. 572 if ( oldenum->enumeration.anon ) { 573 delete oldenum->enumeration.name; 574 oldenum->enumeration.name = new string( "__anonymous_" + *olddecl->name ); 575 oldenum->enumeration.anon = false; 576 oldenum->qualifiers.reset(); 577 } 578 579 // Replace the wrapped TypeData with a forward declaration. 580 TypeData * newenum = new TypeData( TypeData::Enum ); 581 newenum->enumeration.name = oldenum->enumeration.name ? new string( *oldenum->enumeration.name ) : nullptr; 582 newenum->enumeration.body = false; 583 newenum->enumeration.anon = oldenum->enumeration.anon; 584 newenum->enumeration.typed = oldenum->enumeration.typed; 585 newenum->enumeration.hiding = oldenum->enumeration.hiding; 586 swap( newenum, oldenum ); 587 588 newtype->base = olddecl->type; 589 olddecl->type = newtype; 590 DeclarationNode * newdecl = new DeclarationNode; 591 newdecl->type = newenum; 592 newdecl->next = olddecl; 593 594 return newdecl; 595 } 596 597 // Wrap the declaration in a typedef. It actually does that by modifying the 598 // existing declaration, and may split it into two declarations. 599 // This only happens if the wrapped type is actually a declaration of a SUE 600 // type. If it does, the DeclarationNode for the SUE declaration is the node 601 // returned, make sure later transformations are applied to the right node. 504 602 DeclarationNode * DeclarationNode::addTypedef() { 505 603 TypeData * newtype = new TypeData( TypeData::Symbolic ); … … 507 605 newtype->symbolic.isTypedef = true; 508 606 newtype->symbolic.name = name ? new string( *name ) : nullptr; 509 newtype->base = type; 510 type = newtype; 511 return this; 607 // If this typedef is wrapping an aggregate, separate them out. 608 if ( TypeData::AggregateInst == type->kind 609 && TypeData::Aggregate == type->aggInst.aggregate->kind 610 && type->aggInst.aggregate->aggregate.body ) { 611 return addTypedefAggr( this, newtype ); 612 // If this typedef is wrapping an enumeration, separate them out. 613 } else if ( TypeData::AggregateInst == type->kind 614 && TypeData::Enum == type->aggInst.aggregate->kind 615 && type->aggInst.aggregate->enumeration.body ) { 616 return addTypedefEnum( this, newtype ); 617 // There is no internal declaration, just a type. 618 } else { 619 newtype->base = type; 620 type = newtype; 621 return this; 622 } 512 623 } 513 624 … … 711 822 } 712 823 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 824 // Get the non-anonymous name of the instance type of the declaration, 783 825 // if one exists. … … 800 842 try { 801 843 bool extracted_named = false; 802 ast::UnionDecl * unionDecl = nullptr;803 844 804 845 if ( DeclarationNode * extr = cur->extractAggregate() ) { 805 846 assert( cur->type ); 806 nameTypedefedDecl( extr, cur );807 847 808 848 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 849 *out++ = decl; 813 850 … … 828 865 829 866 if ( ast::Decl * decl = cur->build() ) { 830 moveUnionAttribute( decl, unionDecl );831 832 867 if ( "" == decl->name && !cur->get_inLine() ) { 833 868 // Don't include anonymous declaration for named aggregates,
Note:
See TracChangeset
for help on using the changeset viewer.