Changeset 45e753c


Ignore:
Timestamp:
Apr 20, 2023, 11:58:06 AM (19 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, ast-experimental, master
Children:
699a97d
Parents:
028e512
Message:

Clean-up in DeclarationNode?.cc. Made all buildList loops the same. The ast::Decl function also got some restructuring, mostly moving code around and into helpers.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Parser/DeclarationNode.cc

    r028e512 r45e753c  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Apr  4 10:28:00 2023
    13 // Update Count     : 1392
     12// Last Modified On : Thr Apr 20 11:46:00 2023
     13// Update Count     : 1393
    1414//
    1515
     
    10031003}
    10041004
     1005// If a typedef wraps an anonymous declaration, name the inner declaration
     1006// so it has a consistent name across translation units.
     1007static void nameTypedefedDecl(
     1008                DeclarationNode * innerDecl,
     1009                const DeclarationNode * outerDecl ) {
     1010        TypeData * outer = outerDecl->type;
     1011        assert( outer );
     1012        // First make sure this is a typedef:
     1013        if ( outer->kind != TypeData::Symbolic || !outer->symbolic.isTypedef ) {
     1014                return;
     1015        }
     1016        TypeData * inner = innerDecl->type;
     1017        assert( inner );
     1018        // Always clear any CVs associated with the aggregate:
     1019        inner->qualifiers.reset();
     1020        // Handle anonymous aggregates: typedef struct { int i; } foo
     1021        if ( inner->kind == TypeData::Aggregate && inner->aggregate.anon ) {
     1022                delete inner->aggregate.name;
     1023                inner->aggregate.name = new string( "__anonymous_" + *outerDecl->name );
     1024                inner->aggregate.anon = false;
     1025                assert( outer->base );
     1026                delete outer->base->aggInst.aggregate->aggregate.name;
     1027                outer->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *outerDecl->name );
     1028                outer->base->aggInst.aggregate->aggregate.anon = false;
     1029                outer->base->aggInst.aggregate->qualifiers.reset();
     1030        // Handle anonymous enumeration: typedef enum { A, B, C } foo
     1031        } else if ( inner->kind == TypeData::Enum && inner->enumeration.anon ) {
     1032                delete inner->enumeration.name;
     1033                inner->enumeration.name = new string( "__anonymous_" + *outerDecl->name );
     1034                inner->enumeration.anon = false;
     1035                assert( outer->base );
     1036                delete outer->base->aggInst.aggregate->enumeration.name;
     1037                outer->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *outerDecl->name );
     1038                outer->base->aggInst.aggregate->enumeration.anon = false;
     1039                // No qualifiers.reset() here.
     1040        }
     1041}
     1042
     1043// This code handles a special issue with the attribute transparent_union.
     1044//
     1045//    typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union ))
     1046//
     1047// Here the attribute aligned goes with the typedef_name, so variables declared of this type are
     1048// aligned.  However, the attribute transparent_union must be moved from the typedef_name to
     1049// alias union U.  Currently, this is the only know attribute that must be moved from typedef to
     1050// alias.
     1051static void moveUnionAttribute( ast::Decl * decl, ast::UnionDecl * unionDecl ) {
     1052        if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) {
     1053                // Is the typedef alias a union aggregate?
     1054                if ( nullptr == unionDecl ) return;
     1055
     1056                // If typedef is an alias for a union, then its alias type was hoisted above and remembered.
     1057                if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) {
     1058                        auto instType = ast::mutate( unionInstType );
     1059                        // Remove all transparent_union attributes from typedef and move to alias union.
     1060                        for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) {
     1061                                assert( *attr );
     1062                                if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) {
     1063                                        unionDecl->attributes.emplace_back( attr->release() );
     1064                                        attr = instType->attributes.erase( attr );
     1065                                } else {
     1066                                        attr++;
     1067                                }
     1068                        }
     1069                        typedefDecl->base = instType;
     1070                }
     1071        }
     1072}
     1073
     1074// Get the non-anonymous name of the instance type of the declaration,
     1075// if one exists.
     1076static const std::string * getInstTypeOfName( ast::Decl * decl ) {
     1077        if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {
     1078                if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) {
     1079                        if ( aggr->name.find("anonymous") == std::string::npos ) {
     1080                                return &aggr->name;
     1081                        }
     1082                }
     1083        }
     1084        return nullptr;
     1085}
     1086
    10051087void buildList( DeclarationNode * firstNode,
    10061088                std::vector<ast::ptr<ast::Decl>> & outputList ) {
     
    10081090        std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList );
    10091091
    1010         for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
     1092        for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
    10111093                try {
    1012                         bool extracted = false, anon = false;
    1013                         ast::AggregateDecl * unionDecl = nullptr;
     1094                        bool extracted_named = false;
     1095                        ast::UnionDecl * unionDecl = nullptr;
    10141096
    10151097                        if ( DeclarationNode * extr = cur->extractAggregate() ) {
    1016                                 // Handle the case where a SUE declaration is contained within an object or type declaration.
    1017 
    10181098                                assert( cur->type );
    1019                                 // Replace anonymous SUE name with typedef name to prevent anonymous naming problems across translation units.
    1020                                 if ( cur->type->kind == TypeData::Symbolic && cur->type->symbolic.isTypedef ) {
    1021                                         assert( extr->type );
    1022                                         // Handle anonymous aggregates: typedef struct { int i; } foo
    1023                                         extr->type->qualifiers.reset();         // clear any CVs associated with the aggregate
    1024                                         if ( extr->type->kind == TypeData::Aggregate && extr->type->aggregate.anon ) {
    1025                                                 delete extr->type->aggregate.name;
    1026                                                 extr->type->aggregate.name = new string( "__anonymous_" + *cur->name );
    1027                                                 extr->type->aggregate.anon = false;
    1028                                                 assert( cur->type->base );
    1029                                                 if ( cur->type->base ) {
    1030                                                         delete cur->type->base->aggInst.aggregate->aggregate.name;
    1031                                                         cur->type->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *cur->name );
    1032                                                         cur->type->base->aggInst.aggregate->aggregate.anon = false;
    1033                                                         cur->type->base->aggInst.aggregate->qualifiers.reset();
    1034                                                 } // if
    1035                                         } // if
    1036                                         // Handle anonymous enumeration: typedef enum { A, B, C } foo
    1037                                         if ( extr->type->kind == TypeData::Enum && extr->type->enumeration.anon ) {
    1038                                                 delete extr->type->enumeration.name;
    1039                                                 extr->type->enumeration.name = new string( "__anonymous_" + *cur->name );
    1040                                                 extr->type->enumeration.anon = false;
    1041                                                 assert( cur->type->base );
    1042                                                 if ( cur->type->base ) {
    1043                                                         delete cur->type->base->aggInst.aggregate->enumeration.name;
    1044                                                         cur->type->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *cur->name );
    1045                                                         cur->type->base->aggInst.aggregate->enumeration.anon = false;
    1046                                                 } // if
    1047                                         } // if
    1048                                 } // if
    1049 
    1050                                 ast::Decl * decl = extr->build();
    1051                                 if ( decl ) {
     1099                                nameTypedefedDecl( extr, cur );
     1100
     1101                                if ( ast::Decl * decl = extr->build() ) {
    10521102                                        // Remember the declaration if it is a union aggregate ?
    10531103                                        unionDecl = dynamic_cast<ast::UnionDecl *>( decl );
     
    10561106
    10571107                                        // need to remember the cases where a declaration contains an anonymous aggregate definition
    1058                                         extracted = true;
    10591108                                        assert( extr->type );
    10601109                                        if ( extr->type->kind == TypeData::Aggregate ) {
    10611110                                                // typedef struct { int A } B is the only case?
    1062                                                 anon = extr->type->aggregate.anon;
     1111                                                extracted_named = !extr->type->aggregate.anon;
    10631112                                        } else if ( extr->type->kind == TypeData::Enum ) {
    10641113                                                // typedef enum { A } B is the only case?
    1065                                                 anon = extr->type->enumeration.anon;
     1114                                                extracted_named = !extr->type->enumeration.anon;
     1115                                        } else {
     1116                                                extracted_named = true;
    10661117                                        }
    10671118                                } // if
     
    10691120                        } // if
    10701121
    1071                         ast::Decl * decl = cur->build();
    1072                         if ( decl ) {
    1073                                 if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) {
    1074                                         if ( unionDecl ) {                                      // is the typedef alias a union aggregate ?
    1075                                                 // This code handles a special issue with the attribute transparent_union.
    1076                                                 //
    1077                                                 //    typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union ))
    1078                                                 //
    1079                                                 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are
    1080                                                 // aligned.  However, the attribute transparent_union must be moved from the typedef_name to
    1081                                                 // alias union U.  Currently, this is the only know attribute that must be moved from typedef to
    1082                                                 // alias.
    1083 
    1084                                                 // If typedef is an alias for a union, then its alias type was hoisted above and remembered.
    1085                                                 if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) {
    1086                                                         auto instType = ast::mutate( unionInstType );
    1087                                                         // Remove all transparent_union attributes from typedef and move to alias union.
    1088                                                         for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) { // forward order
    1089                                                                 assert( *attr );
    1090                                                                 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) {
    1091                                                                         unionDecl->attributes.emplace_back( attr->release() );
    1092                                                                         attr = instType->attributes.erase( attr );
    1093                                                                 } else {
    1094                                                                         attr++;
    1095                                                                 } // if
    1096                                                         } // for
    1097                                                         typedefDecl->base = instType;
    1098                                                 } // if
    1099                                         } // if
     1122                        if ( ast::Decl * decl = cur->build() ) {
     1123                                moveUnionAttribute( decl, unionDecl );
     1124
     1125                                if ( "" == decl->name && !cur->get_inLine() ) {
     1126                                        // Don't include anonymous declaration for named aggregates,
     1127                                        // but do include them for anonymous aggregates, e.g.:
     1128                                        // struct S {
     1129                                        //   struct T { int x; }; // no anonymous member
     1130                                        //   struct { int y; };   // anonymous member
     1131                                        //   struct T;            // anonymous member
     1132                                        // };
     1133                                        if ( extracted_named ) {
     1134                                                continue;
     1135                                        }
     1136
     1137                                        if ( auto name = getInstTypeOfName( decl ) ) {
     1138                                                // Temporary: warn about anonymous member declarations of named types, since
     1139                                                // this conflicts with the syntax for the forward declaration of an anonymous type.
     1140                                                SemanticWarning( cur->location, Warning::AggrForwardDecl, name->c_str() );
     1141                                        }
    11001142                                } // if
    1101 
    1102                                 // don't include anonymous declaration for named aggregates, but do include them for anonymous aggregates, e.g.:
    1103                                 // struct S {
    1104                                 //   struct T { int x; }; // no anonymous member
    1105                                 //   struct { int y; };   // anonymous member
    1106                                 //   struct T;            // anonymous member
    1107                                 // };
    1108                                 if ( ! (extracted && decl->name == "" && ! anon && ! cur->get_inLine()) ) {
    1109                                         if ( decl->name == "" ) {
    1110                                                 if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {
    1111                                                         if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) {
    1112                                                                 if ( aggr->name.find("anonymous") == std::string::npos ) {
    1113                                                                         if ( ! cur->get_inLine() ) {
    1114                                                                                 // temporary: warn about anonymous member declarations of named types, since
    1115                                                                                 // this conflicts with the syntax for the forward declaration of an anonymous type
    1116                                                                                 SemanticWarning( cur->location, Warning::AggrForwardDecl, aggr->name.c_str() );
    1117                                                                         } // if
    1118                                                                 } // if
    1119                                                         } // if
    1120                                                 } // if
    1121                                         } // if
    1122                                         *out++ = decl;
    1123                                 } // if
     1143                                *out++ = decl;
    11241144                        } // if
    1125                 } catch( SemanticErrorException & e ) {
     1145                } catch ( SemanticErrorException & e ) {
    11261146                        errors.append( e );
    11271147                } // try
     
    11381158        std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList );
    11391159
    1140         for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
     1160        for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur ) ) {
    11411161                try {
    11421162                        ast::Decl * decl = cur->build();
    1143                         assert( decl );
     1163                        assertf( decl, "buildList: build for ast::DeclWithType." );
    11441164                        if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {
    11451165                                dwt->location = cur->location;
     
    11701190                                );
    11711191                                *out++ = obj;
     1192                        } else {
     1193                                assertf( false, "buildList: Could not convert to ast::DeclWithType." );
    11721194                        } // if
    1173                 } catch( SemanticErrorException & e ) {
     1195                } catch ( SemanticErrorException & e ) {
    11741196                        errors.append( e );
    11751197                } // try
     
    11851207        SemanticErrorException errors;
    11861208        std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList );
    1187         const DeclarationNode * cur = firstNode;
    1188 
    1189         while ( cur ) {
     1209
     1210        for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
    11901211                try {
    11911212                        * out++ = cur->buildType();
    1192                 } catch( SemanticErrorException & e ) {
     1213                } catch ( SemanticErrorException & e ) {
    11931214                        errors.append( e );
    11941215                } // try
    1195                 cur = dynamic_cast< DeclarationNode * >( cur->get_next() );
    1196         } // while
     1216        } // for
    11971217
    11981218        if ( ! errors.isEmpty() ) {
Note: See TracChangeset for help on using the changeset viewer.