Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/DeclarationNode.cc

    r2583407 ra3525c4  
    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         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.
    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 } 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 
    598504DeclarationNode * DeclarationNode::addTypedef() {
    599505        TypeData * newtype = new TypeData( TypeData::Symbolic );
     
    601507        newtype->symbolic.isTypedef = true;
    602508        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;
    619512}
    620513
     
    818711}
    819712
     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
    820782// Get the non-anonymous name of the instance type of the declaration,
    821783// if one exists.
     
    838800                try {
    839801                        bool extracted_named = false;
     802                        ast::UnionDecl * unionDecl = nullptr;
    840803
    841804                        if ( DeclarationNode * extr = cur->extractAggregate() ) {
    842805                                assert( cur->type );
     806                                nameTypedefedDecl( extr, cur );
    843807
    844808                                if ( ast::Decl * decl = extr->build() ) {
     809                                        // Remember the declaration if it is a union aggregate ?
     810                                        unionDecl = dynamic_cast<ast::UnionDecl *>( decl );
     811
    845812                                        *out++ = decl;
    846813
     
    861828
    862829                        if ( ast::Decl * decl = cur->build() ) {
     830                                moveUnionAttribute( decl, unionDecl );
     831
    863832                                if ( "" == decl->name && !cur->get_inLine() ) {
    864833                                        // Don't include anonymous declaration for named aggregates,
Note: See TracChangeset for help on using the changeset viewer.