Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/DeclarationNode.cc

    ra3525c4 rbf050c5  
    185185        newnode->type->aggregate.fields = fields;
    186186        newnode->type->aggregate.body = body;
    187         newnode->type->aggregate.tagged = false;
    188         newnode->type->aggregate.parent = nullptr;
    189187        return newnode;
    190188} // DeclarationNode::newAggregate
     
    199197        newnode->type->enumeration.typed = typed;
    200198        newnode->type->enumeration.hiding = hiding;
    201         if ( base && base->type )  {
     199        if ( base ) {
     200                assert( typed );
     201                assert( base->type );
    202202                newnode->type->base = base->type;
     203                base->type = nullptr;
     204                delete base;
    203205        } // if
    204206
     
    220222
    221223DeclarationNode * 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() );
    230228        } else {
    231                 return newName( name );
     229                DeclarationNode * newnode = newName( name );
     230                newnode->initializer = init;
     231                return newnode;
    232232        } // if
    233233} // DeclarationNode::newEnumValueGeneric
     
    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        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.
     566static 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.
    504602DeclarationNode * DeclarationNode::addTypedef() {
    505603        TypeData * newtype = new TypeData( TypeData::Symbolic );
     
    507605        newtype->symbolic.isTypedef = true;
    508606        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        }
    512623}
    513624
     
    711822}
    712823
    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 
    782824// Get the non-anonymous name of the instance type of the declaration,
    783825// if one exists.
     
    800842                try {
    801843                        bool extracted_named = false;
    802                         ast::UnionDecl * unionDecl = nullptr;
    803844
    804845                        if ( DeclarationNode * extr = cur->extractAggregate() ) {
    805846                                assert( cur->type );
    806                                 nameTypedefedDecl( extr, cur );
    807847
    808848                                if ( ast::Decl * decl = extr->build() ) {
    809                                         // Remember the declaration if it is a union aggregate ?
    810                                         unionDecl = dynamic_cast<ast::UnionDecl *>( decl );
    811 
    812849                                        *out++ = decl;
    813850
     
    828865
    829866                        if ( ast::Decl * decl = cur->build() ) {
    830                                 moveUnionAttribute( decl, unionDecl );
    831 
    832867                                if ( "" == decl->name && !cur->get_inLine() ) {
    833868                                        // Don't include anonymous declaration for named aggregates,
Note: See TracChangeset for help on using the changeset viewer.