Changeset 92538ab for src


Ignore:
Timestamp:
Apr 10, 2022, 2:53:18 PM (4 years ago)
Author:
JiadaL <j82liang@…>
Branches:
ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
Children:
d8e2a09
Parents:
4559b34 (diff), 6256891 (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:

Resolve conflict

Location:
src
Files:
4 added
2 deleted
48 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    r4559b34 r92538ab  
    99// Author           : Thierry Delisle
    1010// Created On       : Thu May 09 15::37::05 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb  2 13:19:22 2022
    13 // Update Count     : 41
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Mar 16 15:01:00 2022
     13// Update Count     : 42
    1414//
    1515
     
    4949//================================================================================================
    5050namespace ast {
    51 
    52 // This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not)
    53 // allow us to use the same stratagy in the new ast.
    54 // xxx - since convert back pass works, this concern seems to be unnecessary.
    55 
    56 // these need to be accessed in new FixInit now
    57 ast::ptr<ast::Type> sizeType = nullptr;
    58 const ast::FunctionDecl * dereferenceOperator = nullptr;
    59 const ast::StructDecl   * dtorStruct = nullptr;
    60 const ast::FunctionDecl * dtorStructDestroy = nullptr;
     51// These are the shared local information used by ConverterNewToOld and
     52// ConverterOldToNew to update the global information in the two versions.
     53
     54static ast::ptr<ast::Type> sizeType = nullptr;
     55static const ast::FunctionDecl * dereferenceOperator = nullptr;
     56static const ast::StructDecl   * dtorStruct = nullptr;
     57static const ast::FunctionDecl * dtorStructDestroy = nullptr;
    6158
    6259}
     
    357354        }
    358355
     356        void clausePostamble( Statement * stmt, const ast::StmtClause * node ) {
     357                stmt->location = node->location;
     358                this->node = stmt;
     359        }
     360
    359361        const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
    360362                if ( inCache( node ) ) return nullptr;
     
    405407                auto stmt = new SwitchStmt(
    406408                        get<Expression>().accept1( node->cond ),
    407                         get<Statement>().acceptL( node->stmts )
     409                        get<Statement>().acceptL( node->cases )
    408410                );
    409411                return stmtPostamble( stmt, node );
    410412        }
    411413
    412         const ast::Stmt * visit( const ast::CaseStmt * node ) override final {
     414        const ast::CaseClause * visit( const ast::CaseClause * node ) override final {
    413415                if ( inCache( node ) ) return nullptr;
    414416                auto stmt = new CaseStmt(
     
    417419                        node->isDefault()
    418420                );
    419                 return stmtPostamble( stmt, node );
     421                clausePostamble( stmt, node );
     422                return nullptr;
    420423        }
    421424
     
    513516        }
    514517
    515         const ast::Stmt * visit( const ast::CatchStmt * node ) override final {
     518        const ast::CatchClause * visit( const ast::CatchClause * node ) override final {
    516519                if ( inCache( node ) ) return nullptr;
    517520                CatchStmt::Kind kind;
     
    524527                        break;
    525528                default:
    526                         assertf(false, "Invalid ast::CatchStmt::Kind: %d\n", node->kind);
     529                        assertf(false, "Invalid ast::ExceptionKind: %d\n", node->kind);
    527530                }
    528531                auto stmt = new CatchStmt(
     
    532535                        get<Statement>().accept1( node->body )
    533536                );
    534                 return stmtPostamble( stmt, node );
    535         }
    536 
    537         const ast::Stmt * visit( const ast::FinallyStmt * node ) override final {
     537                return clausePostamble( stmt, node ), nullptr;
     538        }
     539
     540        const ast::FinallyClause * visit( const ast::FinallyClause * node ) override final {
    538541                if ( inCache( node ) ) return nullptr;
    539542                auto stmt = new FinallyStmt( get<CompoundStmt>().accept1( node->body ) );
    540                 return stmtPostamble( stmt, node );
     543                return clausePostamble( stmt, node ), nullptr;
    541544        }
    542545
     
    18941897                        old->location,
    18951898                        GET_ACCEPT_1(condition, Expr),
    1896                         GET_ACCEPT_V(statements, Stmt),
     1899                        GET_ACCEPT_V(statements, CaseClause),
    18971900                        GET_LABELS_V(old->labels)
    18981901                );
     
    19021905        virtual void visit( const CaseStmt * old ) override final {
    19031906                if ( inCache( old ) ) return;
    1904                 this->node = new ast::CaseStmt(
     1907                this->node = new ast::CaseClause(
    19051908                        old->location,
    19061909                        GET_ACCEPT_1(condition, Expr),
    1907                         GET_ACCEPT_V(stmts, Stmt),
    1908                         GET_LABELS_V(old->labels)
    1909                 );
     1910                        GET_ACCEPT_V(stmts, Stmt)
     1911                );
     1912                auto labels = GET_LABELS_V(old->labels);
     1913                assertf(labels.empty(), "Labels found on CaseStmt.");
    19101914                cache.emplace( old, this->node );
    19111915        }
     
    20152019                        old->location,
    20162020                        GET_ACCEPT_1(block, CompoundStmt),
    2017                         GET_ACCEPT_V(handlers, CatchStmt),
    2018                         GET_ACCEPT_1(finallyBlock, FinallyStmt),
     2021                        GET_ACCEPT_V(handlers, CatchClause),
     2022                        GET_ACCEPT_1(finallyBlock, FinallyClause),
    20192023                        GET_LABELS_V(old->labels)
    20202024                );
     
    20362040                }
    20372041
    2038                 this->node = new ast::CatchStmt(
     2042                this->node = new ast::CatchClause(
    20392043                        old->location,
    20402044                        kind,
    20412045                        GET_ACCEPT_1(decl, Decl),
    20422046                        GET_ACCEPT_1(cond, Expr),
    2043                         GET_ACCEPT_1(body, Stmt),
    2044                         GET_LABELS_V(old->labels)
    2045                 );
     2047                        GET_ACCEPT_1(body, Stmt)
     2048                );
     2049                auto labels = GET_LABELS_V(old->labels);
     2050                assertf(labels.empty(), "Labels found on CatchStmt.");
    20462051                cache.emplace( old, this->node );
    20472052        }
     
    20492054        virtual void visit( const FinallyStmt * old ) override final {
    20502055                if ( inCache( old ) ) return;
    2051                 this->node = new ast::FinallyStmt(
    2052                         old->location,
    2053                         GET_ACCEPT_1(block, CompoundStmt),
    2054                         GET_LABELS_V(old->labels)
    2055                 );
     2056                this->node = new ast::FinallyClause(
     2057                        old->location,
     2058                        GET_ACCEPT_1(block, CompoundStmt)
     2059                );
     2060                auto labels = GET_LABELS_V(old->labels);
     2061                assertf(labels.empty(), "Labels found on FinallyStmt.");
    20562062                cache.emplace( old, this->node );
    20572063        }
     
    27182724
    27192725                for (auto & param : foralls) {
    2720                         ty->forall.emplace_back(new ast::TypeInstType(param->name, param));
     2726                        ty->forall.emplace_back(new ast::TypeInstType(param));
    27212727                        for (auto asst : param->assertions) {
    27222728                                ty->assertions.emplace_back(new ast::VariableExpr({}, asst));
  • src/AST/Decl.cpp

    r4559b34 r92538ab  
    3939        if ( uniqueId ) return;  // ensure only set once
    4040        uniqueId = ++lastUniqueId;
    41         idMap[ uniqueId ] = this;
     41        // The extra readonly pointer is causing some reference counting issues.
     42        // idMap[ uniqueId ] = this;
    4243}
    4344
    4445readonly<Decl> Decl::fromId( UniqueId id ) {
     46        // Right now this map is always empty, so don't use it.
     47        assert( false );
    4548        IdMapType::const_iterator i = idMap.find( id );
    4649        if ( i != idMap.end() ) return i->second;
     
    6568        }
    6669        for (auto & tp : this->type_params) {
    67                 ftype->forall.emplace_back(new TypeInstType(tp->name, tp));
     70                ftype->forall.emplace_back(new TypeInstType(tp));
    6871                for (auto & ap: tp->assertions) {
    6972                        ftype->assertions.emplace_back(new VariableExpr(loc, ap));
  • src/AST/Fwd.hpp

    r4559b34 r92538ab  
    4747class ForStmt;
    4848class SwitchStmt;
    49 class CaseStmt;
     49class CaseClause;
    5050class BranchStmt;
    5151class ReturnStmt;
    5252class ThrowStmt;
    5353class TryStmt;
    54 class CatchStmt;
    55 class FinallyStmt;
     54class CatchClause;
     55class FinallyClause;
    5656class SuspendStmt;
    5757class WaitForStmt;
     
    141141
    142142class TranslationUnit;
    143 // TODO: Get from the TranslationUnit:
    144 extern ptr<Type> sizeType;
    145 extern const FunctionDecl * dereferenceOperator;
    146 extern const StructDecl   * dtorStruct;
    147 extern const FunctionDecl * dtorStructDestroy;
     143class TranslationGlobal;
    148144
    149145}
  • src/AST/GenericSubstitution.cpp

    r4559b34 r92538ab  
    4545                        visit_children = false;
    4646                        const AggregateDecl * aggr = ty->aggr();
    47                         sub = TypeSubstitution{ aggr->params.begin(), aggr->params.end(), ty->params.begin() };
     47                        sub = TypeSubstitution( aggr->params, ty->params );
    4848                }
    4949
  • src/AST/Node.cpp

    r4559b34 r92538ab  
    99// Author           : Thierry Delisle
    1010// Created On       : Thu May 16 14:16:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  1 09:09:39 2022
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Mar 25 10:30:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    1919#include <csignal>  // MEMORY DEBUG -- for raise
    2020#include <iostream>
     21#include <utility>
    2122
    2223#include "Attribute.hpp"
     
    7677void ast::ptr_base<node_t, ref_t>::_check() const {
    7778        // if(node) assert(node->was_ever_strong == false || node->strong_count > 0);
     79}
     80
     81template< typename node_t, enum ast::Node::ref_type ref_t >
     82void ast::ptr_base<node_t, ref_t>::swap( ptr_base & other ) noexcept {
     83        std::swap( this->node, other.node );
     84        _trap( this->node );
     85        _trap( other.node );
    7886}
    7987
     
    152160template class ast::ptr_base< ast::SwitchStmt, ast::Node::ref_type::weak >;
    153161template class ast::ptr_base< ast::SwitchStmt, ast::Node::ref_type::strong >;
    154 template class ast::ptr_base< ast::CaseStmt, ast::Node::ref_type::weak >;
    155 template class ast::ptr_base< ast::CaseStmt, ast::Node::ref_type::strong >;
     162template class ast::ptr_base< ast::CaseClause, ast::Node::ref_type::weak >;
     163template class ast::ptr_base< ast::CaseClause, ast::Node::ref_type::strong >;
    156164template class ast::ptr_base< ast::BranchStmt, ast::Node::ref_type::weak >;
    157165template class ast::ptr_base< ast::BranchStmt, ast::Node::ref_type::strong >;
     
    162170template class ast::ptr_base< ast::TryStmt, ast::Node::ref_type::weak >;
    163171template class ast::ptr_base< ast::TryStmt, ast::Node::ref_type::strong >;
    164 template class ast::ptr_base< ast::CatchStmt, ast::Node::ref_type::weak >;
    165 template class ast::ptr_base< ast::CatchStmt, ast::Node::ref_type::strong >;
    166 template class ast::ptr_base< ast::FinallyStmt, ast::Node::ref_type::weak >;
    167 template class ast::ptr_base< ast::FinallyStmt, ast::Node::ref_type::strong >;
     172template class ast::ptr_base< ast::CatchClause, ast::Node::ref_type::weak >;
     173template class ast::ptr_base< ast::CatchClause, ast::Node::ref_type::strong >;
     174template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::weak >;
     175template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::strong >;
    168176template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::weak >;
    169177template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::strong >;
  • src/AST/Node.hpp

    r4559b34 r92538ab  
    1010// Created On       : Wed May 8 10:27:04 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jun 5 9:47:00 2020
    13 // Update Count     : 6
     12// Last Modified On : Fri Mar 25 10:33:00 2022
     13// Update Count     : 7
    1414//
    1515
     
    103103
    104104/// Mutate a node field (only clones if not equal to existing value)
    105 template<typename node_t, typename parent_t, typename field_t, typename assn_t>
    106 const node_t * mutate_field( const node_t * node, field_t parent_t::* field, assn_t && val ) {
     105template<typename node_t, typename super_t, typename field_t, typename assn_t>
     106const node_t * mutate_field( const node_t * node, field_t super_t::* field, assn_t && val ) {
    107107        // skip mutate if equivalent
    108108        if ( node->*field == val ) return node;
     
    115115
    116116/// Mutate a single index of a node field (only clones if not equal to existing value)
    117 template<typename node_t, typename parent_t, typename coll_t, typename ind_t, typename field_t>
     117template<typename node_t, typename super_t, typename coll_t, typename ind_t, typename field_t>
    118118const node_t * mutate_field_index(
    119         const node_t * node, coll_t parent_t::* field, ind_t i, field_t && val
     119        const node_t * node, coll_t super_t::* field, ind_t i, field_t && val
    120120) {
    121121        // skip mutate if equivalent
     
    129129
    130130/// Mutate an entire indexed collection by cloning to accepted value
    131 template<typename node_t, typename parent_t, typename coll_t>
    132 const node_t * mutate_each( const node_t * node, coll_t parent_t::* field, Visitor & v ) {
     131template<typename node_t, typename super_t, typename coll_t>
     132const node_t * mutate_each( const node_t * node, coll_t super_t::* field, Visitor & v ) {
    133133        for ( unsigned i = 0; i < (node->*field).size(); ++i ) {
    134134                node = mutate_field_index( node, field, i, (node->*field)[i]->accept( v ) );
     
    230230        }
    231231
     232        /// Swaps the nodes contained within two pointers.
     233        void swap( ptr_base & other ) noexcept;
     234
    232235        const node_t * get() const { _check(); return  node; }
    233236        const node_t * operator->() const { _check(); return  node; }
     
    292295template< typename node_t >
    293296using readonly = ptr_base< node_t, Node::ref_type::weak >;
     297
     298/// Non-member swap that an participate in overload resolution.
     299template< typename node_t, enum Node::ref_type ref_t >
     300void swap( ptr_base< node_t, ref_t > & l, ptr_base< node_t, ref_t > & r ) {
     301        l.swap( r );
     302}
     303
    294304}
    295305
  • src/AST/Pass.hpp

    r4559b34 r92538ab  
    149149        const ast::Stmt *             visit( const ast::ForStmt              * ) override final;
    150150        const ast::Stmt *             visit( const ast::SwitchStmt           * ) override final;
    151         const ast::Stmt *             visit( const ast::CaseStmt             * ) override final;
     151        const ast::CaseClause *       visit( const ast::CaseClause           * ) override final;
    152152        const ast::Stmt *             visit( const ast::BranchStmt           * ) override final;
    153153        const ast::Stmt *             visit( const ast::ReturnStmt           * ) override final;
    154154        const ast::Stmt *             visit( const ast::ThrowStmt            * ) override final;
    155155        const ast::Stmt *             visit( const ast::TryStmt              * ) override final;
    156         const ast::Stmt *             visit( const ast::CatchStmt            * ) override final;
    157         const ast::Stmt *             visit( const ast::FinallyStmt          * ) override final;
     156        const ast::CatchClause *      visit( const ast::CatchClause          * ) override final;
     157        const ast::FinallyClause *    visit( const ast::FinallyClause        * ) override final;
    158158        const ast::Stmt *             visit( const ast::SuspendStmt          * ) override final;
    159159        const ast::Stmt *             visit( const ast::WaitForStmt          * ) override final;
  • src/AST/Pass.impl.hpp

    r4559b34 r92538ab  
    354354                        // Take all the elements that are different in 'values'
    355355                        // and swap them into 'container'
    356                         if( values[i] != nullptr ) std::swap(container[i], values[i]);
     356                        if( values[i] != nullptr ) swap(container[i], values[i]);
    357357                }
    358358
     
    399399
    400400        template< typename core_t >
    401         template<typename node_t, typename parent_t, typename child_t>
     401        template<typename node_t, typename super_t, typename field_t>
    402402        void ast::Pass< core_t >::maybe_accept(
    403403                const node_t * & parent,
    404                 child_t parent_t::*child
     404                field_t super_t::*field
    405405        ) {
    406                 static_assert( std::is_base_of<parent_t, node_t>::value, "Error deducing member object" );
    407 
    408                 if(__pass::skip(parent->*child)) return;
    409                 const auto & old_val = __pass::get(parent->*child, 0);
     406                static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
     407
     408                if(__pass::skip(parent->*field)) return;
     409                const auto & old_val = __pass::get(parent->*field, 0);
    410410
    411411                static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
     
    417417                if( new_val.differs ) {
    418418                        auto new_parent = __pass::mutate<core_t>(parent);
    419                         new_val.apply(new_parent, child);
     419                        new_val.apply(new_parent, field);
    420420                        parent = new_parent;
    421421                }
     
    423423
    424424        template< typename core_t >
    425         template<typename node_t, typename parent_t, typename child_t>
     425        template<typename node_t, typename super_t, typename field_t>
    426426        void ast::Pass< core_t >::maybe_accept_as_compound(
    427427                const node_t * & parent,
    428                 child_t parent_t::*child
     428                field_t super_t::*child
    429429        ) {
    430                 static_assert( std::is_base_of<parent_t, node_t>::value, "Error deducing member object" );
     430                static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
    431431
    432432                if(__pass::skip(parent->*child)) return;
     
    893893        if ( __visit_children() ) {
    894894                maybe_accept( node, &SwitchStmt::cond  );
    895                 maybe_accept( node, &SwitchStmt::stmts );
     895                maybe_accept( node, &SwitchStmt::cases );
    896896        }
    897897
     
    900900
    901901//--------------------------------------------------------------------------
    902 // CaseStmt
    903 template< typename core_t >
    904 const ast::Stmt * ast::Pass< core_t >::visit( const ast::CaseStmt * node ) {
    905         VISIT_START( node );
    906 
    907         if ( __visit_children() ) {
    908                 maybe_accept( node, &CaseStmt::cond  );
    909                 maybe_accept( node, &CaseStmt::stmts );
    910         }
    911 
    912         VISIT_END( Stmt, node );
     902// CaseClause
     903template< typename core_t >
     904const ast::CaseClause * ast::Pass< core_t >::visit( const ast::CaseClause * node ) {
     905        VISIT_START( node );
     906
     907        if ( __visit_children() ) {
     908                maybe_accept( node, &CaseClause::cond  );
     909                maybe_accept( node, &CaseClause::stmts );
     910        }
     911
     912        VISIT_END( CaseClause, node );
    913913}
    914914
     
    964964
    965965//--------------------------------------------------------------------------
    966 // CatchStmt
    967 template< typename core_t >
    968 const ast::Stmt * ast::Pass< core_t >::visit( const ast::CatchStmt * node ) {
     966// CatchClause
     967template< typename core_t >
     968const ast::CatchClause * ast::Pass< core_t >::visit( const ast::CatchClause * node ) {
    969969        VISIT_START( node );
    970970
     
    972972                // catch statements introduce a level of scope (for the caught exception)
    973973                guard_symtab guard { *this };
    974                 maybe_accept( node, &CatchStmt::decl );
    975                 maybe_accept( node, &CatchStmt::cond );
    976                 maybe_accept_as_compound( node, &CatchStmt::body );
    977         }
    978 
    979         VISIT_END( Stmt, node );
    980 }
    981 
    982 //--------------------------------------------------------------------------
    983 // FinallyStmt
    984 template< typename core_t >
    985 const ast::Stmt * ast::Pass< core_t >::visit( const ast::FinallyStmt * node ) {
    986         VISIT_START( node );
    987 
    988         if ( __visit_children() ) {
    989                 maybe_accept( node, &FinallyStmt::body );
    990         }
    991 
    992         VISIT_END( Stmt, node );
     974                maybe_accept( node, &CatchClause::decl );
     975                maybe_accept( node, &CatchClause::cond );
     976                maybe_accept_as_compound( node, &CatchClause::body );
     977        }
     978
     979        VISIT_END( CatchClause, node );
     980}
     981
     982//--------------------------------------------------------------------------
     983// FinallyClause
     984template< typename core_t >
     985const ast::FinallyClause * ast::Pass< core_t >::visit( const ast::FinallyClause * node ) {
     986        VISIT_START( node );
     987
     988        if ( __visit_children() ) {
     989                maybe_accept( node, &FinallyClause::body );
     990        }
     991
     992        VISIT_END( FinallyClause, node );
    993993}
    994994
     
    10541054                        auto n = __pass::mutate<core_t>(node);
    10551055                        for(size_t i = 0; i < new_clauses.size(); i++) {
    1056                                 if(new_clauses.at(i).target.func != nullptr) std::swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func);
     1056                                if(new_clauses.at(i).target.func != nullptr) swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func);
    10571057
    10581058                                for(size_t j = 0; j < new_clauses.at(i).target.args.size(); j++) {
    1059                                         if(new_clauses.at(i).target.args.at(j) != nullptr) std::swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j));
     1059                                        if(new_clauses.at(i).target.args.at(j) != nullptr) swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j));
    10601060                                }
    10611061
    1062                                 if(new_clauses.at(i).stmt != nullptr) std::swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt);
    1063                                 if(new_clauses.at(i).cond != nullptr) std::swap(n->clauses.at(i).cond, new_clauses.at(i).cond);
     1062                                if(new_clauses.at(i).stmt != nullptr) swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt);
     1063                                if(new_clauses.at(i).cond != nullptr) swap(n->clauses.at(i).cond, new_clauses.at(i).cond);
    10641064                        }
    10651065                        node = n;
     
    21512151
    21522152        if ( __visit_children() ) {
    2153                 {
    2154                         bool mutated = false;
    2155                         std::unordered_map< ast::TypeInstType::TypeEnvKey, ast::ptr< ast::Type > > new_map;
    2156                         for ( const auto & p : node->typeEnv ) {
    2157                                 guard_symtab guard { *this };
    2158                                 auto new_node = p.second->accept( *this );
    2159                                 if (new_node != p.second) mutated = true;
    2160                                 new_map.insert({ p.first, new_node });
    2161                         }
    2162                         if (mutated) {
    2163                                 auto new_node = __pass::mutate<core_t>( node );
    2164                                 new_node->typeEnv.swap( new_map );
    2165                                 node = new_node;
    2166                         }
     2153                bool mutated = false;
     2154                std::unordered_map< ast::TypeInstType::TypeEnvKey, ast::ptr< ast::Type > > new_map;
     2155                for ( const auto & p : node->typeEnv ) {
     2156                        guard_symtab guard { *this };
     2157                        auto new_node = p.second->accept( *this );
     2158                        if (new_node != p.second) mutated = true;
     2159                        new_map.insert({ p.first, new_node });
     2160                }
     2161                if (mutated) {
     2162                        auto new_node = __pass::mutate<core_t>( node );
     2163                        new_node->typeEnv.swap( new_map );
     2164                        node = new_node;
    21672165                }
    21682166        }
  • src/AST/Print.cpp

    r4559b34 r92538ab  
    597597
    598598                ++indent;
    599                 for ( const ast::Stmt * stmt : node->stmts ) {
     599                for ( const ast::CaseClause * stmt : node->cases ) {
    600600                        stmt->accept( *this );
    601601                }
     
    605605        }
    606606
    607         virtual const ast::Stmt * visit( const ast::CaseStmt * node ) override final {
     607        virtual const ast::CaseClause * visit( const ast::CaseClause * node ) override final {
    608608                if ( node->isDefault() ) {
    609609                        os << indent << "Default ";
     
    687687
    688688                os << indent-1 << "... and handlers:" << endl;
    689                 for ( const ast::CatchStmt * stmt : node->handlers ) {
     689                for ( const ast::CatchClause * stmt : node->handlers ) {
    690690                        os << indent;
    691691                        stmt->accept( *this );
     
    701701        }
    702702
    703         virtual const ast::Stmt * visit( const ast::CatchStmt * node ) override final {
     703        virtual const ast::CatchClause * visit( const ast::CatchClause * node ) override final {
    704704                os << "Catch ";
    705705                switch ( node->kind ) {
     
    726726        }
    727727
    728         virtual const ast::Stmt * visit( const ast::FinallyStmt * node ) override final {
     728        virtual const ast::FinallyClause * visit( const ast::FinallyClause * node ) override final {
    729729                os << "Finally Statement" << endl;
    730730                os << indent << "... with block:" << endl;
  • src/AST/Stmt.hpp

    r4559b34 r92538ab  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed May  8 13:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb  2 20:06:41 2022
    13 // Update Count     : 34
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Mar 28  9:50:00 2022
     13// Update Count     : 35
    1414//
    1515
     
    4747  private:
    4848        Stmt * clone() const override = 0;
     49        MUTATE_FRIEND
     50};
     51
     52// Base statement component node (only serves to group them).
     53class StmtClause : public ParseNode {
     54  public:
     55        // This is for non-statements that still belong with the statements,
     56        // but are not statements, usually some sort of clause. Often these can
     57        // (and should) be folded into the approprate parent node, but if they
     58        // cannot be, they are sub-types of this type, for organization.
     59
     60    StmtClause( const CodeLocation & loc )
     61                : ParseNode(loc) {}
     62
     63  private:
     64        StmtClause * clone() const override = 0;
    4965        MUTATE_FRIEND
    5066};
     
    158174  public:
    159175        ptr<Expr> cond;
     176        std::vector<ptr<CaseClause>> cases;
     177
     178        SwitchStmt( const CodeLocation & loc, const Expr * cond,
     179                                const std::vector<ptr<CaseClause>> && cases,
     180                                const std::vector<Label> && labels = {} )
     181                : Stmt(loc, std::move(labels)), cond(cond), cases(std::move(cases)) {}
     182
     183        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     184  private:
     185        SwitchStmt * clone() const override { return new SwitchStmt{ *this }; }
     186        MUTATE_FRIEND
     187};
     188
     189// Case label: case ...: or default:
     190class CaseClause final : public StmtClause {
     191  public:
     192        // Null for the default label.
     193        ptr<Expr> cond;
    160194        std::vector<ptr<Stmt>> stmts;
    161195
    162         SwitchStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts,
    163                                 const std::vector<Label> && labels = {} )
    164                 : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
    165 
    166         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    167   private:
    168         SwitchStmt * clone() const override { return new SwitchStmt{ *this }; }
    169         MUTATE_FRIEND
    170 };
    171 
    172 // Case label: case ...: or default:
    173 class CaseStmt final : public Stmt {
    174   public:
    175         // Null for the default label.
    176         ptr<Expr> cond;
    177         std::vector<ptr<Stmt>> stmts;
    178 
    179         CaseStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts,
    180                           const std::vector<Label> && labels = {} )
    181                 : Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
     196        CaseClause( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts )
     197                : StmtClause(loc), cond(cond), stmts(std::move(stmts)) {}
    182198
    183199        bool isDefault() const { return !cond; }
    184200
    185         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    186   private:
    187         CaseStmt * clone() const override { return new CaseStmt{ *this }; }
     201        const CaseClause * accept( Visitor & v ) const override { return v.visit( this ); }
     202  private:
     203        CaseClause * clone() const override { return new CaseClause{ *this }; }
    188204        MUTATE_FRIEND
    189205};
     
    298314  public:
    299315        ptr<CompoundStmt> body;
    300         std::vector<ptr<CatchStmt>> handlers;
    301         ptr<FinallyStmt> finally;
     316        std::vector<ptr<CatchClause>> handlers;
     317        ptr<FinallyClause> finally;
    302318
    303319        TryStmt( const CodeLocation & loc, const CompoundStmt * body,
    304                          const std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally,
     320                         const std::vector<ptr<CatchClause>> && handlers, const FinallyClause * finally,
    305321                         const std::vector<Label> && labels = {} )
    306322                : Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {}
     
    313329
    314330// Catch clause of try statement
    315 class CatchStmt final : public Stmt {
     331class CatchClause final : public StmtClause {
    316332  public:
    317333        ptr<Decl> decl;
     
    320336        ExceptionKind kind;
    321337
    322         CatchStmt( const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
    323                            const Stmt * body, const std::vector<Label> && labels = {} )
    324                 : Stmt(loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {}
    325 
    326         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    327   private:
    328         CatchStmt * clone() const override { return new CatchStmt{ *this }; }
     338        CatchClause( const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
     339                           const Stmt * body )
     340                : StmtClause(loc), decl(decl), cond(cond), body(body), kind(kind) {}
     341
     342        const CatchClause * accept( Visitor & v ) const override { return v.visit( this ); }
     343  private:
     344        CatchClause * clone() const override { return new CatchClause{ *this }; }
    329345        MUTATE_FRIEND
    330346};
    331347
    332348// Finally clause of try statement
    333 class FinallyStmt final : public Stmt {
     349class FinallyClause final : public StmtClause {
    334350  public:
    335351        ptr<CompoundStmt> body;
    336352
    337         FinallyStmt( const CodeLocation & loc, const CompoundStmt * body,
    338                                  std::vector<Label> && labels = {} )
    339                 : Stmt(loc, std::move(labels)), body(body) {}
    340 
    341         const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
    342   private:
    343         FinallyStmt * clone() const override { return new FinallyStmt{ *this }; }
     353        FinallyClause( const CodeLocation & loc, const CompoundStmt * body )
     354                : StmtClause(loc), body(body) {}
     355
     356        const FinallyClause * accept( Visitor & v ) const override { return v.visit( this ); }
     357  private:
     358        FinallyClause * clone() const override { return new FinallyClause{ *this }; }
    344359        MUTATE_FRIEND
    345360};
  • src/AST/TranslationUnit.hpp

    r4559b34 r92538ab  
    1010// Created On       : Tue Jun 11 15:30:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Jun 11 15:42:00 2019
    13 // Update Count     : 0
     12// Last Modified On : Tue Mar 11 11:19:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    2323namespace ast {
    2424
     25class TranslationGlobal {
     26public:
     27        std::map< UniqueId, Decl * > idMap;
     28
     29        ptr<Type> sizeType;
     30        const FunctionDecl * dereference;
     31        const StructDecl * dtorStruct;
     32        const FunctionDecl * dtorDestroy;
     33};
     34
    2535class TranslationUnit {
    2636public:
    2737        std::list< ptr< Decl > > decls;
    28 
    29         struct Global {
    30                 std::map< UniqueId, Decl * > idMap;
    31 
    32                 ptr<Type> sizeType;
    33                 const FunctionDecl * dereference;
    34                 const StructDecl * dtorStruct;
    35                 const FunctionDecl * dtorDestroy;
    36         } global;
     38        TranslationGlobal global;
    3739};
    3840
  • src/AST/Type.cpp

    r4559b34 r92538ab  
    147147// --- TypeInstType
    148148
     149TypeInstType::TypeInstType( const TypeDecl * b,
     150        CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
     151: BaseInstType( b->name, q, move(as) ), base( b ), kind( b->kind ) {}
     152
    149153void TypeInstType::set_base( const TypeDecl * b ) {
    150154        base = b;
  • src/AST/Type.hpp

    r4559b34 r92538ab  
    421421                std::vector<ptr<Attribute>> && as = {} )
    422422        : BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
     423
     424        TypeInstType( const TypeDecl * b,
     425                CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
     426
    423427        TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
    424428                std::vector<ptr<Attribute>> && as = {} )
  • src/AST/TypeSubstitution.hpp

    r4559b34 r92538ab  
    3737  public:
    3838        TypeSubstitution();
     39        template< typename FormalContainer, typename ActualContainer >
     40        TypeSubstitution( FormalContainer formals, ActualContainer actuals );
    3941        template< typename FormalIterator, typename ActualIterator >
    4042        TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
     
    7678        bool empty() const;
    7779
     80        template< typename FormalContainer, typename ActualContainer >
     81        void addAll( FormalContainer formals, ActualContainer actuals );
    7882        template< typename FormalIterator, typename ActualIterator >
    79         void add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
     83        void addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
    8084
    8185        /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
     
    112116};
    113117
     118template< typename FormalContainer, typename ActualContainer >
     119TypeSubstitution::TypeSubstitution( FormalContainer formals, ActualContainer actuals ) {
     120        assert( formals.size() == actuals.size() );
     121        addAll( formals.begin(), formals.end(), actuals.begin() );
     122}
     123
     124template< typename FormalIterator, typename ActualIterator >
     125TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
     126        addAll( formalBegin, formalEnd, actualBegin );
     127}
     128
     129template< typename FormalContainer, typename ActualContainer >
     130void TypeSubstitution::addAll( FormalContainer formals, ActualContainer actuals ) {
     131        assert( formals.size() == actuals.size() );
     132        addAll( formals.begin(), formals.end(), actuals.begin() );
     133}
     134
    114135// this is the only place where type parameters outside a function formal may be substituted.
    115136template< typename FormalIterator, typename ActualIterator >
    116 void TypeSubstitution::add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
     137void TypeSubstitution::addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
    117138        // FormalIterator points to a TypeDecl
    118139        // ActualIterator points to a Type
     
    129150                        } // if
    130151                } else {
    131                        
     152                        // Is this an error?
    132153                } // if
    133154        } // for
    134155}
    135 
    136 
    137 
    138 template< typename FormalIterator, typename ActualIterator >
    139 TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
    140         add( formalBegin, formalEnd, actualBegin );
    141 }
    142 
    143156
    144157} // namespace ast
  • src/AST/Visitor.hpp

    r4559b34 r92538ab  
    4141    virtual const ast::Stmt *             visit( const ast::ForStmt              * ) = 0;
    4242    virtual const ast::Stmt *             visit( const ast::SwitchStmt           * ) = 0;
    43     virtual const ast::Stmt *             visit( const ast::CaseStmt             * ) = 0;
     43    virtual const ast::CaseClause *       visit( const ast::CaseClause           * ) = 0;
    4444    virtual const ast::Stmt *             visit( const ast::BranchStmt           * ) = 0;
    4545    virtual const ast::Stmt *             visit( const ast::ReturnStmt           * ) = 0;
    4646    virtual const ast::Stmt *             visit( const ast::ThrowStmt            * ) = 0;
    4747    virtual const ast::Stmt *             visit( const ast::TryStmt              * ) = 0;
    48     virtual const ast::Stmt *             visit( const ast::CatchStmt            * ) = 0;
    49     virtual const ast::Stmt *             visit( const ast::FinallyStmt          * ) = 0;
     48    virtual const ast::CatchClause *      visit( const ast::CatchClause          * ) = 0;
     49    virtual const ast::FinallyClause *    visit( const ast::FinallyClause        * ) = 0;
    5050    virtual const ast::Stmt *             visit( const ast::SuspendStmt          * ) = 0;
    5151    virtual const ast::Stmt *             visit( const ast::WaitForStmt          * ) = 0;
  • src/AST/module.mk

    r4559b34 r92538ab  
    1616
    1717SRC_AST = \
    18         AST/AssertAcyclic.cpp \
    19         AST/AssertAcyclic.hpp \
    2018        AST/Attribute.cpp \
    2119        AST/Attribute.hpp \
     
    6462        AST/TypeSubstitution.cpp \
    6563        AST/TypeSubstitution.hpp \
     64        AST/Util.cpp \
     65        AST/Util.hpp \
    6666        AST/Visitor.hpp
    6767
  • src/Common/CodeLocationTools.cpp

    r4559b34 r92538ab  
    99// Author           : Andrew Beach
    1010// Created On       : Fri Dec  4 15:42:00 2020
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  1 09:14:39 2022
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Mar 14 15:14:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    112112    macro(ForStmt, Stmt) \
    113113    macro(SwitchStmt, Stmt) \
    114     macro(CaseStmt, Stmt) \
     114    macro(CaseClause, CaseClause) \
    115115    macro(BranchStmt, Stmt) \
    116116    macro(ReturnStmt, Stmt) \
    117117    macro(ThrowStmt, Stmt) \
    118118    macro(TryStmt, Stmt) \
    119     macro(CatchStmt, Stmt) \
    120     macro(FinallyStmt, Stmt) \
     119    macro(CatchClause, CatchClause) \
     120    macro(FinallyClause, FinallyClause) \
    121121    macro(SuspendStmt, Stmt) \
    122122    macro(WaitForStmt, Stmt) \
     
    239239};
    240240
     241class LocalFillCore : public ast::WithGuards {
     242        CodeLocation const * parent;
     243public:
     244        LocalFillCore( CodeLocation const & location ) : parent( &location ) {
     245                assert( location.isSet() );
     246        }
     247
     248        template<typename node_t>
     249        auto previsit( node_t const * node )
     250                        -> typename std::enable_if<has_code_location<node_t>::value, node_t const *>::type {
     251                if ( node->location.isSet() ) {
     252                        GuardValue( parent ) = &node->location;
     253                        return node;
     254                } else {
     255                        node_t * mut = ast::mutate( node );
     256                        mut->location = *parent;
     257                        return mut;
     258                }
     259        }
     260};
     261
    241262} // namespace
    242263
     
    278299        ast::Pass<FillCore>::run( unit );
    279300}
     301
     302ast::Node const * localFillCodeLocations(
     303                CodeLocation const & location , ast::Node const * node ) {
     304        ast::Pass<LocalFillCore> visitor( location );
     305        return node->accept( visitor );
     306}
  • src/Common/CodeLocationTools.hpp

    r4559b34 r92538ab  
    1010// Created On       : Fri Dec  4 15:35:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Dec  9  9:53:00 2020
    13 // Update Count     : 1
     12// Last Modified On : Mon Mar 14 15:14:00 2022
     13// Update Count     : 2
    1414//
    1515
    1616#pragma once
    1717
     18struct CodeLocation;
    1819namespace ast {
     20        class Node;
    1921        class TranslationUnit;
    2022}
     
    2830// Assign a nearby code-location to any unset code locations in the forest.
    2931void forceFillCodeLocations( ast::TranslationUnit & unit );
     32
     33// Fill in code-locations with a parent code location,
     34// using the provided CodeLocation as the base.
     35ast::Node const *
     36        localFillCodeLocations( CodeLocation const &, ast::Node const * );
  • src/Common/Examine.cc

    r4559b34 r92538ab  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Examine.h --
     7// Examine.cc -- Helpers for examining AST code.
    88//
    99// Author           : Andrew Beach
    1010// Created On       : Wed Sept 2 14:02 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Sep  8 12:15 2020
    13 // Update Count     : 0
     12// Last Modified On : Fri Dec 10 10:27 2021
     13// Update Count     : 1
    1414//
    1515
    1616#include "Common/Examine.h"
    1717
     18#include "AST/Type.hpp"
    1819#include "CodeGen/OperatorTable.h"
     20#include "InitTweak/InitTweak.h"
    1921
    2022DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind ) {
     
    3638
    3739namespace {
     40
     41// getTypeofThis but does some extra checks used in this module.
     42const ast::Type * getTypeofThisSolo( const ast::FunctionDecl * func ) {
     43        if ( 1 != func->params.size() ) {
     44                return nullptr;
     45        }
     46        auto ref = func->type->params.front().as<ast::ReferenceType>();
     47        return (ref) ? ref->base : nullptr;
     48}
     49
     50}
     51
     52const ast::DeclWithType * isMainFor(
     53                const ast::FunctionDecl * func, ast::AggregateDecl::Aggregate kind ) {
     54        if ( "main" != func->name ) return nullptr;
     55        if ( 1 != func->params.size() ) return nullptr;
     56
     57        auto param = func->params.front();
     58
     59        auto type = dynamic_cast<const ast::ReferenceType *>( param->get_type() );
     60        if ( !type ) return nullptr;
     61
     62        auto obj = type->base.as<ast::StructInstType>();
     63        if ( !obj ) return nullptr;
     64
     65        if ( kind != obj->base->kind ) return nullptr;
     66
     67        return param;
     68}
     69
     70namespace {
    3871        Type * getDestructorParam( FunctionDecl * func ) {
    3972                if ( !CodeGen::isDestructor( func->name ) ) return nullptr;
     
    4881                return nullptr;
    4982        }
     83
     84const ast::Type * getDestructorParam( const ast::FunctionDecl * func ) {
     85        if ( !CodeGen::isDestructor( func->name ) ) return nullptr;
     86        //return InitTweak::getParamThis( func )->type;
     87        return getTypeofThisSolo( func );
     88}
     89
    5090}
    5191
     
    5797        return false;
    5898}
     99
     100bool isDestructorFor(
     101                const ast::FunctionDecl * func, const ast::StructDecl * type_decl ) {
     102        if ( const ast::Type * type = getDestructorParam( func ) ) {
     103                auto stype = dynamic_cast<const ast::StructInstType *>( type );
     104                return stype && stype->base.get() == type_decl;
     105        }
     106        return false;
     107}
  • src/Common/Examine.h

    r4559b34 r92538ab  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Examine.h --
     7// Examine.h -- Helpers for examining AST code.
    88//
    99// Author           : Andrew Beach
    1010// Created On       : Wed Sept 2 13:57 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Sep  8 12:08 2020
    13 // Update Count     : 0
     12// Last Modified On : Fri Dec 10 10:28 2021
     13// Update Count     : 1
    1414//
    1515
     16#include "AST/Decl.hpp"
    1617#include "SynTree/Declaration.h"
    1718
    1819/// Check if this is a main function for a type of an aggregate kind.
    1920DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind );
     21const ast::DeclWithType * isMainFor(
     22        const ast::FunctionDecl * func, ast::AggregateDecl::Aggregate kind );
    2023// Returns a pointer to the parameter if true, nullptr otherwise.
    2124
    2225/// Check if this function is a destructor for the given structure.
    2326bool isDestructorFor( FunctionDecl * func, StructDecl * type_decl );
     27bool isDestructorFor(
     28        const ast::FunctionDecl * func, const ast::StructDecl * type );
  • src/Concurrency/Keywords.cc

    r4559b34 r92538ab  
    422422                        ;
    423423                else if ( auto param = isMainFor( decl, cast_target ) ) {
    424                         // This should never trigger.
    425                         assert( vtable_decl );
     424                        if ( !vtable_decl ) {
     425                                SemanticError( decl, context_error );
     426                        }
    426427                        // Should be safe because of isMainFor.
    427428                        StructInstType * struct_type = static_cast<StructInstType *>(
     
    12031204                                        //new TypeofType( noQualifiers, args.front()->clone() )
    12041205                                        new TypeofType( noQualifiers, new UntypedExpr(
    1205                                                         new NameExpr( "__get_type" ),
     1206                                                        new NameExpr( "__get_mutexstmt_lock_type" ),
    12061207                                                        { args.front()->clone() }
    12071208                                                )
     
    12151216                                map_range < std::list<Initializer*> > ( args, [](Expression * var ){
    12161217                                        return new SingleInit( new UntypedExpr(
    1217                                                         new NameExpr( "__get_ptr" ),
     1218                                                        new NameExpr( "__get_mutexstmt_lock_ptr" ),
    12181219                                                        { var }
    12191220                                        ) );
     
    12261227                TypeExpr * lock_type_expr = new TypeExpr(
    12271228                        new TypeofType( noQualifiers, new UntypedExpr(
    1228                                 new NameExpr( "__get_type" ),
     1229                                new NameExpr( "__get_mutexstmt_lock_type" ),
    12291230                                { args.front()->clone() }
    12301231                                )
  • src/Concurrency/KeywordsNew.cpp

    r4559b34 r92538ab  
    1010// Created On       : Tue Nov 16  9:53:00 2021
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Dec  1 11:24:00 2021
    13 // Update Count     : 1
     12// Last Modified On : Fri Mar 11 10:40:00 2022
     13// Update Count     : 2
    1414//
     15
     16#include <iostream>
    1517
    1618#include "Concurrency/Keywords.h"
     
    1820#include "AST/Copy.hpp"
    1921#include "AST/Decl.hpp"
     22#include "AST/Expr.hpp"
    2023#include "AST/Pass.hpp"
    2124#include "AST/Stmt.hpp"
     25#include "AST/DeclReplacer.hpp"
    2226#include "AST/TranslationUnit.hpp"
    2327#include "CodeGen/OperatorTable.h"
     28#include "Common/Examine.h"
    2429#include "Common/utility.h"
     30#include "Common/UniqueName.h"
     31#include "ControlStruct/LabelGeneratorNew.hpp"
    2532#include "InitTweak/InitTweak.h"
     33#include "Virtual/Tables.h"
    2634
    2735namespace Concurrency {
     
    2937namespace {
    3038
    31 inline static bool isThread( const ast::DeclWithType * decl ) {
     39// --------------------------------------------------------------------------
     40// Loose Helper Functions:
     41
     42/// Detect threads constructed with the keyword thread.
     43bool isThread( const ast::DeclWithType * decl ) {
    3244        auto baseType = decl->get_type()->stripDeclarator();
    3345        auto instType = dynamic_cast<const ast::StructInstType *>( baseType );
     
    3648}
    3749
     50/// Get the virtual type id if given a type name.
     51std::string typeIdType( std::string const & exception_name ) {
     52        return exception_name.empty() ? std::string()
     53                : Virtual::typeIdType( exception_name );
     54}
     55
     56/// Get the vtable type name if given a type name.
     57std::string vtableTypeName( std::string const & exception_name ) {
     58        return exception_name.empty() ? std::string()
     59                : Virtual::vtableTypeName( exception_name );
     60}
     61
     62static ast::Type * mutate_under_references( ast::ptr<ast::Type>& type ) {
     63        ast::Type * mutType = type.get_and_mutate();
     64        for ( ast::ReferenceType * mutRef
     65                ; (mutRef = dynamic_cast<ast::ReferenceType *>( mutType ))
     66                ; mutType = mutRef->base.get_and_mutate() );
     67        return mutType;
     68}
     69
     70// Describe that it adds the generic parameters and the uses of the generic
     71// parameters on the function and first "this" argument.
     72ast::FunctionDecl * fixupGenerics(
     73                const ast::FunctionDecl * func, const ast::StructDecl * decl ) {
     74        const CodeLocation & location = decl->location;
     75        // We have to update both the declaration
     76        auto mutFunc = ast::mutate( func );
     77        auto mutType = mutFunc->type.get_and_mutate();
     78
     79        if ( decl->params.empty() ) {
     80                return mutFunc;
     81        }
     82
     83        assert( 0 != mutFunc->params.size() );
     84        assert( 0 != mutType->params.size() );
     85
     86        // Add the "forall" clause information.
     87        for ( const ast::ptr<ast::TypeDecl> & typeParam : decl->params ) {
     88                auto typeDecl = ast::deepCopy( typeParam );
     89                mutFunc->type_params.push_back( typeDecl );
     90                mutType->forall.push_back( new ast::TypeInstType( typeDecl ) );
     91                for ( auto & assertion : typeDecl->assertions ) {
     92                        mutFunc->assertions.push_back( assertion );
     93                        mutType->assertions.emplace_back(
     94                                new ast::VariableExpr( location, assertion ) );
     95                }
     96                typeDecl->assertions.clear();
     97        }
     98
     99        // Even chain_mutate is not powerful enough for this:
     100        ast::ptr<ast::Type>& paramType = strict_dynamic_cast<ast::ObjectDecl *>(
     101                mutFunc->params[0].get_and_mutate() )->type;
     102        auto paramTypeInst = strict_dynamic_cast<ast::StructInstType *>(
     103                mutate_under_references( paramType ) );
     104        auto typeParamInst = strict_dynamic_cast<ast::StructInstType *>(
     105                mutate_under_references( mutType->params[0] ) );
     106
     107        for ( const ast::ptr<ast::TypeDecl> & typeDecl : mutFunc->type_params ) {
     108                paramTypeInst->params.push_back(
     109                        new ast::TypeExpr( location, new ast::TypeInstType( typeDecl ) ) );
     110                typeParamInst->params.push_back(
     111                        new ast::TypeExpr( location, new ast::TypeInstType( typeDecl ) ) );
     112        }
     113
     114        return mutFunc;
     115}
     116
    38117// --------------------------------------------------------------------------
    39 struct MutexKeyword final {
     118struct ConcurrentSueKeyword : public ast::WithDeclsToAdd<> {
     119        ConcurrentSueKeyword(
     120                std::string&& type_name, std::string&& field_name,
     121                std::string&& getter_name, std::string&& context_error,
     122                std::string&& exception_name,
     123                bool needs_main, ast::AggregateDecl::Aggregate cast_target
     124        ) :
     125                type_name( type_name ), field_name( field_name ),
     126                getter_name( getter_name ), context_error( context_error ),
     127                exception_name( exception_name ),
     128                typeid_name( typeIdType( exception_name ) ),
     129                vtable_name( vtableTypeName( exception_name ) ),
     130                needs_main( needs_main ), cast_target( cast_target )
     131        {}
     132
     133        virtual ~ConcurrentSueKeyword() {}
     134
     135        const ast::Decl * postvisit( const ast::StructDecl * decl );
     136        const ast::DeclWithType * postvisit( const ast::FunctionDecl * decl );
     137        const ast::Expr * postvisit( const ast::KeywordCastExpr * expr );
     138
     139        struct StructAndField {
     140                const ast::StructDecl * decl;
     141                const ast::ObjectDecl * field;
     142        };
     143
     144        const ast::StructDecl * handleStruct( const ast::StructDecl * );
     145        void handleMain( const ast::FunctionDecl *, const ast::StructInstType * );
     146        void addTypeId( const ast::StructDecl * );
     147        void addVtableForward( const ast::StructDecl * );
     148        const ast::FunctionDecl * forwardDeclare( const ast::StructDecl * );
     149        StructAndField addField( const ast::StructDecl * );
     150        void addGetRoutines( const ast::ObjectDecl *, const ast::FunctionDecl * );
     151        void addLockUnlockRoutines( const ast::StructDecl * );
     152
     153private:
     154        const std::string type_name;
     155        const std::string field_name;
     156        const std::string getter_name;
     157        const std::string context_error;
     158        const std::string exception_name;
     159        const std::string typeid_name;
     160        const std::string vtable_name;
     161        const bool needs_main;
     162        const ast::AggregateDecl::Aggregate cast_target;
     163
     164        const ast::StructDecl   * type_decl = nullptr;
     165        const ast::FunctionDecl * dtor_decl = nullptr;
     166        const ast::StructDecl * except_decl = nullptr;
     167        const ast::StructDecl * typeid_decl = nullptr;
     168        const ast::StructDecl * vtable_decl = nullptr;
     169
     170};
     171
     172// Handles thread type declarations:
     173//
     174// thread Mythread {                         struct MyThread {
     175//  int data;                                  int data;
     176//  a_struct_t more_data;                      a_struct_t more_data;
     177//                                =>             thread$ __thrd_d;
     178// };                                        };
     179//                                           static inline thread$ * get_thread( MyThread * this ) { return &this->__thrd_d; }
     180//
     181struct ThreadKeyword final : public ConcurrentSueKeyword {
     182        ThreadKeyword() : ConcurrentSueKeyword(
     183                "thread$",
     184                "__thrd",
     185                "get_thread",
     186                "thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
     187                "ThreadCancelled",
     188                true,
     189                ast::AggregateDecl::Thread )
     190        {}
     191
     192        virtual ~ThreadKeyword() {}
     193};
     194
     195// Handles coroutine type declarations:
     196//
     197// coroutine MyCoroutine {                   struct MyCoroutine {
     198//  int data;                                  int data;
     199//  a_struct_t more_data;                      a_struct_t more_data;
     200//                                =>             coroutine$ __cor_d;
     201// };                                        };
     202//                                           static inline coroutine$ * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
     203//
     204struct CoroutineKeyword final : public ConcurrentSueKeyword {
     205        CoroutineKeyword() : ConcurrentSueKeyword(
     206                "coroutine$",
     207                "__cor",
     208                "get_coroutine",
     209                "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n",
     210                "CoroutineCancelled",
     211                true,
     212                ast::AggregateDecl::Coroutine )
     213        {}
     214
     215        virtual ~CoroutineKeyword() {}
     216};
     217
     218// Handles monitor type declarations:
     219//
     220// monitor MyMonitor {                       struct MyMonitor {
     221//  int data;                                  int data;
     222//  a_struct_t more_data;                      a_struct_t more_data;
     223//                                =>             monitor$ __mon_d;
     224// };                                        };
     225//                                           static inline monitor$ * get_coroutine( MyMonitor * this ) {
     226//                                               return &this->__cor_d;
     227//                                           }
     228//                                           void lock(MyMonitor & this) {
     229//                                               lock(get_monitor(this));
     230//                                           }
     231//                                           void unlock(MyMonitor & this) {
     232//                                               unlock(get_monitor(this));
     233//                                           }
     234//
     235struct MonitorKeyword final : public ConcurrentSueKeyword {
     236        MonitorKeyword() : ConcurrentSueKeyword(
     237                "monitor$",
     238                "__mon",
     239                "get_monitor",
     240                "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n",
     241                "",
     242                false,
     243                ast::AggregateDecl::Monitor )
     244        {}
     245
     246        virtual ~MonitorKeyword() {}
     247};
     248
     249// Handles generator type declarations:
     250//
     251// generator MyGenerator {                   struct MyGenerator {
     252//  int data;                                  int data;
     253//  a_struct_t more_data;                      a_struct_t more_data;
     254//                                =>             int __generator_state;
     255// };                                        };
     256//
     257struct GeneratorKeyword final : public ConcurrentSueKeyword {
     258        GeneratorKeyword() : ConcurrentSueKeyword(
     259                "generator$",
     260                "__generator_state",
     261                "get_generator",
     262                "Unable to find builtin type generator$\n",
     263                "",
     264                true,
     265                ast::AggregateDecl::Generator )
     266        {}
     267
     268        virtual ~GeneratorKeyword() {}
     269};
     270
     271const ast::Decl * ConcurrentSueKeyword::postvisit(
     272                const ast::StructDecl * decl ) {
     273        if ( !decl->body ) {
     274                return decl;
     275        } else if ( cast_target == decl->kind ) {
     276                return handleStruct( decl );
     277        } else if ( type_name == decl->name ) {
     278                assert( !type_decl );
     279                type_decl = decl;
     280        } else if ( exception_name == decl->name ) {
     281                assert( !except_decl );
     282                except_decl = decl;
     283        } else if ( typeid_name == decl->name ) {
     284                assert( !typeid_decl );
     285                typeid_decl = decl;
     286        } else if ( vtable_name == decl->name ) {
     287                assert( !vtable_decl );
     288                vtable_decl = decl;
     289        }
     290        return decl;
     291}
     292
     293// Try to get the full definition, but raise an error on conflicts.
     294const ast::FunctionDecl * getDefinition(
     295                const ast::FunctionDecl * old_decl,
     296                const ast::FunctionDecl * new_decl ) {
     297        if ( !new_decl->stmts ) {
     298                return old_decl;
     299        } else if ( !old_decl->stmts ) {
     300                return new_decl;
     301        } else {
     302                assert( !old_decl->stmts || !new_decl->stmts );
     303                return nullptr;
     304        }
     305}
     306
     307const ast::DeclWithType * ConcurrentSueKeyword::postvisit(
     308                const ast::FunctionDecl * decl ) {
     309        if ( type_decl && isDestructorFor( decl, type_decl ) ) {
     310                // Check for forward declarations, try to get the full definition.
     311                dtor_decl = (dtor_decl) ? getDefinition( dtor_decl, decl ) : decl;
     312        } else if ( !vtable_name.empty() && decl->has_body() ) {
     313                if (const ast::DeclWithType * param = isMainFor( decl, cast_target )) {
     314                        if ( !vtable_decl ) {
     315                                SemanticError( decl, context_error );
     316                        }
     317                        // Should be safe because of isMainFor.
     318                        const ast::StructInstType * struct_type =
     319                                static_cast<const ast::StructInstType *>(
     320                                        static_cast<const ast::ReferenceType *>(
     321                                                param->get_type() )->base.get() );
     322
     323                        handleMain( decl, struct_type );
     324                }
     325        }
     326        return decl;
     327}
     328
     329const ast::Expr * ConcurrentSueKeyword::postvisit(
     330                const ast::KeywordCastExpr * expr ) {
     331        if ( cast_target == expr->target ) {
     332                // Convert `(thread &)ex` to `(thread$ &)*get_thread(ex)`, etc.
     333                if ( !type_decl || !dtor_decl ) {
     334                        SemanticError( expr, context_error );
     335                }
     336                assert( nullptr == expr->result );
     337                auto cast = ast::mutate( expr );
     338                cast->result = new ast::ReferenceType( new ast::StructInstType( type_decl ) );
     339                cast->concrete_target.field  = field_name;
     340                cast->concrete_target.getter = getter_name;
     341                return cast;
     342        }
     343        return expr;
     344}
     345
     346const ast::StructDecl * ConcurrentSueKeyword::handleStruct(
     347                const ast::StructDecl * decl ) {
     348        assert( decl->body );
     349
     350        if ( !type_decl || !dtor_decl ) {
     351                SemanticError( decl, context_error );
     352        }
     353
     354        if ( !exception_name.empty() ) {
     355                if( !typeid_decl || !vtable_decl ) {
     356                        SemanticError( decl, context_error );
     357                }
     358                addTypeId( decl );
     359                addVtableForward( decl );
     360        }
     361
     362        const ast::FunctionDecl * func = forwardDeclare( decl );
     363        StructAndField addFieldRet = addField( decl );
     364        decl = addFieldRet.decl;
     365        const ast::ObjectDecl * field = addFieldRet.field;
     366
     367        addGetRoutines( field, func );
     368        // Add routines to monitors for use by mutex stmt.
     369        if ( ast::AggregateDecl::Monitor == cast_target ) {
     370                addLockUnlockRoutines( decl );
     371        }
     372
     373        return decl;
     374}
     375
     376void ConcurrentSueKeyword::handleMain(
     377                const ast::FunctionDecl * decl, const ast::StructInstType * type ) {
     378        assert( vtable_decl );
     379        assert( except_decl );
     380
     381        const CodeLocation & location = decl->location;
     382
     383        std::vector<ast::ptr<ast::Expr>> poly_args = {
     384                new ast::TypeExpr( location, type ),
     385        };
     386        ast::ObjectDecl * vtable_object = Virtual::makeVtableInstance(
     387                location,
     388                "_default_vtable_object_declaration",
     389                new ast::StructInstType( vtable_decl, copy( poly_args ) ),
     390                type,
     391                nullptr
     392        );
     393        declsToAddAfter.push_back( vtable_object );
     394        declsToAddAfter.push_back(
     395                new ast::ObjectDecl(
     396                        location,
     397                        Virtual::concurrentDefaultVTableName(),
     398                        new ast::ReferenceType( vtable_object->type, ast::CV::Const ),
     399                        new ast::SingleInit( location,
     400                                new ast::VariableExpr( location, vtable_object ) ),
     401                        ast::Storage::Classes(),
     402                        ast::Linkage::Cforall
     403                )
     404        );
     405        declsToAddAfter.push_back( Virtual::makeGetExceptionFunction(
     406                location,
     407                vtable_object,
     408                new ast::StructInstType( except_decl, copy( poly_args ) )
     409        ) );
     410}
     411
     412void ConcurrentSueKeyword::addTypeId( const ast::StructDecl * decl ) {
     413        assert( typeid_decl );
     414        const CodeLocation & location = decl->location;
     415
     416        ast::StructInstType * typeid_type =
     417                new ast::StructInstType( typeid_decl, ast::CV::Const );
     418        typeid_type->params.push_back(
     419                new ast::TypeExpr( location, new ast::StructInstType( decl ) ) );
     420        declsToAddBefore.push_back(
     421                Virtual::makeTypeIdInstance( location, typeid_type ) );
     422        // If the typeid_type is going to be kept, the other reference will have
     423        // been made by now, but we also get to avoid extra mutates.
     424        ast::ptr<ast::StructInstType> typeid_cleanup = typeid_type;
     425}
     426
     427void ConcurrentSueKeyword::addVtableForward( const ast::StructDecl * decl ) {
     428        assert( vtable_decl );
     429        const CodeLocation& location = decl->location;
     430
     431        std::vector<ast::ptr<ast::Expr>> poly_args = {
     432                new ast::TypeExpr( location, new ast::StructInstType( decl ) ),
     433        };
     434        declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
     435                location,
     436                new ast::StructInstType( vtable_decl, copy( poly_args ) ),
     437                new ast::StructInstType( except_decl, copy( poly_args ) )
     438        ) );
     439        ast::ObjectDecl * vtable_object = Virtual::makeVtableForward(
     440                location,
     441                "_default_vtable_object_declaration",
     442                new ast::StructInstType( vtable_decl, std::move( poly_args ) )
     443        );
     444        declsToAddBefore.push_back( vtable_object );
     445        declsToAddBefore.push_back(
     446                new ast::ObjectDecl(
     447                        location,
     448                        Virtual::concurrentDefaultVTableName(),
     449                        new ast::ReferenceType( vtable_object->type, ast::CV::Const ),
     450                        nullptr,
     451                        ast::Storage::Extern,
     452                        ast::Linkage::Cforall
     453                )
     454        );
     455}
     456
     457const ast::FunctionDecl * ConcurrentSueKeyword::forwardDeclare(
     458                const ast::StructDecl * decl ) {
     459        const CodeLocation & location = decl->location;
     460
     461        ast::StructDecl * forward = ast::deepCopy( decl );
     462        {
     463                // If removing members makes ref-count go to zero, do not free.
     464                ast::ptr<ast::StructDecl> forward_ptr = forward;
     465                forward->body = false;
     466                forward->members.clear();
     467                forward_ptr.release();
     468        }
     469
     470        ast::ObjectDecl * this_decl = new ast::ObjectDecl(
     471                location,
     472                "this",
     473                new ast::ReferenceType( new ast::StructInstType( decl ) ),
     474                nullptr,
     475                ast::Storage::Classes(),
     476                ast::Linkage::Cforall
     477        );
     478
     479        ast::ObjectDecl * ret_decl = new ast::ObjectDecl(
     480                location,
     481                "ret",
     482                new ast::PointerType( new ast::StructInstType( type_decl ) ),
     483                nullptr,
     484                ast::Storage::Classes(),
     485                ast::Linkage::Cforall
     486        );
     487
     488        ast::FunctionDecl * get_decl = new ast::FunctionDecl(
     489                location,
     490                getter_name,
     491                {}, // forall
     492                { this_decl }, // params
     493                { ret_decl }, // returns
     494                nullptr, // stmts
     495                ast::Storage::Static,
     496                ast::Linkage::Cforall,
     497                { new ast::Attribute( "const" ) },
     498                ast::Function::Inline
     499        );
     500        get_decl = fixupGenerics( get_decl, decl );
     501
     502        ast::FunctionDecl * main_decl = nullptr;
     503        if ( needs_main ) {
     504                // `this_decl` is copied here because the original was used above.
     505                main_decl = new ast::FunctionDecl(
     506                        location,
     507                        "main",
     508                        {},
     509                        { ast::deepCopy( this_decl ) },
     510                        {},
     511                        nullptr,
     512                        ast::Storage::Classes(),
     513                        ast::Linkage::Cforall
     514                );
     515                main_decl = fixupGenerics( main_decl, decl );
     516        }
     517
     518        declsToAddBefore.push_back( forward );
     519        if ( needs_main ) declsToAddBefore.push_back( main_decl );
     520        declsToAddBefore.push_back( get_decl );
     521
     522        return get_decl;
     523}
     524
     525ConcurrentSueKeyword::StructAndField ConcurrentSueKeyword::addField(
     526                const ast::StructDecl * decl ) {
     527        const CodeLocation & location = decl->location;
     528
     529        ast::ObjectDecl * field = new ast::ObjectDecl(
     530                location,
     531                field_name,
     532                new ast::StructInstType( type_decl ),
     533                nullptr,
     534                ast::Storage::Classes(),
     535                ast::Linkage::Cforall
     536        );
     537
     538        auto mutDecl = ast::mutate( decl );
     539        mutDecl->members.push_back( field );
     540
     541        return {mutDecl, field};
     542}
     543
     544void ConcurrentSueKeyword::addGetRoutines(
     545                const ast::ObjectDecl * field, const ast::FunctionDecl * forward ) {
     546        // Say it is generated at the "same" places as the forward declaration.
     547        const CodeLocation & location = forward->location;
     548
     549        const ast::DeclWithType * param = forward->params.front();
     550        ast::Stmt * stmt = new ast::ReturnStmt( location,
     551                new ast::AddressExpr( location,
     552                        new ast::MemberExpr( location,
     553                                field,
     554                                new ast::CastExpr( location,
     555                                        new ast::VariableExpr( location, param ),
     556                                        ast::deepCopy( param->get_type()->stripReferences() ),
     557                                        ast::ExplicitCast
     558                                )
     559                        )
     560                )
     561        );
     562
     563        ast::FunctionDecl * decl = ast::deepCopy( forward );
     564        decl->stmts = new ast::CompoundStmt( location, { stmt } );
     565        declsToAddAfter.push_back( decl );
     566}
     567
     568void ConcurrentSueKeyword::addLockUnlockRoutines(
     569                const ast::StructDecl * decl ) {
     570        // This should only be used on monitors.
     571        assert( ast::AggregateDecl::Monitor == cast_target );
     572
     573        const CodeLocation & location = decl->location;
     574
     575        // The parameter for both routines.
     576        ast::ObjectDecl * this_decl = new ast::ObjectDecl(
     577                location,
     578                "this",
     579                new ast::ReferenceType( new ast::StructInstType( decl ) ),
     580                nullptr,
     581                ast::Storage::Classes(),
     582                ast::Linkage::Cforall
     583        );
     584
     585        ast::FunctionDecl * lock_decl = new ast::FunctionDecl(
     586                location,
     587                "lock",
     588                { /* forall */ },
     589                {
     590                        // Copy the declaration of this.
     591                        ast::deepCopy( this_decl ),
     592                },
     593                { /* returns */ },
     594                nullptr,
     595                ast::Storage::Static,
     596                ast::Linkage::Cforall,
     597                { /* attributes */ },
     598                ast::Function::Inline
     599        );
     600        lock_decl = fixupGenerics( lock_decl, decl );
     601
     602        lock_decl->stmts = new ast::CompoundStmt( location, {
     603                new ast::ExprStmt( location,
     604                        new ast::UntypedExpr( location,
     605                                new ast::NameExpr( location, "lock" ),
     606                                {
     607                                        new ast::UntypedExpr( location,
     608                                                new ast::NameExpr( location, "get_monitor" ),
     609                                                { new ast::VariableExpr( location,
     610                                                        InitTweak::getParamThis( lock_decl ) ) }
     611                                        )
     612                                }
     613                        )
     614                )
     615        } );
     616
     617        ast::FunctionDecl * unlock_decl = new ast::FunctionDecl(
     618                location,
     619                "unlock",
     620                { /* forall */ },
     621                {
     622                        // Last use, consume the declaration of this.
     623                        this_decl,
     624                },
     625                { /* returns */ },
     626                nullptr,
     627                ast::Storage::Static,
     628                ast::Linkage::Cforall,
     629                { /* attributes */ },
     630                ast::Function::Inline
     631        );
     632        unlock_decl = fixupGenerics( unlock_decl, decl );
     633
     634        unlock_decl->stmts = new ast::CompoundStmt( location, {
     635                new ast::ExprStmt( location,
     636                        new ast::UntypedExpr( location,
     637                                new ast::NameExpr( location, "unlock" ),
     638                                {
     639                                        new ast::UntypedExpr( location,
     640                                                new ast::NameExpr( location, "get_monitor" ),
     641                                                { new ast::VariableExpr( location,
     642                                                        InitTweak::getParamThis( unlock_decl ) ) }
     643                                        )
     644                                }
     645                        )
     646                )
     647        } );
     648
     649        declsToAddAfter.push_back( lock_decl );
     650        declsToAddAfter.push_back( unlock_decl );
     651}
     652
     653
     654// --------------------------------------------------------------------------
     655struct SuspendKeyword final :
     656                public ast::WithStmtsToAdd<>, public ast::WithGuards {
     657        SuspendKeyword() = default;
     658        virtual ~SuspendKeyword() = default;
     659
     660        void previsit( const ast::FunctionDecl * );
     661        const ast::DeclWithType * postvisit( const ast::FunctionDecl * );
     662        const ast::Stmt * postvisit( const ast::SuspendStmt * );
     663
     664private:
     665        bool is_real_suspend( const ast::FunctionDecl * );
     666
     667        const ast::Stmt * make_generator_suspend( const ast::SuspendStmt * );
     668        const ast::Stmt * make_coroutine_suspend( const ast::SuspendStmt * );
     669
     670        struct LabelPair {
     671                ast::Label obj;
     672                int idx;
     673        };
     674
     675        LabelPair make_label(const ast::Stmt * stmt ) {
     676                labels.push_back( ControlStruct::newLabel( "generator", stmt ) );
     677                return { labels.back(), int(labels.size()) };
     678        }
     679
     680        const ast::DeclWithType * in_generator = nullptr;
     681        const ast::FunctionDecl * decl_suspend = nullptr;
     682        std::vector<ast::Label> labels;
     683};
     684
     685void SuspendKeyword::previsit( const ast::FunctionDecl * decl ) {
     686        GuardValue( in_generator ); in_generator = nullptr;
     687
     688        // If it is the real suspend, grab it if we don't have one already.
     689        if ( is_real_suspend( decl ) ) {
     690                decl_suspend = decl_suspend ? decl_suspend : decl;
     691                return;
     692        }
     693
     694        // Otherwise check if this is a generator main and, if so, handle it.
     695        auto param = isMainFor( decl, ast::AggregateDecl::Generator );
     696        if ( !param ) return;
     697
     698        if ( 0 != decl->returns.size() ) {
     699                SemanticError( decl->location, "Generator main must return void" );
     700        }
     701
     702        in_generator = param;
     703        GuardValue( labels ); labels.clear();
     704}
     705
     706const ast::DeclWithType * SuspendKeyword::postvisit(
     707                const ast::FunctionDecl * decl ) {
     708        // Only modify a full definition of a generator with states.
     709        if ( !decl->stmts || !in_generator || labels.empty() ) return decl;
     710
     711        const CodeLocation & location = decl->location;
     712
     713        // Create a new function body:
     714        // static void * __generator_labels[] = {&&s0, &&s1, ...};
     715        // void * __generator_label = __generator_labels[GEN.__generator_state];
     716        // goto * __generator_label;
     717        // s0: ;
     718        // OLD_BODY
     719
     720        // This is the null statement inserted right before the body.
     721        ast::NullStmt * noop = new ast::NullStmt( location );
     722        noop->labels.push_back( ControlStruct::newLabel( "generator", noop ) );
     723        const ast::Label & first_label = noop->labels.back();
     724
     725        // Add each label to the init, starting with the first label.
     726        std::vector<ast::ptr<ast::Init>> inits = {
     727                new ast::SingleInit( location,
     728                        new ast::LabelAddressExpr( location, copy( first_label ) ) ) };
     729        // Then go through all the stored labels, and clear the store.
     730        for ( auto && label : labels ) {
     731                inits.push_back( new ast::SingleInit( label.location,
     732                        new ast::LabelAddressExpr( label.location, std::move( label )
     733                        ) ) );
     734        }
     735        labels.clear();
     736        // Then construct the initializer itself.
     737        auto init = new ast::ListInit( location, std::move( inits ) );
     738
     739        ast::ObjectDecl * generatorLabels = new ast::ObjectDecl(
     740                location,
     741                "__generator_labels",
     742                new ast::ArrayType(
     743                        new ast::PointerType( new ast::VoidType() ),
     744                        nullptr,
     745                        ast::FixedLen,
     746                        ast::DynamicDim
     747                ),
     748                init,
     749                ast::Storage::Classes(),
     750                ast::Linkage::AutoGen
     751        );
     752
     753        ast::ObjectDecl * generatorLabel = new ast::ObjectDecl(
     754                location,
     755                "__generator_label",
     756                new ast::PointerType( new ast::VoidType() ),
     757                new ast::SingleInit( location,
     758                        new ast::UntypedExpr( location,
     759                                new ast::NameExpr( location, "?[?]" ),
     760                                {
     761                                        // TODO: Could be a variable expr.
     762                                        new ast::NameExpr( location, "__generator_labels" ),
     763                                        new ast::UntypedMemberExpr( location,
     764                                                new ast::NameExpr( location, "__generator_state" ),
     765                                                new ast::VariableExpr( location, in_generator )
     766                                        )
     767                                }
     768                        )
     769                ),
     770                ast::Storage::Classes(),
     771                ast::Linkage::AutoGen
     772        );
     773
     774        ast::BranchStmt * theGoTo = new ast::BranchStmt(
     775                location, new ast::VariableExpr( location, generatorLabel )
     776        );
     777
     778        // The noop goes here in order.
     779
     780        ast::CompoundStmt * body = new ast::CompoundStmt( location, {
     781                { new ast::DeclStmt( location, generatorLabels ) },
     782                { new ast::DeclStmt( location, generatorLabel ) },
     783                { theGoTo },
     784                { noop },
     785                { decl->stmts },
     786        } );
     787
     788        auto mutDecl = ast::mutate( decl );
     789        mutDecl->stmts = body;
     790        return mutDecl;
     791}
     792
     793const ast::Stmt * SuspendKeyword::postvisit( const ast::SuspendStmt * stmt ) {
     794        switch ( stmt->type ) {
     795        case ast::SuspendStmt::None:
     796                // Use the context to determain the implicit target.
     797                if ( in_generator ) {
     798                        return make_generator_suspend( stmt );
     799                } else {
     800                        return make_coroutine_suspend( stmt );
     801                }
     802        case ast::SuspendStmt::Coroutine:
     803                return make_coroutine_suspend( stmt );
     804        case ast::SuspendStmt::Generator:
     805                // Generator suspends must be directly in a generator.
     806                if ( !in_generator ) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type." );
     807                return make_generator_suspend( stmt );
     808        }
     809        assert( false );
     810        return stmt;
     811}
     812
     813/// Find the real/official suspend declaration.
     814bool SuspendKeyword::is_real_suspend( const ast::FunctionDecl * decl ) {
     815        return ( !decl->linkage.is_mangled
     816                && 0 == decl->params.size()
     817                && 0 == decl->returns.size()
     818                && "__cfactx_suspend" == decl->name );
     819}
     820
     821const ast::Stmt * SuspendKeyword::make_generator_suspend(
     822                const ast::SuspendStmt * stmt ) {
     823        assert( in_generator );
     824        // Target code is:
     825        //   GEN.__generator_state = X;
     826        //   THEN
     827        //   return;
     828        //   __gen_X:;
     829
     830        const CodeLocation & location = stmt->location;
     831
     832        LabelPair label = make_label( stmt );
     833
     834        // This is the context saving statement.
     835        stmtsToAddBefore.push_back( new ast::ExprStmt( location,
     836                new ast::UntypedExpr( location,
     837                        new ast::NameExpr( location, "?=?" ),
     838                        {
     839                                new ast::UntypedMemberExpr( location,
     840                                        new ast::NameExpr( location, "__generator_state" ),
     841                                        new ast::VariableExpr( location, in_generator )
     842                                ),
     843                                ast::ConstantExpr::from_int( location, label.idx ),
     844                        }
     845                )
     846        ) );
     847
     848        // The THEN component is conditional (return is not).
     849        if ( stmt->then ) {
     850                stmtsToAddBefore.push_back( stmt->then.get() );
     851        }
     852        stmtsToAddBefore.push_back( new ast::ReturnStmt( location, nullptr ) );
     853
     854        // The null statement replaces the old suspend statement.
     855        return new ast::NullStmt( location, { label.obj } );
     856}
     857
     858const ast::Stmt * SuspendKeyword::make_coroutine_suspend(
     859                const ast::SuspendStmt * stmt ) {
     860        // The only thing we need from the old statement is the location.
     861        const CodeLocation & location = stmt->location;
     862
     863        if ( !decl_suspend ) {
     864                SemanticError( location, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n" );
     865        }
     866        if ( stmt->then ) {
     867                SemanticError( location, "Compound statement following coroutines is not implemented." );
     868        }
     869
     870        return new ast::ExprStmt( location,
     871                new ast::UntypedExpr( location,
     872                        ast::VariableExpr::functionPointer( location, decl_suspend ) )
     873        );
     874}
     875
     876// --------------------------------------------------------------------------
     877struct MutexKeyword final : public ast::WithDeclsToAdd<> {
    40878        const ast::FunctionDecl * postvisit( const ast::FunctionDecl * decl );
    41879        void postvisit( const ast::StructDecl * decl );
     
    50888        ast::CompoundStmt * addStatements( const ast::CompoundStmt * body, const std::vector<ast::ptr<ast::Expr>> & args );
    51889        ast::CompoundStmt * addThreadDtorStatements( const ast::FunctionDecl* func, const ast::CompoundStmt * body, const std::vector<const ast::DeclWithType *> & args );
    52 
     890        ast::ExprStmt * genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param);
     891        ast::IfStmt * genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam );
    53892private:
    54893        const ast::StructDecl * monitor_decl = nullptr;
     
    59898
    60899        static ast::ptr<ast::Type> generic_func;
     900
     901        UniqueName mutex_func_namer = UniqueName("__lock_unlock_curr");
    61902};
    62903
     
    1601001
    1611002const ast::Stmt * MutexKeyword::postvisit( const ast::MutexStmt * stmt ) {
     1003        if ( !lock_guard_decl ) {
     1004                SemanticError( stmt->location, "mutex stmt requires a header, add #include <mutex_stmt.hfa>\n" );
     1005        }
    1621006        ast::CompoundStmt * body =
    1631007                        new ast::CompoundStmt( stmt->location, { stmt->stmt } );
    164         addStatements( body, stmt->mutexObjs );
    165         return body;
     1008       
     1009        return addStatements( body, stmt->mutexObjs );;
    1661010}
    1671011
     
    2511095                                {
    2521096                                        new ast::SingleInit( location,
    253                                                 new ast::AddressExpr(
     1097                                                new ast::AddressExpr( location,
    2541098                                                        new ast::VariableExpr( location, monitor ) ) ),
    2551099                                        new ast::SingleInit( location,
     
    3581202}
    3591203
     1204// generates a cast to the void ptr to the appropriate lock type and dereferences it before calling lock or unlock on it
     1205// used to undo the type erasure done by storing all the lock pointers as void
     1206ast::ExprStmt * MutexKeyword::genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param ) {
     1207        return new ast::ExprStmt( location,
     1208                new ast::UntypedExpr( location,
     1209                        new ast::NameExpr( location, fnName ), {
     1210                                ast::UntypedExpr::createDeref(
     1211                                        location,
     1212                                        new ast::CastExpr( location,
     1213                                                param,
     1214                                                new ast::PointerType( new ast::TypeofType( new ast::UntypedExpr(
     1215                                                        expr->location,
     1216                                                        new ast::NameExpr( expr->location, "__get_mutexstmt_lock_type" ),
     1217                                                        { expr }
     1218                                                ) ) ),
     1219                                                ast::GeneratedFlag::ExplicitCast
     1220                                        )
     1221                                )
     1222                        }
     1223                )
     1224        );
     1225}
     1226
     1227ast::IfStmt * MutexKeyword::genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam ) {
     1228        ast::IfStmt * outerLockIf = nullptr;
     1229        ast::IfStmt * lastLockIf = nullptr;
     1230
     1231        //adds an if/elif clause for each lock to assign type from void ptr based on ptr address
     1232        for ( long unsigned int i = 0; i < args.size(); i++ ) {
     1233               
     1234                ast::UntypedExpr * ifCond = new ast::UntypedExpr( location,
     1235                        new ast::NameExpr( location, "?==?" ), {
     1236                                ast::deepCopy( thisParam ),
     1237                                new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() ))
     1238                        }
     1239                );
     1240
     1241                ast::IfStmt * currLockIf = new ast::IfStmt(
     1242                        location,
     1243                        ifCond,
     1244                        genVirtLockUnlockExpr( fnName, args.at(i), location, ast::deepCopy( thisParam ) )
     1245                );
     1246               
     1247                if ( i == 0 ) {
     1248                        outerLockIf = currLockIf;
     1249                } else {
     1250                        // add ifstmt to else of previous stmt
     1251                        lastLockIf->else_ = currLockIf;
     1252                }
     1253
     1254                lastLockIf = currLockIf;
     1255        }
     1256        return outerLockIf;
     1257}
     1258
    3601259ast::CompoundStmt * MutexKeyword::addStatements(
    3611260                const ast::CompoundStmt * body,
    3621261                const std::vector<ast::ptr<ast::Expr>> & args ) {
    363         ast::CompoundStmt * mutBody = ast::mutate( body );
    3641262
    3651263        // Code is generated near the beginning of the compound statement.
    366         const CodeLocation & location = mutBody->location;
     1264        const CodeLocation & location = body->location;
     1265
     1266                // final body to return
     1267        ast::CompoundStmt * newBody = new ast::CompoundStmt( location );
     1268
     1269        // std::string lockFnName = mutex_func_namer.newName();
     1270        // std::string unlockFnName = mutex_func_namer.newName();
    3671271
    3681272        // Make pointer to the monitors.
     
    3721276                new ast::ArrayType(
    3731277                        new ast::PointerType(
    374                                 new ast::TypeofType(
    375                                         new ast::UntypedExpr(
    376                                                 location,
    377                                                 new ast::NameExpr( location, "__get_type" ),
    378                                                 { args.front() }
    379                                         )
    380                                 )
     1278                                new ast::VoidType()
    3811279                        ),
    3821280                        ast::ConstantExpr::from_ulong( location, args.size() ),
     
    3921290                                                new ast::UntypedExpr(
    3931291                                                        expr->location,
    394                                                         new ast::NameExpr( expr->location, "__get_ptr" ),
     1292                                                        new ast::NameExpr( expr->location, "__get_mutexstmt_lock_ptr" ),
    3951293                                                        { expr }
    3961294                                                )
     
    4051303        ast::StructInstType * lock_guard_struct =
    4061304                        new ast::StructInstType( lock_guard_decl );
    407         ast::TypeExpr * lock_type_expr = new ast::TypeExpr(
    408                 location,
    409                 new ast::TypeofType(
    410                         new ast::UntypedExpr(
    411                                 location,
    412                                 new ast::NameExpr( location, "__get_type" ),
    413                                 { args.front() }
    414                         )
    415                 )
    416         );
    417 
    418         lock_guard_struct->params.push_back( lock_type_expr );
    419 
    420         // In reverse order:
     1305
     1306        // use try stmts to lock and finally to unlock
     1307        ast::TryStmt * outerTry = nullptr;
     1308        ast::TryStmt * currentTry;
     1309        ast::CompoundStmt * lastBody = nullptr;
     1310
     1311        // adds a nested try stmt for each lock we are locking
     1312        for ( long unsigned int i = 0; i < args.size(); i++ ) {
     1313                ast::UntypedExpr * innerAccess = new ast::UntypedExpr(
     1314                        location,
     1315                        new ast::NameExpr( location,"?[?]" ), {
     1316                                new ast::NameExpr( location, "__monitors" ),
     1317                                ast::ConstantExpr::from_int( location, i )
     1318                        }
     1319                );
     1320
     1321                // make the try body
     1322                ast::CompoundStmt * currTryBody = new ast::CompoundStmt( location );
     1323                ast::IfStmt * lockCall = genTypeDiscrimLockUnlock( "lock", args, location, innerAccess );
     1324                currTryBody->push_back( lockCall );
     1325
     1326                // make the finally stmt
     1327                ast::CompoundStmt * currFinallyBody = new ast::CompoundStmt( location );
     1328                ast::IfStmt * unlockCall = genTypeDiscrimLockUnlock( "unlock", args, location, innerAccess );
     1329                currFinallyBody->push_back( unlockCall );
     1330
     1331                // construct the current try
     1332                currentTry = new ast::TryStmt(
     1333                        location,
     1334                        currTryBody,
     1335                        {},
     1336                        new ast::FinallyClause( location, currFinallyBody )
     1337                );
     1338                if ( i == 0 ) outerTry = currentTry;
     1339                else {
     1340                        // pushback try into the body of the outer try
     1341                        lastBody->push_back( currentTry );
     1342                }
     1343                lastBody = currTryBody;
     1344        }
     1345
     1346        // push body into innermost try body
     1347        if ( lastBody != nullptr ) {
     1348                lastBody->push_back( body );
     1349                newBody->push_front( outerTry );
     1350        }
     1351
    4211352        // monitor_guard_t __guard = { __monitors, # };
    422         mutBody->push_front(
     1353        newBody->push_front(
    4231354                new ast::DeclStmt(
    4241355                        location,
     
    4471378
    4481379        // monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) };
    449         mutBody->push_front( new ast::DeclStmt( location, monitors ) );
    450 
    451         return mutBody;
     1380        newBody->push_front( new ast::DeclStmt( location, monitors ) );
     1381
     1382        // // The parameter for both __lock_curr/__unlock_curr routines.
     1383        // ast::ObjectDecl * this_decl = new ast::ObjectDecl(
     1384        //      location,
     1385        //      "this",
     1386        //      new ast::PointerType( new ast::VoidType() ),
     1387        //      nullptr,
     1388        //      {},
     1389        //      ast::Linkage::Cforall
     1390        // );
     1391
     1392        // ast::FunctionDecl * lock_decl = new ast::FunctionDecl(
     1393        //      location,
     1394        //      lockFnName,
     1395        //      { /* forall */ },
     1396        //      {
     1397        //              // Copy the declaration of this.
     1398        //              this_decl,
     1399        //      },
     1400        //      { /* returns */ },
     1401        //      nullptr,
     1402        //      0,
     1403        //      ast::Linkage::Cforall,
     1404        //      { /* attributes */ },
     1405        //      ast::Function::Inline
     1406        // );
     1407
     1408        // ast::FunctionDecl * unlock_decl = new ast::FunctionDecl(
     1409        //      location,
     1410        //      unlockFnName,
     1411        //      { /* forall */ },
     1412        //      {
     1413        //              // Copy the declaration of this.
     1414        //              ast::deepCopy( this_decl ),
     1415        //      },
     1416        //      { /* returns */ },
     1417        //      nullptr,
     1418        //      0,
     1419        //      ast::Linkage::Cforall,
     1420        //      { /* attributes */ },
     1421        //      ast::Function::Inline
     1422        // );
     1423
     1424        // ast::IfStmt * outerLockIf = nullptr;
     1425        // ast::IfStmt * outerUnlockIf = nullptr;
     1426        // ast::IfStmt * lastLockIf = nullptr;
     1427        // ast::IfStmt * lastUnlockIf = nullptr;
     1428
     1429        // //adds an if/elif clause for each lock to assign type from void ptr based on ptr address
     1430        // for ( long unsigned int i = 0; i < args.size(); i++ ) {
     1431        //      ast::VariableExpr * thisParam = new ast::VariableExpr( location, InitTweak::getParamThis( lock_decl ) );
     1432        //      ast::UntypedExpr * ifCond = new ast::UntypedExpr( location,
     1433        //              new ast::NameExpr( location, "?==?" ), {
     1434        //                      thisParam,
     1435        //                      new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() ))
     1436        //              }
     1437        //      );
     1438
     1439        //      ast::IfStmt * currLockIf = new ast::IfStmt(
     1440        //              location,
     1441        //              ast::deepCopy( ifCond ),
     1442        //              genVirtLockUnlockExpr( "lock", args.at(i), location, ast::deepCopy( thisParam ) )
     1443        //      );
     1444
     1445        //      ast::IfStmt * currUnlockIf = new ast::IfStmt(
     1446        //              location,
     1447        //              ifCond,
     1448        //              genVirtLockUnlockExpr( "unlock", args.at(i), location, ast::deepCopy( thisParam ) )
     1449        //      );
     1450               
     1451        //      if ( i == 0 ) {
     1452        //              outerLockIf = currLockIf;
     1453        //              outerUnlockIf = currUnlockIf;
     1454        //      } else {
     1455        //              // add ifstmt to else of previous stmt
     1456        //              lastLockIf->else_ = currLockIf;
     1457        //              lastUnlockIf->else_ = currUnlockIf;
     1458        //      }
     1459
     1460        //      lastLockIf = currLockIf;
     1461        //      lastUnlockIf = currUnlockIf;
     1462        // }
     1463       
     1464        // // add pointer typing if/elifs to body of routines
     1465        // lock_decl->stmts = new ast::CompoundStmt( location, { outerLockIf } );
     1466        // unlock_decl->stmts = new ast::CompoundStmt( location, { outerUnlockIf } );
     1467
     1468        // // add routines to scope
     1469        // declsToAddBefore.push_back( lock_decl );
     1470        // declsToAddBefore.push_back( unlock_decl );
     1471
     1472        // newBody->push_front(new ast::DeclStmt( location, lock_decl ));
     1473        // newBody->push_front(new ast::DeclStmt( location, unlock_decl ));
     1474
     1475        return newBody;
    4521476}
    4531477
     
    5641588
    5651589// --------------------------------------------------------------------------
     1590// Interface Functions:
    5661591
    5671592void implementKeywords( ast::TranslationUnit & translationUnit ) {
    568         (void)translationUnit;
    569         assertf(false, "Apply Keywords not implemented." );
     1593        ast::Pass<ThreadKeyword>::run( translationUnit );
     1594        ast::Pass<CoroutineKeyword>::run( translationUnit );
     1595        ast::Pass<MonitorKeyword>::run( translationUnit );
     1596        ast::Pass<GeneratorKeyword>::run( translationUnit );
     1597        ast::Pass<SuspendKeyword>::run( translationUnit );
    5701598}
    5711599
  • src/ControlStruct/ExceptTranslateNew.cpp

    r4559b34 r92538ab  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Nov  8 11:53:00 2021
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan 31 18:49:58 2022
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Mar 11 17:51:00 2022
     13// Update Count     : 2
    1414//
    1515
     
    2626namespace {
    2727
    28         typedef std::list<ast::CatchStmt*> CatchList;
    29 
    30         void split( CatchList& allHandlers, CatchList& terHandlers,
    31                                 CatchList& resHandlers ) {
    32                 while ( !allHandlers.empty() ) {
    33                         ast::CatchStmt * stmt = allHandlers.front();
    34                         allHandlers.pop_front();
    35                         if (stmt->kind == ast::ExceptionKind::Terminate) {
    36                                 terHandlers.push_back(stmt);
    37                         } else {
    38                                 resHandlers.push_back(stmt);
    39                         }
    40                 }
    41         }
     28        typedef std::list<ast::CatchClause*> CatchList;
    4229
    4330        void appendDeclStmt( ast::CompoundStmt * block, ast::DeclWithType * item ) {
     
    5845        {}
    5946
    60         void previsit( const ast::CatchStmt * stmt );
     47        void previsit( const ast::CatchClause * stmt );
    6148        const ast::Stmt * postvisit( const ast::ThrowStmt * stmt );
    6249};
     
    10188}
    10289
    103 void TranslateThrowsCore::previsit( const ast::CatchStmt * stmt ) {
     90void TranslateThrowsCore::previsit( const ast::CatchClause * stmt ) {
    10491        // Validate the statement's form.
    10592        const ast::ObjectDecl * decl = stmt->decl.as<ast::ObjectDecl>();
     
    160147        ast::FunctionDecl * create_terminate_catch( CatchList &handlers );
    161148        ast::CompoundStmt * create_single_matcher(
    162                 const ast::DeclWithType * except_obj, ast::CatchStmt * modded_handler );
     149                const ast::DeclWithType * except_obj, ast::CatchClause * modded_handler );
    163150        ast::FunctionDecl * create_terminate_match( CatchList &handlers );
    164151        ast::CompoundStmt * create_terminate_caller( CodeLocation loc, ast::FunctionDecl * try_wrapper,
     
    171158        ast::Stmt * create_resume_rethrow( const ast::ThrowStmt * throwStmt );
    172159
    173         // Types used in translation, make sure to use clone.
     160        // Types used in translation, first group are internal.
     161        ast::ObjectDecl * make_index_object( CodeLocation const & ) const;
     162        ast::ObjectDecl * make_exception_object( CodeLocation const & ) const;
     163        ast::ObjectDecl * make_bool_object( CodeLocation const & ) const;
     164        ast::ObjectDecl * make_voidptr_object( CodeLocation const & ) const;
     165        ast::ObjectDecl * make_unused_index_object( CodeLocation const & ) const;
    174166        // void (*function)();
    175         ast::FunctionDecl * try_func_t;
     167        ast::FunctionDecl * make_try_function( CodeLocation const & ) const;
    176168        // void (*function)(int, exception);
    177         ast::FunctionDecl * catch_func_t;
     169        ast::FunctionDecl * make_catch_function( CodeLocation const & ) const;
    178170        // int (*function)(exception);
    179         ast::FunctionDecl * match_func_t;
     171        ast::FunctionDecl * make_match_function( CodeLocation const & ) const;
    180172        // bool (*function)(exception);
    181         ast::FunctionDecl * handle_func_t;
     173        ast::FunctionDecl * make_handle_function( CodeLocation const & ) const;
    182174        // void (*function)(__attribute__((unused)) void *);
    183         ast::FunctionDecl * finally_func_t;
    184 
    185         ast::StructInstType * create_except_type() {
    186                 assert( except_decl );
    187                 return new ast::StructInstType( except_decl );
    188         }
    189         void init_func_types();
     175        ast::FunctionDecl * make_finally_function( CodeLocation const & ) const;
    190176
    191177public:
     
    199185};
    200186
    201 void TryMutatorCore::init_func_types() {
     187ast::ObjectDecl * TryMutatorCore::make_index_object(
     188                CodeLocation const & location ) const {
     189        return new ast::ObjectDecl(
     190                location,
     191                "__handler_index",
     192                new ast::BasicType(ast::BasicType::SignedInt),
     193                nullptr, //init
     194                ast::Storage::Classes{},
     195                ast::Linkage::Cforall
     196                );
     197}
     198
     199ast::ObjectDecl * TryMutatorCore::make_exception_object(
     200                CodeLocation const & location ) const {
    202201        assert( except_decl );
    203 
    204         ast::ObjectDecl index_obj(
    205                 {},
    206                 "__handler_index",
    207                 new ast::BasicType(ast::BasicType::SignedInt)
    208                 );
    209         ast::ObjectDecl exception_obj(
    210                 {},
     202        return new ast::ObjectDecl(
     203                location,
    211204                "__exception_inst",
    212205                new ast::PointerType(
    213206                        new ast::StructInstType( except_decl )
    214207                        ),
    215                 NULL
    216                 );
    217         ast::ObjectDecl bool_obj(
    218                 {},
     208                nullptr, //init
     209                ast::Storage::Classes{},
     210                ast::Linkage::Cforall
     211                );
     212}
     213
     214ast::ObjectDecl * TryMutatorCore::make_bool_object(
     215                CodeLocation const & location ) const {
     216        return new ast::ObjectDecl(
     217                location,
    219218                "__ret_bool",
    220219                new ast::BasicType( ast::BasicType::Bool ),
     
    225224                std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
    226225                );
    227         ast::ObjectDecl voidptr_obj(
    228                 {},
     226}
     227
     228ast::ObjectDecl * TryMutatorCore::make_voidptr_object(
     229                CodeLocation const & location ) const {
     230        return new ast::ObjectDecl(
     231                location,
    229232                "__hook",
    230233                new ast::PointerType(
     
    237240                std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
    238241                );
    239 
    240         ast::ObjectDecl unused_index_obj(
    241                 {},
     242}
     243
     244ast::ObjectDecl * TryMutatorCore::make_unused_index_object(
     245                CodeLocation const & location ) const {
     246        return new ast::ObjectDecl(
     247                location,
    242248                "__handler_index",
    243249                new ast::BasicType(ast::BasicType::SignedInt),
     
    248254                std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
    249255        );
    250         //unused_index_obj->attributes.push_back( new Attribute( "unused" ) );
    251 
    252         try_func_t = new ast::FunctionDecl(
    253                 {},
     256}
     257
     258ast::FunctionDecl * TryMutatorCore::make_try_function(
     259                CodeLocation const & location ) const {
     260        return new ast::FunctionDecl(
     261                location,
    254262                "try",
    255263                {}, //forall
     
    260268                ast::Linkage::Cforall
    261269        );
    262 
    263         catch_func_t = new ast::FunctionDecl(
    264                 {},
     270}
     271
     272ast::FunctionDecl * TryMutatorCore::make_catch_function(
     273                CodeLocation const & location ) const {
     274        return new ast::FunctionDecl(
     275                location,
    265276                "catch",
    266277                {}, //forall
    267                 {ast::deepCopy(&index_obj), ast::deepCopy(&exception_obj)},//param
     278                { make_index_object( location ), make_exception_object( location ) },
    268279                {}, //return void
    269280                nullptr,
     
    271282                ast::Linkage::Cforall
    272283        );
    273 
    274         match_func_t = new ast::FunctionDecl(
    275                 {},
     284}
     285
     286ast::FunctionDecl * TryMutatorCore::make_match_function(
     287                CodeLocation const & location ) const {
     288        return new ast::FunctionDecl(
     289                location,
    276290                "match",
    277291                {}, //forall
    278                 {ast::deepCopy(&exception_obj)},
    279                 {ast::deepCopy(&unused_index_obj)},
     292                { make_exception_object( location ) },
     293                { make_unused_index_object( location ) },
    280294                nullptr,
    281295                ast::Storage::Classes{},
    282296                ast::Linkage::Cforall
    283297        );
    284 
    285         handle_func_t = new ast::FunctionDecl(
    286                 {},
     298}
     299
     300ast::FunctionDecl * TryMutatorCore::make_handle_function(
     301                CodeLocation const & location ) const {
     302        return new ast::FunctionDecl(
     303                location,
    287304                "handle",
    288305                {}, //forall
    289                 {ast::deepCopy(&exception_obj)},
    290                 {ast::deepCopy(&bool_obj)},
     306                { make_exception_object( location ) },
     307                { make_bool_object( location ) },
    291308                nullptr,
    292309                ast::Storage::Classes{},
    293310                ast::Linkage::Cforall
    294311        );
    295 
    296         finally_func_t = new ast::FunctionDecl(
    297                 {},
     312}
     313
     314ast::FunctionDecl * TryMutatorCore::make_finally_function(
     315                CodeLocation const & location ) const {
     316        return new ast::FunctionDecl(
     317                location,
    298318                "finally",
    299319                {}, //forall
    300                 {ast::deepCopy(&voidptr_obj)},
     320                { make_voidptr_object( location ) },
    301321                {}, //return void
    302322                nullptr,
     
    304324                ast::Linkage::Cforall
    305325        );
    306 
    307         //catch_func_t.get_parameters().push_back( index_obj.clone() );
    308         //catch_func_t.get_parameters().push_back( exception_obj.clone() );
    309         //match_func_t.get_returnVals().push_back( unused_index_obj );
    310         //match_func_t.get_parameters().push_back( exception_obj.clone() );
    311         //handle_func_t.get_returnVals().push_back( bool_obj.clone() );
    312         //handle_func_t.get_parameters().push_back( exception_obj.clone() );
    313         //finally_func_t.get_parameters().push_back( voidptr_obj.clone() );
    314326}
    315327
    316328// TryStmt Mutation Helpers
    317 
    318 /*
    319 ast::CompoundStmt * TryMutatorCore::take_try_block( ast::TryStmt *tryStmt ) {
    320         ast::CompoundStmt * block = tryStmt->body;
    321         tryStmt->body = nullptr;
    322         return block;
    323 }
    324 */
    325329
    326330ast::FunctionDecl * TryMutatorCore::create_try_wrapper(
    327331                const ast::CompoundStmt *body ) {
    328332
    329         ast::FunctionDecl * ret = ast::deepCopy(try_func_t);
     333        ast::FunctionDecl * ret = make_try_function( body->location );
    330334        ret->stmts = body;
    331335        return ret;
     
    334338ast::FunctionDecl * TryMutatorCore::create_terminate_catch(
    335339                CatchList &handlers ) {
    336         std::vector<ast::ptr<ast::Stmt>> handler_wrappers;
     340        std::vector<ast::ptr<ast::CaseClause>> handler_wrappers;
    337341
    338342        assert (!handlers.empty());
    339343        const CodeLocation loc = handlers.front()->location;
    340344
    341         ast::FunctionDecl * func_t = ast::deepCopy(catch_func_t);
     345        ast::FunctionDecl * func_t = make_catch_function( loc );
    342346        const ast::DeclWithType * index_obj = func_t->params.front();
    343347        const ast::DeclWithType * except_obj = func_t->params.back();
     
    348352        for ( ; it != handlers.end() ; ++it ) {
    349353                ++index;
    350                 ast::CatchStmt * handler = *it;
     354                ast::CatchClause * handler = *it;
    351355                const CodeLocation loc = handler->location;
    352356
     
    386390                // handler->body = nullptr;
    387391
    388                 handler_wrappers.push_back( new ast::CaseStmt(loc,
     392                handler_wrappers.push_back( new ast::CaseClause(loc,
    389393                        ast::ConstantExpr::from_int(loc, index) ,
    390394                        { block, new ast::ReturnStmt( loc, nullptr ) }
     
    393397        // TODO: Some sort of meaningful error on default perhaps?
    394398
    395         /*
    396         std::list<Statement*> stmt_handlers;
    397         while ( !handler_wrappers.empty() ) {
    398                 stmt_handlers.push_back( handler_wrappers.front() );
    399                 handler_wrappers.pop_front();
    400         }
    401         */
    402 
    403         ast::SwitchStmt * handler_lookup = new ast::SwitchStmt(loc,
     399        ast::SwitchStmt * handler_lookup = new ast::SwitchStmt( loc,
    404400                new ast::VariableExpr( loc, index_obj ),
    405401                std::move(handler_wrappers)
    406402                );
    407         ast::CompoundStmt * body = new ast::CompoundStmt(loc,
    408                 {handler_lookup});
     403        ast::CompoundStmt * body = new ast::CompoundStmt( loc, {handler_lookup} );
    409404
    410405        func_t->stmts = body;
     
    415410// except_obj is referenced, modded_handler will be freed.
    416411ast::CompoundStmt * TryMutatorCore::create_single_matcher(
    417                 const ast::DeclWithType * except_obj, ast::CatchStmt * modded_handler ) {
     412                const ast::DeclWithType * except_obj, ast::CatchClause * modded_handler ) {
    418413        // {
    419414        //     `modded_handler.decl`
     
    433428
    434429        // Check for type match.
    435         ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc, 
     430        ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc,
    436431                new ast::VariableExpr(loc, except_obj ),
    437432                local_except->get_type()
     
    445440        }
    446441        // Construct the match condition.
    447         block->push_back( new ast::IfStmt(loc, 
     442        block->push_back( new ast::IfStmt(loc,
    448443                cond, modded_handler->body, nullptr ) );
    449444
    450         // xxx - how does this work in new ast
    451         //modded_handler->set_decl( nullptr );
    452         //modded_handler->set_cond( nullptr );
    453         //modded_handler->set_body( nullptr );
    454         //delete modded_handler;
    455445        return block;
    456446}
     
    467457        ast::CompoundStmt * body = new ast::CompoundStmt(loc);
    468458
    469         ast::FunctionDecl * func_t = ast::deepCopy(match_func_t);
     459        ast::FunctionDecl * func_t = make_match_function( loc );
    470460        const ast::DeclWithType * except_obj = func_t->params.back();
    471461
     
    475465        for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
    476466                ++index;
    477                 ast::CatchStmt * handler = *it;
     467                ast::CatchClause * handler = *it;
    478468
    479469                // Body should have been taken by create_terminate_catch.
     
    490480        }
    491481
    492         body->push_back( new ast::ReturnStmt(loc, 
     482        body->push_back( new ast::ReturnStmt(loc,
    493483                ast::ConstantExpr::from_int( loc, 0 ) ));
    494484
     
    525515        ast::CompoundStmt * body = new ast::CompoundStmt(loc);
    526516
    527         ast::FunctionDecl * func_t = ast::deepCopy(handle_func_t);
     517        ast::FunctionDecl * func_t = make_handle_function( loc );
    528518        const ast::DeclWithType * except_obj = func_t->params.back();
    529519
    530520        CatchList::iterator it;
    531521        for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
    532                 ast::CatchStmt * handler = *it;
     522                ast::CatchClause * handler = *it;
    533523                const CodeLocation loc = handler->location;
    534524                // Modifiy body.
    535525                ast::CompoundStmt * handling_code;
    536526                if (handler->body.as<ast::CompoundStmt>()) {
    537                         handling_code =
    538                         strict_dynamic_cast<ast::CompoundStmt*>( handler->body.get_and_mutate() );
     527                        handling_code = strict_dynamic_cast<ast::CompoundStmt*>(
     528                                handler->body.get_and_mutate() );
    539529                } else {
    540530                        handling_code = new ast::CompoundStmt(loc);
     
    597587                ast::TryStmt * tryStmt ) {
    598588        // void finally() { `finally->block` }
    599         const ast::FinallyStmt * finally = tryStmt->finally;
     589        const ast::FinallyClause * finally = tryStmt->finally;
    600590        const ast::CompoundStmt * body = finally->body;
    601591
    602         ast::FunctionDecl * func_t = ast::deepCopy(finally_func_t);
     592        ast::FunctionDecl * func_t = make_finally_function( tryStmt->location );
    603593        func_t->stmts = body;
    604594
    605         // finally->set_block( nullptr );
    606         // delete finally;
    607595        tryStmt->finally = nullptr;
    608 
    609596
    610597        return func_t;
     
    617604
    618605        const CodeLocation loc = finally_wrapper->location;
    619         // Make Cleanup Attribute.
    620         /*
    621         std::list< ast::Attribute * > attributes;
    622         {
    623                 std::list<  > attr_params;
    624                 attr_params.push_back( nameOf( finally_wrapper ) );
    625                 attributes.push_back( new Attribute( "cleanup", attr_params ) );
    626         }
    627         */
    628 
    629606        return new ast::ObjectDecl(
    630607                loc,
     
    644621        // return false;
    645622        const CodeLocation loc = throwStmt->location;
    646         ast::Stmt * result = new ast::ReturnStmt(loc, 
     623        ast::Stmt * result = new ast::ReturnStmt(loc,
    647624                ast::ConstantExpr::from_bool( loc, false )
    648625                );
    649626        result->labels = throwStmt->labels;
    650         // delete throwStmt; done by postvisit
    651627        return result;
    652628}
     
    660636                assert( nullptr == except_decl );
    661637                except_decl = structDecl;
    662                 init_func_types();
    663638        } else if ( structDecl->name == "__cfaehm_try_resume_node" ) {
    664639                assert( nullptr == node_decl );
     
    706681                }
    707682        }
    708         // split( mutStmt->handlers,
    709         //              termination_handlers, resumption_handlers );
    710683
    711684        if ( resumption_handlers.size() ) {
  • src/ControlStruct/LabelGeneratorNew.cpp

    r4559b34 r92538ab  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // LabelGenerator.cc --
     7// LabelGeneratorNew.cpp --
    88//
    99// Author           : Peter A. Buhr
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb  2 09:11:17 2022
    13 // Update Count     : 72
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Mar 28 10:03:00 2022
     13// Update Count     : 73
    1414//
    1515
     
    2525namespace ControlStruct {
    2626
    27 Label newLabel( const string & suffix, const Stmt * stmt ) {
     27enum { size = 128 };
     28
     29static int newLabelPre( char buf[size], const string & suffix ) {
    2830        static int current = 0;
    2931
    30         assertf( stmt, "CFA internal error: parameter statement cannot be null pointer" );
    31 
    32         enum { size = 128 };
    33         char buf[size];                                                                         // space to build label
    3432        int len = snprintf( buf, size, "__L%d__%s", current++, suffix.c_str() );
    3533        assertf( len < size, "CFA Internal error: buffer overflow creating label" );
     34        return len;
     35}
     36
     37static Label newLabelPost( char buf[size], const CodeLocation & location ) {
     38        Label ret_label( location, buf );
     39        ret_label.attributes.push_back( new Attribute( "unused" ) );
     40        return ret_label;
     41}
     42
     43Label newLabel( const string & suffix, const Stmt * stmt ) {
     44        // Buffer for string manipulation.
     45        char buf[size];
     46
     47        assertf( stmt, "CFA internal error: parameter statement cannot be null pointer" );
     48        int len = newLabelPre( buf, suffix );
    3649
    3750        // What does this do?
     
    4154        } // if
    4255
    43         Label ret_label( stmt->location, buf );
    44         ret_label.attributes.push_back( new Attribute( "unused" ) );
    45         return ret_label;
     56        return newLabelPost( buf, stmt->location );
     57}
     58
     59Label newLabel( const string & suffix, const CodeLocation & location ) {
     60        // Buffer for string manipulation.
     61        char buf[size];
     62
     63        newLabelPre( buf, suffix );
     64        return newLabelPost( buf, location );
    4665}
    4766
  • src/ControlStruct/LabelGeneratorNew.hpp

    r4559b34 r92538ab  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan 31 18:03:09 2022
    13 // Update Count     : 27
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fir Mar 25 15:40:00 2022
     13// Update Count     : 28
    1414//
    1515
     
    1818#include <string>                                                                               // for string
    1919
    20 class Statement;
     20class CodeLocation;
    2121
    2222namespace ast {
     23        class Label;
    2324        class Stmt;
    24         class Label;
    2525} // namespace ast
    2626
    2727namespace ControlStruct {
    2828        ast::Label newLabel( const std::string &, const ast::Stmt * );
     29        ast::Label newLabel( const std::string &, const CodeLocation & );
    2930} // namespace ControlStruct
    3031
  • src/ControlStruct/MultiLevelExit.cpp

    r4559b34 r92538ab  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Nov  1 13:48:00 2021
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb  2 23:07:54 2022
    13 // Update Count     : 33
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Mar 28  9:42:00 2022
     13// Update Count     : 34
    1414//
    1515
     
    4040
    4141        enum Kind {
    42                 ForStmtK, WhileDoStmtK, CompoundStmtK, IfStmtK, CaseStmtK, SwitchStmtK, TryStmtK
     42                ForStmtK, WhileDoStmtK, CompoundStmtK, IfStmtK, CaseClauseK, SwitchStmtK, TryStmtK
    4343        } kind;
    4444
     
    5858        Entry( const IfStmt *stmt, Label breakExit ) :
    5959                stmt( stmt ), firstTarget( breakExit ), secondTarget(), kind( IfStmtK ) {}
    60         Entry( const CaseStmt *stmt, Label fallExit ) :
    61                 stmt( stmt ), firstTarget( fallExit ), secondTarget(), kind( CaseStmtK ) {}
     60        Entry( const CaseClause *, const CompoundStmt *stmt, Label fallExit ) :
     61                stmt( stmt ), firstTarget( fallExit ), secondTarget(), kind( CaseClauseK ) {}
    6262        Entry( const SwitchStmt *stmt, Label breakExit, Label fallDefaultExit ) :
    6363                stmt( stmt ), firstTarget( breakExit ), secondTarget( fallDefaultExit ), kind( SwitchStmtK ) {}
     
    6666
    6767        bool isContTarget() const { return kind <= WhileDoStmtK; }
    68         bool isBreakTarget() const { return kind != CaseStmtK; }
    69         bool isFallTarget() const { return kind == CaseStmtK; }
     68        bool isBreakTarget() const { return kind != CaseClauseK; }
     69        bool isFallTarget() const { return kind == CaseClauseK; }
    7070        bool isFallDefaultTarget() const { return kind == SwitchStmtK; }
    7171
    7272        // These routines set a target as being "used" by a BranchStmt
    7373        Label useContExit() { assert( kind <= WhileDoStmtK ); return useTarget(secondTarget); }
    74         Label useBreakExit() { assert( kind != CaseStmtK ); return useTarget(firstTarget); }
    75         Label useFallExit() { assert( kind == CaseStmtK );  return useTarget(firstTarget); }
     74        Label useBreakExit() { assert( kind != CaseClauseK ); return useTarget(firstTarget); }
     75        Label useFallExit() { assert( kind == CaseClauseK );  return useTarget(firstTarget); }
    7676        Label useFallDefaultExit() { assert( kind == SwitchStmtK ); return useTarget(secondTarget); }
    7777
    7878        // These routines check if a specific label for a statement is used by a BranchStmt
    7979        bool isContUsed() const { assert( kind <= WhileDoStmtK ); return secondTarget.used; }
    80         bool isBreakUsed() const { assert( kind != CaseStmtK ); return firstTarget.used; }
    81         bool isFallUsed() const { assert( kind == CaseStmtK ); return firstTarget.used; }
     80        bool isBreakUsed() const { assert( kind != CaseClauseK ); return firstTarget.used; }
     81        bool isFallUsed() const { assert( kind == CaseClauseK ); return firstTarget.used; }
    8282        bool isFallDefaultUsed() const { assert( kind == SwitchStmtK ); return secondTarget.used; }
    8383        void seenDefault() { fallDefaultValid = false; }
     
    115115        void previsit( const ForStmt * );
    116116        const ForStmt * postvisit( const ForStmt * );
    117         const CaseStmt * previsit( const CaseStmt * );
     117        const CaseClause * previsit( const CaseClause * );
    118118        void previsit( const IfStmt * );
    119119        const IfStmt * postvisit( const IfStmt * );
     
    123123        void previsit( const TryStmt * );
    124124        void postvisit( const TryStmt * );
    125         void previsit( const FinallyStmt * );
     125        void previsit( const FinallyClause * );
    126126
    127127        const Stmt * mutateLoop( const Stmt * body, Entry& );
     
    288288                  auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt );
    289289                  bool foundDefault = false;
    290                   for ( auto subStmt : switchStmt->stmts ) {
    291                           const CaseStmt * caseStmt = subStmt.strict_as<CaseStmt>();
     290                  for ( auto caseStmt : switchStmt->cases ) {
    292291                          if ( caseStmt->isDefault() ) {
    293292                                  foundDefault = true;
     
    365364}
    366365
    367 const CaseStmt * MultiLevelExitCore::previsit( const CaseStmt * stmt ) {
     366const CaseClause * MultiLevelExitCore::previsit( const CaseClause * stmt ) {
    368367        visit_children = false;
    369368
     
    375374
    376375        // The cond may not exist, but if it does update it now.
    377         visitor->maybe_accept( stmt, &CaseStmt::cond );
     376        visitor->maybe_accept( stmt, &CaseClause::cond );
    378377
    379378        // Just save the mutated node for simplicity.
    380         CaseStmt * mutStmt = mutate( stmt );
    381 
    382         Label fallLabel = newLabel( "fallThrough", stmt );
     379        CaseClause * mutStmt = mutate( stmt );
     380
     381        Label fallLabel = newLabel( "fallThrough", stmt->location );
    383382        if ( ! mutStmt->stmts.empty() ) {
     383                // These should already be in a block.
     384                auto first = mutStmt->stmts.front().get_and_mutate();
     385                auto block = strict_dynamic_cast<CompoundStmt *>( first );
     386
    384387                // Ensure that the stack isn't corrupted by exceptions in fixBlock.
    385388                auto guard = makeFuncGuard(
    386                         [&](){ enclosing_control_structures.emplace_back( mutStmt, fallLabel ); },
     389                        [&](){ enclosing_control_structures.emplace_back( mutStmt, block, fallLabel ); },
    387390                        [this](){ enclosing_control_structures.pop_back(); }
    388391                        );
    389392
    390                 // These should already be in a block.
    391                 auto block = mutate( mutStmt->stmts.front().strict_as<CompoundStmt>() );
    392393                block->kids = fixBlock( block->kids, true );
    393394
     
    396397                Entry & entry = enclosing_control_structures.back();
    397398                if ( entry.isFallUsed() ) {
    398                         mutStmt->stmts.push_back( labelledNullStmt( mutStmt->location, entry.useFallExit() ) );
     399                        mutStmt->stmts.push_back( labelledNullStmt( block->location, entry.useFallExit() ) );
    399400                }
    400401        }
     
    433434}
    434435
    435 bool isDefaultCase( const ptr<Stmt> & stmt ) {
    436         const CaseStmt * caseStmt = stmt.strict_as<CaseStmt>();
    437         return caseStmt->isDefault();
     436static bool isDefaultCase( const ptr<CaseClause> & caseClause ) {
     437        return caseClause->isDefault();
    438438}
    439439
    440440void MultiLevelExitCore::previsit( const SwitchStmt * stmt ) {
    441441        Label label = newLabel( "switchBreak", stmt );
    442         auto it = find_if( stmt->stmts.rbegin(), stmt->stmts.rend(), isDefaultCase );
    443 
    444         const CaseStmt * defaultCase = it != stmt->stmts.rend() ? (it)->strict_as<CaseStmt>() : nullptr;
    445         Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase ) : Label( stmt->location, "" );
     442        auto it = find_if( stmt->cases.rbegin(), stmt->cases.rend(), isDefaultCase );
     443
     444        const CaseClause * defaultCase = it != stmt->cases.rend() ? (*it) : nullptr;
     445        Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase->location ) : Label( stmt->location, "" );
    446446        enclosing_control_structures.emplace_back( stmt, label, defaultLabel );
    447447        GuardAction( [this]() { enclosing_control_structures.pop_back(); } );
     
    449449        // Collect valid labels for fallthrough. It starts with all labels at this level, then remove as each is seen during
    450450        // traversal.
    451         for ( const Stmt * stmt : stmt->stmts ) {
    452                 auto * caseStmt = strict_dynamic_cast< const CaseStmt * >( stmt );
     451        for ( const CaseClause * caseStmt : stmt->cases ) {
    453452                if ( caseStmt->stmts.empty() ) continue;
    454453                auto block = caseStmt->stmts.front().strict_as<CompoundStmt>();
     
    471470                // exit label and break to the last case, create a default case if no cases.
    472471                SwitchStmt * mutStmt = mutate( stmt );
    473                 if ( mutStmt->stmts.empty() ) {
    474                         mutStmt->stmts.push_back( new CaseStmt( mutStmt->location, nullptr, {} ) );
    475                 }
    476 
    477                 auto caseStmt = mutStmt->stmts.back().strict_as<CaseStmt>();
     472                if ( mutStmt->cases.empty() ) {
     473                        mutStmt->cases.push_back( new CaseClause( mutStmt->location, nullptr, {} ) );
     474                }
     475
     476                auto caseStmt = mutStmt->cases.back().get();
    478477                auto mutCase = mutate( caseStmt );
    479                 mutStmt->stmts.back() = mutCase;
     478                mutStmt->cases.back() = mutCase;
    480479
    481480                Label label( mutCase->location, "breakLabel" );
     
    514513}
    515514
    516 void MultiLevelExitCore::previsit( const FinallyStmt * ) {
     515void MultiLevelExitCore::previsit( const FinallyClause * ) {
    517516        GuardAction([this, old = move( enclosing_control_structures)](){ enclosing_control_structures = move(old); });
    518517        enclosing_control_structures = vector<Entry>();
  • src/InitTweak/FixGlobalInit.cc

    r4559b34 r92538ab  
    113113                accept_all(translationUnit, fixer);
    114114
     115                // Say these magic declarations come at the end of the file.
     116                CodeLocation const & location = translationUnit.decls.back()->location;
     117
    115118                if ( !fixer.core.initStmts.empty() ) {
    116119                        std::vector<ast::ptr<ast::Expr>> ctorParams;
    117                         if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int({}, 200));
    118                         auto initFunction = new ast::FunctionDecl({}, "__global_init__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.initStmts)),
    119                                 ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("constructor", std::move(ctorParams))});
     120                        if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
     121                        auto initFunction = new ast::FunctionDecl(location,
     122                                "__global_init__", {}, {}, {},
     123                                new ast::CompoundStmt(location, std::move(fixer.core.initStmts)),
     124                                ast::Storage::Static, ast::Linkage::C,
     125                                {new ast::Attribute("constructor", std::move(ctorParams))});
    120126
    121127                        translationUnit.decls.emplace_back( initFunction );
     
    124130                if ( !fixer.core.destroyStmts.empty() ) {
    125131                        std::vector<ast::ptr<ast::Expr>> dtorParams;
    126                         if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int({}, 200));
    127                         auto destroyFunction = new ast::FunctionDecl({}, "__global_destroy__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.destroyStmts)),
    128                                 ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("destructor", std::move(dtorParams))});
     132                        if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
     133                        auto destroyFunction = new ast::FunctionDecl( location,
     134                                "__global_destroy__", {}, {}, {},
     135                                new ast::CompoundStmt(location, std::move(fixer.core.destroyStmts)),
     136                                ast::Storage::Static, ast::Linkage::C,
     137                                {new ast::Attribute("destructor", std::move(dtorParams))});
    129138
    130139                        translationUnit.decls.emplace_back(destroyFunction);
  • src/InitTweak/FixInitNew.cpp

    r4559b34 r92538ab  
    1616#include "CodeGen/GenType.h"           // for genPrettyType
    1717#include "CodeGen/OperatorTable.h"
     18#include "Common/CodeLocationTools.hpp"
    1819#include "Common/PassVisitor.h"        // for PassVisitor, WithStmtsToAdd
    1920#include "Common/SemanticError.h"      // for SemanticError
     
    8586        /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both
    8687        /// arguments and return value temporaries
    87         struct ResolveCopyCtors final : public ast::WithGuards, public ast::WithStmtsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithVisitorRef<ResolveCopyCtors> {
     88        struct ResolveCopyCtors final : public ast::WithGuards, public ast::WithStmtsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithVisitorRef<ResolveCopyCtors>, public ast::WithConstTranslationUnit {
    8889                const ast::Expr * postvisit( const ast::ImplicitCopyCtorExpr * impCpCtorExpr );
    8990                const ast::StmtExpr * previsit( const ast::StmtExpr * stmtExpr );
     
    189190        /// for any member that is missing a corresponding ctor/dtor call.
    190191        /// error if a member is used before constructed
    191         struct GenStructMemberCalls final : public ast::WithGuards, public ast::WithShortCircuiting, public ast::WithSymbolTable, public ast::WithVisitorRef<GenStructMemberCalls> {
     192        struct GenStructMemberCalls final : public ast::WithGuards, public ast::WithShortCircuiting, public ast::WithSymbolTable, public ast::WithVisitorRef<GenStructMemberCalls>, public ast::WithConstTranslationUnit {
    192193                void previsit( const ast::FunctionDecl * funcDecl );
    193194                const ast::DeclWithType * postvisit( const ast::FunctionDecl * funcDecl );
     
    214215
    215216        /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
    216         struct FixCtorExprs final : public ast::WithDeclsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting {
     217        struct FixCtorExprs final : public ast::WithDeclsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithConstTranslationUnit {
    217218                const ast::Expr * postvisit( const ast::ConstructorExpr * ctorExpr );
    218219        };
     
    509510                // (VariableExpr and already resolved expression)
    510511                CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
    511                 ast::ptr<ast::Expr> resolved = ResolvExpr::findVoidExpression(untyped, symtab);
     512                ast::ptr<ast::Expr> resolved = ResolvExpr::findVoidExpression(untyped, { symtab, transUnit().global } );
    512513                assert( resolved );
    513514                if ( resolved->env ) {
     
    553554                ast::ptr<ast::Expr> guard = mutArg;
    554555
    555                 ast::ptr<ast::ObjectDecl> tmp = new ast::ObjectDecl({}, "__tmp", mutResult, nullptr );
     556                ast::ptr<ast::ObjectDecl> tmp = new ast::ObjectDecl(loc, "__tmp", mutResult, nullptr );
    556557
    557558                // create and resolve copy constructor
     
    587588
    588589        ast::Expr * ResolveCopyCtors::destructRet( const ast::ObjectDecl * ret, const ast::Expr * arg ) {
     590                auto global = transUnit().global;
    589591                // TODO: refactor code for generating cleanup attribute, since it's common and reused in ~3-4 places
    590592                // check for existing cleanup attribute before adding another(?)
    591593                // need to add __Destructor for _tmp_cp variables as well
    592594
    593                 assertf( ast::dtorStruct, "Destructor generation requires __Destructor definition." );
    594                 assertf( ast::dtorStruct->members.size() == 2, "__Destructor definition does not have expected fields." );
    595                 assertf( ast::dtorStructDestroy, "Destructor generation requires __destroy_Destructor." );
     595                assertf( global.dtorStruct, "Destructor generation requires __Destructor definition." );
     596                assertf( global.dtorStruct->members.size() == 2, "__Destructor definition does not have expected fields." );
     597                assertf( global.dtorDestroy, "Destructor generation requires __destroy_Destructor." );
    596598
    597599                const CodeLocation loc = ret->location;
     
    610612                auto dtorFunc = getDtorFunc( ret, new ast::ExprStmt(loc, dtor ), stmtsToAddBefore );
    611613
    612                 auto dtorStructType = new ast::StructInstType(ast::dtorStruct);
     614                auto dtorStructType = new ast::StructInstType( global.dtorStruct );
    613615
    614616                // what does this do???
     
    622624                static UniqueName namer( "_ret_dtor" );
    623625                auto retDtor = new ast::ObjectDecl(loc, namer.newName(), dtorStructType, new ast::ListInit(loc, { new ast::SingleInit(loc, ast::ConstantExpr::null(loc) ), new ast::SingleInit(loc, new ast::CastExpr( new ast::VariableExpr(loc, dtorFunc ), dtorType ) ) } ) );
    624                 retDtor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, ast::dtorStructDestroy ) } ) );
     626                retDtor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, global.dtorDestroy ) } ) );
    625627                stmtsToAddBefore.push_back( new ast::DeclStmt(loc, retDtor ) );
    626628
    627629                if ( arg ) {
    628                         auto member = new ast::MemberExpr(loc, ast::dtorStruct->members.front().strict_as<ast::DeclWithType>(), new ast::VariableExpr(loc, retDtor ) );
     630                        auto member = new ast::MemberExpr(loc, global.dtorStruct->members.front().strict_as<ast::DeclWithType>(), new ast::VariableExpr(loc, retDtor ) );
    629631                        auto object = new ast::CastExpr( new ast::AddressExpr( new ast::VariableExpr(loc, ret ) ), new ast::PointerType(new ast::VoidType() ) );
    630632                        ast::Expr * assign = createBitwiseAssignment( member, object );
     
    799801        // to prevent warnings ('_unq0' may be used uninitialized in this function),
    800802        // insert an appropriate zero initializer for UniqueExpr temporaries.
    801         ast::Init * makeInit( const ast::Type * t ) {
     803        ast::Init * makeInit( const ast::Type * t, CodeLocation const & loc ) {
    802804                if ( auto inst = dynamic_cast< const ast::StructInstType * >( t ) ) {
    803805                        // initizer for empty struct must be empty
    804                         if ( inst->base->members.empty() ) return new ast::ListInit({}, {});
     806                        if ( inst->base->members.empty() ) {
     807                                return new ast::ListInit( loc, {} );
     808                        }
    805809                } else if ( auto inst = dynamic_cast< const ast::UnionInstType * >( t ) ) {
    806810                        // initizer for empty union must be empty
    807                         if ( inst->base->members.empty() ) return new ast::ListInit({}, {});
    808                 }
    809 
    810                 return new ast::ListInit( {}, { new ast::SingleInit( {}, ast::ConstantExpr::from_int({}, 0) ) } );
     811                        if ( inst->base->members.empty() ) {
     812                                return new ast::ListInit( loc, {} );
     813                        }
     814                }
     815
     816                return new ast::ListInit( loc, {
     817                        new ast::SingleInit( loc, ast::ConstantExpr::from_int( loc, 0 ) )
     818                } );
    811819        }
    812820
     
    832840                        } else {
    833841                                // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
    834                                 mutExpr->object = new ast::ObjectDecl( mutExpr->location, toString("_unq", mutExpr->id), mutExpr->result, makeInit( mutExpr->result ) );
     842                                mutExpr->object = new ast::ObjectDecl( mutExpr->location, toString("_unq", mutExpr->id), mutExpr->result, makeInit( mutExpr->result, mutExpr->location ) );
    835843                                mutExpr->var = new ast::VariableExpr( mutExpr->location, mutExpr->object );
    836844                        }
     
    11721180                        auto guard = makeFuncGuard( [this]() { symtab.enterScope(); }, [this]() { symtab.leaveScope(); } );
    11731181                        symtab.addFunction( function );
     1182                        auto global = transUnit().global;
    11741183
    11751184                        // need to iterate through members in reverse in order for
     
    12171226
    12181227                                                        static UniqueName memberDtorNamer = { "__memberDtor" };
    1219                                                         assertf( ast::dtorStruct, "builtin __Destructor not found." );
    1220                                                         assertf( ast::dtorStructDestroy, "builtin __destroy_Destructor not found." );
     1228                                                        assertf( global.dtorStruct, "builtin __Destructor not found." );
     1229                                                        assertf( global.dtorDestroy, "builtin __destroy_Destructor not found." );
    12211230
    12221231                                                        ast::Expr * thisExpr = new ast::CastExpr( new ast::AddressExpr( new ast::VariableExpr(loc, thisParam ) ), new ast::PointerType( new ast::VoidType(), ast::CV::Qualifiers() ) );
     
    12281237                                                        auto dtorType = new ast::PointerType( dtorFtype );
    12291238
    1230                                                         auto destructor = new ast::ObjectDecl(loc, memberDtorNamer.newName(), new ast::StructInstType( ast::dtorStruct ), new ast::ListInit(loc, { new ast::SingleInit(loc, thisExpr ), new ast::SingleInit(loc, new ast::CastExpr( dtorExpr, dtorType ) ) } ) );
    1231                                                         destructor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr({}, ast::dtorStructDestroy ) } ) );
     1239                                                        auto destructor = new ast::ObjectDecl(loc, memberDtorNamer.newName(), new ast::StructInstType( global.dtorStruct ), new ast::ListInit(loc, { new ast::SingleInit(loc, thisExpr ), new ast::SingleInit(loc, new ast::CastExpr( dtorExpr, dtorType ) ) } ) );
     1240                                                        destructor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr( loc, global.dtorDestroy ) } ) );
    12321241                                                        mutStmts->push_front( new ast::DeclStmt(loc, destructor ) );
    12331242                                                        mutStmts->kids.splice( mutStmts->kids.begin(), stmtsToAdd );
     
    13231332
    13241333        const ast::Expr * GenStructMemberCalls::postvisit( const ast::UntypedExpr * untypedExpr ) {
    1325                 // Expression * newExpr = untypedExpr;
    13261334                // xxx - functions returning ast::ptr seems wrong...
    1327                 auto res = ResolvExpr::findVoidExpression( untypedExpr, symtab );
    1328                 return res.release();
    1329                 // return newExpr;
     1335                auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } );
     1336                // Fix CodeLocation (at least until resolver is fixed).
     1337                auto fix = localFillCodeLocations( untypedExpr->location, res.release() );
     1338                return strict_dynamic_cast<const ast::Expr *>( fix );
    13301339        }
    13311340
     
    13611370
    13621371                // resolve assignment and dispose of new env
    1363                 auto resolved = ResolvExpr::findVoidExpression( assign, symtab );
     1372                auto resolved = ResolvExpr::findVoidExpression( assign, { symtab, transUnit().global } );
    13641373                auto mut = resolved.get_and_mutate();
    13651374                assertf(resolved.get() == mut, "newly resolved expression must be unique");
  • src/InitTweak/InitTweak.cc

    r4559b34 r92538ab  
    423423                                loc, targetLabel.newName(), { new ast::Attribute{ "unused" } } };
    424424
    425                         std::vector< ast::ptr< ast::Stmt > > branches;
     425                        std::vector< ast::ptr< ast::CaseClause > > branches;
    426426                        for ( const ast::Init * init : *listInit ) {
    427427                                auto condition = ast::ConstantExpr::from_ulong( loc, cond );
     
    432432                                stmts.emplace_back(
    433433                                        new ast::BranchStmt{ loc, ast::BranchStmt::Break, switchLabel } );
    434                                 branches.emplace_back( new ast::CaseStmt{ loc, condition, std::move( stmts ) } );
     434                                branches.emplace_back( new ast::CaseClause{ loc, condition, std::move( stmts ) } );
    435435                        }
    436436                        out.emplace_back( new ast::SwitchStmt{ loc, index, std::move( branches ) } );
  • src/Parser/parser.yy

    r4559b34 r92538ab  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  1 11:06:13 2022
    13 // Update Count     : 5167
     12// Last Modified On : Mon Mar 14 16:35:29 2022
     13// Update Count     : 5276
    1414//
    1515
     
    610610        // | RESUME '(' comma_expression ')' compound_statement
    611611        //      { SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; }
     612        | IDENTIFIER IDENTIFIER                                                         // syntax error
     613                {
     614                        SemanticError( yylloc, ::toString( "Adjacent identifiers are not meaningful in an expression. "
     615                                                                                           "Possible problem is identifier \"", *$1.str,
     616                                                                                           "\" is a misspelled typename or an incorrectly specified type name, "
     617                                                                                           "e.g., missing generic parameter or missing struct/union/enum before typename." ) );
     618                        $$ = nullptr;
     619                }
     620        | IDENTIFIER direct_type                                                        // syntax error
     621                {
     622                        SemanticError( yylloc, ::toString( "Identifier \"", *$1.str, "\" cannot appear before a type. "
     623                                                                                           "Possible problem is misspelled storage or CV qualifier." ) );
     624                        $$ = nullptr;
     625                }
    612626        ;
    613627
     
    638652                        // Historic, transitional: Disallow commas in subscripts.
    639653                        // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts.
    640                 // { SemanticError( yylloc, "New array subscript is currently unimplemented." ); $$ = nullptr; }
    641654                        // Current: Commas in subscripts make tuples.
    642655                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
     
    647660                // equivalent to the old x[i,j].
    648661                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
     662        | constant '[' assignment_expression ']'                        // 3[a], 'a'[a], 3.5[a]
     663                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
     664        | string_literal '[' assignment_expression ']'          // "abc"[3], 3["abc"]
     665                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); }
    649666        | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call
    650667                {
     
    10521069        identifier_or_type_name ':' attribute_list_opt statement
    10531070                { $$ = $4->add_label( $1, $3 ); }
     1071        | identifier_or_type_name ':' attribute_list_opt error // syntax error
     1072                {
     1073                        SemanticError( yylloc, ::toString( "Label \"", *$1.str, "\" must be associated with a statement, "
     1074                                                                                           "where a declaration, case, or default is not a statement. "
     1075                                                                                           "Move the label or terminate with a semi-colon." ) );
     1076                        $$ = nullptr;
     1077                }
    10541078        ;
    10551079
     
    10861110        | statement_list_nodecl statement
    10871111                { assert( $1 ); $1->set_last( $2 ); $$ = $1; }
     1112        | statement_list_nodecl error                                           // syntax error
     1113                { SemanticError( yylloc, "Declarations only allowed at the start of the switch body, i.e., after the '{'." ); $$ = nullptr; }
    10881114        ;
    10891115
     
    10931119        | MUTEX '(' ')' comma_expression ';'
    10941120                { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); }
    1095                 // { SemanticError( yylloc, "Mutex expression is currently unimplemented." ); $$ = nullptr; }
    10961121        ;
    10971122
     
    11131138                        $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    11141139                }
     1140        | SWITCH '(' comma_expression ')' '{' error '}'         // CFA, syntax error
     1141                { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; }
    11151142        | CHOOSE '(' comma_expression ')' case_clause           // CFA
    11161143                { $$ = new StatementNode( build_switch( false, $3, $5 ) ); }
     
    11201147                        $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    11211148                }
     1149        | CHOOSE '(' comma_expression ')' '{' error '}'         // CFA, syntax error
     1150                { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; }
    11221151        ;
    11231152
     
    11581187
    11591188case_label:                                                                                             // CFA
    1160         CASE case_value_list ':'                                        { $$ = $2; }
     1189        CASE error                                                                                      // syntax error
     1190                { SemanticError( yylloc, "Missing case list after case." ); $$ = nullptr; }
     1191        | CASE case_value_list ':'                                      { $$ = $2; }
     1192        | CASE case_value_list error                                            // syntax error
     1193                { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; }
    11611194        | DEFAULT ':'                                                           { $$ = new StatementNode( build_default() ); }
    11621195                // A semantic check is required to ensure only one default clause per switch/choose statement.
    1163         ;
    1164 
    1165 //label_list_opt:
    1166 //      // empty
    1167 //      | identifier_or_type_name ':'
    1168 //      | label_list_opt identifier_or_type_name ':'
    1169 //      ;
     1196        | DEFAULT error                                                                         //  syntax error
     1197                { SemanticError( yylloc, "Missing colon after default." ); $$ = nullptr; }
     1198        ;
    11701199
    11711200case_label_list:                                                                                // CFA
     
    11971226                { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
    11981227        | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA
    1199                 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
    12001228                { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); }
    12011229        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
     
    12041232                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
    12051233        | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
    1206                 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
    12071234                { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); }
    12081235        | FOR '(' ')' statement                                                         // CFA => for ( ;; )
     
    12111238                { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
    12121239        | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
    1213                 // { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
    12141240                { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); }
    12151241        ;
     
    14061432        | when_clause_opt ELSE statement
    14071433                { $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); }
    1408                 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    1409         | when_clause_opt timeout statement WOR ELSE statement
     1434        // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
     1435        | when_clause_opt timeout statement WOR ELSE statement // syntax error
    14101436                { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    14111437        | when_clause_opt timeout statement WOR when_clause ELSE statement
     
    27352761        | ASM '(' string_literal ')' ';'                                        // GCC, global assembler statement
    27362762                { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, 0 ) ) ); }
     2763        | EXTERN STRINGliteral
     2764                {
     2765                        linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
     2766                        linkage = LinkageSpec::update( yylloc, linkage, $2 );
     2767                }
     2768          up external_definition down
     2769                {
     2770                        linkage = linkageStack.top();
     2771                        linkageStack.pop();
     2772                        $$ = $5;
     2773                }
    27372774        | EXTERN STRINGliteral                                                          // C++-style linkage specifier
    27382775                {
  • src/ResolvExpr/CandidateFinder.cpp

    r4559b34 r92538ab  
    1010// Created On       : Wed Jun 5 14:30:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  1 14:55:00 2019
    13 // Update Count     : 2
     12// Last Modified On : Wed Mar 16 11:58:00 2022
     13// Update Count     : 3
    1414//
    1515
     
    595595        /// Actually visits expressions to find their candidate interpretations
    596596        class Finder final : public ast::WithShortCircuiting {
     597                const ResolveContext & context;
    597598                const ast::SymbolTable & symtab;
    598599        public:
     
    618619
    619620                Finder( CandidateFinder & f )
    620                 : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    621                   targetType( f.targetType ) {}
     621                : context( f.context ), symtab( context.symtab ), selfFinder( f ),
     622                  candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {}
    622623
    623624                void previsit( const ast::Node * ) { visit_children = false; }
     
    872873                        Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );
    873874
    874                         CandidateFinder funcFinder{ symtab, tenv };
     875                        CandidateFinder funcFinder( context, tenv );
    875876                        if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) {
    876877                                auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);
     
    918919                        // find function operators
    919920                        ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" };
    920                         CandidateFinder opFinder{ symtab, tenv };
     921                        CandidateFinder opFinder( context, tenv );
    921922                        // okay if there aren't any function operations
    922923                        opFinder.find( opExpr, ResolvMode::withoutFailFast() );
     
    10591060
    10601061                void postvisit( const ast::AddressExpr * addressExpr ) {
    1061                         CandidateFinder finder{ symtab, tenv };
     1062                        CandidateFinder finder( context, tenv );
    10621063                        finder.find( addressExpr->arg );
    10631064
     
    10791080                        ast::ptr< ast::Type > toType = castExpr->result;
    10801081                        assert( toType );
    1081                         toType = resolveTypeof( toType, symtab );
     1082                        toType = resolveTypeof( toType, context );
    10821083                        // toType = SymTab::validateType( castExpr->location, toType, symtab );
    10831084                        toType = adjustExprType( toType, tenv, symtab );
    10841085
    1085                         CandidateFinder finder{ symtab, tenv, toType };
     1086                        CandidateFinder finder( context, tenv, toType );
    10861087                        finder.find( castExpr->arg, ResolvMode::withAdjustment() );
    10871088
     
    11361137                void postvisit( const ast::VirtualCastExpr * castExpr ) {
    11371138                        assertf( castExpr->result, "Implicit virtual cast targets not yet supported." );
    1138                         CandidateFinder finder{ symtab, tenv };
     1139                        CandidateFinder finder( context, tenv );
    11391140                        // don't prune here, all alternatives guaranteed to have same type
    11401141                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
     
    11531154                        auto target = inst->base.get();
    11541155
    1155                         CandidateFinder finder{ symtab, tenv };
     1156                        CandidateFinder finder( context, tenv );
    11561157
    11571158                        auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) {
     
    12021203
    12031204                void postvisit( const ast::UntypedMemberExpr * memberExpr ) {
    1204                         CandidateFinder aggFinder{ symtab, tenv };
     1205                        CandidateFinder aggFinder( context, tenv );
    12051206                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    12061207                        for ( CandidateRef & agg : aggFinder.candidates ) {
     
    12871288                                addCandidate(
    12881289                                        new ast::SizeofExpr{
    1289                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
     1290                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) },
    12901291                                        tenv );
    12911292                        } else {
    12921293                                // find all candidates for the argument to sizeof
    1293                                 CandidateFinder finder{ symtab, tenv };
     1294                                CandidateFinder finder( context, tenv );
    12941295                                finder.find( sizeofExpr->expr );
    12951296                                // find the lowest-cost candidate, otherwise ambiguous
     
    13111312                                addCandidate(
    13121313                                        new ast::AlignofExpr{
    1313                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
     1314                                                alignofExpr->location, resolveTypeof( alignofExpr->type, context ) },
    13141315                                        tenv );
    13151316                        } else {
    13161317                                // find all candidates for the argument to alignof
    1317                                 CandidateFinder finder{ symtab, tenv };
     1318                                CandidateFinder finder( context, tenv );
    13181319                                finder.find( alignofExpr->expr );
    13191320                                // find the lowest-cost candidate, otherwise ambiguous
     
    13541355
    13551356                void postvisit( const ast::LogicalExpr * logicalExpr ) {
    1356                         CandidateFinder finder1{ symtab, tenv };
     1357                        CandidateFinder finder1( context, tenv );
    13571358                        finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() );
    13581359                        if ( finder1.candidates.empty() ) return;
    13591360
    1360                         CandidateFinder finder2{ symtab, tenv };
     1361                        CandidateFinder finder2( context, tenv );
    13611362                        finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
    13621363                        if ( finder2.candidates.empty() ) return;
     
    13841385                void postvisit( const ast::ConditionalExpr * conditionalExpr ) {
    13851386                        // candidates for condition
    1386                         CandidateFinder finder1{ symtab, tenv };
     1387                        CandidateFinder finder1( context, tenv );
    13871388                        finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );
    13881389                        if ( finder1.candidates.empty() ) return;
    13891390
    13901391                        // candidates for true result
    1391                         CandidateFinder finder2{ symtab, tenv };
     1392                        CandidateFinder finder2( context, tenv );
    13921393                        finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );
    13931394                        if ( finder2.candidates.empty() ) return;
    13941395
    13951396                        // candidates for false result
    1396                         CandidateFinder finder3{ symtab, tenv };
     1397                        CandidateFinder finder3( context, tenv );
    13971398                        finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    13981399                        if ( finder3.candidates.empty() ) return;
     
    14451446                void postvisit( const ast::CommaExpr * commaExpr ) {
    14461447                        ast::TypeEnvironment env{ tenv };
    1447                         ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1448 
    1449                         CandidateFinder finder2{ symtab, env };
     1448                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env );
     1449
     1450                        CandidateFinder finder2( context, env );
    14501451                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
    14511452
     
    14601461
    14611462                void postvisit( const ast::ConstructorExpr * ctorExpr ) {
    1462                         CandidateFinder finder{ symtab, tenv };
     1463                        CandidateFinder finder( context, tenv );
    14631464                        finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() );
    14641465                        for ( CandidateRef & r : finder.candidates ) {
     
    14691470                void postvisit( const ast::RangeExpr * rangeExpr ) {
    14701471                        // resolve low and high, accept candidates where low and high types unify
    1471                         CandidateFinder finder1{ symtab, tenv };
     1472                        CandidateFinder finder1( context, tenv );
    14721473                        finder1.find( rangeExpr->low, ResolvMode::withAdjustment() );
    14731474                        if ( finder1.candidates.empty() ) return;
    14741475
    1475                         CandidateFinder finder2{ symtab, tenv };
     1476                        CandidateFinder finder2( context, tenv );
    14761477                        finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
    14771478                        if ( finder2.candidates.empty() ) return;
     
    15491550
    15501551                void postvisit( const ast::UniqueExpr * unqExpr ) {
    1551                         CandidateFinder finder{ symtab, tenv };
     1552                        CandidateFinder finder( context, tenv );
    15521553                        finder.find( unqExpr->expr, ResolvMode::withAdjustment() );
    15531554                        for ( CandidateRef & r : finder.candidates ) {
     
    15581559
    15591560                void postvisit( const ast::StmtExpr * stmtExpr ) {
    1560                         addCandidate( resolveStmtExpr( stmtExpr, symtab ), tenv );
     1561                        addCandidate( resolveStmtExpr( stmtExpr, context ), tenv );
    15611562                }
    15621563
     
    15701571                        for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) {
    15711572                                // calculate target type
    1572                                 const ast::Type * toType = resolveTypeof( initAlt.type, symtab );
     1573                                const ast::Type * toType = resolveTypeof( initAlt.type, context );
    15731574                                // toType = SymTab::validateType( initExpr->location, toType, symtab );
    15741575                                toType = adjustExprType( toType, tenv, symtab );
     
    15761577                                // types are not bound to the initialization type, since return type variables are
    15771578                                // only open for the duration of resolving the UntypedExpr.
    1578                                 CandidateFinder finder{ symtab, tenv, toType };
     1579                                CandidateFinder finder( context, tenv, toType );
    15791580                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
    15801581                                for ( CandidateRef & cand : finder.candidates ) {
     
    16931694                }
    16941695                else {
    1695                         satisfyAssertions(candidate, localSyms, satisfied, errors);
     1696                        satisfyAssertions(candidate, context.symtab, satisfied, errors);
    16961697                        needRecomputeKey = true;
    16971698                }
     
    18551856                        r->expr = ast::mutate_field(
    18561857                                r->expr.get(), &ast::Expr::result,
    1857                                 adjustExprType( r->expr->result, r->env, localSyms ) );
     1858                                adjustExprType( r->expr->result, r->env, context.symtab ) );
    18581859                }
    18591860        }
     
    18731874
    18741875        for ( const auto & x : xs ) {
    1875                 out.emplace_back( localSyms, env );
     1876                out.emplace_back( context, env );
    18761877                out.back().find( x, ResolvMode::withAdjustment() );
    18771878
  • src/ResolvExpr/CandidateFinder.hpp

    r4559b34 r92538ab  
    1010// Created On       : Wed Jun 5 14:30:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  1  9:51:00 2019
    13 // Update Count     : 2
     12// Last Modified On : Wed Mar 16 15:22:00 2022
     13// Update Count     : 3
    1414//
    1515
     
    2525namespace ResolvExpr {
    2626
     27struct ResolveContext;
     28
    2729/// Data to perform expression resolution
    2830struct CandidateFinder {
    2931        CandidateList candidates;          ///< List of candidate resolutions
    30         const ast::SymbolTable & localSyms;   ///< Symbol table to lookup candidates
     32        const ResolveContext & context;  ///< Information about where the canditates are being found.
    3133        const ast::TypeEnvironment & env;  ///< Substitutions performed in this resolution
    3234        ast::ptr< ast::Type > targetType;  ///< Target type for resolution
     
    3436
    3537        CandidateFinder(
    36                 const ast::SymbolTable & syms, const ast::TypeEnvironment & env,
     38                const ResolveContext & context, const ast::TypeEnvironment & env,
    3739                const ast::Type * tt = nullptr )
    38         : candidates(), localSyms( syms ), env( env ), targetType( tt ) {}
     40        : candidates(), context( context ), env( env ), targetType( tt ) {}
    3941
    4042        /// Fill candidates with feasible resolutions for `expr`
  • src/ResolvExpr/CandidatePrinter.cpp

    r4559b34 r92538ab  
    1010// Created On       : Tue Nov  9  9:54:00 2021
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Nov  9 15:47:00 2021
    13 // Update Count     : 0
     12// Last Modified On : Wed Mar 16 13:56:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    2222#include "AST/TranslationUnit.hpp"
    2323#include "ResolvExpr/CandidateFinder.hpp"
     24#include "ResolvExpr/Resolver.h"
    2425
    2526#include <iostream>
     
    2930namespace {
    3031
    31 class CandidatePrintCore : public ast::WithSymbolTable {
     32class CandidatePrintCore : public ast::WithSymbolTable,
     33                public ast::WithConstTranslationUnit {
    3234        std::ostream & os;
    3335public:
     
    3638        void postvisit( const ast::ExprStmt * stmt ) {
    3739                ast::TypeEnvironment env;
    38                 CandidateFinder finder( symtab, env );
     40                CandidateFinder finder( { symtab, transUnit().global }, env );
    3941                finder.find( stmt->expr, ResolvMode::withAdjustment() );
    4042                int count = 1;
  • src/ResolvExpr/RenameVars.h

    r4559b34 r92538ab  
    3636        };
    3737        const ast::Type * renameTyVars( const ast::Type *, RenameMode mode = GEN_USAGE, bool reset = true );
    38        
    3938
    4039        /// resets internal state of renamer to avoid overflow
    4140        void resetTyVarRenaming();
    42 
    43        
    4441} // namespace ResolvExpr
    4542
  • src/ResolvExpr/ResolveTypeof.cc

    r4559b34 r92538ab  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:12:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 19 16:49:04 2015
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Mar 16 16:09:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    2222#include "AST/Node.hpp"
    2323#include "AST/Pass.hpp"
     24#include "AST/TranslationUnit.hpp"
    2425#include "AST/Type.hpp"
    2526#include "AST/TypeEnvironment.hpp"
     
    119120namespace {
    120121        struct ResolveTypeof_new : public ast::WithShortCircuiting {
    121                 const ast::SymbolTable & localSymtab;
    122 
    123                 ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {}
     122                const ResolveContext & context;
     123
     124                ResolveTypeof_new( const ResolveContext & context ) :
     125                        context( context ) {}
    124126
    125127                void previsit( const ast::TypeofType * ) { visit_children = false; }
     
    137139                                ast::TypeEnvironment dummy;
    138140                                ast::ptr< ast::Expr > newExpr =
    139                                         resolveInVoidContext( typeofType->expr, localSymtab, dummy );
     141                                        resolveInVoidContext( typeofType->expr, context, dummy );
    140142                                assert( newExpr->result && ! newExpr->result->isVoid() );
    141143                                newType = newExpr->result;
     
    161163} // anonymous namespace
    162164
    163 const ast::Type * resolveTypeof( const ast::Type * type , const ast::SymbolTable & symtab ) {
    164         ast::Pass< ResolveTypeof_new > mutator{ symtab };
     165const ast::Type * resolveTypeof( const ast::Type * type , const ResolveContext & context ) {
     166        ast::Pass< ResolveTypeof_new > mutator( context );
    165167        return type->accept( mutator );
    166168}
    167169
    168170struct FixArrayDimension {
    169         // should not require a mutable symbol table - prevent pass template instantiation
    170         const ast::SymbolTable & _symtab;
    171         FixArrayDimension(const ast::SymbolTable & symtab): _symtab(symtab) {}
     171        const ResolveContext & context;
     172        FixArrayDimension(const ResolveContext & context) : context( context ) {}
    172173
    173174        const ast::ArrayType * previsit (const ast::ArrayType * arrayType) {
    174175                if (!arrayType->dimension) return arrayType;
    175176                auto mutType = mutate(arrayType);
    176                 ast::ptr<ast::Type> sizetype = ast::sizeType ? ast::sizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt);
    177                 mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, _symtab);
     177                auto globalSizeType = context.global.sizeType;
     178                ast::ptr<ast::Type> sizetype = globalSizeType ? globalSizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt);
     179                mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, context );
    178180
    179181                if (InitTweak::isConstExpr(mutType->dimension)) {
     
    187189};
    188190
    189 const ast::Type * fixArrayType( const ast::Type * type, const ast::SymbolTable & symtab) {
    190         ast::Pass<FixArrayDimension> visitor {symtab};
     191const ast::Type * fixArrayType( const ast::Type * type, const ResolveContext & context ) {
     192        ast::Pass<FixArrayDimension> visitor(context);
    191193        return type->accept(visitor);
    192194}
    193195
    194 const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab ) {
    195         if (!decl->isTypeFixed) {
    196                 auto mutDecl = mutate(decl);
    197                 auto resolvedType = resolveTypeof(decl->type, symtab);
    198                 resolvedType = fixArrayType(resolvedType, symtab);
     196const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & context ) {
     197        if (decl->isTypeFixed) {
     198                return decl;
     199        }
     200
     201        auto mutDecl = mutate(decl);
     202        {
     203                auto resolvedType = resolveTypeof(decl->type, context);
     204                resolvedType = fixArrayType(resolvedType, context);
    199205                mutDecl->type = resolvedType;
    200 
    201                 // check variable length if object is an array.
    202                 // xxx - should this be part of fixObjectType?
    203 
    204                 /*
    205                 if (auto arrayType = dynamic_cast<const ast::ArrayType *>(resolvedType)) {
    206                         auto dimExpr = findSingleExpression(arrayType->dimension, ast::sizeType, symtab);
    207                         if (auto varexpr = arrayType->dimension.as<ast::VariableExpr>()) {// hoisted previously
    208                                 if (InitTweak::isConstExpr(varexpr->var.strict_as<ast::ObjectDecl>()->init)) {
    209                                         auto mutType = mutate(arrayType);
    210                                         mutType->isVarLen = ast::LengthFlag::VariableLen;
    211                                         mutDecl->type = mutType;
    212                                 }
    213                         }
    214                 }
    215                 */
    216 
    217 
    218                 if (!mutDecl->name.empty())
    219                         mutDecl->mangleName = Mangle::mangle(mutDecl); // do not mangle unnamed variables
    220                
    221                 mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID);
    222                 mutDecl->isTypeFixed = true;
    223                 return mutDecl;
    224         }
    225         return decl;
     206        }
     207
     208        // Do not mangle unnamed variables.
     209        if (!mutDecl->name.empty()) {
     210                mutDecl->mangleName = Mangle::mangle(mutDecl);
     211        }
     212
     213        mutDecl->type = renameTyVars(mutDecl->type, RenameMode::GEN_EXPR_ID);
     214        mutDecl->isTypeFixed = true;
     215        return mutDecl;
    226216}
    227217
  • src/ResolvExpr/ResolveTypeof.h

    r4559b34 r92538ab  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ResolveTypeof.h -- 
     7// ResolveTypeof.h --
    88//
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:14:53 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:38:35 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Mar 16 11:33:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    2222namespace ast {
    2323        class Type;
    24         class SymbolTable;
    2524        class ObjectDecl;
    2625}
    2726
    2827namespace ResolvExpr {
     28        struct ResolveContext;
     29
    2930        Type *resolveTypeof( Type*, const SymTab::Indexer &indexer );
    30         const ast::Type * resolveTypeof( const ast::Type *, const ast::SymbolTable & );
    31         const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab );
     31        const ast::Type * resolveTypeof( const ast::Type *, const ResolveContext & );
     32        const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & );
    3233} // namespace ResolvExpr
    3334
  • src/ResolvExpr/Resolver.cc

    r4559b34 r92538ab  
    99// Author           : Aaron B. Moss
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  1 16:27:14 2022
    13 // Update Count     : 245
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Mar 18 10:41:00 2022
     13// Update Count     : 247
    1414//
    1515
     
    997997                /// Calls the CandidateFinder and finds the single best candidate
    998998                CandidateRef findUnfinishedKindExpression(
    999                         const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
     999                        const ast::Expr * untyped, const ResolveContext & context, const std::string & kind,
    10001000                        std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
    10011001                ) {
     
    10071007                        ++recursion_level;
    10081008                        ast::TypeEnvironment env;
    1009                         CandidateFinder finder{ symtab, env };
     1009                        CandidateFinder finder( context, env );
    10101010                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    10111011                        --recursion_level;
     
    11291129
    11301130        ast::ptr< ast::Expr > resolveInVoidContext(
    1131                 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env
     1131                const ast::Expr * expr, const ResolveContext & context,
     1132                ast::TypeEnvironment & env
    11321133        ) {
    11331134                assertf( expr, "expected a non-null expression" );
     
    11361137                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
    11371138                CandidateRef choice = findUnfinishedKindExpression(
    1138                         untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
     1139                        untyped, context, "", anyCandidate, ResolvMode::withAdjustment() );
    11391140
    11401141                // a cast expression has either 0 or 1 interpretations (by language rules);
     
    11491150                /// context.
    11501151                ast::ptr< ast::Expr > findVoidExpression(
    1151                         const ast::Expr * untyped, const ast::SymbolTable & symtab
     1152                        const ast::Expr * untyped, const ResolveContext & context
    11521153                ) {
    11531154                        ast::TypeEnvironment env;
    1154                         ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );
     1155                        ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, context, env );
    11551156                        finishExpr( newExpr, env, untyped->env );
    11561157                        return newExpr;
     
    11631164                /// lowest cost, returning the resolved version
    11641165                ast::ptr< ast::Expr > findKindExpression(
    1165                         const ast::Expr * untyped, const ast::SymbolTable & symtab,
     1166                        const ast::Expr * untyped, const ResolveContext & context,
    11661167                        std::function<bool(const Candidate &)> pred = anyCandidate,
    11671168                        const std::string & kind = "", ResolvMode mode = {}
     
    11691170                        if ( ! untyped ) return {};
    11701171                        CandidateRef choice =
    1171                                 findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );
     1172                                findUnfinishedKindExpression( untyped, context, kind, pred, mode );
    11721173                        ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env );
    11731174                        return std::move( choice->expr );
     
    11761177                /// Resolve `untyped` to the single expression whose candidate is the best match
    11771178                ast::ptr< ast::Expr > findSingleExpression(
    1178                         const ast::Expr * untyped, const ast::SymbolTable & symtab
     1179                        const ast::Expr * untyped, const ResolveContext & context
    11791180                ) {
    11801181                        Stats::ResolveTime::start( untyped );
    1181                         auto res = findKindExpression( untyped, symtab );
     1182                        auto res = findKindExpression( untyped, context );
    11821183                        Stats::ResolveTime::stop();
    11831184                        return res;
     
    11861187
    11871188        ast::ptr< ast::Expr > findSingleExpression(
    1188                 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
     1189                const ast::Expr * untyped, const ast::Type * type,
     1190                const ResolveContext & context
    11891191        ) {
    11901192                assert( untyped && type );
    11911193                ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
    1192                 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
    1193                 removeExtraneousCast( newExpr, symtab );
     1194                ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context );
     1195                removeExtraneousCast( newExpr, context.symtab );
    11941196                return newExpr;
    11951197        }
     
    12171219                /// Resolve `untyped` as an integral expression, returning the resolved version
    12181220                ast::ptr< ast::Expr > findIntegralExpression(
    1219                         const ast::Expr * untyped, const ast::SymbolTable & symtab
     1221                        const ast::Expr * untyped, const ResolveContext & context
    12201222                ) {
    1221                         return findKindExpression( untyped, symtab, hasIntegralType, "condition" );
     1223                        return findKindExpression( untyped, context, hasIntegralType, "condition" );
    12221224                }
    12231225
     
    12491251                // for work previously in GenInit
    12501252                static InitTweak::ManagedTypes_new managedTypes;
     1253                ResolveContext context;
    12511254
    12521255                bool inEnumDecl = false;
     
    12541257        public:
    12551258                static size_t traceId;
    1256                 Resolver_new() = default;
    1257                 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
     1259                Resolver_new( const ast::TranslationGlobal & global ) :
     1260                        context{ symtab, global } {}
     1261                Resolver_new( const ResolveContext & context ) :
     1262                        ast::WithSymbolTable{ context.symtab },
     1263                        context{ symtab, context.global } {}
    12581264
    12591265                const ast::FunctionDecl * previsit( const ast::FunctionDecl * );
     
    12721278                const ast::AsmStmt *         previsit( const ast::AsmStmt * );
    12731279                const ast::IfStmt *          previsit( const ast::IfStmt * );
    1274                 const ast::WhileDoStmt *       previsit( const ast::WhileDoStmt * );
     1280                const ast::WhileDoStmt *     previsit( const ast::WhileDoStmt * );
    12751281                const ast::ForStmt *         previsit( const ast::ForStmt * );
    12761282                const ast::SwitchStmt *      previsit( const ast::SwitchStmt * );
    1277                 const ast::CaseStmt *        previsit( const ast::CaseStmt * );
     1283                const ast::CaseClause *      previsit( const ast::CaseClause * );
    12781284                const ast::BranchStmt *      previsit( const ast::BranchStmt * );
    12791285                const ast::ReturnStmt *      previsit( const ast::ReturnStmt * );
    12801286                const ast::ThrowStmt *       previsit( const ast::ThrowStmt * );
    1281                 const ast::CatchStmt *       previsit( const ast::CatchStmt * );
    1282                 const ast::CatchStmt *       postvisit( const ast::CatchStmt * );
     1287                const ast::CatchClause *     previsit( const ast::CatchClause * );
     1288                const ast::CatchClause *     postvisit( const ast::CatchClause * );
    12831289                const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
    12841290                const ast::WithStmt *        previsit( const ast::WithStmt * );
     
    12991305
    13001306        void resolve( ast::TranslationUnit& translationUnit ) {
    1301                 ast::Pass< Resolver_new >::run( translationUnit );
     1307                ast::Pass< Resolver_new >::run( translationUnit, translationUnit.global );
    13021308        }
    13031309
    13041310        ast::ptr< ast::Init > resolveCtorInit(
    1305                 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab
     1311                const ast::ConstructorInit * ctorInit, const ResolveContext & context
    13061312        ) {
    13071313                assert( ctorInit );
    1308                 ast::Pass< Resolver_new > resolver{ symtab };
     1314                ast::Pass< Resolver_new > resolver( context );
    13091315                return ctorInit->accept( resolver );
    13101316        }
    13111317
    13121318        const ast::Expr * resolveStmtExpr(
    1313                 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab
     1319                const ast::StmtExpr * stmtExpr, const ResolveContext & context
    13141320        ) {
    13151321                assert( stmtExpr );
    1316                 ast::Pass< Resolver_new > resolver{ symtab };
     1322                ast::Pass< Resolver_new > resolver( context );
    13171323                auto ret = mutate(stmtExpr->accept(resolver));
    13181324                strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult();
     
    13211327
    13221328        namespace {
    1323                 const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ast::SymbolTable & symtab) {
     1329                const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ResolveContext & context) {
    13241330                        std::string name = attr->normalizedName();
    13251331                        if (name == "constructor" || name == "destructor") {
    13261332                                if (attr->params.size() == 1) {
    13271333                                        auto arg = attr->params.front();
    1328                                         auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), symtab );
     1334                                        auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), context );
    13291335                                        auto result = eval(arg);
    13301336
     
    13691375
    13701376                        for (auto & attr: mutDecl->attributes) {
    1371                                 attr = handleAttribute(mutDecl->location, attr, symtab);
     1377                                attr = handleAttribute(mutDecl->location, attr, context );
    13721378                        }
    13731379
     
    13791385                        for (auto & typeParam : mutDecl->type_params) {
    13801386                                symtab.addType(typeParam);
    1381                                 mutType->forall.emplace_back(new ast::TypeInstType(typeParam->name, typeParam));
     1387                                mutType->forall.emplace_back(new ast::TypeInstType(typeParam));
    13821388                        }
    13831389                        for (auto & asst : mutDecl->assertions) {
    1384                                 asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab);
     1390                                asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), context);
    13851391                                symtab.addId(asst);
    13861392                                mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst));
     
    13941400
    13951401                        for (auto & param : mutDecl->params) {
    1396                                 param = fixObjectType(param.strict_as<ast::ObjectDecl>(), symtab);
     1402                                param = fixObjectType(param.strict_as<ast::ObjectDecl>(), context);
    13971403                                symtab.addId(param);
    13981404                                paramTypes.emplace_back(param->get_type());
    13991405                        }
    14001406                        for (auto & ret : mutDecl->returns) {
    1401                                 ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), symtab);
     1407                                ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), context);
    14021408                                returnTypes.emplace_back(ret->get_type());
    14031409                        }
     
    14981504                else {
    14991505                        if (!objectDecl->isTypeFixed) {
    1500                                 auto newDecl = fixObjectType(objectDecl, symtab);
     1506                                auto newDecl = fixObjectType(objectDecl, context);
    15011507                                auto mutDecl = mutate(newDecl);
    15021508
     
    15291535                        // nested type decls are hoisted already. no need to do anything
    15301536                        if (auto obj = member.as<ast::ObjectDecl>()) {
    1531                                 member = fixObjectType(obj, symtab);
     1537                                member = fixObjectType(obj, context);
    15321538                        }
    15331539                }
     
    15521558                return ast::mutate_field(
    15531559                        assertDecl, &ast::StaticAssertDecl::cond,
    1554                         findIntegralExpression( assertDecl->cond, symtab ) );
     1560                        findIntegralExpression( assertDecl->cond, context ) );
    15551561        }
    15561562
    15571563        template< typename PtrType >
    1558         const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
     1564        const PtrType * handlePtrType( const PtrType * type, const ResolveContext & context ) {
    15591565                if ( type->dimension ) {
    1560                         ast::ptr< ast::Type > sizeType = ast::sizeType;
     1566                        ast::ptr< ast::Type > sizeType = context.global.sizeType;
    15611567                        ast::mutate_field(
    15621568                                type, &PtrType::dimension,
    1563                                 findSingleExpression( type->dimension, sizeType, symtab ) );
     1569                                findSingleExpression( type->dimension, sizeType, context ) );
    15641570                }
    15651571                return type;
     
    15671573
    15681574        const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) {
    1569                 return handlePtrType( at, symtab );
     1575                return handlePtrType( at, context );
    15701576        }
    15711577
    15721578        const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) {
    1573                 return handlePtrType( pt, symtab );
     1579                return handlePtrType( pt, context );
    15741580        }
    15751581
     
    15791585
    15801586                return ast::mutate_field(
    1581                         exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) );
     1587                        exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, context ) );
    15821588        }
    15831589
     
    15861592
    15871593                asmExpr = ast::mutate_field(
    1588                         asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) );
     1594                        asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, context ) );
    15891595
    15901596                return asmExpr;
     
    16001606        const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
    16011607                return ast::mutate_field(
    1602                         ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) );
     1608                        ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, context ) );
    16031609        }
    16041610
    16051611        const ast::WhileDoStmt * Resolver_new::previsit( const ast::WhileDoStmt * whileDoStmt ) {
    16061612                return ast::mutate_field(
    1607                         whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, symtab ) );
     1613                        whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, context ) );
    16081614        }
    16091615
     
    16111617                if ( forStmt->cond ) {
    16121618                        forStmt = ast::mutate_field(
    1613                                 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) );
     1619                                forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, context ) );
    16141620                }
    16151621
    16161622                if ( forStmt->inc ) {
    16171623                        forStmt = ast::mutate_field(
    1618                                 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) );
     1624                                forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, context ) );
    16191625                }
    16201626
     
    16261632                switchStmt = ast::mutate_field(
    16271633                        switchStmt, &ast::SwitchStmt::cond,
    1628                         findIntegralExpression( switchStmt->cond, symtab ) );
     1634                        findIntegralExpression( switchStmt->cond, context ) );
    16291635                currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };
    16301636                return switchStmt;
    16311637        }
    16321638
    1633         const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
     1639        const ast::CaseClause * Resolver_new::previsit( const ast::CaseClause * caseStmt ) {
    16341640                if ( caseStmt->cond ) {
    16351641                        std::deque< ast::InitAlternative > initAlts = currentObject.getOptions();
     
    16391645                        ast::ptr< ast::Expr > untyped =
    16401646                                new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
    1641                         ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab );
     1647                        ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, context );
    16421648
    16431649                        // case condition cannot have a cast in C, so it must be removed here, regardless of
     
    16471653                        }
    16481654
    1649                         caseStmt = ast::mutate_field( caseStmt, &ast::CaseStmt::cond, newExpr );
     1655                        caseStmt = ast::mutate_field( caseStmt, &ast::CaseClause::cond, newExpr );
    16501656                }
    16511657                return caseStmt;
     
    16601666                        branchStmt = ast::mutate_field(
    16611667                                branchStmt, &ast::BranchStmt::computedTarget,
    1662                                 findSingleExpression( branchStmt->computedTarget, target, symtab ) );
     1668                                findSingleExpression( branchStmt->computedTarget, target, context ) );
    16631669                }
    16641670                return branchStmt;
     
    16701676                        returnStmt = ast::mutate_field(
    16711677                                returnStmt, &ast::ReturnStmt::expr,
    1672                                 findSingleExpression( returnStmt->expr, functionReturn, symtab ) );
     1678                                findSingleExpression( returnStmt->expr, functionReturn, context ) );
    16731679                }
    16741680                return returnStmt;
     
    16851691                        throwStmt = ast::mutate_field(
    16861692                                throwStmt, &ast::ThrowStmt::expr,
    1687                                 findSingleExpression( throwStmt->expr, exceptType, symtab ) );
     1693                                findSingleExpression( throwStmt->expr, exceptType, context ) );
    16881694                }
    16891695                return throwStmt;
    16901696        }
    16911697
    1692         const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
     1698        const ast::CatchClause * Resolver_new::previsit( const ast::CatchClause * catchClause ) {
    16931699                // Until we are very sure this invarent (ifs that move between passes have then)
    16941700                // holds, check it. This allows a check for when to decode the mangling.
    1695                 if ( auto ifStmt = catchStmt->body.as<ast::IfStmt>() ) {
     1701                if ( auto ifStmt = catchClause->body.as<ast::IfStmt>() ) {
    16961702                        assert( ifStmt->then );
    16971703                }
    16981704                // Encode the catchStmt so the condition can see the declaration.
    1699                 if ( catchStmt->cond ) {
    1700                         ast::CatchStmt * stmt = mutate( catchStmt );
    1701                         stmt->body = new ast::IfStmt( stmt->location, stmt->cond, nullptr, stmt->body );
    1702                         stmt->cond = nullptr;
    1703                         return stmt;
    1704                 }
    1705                 return catchStmt;
    1706         }
    1707 
    1708         const ast::CatchStmt * Resolver_new::postvisit( const ast::CatchStmt * catchStmt ) {
     1705                if ( catchClause->cond ) {
     1706                        ast::CatchClause * clause = mutate( catchClause );
     1707                        clause->body = new ast::IfStmt( clause->location, clause->cond, nullptr, clause->body );
     1708                        clause->cond = nullptr;
     1709                        return clause;
     1710                }
     1711                return catchClause;
     1712        }
     1713
     1714        const ast::CatchClause * Resolver_new::postvisit( const ast::CatchClause * catchClause ) {
    17091715                // Decode the catchStmt so everything is stored properly.
    1710                 const ast::IfStmt * ifStmt = catchStmt->body.as<ast::IfStmt>();
     1716                const ast::IfStmt * ifStmt = catchClause->body.as<ast::IfStmt>();
    17111717                if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
    17121718                        assert( ifStmt->cond );
    17131719                        assert( ifStmt->else_ );
    1714                         ast::CatchStmt * stmt = ast::mutate( catchStmt );
    1715                         stmt->cond = ifStmt->cond;
    1716                         stmt->body = ifStmt->else_;
     1720                        ast::CatchClause * clause = ast::mutate( catchClause );
     1721                        clause->cond = ifStmt->cond;
     1722                        clause->body = ifStmt->else_;
    17171723                        // ifStmt should be implicately deleted here.
    1718                         return stmt;
    1719                 }
    1720                 return catchStmt;
     1724                        return clause;
     1725                }
     1726                return catchClause;
    17211727        }
    17221728
     
    17291735
    17301736                        ast::TypeEnvironment env;
    1731                         CandidateFinder funcFinder{ symtab, env };
     1737                        CandidateFinder funcFinder( context, env );
    17321738
    17331739                        // Find all candidates for a function in canonical form
     
    19431949                                );
    19441950
    1945                                 clause2.target.args.emplace_back( findSingleExpression( init, symtab ) );
     1951                                clause2.target.args.emplace_back( findSingleExpression( init, context ) );
    19461952                        }
    19471953
    19481954                        // Resolve the conditions as if it were an IfStmt, statements normally
    1949                         clause2.cond = findSingleExpression( clause.cond, symtab );
     1955                        clause2.cond = findSingleExpression( clause.cond, context );
    19501956                        clause2.stmt = clause.stmt->accept( *visitor );
    19511957
     
    19621968                        ast::ptr< ast::Type > target =
    19631969                                new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
    1964                         timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab );
    1965                         timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab );
     1970                        timeout2.time = findSingleExpression( stmt->timeout.time, target, context );
     1971                        timeout2.cond = findSingleExpression( stmt->timeout.cond, context );
    19661972                        timeout2.stmt = stmt->timeout.stmt->accept( *visitor );
    19671973
     
    19761982                        ast::WaitForStmt::OrElse orElse2;
    19771983
    1978                         orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab );
     1984                        orElse2.cond = findSingleExpression( stmt->orElse.cond, context );
    19791985                        orElse2.stmt = stmt->orElse.stmt->accept( *visitor );
    19801986
     
    19972003                for (auto & expr : exprs) {
    19982004                        // only struct- and union-typed expressions are viable candidates
    1999                         expr = findKindExpression( expr, symtab, structOrUnion, "with expression" );
     2005                        expr = findKindExpression( expr, context, structOrUnion, "with expression" );
    20002006
    20012007                        // if with expression might be impure, create a temporary so that it is evaluated once
     
    20232029                ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
    20242030                        singleInit->location, singleInit->value, currentObject.getOptions() };
    2025                 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab );
     2031                ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, context );
    20262032                const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
    20272033
  • src/ResolvExpr/Resolver.h

    r4559b34 r92538ab  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:18:34 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Feb 18 20:40:38 2019
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Mar 16 11:32:00 2022
     13// Update Count     : 5
    1414//
    1515
     
    2323class Declaration;
    2424class Expression;
     25class DeletedExpr;
    2526class StmtExpr;
     27class Type;
    2628namespace SymTab {
    2729        class Indexer;
     
    3537        class StmtExpr;
    3638        class SymbolTable;
     39        class TranslationGlobal;
    3740        class TranslationUnit;
    3841        class Type;
     
    5558        void resolveWithExprs( std::list< Declaration * > & translationUnit );
    5659
     60        /// Helper Type: Passes around information between various sub-calls.
     61        struct ResolveContext {
     62                const ast::SymbolTable & symtab;
     63                const ast::TranslationGlobal & global;
     64        };
     65
    5766        /// Checks types and binds syntactic constructs to typed representations
    5867        void resolve( ast::TranslationUnit& translationUnit );
     
    6271        /// context.
    6372        ast::ptr< ast::Expr > resolveInVoidContext(
    64                 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env );
     73                const ast::Expr * expr, const ResolveContext &, ast::TypeEnvironment & env );
    6574        /// Resolve `untyped` to the single expression whose candidate is the best match for the
    6675        /// given type.
    6776        ast::ptr< ast::Expr > findSingleExpression(
    68                 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab );
     77                const ast::Expr * untyped, const ast::Type * type, const ResolveContext & );
    6978        ast::ptr< ast::Expr > findVoidExpression(
    70                 const ast::Expr * untyped, const ast::SymbolTable & symtab);
     79                const ast::Expr * untyped, const ResolveContext & );
    7180        /// Resolves a constructor init expression
    7281        ast::ptr< ast::Init > resolveCtorInit(
    73                 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab );
     82                const ast::ConstructorInit * ctorInit, const ResolveContext & context );
    7483        /// Resolves a statement expression
    7584        const ast::Expr * resolveStmtExpr(
    76                 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab );
     85                const ast::StmtExpr * stmtExpr, const ResolveContext & context );
    7786} // namespace ResolvExpr
    7887
  • src/ResolvExpr/Unify.cc

    r4559b34 r92538ab  
    943943                        // check that the other type is compatible and named the same
    944944                        auto otherInst = dynamic_cast< const XInstType * >( other );
    945                         this->result = otherInst && inst->name == otherInst->name;
     945                        if (otherInst && inst->name == otherInst->name) this->result = otherInst;
    946946                        return otherInst;
    947947                }
  • src/SymTab/Validate.cc

    r4559b34 r92538ab  
    194194        };
    195195
     196        // These structs are the sub-sub-passes of ForallPointerDecay_old.
     197
     198        struct TraitExpander_old final {
     199                void previsit( FunctionType * );
     200                void previsit( StructDecl * );
     201                void previsit( UnionDecl * );
     202        };
     203
     204        struct AssertionFixer_old final {
     205                void previsit( FunctionType * );
     206                void previsit( StructDecl * );
     207                void previsit( UnionDecl * );
     208        };
     209
     210        struct CheckOperatorTypes_old final {
     211                void previsit( ObjectDecl * );
     212        };
     213
     214        struct FixUniqueIds_old final {
     215                void previsit( DeclarationWithType * );
     216        };
     217
    196218        struct ReturnChecker : public WithGuards {
    197219                /// Checks that return statements return nothing if their return type is void
     
    373395                                TranslateDimensionGenericParameters::translateDimensions( translationUnit );
    374396                        });
     397                        if (!useNewAST) {
    375398                        Stats::Time::TimeBlock("Resolve Enum Initializers", [&]() {
    376399                                acceptAll( translationUnit, rei ); // must happen after translateDimensions because rei needs identifier lookup, which needs name mangling
    377400                        });
     401                        }
    378402                        Stats::Time::TimeBlock("Check Function Returns", [&]() {
    379403                                ReturnChecker::checkFunctionReturns( translationUnit );
     
    385409        }
    386410
     411        static void decayForallPointers( std::list< Declaration * > & translationUnit ) {
     412                PassVisitor<TraitExpander_old> te;
     413                acceptAll( translationUnit, te );
     414                PassVisitor<AssertionFixer_old> af;
     415                acceptAll( translationUnit, af );
     416                PassVisitor<CheckOperatorTypes_old> cot;
     417                acceptAll( translationUnit, cot );
     418                PassVisitor<FixUniqueIds_old> fui;
     419                acceptAll( translationUnit, fui );
     420        }
     421
    387422        void validate_D( std::list< Declaration * > & translationUnit ) {
    388                 PassVisitor<ForallPointerDecay_old> fpd;
    389423                {
    390424                        Stats::Heap::newPass("validate-D");
     
    394428                        });
    395429                        Stats::Time::TimeBlock("Forall Pointer Decay", [&]() {
    396                                 acceptAll( translationUnit, fpd ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution
     430                                decayForallPointers( translationUnit ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution
    397431                        });
    398432                        Stats::Time::TimeBlock("Hoist Control Declarations", [&]() {
     
    453487        }
    454488
    455         void decayForallPointers( std::list< Declaration * > & translationUnit ) {
    456                 PassVisitor<ForallPointerDecay_old> fpd;
    457                 acceptAll( translationUnit, fpd );
    458         }
    459 
    460489        void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
    461490                validate_A( translationUnit );
     
    470499                PassVisitor<EnumAndPointerDecay_old> epc;
    471500                PassVisitor<LinkReferenceToTypes_old> lrt( indexer );
    472                 PassVisitor<ForallPointerDecay_old> fpd;
     501                PassVisitor<TraitExpander_old> te;
     502                PassVisitor<AssertionFixer_old> af;
     503                PassVisitor<CheckOperatorTypes_old> cot;
     504                PassVisitor<FixUniqueIds_old> fui;
    473505                type->accept( epc );
    474506                type->accept( lrt );
    475                 type->accept( fpd );
     507                type->accept( te );
     508                type->accept( af );
     509                type->accept( cot );
     510                type->accept( fui );
    476511        }
    477512
     
    9841019        }
    9851020
     1021        /// Replace all traits in assertion lists with their assertions.
     1022        void expandTraits( std::list< TypeDecl * > & forall ) {
     1023                for ( TypeDecl * type : forall ) {
     1024                        std::list< DeclarationWithType * > asserts;
     1025                        asserts.splice( asserts.end(), type->assertions );
     1026                        // expand trait instances into their members
     1027                        for ( DeclarationWithType * assertion : asserts ) {
     1028                                if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
     1029                                        // expand trait instance into all of its members
     1030                                        expandAssertions( traitInst, back_inserter( type->assertions ) );
     1031                                        delete traitInst;
     1032                                } else {
     1033                                        // pass other assertions through
     1034                                        type->assertions.push_back( assertion );
     1035                                } // if
     1036                        } // for
     1037                }
     1038        }
     1039
     1040        /// Fix each function in the assertion list and check for invalid void type.
     1041        void fixAssertions(
     1042                        std::list< TypeDecl * > & forall, BaseSyntaxNode * node ) {
     1043                for ( TypeDecl * type : forall ) {
     1044                        for ( DeclarationWithType *& assertion : type->assertions ) {
     1045                                bool isVoid = fixFunction( assertion );
     1046                                if ( isVoid ) {
     1047                                        SemanticError( node, "invalid type void in assertion of function " );
     1048                                } // if
     1049                        } // for
     1050                }
     1051        }
     1052
    9861053        void ForallPointerDecay_old::previsit( ObjectDecl * object ) {
    9871054                // ensure that operator names only apply to functions or function pointers
     
    10061073        void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) {
    10071074                forallFixer( aggrDecl->parameters, aggrDecl );
     1075        }
     1076
     1077        void TraitExpander_old::previsit( FunctionType * ftype ) {
     1078                expandTraits( ftype->forall );
     1079        }
     1080
     1081        void TraitExpander_old::previsit( StructDecl * aggrDecl ) {
     1082                expandTraits( aggrDecl->parameters );
     1083        }
     1084
     1085        void TraitExpander_old::previsit( UnionDecl * aggrDecl ) {
     1086                expandTraits( aggrDecl->parameters );
     1087        }
     1088
     1089        void AssertionFixer_old::previsit( FunctionType * ftype ) {
     1090                fixAssertions( ftype->forall, ftype );
     1091        }
     1092
     1093        void AssertionFixer_old::previsit( StructDecl * aggrDecl ) {
     1094                fixAssertions( aggrDecl->parameters, aggrDecl );
     1095        }
     1096
     1097        void AssertionFixer_old::previsit( UnionDecl * aggrDecl ) {
     1098                fixAssertions( aggrDecl->parameters, aggrDecl );
     1099        }
     1100
     1101        void CheckOperatorTypes_old::previsit( ObjectDecl * object ) {
     1102                // ensure that operator names only apply to functions or function pointers
     1103                if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) {
     1104                        SemanticError( object->location, toCString( "operator ", object->name.c_str(), " is not a function or function pointer." )  );
     1105                }
     1106        }
     1107
     1108        void FixUniqueIds_old::previsit( DeclarationWithType * decl ) {
     1109                decl->fixUniqueId();
    10081110        }
    10091111
  • src/SymTab/Validate.h

    r4559b34 r92538ab  
    4242        void validate_E( std::list< Declaration * > &translationUnit );
    4343        void validate_F( std::list< Declaration * > &translationUnit );
    44         void decayForallPointers( std::list< Declaration * > & translationUnit );
    4544
    4645        const ast::Type * validateType(
  • src/Tuples/TupleAssignment.cc

    r4559b34 r92538ab  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 23:45:33 2019
    13 // Update Count     : 9
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Mar 16 14:06:00 2022
     13// Update Count     : 10
    1414//
    1515
     
    465465                                        // resolve ctor/dtor for the new object
    466466                                        ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(
    467                                                         InitTweak::genCtorInit( location, ret ), spotter.crntFinder.localSyms );
     467                                                        InitTweak::genCtorInit( location, ret ), spotter.crntFinder.context );
    468468                                        // remove environments from subexpressions of stmtExpr
    469469                                        ast::Pass< EnvRemover > rm{ env };
     
    560560                                        // resolve the cast expression so that rhsCand return type is bound by the cast
    561561                                        // type as needed, and transfer the resulting environment
    562                                         ResolvExpr::CandidateFinder finder{ spotter.crntFinder.localSyms, env };
     562                                        ResolvExpr::CandidateFinder finder( spotter.crntFinder.context, env );
    563563                                        finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() );
    564564                                        assert( finder.candidates.size() == 1 );
     
    609609                                        // explode the LHS so that each field of a tuple-valued expr is assigned
    610610                                        ResolvExpr::CandidateList lhs;
    611                                         explode( *lhsCand, crntFinder.localSyms, back_inserter(lhs), true );
     611                                        explode( *lhsCand, crntFinder.context.symtab, back_inserter(lhs), true );
    612612                                        for ( ResolvExpr::CandidateRef & cand : lhs ) {
    613613                                                // each LHS value must be a reference - some come in with a cast, if not
     
    629629                                                        if ( isTuple( rhsCand->expr ) ) {
    630630                                                                // multiple assignment
    631                                                                 explode( *rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
     631                                                                explode( *rhsCand, crntFinder.context.symtab, back_inserter(rhs), true );
    632632                                                                matcher.reset(
    633633                                                                        new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    648648                                                        // multiple assignment
    649649                                                        ResolvExpr::CandidateList rhs;
    650                                                         explode( rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
     650                                                        explode( rhsCand, crntFinder.context.symtab, back_inserter(rhs), true );
    651651                                                        matcher.reset(
    652652                                                                new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    678678                                )
    679679
    680                                 ResolvExpr::CandidateFinder finder{ crntFinder.localSyms, matcher->env };
     680                                ResolvExpr::CandidateFinder finder( crntFinder.context, matcher->env );
    681681
    682682                                try {
  • src/Validate/Autogen.cpp

    r4559b34 r92538ab  
    248248                structInst.params.push_back( new ast::TypeExpr(
    249249                        typeDecl->location,
    250                         new ast::TypeInstType( typeDecl->name, typeDecl )
     250                        new ast::TypeInstType( typeDecl )
    251251                ) );
    252252        }
     
    264264                unionInst.params.push_back( new ast::TypeExpr(
    265265                        unionDecl->location,
    266                         new ast::TypeInstType( typeDecl->name, typeDecl )
     266                        new ast::TypeInstType( typeDecl )
    267267                ) );
    268268        }
  • src/Validate/FindSpecialDeclsNew.cpp

    r4559b34 r92538ab  
    3030
    3131struct FindDeclsCore : public ast::WithShortCircuiting {
    32         ast::TranslationUnit::Global & global;
    33         FindDeclsCore( ast::TranslationUnit::Global & g ) : global( g ) {}
     32        ast::TranslationGlobal & global;
     33        FindDeclsCore( ast::TranslationGlobal & g ) : global( g ) {}
    3434
    3535        void previsit( const ast::Decl * decl );
     
    7474        ast::Pass<FindDeclsCore>::run( translationUnit, translationUnit.global );
    7575
    76         // TODO: When everything gets the globals from the translation unit,
    77         // remove these.
    78         ast::dereferenceOperator = translationUnit.global.dereference;
    79         ast::dtorStruct = translationUnit.global.dtorStruct;
    80         ast::dtorStructDestroy = translationUnit.global.dtorDestroy;
    81 
    8276        // TODO: conditionally generate 'fake' declarations for missing features,
    8377        // so that translation can proceed in the event that builtins, prelude,
  • src/Validate/module.mk

    r4559b34 r92538ab  
    2020        Validate/CompoundLiteral.cpp \
    2121        Validate/CompoundLiteral.hpp \
     22        Validate/ForallPointerDecay.cpp \
     23        Validate/ForallPointerDecay.hpp \
    2224        Validate/HandleAttributes.cc \
    2325        Validate/HandleAttributes.h \
  • src/Virtual/Tables.cc

    r4559b34 r92538ab  
    1010// Created On       : Mon Aug 31 11:11:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Apr 21 15:36:00 2021
    13 // Update Count     : 2
    14 //
    15 
     12// Last Modified On : Fri Mar 11 10:40:00 2022
     13// Update Count     : 3
     14//
     15
     16#include "AST/Attribute.hpp"
     17#include "AST/Copy.hpp"
     18#include "AST/Decl.hpp"
     19#include "AST/Expr.hpp"
     20#include "AST/Init.hpp"
     21#include "AST/Stmt.hpp"
     22#include "AST/Type.hpp"
    1623#include <SynTree/Attribute.h>
    1724#include <SynTree/Declaration.h>
     
    7784}
    7885
     86static ast::ObjectDecl * makeVtableDeclaration(
     87                CodeLocation const & location, std::string const & name,
     88                ast::StructInstType const * type, ast::Init const * init ) {
     89        ast::Storage::Classes storage;
     90        if ( nullptr == init ) {
     91                storage.is_extern = true;
     92        }
     93        return new ast::ObjectDecl(
     94                location,
     95                name,
     96                type,
     97                init,
     98                storage,
     99                ast::Linkage::Cforall
     100        );
     101}
     102
    79103ObjectDecl * makeVtableForward( std::string const & name, StructInstType * type ) {
    80104        assert( type );
    81105        return makeVtableDeclaration( name, type, nullptr );
     106}
     107
     108ast::ObjectDecl * makeVtableForward(
     109                CodeLocation const & location, std::string const & name,
     110                ast::StructInstType const * vtableType ) {
     111        assert( vtableType );
     112        return makeVtableDeclaration( location, name, vtableType, nullptr );
    82113}
    83114
     
    123154}
    124155
     156static std::vector<ast::ptr<ast::Init>> buildInits(
     157                CodeLocation const & location,
     158                //std::string const & name,
     159                ast::StructInstType const * vtableType,
     160                ast::Type const * objectType ) {
     161        ast::StructDecl const * vtableStruct = vtableType->base;
     162
     163        std::vector<ast::ptr<ast::Init>> inits;
     164        inits.reserve( vtableStruct->members.size() );
     165
     166        // This is designed to run before the resolver.
     167        for ( auto field : vtableStruct->members ) {
     168                if ( std::string( "parent" ) == field->name ) {
     169                        // This will not work with polymorphic state.
     170                        auto oField = field.strict_as<ast::ObjectDecl>();
     171                        auto fieldType = oField->type.strict_as<ast::PointerType>();
     172                        auto parentType = fieldType->base.strict_as<ast::StructInstType>();
     173                        std::string const & parentInstance = instanceName( parentType->name );
     174                        inits.push_back(
     175                                        new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, parentInstance ) ) ) );
     176                } else if ( std::string( "__cfavir_typeid" ) == field->name ) {
     177                        std::string const & baseType = baseTypeName( vtableType->name );
     178                        std::string const & typeId = typeIdName( baseType );
     179                        inits.push_back( new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, typeId ) ) ) );
     180                } else if ( std::string( "size" ) == field->name ) {
     181                        inits.push_back( new ast::SingleInit( location, new ast::SizeofExpr( location, objectType )
     182                        ) );
     183                } else if ( std::string( "align" ) == field->name ) {
     184                        inits.push_back( new ast::SingleInit( location,
     185                                new ast::AlignofExpr( location, objectType )
     186                        ) );
     187                } else {
     188                        inits.push_back( new ast::SingleInit( location,
     189                                new ast::NameExpr( location, field->name )
     190                        ) );
     191                }
     192                //ast::Expr * expr = buildInitExpr(...);
     193                //inits.push_back( new ast::SingleInit( location, expr ) )
     194        }
     195
     196        return inits;
     197}
     198
     199ast::ObjectDecl * makeVtableInstance(
     200                CodeLocation const & location,
     201                std::string const & name,
     202                ast::StructInstType const * vtableType,
     203                ast::Type const * objectType,
     204                ast::Init const * init ) {
     205        assert( vtableType );
     206        assert( objectType );
     207
     208        // Build the initialization.
     209        if ( nullptr == init ) {
     210                init = new ast::ListInit( location,
     211                        buildInits( location, vtableType, objectType ) );
     212
     213        // The provided init should initialize everything except the parent
     214        // pointer, the size-of and align-of fields. These should be inserted.
     215        } else {
     216                // Except this is not yet supported.
     217                assert(false);
     218        }
     219        return makeVtableDeclaration( location, name, vtableType, init );
     220}
     221
    125222namespace {
    126223        std::string const functionName = "get_exception_vtable";
     
    140237                new ReferenceType( noQualifiers, vtableType ),
    141238                nullptr,
    142         { new Attribute("unused") }
     239                { new Attribute("unused") }
    143240        ) );
    144241        type->parameters.push_back( new ObjectDecl(
     
    157254                type,
    158255                nullptr
     256        );
     257}
     258
     259ast::FunctionDecl * makeGetExceptionForward(
     260                CodeLocation const & location,
     261                ast::Type const * vtableType,
     262                ast::Type const * exceptType ) {
     263        assert( vtableType );
     264        assert( exceptType );
     265        return new ast::FunctionDecl(
     266                location,
     267                functionName,
     268                { /* forall */ },
     269                { new ast::ObjectDecl(
     270                        location,
     271                        "__unused",
     272                        new ast::PointerType( exceptType )
     273                ) },
     274                { new ast::ObjectDecl(
     275                        location,
     276                        "_retvalue",
     277                        new ast::ReferenceType( vtableType )
     278                ) },
     279                nullptr,
     280                ast::Storage::Classes(),
     281                ast::Linkage::Cforall,
     282                { new ast::Attribute( "unused" ) }
    159283        );
    160284}
     
    172296}
    173297
     298ast::FunctionDecl * makeGetExceptionFunction(
     299                CodeLocation const & location,
     300                ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType ) {
     301        assert( vtableInstance );
     302        assert( exceptType );
     303        ast::FunctionDecl * func = makeGetExceptionForward(
     304                        location, ast::deepCopy( vtableInstance->type ), exceptType );
     305        func->stmts = new ast::CompoundStmt( location, {
     306                new ast::ReturnStmt( location, new ast::VariableExpr( location, vtableInstance ) )
     307        } );
     308        return func;
     309}
     310
    174311ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) {
    175312        assert( typeIdType );
     
    191328}
    192329
    193 }
     330ast::ObjectDecl * makeTypeIdInstance(
     331                CodeLocation const & location,
     332                ast::StructInstType const * typeIdType ) {
     333        assert( typeIdType );
     334        ast::StructInstType * type = ast::mutate( typeIdType );
     335        type->set_const( true );
     336        std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
     337        return new ast::ObjectDecl(
     338                location,
     339                typeid_name,
     340                type,
     341                new ast::ListInit( location, {
     342                        new ast::SingleInit( location,
     343                                new ast::AddressExpr( location,
     344                                        new ast::NameExpr( location, "__cfatid_exception_t" ) ) )
     345                } ),
     346                ast::Storage::Classes(),
     347                ast::Linkage::Cforall,
     348                nullptr,
     349                { new ast::Attribute( "cfa_linkonce" ) }
     350        );
     351}
     352
     353}
  • src/Virtual/Tables.h

    r4559b34 r92538ab  
    1010// Created On       : Mon Aug 31 11:07:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Apr 21 10:30:00 2021
    13 // Update Count     : 2
     12// Last Modified On : Wec Dec  8 16:58:00 2021
     13// Update Count     : 3
    1414//
    1515
    1616#include <list>  // for list
    1717
     18#include <string>
     19#include "AST/Fwd.hpp"
    1820class Declaration;
    1921class StructDecl;
     
    3537 * vtableType node is consumed.
    3638 */
     39ast::ObjectDecl * makeVtableForward(
     40        CodeLocation const & location, std::string const & name,
     41        ast::StructInstType const * vtableType );
    3742
    3843ObjectDecl * makeVtableInstance(
     
    4348 * vtableType and init (if provided) nodes are consumed.
    4449 */
     50ast::ObjectDecl * makeVtableInstance(
     51        CodeLocation const & location,
     52        std::string const & name,
     53        ast::StructInstType const * vtableType,
     54        ast::Type const * objectType,
     55        ast::Init const * init = nullptr );
    4556
    4657// Some special code for how exceptions interact with virtual tables.
     
    4960 * linking the vtableType to the exceptType. Both nodes are consumed.
    5061 */
     62ast::FunctionDecl * makeGetExceptionForward(
     63        CodeLocation const & location,
     64        ast::Type const * vtableType,
     65        ast::Type const * exceptType );
    5166
    5267FunctionDecl * makeGetExceptionFunction(
     
    5570 * exceptType node is consumed.
    5671 */
     72ast::FunctionDecl * makeGetExceptionFunction(
     73        CodeLocation const & location,
     74        ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType );
    5775
    5876ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType );
     
    6078 * TODO: Should take the parent type. Currently locked to the exception_t.
    6179 */
     80ast::ObjectDecl * makeTypeIdInstance(
     81        const CodeLocation & location, ast::StructInstType const * typeIdType );
    6282
    6383}
  • src/main.cc

    r4559b34 r92538ab  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jan 26 14:09:00 2022
    13 // Update Count     : 670
     12// Last Modified On : Fri Mar 11 10:39:00 2022
     13// Update Count     : 671
    1414//
    1515
     
    7676#include "Validate/Autogen.hpp"             // for autogenerateRoutines
    7777#include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
     78#include "Validate/ForallPointerDecay.hpp"  // for decayForallPointers
    7879#include "Validate/CompoundLiteral.hpp"     // for handleCompoundLiterals
    7980#include "Validate/InitializerLength.hpp"   // for setLengthFromInitializer
     
    331332
    332333                if( useNewAST ) {
    333                         PASS( "Apply Concurrent Keywords", Concurrency::applyKeywords( translationUnit ) );
    334                         PASS( "Forall Pointer Decay", SymTab::decayForallPointers( translationUnit ) );
    335334                        CodeTools::fillLocations( translationUnit );
    336335
     
    342341
    343342                        forceFillCodeLocations( transUnit );
     343
     344                        PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) );
     345
     346                        // Must be after implement concurrent keywords; because uniqueIds
     347                        //   must be set on declaration before resolution.
     348                        // Must happen before autogen routines are added.
     349                        PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) );
    344350
    345351                        // Must happen before autogen routines are added.
     
    487493                        PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );
    488494                }
    489 
    490                
    491495
    492496                PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) );
Note: See TracChangeset for help on using the changeset viewer.