Ignore:
Timestamp:
Jul 14, 2023, 9:32:31 AM (15 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
402a1e7
Parents:
4acf56d
Message:

Added a new invariant check and the fixes required to make it pass. Not the new check is by no means exaustive (it doesn't even check every readonly pointer) but it should catch the most common/problematic cases.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Validate/LinkReferenceToTypes.cpp

    r4acf56d rb7c53a9d  
    1010// Created On       : Thr Apr 21 11:41:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Sep 20 16:17:00 2022
    13 // Update Count     : 2
     12// Last Modified On : Fri Jul 14  9:19:00 2023
     13// Update Count     : 3
    1414//
    1515
     
    2727struct LinkTypesCore : public WithNoIdSymbolTable,
    2828                public ast::WithCodeLocation,
     29                public ast::WithDeclsToAdd<>,
    2930                public ast::WithGuards,
    3031                public ast::WithShortCircuiting,
     
    6364        template<typename AggrDecl>
    6465        AggrDecl const * renameGenericParams( AggrDecl const * decl );
     66
     67        // This cluster is used to add declarations (before) but outside of
     68        // any "namespaces" which would qualify the names.
     69        bool inNamespace = false;
     70        std::list<ast::ptr<ast::Decl>> declsToAddOutside;
     71        /// The "leaveNamespace" is handled by guard.
     72        void enterNamespace();
     73        /// Puts the decl on the back of declsToAddBefore once traversal is
     74        /// outside of any namespaces.
     75        void addDeclBeforeOutside( ast::Decl const * );
    6576};
     77
     78void LinkTypesCore::enterNamespace() {
     79        if ( inNamespace ) return;
     80        inNamespace = true;
     81        GuardAction( [this](){
     82                inNamespace = false;
     83                declsToAddBefore.splice( declsToAddBefore.begin(), declsToAddOutside );
     84        } );
     85}
     86
     87void LinkTypesCore::addDeclBeforeOutside( ast::Decl const * decl ) {
     88        if ( inNamespace ) {
     89                declsToAddOutside.emplace_back( decl );
     90        } else {
     91                declsToAddBefore.emplace_back( decl );
     92        }
     93}
    6694
    6795ast::TypeInstType const * LinkTypesCore::postvisit( ast::TypeInstType const * type ) {
     
    80108ast::EnumInstType const * LinkTypesCore::postvisit( ast::EnumInstType const * type ) {
    81109        ast::EnumDecl const * decl = symtab.lookupEnum( type->name );
     110        // It's not a semantic error if the enum is not found, just an implicit forward declaration.
     111        // The unset code location is used to detect imaginary declarations.
     112        // (They may never be used for enumerations.)
     113        if ( !decl || decl->location.isUnset() ) {
     114                assert( location );
     115                decl = new ast::EnumDecl( *location, type->name );
     116                symtab.addEnum( decl );
     117                addDeclBeforeOutside( decl );
     118        }
     119
    82120        ast::EnumInstType * mut = ast::mutate( type );
    83         // It's not a semantic error if the enum is not found, just an implicit forward declaration.
    84         if ( decl ) {
    85                 // Just linking in the node.
    86                 mut->base = decl;
    87         }
    88         if ( !decl || !decl->body ) {
     121
     122        // Just linking in the node.
     123        mut->base = decl;
     124
     125        if ( !decl->body ) {
    89126                forwardEnums[ mut->name ].push_back( mut );
    90127        }
     
    94131ast::StructInstType const * LinkTypesCore::postvisit( ast::StructInstType const * type ) {
    95132        ast::StructDecl const * decl = symtab.lookupStruct( type->name );
     133        // It's not a semantic error if the struct is not found, just an implicit forward declaration.
     134        // The unset code location is used to detect imaginary declarations.
     135        if ( !decl || decl->location.isUnset() ) {
     136                assert( location );
     137                decl = new ast::StructDecl( *location, type->name );
     138                symtab.addStruct( decl );
     139                addDeclBeforeOutside( decl );
     140        }
     141
    96142        ast::StructInstType * mut = ast::mutate( type );
    97         // It's not a semantic error if the struct is not found, just an implicit forward declaration.
    98         if ( decl ) {
    99                 // Just linking in the node.
    100                 mut->base = decl;
    101         }
    102         if ( !decl || !decl->body ) {
     143
     144        // Just linking in the node.
     145        mut->base = decl;
     146
     147        if ( !decl->body ) {
    103148                forwardStructs[ mut->name ].push_back( mut );
    104149        }
     
    108153ast::UnionInstType const * LinkTypesCore::postvisit( ast::UnionInstType const * type ) {
    109154        ast::UnionDecl const * decl = symtab.lookupUnion( type->name );
     155        // It's not a semantic error if the union is not found, just an implicit forward declaration.
     156        // The unset code location is used to detect imaginary declarations.
     157        if ( !decl || decl->location.isUnset() ) {
     158                assert( location );
     159                decl = new ast::UnionDecl( *location, type->name );
     160                symtab.addUnion( decl );
     161                addDeclBeforeOutside( decl );
     162        }
     163
    110164        ast::UnionInstType * mut = ast::mutate( type );
    111         // It's not a semantic error if the union is not found, just an implicit forward declaration.
    112         if ( decl ) {
    113                 // Just linking in the node.
    114                 mut->base = decl;
    115         }
    116         if ( !decl || !decl->body ) {
     165
     166        // Just linking in the node.
     167        mut->base = decl;
     168
     169        if ( !decl->body ) {
    117170                forwardUnions[ mut->name ].push_back( mut );
    118171        }
     
    219272
    220273ast::StructDecl const * LinkTypesCore::previsit( ast::StructDecl const * decl ) {
     274        enterNamespace();
    221275        return renameGenericParams( decl );
    222276}
     
    237291
    238292ast::UnionDecl const * LinkTypesCore::previsit( ast::UnionDecl const * decl ) {
     293        enterNamespace();
    239294        return renameGenericParams( decl );
    240295}
Note: See TracChangeset for help on using the changeset viewer.