Changeset 8a930c03 for src


Ignore:
Timestamp:
Jun 12, 2023, 12:05:58 PM (2 years ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
fec8bd1
Parents:
2b78949 (diff), 38e266ca (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src
Files:
43 edited

Legend:

Unmodified
Added
Removed
  • src/AST/DeclReplacer.hpp

    r2b78949 r8a930c03  
    1818#include <unordered_map>
    1919
    20 #include "Node.hpp"
     20namespace ast {
     21        class DeclWithType;
     22        class Expr;
     23        class Node;
     24        class TypeDecl;
     25}
    2126
    2227namespace ast {
    23         class DeclWithType;
    24         class TypeDecl;
    25         class Expr;
    2628
    27         namespace DeclReplacer {
    28                 using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >;
    29                 using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >;
    30                 using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >;
     29namespace DeclReplacer {
    3130
    32                 const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false );
    33                 const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false );
    34                 const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
    35                 const Node * replace( const Node * node, const ExprMap & exprMap);
    36         }
     31using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >;
     32using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >;
     33using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >;
     34
     35const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false );
     36const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false );
     37const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false );
     38const Node * replace( const Node * node, const ExprMap & exprMap);
     39
     40}
     41
    3742}
    3843
  • src/AST/Pass.hpp

    r2b78949 r8a930c03  
    414414};
    415415
    416 /// Use when the templated visitor should update the symbol table
     416/// Use when the templated visitor should update the symbol table,
     417/// that is, when your pass core needs to query the symbol table.
     418/// Expected setups:
     419/// - For master passes that kick off at the compilation unit
     420///   - before resolver: extend WithSymbolTableX<IgnoreErrors>
     421///   - after resolver: extend WithSymbolTable and use defaults
     422///   - (FYI, for completeness, the resolver's main pass uses ValidateOnAdd when it kicks off)
     423/// - For helper passes that kick off at arbitrary points in the AST:
     424///   - take an existing symbol table as a parameter, extend WithSymbolTable,
     425///     and construct with WithSymbolTable(const SymbolTable &)
    417426struct WithSymbolTable {
    418         SymbolTable symtab;
     427        WithSymbolTable(const ast::SymbolTable & from) : symtab(from) {}
     428        WithSymbolTable(ast::SymbolTable::ErrorDetection errorMode = ast::SymbolTable::ErrorDetection::AssertClean) : symtab(errorMode) {}
     429        ast::SymbolTable symtab;
     430};
     431template <ast::SymbolTable::ErrorDetection errorMode>
     432struct WithSymbolTableX : WithSymbolTable {
     433        WithSymbolTableX() : WithSymbolTable(errorMode) {}
    419434};
    420435
  • src/AST/Pass.impl.hpp

    r2b78949 r8a930c03  
    2020#include <unordered_map>
    2121
     22#include "AST/Copy.hpp"
    2223#include "AST/TranslationUnit.hpp"
    2324#include "AST/TypeSubstitution.hpp"
     
    4546
    4647#ifdef PEDANTIC_PASS_ASSERT
    47 #define __pedantic_pass_assert(...) assert (__VA_ARGS__)
     48#define __pedantic_pass_assert(...) assert(__VA_ARGS__)
    4849#define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
    4950#else
     
    7172                template<typename it_t, template <class...> class container_t>
    7273                static inline void take_all( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) {
    73                         if(empty(decls)) return;
     74                        if ( empty( decls ) ) return;
    7475
    7576                        std::transform(decls->begin(), decls->end(), it, [](const ast::Decl * decl) -> auto {
     
    7778                                });
    7879                        decls->clear();
    79                         if(mutated) *mutated = true;
     80                        if ( mutated ) *mutated = true;
    8081                }
    8182
    8283                template<typename it_t, template <class...> class container_t>
    8384                static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * stmts, bool * mutated = nullptr ) {
    84                         if(empty(stmts)) return;
     85                        if ( empty( stmts ) ) return;
    8586
    8687                        std::move(stmts->begin(), stmts->end(), it);
    8788                        stmts->clear();
    88                         if(mutated) *mutated = true;
     89                        if ( mutated ) *mutated = true;
    8990                }
    9091
     
    9293                /// Check if should be skipped, different for pointers and containers
    9394                template<typename node_t>
    94                 bool skip( const ast::ptr<node_t> & val) {
     95                bool skip( const ast::ptr<node_t> & val ) {
    9596                        return !val;
    9697                }
     
    109110
    110111                template<typename node_t>
    111                 const node_t & get( const node_t & val, long) {
     112                const node_t & get( const node_t & val, long ) {
    112113                        return val;
    113114                }
     
    125126                }
    126127        }
    127 
    128         template< typename core_t >
    129         template< typename node_t >
    130         auto ast::Pass< core_t >::call_accept( const node_t * node )
    131                 -> typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type
    132         {
    133                 __pedantic_pass_assert( __visit_children() );
    134                 __pedantic_pass_assert( node );
    135 
    136                 static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR");
    137                 static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR");
    138 
    139                 auto nval = node->accept( *this );
    140                 __pass::result1<
    141                         typename std::remove_pointer< decltype( node->accept(*this) ) >::type
    142                 > res;
    143                 res.differs = nval != node;
    144                 res.value = nval;
    145                 return res;
    146         }
    147 
    148         template< typename core_t >
    149         __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
    150                 __pedantic_pass_assert( __visit_children() );
    151                 __pedantic_pass_assert( expr );
    152 
    153                 auto nval = expr->accept( *this );
    154                 return { nval != expr, nval };
    155         }
    156 
    157         template< typename core_t >
    158         __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
    159                 __pedantic_pass_assert( __visit_children() );
    160                 __pedantic_pass_assert( stmt );
    161 
    162                 const ast::Stmt * nval = stmt->accept( *this );
    163                 return { nval != stmt, nval };
    164         }
    165 
    166         template< typename core_t >
    167         __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept_top( const ast::Expr * expr ) {
    168                 __pedantic_pass_assert( __visit_children() );
    169                 __pedantic_pass_assert( expr );
    170 
    171                 const ast::TypeSubstitution ** typeSubs_ptr = __pass::typeSubs( core, 0 );
    172                 if ( typeSubs_ptr && expr->env ) {
    173                         *typeSubs_ptr = expr->env;
    174                 }
    175 
    176                 auto nval = expr->accept( *this );
    177                 return { nval != expr, nval };
    178         }
    179 
    180         template< typename core_t >
    181         __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
    182                 __pedantic_pass_assert( __visit_children() );
    183                 __pedantic_pass_assert( stmt );
    184 
    185                 // add a few useful symbols to the scope
    186                 using __pass::empty;
    187 
    188                 // get the stmts/decls that will need to be spliced in
    189                 auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
    190                 auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
    191                 auto decls_before = __pass::declsToAddBefore( core, 0 );
    192                 auto decls_after  = __pass::declsToAddAfter ( core, 0 );
    193 
    194                 // These may be modified by subnode but most be restored once we exit this statemnet.
    195                 ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::typeSubs( core, 0 ) );
    196                 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    197                 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
    198                 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
    199                 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
    200 
    201                 // Now is the time to actually visit the node
    202                 const ast::Stmt * nstmt = stmt->accept( *this );
    203 
    204                 // If the pass doesn't want to add anything then we are done
    205                 if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {
    206                         return { nstmt != stmt, nstmt };
    207                 }
    208 
    209                 // Make sure that it is either adding statements or declartions but not both
    210                 // this is because otherwise the order would be awkward to predict
    211                 assert(( empty( stmts_before ) && empty( stmts_after ))
    212                     || ( empty( decls_before ) && empty( decls_after )) );
    213 
    214                 // Create a new Compound Statement to hold the new decls/stmts
    215                 ast::CompoundStmt * compound = new ast::CompoundStmt( stmt->location );
    216 
    217                 // Take all the declarations that go before
    218                 __pass::take_all( std::back_inserter( compound->kids ), decls_before );
    219                 __pass::take_all( std::back_inserter( compound->kids ), stmts_before );
    220 
    221                 // Insert the original declaration
    222                 compound->kids.emplace_back( nstmt );
    223 
    224                 // Insert all the declarations that go before
    225                 __pass::take_all( std::back_inserter( compound->kids ), decls_after );
    226                 __pass::take_all( std::back_inserter( compound->kids ), stmts_after );
    227 
    228                 return {true, compound};
    229         }
    230 
    231         template< typename core_t >
    232         template< template <class...> class container_t >
    233         __pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
    234                 __pedantic_pass_assert( __visit_children() );
    235                 if( statements.empty() ) return {};
    236 
    237                 // We are going to aggregate errors for all these statements
    238                 SemanticErrorException errors;
    239 
    240                 // add a few useful symbols to the scope
    241                 using __pass::empty;
    242 
    243                 // get the stmts/decls that will need to be spliced in
    244                 auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
    245                 auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
    246                 auto decls_before = __pass::declsToAddBefore( core, 0 );
    247                 auto decls_after  = __pass::declsToAddAfter ( core, 0 );
    248 
    249                 // These may be modified by subnode but most be restored once we exit this statemnet.
    250                 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
    251                 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
    252                 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
    253                 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
    254 
    255                 // update pass statitistics
    256                 pass_visitor_stats.depth++;
    257                 pass_visitor_stats.max->push(pass_visitor_stats.depth);
    258                 pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    259 
    260                 __pass::resultNstmt<container_t> new_kids;
    261                 for( auto value : enumerate( statements ) ) {
    262                         try {
    263                                 size_t i = value.idx;
    264                                 const Stmt * stmt = value.val;
    265                                 __pedantic_pass_assert( stmt );
    266                                 const ast::Stmt * new_stmt = stmt->accept( *this );
    267                                 assert( new_stmt );
    268                                 if(new_stmt != stmt ) { new_kids.differs = true; }
    269 
    270                                 // Make sure that it is either adding statements or declartions but not both
    271                                 // this is because otherwise the order would be awkward to predict
    272                                 assert(( empty( stmts_before ) && empty( stmts_after ))
    273                                     || ( empty( decls_before ) && empty( decls_after )) );
    274 
    275                                 // Take all the statements which should have gone after, N/A for first iteration
    276                                 new_kids.take_all( decls_before );
    277                                 new_kids.take_all( stmts_before );
    278 
    279                                 // Now add the statement if there is one
    280                                 if(new_stmt != stmt) {
    281                                         new_kids.values.emplace_back( new_stmt, i, false );
    282                                 } else {
    283                                         new_kids.values.emplace_back( nullptr, i, true );
    284                                 }
    285 
    286                                 // Take all the declarations that go before
    287                                 new_kids.take_all( decls_after );
    288                                 new_kids.take_all( stmts_after );
     128}
     129
     130template< typename core_t >
     131template< typename node_t >
     132auto ast::Pass< core_t >::call_accept( const node_t * node ) ->
     133        typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type
     134{
     135        __pedantic_pass_assert( __visit_children() );
     136        __pedantic_pass_assert( node );
     137
     138        static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR" );
     139        static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR" );
     140
     141        auto nval = node->accept( *this );
     142        __pass::result1<
     143                typename std::remove_pointer< decltype( node->accept(*this) ) >::type
     144        > res;
     145        res.differs = nval != node;
     146        res.value = nval;
     147        return res;
     148}
     149
     150template< typename core_t >
     151ast::__pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) {
     152        __pedantic_pass_assert( __visit_children() );
     153        __pedantic_pass_assert( expr );
     154
     155        auto nval = expr->accept( *this );
     156        return { nval != expr, nval };
     157}
     158
     159template< typename core_t >
     160ast::__pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) {
     161        __pedantic_pass_assert( __visit_children() );
     162        __pedantic_pass_assert( stmt );
     163
     164        const ast::Stmt * nval = stmt->accept( *this );
     165        return { nval != stmt, nval };
     166}
     167
     168template< typename core_t >
     169ast::__pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept_top( const ast::Expr * expr ) {
     170        __pedantic_pass_assert( __visit_children() );
     171        __pedantic_pass_assert( expr );
     172
     173        const ast::TypeSubstitution ** typeSubs_ptr = __pass::typeSubs( core, 0 );
     174        if ( typeSubs_ptr && expr->env ) {
     175                *typeSubs_ptr = expr->env;
     176        }
     177
     178        auto nval = expr->accept( *this );
     179        return { nval != expr, nval };
     180}
     181
     182template< typename core_t >
     183ast::__pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) {
     184        __pedantic_pass_assert( __visit_children() );
     185        __pedantic_pass_assert( stmt );
     186
     187        // add a few useful symbols to the scope
     188        using __pass::empty;
     189
     190        // get the stmts/decls that will need to be spliced in
     191        auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
     192        auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
     193        auto decls_before = __pass::declsToAddBefore( core, 0 );
     194        auto decls_after  = __pass::declsToAddAfter ( core, 0 );
     195
     196        // These may be modified by subnode but most be restored once we exit this statemnet.
     197        ValueGuardPtr< const ast::TypeSubstitution * > __old_env         ( __pass::typeSubs( core, 0 ) );
     198        ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
     199        ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     200        ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
     201        ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
     202
     203        // Now is the time to actually visit the node
     204        const ast::Stmt * nstmt = stmt->accept( *this );
     205
     206        // If the pass doesn't want to add anything then we are done
     207        if ( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {
     208                return { nstmt != stmt, nstmt };
     209        }
     210
     211        // Make sure that it is either adding statements or declartions but not both
     212        // this is because otherwise the order would be awkward to predict
     213        assert(( empty( stmts_before ) && empty( stmts_after ))
     214            || ( empty( decls_before ) && empty( decls_after )) );
     215
     216        // Create a new Compound Statement to hold the new decls/stmts
     217        ast::CompoundStmt * compound = new ast::CompoundStmt( stmt->location );
     218
     219        // Take all the declarations that go before
     220        __pass::take_all( std::back_inserter( compound->kids ), decls_before );
     221        __pass::take_all( std::back_inserter( compound->kids ), stmts_before );
     222
     223        // Insert the original declaration
     224        compound->kids.emplace_back( nstmt );
     225
     226        // Insert all the declarations that go before
     227        __pass::take_all( std::back_inserter( compound->kids ), decls_after );
     228        __pass::take_all( std::back_inserter( compound->kids ), stmts_after );
     229
     230        return { true, compound };
     231}
     232
     233template< typename core_t >
     234template< template <class...> class container_t >
     235ast::__pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) {
     236        __pedantic_pass_assert( __visit_children() );
     237        if ( statements.empty() ) return {};
     238
     239        // We are going to aggregate errors for all these statements
     240        SemanticErrorException errors;
     241
     242        // add a few useful symbols to the scope
     243        using __pass::empty;
     244
     245        // get the stmts/decls that will need to be spliced in
     246        auto stmts_before = __pass::stmtsToAddBefore( core, 0 );
     247        auto stmts_after  = __pass::stmtsToAddAfter ( core, 0 );
     248        auto decls_before = __pass::declsToAddBefore( core, 0 );
     249        auto decls_after  = __pass::declsToAddAfter ( core, 0 );
     250
     251        // These may be modified by subnode but most be restored once we exit this statemnet.
     252        ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before );
     253        ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after  );
     254        ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before );
     255        ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after  );
     256
     257        // update pass statitistics
     258        pass_visitor_stats.depth++;
     259        pass_visitor_stats.max->push(pass_visitor_stats.depth);
     260        pass_visitor_stats.avg->push(pass_visitor_stats.depth);
     261
     262        __pass::resultNstmt<container_t> new_kids;
     263        for ( auto value : enumerate( statements ) ) {
     264                try {
     265                        size_t i = value.idx;
     266                        const Stmt * stmt = value.val;
     267                        __pedantic_pass_assert( stmt );
     268                        const ast::Stmt * new_stmt = stmt->accept( *this );
     269                        assert( new_stmt );
     270                        if ( new_stmt != stmt ) { new_kids.differs = true; }
     271
     272                        // Make sure that it is either adding statements or declartions but not both
     273                        // this is because otherwise the order would be awkward to predict
     274                        assert(( empty( stmts_before ) && empty( stmts_after ))
     275                            || ( empty( decls_before ) && empty( decls_after )) );
     276
     277                        // Take all the statements which should have gone after, N/A for first iteration
     278                        new_kids.take_all( decls_before );
     279                        new_kids.take_all( stmts_before );
     280
     281                        // Now add the statement if there is one
     282                        if ( new_stmt != stmt ) {
     283                                new_kids.values.emplace_back( new_stmt, i, false );
     284                        } else {
     285                                new_kids.values.emplace_back( nullptr, i, true );
    289286                        }
    290                         catch ( SemanticErrorException &e ) {
    291                                 errors.append( e );
     287
     288                        // Take all the declarations that go before
     289                        new_kids.take_all( decls_after );
     290                        new_kids.take_all( stmts_after );
     291                } catch ( SemanticErrorException &e ) {
     292                        errors.append( e );
     293                }
     294        }
     295        pass_visitor_stats.depth--;
     296        if ( !errors.isEmpty() ) { throw errors; }
     297
     298        return new_kids;
     299}
     300
     301template< typename core_t >
     302template< template <class...> class container_t, typename node_t >
     303ast::__pass::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
     304        __pedantic_pass_assert( __visit_children() );
     305        if ( container.empty() ) return {};
     306        SemanticErrorException errors;
     307
     308        pass_visitor_stats.depth++;
     309        pass_visitor_stats.max->push(pass_visitor_stats.depth);
     310        pass_visitor_stats.avg->push(pass_visitor_stats.depth);
     311
     312        bool mutated = false;
     313        container_t<ptr<node_t>> new_kids;
     314        for ( const node_t * node : container ) {
     315                try {
     316                        __pedantic_pass_assert( node );
     317                        const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) );
     318                        if ( new_stmt != node ) {
     319                                mutated = true;
     320                                new_kids.emplace_back( new_stmt );
     321                        } else {
     322                                new_kids.emplace_back( nullptr );
    292323                        }
    293                 }
    294                 pass_visitor_stats.depth--;
    295                 if ( !errors.isEmpty() ) { throw errors; }
    296 
    297                 return new_kids;
    298         }
    299 
    300         template< typename core_t >
    301         template< template <class...> class container_t, typename node_t >
    302         __pass::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) {
    303                 __pedantic_pass_assert( __visit_children() );
    304                 if( container.empty() ) return {};
    305                 SemanticErrorException errors;
    306 
    307                 pass_visitor_stats.depth++;
    308                 pass_visitor_stats.max->push(pass_visitor_stats.depth);
    309                 pass_visitor_stats.avg->push(pass_visitor_stats.depth);
    310 
    311                 bool mutated = false;
    312                 container_t<ptr<node_t>> new_kids;
    313                 for ( const node_t * node : container ) {
    314                         try {
    315                                 __pedantic_pass_assert( node );
    316                                 const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) );
    317                                 if(new_stmt != node ) {
    318                                         mutated = true;
    319                                         new_kids.emplace_back( new_stmt );
    320                                 } else {
    321                                         new_kids.emplace_back( nullptr );
    322                                 }
    323 
    324                         }
    325                         catch( SemanticErrorException &e ) {
    326                                 errors.append( e );
    327                         }
    328                 }
    329 
    330                 __pedantic_pass_assert( new_kids.size() == container.size() );
    331                 pass_visitor_stats.depth--;
    332                 if ( ! errors.isEmpty() ) { throw errors; }
    333 
    334                 return ast::__pass::resultN<container_t, node_t>{ mutated, new_kids };
    335         }
    336 
    337         template< typename core_t >
    338         template<typename node_t, typename super_t, typename field_t>
    339         void ast::Pass< core_t >::maybe_accept(
    340                 const node_t * & parent,
    341                 field_t super_t::*field
    342         ) {
    343                 static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
    344 
    345                 if(__pass::skip(parent->*field)) return;
    346                 const auto & old_val = __pass::get(parent->*field, 0);
    347 
    348                 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
    349 
    350                 auto new_val = call_accept( old_val );
    351 
    352                 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR");
    353 
    354                 if( new_val.differs ) {
    355                         auto new_parent = __pass::mutate<core_t>(parent);
    356                         new_val.apply(new_parent, field);
    357                         parent = new_parent;
    358                 }
    359         }
    360 
    361         template< typename core_t >
    362         template<typename node_t, typename super_t, typename field_t>
    363         void ast::Pass< core_t >::maybe_accept_top(
    364                 const node_t * & parent,
    365                 field_t super_t::*field
    366         ) {
    367                 static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
    368 
    369                 if(__pass::skip(parent->*field)) return;
    370                 const auto & old_val = __pass::get(parent->*field, 0);
    371 
    372                 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
    373 
    374                 auto new_val = call_accept_top( old_val );
    375 
    376                 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR");
    377 
    378                 if( new_val.differs ) {
    379                         auto new_parent = __pass::mutate<core_t>(parent);
    380                         new_val.apply(new_parent, field);
    381                         parent = new_parent;
    382                 }
    383         }
    384 
    385         template< typename core_t >
    386         template<typename node_t, typename super_t, typename field_t>
    387         void ast::Pass< core_t >::maybe_accept_as_compound(
    388                 const node_t * & parent,
    389                 field_t super_t::*child
    390         ) {
    391                 static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
    392 
    393                 if(__pass::skip(parent->*child)) return;
    394                 const auto & old_val = __pass::get(parent->*child, 0);
    395 
    396                 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
    397 
    398                 auto new_val = call_accept_as_compound( old_val );
    399 
    400                 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR");
    401 
    402                 if( new_val.differs ) {
    403                         auto new_parent = __pass::mutate<core_t>(parent);
    404                         new_val.apply( new_parent, child );
    405                         parent = new_parent;
    406                 }
    407         }
    408 
     324                } catch ( SemanticErrorException &e ) {
     325                        errors.append( e );
     326                }
     327        }
     328
     329        __pedantic_pass_assert( new_kids.size() == container.size() );
     330        pass_visitor_stats.depth--;
     331        if ( !errors.isEmpty() ) { throw errors; }
     332
     333        return ast::__pass::resultN<container_t, node_t>{ mutated, new_kids };
     334}
     335
     336template< typename core_t >
     337template<typename node_t, typename super_t, typename field_t>
     338void ast::Pass< core_t >::maybe_accept(
     339        const node_t * & parent,
     340        field_t super_t::*field
     341) {
     342        static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
     343
     344        if ( __pass::skip( parent->*field ) ) return;
     345        const auto & old_val = __pass::get(parent->*field, 0);
     346
     347        static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" );
     348
     349        auto new_val = call_accept( old_val );
     350
     351        static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR" );
     352
     353        if ( new_val.differs ) {
     354                auto new_parent = __pass::mutate<core_t>(parent);
     355                new_val.apply(new_parent, field);
     356                parent = new_parent;
     357        }
     358}
     359
     360template< typename core_t >
     361template<typename node_t, typename super_t, typename field_t>
     362void ast::Pass< core_t >::maybe_accept_top(
     363        const node_t * & parent,
     364        field_t super_t::*field
     365) {
     366        static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
     367
     368        if ( __pass::skip( parent->*field ) ) return;
     369        const auto & old_val = __pass::get(parent->*field, 0);
     370
     371        static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" );
     372
     373        auto new_val = call_accept_top( old_val );
     374
     375        static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR" );
     376
     377        if ( new_val.differs ) {
     378                auto new_parent = __pass::mutate<core_t>(parent);
     379                new_val.apply(new_parent, field);
     380                parent = new_parent;
     381        }
     382}
     383
     384template< typename core_t >
     385template<typename node_t, typename super_t, typename field_t>
     386void ast::Pass< core_t >::maybe_accept_as_compound(
     387        const node_t * & parent,
     388        field_t super_t::*child
     389) {
     390        static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
     391
     392        if ( __pass::skip( parent->*child ) ) return;
     393        const auto & old_val = __pass::get(parent->*child, 0);
     394
     395        static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" );
     396
     397        auto new_val = call_accept_as_compound( old_val );
     398
     399        static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR" );
     400
     401        if ( new_val.differs ) {
     402                auto new_parent = __pass::mutate<core_t>(parent);
     403                new_val.apply( new_parent, child );
     404                parent = new_parent;
     405        }
    409406}
    410407
     
    760757
    761758        if ( __visit_children() ) {
    762                 // Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
    763                 auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
    764                         if ( enterScope ) {
    765                                 __pass::symtab::enter(core, 0);
    766                         }
    767                 }, [this, leaveScope = !this->atFunctionTop]() {
    768                         if ( leaveScope ) {
    769                                 __pass::symtab::leave(core, 0);
    770                         }
    771                 });
    772                 ValueGuard< bool > guard2( atFunctionTop );
    773                 atFunctionTop = false;
    774                 guard_scope guard3 { *this };
    775                 maybe_accept( node, &CompoundStmt::kids );
     759                // Do not enter (or leave) a new symbol table scope if atFunctionTop.
     760                // But always enter (and leave) a new general scope.
     761                if ( atFunctionTop ) {
     762                        ValueGuard< bool > guard1( atFunctionTop );
     763                        atFunctionTop = false;
     764                        guard_scope guard2( *this );
     765                        maybe_accept( node, &CompoundStmt::kids );
     766                } else {
     767                        guard_symtab guard1( *this );
     768                        guard_scope guard2( *this );
     769                        maybe_accept( node, &CompoundStmt::kids );
     770                }
    776771        }
    777772
  • src/AST/Pass.proto.hpp

    r2b78949 r8a930c03  
    2727
    2828#ifdef PEDANTIC_PASS_ASSERT
    29 #define __pedantic_pass_assert(...) assert (__VA_ARGS__)
     29#define __pedantic_pass_assert(...) assert(__VA_ARGS__)
    3030#define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
    3131#else
  • src/AST/Print.cpp

    r2b78949 r8a930c03  
    1616#include "Print.hpp"
    1717
     18#include "Attribute.hpp"
    1819#include "Decl.hpp"
    1920#include "Expr.hpp"
     21#include "Init.hpp"
    2022#include "Stmt.hpp"
    2123#include "Type.hpp"
    2224#include "TypeSubstitution.hpp"
    2325#include "CompilationState.h"
    24 
    25 #include "Common/utility.h" // for group_iterate
     26#include "Common/Iterate.hpp"
    2627
    2728using namespace std;
  • src/AST/SymbolTable.cpp

    r2b78949 r8a930c03  
    1818#include <cassert>
    1919
     20#include "Copy.hpp"
    2021#include "Decl.hpp"
    2122#include "Expr.hpp"
     
    8788}
    8889
    89 SymbolTable::SymbolTable()
     90SymbolTable::SymbolTable( ErrorDetection errorMode )
    9091: idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(),
    91   prevScope(), scope( 0 ), repScope( 0 ) { ++*stats().count; }
     92  prevScope(), scope( 0 ), repScope( 0 ), errorMode(errorMode) { ++*stats().count; }
    9293
    9394SymbolTable::~SymbolTable() { stats().size->push( idTable ? idTable->size() : 0 ); }
     95
     96void SymbolTable::OnFindError( CodeLocation location, std::string error ) const {
     97        assertf( errorMode != AssertClean, "Name collision/redefinition, found during a compilation phase where none should be possible.  Detail: %s", error.c_str() );
     98        if (errorMode == ValidateOnAdd) {
     99                SemanticError(location, error);
     100        }
     101        assertf( errorMode == IgnoreErrors, "Unrecognized symbol-table error mode %d", errorMode );
     102}
    94103
    95104void SymbolTable::enterScope() {
     
    268277}
    269278
    270 namespace {
    271         /// true if redeclaration conflict between two types
    272         bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) {
    273                 if ( existing->base == nullptr ) {
    274                         return false;
    275                 } else if ( added->base == nullptr ) {
    276                         return true;
    277                 } else {
    278                         // typedef redeclarations are errors only if types are different
    279                         if ( ! ResolvExpr::typesCompatible( existing->base, added->base, SymbolTable{} ) ) {
    280                                 SemanticError( added->location, "redeclaration of " + added->name );
    281                         }
    282                 }
    283                 // does not need to be added to the table if both existing and added have a base that are
    284                 // the same
     279bool SymbolTable::addedTypeConflicts(
     280                const NamedTypeDecl * existing, const NamedTypeDecl * added ) const {
     281        if ( existing->base == nullptr ) {
     282                return false;
     283        } else if ( added->base == nullptr ) {
    285284                return true;
    286         }
    287 
    288         /// true if redeclaration conflict between two aggregate declarations
    289         bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) {
    290                 if ( ! existing->body ) {
    291                         return false;
    292                 } else if ( added->body ) {
    293                         SemanticError( added, "redeclaration of " );
    294                 }
    295                 return true;
    296         }
     285        } else {
     286                // typedef redeclarations are errors only if types are different
     287                if ( ! ResolvExpr::typesCompatible( existing->base, added->base ) ) {
     288                        OnFindError( added->location, "redeclaration of " + added->name );
     289                }
     290        }
     291        // does not need to be added to the table if both existing and added have a base that are
     292        // the same
     293        return true;
     294}
     295
     296bool SymbolTable::addedDeclConflicts(
     297                const AggregateDecl * existing, const AggregateDecl * added ) const {
     298        if ( ! existing->body ) {
     299                return false;
     300        } else if ( added->body ) {
     301                OnFindError( added, "redeclaration of " );
     302        }
     303        return true;
    297304}
    298305
     
    642649        } else if ( existing.id->linkage.is_mangled
    643650                        || ResolvExpr::typesCompatible(
    644                                 added->get_type(), existing.id->get_type(), SymbolTable{} ) ) {
     651                                added->get_type(), existing.id->get_type() ) ) {
    645652
    646653                // it is a conflict if one declaration is deleted and the other is not
    647654                if ( deleter && ! existing.deleter ) {
    648655                        if ( handleConflicts.mode == OnConflict::Error ) {
    649                                 SemanticError( added, "deletion of defined identifier " );
     656                                OnFindError( added, "deletion of defined identifier " );
    650657                        }
    651658                        return true;
    652659                } else if ( ! deleter && existing.deleter ) {
    653660                        if ( handleConflicts.mode == OnConflict::Error ) {
    654                                 SemanticError( added, "definition of deleted identifier " );
     661                                OnFindError( added, "definition of deleted identifier " );
    655662                        }
    656663                        return true;
     
    660667                if ( isDefinition( added ) && isDefinition( existing.id ) ) {
    661668                        if ( handleConflicts.mode == OnConflict::Error ) {
    662                                 SemanticError( added,
     669                                OnFindError( added,
    663670                                        isFunction( added ) ?
    664671                                                "duplicate function definition for " :
     
    669676        } else {
    670677                if ( handleConflicts.mode == OnConflict::Error ) {
    671                         SemanticError( added, "duplicate definition for " );
     678                        OnFindError( added, "duplicate definition for " );
    672679                }
    673680                return true;
     
    721728                // Check that a Cforall declaration doesn't override any C declaration
    722729                if ( hasCompatibleCDecl( name, mangleName ) ) {
    723                         SemanticError( decl, "Cforall declaration hides C function " );
     730                        OnFindError( decl, "Cforall declaration hides C function " );
    724731                }
    725732        } else {
     
    727734                // type-compatibility, which it may not be.
    728735                if ( hasIncompatibleCDecl( name, mangleName ) ) {
    729                         SemanticError( decl, "conflicting overload of C function " );
     736                        OnFindError( decl, "conflicting overload of C function " );
    730737                }
    731738        }
  • src/AST/SymbolTable.hpp

    r2b78949 r8a930c03  
    9393
    9494public:
    95         SymbolTable();
     95
     96        /// Mode to control when (during which pass) user-caused name-declaration errors get reported.
     97        /// The default setting `AssertClean` supports, "I expect all user-caused errors to have been
     98        /// reported by now," or, "I wouldn't know what to do with an error; are there even any here?"
     99        enum ErrorDetection {
     100                AssertClean,               ///< invalid user decls => assert fails during addFoo (default)
     101                ValidateOnAdd,             ///< invalid user decls => calls SemanticError during addFoo
     102                IgnoreErrors               ///< acts as if unspecified decls were removed, forcing validity
     103        };
     104
     105        explicit SymbolTable(
     106                ErrorDetection             ///< mode for the lifetime of the symbol table (whole pass)
     107        );
     108        SymbolTable() : SymbolTable(AssertClean) {}
    96109        ~SymbolTable();
     110
     111        ErrorDetection getErrorMode() const {
     112                return errorMode;
     113        }
    97114
    98115        // when using an indexer manually (e.g., within a mutator traversal), it is necessary to
     
    158175
    159176private:
     177        void OnFindError( CodeLocation location, std::string error ) const;
     178
     179        template< typename T >
     180        void OnFindError( const T * obj, const std::string & error ) const {
     181                OnFindError( obj->location, toString( error, obj ) );
     182        }
     183
     184        template< typename T >
     185        void OnFindError( CodeLocation location, const T * obj, const std::string & error ) const {
     186                OnFindError( location, toString( error, obj ) );
     187        }
     188
    160189        /// Ensures that a proper backtracking scope exists before a mutation
    161190        void lazyInitScope();
     
    168197        bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr & mangleTable );
    169198
    170         /// Options for handling identifier conflicts
     199        /// Error detection mode given at construction (pass-specific).
     200        /// Logically const, except that the symbol table's push-pop is achieved by autogenerated
     201        /// assignment onto self.  The feield is left motuable to keep this code-gen simple.
     202        /// Conceptual constness is preserved by all SymbolTable in a stack sharing the same mode.
     203        ErrorDetection errorMode;
     204
     205        /// Options for handling identifier conflicts.
     206        /// Varies according to AST location during traversal: captures semantics of the construct
     207        /// being visited as "would shadow" vs "must not collide."
     208        /// At a given AST location, is the same for every pass.
    171209        struct OnConflict {
    172210                enum {
    173                         Error,  ///< Throw a semantic error
     211                        Error,  ///< Follow the current pass's ErrorDetection mode (may throw a semantic error)
    174212                        Delete  ///< Delete the earlier version with the delete statement
    175213                } mode;
     
    191229                const Decl * deleter );
    192230
     231        /// true if redeclaration conflict between two types
     232        bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) const;
     233
     234        /// true if redeclaration conflict between two aggregate declarations
     235        bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) const;
     236
    193237        /// common code for addId, addDeletedId, etc.
    194238        void addIdCommon(
     
    213257}
    214258
     259
    215260// Local Variables: //
    216261// tab-width: 4 //
  • src/AST/TypeEnvironment.cpp

    r2b78949 r8a930c03  
    178178
    179179bool TypeEnvironment::combine(
    180                 const TypeEnvironment & o, OpenVarSet & open, const SymbolTable & symtab ) {
     180                const TypeEnvironment & o, OpenVarSet & open ) {
    181181        // short-circuit easy cases
    182182        if ( o.empty() ) return true;
     
    201201                        EqvClass & r = *rt;
    202202                        // merge bindings
    203                         if ( ! mergeBound( r, c, open, symtab ) ) return false;
     203                        if ( ! mergeBound( r, c, open ) ) return false;
    204204                        // merge previous unbound variables into this class, checking occurs if needed
    205205                        if ( r.bound ) for ( const auto & u : c.vars ) {
     
    216216                                } else if ( st != rt ) {
    217217                                        // bound, but not to the same class
    218                                         if ( ! mergeClasses( rt, st, open, symtab ) ) return false;
     218                                        if ( ! mergeClasses( rt, st, open ) ) return false;
    219219                                }       // ignore bound into the same class
    220220                        }
     
    280280bool TypeEnvironment::bindVar(
    281281                const TypeInstType * typeInst, const Type * bindTo, const TypeData & data,
    282                 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen,
    283                 const SymbolTable & symtab
     282                AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen
    284283) {
    285284        // remove references from bound type, so that type variables can only bind to value types
     
    300299                        if ( unifyInexact(
    301300                                        newType, target, *this, need, have, open,
    302                                         widen & WidenMode{ it->allowWidening, true }, symtab, common ) ) {
     301                                        widen & WidenMode{ it->allowWidening, true }, common ) ) {
    303302                                if ( common ) {
    304303                                        it->bound = std::move(common);
     
    321320                const TypeInstType * var1, const TypeInstType * var2, TypeData && data,
    322321                AssertionSet & need, AssertionSet & have, const OpenVarSet & open,
    323                 WidenMode widen, const SymbolTable & symtab
     322                WidenMode widen
    324323) {
    325324        auto c1 = internal_lookup( *var1 );
     
    358357
    359358                if ( unifyInexact(
    360                                 newType1, newType2, *this, need, have, open, newWidenMode, symtab, common ) ) {
     359                                newType1, newType2, *this, need, have, open, newWidenMode, common ) ) {
    361360                        c1->vars.insert( c2->vars.begin(), c2->vars.end() );
    362361                        c1->allowWidening = widen1 && widen2;
     
    409408
    410409bool TypeEnvironment::mergeBound(
    411                 EqvClass & to, const EqvClass & from, OpenVarSet & open, const SymbolTable & symtab ) {
     410                EqvClass & to, const EqvClass & from, OpenVarSet & open ) {
    412411        if ( from.bound ) {
    413412                if ( to.bound ) {
     
    419418
    420419                        if ( unifyInexact(
    421                                         toType, fromType, *this, need, have, open, widen, symtab, common ) ) {
     420                                        toType, fromType, *this, need, have, open, widen, common ) ) {
    422421                                // unifies, set common type if necessary
    423422                                if ( common ) {
     
    437436
    438437bool TypeEnvironment::mergeClasses(
    439         ClassList::iterator to, ClassList::iterator from, OpenVarSet & open, const SymbolTable & symtab
     438        ClassList::iterator to, ClassList::iterator from, OpenVarSet & open
    440439) {
    441440        EqvClass & r = *to, & s = *from;
    442441
    443442        // ensure bounds match
    444         if ( ! mergeBound( r, s, open, symtab ) ) return false;
     443        if ( ! mergeBound( r, s, open ) ) return false;
    445444
    446445        // check safely bindable
  • src/AST/TypeEnvironment.hpp

    r2b78949 r8a930c03  
    169169        /// Merge environment with this one, checking compatibility.
    170170        /// Returns false if fails, but does NOT roll back partial changes.
    171         bool combine( const TypeEnvironment & o, OpenVarSet & openVars, const SymbolTable & symtab );
     171        bool combine( const TypeEnvironment & o, OpenVarSet & openVars );
    172172
    173173        /// Add all type variables in environment to open var list
     
    183183                const TypeInstType * typeInst, const Type * bindTo, const TypeData & data,
    184184                AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
    185                 ResolvExpr::WidenMode widen, const SymbolTable & symtab );
     185                ResolvExpr::WidenMode widen );
    186186
    187187        /// Binds the type classes represented by `var1` and `var2` together; will add one or both
     
    190190                const TypeInstType * var1, const TypeInstType * var2, TypeData && data,
    191191                AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars,
    192                 ResolvExpr::WidenMode widen, const SymbolTable & symtab );
     192                ResolvExpr::WidenMode widen );
    193193
    194194        /// Disallows widening for all bindings in the environment
     
    205205        /// Unifies the type bound of `to` with the type bound of `from`, returning false if fails
    206206        bool mergeBound(
    207                 EqvClass & to, const EqvClass & from, OpenVarSet & openVars, const SymbolTable & symtab );
     207                EqvClass & to, const EqvClass & from, OpenVarSet & openVars );
    208208
    209209        /// Merges two type classes from local environment, returning false if fails
    210210        bool mergeClasses(
    211                 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars,
    212                 const SymbolTable & symtab );
     211                ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars);
    213212
    214213        /// Private lookup API; returns array index of string, or env.size() for not found
  • src/AST/TypeSubstitution.cpp

    r2b78949 r8a930c03  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Jun  3 13:26:00 2017
    13 // Update Count     : 5
    14 //
     12// Last Modified On : Thr May 25 11:24:00 2023
     13// Update Count     : 6
     14//
     15
     16#include "TypeSubstitution.hpp"
    1517
    1618#include "Type.hpp"   // for TypeInstType, Type, StructInstType, UnionInstType
    17 #include "TypeSubstitution.hpp"
     19#include "Pass.hpp"   // for Pass, PureVisitor, WithGuards, WithVisitorRef
    1820
    1921namespace ast {
    20 
    21 
    22 // size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");
    2322
    2423TypeSubstitution::TypeSubstitution() {
     
    119118}
    120119
     120// definitition must happen after PassVisitor is included so that WithGuards can be used
     121struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter>, public PureVisitor {
     122        //static size_t traceId;
     123
     124        Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
     125
     126        const Type * postvisit( const TypeInstType * aggregateUseType );
     127
     128        /// Records type variable bindings from forall-statements
     129        void previsit( const FunctionType * type );
     130        /// Records type variable bindings from forall-statements and instantiations of generic types
     131        // void handleAggregateType( const BaseInstType * type );
     132
     133        // void previsit( const StructInstType * aggregateUseType );
     134        // void previsit( const UnionInstType * aggregateUseType );
     135
     136        const TypeSubstitution & sub;
     137        int subCount = 0;
     138        bool freeOnly;
     139        typedef std::unordered_set< TypeEnvKey > BoundVarsType;
     140        BoundVarsType boundVars;
     141};
     142
     143// size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");
     144
    121145void TypeSubstitution::normalize() {
    122146        Pass<Substituter> sub( *this, true );
     
    128152                }
    129153        } while ( sub.core.subCount );
     154}
     155
     156TypeSubstitution::ApplyResult<Node> TypeSubstitution::applyBase(
     157                const Node * input, bool isFree ) const {
     158        assert( input );
     159        Pass<Substituter> sub( *this, isFree );
     160        const Node * output = input->accept( sub );
     161        return { output, sub.core.subCount };
    130162}
    131163
  • src/AST/TypeSubstitution.hpp

    r2b78949 r8a930c03  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Apr 30 22:52:47 2019
    13 // Update Count     : 9
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr May 25 12:31:00 2023
     13// Update Count     : 10
    1414//
    1515
     
    4646        TypeSubstitution &operator=( const TypeSubstitution &other );
    4747
    48         template< typename SynTreeClass >
     48        template< typename node_t >
    4949        struct ApplyResult {
    50                 ast::ptr<SynTreeClass> node;
     50                ast::ptr<node_t> node;
    5151                int count;
    5252        };
    5353
    54         template< typename SynTreeClass > ApplyResult<SynTreeClass> apply( const SynTreeClass * input ) const;
    55         template< typename SynTreeClass > ApplyResult<SynTreeClass> applyFree( const SynTreeClass * input ) const;
     54        template< typename node_t >
     55        ApplyResult<node_t> apply( const node_t * input ) const {
     56                ApplyResult<Node> ret = applyBase( input, false );
     57                return { ret.node.strict_as<node_t>(), ret.count };
     58        }
    5659
    5760        template< typename node_t, enum Node::ref_type ref_t >
    5861        int apply( ptr_base< node_t, ref_t > & input ) const {
    59                 const node_t * p = input.get();
    60                 auto ret = apply(p);
    61                 input = ret.node;
     62                ApplyResult<Node> ret = applyBase( input.get(), false );
     63                input = ret.node.strict_as<node_t>();
    6264                return ret.count;
     65        }
     66
     67        template< typename node_t >
     68        ApplyResult<node_t> applyFree( const node_t * input ) const {
     69                ApplyResult<Node> ret = applyBase( input, true );
     70                return { ret.node.strict_as<node_t>(), ret.count };
    6371        }
    6472
    6573        template< typename node_t, enum Node::ref_type ref_t >
    6674        int applyFree( ptr_base< node_t, ref_t > & input ) const {
    67                 const node_t * p = input.get();
    68                 auto ret = applyFree(p);
    69                 input = ret.node;
     75                ApplyResult<Node> ret = applyBase( input.get(), true );
     76                input = ret.node.strict_as<node_t>();
    7077                return ret.count;
    7178        }
     
    97104        // Mutator that performs the substitution
    98105        struct Substituter;
     106        ApplyResult<Node> applyBase( const Node * input, bool isFree ) const;
    99107
    100108        // TODO: worry about traversing into a forall-qualified function type or type decl with assertions
     
    158166} // namespace ast
    159167
    160 // include needs to happen after TypeSubstitution is defined so that both TypeSubstitution and
    161 // PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.
    162 #include "Pass.hpp"
    163 #include "Copy.hpp"
    164 
    165 namespace ast {
    166 
    167 // definitition must happen after PassVisitor is included so that WithGuards can be used
    168 struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter>, public PureVisitor {
    169                 static size_t traceId;
    170 
    171                 Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
    172 
    173                 const Type * postvisit( const TypeInstType * aggregateUseType );
    174 
    175                 /// Records type variable bindings from forall-statements
    176                 void previsit( const FunctionType * type );
    177                 /// Records type variable bindings from forall-statements and instantiations of generic types
    178                 // void handleAggregateType( const BaseInstType * type );
    179 
    180                 // void previsit( const StructInstType * aggregateUseType );
    181                 // void previsit( const UnionInstType * aggregateUseType );
    182 
    183                 const TypeSubstitution & sub;
    184                 int subCount = 0;
    185                 bool freeOnly;
    186                 typedef std::unordered_set< TypeEnvKey > BoundVarsType;
    187                 BoundVarsType boundVars;
    188 
    189 };
    190 
    191 template< typename SynTreeClass >
    192 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const {
    193         assert( input );
    194         Pass<Substituter> sub( *this, false );
    195         input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    196         return { input, sub.core.subCount };
    197 }
    198 
    199 template< typename SynTreeClass >
    200 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const {
    201         assert( input );
    202         Pass<Substituter> sub( *this, true );
    203         input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );
    204         return { input, sub.core.subCount };
    205 }
    206 
    207 } // namespace ast
    208 
    209168// Local Variables: //
    210169// tab-width: 4 //
  • src/AST/Util.cpp

    r2b78949 r8a930c03  
    8383}
    8484
     85/// Check that the MemberExpr has an aggregate type and matching member.
     86void memberMatchesAggregate( const MemberExpr * expr ) {
     87        const Type * aggrType = expr->aggregate->result->stripReferences();
     88        const AggregateDecl * decl = nullptr;
     89        if ( auto inst = dynamic_cast<const StructInstType *>( aggrType ) ) {
     90                decl = inst->base;
     91        } else if ( auto inst = dynamic_cast<const UnionInstType *>( aggrType ) ) {
     92                decl = inst->base;
     93        }
     94        assertf( decl, "Aggregate of member not correct type." );
     95
     96        for ( auto aggrMember : decl->members ) {
     97                if ( expr->member == aggrMember ) {
     98                        return;
     99                }
     100        }
     101        assertf( false, "Member not found." );
     102}
     103
    85104struct InvariantCore {
    86105        // To save on the number of visits: this is a kind of composed core.
     
    108127        }
    109128
     129        void previsit( const MemberExpr * node ) {
     130                previsit( (const ParseNode *)node );
     131                memberMatchesAggregate( node );
     132        }
     133
    110134        void postvisit( const Node * node ) {
    111135                no_strong_cycles.postvisit( node );
  • src/Concurrency/Actors.cpp

    r2b78949 r8a930c03  
    3838    bool namedDecl = false;
    3939
    40     // finds and sets a ptr to the Allocation enum, which is needed in the next pass
     40    // finds and sets a ptr to the allocation enum, which is needed in the next pass
    4141    void previsit( const EnumDecl * decl ) {
    42         if( decl->name == "Allocation" ) *allocationDecl = decl;
     42        if( decl->name == "allocation" ) *allocationDecl = decl;
    4343    }
    4444
     
    227227                static inline derived_actor & ?|?( derived_actor & receiver, derived_msg & msg ) {
    228228                    request new_req;
    229                     Allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
     229                    allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
    230230                    __receive_fn fn = (__receive_fn)my_work_fn;
    231231                    new_req{ &receiver, &msg, fn };
     
    246246            ));
    247247           
    248             // Function type is: Allocation (*)( derived_actor &, derived_msg & )
     248            // Function type is: allocation (*)( derived_actor &, derived_msg & )
    249249            FunctionType * derivedReceive = new FunctionType();
    250250            derivedReceive->params.push_back( ast::deepCopy( derivedActorRef ) );
     
    252252            derivedReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
    253253
    254             // Generates: Allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
     254            // Generates: allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
    255255            sendBody->push_back( new DeclStmt(
    256256                decl->location,
     
    263263            ));
    264264
    265             // Function type is: Allocation (*)( actor &, message & )
     265            // Function type is: allocation (*)( actor &, message & )
    266266            FunctionType * genericReceive = new FunctionType();
    267267            genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) );
     
    269269            genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
    270270
    271             // Generates: Allocation (*fn)( actor &, message & ) = (Allocation (*)( actor &, message & ))my_work_fn;
     271            // Generates: allocation (*fn)( actor &, message & ) = (allocation (*)( actor &, message & ))my_work_fn;
    272272            // More readable synonymous code:
    273             //     typedef Allocation (*__receive_fn)(actor &, message &);
     273            //     typedef allocation (*__receive_fn)(actor &, message &);
    274274            //     __receive_fn fn = (__receive_fn)my_work_fn;
    275275            sendBody->push_back( new DeclStmt(
     
    422422    const StructDecl ** msgDecl = &msgDeclPtr;
    423423
    424     // first pass collects ptrs to Allocation enum, request type, and generic receive fn typedef
     424    // first pass collects ptrs to allocation enum, request type, and generic receive fn typedef
    425425    // also populates maps of all derived actors and messages
    426426    Pass<CollectactorStructDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,
  • src/Concurrency/Waituntil.cpp

    r2b78949 r8a930c03  
    1414//
    1515
     16#include "Waituntil.hpp"
     17
    1618#include <string>
    1719
    18 #include "Waituntil.hpp"
     20#include "AST/Copy.hpp"
    1921#include "AST/Expr.hpp"
    2022#include "AST/Pass.hpp"
     
    9395                        case 0:
    9496                            try {
    95                                 if (on_selected( A, clause1 ))
     97                                    on_selected( A, clause1 );
    9698                                    doA();
    9799                            }
     
    120122        // the unregister and on_selected calls are needed to support primitives where the acquire has side effects
    121123        // so the corresponding block MUST be run for those primitives to not lose state (example is channels)
    122         if ( ! has_run(clause_statuses[0]) && whenA && unregister_select(A, clause1) && on_selected( A, clause1 ) )
     124        if ( !has_run(clause_statuses[0]) && whenA && unregister_select(A, clause1) )
     125            on_selected( A, clause1 )
    123126            doA();
    124127        ... repeat if above for B and C ...
     
    617620
    618621// Generates:
    619 /* if ( on_selected( target_1, node_1 )) ... corresponding body of target_1 ...
     622/* on_selected( target_1, node_1 ); ... corresponding body of target_1 ...
    620623*/
    621624CompoundStmt * GenerateWaitUntilCore::genStmtBlock( const WhenClause * clause, const ClauseData * data ) {
     
    623626    return new CompoundStmt( cLoc,
    624627        {
    625             new IfStmt( cLoc,
    626                 genSelectTraitCall( clause, data, "on_selected" ),
    627                 new CompoundStmt( cLoc,
    628                     {
    629                         ast::deepCopy( clause->stmt )
    630                     }
    631                 )
    632             )
     628            new ExprStmt( cLoc,
     629                genSelectTraitCall( clause, data, "on_selected" )
     630            ),
     631            ast::deepCopy( clause->stmt )
    633632        }
    634633    );
     
    642641            case 0:
    643642                try {
    644                     if (on_selected( target1, clause1 ))
    645                         dotarget1stmt();
     643                    on_selected( target1, clause1 );
     644                    dotarget1stmt();
    646645                }
    647646                finally { clause_statuses[i] = __SELECT_RUN; unregister_select(target1, clause1); }
     
    662661        case 0:
    663662            try {
    664                 if (on_selected( target1, clause1 ))
    665                     dotarget1stmt();
     663                on_selected( target1, clause1 );
     664                dotarget1stmt();
    666665            }
    667666            finally { clause_statuses[i] = __SELECT_RUN; unregister_select(target1, clause1); }
     
    938937        }
    939938
    940     // C_TODO: will remove this commented code later. Currently it isn't needed but may switch to a modified version of this later if it has better performance
    941     // std::vector<ptr<CaseClause>> switchCases;
    942 
    943     // int idx = 0;
    944     // for ( const auto & clause: stmt->clauses ) {
    945     //     const CodeLocation & cLoc = clause->location;
    946     //     switchCases.push_back(
    947     //         new CaseClause( cLoc,
    948     //             new CastExpr( cLoc,
    949     //                 new AddressExpr( cLoc, new NameExpr( cLoc, data.at(idx)->targetName ) ),
    950     //                 new BasicType( BasicType::Kind::LongUnsignedInt ), GeneratedFlag::ExplicitCast
    951     //             ),
    952     //             {
    953     //                 new CompoundStmt( cLoc,
    954     //                     {
    955     //                         ast::deepCopy( clause->stmt ),
    956     //                         new BranchStmt( cLoc, BranchStmt::Kind::Break, Label( cLoc ) )
    957     //                     }
    958     //                 )
    959     //             }
    960     //         )
    961     //     );
    962     //     idx++;
    963     // }
    964 
    965939    return new CompoundStmt( loc,
    966940        {
    967941            new ExprStmt( loc, new UntypedExpr( loc, new NameExpr( loc, "park" ) ) ),
    968942            outerIf
    969             // new SwitchStmt( loc,
    970             //     new NameExpr( loc, statusName ),
    971             //     std::move( switchCases )
    972             // )
    973943        }
    974944    );
     
    1013983    const CodeLocation & cLoc = stmt->clauses.at(idx)->location;
    1014984
     985    Expr * baseCond = genSelectTraitCall( stmt->clauses.at(idx), data.at(idx), "register_select" );
    1015986    Expr * ifCond;
    1016987
     
    1023994            ),
    1024995            new CastExpr( cLoc,
    1025                 genSelectTraitCall( stmt->clauses.at(idx), data.at(idx), "register_select" ),
     996                baseCond,
    1026997                new BasicType( BasicType::Kind::Bool ), GeneratedFlag::ExplicitCast
    1027998            ),
    1028999            LogicalFlag::AndExpr
    10291000        );
    1030     } else ifCond = genSelectTraitCall( stmt->clauses.at(idx), data.at(idx), "register_select" );
     1001    } else ifCond = baseCond;
    10311002
    10321003    return new CompoundStmt( cLoc,
     
    10461017                ifCond,
    10471018                genStmtBlock( stmt->clauses.at(idx), data.at(idx) ),
    1048                 // ast::deepCopy( stmt->clauses.at(idx)->stmt ),
    10491019                recursiveOrIfGen( stmt, data, idx + 1, elseWhenName )
    10501020            )
  • src/ControlStruct/ExceptDeclNew.cpp

    r2b78949 r8a930c03  
    1818#include <sstream>
    1919
     20#include "AST/Copy.hpp"
    2021#include "AST/Decl.hpp"
    2122#include "AST/Pass.hpp"
  • src/GenPoly/InstantiateGenericNew.cpp

    r2b78949 r8a930c03  
    362362                        ResolvExpr::typesCompatible(
    363363                                memberExpr->result,
    364                                 memberExpr->member->get_type(), ast::SymbolTable() ) ) {
     364                                memberExpr->member->get_type() ) ) {
    365365                return memberExpr;
    366366        }
  • src/GenPoly/LvalueNew.cpp

    r2b78949 r8a930c03  
    359359                                !ResolvExpr::typesCompatible(
    360360                                        srcType,
    361                                         strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base,
    362                                         ast::SymbolTable() ) ) {
     361                                        strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base ) ) {
    363362                        // Must keep cast if cast-to type is different from the actual type.
    364363                        return ast::mutate_field( expr, &ast::CastExpr::arg, ret );
     
    377376                if ( !ResolvExpr::typesCompatibleIgnoreQualifiers(
    378377                                dstType->stripReferences(),
    379                                 srcType->stripReferences(),
    380                                 ast::SymbolTable() ) ) {
     378                                srcType->stripReferences() ) ) {
    381379                        return ast::mutate_field( expr, &ast::CastExpr::arg, ret );
    382380                }
     
    393391                                ResolvExpr::typesCompatible(
    394392                                        expr->result,
    395                                         expr->arg->result, ast::SymbolTable() ) ) {
     393                                        expr->arg->result ) ) {
    396394                        PRINT(
    397395                                std::cerr << "types are compatible, removing cast: " << expr << '\n';
     
    590588                ast::OpenVarSet openVars;
    591589                ResolvExpr::unify( ret->arg2->result, ret->arg3->result, newEnv,
    592                         needAssertions, haveAssertions, openVars,
    593                         ast::SymbolTable(), common );
     590                        needAssertions, haveAssertions, openVars, common );
    594591                ret->result = common ? common : ast::deepCopy( ret->arg2->result );
    595592                return ret;
  • src/GenPoly/SpecializeNew.cpp

    r2b78949 r8a930c03  
    1616#include "Specialize.h"
    1717
     18#include "AST/Copy.hpp"                  // for deepCopy
    1819#include "AST/Inspect.hpp"               // for isIntrinsicCallExpr
    1920#include "AST/Pass.hpp"                  // for Pass
  • src/InitTweak/InitTweak.cc

    r2b78949 r8a930c03  
    10661066        const ast::Type * t2 = ftype->params.back();
    10671067
    1068         return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable() );
     1068        return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2 );
    10691069}
    10701070
  • src/MakeLibCfaNew.cpp

    r2b78949 r8a930c03  
    1616#include "MakeLibCfa.h"
    1717
     18#include "AST/Copy.hpp"
    1819#include "AST/Fwd.hpp"
    1920#include "AST/Pass.hpp"
  • src/Parser/lex.ll

    r2b78949 r8a930c03  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Tue May  2 08:45:21 2023
    13  * Update Count     : 769
     12 * Last Modified On : Fri Jun  9 10:04:00 2023
     13 * Update Count     : 770
    1414 */
    1515
     
    319319static                  { KEYWORD_RETURN(STATIC); }
    320320_Static_assert  { KEYWORD_RETURN(STATICASSERT); }               // C11
     321_static_assert  { KEYWORD_RETURN(STATICASSERT); }               // C23
    321322struct                  { KEYWORD_RETURN(STRUCT); }
    322323suspend                 { KEYWORD_RETURN(SUSPEND); }                    // CFA
  • src/Parser/parser.yy

    r2b78949 r8a930c03  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Apr 26 16:45:37 2023
    13 // Update Count     : 6330
     12// Last Modified On : Wed Jun  7 14:32:28 2023
     13// Update Count     : 6341
    1414//
    1515
     
    108108        assert( declList );
    109109        // printf( "distAttr1 typeSpec %p\n", typeSpec ); typeSpec->print( std::cout );
    110         DeclarationNode * cur = declList, * cl = (new DeclarationNode)->addType( typeSpec );
     110        DeclarationNode * cl = (new DeclarationNode)->addType( typeSpec );
    111111        // printf( "distAttr2 cl %p\n", cl ); cl->type->print( std::cout );
    112112        // cl->type->aggregate.name = cl->type->aggInst.aggregate->aggregate.name;
    113113
    114         for ( cur = dynamic_cast<DeclarationNode *>( cur->get_next() ); cur != nullptr; cur = dynamic_cast<DeclarationNode *>( cur->get_next() ) ) {
     114        for ( DeclarationNode * cur = dynamic_cast<DeclarationNode *>( declList->get_next() ); cur != nullptr; cur = dynamic_cast<DeclarationNode *>( cur->get_next() ) ) {
    115115                cl->cloneBaseType( cur );
    116116        } // for
     
    206206#define NEW_ONE  new ExpressionNode( build_constantInteger( yylloc, *new string( "1" ) ) )
    207207#define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right)
    208 #define MISSING_ANON_FIELD "Missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body."
    209 #define MISSING_LOW "Missing low value for up-to range so index is uninitialized."
    210 #define MISSING_HIGH "Missing high value for down-to range so index is uninitialized."
     208#define MISSING_ANON_FIELD "syntax error, missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body."
     209#define MISSING_LOW "syntax error, missing low value for up-to range so index is uninitialized."
     210#define MISSING_HIGH "syntax error, missing high value for down-to range so index is uninitialized."
    211211
    212212static ForCtrl * makeForCtrl(
     
    232232ForCtrl * forCtrl( const CodeLocation & location, DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
    233233        if ( index->initializer ) {
    234                 SemanticError( yylloc, "Direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." );
     234                SemanticError( yylloc, "syntax error, direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." );
    235235        } // if
    236236        if ( index->next ) {
    237                 SemanticError( yylloc, "Multiple loop indexes disallowed in for-loop declaration." );
     237                SemanticError( yylloc, "syntax error, multiple loop indexes disallowed in for-loop declaration." );
    238238        } // if
    239239        DeclarationNode * initDecl = index->addInitializer( new InitializerNode( start ) );
     
    260260                        return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc );
    261261                } else {
    262                         SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr;
     262                        SemanticError( yylloc, "syntax error, loop-index name missing. Expression disallowed." ); return nullptr;
    263263                } // if
    264264        } else {
    265                 SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr;
     265                SemanticError( yylloc, "syntax error, loop-index name missing. Expression disallowed. ." ); return nullptr;
    266266        } // if
    267267} // forCtrl
    268268
    269269static void IdentifierBeforeIdentifier( string & identifier1, string & identifier2, const char * kind ) {
    270         SemanticError( yylloc, ::toString( "Adjacent identifiers \"", identifier1, "\" and \"", identifier2, "\" are not meaningful in a", kind, ".\n"
     270        SemanticError( yylloc, ::toString( "syntax error, adjacent identifiers \"", identifier1, "\" and \"", identifier2, "\" are not meaningful in a", kind, ".\n"
    271271                                   "Possible cause is misspelled type name or missing generic parameter." ) );
    272272} // IdentifierBeforeIdentifier
    273273
    274274static void IdentifierBeforeType( string & identifier, const char * kind ) {
    275         SemanticError( yylloc, ::toString( "Identifier \"", identifier, "\" cannot appear before a ", kind, ".\n"
     275        SemanticError( yylloc, ::toString( "syntax error, identifier \"", identifier, "\" cannot appear before a ", kind, ".\n"
    276276                                   "Possible cause is misspelled storage/CV qualifier, misspelled typename, or missing generic parameter." ) );
    277277} // IdentifierBeforeType
     
    689689        // | RESUME '(' comma_expression ')' compound_statement
    690690        //      { SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; }
    691         | IDENTIFIER IDENTIFIER                                                         // syntax error
     691        | IDENTIFIER IDENTIFIER                                                         // invalid syntax rules
    692692                { IdentifierBeforeIdentifier( *$1.str, *$2.str, "n expression" ); $$ = nullptr; }
    693         | IDENTIFIER type_qualifier                                                     // syntax error
     693        | IDENTIFIER type_qualifier                                                     // invalid syntax rules
    694694                { IdentifierBeforeType( *$1.str, "type qualifier" ); $$ = nullptr; }
    695         | IDENTIFIER storage_class                                                      // syntax error
     695        | IDENTIFIER storage_class                                                      // invalid syntax rules
    696696                { IdentifierBeforeType( *$1.str, "storage class" ); $$ = nullptr; }
    697         | IDENTIFIER basic_type_name                                            // syntax error
     697        | IDENTIFIER basic_type_name                                            // invalid syntax rules
    698698                { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
    699         | IDENTIFIER TYPEDEFname                                                        // syntax error
     699        | IDENTIFIER TYPEDEFname                                                        // invalid syntax rules
    700700                { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
    701         | IDENTIFIER TYPEGENname                                                        // syntax error
     701        | IDENTIFIER TYPEGENname                                                        // invalid syntax rules
    702702                { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
    703703        ;
     
    11521152        identifier_or_type_name ':' attribute_list_opt statement
    11531153                { $$ = $4->add_label( yylloc, $1, $3 ); }
    1154         | identifier_or_type_name ':' attribute_list_opt error // syntax error
    1155                 {
    1156                         SemanticError( yylloc, ::toString( "Label \"", *$1.str, "\" must be associated with a statement, "
     1154        | identifier_or_type_name ':' attribute_list_opt error // invalid syntax rule
     1155                {
     1156                        SemanticError( yylloc, ::toString( "syntx error, label \"", *$1.str, "\" must be associated with a statement, "
    11571157                                                                                           "where a declaration, case, or default is not a statement. "
    11581158                                                                                           "Move the label or terminate with a semi-colon." ) );
     
    11931193        | statement_list_nodecl statement
    11941194                { assert( $1 ); $1->set_last( $2 ); $$ = $1; }
    1195         | statement_list_nodecl error                                           // syntax error
    1196                 { SemanticError( yylloc, "Declarations only allowed at the start of the switch body, i.e., after the '{'." ); $$ = nullptr; }
     1195        | statement_list_nodecl error                                           // invalid syntax rule
     1196                { SemanticError( yylloc, "syntax error, declarations only allowed at the start of the switch body, i.e., after the '{'." ); $$ = nullptr; }
    11971197        ;
    11981198
     
    12191219                        $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    12201220                }
    1221         | SWITCH '(' comma_expression ')' '{' error '}'         // CFA, syntax error
    1222                 { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; }
     1221        | SWITCH '(' comma_expression ')' '{' error '}'         // CFA, invalid syntax rule error
     1222                { SemanticError( yylloc, "synatx error, declarations can only appear before the list of case clauses." ); $$ = nullptr; }
    12231223        | CHOOSE '(' comma_expression ')' case_clause           // CFA
    12241224                { $$ = new StatementNode( build_switch( yylloc, false, $3, $5 ) ); }
     
    12281228                        $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    12291229                }
    1230         | CHOOSE '(' comma_expression ')' '{' error '}'         // CFA, syntax error
    1231                 { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; }
     1230        | CHOOSE '(' comma_expression ')' '{' error '}'         // CFA, invalid syntax rule
     1231                { SemanticError( yylloc, "syntax error, declarations can only appear before the list of case clauses." ); $$ = nullptr; }
    12321232        ;
    12331233
     
    12681268
    12691269case_label:                                                                                             // CFA
    1270         CASE error                                                                                      // syntax error
    1271                 { SemanticError( yylloc, "Missing case list after case." ); $$ = nullptr; }
     1270        CASE error                                                                                      // invalid syntax rule
     1271                { SemanticError( yylloc, "syntax error, case list missing after case." ); $$ = nullptr; }
    12721272        | CASE case_value_list ':'                                      { $$ = $2; }
    1273         | CASE case_value_list error                                            // syntax error
    1274                 { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; }
     1273        | CASE case_value_list error                                            // invalid syntax rule
     1274                { SemanticError( yylloc, "syntax error, colon missing after case list." ); $$ = nullptr; }
    12751275        | DEFAULT ':'                                                           { $$ = new ClauseNode( build_default( yylloc ) ); }
    12761276                // A semantic check is required to ensure only one default clause per switch/choose statement.
    1277         | DEFAULT error                                                                         //  syntax error
    1278                 { SemanticError( yylloc, "Missing colon after default." ); $$ = nullptr; }
     1277        | DEFAULT error                                                                         //  invalid syntax rules
     1278                { SemanticError( yylloc, "syntax error, colon missing after default." ); $$ = nullptr; }
    12791279        ;
    12801280
     
    14051405                        else { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14061406                }
    1407         | comma_expression updowneq comma_expression '~' '@' // CFA, error
     1407        | comma_expression updowneq comma_expression '~' '@' // CFA, invalid syntax rules
    14081408                { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
    1409         | '@' updowneq '@'                                                                      // CFA, error
     1409        | '@' updowneq '@'                                                                      // CFA, invalid syntax rules
    14101410                { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
    1411         | '@' updowneq comma_expression '~' '@'                         // CFA, error
     1411        | '@' updowneq comma_expression '~' '@'                         // CFA, invalid syntax rules
    14121412                { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
    1413         | comma_expression updowneq '@' '~' '@'                         // CFA, error
     1413        | comma_expression updowneq '@' '~' '@'                         // CFA, invalid syntax rules
    14141414                { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
    1415         | '@' updowneq '@' '~' '@'                                                      // CFA, error
     1415        | '@' updowneq '@' '~' '@'                                                      // CFA, invalid syntax rules
    14161416                { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; }
    14171417
     
    14311431                {
    14321432                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    1433                         else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1433                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    14341434                        else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, NEW_ONE );
    14351435                }
    1436         | comma_expression ';' '@' updowneq '@'                         // CFA, error
    1437                 { SemanticError( yylloc, "Missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
     1436        | comma_expression ';' '@' updowneq '@'                         // CFA, invalid syntax rules
     1437                { SemanticError( yylloc, "syntax error, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
    14381438
    14391439        | comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA
    14401440                { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }
    1441         | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, error
     1441        | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, invalid syntax rules
    14421442                {
    14431443                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
     
    14471447                {
    14481448                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    1449                         else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1449                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    14501450                        else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, $7 );
    14511451                }
    14521452        | comma_expression ';' comma_expression updowneq comma_expression '~' '@' // CFA
    14531453                { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }
    1454         | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, error
     1454        | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, invalid syntax rules
    14551455                {
    14561456                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
     
    14601460                {
    14611461                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    1462                         else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1462                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    14631463                        else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, nullptr );
    14641464                }
    14651465        | comma_expression ';' '@' updowneq '@' '~' '@' // CFA
    1466                 { SemanticError( yylloc, "Missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
     1466                { SemanticError( yylloc, "syntax error, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
    14671467
    14681468        | declaration comma_expression                                          // CFA
     
    14811481                {
    14821482                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    1483                         else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1483                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    14841484                        else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, NEW_ONE );
    14851485                }
     
    14951495                {
    14961496                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    1497                         else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1497                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    14981498                        else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, $6 );
    14991499                }
     
    15081508                {
    15091509                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    1510                         else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
     1510                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    15111511                        else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, nullptr );
    15121512                }
    1513         | declaration '@' updowneq '@' '~' '@'                          // CFA, error
    1514                 { SemanticError( yylloc, "Missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
     1513        | declaration '@' updowneq '@' '~' '@'                          // CFA, invalid syntax rules
     1514                { SemanticError( yylloc, "syntax error, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }
    15151515
    15161516        | comma_expression ';' TYPEDEFname                                      // CFA, array type
     
    15211521        | comma_expression ';' downupdowneq TYPEDEFname         // CFA, array type
    15221522                {
    1523                         if ( $3 == OperKinds::LEThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, "All enumation ranges are equal (all values). Remove \"=~\"." ); $$ = nullptr; }
     1523                        if ( $3 == OperKinds::LEThan || $3 == OperKinds::GEThan ) {
     1524                                SemanticError( yylloc, "syntax error, all enumeration ranges are equal (all values). Remove \"=~\"." ); $$ = nullptr;
     1525                        }
    15241526                        SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr;
    15251527                }
     
    16161618        MUTEX '(' argument_expression_list_opt ')' statement
    16171619                {
    1618                         if ( ! $3 ) { SemanticError( yylloc, "mutex argument list cannot be empty." ); $$ = nullptr; }
     1620                        if ( ! $3 ) { SemanticError( yylloc, "syntax error, mutex argument list cannot be empty." ); $$ = nullptr; }
    16191621                        $$ = new StatementNode( build_mutex( yylloc, $3, $5 ) );
    16201622                }
     
    16641666                { $$ = build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); }
    16651667        // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    1666         | wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
    1667                 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
     1668        | wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // invalid syntax rules
     1669                { SemanticError( yylloc, "syntax error, else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    16681670        | wor_waitfor_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
    16691671                { $$ = build_waitfor_else( yylloc, build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ), $7, maybe_build_compound( yylloc, $9 ) ); }
     
    17091711                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ) ); }
    17101712        // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    1711         | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
    1712                 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
     1713        | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // invalid syntax rules
     1714                { SemanticError( yylloc, "syntax error, else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    17131715        | wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
    17141716                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1,
     
    20652067                        assert( $1->type );
    20662068                        if ( $1->type->qualifiers.any() ) {                     // CV qualifiers ?
    2067                                 SemanticError( yylloc, "Useless type qualifier(s) in empty declaration." ); $$ = nullptr;
     2069                                SemanticError( yylloc, "syntax error, useless type qualifier(s) in empty declaration." ); $$ = nullptr;
    20682070                        }
    20692071                        // enums are never empty declarations because there must have at least one enumeration.
    20702072                        if ( $1->type->kind == TypeData::AggregateInst && $1->storageClasses.any() ) { // storage class ?
    2071                                 SemanticError( yylloc, "Useless storage qualifier(s) in empty aggregate declaration." ); $$ = nullptr;
     2073                                SemanticError( yylloc, "syntax error, useless storage qualifier(s) in empty aggregate declaration." ); $$ = nullptr;
    20722074                        }
    20732075                }
     
    21002102        | type_declaration_specifier
    21012103        | sue_declaration_specifier
    2102         | sue_declaration_specifier invalid_types
    2103                 {
    2104                         SemanticError( yylloc, ::toString( "Missing ';' after end of ",
     2104        | sue_declaration_specifier invalid_types                       // invalid syntax rule
     2105                {
     2106                        SemanticError( yylloc, ::toString( "syntax error, expecting ';' at end of ",
    21052107                                $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ),
    2106                                 " declaration" ) );
     2108                                " declaration." ) );
    21072109                        $$ = nullptr;
    21082110                }
     
    25842586                        // } // for
    25852587                }
     2588        | type_specifier field_declaring_list_opt '}'           // invalid syntax rule
     2589                {
     2590                        SemanticError( yylloc, ::toString( "syntax error, expecting ';' at end of previous declaration." ) );
     2591                        $$ = nullptr;
     2592                }
    25862593        | EXTENSION type_specifier field_declaring_list_opt ';' // GCC
    25872594                { $$ = fieldDecl( $2, $3 ); distExt( $$ ); }
     
    26822689        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}'
    26832690                {
    2684                         if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() )
    2685                         { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    2686 
     2691                        if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() ) {
     2692                                SemanticError( yylloc, "syntax error, storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." );
     2693                        }
    26872694                        $$ = DeclarationNode::newEnum( nullptr, $7, true, true, $3 )->addQualifiers( $5 );
    26882695                }
    26892696        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt
    26902697                {
    2691                         if ( $3->storageClasses.any() || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
     2698                        if ( $3->storageClasses.any() || $3->type->qualifiers.val != 0 ) {
     2699                                SemanticError( yylloc, "syntax error, storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." );
     2700                        }
    26922701                        typedefTable.makeTypedef( *$6 );
    26932702                }
     
    31543163        | IDENTIFIER IDENTIFIER
    31553164                { IdentifierBeforeIdentifier( *$1.str, *$2.str, " declaration" ); $$ = nullptr; }
    3156         | IDENTIFIER type_qualifier                                                     // syntax error
     3165        | IDENTIFIER type_qualifier                                                     // invalid syntax rules
    31573166                { IdentifierBeforeType( *$1.str, "type qualifier" ); $$ = nullptr; }
    3158         | IDENTIFIER storage_class                                                      // syntax error
     3167        | IDENTIFIER storage_class                                                      // invalid syntax rules
    31593168                { IdentifierBeforeType( *$1.str, "storage class" ); $$ = nullptr; }
    3160         | IDENTIFIER basic_type_name                                            // syntax error
     3169        | IDENTIFIER basic_type_name                                            // invalid syntax rules
    31613170                { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
    3162         | IDENTIFIER TYPEDEFname                                                        // syntax error
     3171        | IDENTIFIER TYPEDEFname                                                        // invalid syntax rules
    31633172                { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
    3164         | IDENTIFIER TYPEGENname                                                        // syntax error
     3173        | IDENTIFIER TYPEGENname                                                        // invalid syntax rules
    31653174                { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; }
    31663175        | external_function_definition
     
    31973206        | type_qualifier_list
    31983207                {
    3199                         if ( $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
     3208                        if ( $1->type->qualifiers.any() ) {
     3209                                SemanticError( yylloc, "syntax error, CV qualifiers cannot be distributed; only storage-class and forall qualifiers." );
     3210                        }
    32003211                        if ( $1->type->forall ) forall = true;          // remember generic type
    32013212                }
     
    32083219        | declaration_qualifier_list
    32093220                {
    3210                         if ( $1->type && $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
     3221                        if ( $1->type && $1->type->qualifiers.any() ) {
     3222                                SemanticError( yylloc, "syntax error, CV qualifiers cannot be distributed; only storage-class and forall qualifiers." );
     3223                        }
    32113224                        if ( $1->type && $1->type->forall ) forall = true; // remember generic type
    32123225                }
     
    32193232        | declaration_qualifier_list type_qualifier_list
    32203233                {
    3221                         if ( ($1->type && $1->type->qualifiers.any()) || ($2->type && $2->type->qualifiers.any()) ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
     3234                        if ( ($1->type && $1->type->qualifiers.any()) || ($2->type && $2->type->qualifiers.any()) ) {
     3235                                SemanticError( yylloc, "syntax error, CV qualifiers cannot be distributed; only storage-class and forall qualifiers." );
     3236                        }
    32223237                        if ( ($1->type && $1->type->forall) || ($2->type && $2->type->forall) ) forall = true; // remember generic type
    32233238                }
     
    32503265                        $$ = $3; forall = false;
    32513266                        if ( $5 ) {
    3252                                 SemanticError( yylloc, "Attributes cannot be associated with function body. Move attribute(s) before \"with\" clause." );
     3267                                SemanticError( yylloc, "syntax error, attributes cannot be associated with function body. Move attribute(s) before \"with\" clause." );
    32533268                                $$ = nullptr;
    32543269                        } // if
  • src/ResolvExpr/CandidateFinder.cpp

    r2b78949 r8a930c03  
    373373                                                        unify(
    374374                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    375                                                                 newResult.open, symtab )
     375                                                                newResult.open )
    376376                                                ) {
    377377                                                        finalResults.emplace_back( std::move( newResult ) );
     
    444444                                )
    445445
    446                                 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {
     446                                if ( unify( paramType, argType, env, need, have, open ) ) {
    447447                                        unsigned nextExpl = results[i].nextExpl + 1;
    448448                                        if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }
     
    463463                                        ast::OpenVarSet open = results[i].open;
    464464
    465                                         if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
     465                                        if ( unify( paramType, cnst->result, env, need, have, open ) ) {
    466466                                                results.emplace_back(
    467467                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ),
     
    506506
    507507                                // attempt to unify types
    508                                 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {
     508                                if ( unify( paramType, argType, env, need, have, open ) ) {
    509509                                        // add new result
    510510                                        results.emplace_back(
     
    750750                        const ast::Type * returnType = funcType->returns.front();
    751751                        if ( ! unify(
    752                                 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
     752                                returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen )
    753753                        ) {
    754754                                // unification failed, do not pursue this candidate
     
    11591159
    11601160                        // unification run for side-effects
    1161                         unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
     1161                        unify( toType, cand->expr->result, cand->env, need, have, open );
    11621162                        Cost thisCost =
    11631163                                (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast)
     
    14831483                                        if (
    14841484                                                unify(
    1485                                                         r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1485                                                        r2->expr->result, r3->expr->result, env, need, have, open,
    14861486                                                        common )
    14871487                                        ) {
     
    15561556                                if (
    15571557                                        unify(
    1558                                                 r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1558                                                r1->expr->result, r2->expr->result, env, need, have, open,
    15591559                                                common )
    15601560                                ) {
     
    16591659
    16601660                                // unification run for side-effects
    1661                                 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab );
     1661                                bool canUnify = unify( toType, cand->expr->result, env, need, have, open );
    16621662                                (void) canUnify;
    16631663                                Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
  • src/ResolvExpr/CastCost.cc

    r2b78949 r8a930c03  
    165165                                if (
    166166                                        pointerType->qualifiers <= ptr->qualifiers
    167                                         && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab, env )
     167                                        && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, env )
    168168                                ) {
    169169                                        cost = Cost::safe;
     
    232232        )
    233233
    234         if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
     234        if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) {
    235235                PRINT( std::cerr << "compatible!" << std::endl; )
    236236                return Cost::zero;
  • src/ResolvExpr/CommonType.cc

    r2b78949 r8a930c03  
    2121
    2222#include "AST/Decl.hpp"
     23#include "AST/Pass.hpp"
    2324#include "AST/Type.hpp"
    2425#include "Common/PassVisitor.h"
     
    675676                const ast::Type * type2;
    676677                WidenMode widen;
    677                 const ast::SymbolTable & symtab;
    678678                ast::TypeEnvironment & tenv;
    679679                const ast::OpenVarSet & open;
     
    685685
    686686                CommonType_new(
    687                         const ast::Type * t2, WidenMode w, const ast::SymbolTable & st,
     687                        const ast::Type * t2, WidenMode w,
    688688                        ast::TypeEnvironment & env, const ast::OpenVarSet & o,
    689689                        ast::AssertionSet & need, ast::AssertionSet & have )
    690                 : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), need (need), have (have) ,result() {}
     690                : type2( t2 ), widen( w ), tenv( env ), open( o ), need (need), have (have) ,result() {}
    691691
    692692                void previsit( const ast::Node * ) { visit_children = false; }
     
    748748                                        ast::AssertionSet need, have;
    749749                                        if ( ! tenv.bindVar(
    750                                                 var, voidPtr->base, entry->second, need, have, open, widen, symtab )
     750                                                var, voidPtr->base, entry->second, need, have, open, widen )
    751751                                        ) return;
    752752                                }
     
    761761                                ast::OpenVarSet newOpen{ open };
    762762                                if (enumInst->base->base
    763                                 && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen, symtab)) {
     763                                && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen)) {
    764764                                        result = type1;
    765765                                        return true;
     
    798798
    799799                                        ast::OpenVarSet newOpen{ open };
    800                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     800                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() ) ) {
    801801                                                result = pointer;
    802802                                                if ( q1.val != q2.val ) {
     
    841841                                                                if (unifyExact(
    842842                                                                        arg1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open,
    843                                                                         noWiden(), symtab )) {
     843                                                                        noWiden() )) {
    844844                                                                                break;
    845845
     
    850850                                                                if (unifyExact(
    851851                                                                        tupleFromTypes( crnt1, end1 ), arg2, tenv, need, have, open,
    852                                                                         noWiden(), symtab )) {
     852                                                                        noWiden() )) {
    853853                                                                                break;
    854854
     
    874874
    875875                                                                                if ( ! unifyExact(
    876                                                                                         base1, base2, tenv, need, have, open, noWiden(), symtab )
     876                                                                                        base1, base2, tenv, need, have, open, noWiden() )
    877877                                                                                ) return;
    878878                                                                        }       
     
    894894
    895895                                                                                if ( ! unifyExact(
    896                                                                                         base1, base2, tenv, need, have, open, noWiden(), symtab )
     896                                                                                        base1, base2, tenv, need, have, open, noWiden() )
    897897                                                                                ) return;
    898898                                                                        }       
     
    902902                                                        }
    903903                                                        else if (! unifyExact(
    904                                                                 arg1, arg2, tenv, need, have, open, noWiden(), symtab )) return;
     904                                                                arg1, arg2, tenv, need, have, open, noWiden() )) return;
    905905
    906906                                                        ++crnt1; ++crnt2;
     
    912912                                                        if (! unifyExact(
    913913                                                                t1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open,
    914                                                                 noWiden(), symtab )) return;
     914                                                                noWiden() )) return;
    915915                                                } else if ( crnt2 != end2 ) {
    916916                                                        // try unifying empty tuple with ttype
     
    919919                                                        if (! unifyExact(
    920920                                                                tupleFromTypes( crnt1, end1 ), t2, tenv, need, have, open,
    921                                                                 noWiden(), symtab )) return;
     921                                                                noWiden() )) return;
    922922                                                }
    923923                                                if ((f1->returns.size() == 0 && f2->returns.size() == 0)
    924                                                   || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden(), symtab))) {
     924                                                  || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden()))) {
    925925                                                        result = pointer;
    926926
     
    979979
    980980                                        ast::OpenVarSet newOpen{ open };
    981                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     981                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() ) ) {
    982982                                                result = ref;
    983983                                                if ( q1.val != q2.val ) {
     
    994994                        } else {
    995995                                if (!dynamic_cast<const ast::EnumInstType *>(type2))
    996                                         result = commonType( type2, ref, tenv, need, have, open, widen, symtab );
     996                                        result = commonType( type2, ref, tenv, need, have, open, widen );
    997997                        }
    998998                }
     
    10121012                void postvisit( const ast::EnumInstType * enumInst ) {
    10131013                        if (!dynamic_cast<const ast::EnumInstType *>(type2))
    1014                                 result = commonType( type2, enumInst, tenv, need, have, open, widen, symtab);
     1014                                result = commonType( type2, enumInst, tenv, need, have, open, widen);
    10151015                }
    10161016
    10171017                void postvisit( const ast::TraitInstType * ) {}
    10181018
    1019                 void postvisit( const ast::TypeInstType * inst ) {
    1020                         if ( ! widen.first ) return;
    1021                         if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
    1022                                 if ( const ast::Type * base =
    1023                                                 strict_dynamic_cast< const ast::TypeDecl * >( nt )->base
    1024                                 ) {
    1025                                         ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers;
    1026 
    1027                                         // force t{1,2} to be cloned if their qualifiers must be mutated
    1028                                         ast::ptr< ast::Type > t1{ base }, t2{ type2 };
    1029                                         reset_qualifiers( t1, q1 );
    1030                                         reset_qualifiers( t2 );
    1031 
    1032                                         ast::OpenVarSet newOpen{ open };
    1033                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
    1034                                                 result = type2;
    1035                                                 reset_qualifiers( result, q1 | q2 );
    1036                                         } else {
    1037                                                 tryResolveWithTypedEnum( t1 );
    1038                                         }
    1039                                 }
    1040                         }
    1041                 }
    1042 
    1043                 void postvisit( const ast::TupleType * tuple) {
     1019                void postvisit( const ast::TypeInstType * ) {}
     1020
     1021                void postvisit( const ast::TupleType * tuple ) {
    10441022                        tryResolveWithTypedEnum( tuple );
    10451023                }
     
    11021080                ast::ptr< ast::Type > handleReference(
    11031081                        const ast::ptr< ast::Type > & t1, const ast::ptr< ast::Type > & t2, WidenMode widen,
    1104                         const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
     1082                        ast::TypeEnvironment & env,
    11051083                        const ast::OpenVarSet & open
    11061084                ) {
     
    11101088
    11111089                        // need unify to bind type variables
    1112                         if ( unify( t1, t2, env, have, need, newOpen, symtab, common ) ) {
     1090                        if ( unify( t1, t2, env, have, need, newOpen, common ) ) {
    11131091                                ast::CV::Qualifiers q1 = t1->qualifiers, q2 = t2->qualifiers;
    11141092                                PRINT(
     
    11341112                        const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
    11351113                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1136                         const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab
     1114                        const ast::OpenVarSet & open, WidenMode widen
    11371115        ) {
    11381116                unsigned depth1 = type1->referenceDepth();
     
    11491127                        if ( depth1 > depth2 ) {
    11501128                                assert( ref1 );
    1151                                 result = handleReference( ref1->base, type2, widen, symtab, env, open );
     1129                                result = handleReference( ref1->base, type2, widen, env, open );
    11521130                        } else {  // implies depth1 < depth2
    11531131                                assert( ref2 );
    1154                                 result = handleReference( type1, ref2->base, widen, symtab, env, open );
     1132                                result = handleReference( type1, ref2->base, widen, env, open );
    11551133                        }
    11561134
     
    11701148                }
    11711149                // otherwise both are reference types of the same depth and this is handled by the visitor
    1172                 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open, need, have };
     1150                ast::Pass<CommonType_new> visitor{ type2, widen, env, open, need, have };
    11731151                type1->accept( visitor );
    1174                 ast::ptr< ast::Type > result = visitor.core.result;
    1175 
    1176                 // handling for opaque type declarations (?)
    1177                 if ( ! result && widen.second ) {
    1178                         if ( const ast::TypeInstType * inst = type2.as< ast::TypeInstType >() ) {
    1179                                 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
    1180                                         auto type = strict_dynamic_cast< const ast::TypeDecl * >( nt );
    1181                                         if ( type->base ) {
    1182                                                 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
    1183                                                 ast::OpenVarSet newOpen{ open };
    1184 
    1185                                                 // force t{1,2} to be cloned if its qualifiers must be stripped, so that
    1186                                                 // type1 and type->base are left unchanged; calling convention forces
    1187                                                 // {type1,type->base}->strong_ref >= 1
    1188                                                 ast::ptr<ast::Type> t1{ type1 }, t2{ type->base };
    1189                                                 reset_qualifiers( t1 );
    1190                                                 reset_qualifiers( t2, q1 );
    1191 
    1192                                                 if ( unifyExact( t1, t2, env, have, need, newOpen, noWiden(), symtab ) ) {
    1193                                                         result = t1;
    1194                                                         reset_qualifiers( result, q1 | q2 );
    1195                                                 }
    1196                                         }
    1197                                 }
    1198                         }
    1199                 }
    1200 
    1201                 return result;
     1152                // ast::ptr< ast::Type > result = visitor.core.result;
     1153
     1154                return visitor.core.result;
    12021155        }
    12031156
  • src/ResolvExpr/CommonType.hpp

    r2b78949 r8a930c03  
    3636        ast::TypeEnvironment & env,
    3737        ast::AssertionSet & need, ast::AssertionSet & have,
    38         const ast::OpenVarSet & open, WidenMode widen,
    39         const ast::SymbolTable & symtab );
     38        const ast::OpenVarSet & open, WidenMode widen);
    4039
    4140}
  • src/ResolvExpr/ConversionCost.cc

    r2b78949 r8a930c03  
    532532                }
    533533        }
    534         if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
     534        if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) {
    535535                return Cost::zero;
    536536        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
     
    566566                        ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
    567567                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
    568                                         srcAsRef->base, dstAsRef->base, symtab, env ) ) {
     568                                        srcAsRef->base, dstAsRef->base, env ) ) {
    569569                                if ( tq1 == tq2 ) {
    570570                                        return Cost::zero;
     
    587587                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
    588588                assert( dstAsRef );
    589                 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
     589                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, env ) ) {
    590590                        if ( srcIsLvalue ) {
    591591                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
     
    653653                ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
    654654                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
    655                                 pointerType->base, dstAsPtr->base, symtab, env ) ) {
     655                                pointerType->base, dstAsPtr->base, env ) ) {
    656656                        if ( tq1 == tq2 ) {
    657657                                cost = Cost::zero;
  • src/ResolvExpr/PolyCost.cc

    r2b78949 r8a930c03  
    1515
    1616#include "AST/SymbolTable.hpp"
     17#include "AST/Pass.hpp"
    1718#include "AST/Type.hpp"
    1819#include "AST/TypeEnvironment.hpp"
  • src/ResolvExpr/Resolver.cc

    r2b78949 r8a930c03  
    11061106
    11071107                /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)
    1108                 void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) {
     1108                void removeExtraneousCast( ast::ptr<ast::Expr> & expr ) {
    11091109                        if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
    1110                                 if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) {
     1110                                if ( typesCompatible( castExpr->arg->result, castExpr->result ) ) {
    11111111                                        // cast is to the same type as its argument, remove it
    11121112                                        swap_and_save_env( expr, castExpr->arg );
     
    11961196                ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
    11971197                ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context );
    1198                 removeExtraneousCast( newExpr, context.symtab );
     1198                removeExtraneousCast( newExpr );
    11991199                return newExpr;
    12001200        }
     
    12611261                static size_t traceId;
    12621262                Resolver_new( const ast::TranslationGlobal & global ) :
     1263                        ast::WithSymbolTable(ast::SymbolTable::ErrorDetection::ValidateOnAdd),
    12631264                        context{ symtab, global } {}
    12641265                Resolver_new( const ResolveContext & context ) :
     
    18341835                                                                if (
    18351836                                                                        ! unify(
    1836                                                                                 arg->expr->result, *param, resultEnv, need, have, open,
    1837                                                                                 symtab )
     1837                                                                                arg->expr->result, *param, resultEnv, need, have, open )
    18381838                                                                ) {
    18391839                                                                        // Type doesn't match
     
    20412041                const ast::Type * initContext = currentObject.getCurrentType();
    20422042
    2043                 removeExtraneousCast( newExpr, symtab );
     2043                removeExtraneousCast( newExpr );
    20442044
    20452045                // check if actual object's type is char[]
  • src/ResolvExpr/SatisfyAssertions.cpp

    r2b78949 r8a930c03  
    215215                        findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen );
    216216                        if ( allowConversion ) {
    217                                 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
     217                                if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
    218218                                        // set up binding slot for recursive assertions
    219219                                        ast::UniqueId crntResnSlot = 0;
     
    229229                        }
    230230                        else {
    231                                 if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
     231                                if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
    232232                                        // set up binding slot for recursive assertions
    233233                                        ast::UniqueId crntResnSlot = 0;
     
    392392                        mergeOpenVars( open, i.match.open );
    393393
    394                         if ( ! env.combine( i.match.env, open, symtab ) ) return false;
     394                        if ( ! env.combine( i.match.env, open ) ) return false;
    395395
    396396                        crnt.emplace_back( i );
  • src/ResolvExpr/Unify.cc

    r2b78949 r8a930c03  
    128128                const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    129129                ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    130                 WidenMode widen, const ast::SymbolTable & symtab );
     130                WidenMode widen );
    131131
    132132        bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     
    150150
    151151        bool typesCompatible(
    152                         const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
     152                        const ast::Type * first, const ast::Type * second,
    153153                        const ast::TypeEnvironment & env ) {
    154154                ast::TypeEnvironment newEnv;
     
    163163                findOpenVars( newSecond, open, closed, need, have, FirstOpen );
    164164
    165                 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     165                return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() );
    166166        }
    167167
     
    183183
    184184        bool typesCompatibleIgnoreQualifiers(
    185                         const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
     185                        const ast::Type * first, const ast::Type * second,
    186186                        const ast::TypeEnvironment & env ) {
    187187                ast::TypeEnvironment newEnv;
     
    216216                        subFirst,
    217217                        subSecond,
    218                         newEnv, need, have, open, noWiden(), symtab );
     218                        newEnv, need, have, open, noWiden() );
    219219        }
    220220
     
    786786                const ast::OpenVarSet & open;
    787787                WidenMode widen;
    788                 const ast::SymbolTable & symtab;
    789788        public:
    790789                static size_t traceId;
     
    793792                Unify_new(
    794793                        const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need,
    795                         ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen,
    796                         const ast::SymbolTable & symtab )
     794                        ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen )
    797795                : type2(type2), tenv(env), need(need), have(have), open(open), widen(widen),
    798                   symtab(symtab), result(false) {}
     796                result(false) {}
    799797
    800798                void previsit( const ast::Node * ) { visit_children = false; }
     
    814812                                result = unifyExact(
    815813                                        pointer->base, pointer2->base, tenv, need, have, open,
    816                                         noWiden(), symtab );
     814                                        noWiden());
    817815                        }
    818816                }
     
    837835
    838836                        result = unifyExact(
    839                                 array->base, array2->base, tenv, need, have, open, noWiden(),
    840                                 symtab );
     837                                array->base, array2->base, tenv, need, have, open, noWiden());
    841838                }
    842839
     
    844841                        if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
    845842                                result = unifyExact(
    846                                         ref->base, ref2->base, tenv, need, have, open, noWiden(),
    847                                         symtab );
     843                                        ref->base, ref2->base, tenv, need, have, open, noWiden());
    848844                        }
    849845                }
     
    854850                static bool unifyTypeList(
    855851                        Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
    856                         ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    857                         const ast::SymbolTable & symtab
     852                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open
    858853                ) {
    859854                        while ( crnt1 != end1 && crnt2 != end2 ) {
     
    868863                                        return unifyExact(
    869864                                                t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    870                                                 noWiden(), symtab );
     865                                                noWiden() );
    871866                                } else if ( ! isTuple1 && isTuple2 ) {
    872867                                        // combine remainder of list1, then unify
    873868                                        return unifyExact(
    874869                                                tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    875                                                 noWiden(), symtab );
     870                                                noWiden() );
    876871                                }
    877872
    878873                                if ( ! unifyExact(
    879                                         t1, t2, env, need, have, open, noWiden(), symtab )
     874                                        t1, t2, env, need, have, open, noWiden() )
    880875                                ) return false;
    881876
     
    891886                                return unifyExact(
    892887                                        t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    893                                         noWiden(), symtab );
     888                                        noWiden() );
    894889                        } else if ( crnt2 != end2 ) {
    895890                                // try unifying empty tuple with ttype
     
    898893                                return unifyExact(
    899894                                        tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    900                                         noWiden(), symtab );
     895                                        noWiden() );
    901896                        }
    902897
     
    908903                        const std::vector< ast::ptr< ast::Type > > & list2,
    909904                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    910                         const ast::OpenVarSet & open, const ast::SymbolTable & symtab
     905                        const ast::OpenVarSet & open
    911906                ) {
    912907                        return unifyTypeList(
    913                                 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
    914                                 symtab );
     908                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open);
    915909                }
    916910
     
    953947                        ) return;
    954948
    955                         if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return;
     949                        if ( ! unifyTypeList( params, params2, tenv, need, have, open ) ) return;
    956950                        if ( ! unifyTypeList(
    957                                 func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
     951                                func->returns, func2->returns, tenv, need, have, open ) ) return;
    958952
    959953                        markAssertions( have, need, func );
     
    10261020
    10271021                                if ( ! unifyExact(
    1028                                                 pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) {
     1022                                                pty, pty2, tenv, need, have, open, noWiden() ) ) {
    10291023                                        result = false;
    10301024                                        return;
     
    10651059                        const std::vector< ast::ptr< ast::Type > > & list1,
    10661060                        const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env,
    1067                         ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    1068                         const ast::SymbolTable & symtab
     1061                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open
    10691062                ) {
    10701063                        auto crnt1 = list1.begin();
     
    10811074                                        return unifyExact(
    10821075                                                t1, tupleFromTypes( list2 ), env, need, have, open,
    1083                                                 noWiden(), symtab );
     1076                                                noWiden() );
    10841077                                } else if ( ! isTuple1 && isTuple2 ) {
    10851078                                        // combine entirety of list1, then unify
    10861079                                        return unifyExact(
    10871080                                                tupleFromTypes( list1 ), t2, env, need, have, open,
    1088                                                 noWiden(), symtab );
     1081                                                noWiden() );
    10891082                                }
    10901083
    10911084                                if ( ! unifyExact(
    1092                                         t1, t2, env, need, have, open, noWiden(), symtab )
     1085                                        t1, t2, env, need, have, open, noWiden() )
    10931086                                ) return false;
    10941087
     
    11041097                                return unifyExact(
    11051098                                                t1, tupleFromTypes( list2 ), env, need, have, open,
    1106                                                 noWiden(), symtab );
     1099                                                noWiden() );
    11071100                        } else if ( crnt2 != list2.end() ) {
    11081101                                // try unifying empty tuple with ttype
     
    11131106                                return unifyExact(
    11141107                                                tupleFromTypes( list1 ), t2, env, need, have, open,
    1115                                                 noWiden(), symtab );
     1108                                                noWiden() );
    11161109                        }
    11171110
     
    11321125                        auto types2 = flatten( flat2 );
    11331126
    1134                         result = unifyList( types, types2, tenv, need, have, open, symtab );
     1127                        result = unifyList( types, types2, tenv, need, have, open );
    11351128                }
    11361129
     
    11561149                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    11571150                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1158                         ast::OpenVarSet & open, const ast::SymbolTable & symtab
     1151                        ast::OpenVarSet & open
    11591152        ) {
    11601153                ast::ptr<ast::Type> common;
    1161                 return unify( type1, type2, env, need, have, open, symtab, common );
     1154                return unify( type1, type2, env, need, have, open, common );
    11621155        }
    11631156
     
    11651158                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    11661159                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1167                         ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common
     1160                        ast::OpenVarSet & open, ast::ptr<ast::Type> & common
    11681161        ) {
    11691162                ast::OpenVarSet closed;
     
    11711164                findOpenVars( type2, open, closed, need, have, FirstOpen );
    11721165                return unifyInexact(
    1173                         type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common );
     1166                        type1, type2, env, need, have, open, WidenMode{ true, true }, common );
    11741167        }
    11751168
     
    11771170                        const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    11781171                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    1179                         WidenMode widen, const ast::SymbolTable & symtab
     1172                        WidenMode widen
    11801173        ) {
    11811174                if ( type1->qualifiers != type2->qualifiers ) return false;
     
    11931186                        return env.bindVarToVar(
    11941187                                var1, var2, ast::TypeData{ entry1->second, entry2->second }, need, have,
    1195                                 open, widen, symtab );
     1188                                open, widen );
    11961189                } else if ( isopen1 ) {
    1197                         return env.bindVar( var1, type2, entry1->second, need, have, open, widen, symtab );
     1190                        return env.bindVar( var1, type2, entry1->second, need, have, open, widen );
    11981191                } else if ( isopen2 ) {
    1199                         return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab );
     1192                        return env.bindVar( var2, type1, entry2->second, need, have, open, widen );
    12001193                } else {
    12011194                        return ast::Pass<Unify_new>::read(
    1202                                 type1, type2, env, need, have, open, widen, symtab );
     1195                                type1, type2, env, need, have, open, widen );
    12031196                }
    12041197        }
     
    12071200                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    12081201                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1209                         const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
     1202                        const ast::OpenVarSet & open, WidenMode widen,
    12101203                        ast::ptr<ast::Type> & common
    12111204        ) {
     
    12211214                ast::ptr< ast::Type > t2_(t2);
    12221215
    1223                 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
     1216                if ( unifyExact( t1, t2, env, need, have, open, widen ) ) {
    12241217                        // if exact unification on unqualified types, try to merge qualifiers
    12251218                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
     
    12311224                        }
    12321225
    1233                 } else if (( common = commonType( t1, t2, env, need, have, open, widen, symtab ))) {
     1226                } else if (( common = commonType( t1, t2, env, need, have, open, widen ))) {
    12341227                        // no exact unification, but common type
    12351228                        auto c = shallowCopy(common.get());
  • src/ResolvExpr/Unify.h

    r2b78949 r8a930c03  
    5959        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    6060        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    61         ast::OpenVarSet & open, const ast::SymbolTable & symtab );
     61        ast::OpenVarSet & open );
    6262
    6363bool unify(
    6464        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    6565        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    66         ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common );
     66        ast::OpenVarSet & open, ast::ptr<ast::Type> & common );
    6767
    6868bool unifyExact(
    6969        const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    7070        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    71         WidenMode widen, const ast::SymbolTable & symtab );
     71        WidenMode widen );
    7272
    7373bool unifyInexact(
    7474        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    7575        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    76         const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
     76        const ast::OpenVarSet & open, WidenMode widen,
    7777        ast::ptr<ast::Type> & common );
    7878
    7979bool typesCompatible(
    80         const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},
     80        const ast::Type *, const ast::Type *,
    8181        const ast::TypeEnvironment & env = {} );
    8282
    8383bool typesCompatibleIgnoreQualifiers(
    84         const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},
     84        const ast::Type *, const ast::Type *,
    8585        const ast::TypeEnvironment & env = {} );
    8686
  • src/SymTab/Autogen.h

    r2b78949 r8a930c03  
    2020#include <string>                 // for string
    2121
    22 #include "AST/Decl.hpp"
    23 #include "AST/Expr.hpp"
    24 #include "AST/Init.hpp"
    25 #include "AST/Node.hpp"
    26 #include "AST/Stmt.hpp"
    27 #include "AST/Type.hpp"
    2822#include "CodeGen/OperatorTable.h"
    2923#include "Common/UniqueName.h"    // for UniqueName
     
    5751        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    5852        FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
    59 
    60         /// Enum for loop direction
    61         enum LoopDirection { LoopBackward, LoopForward };
    6253
    6354        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
  • src/SymTab/GenImplicitCall.cpp

    r2b78949 r8a930c03  
    1616#include "GenImplicitCall.hpp"
    1717
     18#include "AST/Decl.hpp"                  // for ObjectDecl
     19#include "AST/Expr.hpp"                  // for ConstantExpr, UntypedExpr,...
     20#include "AST/Init.hpp"                  // for SingleInit
    1821#include "AST/Inspect.hpp"               // for isUnnamedBitfield
     22#include "AST/Stmt.hpp"                  // for ExprStmt
     23#include "AST/Type.hpp"                  // for ArrayType, BasicType, ...
    1924#include "CodeGen/OperatorTable.h"       // for isCtorDtor
    2025#include "Common/UniqueName.h"           // for UniqueName
    2126
    2227namespace SymTab {
     28
     29namespace {
    2330
    2431template< typename OutIter >
     
    173180}
    174181
     182} // namespace
     183
    175184ast::ptr< ast::Stmt > genImplicitCall(
    176185        InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
  • src/SymTab/GenImplicitCall.hpp

    r2b78949 r8a930c03  
    1717
    1818#include "InitTweak/InitTweak.h"  // for InitExpander
    19 #include "SymTab/Autogen.h"       // for LoopDirection
    2019
    2120namespace SymTab {
    2221
     22/// Enum for loop direction
     23enum LoopDirection { LoopBackward, LoopForward };
     24
     25/// Returns a generated call expression to function fname with srcParam and
     26/// dstParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    2327ast::ptr<ast::Stmt> genImplicitCall(
    2428        InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     
    3438// compile-command: "make install" //
    3539// End: //
    36 
  • src/Tuples/Explode.cc

    r2b78949 r8a930c03  
    1717#include <list>                  // for list
    1818
     19#include "AST/Pass.hpp"          // for Pass
    1920#include "SynTree/Mutator.h"     // for Mutator
    2021#include "Common/PassVisitor.h"  // for PassVisitor
  • src/Validate/Autogen.cpp

    r2b78949 r8a930c03  
    2525
    2626#include "AST/Attribute.hpp"
     27#include "AST/Copy.hpp"
    2728#include "AST/Create.hpp"
    2829#include "AST/Decl.hpp"
     
    4344#include "CompilationState.h"
    4445
    45 // TODO: The other new ast function should be moved over to this file.
    46 #include "SymTab/Autogen.h"
    47 
    4846namespace Validate {
    4947
     
    9593
    9694        const CodeLocation& getLocation() const { return getDecl()->location; }
    97         ast::FunctionDecl * genProto( const std::string& name,
     95        ast::FunctionDecl * genProto( std::string&& name,
    9896                std::vector<ast::ptr<ast::DeclWithType>>&& params,
    9997                std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const;
     
    336334}
    337335
     336void replaceAll( std::vector<ast::ptr<ast::DeclWithType>> & dwts,
     337                const ast::DeclReplacer::TypeMap & map ) {
     338        for ( auto & dwt : dwts ) {
     339                dwt = strict_dynamic_cast<const ast::DeclWithType *>(
     340                                ast::DeclReplacer::replace( dwt, map ) );
     341        }
     342}
     343
    338344/// Generates a basic prototype function declaration.
    339 ast::FunctionDecl * FuncGenerator::genProto( const std::string& name,
     345ast::FunctionDecl * FuncGenerator::genProto( std::string&& name,
    340346                std::vector<ast::ptr<ast::DeclWithType>>&& params,
    341347                std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const {
     
    343349        // Handle generic prameters and assertions, if any.
    344350        auto const & old_type_params = getGenericParams( type );
     351        ast::DeclReplacer::TypeMap oldToNew;
    345352        std::vector<ast::ptr<ast::TypeDecl>> type_params;
    346353        std::vector<ast::ptr<ast::DeclWithType>> assertions;
    347354        for ( auto & old_param : old_type_params ) {
    348355                ast::TypeDecl * decl = ast::deepCopy( old_param );
    349                 for ( auto assertion : decl->assertions ) {
    350                         assertions.push_back( assertion );
    351                 }
    352                 decl->assertions.clear();
     356                decl->init = nullptr;
     357                splice( assertions, decl->assertions );
     358                oldToNew.emplace( std::make_pair( old_param, decl ) );
    353359                type_params.push_back( decl );
    354360        }
    355         // TODO: The values in params and returns still may point at the old
    356         // generic params, that does not appear to be an issue but perhaps it
    357         // should be addressed.
     361        replaceAll( params, oldToNew );
     362        replaceAll( returns, oldToNew );
     363        replaceAll( assertions, oldToNew );
    358364
    359365        ast::FunctionDecl * decl = new ast::FunctionDecl(
    360366                // Auto-generated routines use the type declaration's location.
    361367                getLocation(),
    362                 name,
     368                std::move( name ),
    363369                std::move( type_params ),
    364370                std::move( assertions ),
  • src/Validate/FixQualifiedTypes.cpp

    r2b78949 r8a930c03  
    1616#include "Validate/FixQualifiedTypes.hpp"
    1717
     18#include "AST/Copy.hpp"
    1819#include "AST/LinkageSpec.hpp"             // for Linkage
    1920#include "AST/Pass.hpp"
  • src/Validate/GenericParameter.cpp

    r2b78949 r8a930c03  
    1616#include "GenericParameter.hpp"
    1717
     18#include "AST/Copy.hpp"
    1819#include "AST/Decl.hpp"
    1920#include "AST/Expr.hpp"
  • src/Validate/HoistStruct.cpp

    r2b78949 r8a930c03  
    1818#include <sstream>
    1919
     20#include "AST/DeclReplacer.hpp"
    2021#include "AST/Pass.hpp"
    2122#include "AST/TranslationUnit.hpp"
     23#include "AST/Vector.hpp"
    2224
    2325namespace Validate {
     
    5153        template<typename AggrDecl>
    5254        AggrDecl const * postAggregate( AggrDecl const * );
     55        template<typename InstType>
     56        InstType const * preCollectionInstType( InstType const * type );
    5357
    5458        ast::AggregateDecl const * parent = nullptr;
     
    6670        qualifiedName( decl, ss );
    6771        return ss.str();
     72}
     73
     74void extendParams( ast::vector<ast::TypeDecl> & dstParams,
     75                ast::vector<ast::TypeDecl> const & srcParams ) {
     76        if ( srcParams.empty() ) return;
     77
     78        ast::DeclReplacer::TypeMap newToOld;
     79        ast::vector<ast::TypeDecl> params;
     80        for ( ast::ptr<ast::TypeDecl> const & srcParam : srcParams ) {
     81                ast::TypeDecl * dstParam = ast::deepCopy( srcParam.get() );
     82                dstParam->init = nullptr;
     83                newToOld.emplace( srcParam, dstParam );
     84                for ( auto assertion : dstParam->assertions ) {
     85                        assertion = ast::DeclReplacer::replace( assertion, newToOld );
     86                }
     87                params.emplace_back( dstParam );
     88        }
     89        spliceBegin( dstParams, params );
    6890}
    6991
     
    7496                mut->parent = parent;
    7597                mut->name = qualifiedName( mut );
    76                 return mut;
    77         } else {
    78                 GuardValue( parent ) = decl;
    79                 return decl;
    80         }
     98                extendParams( mut->params, parent->params );
     99                decl = mut;
     100        }
     101        GuardValue( parent ) = decl;
     102        return decl;
    81103}
    82104
     
    112134}
    113135
     136ast::AggregateDecl const * commonParent(
     137                ast::AggregateDecl const * lhs, ast::AggregateDecl const * rhs ) {
     138        for ( auto outer = lhs ; outer ; outer = outer->parent ) {
     139                for ( auto inner = rhs ; inner ; inner = inner->parent ) {
     140                        if ( outer == inner ) {
     141                                return outer;
     142                        }
     143                }
     144        }
     145        return nullptr;
     146}
     147
     148template<typename InstType>
     149InstType const * HoistStructCore::preCollectionInstType( InstType const * type ) {
     150    if ( !type->base->parent ) return type;
     151    if ( type->base->params.empty() ) return type;
     152
     153    InstType * mut = ast::mutate( type );
     154    ast::AggregateDecl const * parent =
     155        commonParent( this->parent, mut->base->parent );
     156    assert( parent );
     157
     158    std::vector<ast::ptr<ast::Expr>> args;
     159    for ( const ast::ptr<ast::TypeDecl> & param : parent->params ) {
     160        args.emplace_back( new ast::TypeExpr( param->location,
     161            new ast::TypeInstType( param )
     162        ) );
     163    }
     164    spliceBegin( mut->params, args );
     165    return mut;
     166}
     167
    114168template<typename InstType>
    115169InstType const * preInstType( InstType const * type ) {
     
    121175
    122176ast::StructInstType const * HoistStructCore::previsit( ast::StructInstType const * type ) {
    123         return preInstType( type );
     177        return preInstType( preCollectionInstType( type ) );
    124178}
    125179
    126180ast::UnionInstType const * HoistStructCore::previsit( ast::UnionInstType const * type ) {
    127         return preInstType( type );
     181        return preInstType( preCollectionInstType( type ) );
    128182}
    129183
  • src/Validate/ReplaceTypedef.cpp

    r2b78949 r8a930c03  
    1616#include "ReplaceTypedef.hpp"
    1717
     18#include "AST/Copy.hpp"
    1819#include "AST/Pass.hpp"
    1920#include "Common/ScopedMap.h"
     
    149150                // constant/enumerator. The effort required to fix this corner case
    150151                // likely outweighs the utility of allowing it.
    151                 if ( !ResolvExpr::typesCompatible( t0, t1, ast::SymbolTable() )
     152                if ( !ResolvExpr::typesCompatible( t0, t1 )
    152153                                || ast::Pass<VarLenChecker>::read( t0 )
    153154                                || ast::Pass<VarLenChecker>::read( t1 ) ) {
  • src/Virtual/ExpandCasts.cc

    r2b78949 r8a930c03  
    2020#include <string>                  // for string, allocator, operator==, ope...
    2121
     22#include "AST/Copy.hpp"
    2223#include "AST/Decl.hpp"
    2324#include "AST/Expr.hpp"
  • src/main.cc

    r2b78949 r8a930c03  
    3232
    3333#include "AST/Convert.hpp"
     34#include "AST/Pass.hpp"                     // for pass_visitor_stats
     35#include "AST/TranslationUnit.hpp"          // for TranslationUnit
    3436#include "AST/Util.hpp"                     // for checkInvariants
    3537#include "CompilationState.h"
Note: See TracChangeset for help on using the changeset viewer.