Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/DeclarationNode.cc

    rbf050c5 ra3525c4  
    185185        newnode->type->aggregate.fields = fields;
    186186        newnode->type->aggregate.body = body;
     187        newnode->type->aggregate.tagged = false;
     188        newnode->type->aggregate.parent = nullptr;
    187189        return newnode;
    188190} // DeclarationNode::newAggregate
     
    197199        newnode->type->enumeration.typed = typed;
    198200        newnode->type->enumeration.hiding = hiding;
    199         if ( base ) {
    200                 assert( typed );
    201                 assert( base->type );
     201        if ( base && base->type )  {
    202202                newnode->type->base = base->type;
    203                 base->type = nullptr;
    204                 delete base;
    205203        } // if
    206204
     
    222220
    223221DeclarationNode * DeclarationNode::newEnumValueGeneric( const string * name, InitializerNode * init ) {
    224         if ( nullptr == 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
     230        } else {
    225231                return newName( name );
    226         } else if ( init->get_expression() ) {
    227                 return newEnumConstant( name, init->get_expression() );
    228         } else {
    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.
    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.
    602504DeclarationNode * DeclarationNode::addTypedef() {
    603505        TypeData * newtype = new TypeData( TypeData::Symbolic );
     
    605507        newtype->symbolic.isTypedef = true;
    606508        newtype->symbolic.name = name ? new string( *name ) : nullptr;
    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         }
     509        newtype->base = type;
     510        type = newtype;
     511        return this;
    623512}
    624513
     
    822711}
    823712
     713// If a typedef wraps an anonymous declaration, name the inner declaration so it has a consistent name across
     714// translation units.
     715static 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.
     759static 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
    824782// Get the non-anonymous name of the instance type of the declaration,
    825783// if one exists.
     
    842800                try {
    843801                        bool extracted_named = false;
     802                        ast::UnionDecl * unionDecl = nullptr;
    844803
    845804                        if ( DeclarationNode * extr = cur->extractAggregate() ) {
    846805                                assert( cur->type );
     806                                nameTypedefedDecl( extr, cur );
    847807
    848808                                if ( ast::Decl * decl = extr->build() ) {
     809                                        // Remember the declaration if it is a union aggregate ?
     810                                        unionDecl = dynamic_cast<ast::UnionDecl *>( decl );
     811
    849812                                        *out++ = decl;
    850813
     
    865828
    866829                        if ( ast::Decl * decl = cur->build() ) {
     830                                moveUnionAttribute( decl, unionDecl );
     831
    867832                                if ( "" == decl->name && !cur->get_inLine() ) {
    868833                                        // Don't include anonymous declaration for named aggregates,
Note: See TracChangeset for help on using the changeset viewer.