Changeset 2583407


Ignore:
Timestamp:
Mar 15, 2024, 2:18:42 PM (9 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
3ad5c50
Parents:
223b631
Message:

Handle typedef wrapped declarations before buildList in addTypedef. The extractAggregate code is still used in other cases. There is a small change in behaviour, a typedef wrapping a enum declaration will have the qualifiers on its local copy cleared. This may be the intended behaviour, it is how all other aggregates are handled.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/DeclarationNode.cc

    r223b631 r2583407  
    502502}
    503503
     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.
     512static 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.
     532static 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.
     567static 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
    504598DeclarationNode * DeclarationNode::addTypedef() {
    505599        TypeData * newtype = new TypeData( TypeData::Symbolic );
     
    507601        newtype->symbolic.isTypedef = true;
    508602        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        }
    512619}
    513620
     
    711818}
    712819
    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 
    782820// Get the non-anonymous name of the instance type of the declaration,
    783821// if one exists.
     
    800838                try {
    801839                        bool extracted_named = false;
    802                         ast::UnionDecl * unionDecl = nullptr;
    803840
    804841                        if ( DeclarationNode * extr = cur->extractAggregate() ) {
    805842                                assert( cur->type );
    806                                 nameTypedefedDecl( extr, cur );
    807843
    808844                                if ( ast::Decl * decl = extr->build() ) {
    809                                         // Remember the declaration if it is a union aggregate ?
    810                                         unionDecl = dynamic_cast<ast::UnionDecl *>( decl );
    811 
    812845                                        *out++ = decl;
    813846
     
    828861
    829862                        if ( ast::Decl * decl = cur->build() ) {
    830                                 moveUnionAttribute( decl, unionDecl );
    831 
    832863                                if ( "" == decl->name && !cur->get_inLine() ) {
    833864                                        // Don't include anonymous declaration for named aggregates,
Note: See TracChangeset for help on using the changeset viewer.