Changeset 24d6572 for src


Ignore:
Timestamp:
Jun 12, 2023, 2:45:32 PM (2 years ago)
Author:
Fangren Yu <f37yu@…>
Branches:
ast-experimental, master
Children:
62d62db
Parents:
34b4268 (diff), 251ce80 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into ast-experimental

Location:
src
Files:
24 added
3 deleted
135 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Attribute.hpp

    r34b4268 r24d6572  
    2727class Expr;
    2828
     29/// An entry in an attribute list: `__attribute__(( ... ))`
    2930class Attribute final : public Node {
    3031public:
  • src/AST/Convert.cpp

    r34b4268 r24d6572  
    559559                auto stmt = new SuspendStmt();
    560560                stmt->then   = get<CompoundStmt>().accept1( node->then   );
    561                 switch(node->type) {
     561                switch (node->kind) {
    562562                        case ast::SuspendStmt::None     : stmt->type = SuspendStmt::None     ; break;
    563563                        case ast::SuspendStmt::Coroutine: stmt->type = SuspendStmt::Coroutine; break;
     
    565565                }
    566566                return stmtPostamble( stmt, node );
     567        }
     568
     569    const ast::WhenClause * visit( const ast::WhenClause * node ) override final {
     570                // There is no old-AST WhenClause, so this should never be called.
     571                assert( !node );
     572                return nullptr;
    567573        }
    568574
     
    573579                for ( auto clause : node->clauses ) {
    574580                        stmt->clauses.push_back({{
    575                                         get<Expression>().accept1( clause->target_func ),
     581                                        get<Expression>().accept1( clause->target ),
    576582                                        get<Expression>().acceptL( clause->target_args ),
    577583                                },
    578584                                get<Statement>().accept1( clause->stmt ),
    579                                 get<Expression>().accept1( clause->cond ),
     585                                get<Expression>().accept1( clause->when_cond ),
    580586                        });
    581587                }
     
    594600        const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
    595601                // There is no old-AST WaitForClause, so this should never be called.
     602                assert( !node );
     603                return nullptr;
     604        }
     605
     606    const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final {
     607        // There is no old-AST WaitUntilStmt, so this should never be called.
    596608                assert( !node );
    597609                return nullptr;
     
    16831695                        GET_ACCEPT_V(attributes, Attribute),
    16841696                        { old->get_funcSpec().val },
    1685                         old->type->isVarArgs
     1697                        (old->type->isVarArgs) ? ast::VariableArgs : ast::FixedArgs
    16861698                };
    16871699
     
    19892001                        GET_ACCEPT_1(else_, Stmt),
    19902002                        GET_ACCEPT_V(initialization, Stmt),
    1991                         old->isDoWhile,
     2003                        (old->isDoWhile) ? ast::DoWhile : ast::While,
    19922004                        GET_LABELS_V(old->labels)
    19932005                );
     
    21312143        virtual void visit( const SuspendStmt * old ) override final {
    21322144                if ( inCache( old ) ) return;
    2133                 ast::SuspendStmt::Type type;
     2145                ast::SuspendStmt::Kind type;
    21342146                switch (old->type) {
    21352147                        case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break;
     
    21582170                        auto clause = new ast::WaitForClause( old->location );
    21592171
    2160                         clause->target_func = GET_ACCEPT_1(clauses[i].target.function, Expr);
     2172                        clause->target = GET_ACCEPT_1(clauses[i].target.function, Expr);
    21612173                        clause->target_args = GET_ACCEPT_V(clauses[i].target.arguments, Expr);
    21622174                        clause->stmt = GET_ACCEPT_1(clauses[i].statement, Stmt);
    2163                         clause->cond = GET_ACCEPT_1(clauses[i].condition, Expr);
     2175                        clause->when_cond = GET_ACCEPT_1(clauses[i].condition, Expr);
    21642176
    21652177                        stmt->clauses.push_back( clause );
  • src/AST/Create.cpp

    r34b4268 r24d6572  
    2020#include "AST/Decl.hpp"
    2121#include "AST/Type.hpp"
     22#include "Common/Iterate.hpp"
    2223
    2324namespace ast {
  • src/AST/Decl.cpp

    r34b4268 r24d6572  
    2020#include <unordered_map>
    2121
    22 #include "Common/utility.h"
     22#include "Common/Eval.h"       // for eval
    2323
    2424#include "Fwd.hpp"             // for UniqueId
     
    5757        std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    5858        CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
    59         std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
     59        std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs )
    6060: DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ),
    6161        type_params(std::move(forall)), assertions(),
    6262        params(std::move(params)), returns(std::move(returns)), stmts( stmts ) {
    63         FunctionType * ftype = new FunctionType(static_cast<ArgumentFlag>(isVarArgs));
     63        FunctionType * ftype = new FunctionType( isVarArgs );
    6464        for (auto & param : this->params) {
    6565                ftype->params.emplace_back(param->get_type());
     
    8181        std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    8282        CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
    83         std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
     83        std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs )
    8484: DeclWithType( location, name, storage, linkage, std::move(attrs), fs ),
    8585                type_params( std::move( forall) ), assertions( std::move( assertions ) ),
    8686                params( std::move(params) ), returns( std::move(returns) ),
    8787                type( nullptr ), stmts( stmts ) {
    88         FunctionType * type = new FunctionType( (isVarArgs) ? VariableArgs : FixedArgs );
     88        FunctionType * type = new FunctionType( isVarArgs );
    8989        for ( auto & param : this->params ) {
    9090                type->params.emplace_back( param->get_type() );
  • src/AST/Decl.hpp

    r34b4268 r24d6572  
    1010// Created On       : Thu May 9 10:00:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Nov 24  9:44:00 2022
    13 // Update Count     : 34
     12// Last Modified On : Wed Apr  5 10:42:00 2023
     13// Update Count     : 35
    1414//
    1515
     
    122122};
    123123
     124/// Function variable arguments flag
     125enum ArgumentFlag { FixedArgs, VariableArgs };
     126
    124127/// Object declaration `int foo()`
    125128class FunctionDecl : public DeclWithType {
     
    144147                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    145148                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
    146                 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
     149                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs );
    147150
    148151        FunctionDecl( const CodeLocation & location, const std::string & name,
     
    150153                std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
    151154                CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
    152                 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
     155                std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs );
    153156
    154157        const Type * get_type() const override;
     
    313316public:
    314317        bool isTyped; // isTyped indicated if the enum has a declaration like:
    315         // enum (type_optional) Name {...} 
     318        // enum (type_optional) Name {...}
    316319        ptr<Type> base; // if isTyped == true && base.get() == nullptr, it is a "void" type enum
    317320        enum class EnumHiding { Visible, Hide } hide;
     
    371374};
    372375
     376/// Assembly declaration: `asm ... ( "..." : ... )`
    373377class AsmDecl : public Decl {
    374378public:
  • src/AST/Expr.cpp

    r34b4268 r24d6572  
    3030#include "Common/SemanticError.h"
    3131#include "GenPoly/Lvalue.h"        // for referencesPermissable
    32 #include "ResolvExpr/typeops.h"    // for extractResultType
     32#include "ResolvExpr/Unify.h"      // for extractResultType
    3333#include "Tuples/Tuples.h"         // for makeTupleType
    3434
  • src/AST/Expr.hpp

    r34b4268 r24d6572  
    256256};
    257257
     258/// A name qualified by a namespace or type.
    258259class QualifiedNameExpr final : public Expr {
    259260public:
     
    261262        std::string name;
    262263
    263         QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 
     264        QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n )
    264265        : Expr( loc ), type_decl( d ), name( n ) {}
    265266
     
    631632};
    632633
     634/// A name that refers to a generic dimension parameter.
    633635class DimensionExpr final : public Expr {
    634636public:
     
    920922};
    921923
    922 
    923924}
    924925
  • src/AST/Fwd.hpp

    r34b4268 r24d6572  
    1515
    1616#pragma once
     17
     18template<typename> struct bitfield;
    1719
    1820#include "AST/Node.hpp"
     
    5658class FinallyClause;
    5759class SuspendStmt;
     60class WhenClause;
    5861class WaitForStmt;
    5962class WaitForClause;
     63class WaitUntilStmt;
    6064class WithStmt;
    6165class DeclStmt;
     
    147151class TranslationGlobal;
    148152
     153// For the following types, only use the using type.
     154namespace CV {
     155        struct qualifier_flags;
     156        using Qualifiers = bitfield<qualifier_flags>;
    149157}
     158namespace Function {
     159        struct spec_flags;
     160        using Specs = bitfield<spec_flags>;
     161}
     162namespace Storage {
     163        struct class_flags;
     164        using Classes = bitfield<class_flags>;
     165}
     166namespace Linkage {
     167        struct spec_flags;
     168        using Spec = bitfield<spec_flags>;
     169}
     170
     171}
  • src/AST/Init.hpp

    r34b4268 r24d6572  
    117117        ptr<Init> init;
    118118
    119         ConstructorInit( 
     119        ConstructorInit(
    120120                const CodeLocation & loc, const Stmt * ctor, const Stmt * dtor, const Init * init )
    121121        : Init( loc, MaybeConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {}
  • src/AST/Inspect.cpp

    r34b4268 r24d6572  
    1010// Created On       : Fri Jun 24 13:16:31 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Oct  3 11:04:00 2022
    13 // Update Count     : 3
     12// Last Modified On : Fri Apr 14 15:09:00 2023
     13// Update Count     : 4
    1414//
    1515
     
    168168}
    169169
     170bool isUnnamedBitfield( const ast::ObjectDecl * obj ) {
     171        return obj && obj->name.empty() && obj->bitfieldWidth;
     172}
     173
    170174} // namespace ast
  • src/AST/Inspect.hpp

    r34b4268 r24d6572  
    1010// Created On       : Fri Jun 24 13:16:31 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Sep 22 13:44:00 2022
    13 // Update Count     : 2
     12// Last Modified On : Fri Apr 14 15:09:00 2023
     13// Update Count     : 3
    1414//
    1515
     
    3838const ApplicationExpr * isIntrinsicCallExpr( const Expr * expr );
    3939
     40/// Returns true if obj's name is the empty string and it has a bitfield width.
     41bool isUnnamedBitfield( const ObjectDecl * obj );
     42
    4043}
  • src/AST/Node.cpp

    r34b4268 r24d6572  
    174174template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::weak >;
    175175template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::strong >;
     176template class ast::ptr_base< ast::WhenClause, ast::Node::ref_type::weak >;
     177template class ast::ptr_base< ast::WhenClause, ast::Node::ref_type::strong >;
    176178template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::weak >;
    177179template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::strong >;
    178180template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::weak >;
    179181template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::strong >;
     182template class ast::ptr_base< ast::WaitUntilStmt, ast::Node::ref_type::weak >;
     183template class ast::ptr_base< ast::WaitUntilStmt, ast::Node::ref_type::strong >;
    180184template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::weak >;
    181185template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::strong >;
  • src/AST/Node.hpp

    r34b4268 r24d6572  
    1919#include <cstddef>     // for nullptr_t
    2020#include <iosfwd>
    21 #include <type_traits> // for remove_reference
    2221
    2322#include "Common/ErrorObjects.h"  // for SemanticErrorException
     
    3635        Node(const Node&) : strong_count(0), weak_count(0) {}
    3736        Node(Node&&) : strong_count(0), weak_count(0) {}
    38         Node& operator= (const Node&) = delete;
    39         Node& operator= (Node&&) = delete;
     37        Node& operator=(const Node&) = delete;
     38        Node& operator=(Node&&) = delete;
    4039        virtual ~Node() {}
    4140
  • src/AST/ParseNode.hpp

    r34b4268 r24d6572  
    4040        template<typename node_t>
    4141        friend node_t * mutate(const node_t * node);
     42        template<typename node_t>
     43        friend node_t * shallowCopy(const node_t * node);
    4244};
    4345
  • src/AST/Pass.hpp

    r34b4268 r24d6572  
    6666//
    6767// Other Special Members:
     68// | beginScope            - A method with no parameters or return value, called each time the
     69//                           visitor enters a block.
     70// | endScope              - A method with no parameters or return value, called each time the
     71//                           visitor leaves a block.
    6872// | result                - Either a method that takes no parameters or a field. If a method (or
    6973//                           callable field) get_result calls it, otherwise the value is returned.
     
    8286        {
    8387                // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor
    84                 type * const * visitor = __pass::visitor(core, 0);
    85                 if(visitor) {
     88                type * const * visitor = __pass::visitor( core, 0 );
     89                if ( visitor ) {
    8690                        *const_cast<type **>( visitor ) = this;
    8791                }
     
    9498
    9599        /// If the core defines a result, call it if possible, otherwise return it.
    96         inline auto get_result() -> decltype( __pass::get_result( core, '0' ) ) {
    97                 return __pass::get_result( core, '0' );
     100        inline auto get_result() -> decltype( __pass::result::get( core, '0' ) ) {
     101                return __pass::result::get( core, '0' );
    98102        }
    99103
     
    158162        const ast::FinallyClause *    visit( const ast::FinallyClause        * ) override final;
    159163        const ast::Stmt *             visit( const ast::SuspendStmt          * ) override final;
     164    const ast::WhenClause *       visit( const ast::WhenClause           * ) override final;
    160165        const ast::Stmt *             visit( const ast::WaitForStmt          * ) override final;
    161166        const ast::WaitForClause *    visit( const ast::WaitForClause        * ) override final;
     167    const ast::Stmt *             visit( const ast::WaitUntilStmt        * ) override final;
    162168        const ast::Decl *             visit( const ast::WithStmt             * ) override final;
    163169        const ast::NullStmt *         visit( const ast::NullStmt             * ) override final;
  • src/AST/Pass.impl.hpp

    r34b4268 r24d6572  
    2020#include <unordered_map>
    2121
     22#include "AST/Copy.hpp"
    2223#include "AST/TranslationUnit.hpp"
    2324#include "AST/TypeSubstitution.hpp"
     
    4546
    4647#ifdef PEDANTIC_PASS_ASSERT
    47 #define __pedantic_pass_assert(...) assert (__VA_ARGS__)
     48#define __pedantic_pass_assert(...) assert(__VA_ARGS__)
    4849#define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
    4950#else
     
    124125                        return !new_val.empty();
    125126                }
    126         }
    127 
    128         template< typename node_t >
    129         template< typename object_t, typename super_t, typename field_t >
    130         void __pass::result1< node_t >::apply( object_t * object, field_t super_t::* field ) {
    131                 object->*field = value;
    132127        }
    133128
     
    233228
    234229                return {true, compound};
    235         }
    236 
    237         template< template <class...> class container_t >
    238         template< typename object_t, typename super_t, typename field_t >
    239         void __pass::resultNstmt<container_t>::apply(object_t * object, field_t super_t::* field) {
    240                 auto & container = object->*field;
    241                 __pedantic_pass_assert( container.size() <= values.size() );
    242 
    243                 auto cit = enumerate(container).begin();
    244 
    245                 container_t<ptr<Stmt>> nvals;
    246                 for (delta & d : values) {
    247                         if ( d.is_old ) {
    248                                 __pedantic_pass_assert( cit.idx <= d.old_idx );
    249                                 std::advance( cit, d.old_idx - cit.idx );
    250                                 nvals.push_back( std::move( (*cit).val) );
    251                         } else {
    252                                 nvals.push_back( std::move(d.new_val) );
    253                         }
    254                 }
    255 
    256                 container = std::move(nvals);
    257         }
    258 
    259         template< template <class...> class container_t >
    260         template< template <class...> class incontainer_t >
    261         void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Stmt>> * stmts ) {
    262                 if (!stmts || stmts->empty()) return;
    263 
    264                 std::transform(stmts->begin(), stmts->end(), std::back_inserter( values ),
    265                         [](ast::ptr<ast::Stmt>& stmt) -> delta {
    266                                 return delta( stmt.release(), -1, false );
    267                         });
    268                 stmts->clear();
    269                 differs = true;
    270         }
    271 
    272         template< template<class...> class container_t >
    273         template< template<class...> class incontainer_t >
    274         void __pass::resultNstmt< container_t >::take_all( incontainer_t<ptr<Decl>> * decls ) {
    275                 if (!decls || decls->empty()) return;
    276 
    277                 std::transform(decls->begin(), decls->end(), std::back_inserter( values ),
    278                         [](ast::ptr<ast::Decl>& decl) -> delta {
    279                                 auto loc = decl->location;
    280                                 auto stmt = new DeclStmt( loc, decl.release() );
    281                                 return delta( stmt, -1, false );
    282                         });
    283                 decls->clear();
    284                 differs = true;
    285230        }
    286231
     
    352297
    353298                return new_kids;
    354         }
    355 
    356         template< template <class...> class container_t, typename node_t >
    357         template< typename object_t, typename super_t, typename field_t >
    358         void __pass::resultN<container_t, node_t>::apply(object_t * object, field_t super_t::* field) {
    359                 auto & container = object->*field;
    360                 __pedantic_pass_assert( container.size() == values.size() );
    361 
    362                 for(size_t i = 0; i < container.size(); i++) {
    363                         // Take all the elements that are different in 'values'
    364                         // and swap them into 'container'
    365                         if( values[i] != nullptr ) swap(container[i], values[i]);
    366                 }
    367 
    368                 // Now the original containers should still have the unchanged values
    369                 // but also contain the new values
    370299        }
    371300
     
    836765                        if ( enterScope ) {
    837766                                __pass::symtab::enter(core, 0);
    838                                 __pass::scope::enter(core, 0);
    839767                        }
    840768                }, [this, leaveScope = !this->atFunctionTop]() {
    841769                        if ( leaveScope ) {
    842770                                __pass::symtab::leave(core, 0);
    843                                 __pass::scope::leave(core, 0);
    844771                        }
    845772                });
     
    1067994
    1068995//--------------------------------------------------------------------------
     996// WhenClause
     997template< typename core_t >
     998const ast::WhenClause * ast::Pass< core_t >::visit( const ast::WhenClause * node ) {
     999        VISIT_START( node );
     1000
     1001        if ( __visit_children() ) {
     1002                maybe_accept( node, &WhenClause::target );
     1003                maybe_accept( node, &WhenClause::stmt );
     1004                maybe_accept( node, &WhenClause::when_cond );
     1005        }
     1006
     1007        VISIT_END( WhenClause, node );
     1008}
     1009
     1010//--------------------------------------------------------------------------
    10691011// WaitForStmt
    10701012template< typename core_t >
     
    10911033
    10921034        if ( __visit_children() ) {
    1093                 maybe_accept( node, &WaitForClause::target_func );
     1035                maybe_accept( node, &WaitForClause::target );
    10941036                maybe_accept( node, &WaitForClause::target_args );
    10951037                maybe_accept( node, &WaitForClause::stmt );
    1096                 maybe_accept( node, &WaitForClause::cond );
     1038                maybe_accept( node, &WaitForClause::when_cond );
    10971039        }
    10981040
    10991041        VISIT_END( WaitForClause, node );
     1042}
     1043
     1044//--------------------------------------------------------------------------
     1045// WaitUntilStmt
     1046template< typename core_t >
     1047const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitUntilStmt * node ) {
     1048        VISIT_START( node );
     1049
     1050        if ( __visit_children() ) {
     1051                maybe_accept( node, &WaitUntilStmt::clauses );
     1052                maybe_accept( node, &WaitUntilStmt::timeout_time );
     1053                maybe_accept( node, &WaitUntilStmt::timeout_stmt );
     1054                maybe_accept( node, &WaitUntilStmt::timeout_cond );
     1055                maybe_accept( node, &WaitUntilStmt::else_stmt );
     1056                maybe_accept( node, &WaitUntilStmt::else_cond );
     1057        }
     1058
     1059        VISIT_END( Stmt, node );
    11001060}
    11011061
     
    20432003        if ( __visit_children() ) {
    20442004                maybe_accept( node, &TupleType::types );
    2045                 maybe_accept( node, &TupleType::members );
    20462005        }
    20472006
     
    22052164}
    22062165
     2166#undef __pedantic_pass_assertf
     2167#undef __pedantic_pass_assert
    22072168#undef VISIT_START
    22082169#undef VISIT_END
  • src/AST/Pass.proto.hpp

    r34b4268 r24d6572  
    1717// IWYU pragma: private, include "Pass.hpp"
    1818
     19#include "Common/Iterate.hpp"
    1920#include "Common/Stats/Heap.h"
    20 
    2121namespace ast {
    22 template<typename core_t>
    23 class Pass;
    24 
    25 class TranslationUnit;
    26 
    27 struct PureVisitor;
    28 
    29 template<typename node_t>
    30 node_t * deepCopy( const node_t * localRoot );
    31 
    32 namespace __pass {
    33         typedef std::function<void( void * )> cleanup_func_t;
    34         typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t;
    35 
    36 
    37         // boolean reference that may be null
    38         // either refers to a boolean value or is null and returns true
    39         class bool_ref {
    40         public:
    41                 bool_ref() = default;
    42                 ~bool_ref() = default;
    43 
    44                 operator bool() { return m_ref ? *m_ref : true; }
    45                 bool operator=( bool val ) { assert(m_ref); return *m_ref = val; }
    46 
    47         private:
    48 
    49                 friend class visit_children_guard;
    50 
    51                 bool * set( bool * val ) {
    52                         bool * prev = m_ref;
    53                         m_ref = val;
    54                         return prev;
    55                 }
    56 
    57                 bool * m_ref = nullptr;
     22        template<typename core_t> class Pass;
     23        class TranslationUnit;
     24        struct PureVisitor;
     25        template<typename node_t> node_t * deepCopy( const node_t * );
     26}
     27
     28#ifdef PEDANTIC_PASS_ASSERT
     29#define __pedantic_pass_assert(...) assert(__VA_ARGS__)
     30#define __pedantic_pass_assertf(...) assertf(__VA_ARGS__)
     31#else
     32#define __pedantic_pass_assert(...)
     33#define __pedantic_pass_assertf(...)
     34#endif
     35
     36namespace ast::__pass {
     37
     38typedef std::function<void( void * )> cleanup_func_t;
     39typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t;
     40
     41// boolean reference that may be null
     42// either refers to a boolean value or is null and returns true
     43class bool_ref {
     44public:
     45        bool_ref() = default;
     46        ~bool_ref() = default;
     47
     48        operator bool() { return m_ref ? *m_ref : true; }
     49        bool operator=( bool val ) { assert(m_ref); return *m_ref = val; }
     50
     51private:
     52
     53        friend class visit_children_guard;
     54
     55        bool * set( bool * val ) {
     56                bool * prev = m_ref;
     57                m_ref = val;
     58                return prev;
     59        }
     60
     61        bool * m_ref = nullptr;
     62};
     63
     64// Implementation of the guard value
     65// Created inside the visit scope
     66class guard_value {
     67public:
     68        /// Push onto the cleanup
     69        guard_value( at_cleanup_t * at_cleanup ) {
     70                if( at_cleanup ) {
     71                        *at_cleanup = [this]( cleanup_func_t && func, void* val ) {
     72                                push( std::move( func ), val );
     73                        };
     74                }
     75        }
     76
     77        ~guard_value() {
     78                while( !cleanups.empty() ) {
     79                        auto& cleanup = cleanups.top();
     80                        cleanup.func( cleanup.val );
     81                        cleanups.pop();
     82                }
     83        }
     84
     85        void push( cleanup_func_t && func, void* val ) {
     86                cleanups.emplace( std::move(func), val );
     87        }
     88
     89private:
     90        struct cleanup_t {
     91                cleanup_func_t func;
     92                void * val;
     93
     94                cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {}
    5895        };
    5996
    60         // Implementation of the guard value
    61         // Created inside the visit scope
    62         class guard_value {
    63         public:
    64                 /// Push onto the cleanup
    65                 guard_value( at_cleanup_t * at_cleanup ) {
    66                         if( at_cleanup ) {
    67                                 *at_cleanup = [this]( cleanup_func_t && func, void* val ) {
    68                                         push( std::move( func ), val );
    69                                 };
     97        std::stack< cleanup_t, std::vector<cleanup_t> > cleanups;
     98};
     99
     100// Guard structure implementation for whether or not children should be visited
     101class visit_children_guard {
     102public:
     103
     104        visit_children_guard( bool_ref * ref )
     105                : m_val ( true )
     106                , m_prev( ref ? ref->set( &m_val ) : nullptr )
     107                , m_ref ( ref )
     108        {}
     109
     110        ~visit_children_guard() {
     111                if( m_ref ) {
     112                        m_ref->set( m_prev );
     113                }
     114        }
     115
     116        operator bool() { return m_val; }
     117
     118private:
     119        bool       m_val;
     120        bool     * m_prev;
     121        bool_ref * m_ref;
     122};
     123
     124/// "Short hand" to check if this is a valid previsit function
     125/// Mostly used to make the static_assert look (and print) prettier
     126template<typename core_t, typename node_t>
     127struct is_valid_previsit {
     128        using ret_t = decltype( std::declval<core_t*>()->previsit( std::declval<const node_t *>() ) );
     129
     130        static constexpr bool value = std::is_void< ret_t >::value ||
     131                std::is_base_of<const node_t, typename std::remove_pointer<ret_t>::type >::value;
     132};
     133
     134/// The result is a single node.
     135template< typename node_t >
     136struct result1 {
     137        bool differs = false;
     138        const node_t * value = nullptr;
     139
     140        template< typename object_t, typename super_t, typename field_t >
     141        void apply( object_t * object, field_t super_t::* field ) {
     142                object->*field = value;
     143        }
     144};
     145
     146/// The result is a container of statements.
     147template< template<class...> class container_t >
     148struct resultNstmt {
     149        /// The delta/change on a single node.
     150        struct delta {
     151                ptr<Stmt> new_val;
     152                ssize_t old_idx;
     153                bool is_old;
     154
     155                delta(const Stmt * s, ssize_t i, bool old) :
     156                        new_val(s), old_idx(i), is_old(old) {}
     157        };
     158
     159        bool differs = false;
     160        container_t< delta > values;
     161
     162        template< typename object_t, typename super_t, typename field_t >
     163        void apply( object_t * object, field_t super_t::* field ) {
     164                field_t & container = object->*field;
     165                __pedantic_pass_assert( container.size() <= values.size() );
     166
     167                auto cit = enumerate(container).begin();
     168
     169                container_t<ptr<Stmt>> nvals;
     170                for ( delta & d : values ) {
     171                        if ( d.is_old ) {
     172                                __pedantic_pass_assert( cit.idx <= d.old_idx );
     173                                std::advance( cit, d.old_idx - cit.idx );
     174                                nvals.push_back( std::move( (*cit).val ) );
     175                        } else {
     176                                nvals.push_back( std::move( d.new_val ) );
    70177                        }
    71178                }
    72179
    73                 ~guard_value() {
    74                         while( !cleanups.empty() ) {
    75                                 auto& cleanup = cleanups.top();
    76                                 cleanup.func( cleanup.val );
    77                                 cleanups.pop();
    78                         }
    79                 }
    80 
    81                 void push( cleanup_func_t && func, void* val ) {
    82                         cleanups.emplace( std::move(func), val );
    83                 }
    84 
    85         private:
    86                 struct cleanup_t {
    87                         cleanup_func_t func;
    88                         void * val;
    89 
    90                         cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {}
    91                 };
    92 
    93                 std::stack< cleanup_t, std::vector<cleanup_t> > cleanups;
    94         };
    95 
    96         // Guard structure implementation for whether or not children should be visited
    97         class visit_children_guard {
    98         public:
    99 
    100                 visit_children_guard( bool_ref * ref )
    101                         : m_val ( true )
    102                         , m_prev( ref ? ref->set( &m_val ) : nullptr )
    103                         , m_ref ( ref )
    104                 {}
    105 
    106                 ~visit_children_guard() {
    107                         if( m_ref ) {
    108                                 m_ref->set( m_prev );
    109                         }
    110                 }
    111 
    112                 operator bool() { return m_val; }
    113 
    114         private:
    115                 bool       m_val;
    116                 bool     * m_prev;
    117                 bool_ref * m_ref;
    118         };
    119 
    120         /// "Short hand" to check if this is a valid previsit function
    121         /// Mostly used to make the static_assert look (and print) prettier
     180                container = std::move(nvals);
     181        }
     182
     183        template< template<class...> class incontainer_t >
     184        void take_all( incontainer_t<ptr<Stmt>> * stmts ) {
     185                if ( !stmts || stmts->empty() ) return;
     186
     187                std::transform( stmts->begin(), stmts->end(), std::back_inserter( values ),
     188                        [](ast::ptr<ast::Stmt>& stmt) -> delta {
     189                                return delta( stmt.release(), -1, false );
     190                        });
     191                stmts->clear();
     192                differs = true;
     193        }
     194
     195        template< template<class...> class incontainer_t >
     196        void take_all( incontainer_t<ptr<Decl>> * decls ) {
     197                if ( !decls || decls->empty() ) return;
     198
     199                std::transform( decls->begin(), decls->end(), std::back_inserter( values ),
     200                        [](ast::ptr<ast::Decl>& decl) -> delta {
     201                                ast::Decl const * d = decl.release();
     202                                return delta( new DeclStmt( d->location, d ), -1, false );
     203                        });
     204                decls->clear();
     205                differs = true;
     206        }
     207};
     208
     209/// The result is a container of nodes.
     210template< template<class...> class container_t, typename node_t >
     211struct resultN {
     212        bool differs = false;
     213        container_t<ptr<node_t>> values;
     214
     215        template< typename object_t, typename super_t, typename field_t >
     216        void apply( object_t * object, field_t super_t::* field ) {
     217                field_t & container = object->*field;
     218                __pedantic_pass_assert( container.size() == values.size() );
     219
     220                for ( size_t i = 0; i < container.size(); ++i ) {
     221                        // Take all the elements that are different in 'values'
     222                        // and swap them into 'container'
     223                        if ( values[i] != nullptr ) swap(container[i], values[i]);
     224                }
     225                // Now the original containers should still have the unchanged values
     226                // but also contain the new values.
     227        }
     228};
     229
     230/// Used by previsit implementation
     231/// We need to reassign the result to 'node', unless the function
     232/// returns void, then we just leave 'node' unchanged
     233template<bool is_void>
     234struct __assign;
     235
     236template<>
     237struct __assign<true> {
    122238        template<typename core_t, typename node_t>
    123         struct is_valid_previsit {
    124                 using ret_t = decltype( std::declval<core_t*>()->previsit( std::declval<const node_t *>() ) );
    125 
    126                 static constexpr bool value = std::is_void< ret_t >::value ||
    127                         std::is_base_of<const node_t, typename std::remove_pointer<ret_t>::type >::value;
    128         };
    129 
    130         /// The result is a single node.
    131         template< typename node_t >
    132         struct result1 {
    133                 bool differs = false;
    134                 const node_t * value = nullptr;
    135 
    136                 template< typename object_t, typename super_t, typename field_t >
    137                 void apply( object_t *, field_t super_t::* field );
    138         };
    139 
    140         /// The result is a container of statements.
    141         template< template<class...> class container_t >
    142         struct resultNstmt {
    143                 /// The delta/change on a single node.
    144                 struct delta {
    145                         ptr<Stmt> new_val;
    146                         ssize_t old_idx;
    147                         bool is_old;
    148 
    149                         delta(const Stmt * s, ssize_t i, bool old) :
    150                                 new_val(s), old_idx(i), is_old(old) {}
    151                 };
    152 
    153                 bool differs = false;
    154                 container_t< delta > values;
    155 
    156                 template< typename object_t, typename super_t, typename field_t >
    157                 void apply( object_t *, field_t super_t::* field );
    158 
    159                 template< template<class...> class incontainer_t >
    160                 void take_all( incontainer_t<ptr<Stmt>> * stmts );
    161 
    162                 template< template<class...> class incontainer_t >
    163                 void take_all( incontainer_t<ptr<Decl>> * decls );
    164         };
    165 
    166         /// The result is a container of nodes.
    167         template< template<class...> class container_t, typename node_t >
    168         struct resultN {
    169                 bool differs = false;
    170                 container_t<ptr<node_t>> values;
    171 
    172                 template< typename object_t, typename super_t, typename field_t >
    173                 void apply( object_t *, field_t super_t::* field );
    174         };
    175 
    176         /// Used by previsit implementation
    177         /// We need to reassign the result to 'node', unless the function
    178         /// returns void, then we just leave 'node' unchanged
    179         template<bool is_void>
    180         struct __assign;
    181 
    182         template<>
    183         struct __assign<true> {
    184                 template<typename core_t, typename node_t>
    185                 static inline void result( core_t & core, const node_t * & node ) {
    186                         core.previsit( node );
    187                 }
    188         };
    189 
    190         template<>
    191         struct __assign<false> {
    192                 template<typename core_t, typename node_t>
    193                 static inline void result( core_t & core, const node_t * & node ) {
    194                         node = core.previsit( node );
    195                         assertf(node, "Previsit must not return NULL");
    196                 }
    197         };
    198 
    199         /// Used by postvisit implementation
    200         /// We need to return the result unless the function
    201         /// returns void, then we just return the original node
    202         template<bool is_void>
    203         struct __return;
    204 
    205         template<>
    206         struct __return<true> {
    207                 template<typename core_t, typename node_t>
    208                 static inline const node_t * result( core_t & core, const node_t * & node ) {
    209                         core.postvisit( node );
    210                         return node;
    211                 }
    212         };
    213 
    214         template<>
    215         struct __return<false> {
    216                 template<typename core_t, typename node_t>
    217                 static inline auto result( core_t & core, const node_t * & node ) {
    218                         return core.postvisit( node );
    219                 }
    220         };
    221 
    222         //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    223         // Deep magic (a.k.a template meta programming) to make the templated visitor work
    224         // Basically the goal is to make 2 previsit
    225         // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of
    226         //     'pass.previsit( node )' that compiles will be used for that node for that type
    227         //     This requires that this option only compile for passes that actually define an appropriate visit.
    228         //     SFINAE will make sure the compilation errors in this function don't halt the build.
    229         //     See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE
    230         // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing.
    231         //     This is needed only to eliminate the need for passes to specify any kind of handlers.
    232         //     The second implementation only works because it has a lower priority. This is due to the bogus last parameter.
    233         //     The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0
    234         //     the first implementation takes priority in regards to overloading.
    235         //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    236         // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call
     239        static inline void result( core_t & core, const node_t * & node ) {
     240                core.previsit( node );
     241        }
     242};
     243
     244template<>
     245struct __assign<false> {
    237246        template<typename core_t, typename node_t>
    238         static inline auto previsit( core_t & core, const node_t * & node, int ) -> decltype( core.previsit( node ), void() ) {
    239                 static_assert(
    240                         is_valid_previsit<core_t, node_t>::value,
    241                         "Previsit may not change the type of the node. It must return its paremeter or void."
    242                 );
    243 
    244                 __assign<
    245                         std::is_void<
    246                                 decltype( core.previsit( node ) )
    247                         >::value
    248                 >::result( core, node );
    249         }
    250 
     247        static inline void result( core_t & core, const node_t * & node ) {
     248                node = core.previsit( node );
     249                assertf(node, "Previsit must not return NULL");
     250        }
     251};
     252
     253/// Used by postvisit implementation
     254/// We need to return the result unless the function
     255/// returns void, then we just return the original node
     256template<bool is_void>
     257struct __return;
     258
     259template<>
     260struct __return<true> {
    251261        template<typename core_t, typename node_t>
    252         static inline auto previsit( core_t &, const node_t *, long ) {}
    253 
    254         // PostVisit : never mutates the passed pointer but may return a different node
     262        static inline const node_t * result( core_t & core, const node_t * & node ) {
     263                core.postvisit( node );
     264                return node;
     265        }
     266};
     267
     268template<>
     269struct __return<false> {
    255270        template<typename core_t, typename node_t>
    256         static inline auto postvisit( core_t & core, const node_t * node, int ) ->
    257                 decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) )
    258         {
    259                 return __return<
    260                         std::is_void<
    261                                 decltype( core.postvisit( node ) )
    262                         >::value
    263                 >::result( core, node );
    264         }
    265 
    266         template<typename core_t, typename node_t>
    267         static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; }
    268 
    269         //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    270         // Deep magic (a.k.a template meta programming) continued
    271         // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit
    272         // from in order to get extra functionallity for example
    273         // class ErrorChecker : WithShortCircuiting { ... };
    274         // Pass<ErrorChecker> checker;
    275         // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting
    276         // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched
    277         //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    278         // For several accessories, the feature is enabled by detecting that a specific field is present
    279         // Use a macro the encapsulate the logic of detecting a particular field
    280         // The type is not strictly enforced but does match the accessory
    281         #define FIELD_PTR( name, default_type ) \
    282         template< typename core_t > \
    283         static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \
     271        static inline auto result( core_t & core, const node_t * & node ) {
     272                return core.postvisit( node );
     273        }
     274};
     275
     276//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     277// Deep magic (a.k.a template meta programming) to make the templated visitor work
     278// Basically the goal is to make 2 previsit
     279// 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of
     280//     'pass.previsit( node )' that compiles will be used for that node for that type
     281//     This requires that this option only compile for passes that actually define an appropriate visit.
     282//     SFINAE will make sure the compilation errors in this function don't halt the build.
     283//     See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE
     284// 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing.
     285//     This is needed only to eliminate the need for passes to specify any kind of handlers.
     286//     The second implementation only works because it has a lower priority. This is due to the bogus last parameter.
     287//     The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0
     288//     the first implementation takes priority in regards to overloading.
     289//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     290// PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call
     291template<typename core_t, typename node_t>
     292static inline auto previsit( core_t & core, const node_t * & node, int ) -> decltype( core.previsit( node ), void() ) {
     293        static_assert(
     294                is_valid_previsit<core_t, node_t>::value,
     295                "Previsit may not change the type of the node. It must return its paremeter or void."
     296        );
     297
     298        __assign<
     299                std::is_void<
     300                        decltype( core.previsit( node ) )
     301                >::value
     302        >::result( core, node );
     303}
     304
     305template<typename core_t, typename node_t>
     306static inline auto previsit( core_t &, const node_t *, long ) {}
     307
     308// PostVisit : never mutates the passed pointer but may return a different node
     309template<typename core_t, typename node_t>
     310static inline auto postvisit( core_t & core, const node_t * node, int ) ->
     311        decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) )
     312{
     313        return __return<
     314                std::is_void<
     315                        decltype( core.postvisit( node ) )
     316                >::value
     317        >::result( core, node );
     318}
     319
     320template<typename core_t, typename node_t>
     321static inline const node_t * postvisit( core_t &, const node_t * node, long ) { return node; }
     322
     323//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     324// Deep magic (a.k.a template meta programming) continued
     325// To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit
     326// from in order to get extra functionallity for example
     327// class ErrorChecker : WithShortCircuiting { ... };
     328// Pass<ErrorChecker> checker;
     329// this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting
     330// Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched
     331//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     332// For several accessories, the feature is enabled by detecting that a specific field is present
     333// Use a macro the encapsulate the logic of detecting a particular field
     334// The type is not strictly enforced but does match the accessory
     335#define FIELD_PTR( name, default_type ) \
     336template< typename core_t > \
     337static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \
     338\
     339template< typename core_t > \
     340static inline default_type * name( core_t &, long ) { return nullptr; }
     341
     342// List of fields and their expected types
     343FIELD_PTR( typeSubs, const ast::TypeSubstitution * )
     344FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > )
     345FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > )
     346FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > )
     347FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > )
     348FIELD_PTR( visit_children, __pass::bool_ref )
     349FIELD_PTR( at_cleanup, __pass::at_cleanup_t )
     350FIELD_PTR( visitor, ast::Pass<core_t> * const )
     351
     352// Remove the macro to make sure we don't clash
     353#undef FIELD_PTR
     354
     355template< typename core_t >
     356static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
     357        // Stats::Heap::stacktrace_push(core_t::traceId);
     358}
     359
     360template< typename core_t >
     361static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
     362        // Stats::Heap::stacktrace_pop();
     363}
     364
     365template< typename core_t >
     366static void beginTrace(core_t &, long) {}
     367
     368template< typename core_t >
     369static void endTrace(core_t &, long) {}
     370
     371// Allows visitor to handle an error on top-level declarations, and possibly suppress the error.
     372// If on_error() returns false, the error will be ignored. By default, it returns true.
     373
     374template< typename core_t >
     375static bool on_error (core_t &, ptr<Decl> &, long) { return true; }
     376
     377template< typename core_t >
     378static auto on_error (core_t & core, ptr<Decl> & decl, int) -> decltype(core.on_error(decl)) {
     379        return core.on_error(decl);
     380}
     381
     382template< typename core_t, typename node_t >
     383static auto make_location_guard( core_t & core, node_t * node, int )
     384                -> decltype( node->location, ValueGuardPtr<const CodeLocation *>( &core.location ) ) {
     385        ValueGuardPtr<const CodeLocation *> guard( &core.location );
     386        core.location = &node->location;
     387        return guard;
     388}
     389
     390template< typename core_t, typename node_t >
     391static auto make_location_guard( core_t &, node_t *, long ) -> int {
     392        return 0;
     393}
     394
     395// Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement.
     396// All passes which have such functions are assumed desire this behaviour
     397// detect it using the same strategy
     398namespace scope {
     399        template<typename core_t>
     400        static inline auto enter( core_t & core, int ) -> decltype( core.beginScope(), void() ) {
     401                core.beginScope();
     402        }
     403
     404        template<typename core_t>
     405        static inline void enter( core_t &, long ) {}
     406
     407        template<typename core_t>
     408        static inline auto leave( core_t & core, int ) -> decltype( core.endScope(), void() ) {
     409                core.endScope();
     410        }
     411
     412        template<typename core_t>
     413        static inline void leave( core_t &, long ) {}
     414} // namespace scope
     415
     416// Certain passes desire an up to date symbol table automatically
     417// detect the presence of a member name `symtab` and call all the members appropriately
     418namespace symtab {
     419        // Some simple scoping rules
     420        template<typename core_t>
     421        static inline auto enter( core_t & core, int ) -> decltype( core.symtab, void() ) {
     422                core.symtab.enterScope();
     423        }
     424
     425        template<typename core_t>
     426        static inline auto enter( core_t &, long ) {}
     427
     428        template<typename core_t>
     429        static inline auto leave( core_t & core, int ) -> decltype( core.symtab, void() ) {
     430                core.symtab.leaveScope();
     431        }
     432
     433        template<typename core_t>
     434        static inline auto leave( core_t &, long ) {}
     435
     436        // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments
     437        // Create macro to condense these common patterns
     438        #define SYMTAB_FUNC1( func, type ) \
     439        template<typename core_t> \
     440        static inline auto func( core_t & core, int, type arg ) -> decltype( core.symtab.func( arg ), void() ) {\
     441                core.symtab.func( arg ); \
     442        } \
    284443        \
    285         template< typename core_t > \
    286         static inline default_type * name( core_t &, long ) { return nullptr; }
    287 
    288         // List of fields and their expected types
    289         FIELD_PTR( typeSubs, const ast::TypeSubstitution * )
    290         FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > )
    291         FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > )
    292         FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > )
    293         FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > )
    294         FIELD_PTR( visit_children, __pass::bool_ref )
    295         FIELD_PTR( at_cleanup, __pass::at_cleanup_t )
    296         FIELD_PTR( visitor, ast::Pass<core_t> * const )
    297 
    298         // Remove the macro to make sure we don't clash
    299         #undef FIELD_PTR
    300 
    301         template< typename core_t >
    302         static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
    303                 // Stats::Heap::stacktrace_push(core_t::traceId);
    304         }
    305 
    306         template< typename core_t >
    307         static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) {
    308                 // Stats::Heap::stacktrace_pop();
    309         }
    310 
    311         template< typename core_t >
    312         static void beginTrace(core_t &, long) {}
    313 
    314         template< typename core_t >
    315         static void endTrace(core_t &, long) {}
    316 
    317         // Allows visitor to handle an error on top-level declarations, and possibly suppress the error.
    318         // If onError() returns false, the error will be ignored. By default, it returns true.
    319 
    320         template< typename core_t >
    321         static bool on_error (core_t &, ptr<Decl> &, long) { return true; }
    322 
    323         template< typename core_t >
    324         static auto on_error (core_t & core, ptr<Decl> & decl, int) -> decltype(core.on_error(decl)) {
    325                 return core.on_error(decl);
    326         }
    327 
    328         template< typename core_t, typename node_t >
    329         static auto make_location_guard( core_t & core, node_t * node, int )
    330                         -> decltype( node->location, ValueGuardPtr<const CodeLocation *>( &core.location ) ) {
    331                 ValueGuardPtr<const CodeLocation *> guard( &core.location );
    332                 core.location = &node->location;
    333                 return guard;
    334         }
    335 
    336         template< typename core_t, typename node_t >
    337         static auto make_location_guard( core_t &, node_t *, long ) -> int {
    338                 return 0;
    339         }
    340 
    341         // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement.
    342         // All passes which have such functions are assumed desire this behaviour
    343         // detect it using the same strategy
    344         namespace scope {
    345                 template<typename core_t>
    346                 static inline auto enter( core_t & core, int ) -> decltype( core.beginScope(), void() ) {
    347                         core.beginScope();
    348                 }
    349 
    350                 template<typename core_t>
    351                 static inline void enter( core_t &, long ) {}
    352 
    353                 template<typename core_t>
    354                 static inline auto leave( core_t & core, int ) -> decltype( core.endScope(), void() ) {
    355                         core.endScope();
    356                 }
    357 
    358                 template<typename core_t>
    359                 static inline void leave( core_t &, long ) {}
    360         } // namespace scope
    361 
    362         // Certain passes desire an up to date symbol table automatically
    363         // detect the presence of a member name `symtab` and call all the members appropriately
    364         namespace symtab {
    365                 // Some simple scoping rules
    366                 template<typename core_t>
    367                 static inline auto enter( core_t & core, int ) -> decltype( core.symtab, void() ) {
    368                         core.symtab.enterScope();
    369                 }
    370 
    371                 template<typename core_t>
    372                 static inline auto enter( core_t &, long ) {}
    373 
    374                 template<typename core_t>
    375                 static inline auto leave( core_t & core, int ) -> decltype( core.symtab, void() ) {
    376                         core.symtab.leaveScope();
    377                 }
    378 
    379                 template<typename core_t>
    380                 static inline auto leave( core_t &, long ) {}
    381 
    382                 // The symbol table has 2 kind of functions mostly, 1 argument and 2 arguments
    383                 // Create macro to condense these common patterns
    384                 #define SYMTAB_FUNC1( func, type ) \
    385                 template<typename core_t> \
    386                 static inline auto func( core_t & core, int, type arg ) -> decltype( core.symtab.func( arg ), void() ) {\
    387                         core.symtab.func( arg ); \
    388                 } \
    389                 \
    390                 template<typename core_t> \
    391                 static inline void func( core_t &, long, type ) {}
    392 
    393                 #define SYMTAB_FUNC2( func, type1, type2 ) \
    394                 template<typename core_t> \
    395                 static inline auto func( core_t & core, int, type1 arg1, type2 arg2 ) -> decltype( core.symtab.func( arg1, arg2 ), void () ) {\
    396                         core.symtab.func( arg1, arg2 ); \
    397                 } \
    398                         \
    399                 template<typename core_t> \
    400                 static inline void func( core_t &, long, type1, type2 ) {}
    401 
    402                 SYMTAB_FUNC1( addId     , const DeclWithType *  );
    403                 SYMTAB_FUNC1( addType   , const NamedTypeDecl * );
    404                 SYMTAB_FUNC1( addStruct , const StructDecl *    );
    405                 SYMTAB_FUNC1( addEnum   , const EnumDecl *      );
    406                 SYMTAB_FUNC1( addUnion  , const UnionDecl *     );
    407                 SYMTAB_FUNC1( addTrait  , const TraitDecl *     );
    408                 SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Decl * );
    409 
    410                 // A few extra functions have more complicated behaviour, they are hand written
    411                 template<typename core_t>
    412                 static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) {
    413                         ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
    414                         for ( const auto & param : decl->params ) {
    415                                 fwd->params.push_back( deepCopy( param.get() ) );
    416                         }
    417                         core.symtab.addStruct( fwd );
    418                 }
    419 
    420                 template<typename core_t>
    421                 static inline void addStructFwd( core_t &, long, const ast::StructDecl * ) {}
    422 
    423                 template<typename core_t>
    424                 static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) {
    425                         ast::UnionDecl * fwd = new ast::UnionDecl( decl->location, decl->name );
    426                         for ( const auto & param : decl->params ) {
    427                                 fwd->params.push_back( deepCopy( param.get() ) );
    428                         }
    429                         core.symtab.addUnion( fwd );
    430                 }
    431 
    432                 template<typename core_t>
    433                 static inline void addUnionFwd( core_t &, long, const ast::UnionDecl * ) {}
    434 
    435                 template<typename core_t>
    436                 static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) {
    437                         if ( ! core.symtab.lookupStruct( str ) ) {
    438                                 core.symtab.addStruct( str );
    439                         }
    440                 }
    441 
    442                 template<typename core_t>
    443                 static inline void addStruct( core_t &, long, const std::string & ) {}
    444 
    445                 template<typename core_t>
    446                 static inline auto addUnion( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addUnion( str ), void() ) {
    447                         if ( ! core.symtab.lookupUnion( str ) ) {
    448                                 core.symtab.addUnion( str );
    449                         }
    450                 }
    451 
    452                 template<typename core_t>
    453                 static inline void addUnion( core_t &, long, const std::string & ) {}
    454 
    455                 #undef SYMTAB_FUNC1
    456                 #undef SYMTAB_FUNC2
    457         } // namespace symtab
    458 
    459         // Some passes need to mutate TypeDecl and properly update their pointing TypeInstType.
    460         // Detect the presence of a member name `subs` and call all members appropriately
    461         namespace forall {
    462                 // Some simple scoping rules
    463                 template<typename core_t>
    464                 static inline auto enter( core_t & core, int, const ast::FunctionType * type )
    465                 -> decltype( core.subs, void() ) {
    466                         if ( ! type->forall.empty() ) core.subs.beginScope();
    467                 }
    468 
    469                 template<typename core_t>
    470                 static inline auto enter( core_t &, long, const ast::FunctionType * ) {}
    471 
    472                 template<typename core_t>
    473                 static inline auto leave( core_t & core, int, const ast::FunctionType * type )
    474                 -> decltype( core.subs, void() ) {
    475                         if ( ! type->forall.empty() ) { core.subs.endScope(); }
    476                 }
    477 
    478                 template<typename core_t>
    479                 static inline auto leave( core_t &, long, const ast::FunctionType * ) {}
    480 
    481                 // Replaces a TypeInstType's base TypeDecl according to the table
    482                 template<typename core_t>
    483                 static inline auto replace( core_t & core, int, const ast::TypeInstType *& inst )
    484                 -> decltype( core.subs, void() ) {
    485                         inst = ast::mutate_field(
    486                                 inst, &ast::TypeInstType::base, core.subs.replace( inst->base ) );
    487                 }
    488 
    489                 template<typename core_t>
    490                 static inline auto replace( core_t &, long, const ast::TypeInstType *& ) {}
    491 
    492         } // namespace forall
    493 
    494         // For passes that need access to the global context. Sreaches `translationUnit`
    495         namespace translation_unit {
    496                 template<typename core_t>
    497                 static inline auto get_cptr( core_t & core, int )
    498                                 -> decltype( &core.translationUnit ) {
    499                         return &core.translationUnit;
    500                 }
    501 
    502                 template<typename core_t>
    503                 static inline const TranslationUnit ** get_cptr( core_t &, long ) {
    504                         return nullptr;
    505                 }
    506         }
    507 
    508         template<typename core_t>
    509         static inline auto get_result( core_t & core, char ) -> decltype( core.result() ) {
     444        template<typename core_t> \
     445        static inline void func( core_t &, long, type ) {}
     446
     447        #define SYMTAB_FUNC2( func, type1, type2 ) \
     448        template<typename core_t> \
     449        static inline auto func( core_t & core, int, type1 arg1, type2 arg2 ) -> decltype( core.symtab.func( arg1, arg2 ), void () ) {\
     450                core.symtab.func( arg1, arg2 ); \
     451        } \
     452        \
     453        template<typename core_t> \
     454        static inline void func( core_t &, long, type1, type2 ) {}
     455
     456        SYMTAB_FUNC1( addId     , const DeclWithType *  );
     457        SYMTAB_FUNC1( addType   , const NamedTypeDecl * );
     458        SYMTAB_FUNC1( addStruct , const StructDecl *    );
     459        SYMTAB_FUNC1( addEnum   , const EnumDecl *      );
     460        SYMTAB_FUNC1( addUnion  , const UnionDecl *     );
     461        SYMTAB_FUNC1( addTrait  , const TraitDecl *     );
     462        SYMTAB_FUNC2( addWith   , const std::vector< ptr<Expr> > &, const Decl * );
     463
     464        // A few extra functions have more complicated behaviour, they are hand written
     465        template<typename core_t>
     466        static inline auto addStructFwd( core_t & core, int, const ast::StructDecl * decl ) -> decltype( core.symtab.addStruct( decl ), void() ) {
     467                ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
     468                for ( const auto & param : decl->params ) {
     469                        fwd->params.push_back( deepCopy( param.get() ) );
     470                }
     471                core.symtab.addStruct( fwd );
     472        }
     473
     474        template<typename core_t>
     475        static inline void addStructFwd( core_t &, long, const ast::StructDecl * ) {}
     476
     477        template<typename core_t>
     478        static inline auto addUnionFwd( core_t & core, int, const ast::UnionDecl * decl ) -> decltype( core.symtab.addUnion( decl ), void() ) {
     479                ast::UnionDecl * fwd = new ast::UnionDecl( decl->location, decl->name );
     480                for ( const auto & param : decl->params ) {
     481                        fwd->params.push_back( deepCopy( param.get() ) );
     482                }
     483                core.symtab.addUnion( fwd );
     484        }
     485
     486        template<typename core_t>
     487        static inline void addUnionFwd( core_t &, long, const ast::UnionDecl * ) {}
     488
     489        template<typename core_t>
     490        static inline auto addStruct( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addStruct( str ), void() ) {
     491                if ( ! core.symtab.lookupStruct( str ) ) {
     492                        core.symtab.addStruct( str );
     493                }
     494        }
     495
     496        template<typename core_t>
     497        static inline void addStruct( core_t &, long, const std::string & ) {}
     498
     499        template<typename core_t>
     500        static inline auto addUnion( core_t & core, int, const std::string & str ) -> decltype( core.symtab.addUnion( str ), void() ) {
     501                if ( ! core.symtab.lookupUnion( str ) ) {
     502                        core.symtab.addUnion( str );
     503                }
     504        }
     505
     506        template<typename core_t>
     507        static inline void addUnion( core_t &, long, const std::string & ) {}
     508
     509        #undef SYMTAB_FUNC1
     510        #undef SYMTAB_FUNC2
     511} // namespace symtab
     512
     513// Some passes need to mutate TypeDecl and properly update their pointing TypeInstType.
     514// Detect the presence of a member name `subs` and call all members appropriately
     515namespace forall {
     516        // Some simple scoping rules
     517        template<typename core_t>
     518        static inline auto enter( core_t & core, int, const ast::FunctionType * type )
     519                        -> decltype( core.subs, void() ) {
     520                if ( ! type->forall.empty() ) core.subs.beginScope();
     521        }
     522
     523        template<typename core_t>
     524        static inline auto enter( core_t &, long, const ast::FunctionType * ) {}
     525
     526        template<typename core_t>
     527        static inline auto leave( core_t & core, int, const ast::FunctionType * type )
     528                        -> decltype( core.subs, void() ) {
     529                if ( ! type->forall.empty() ) { core.subs.endScope(); }
     530        }
     531
     532        template<typename core_t>
     533        static inline auto leave( core_t &, long, const ast::FunctionType * ) {}
     534
     535        // Replaces a TypeInstType's base TypeDecl according to the table
     536        template<typename core_t>
     537        static inline auto replace( core_t & core, int, const ast::TypeInstType *& inst )
     538                        -> decltype( core.subs, void() ) {
     539                inst = ast::mutate_field(
     540                        inst, &ast::TypeInstType::base, core.subs.replace( inst->base ) );
     541        }
     542
     543        template<typename core_t>
     544        static inline auto replace( core_t &, long, const ast::TypeInstType *& ) {}
     545} // namespace forall
     546
     547// For passes that need access to the global context. Searches `translationUnit`
     548namespace translation_unit {
     549        template<typename core_t>
     550        static inline auto get_cptr( core_t & core, int )
     551                        -> decltype( &core.translationUnit ) {
     552                return &core.translationUnit;
     553        }
     554
     555        template<typename core_t>
     556        static inline const TranslationUnit ** get_cptr( core_t &, long ) {
     557                return nullptr;
     558        }
     559}
     560
     561// For passes, usually utility passes, that have a result.
     562namespace result {
     563        template<typename core_t>
     564        static inline auto get( core_t & core, char ) -> decltype( core.result() ) {
    510565                return core.result();
    511566        }
    512567
    513568        template<typename core_t>
    514         static inline auto get_result( core_t & core, int ) -> decltype( core.result ) {
     569        static inline auto get( core_t & core, int ) -> decltype( core.result ) {
    515570                return core.result;
    516571        }
    517572
    518573        template<typename core_t>
    519         static inline void get_result( core_t &, long ) {}
    520 } // namespace __pass
    521 } // namespace ast
     574        static inline void get( core_t &, long ) {}
     575}
     576
     577} // namespace ast::__pass
     578
     579#undef __pedantic_pass_assertf
     580#undef __pedantic_pass_assert
  • src/AST/Print.cpp

    r34b4268 r24d6572  
    1616#include "Print.hpp"
    1717
     18#include "Attribute.hpp"
    1819#include "Decl.hpp"
    1920#include "Expr.hpp"
     21#include "Init.hpp"
    2022#include "Stmt.hpp"
    2123#include "Type.hpp"
    2224#include "TypeSubstitution.hpp"
    2325#include "CompilationState.h"
    24 
    25 #include "Common/utility.h" // for group_iterate
     26#include "Common/Iterate.hpp"
    2627
    2728using namespace std;
     
    2930namespace ast {
    3031
    31 template <typename C, typename... T>
    32 constexpr array<C,sizeof...(T)> make_array(T&&... values)
    33 {
    34         return array<C,sizeof...(T)>{
    35                 std::forward<T>(values)...
    36         };
     32namespace {
     33
     34template<typename C, typename... T>
     35constexpr array<C, sizeof...(T)> make_array( T&&... values ) {
     36        return array<C, sizeof...(T)>{ std::forward<T>( values )... };
     37}
     38
     39namespace Names {
     40        static constexpr auto FuncSpecifiers = make_array<const char*>(
     41                "inline", "_Noreturn", "fortran"
     42        );
     43
     44        static constexpr auto StorageClasses = make_array<const char*>(
     45                "extern", "static", "auto", "register", "__thread", "_Thread_local"
     46        );
     47
     48        static constexpr auto Qualifiers = make_array<const char*>(
     49                "const", "restrict", "volatile", "mutex", "_Atomic"
     50        );
     51}
     52
     53template<typename bits_t, size_t N>
     54void print( ostream & os, const bits_t & bits,
     55                const array<const char *, N> & names ) {
     56        if ( !bits.any() ) return;
     57        for ( size_t i = 0 ; i < N ; i += 1 ) {
     58                if ( bits[i] ) {
     59                        os << names[i] << ' ';
     60                }
     61        }
    3762}
    3863
     
    80105        static const char* Names[];
    81106
    82         struct Names {
    83                 static constexpr auto FuncSpecifiers = make_array<const char*>(
    84                         "inline", "_Noreturn", "fortran"
    85                 );
    86 
    87                 static constexpr auto StorageClasses = make_array<const char*>(
    88                         "extern", "static", "auto", "register", "__thread", "_Thread_local"
    89                 );
    90 
    91                 static constexpr auto Qualifiers = make_array<const char*>(
    92                         "const", "restrict", "volatile", "mutex", "_Atomic"
    93                 );
    94         };
    95 
    96         template<typename storage_t, size_t N>
    97         void print(const storage_t & storage, const array<const char *, N> & Names ) {
    98                 if ( storage.any() ) {
    99                         for ( size_t i = 0; i < Names.size(); i += 1 ) {
    100                                 if ( storage[i] ) {
    101                                         os << Names[i] << ' ';
    102                                 }
    103                         }
    104                 }
    105         }
    106 
    107         void print( const ast::Function::Specs & specs ) {
    108                 print(specs, Names::FuncSpecifiers);
    109         }
    110 
    111         void print( const ast::Storage::Classes & storage ) {
    112                 print(storage, Names::StorageClasses);
    113         }
    114 
    115         void print( const ast::CV::Qualifiers & qualifiers ) {
    116                 print(qualifiers, Names::Qualifiers);
    117         }
    118 
    119107        void print( const std::vector<ast::Label> & labels ) {
    120108                if ( labels.empty() ) return;
     
    221209        }
    222210
     211    void print( const ast::WaitStmt * node ) {
     212                if ( node->timeout_time ) {
     213                        os << indent-1 << "timeout of:" << endl;
     214                        node->timeout_time->accept( *this );
     215
     216                        if ( node->timeout_stmt ) {
     217                                os << indent-1 << "... with statment:" << endl;
     218                                node->timeout_stmt->accept( *this );
     219                        }
     220
     221                        if ( node->timeout_cond ) {
     222                                os << indent-1 << "... with condition:" << endl;
     223                                node->timeout_cond->accept( *this );
     224                        }
     225                }
     226
     227                if ( node->else_stmt ) {
     228                        os << indent-1 << "else:" << endl;
     229                        node->else_stmt->accept( *this );
     230
     231                        if ( node->else_cond ) {
     232                                os << indent-1 << "... with condition:" << endl;
     233                                node->else_cond->accept( *this );
     234                        }
     235                }
     236        }
     237
    223238        void preprint( const ast::NamedTypeDecl * node ) {
    224239                if ( ! node->name.empty() ) {
     
    230245                }
    231246
    232                 print( node->storage );
     247                ast::print( os, node->storage );
    233248                os << node->typeString();
    234249
     
    272287
    273288        void preprint( const ast::Type * node ) {
    274                 print( node->qualifiers );
     289                ast::print( os, node->qualifiers );
    275290        }
    276291
     
    278293                print( node->forall );
    279294                print( node->assertions );
    280                 print( node->qualifiers );
     295                ast::print( os, node->qualifiers );
    281296        }
    282297
    283298        void preprint( const ast::BaseInstType * node ) {
    284299                print( node->attributes );
    285                 print( node->qualifiers );
     300                ast::print( os, node->qualifiers );
    286301        }
    287302
     
    294309                }
    295310
    296                 print( node->storage );
     311                ast::print( os, node->storage );
    297312
    298313                if ( node->type ) {
     
    338353                if ( ! short_mode ) printAll( node->attributes );
    339354
    340                 print( node->storage );
    341                 print( node->funcSpec );
    342 
    343 
     355                ast::print( os, node->storage );
     356                ast::print( os, node->funcSpec );
    344357
    345358                if ( node->type && node->isTypeFixed ) {
     
    384397                                --indent;
    385398                        }
     399                }
     400
     401                if ( ! node->withExprs.empty() ) {
     402                        // Not with a clause, but the 'with clause'.
     403                        ++indent;
     404                        os << " with clause" << endl << indent;
     405                        printAll( node->withExprs );
     406                        --indent;
    386407                }
    387408
     
    746767        virtual const ast::Stmt * visit( const ast::SuspendStmt * node ) override final {
    747768                os << "Suspend Statement";
    748                 switch (node->type) {
    749                         case ast::SuspendStmt::None     : os << " with implicit target"; break;
    750                         case ast::SuspendStmt::Generator: os << " for generator"; break;
    751                         case ast::SuspendStmt::Coroutine: os << " for coroutine"; break;
     769                switch (node->kind) {
     770                case ast::SuspendStmt::None     : os << " with implicit target"; break;
     771                case ast::SuspendStmt::Generator: os << " for generator"; break;
     772                case ast::SuspendStmt::Coroutine: os << " for coroutine"; break;
    752773                }
    753774                os << endl;
     
    759780                }
    760781                ++indent;
     782
     783                return node;
     784        }
     785
     786        virtual const ast::WhenClause * visit( const ast::WhenClause * node ) override final {
     787                os << indent-1 << "target: ";
     788                safe_print( node->target );
     789
     790                if ( node->stmt ) {
     791                        os << indent-1 << "... with statment:" << endl;
     792                        node->stmt->accept( *this );
     793                }
     794
     795                if ( node->when_cond ) {
     796                        os << indent-1 << "... with when condition:" << endl;
     797                        node->when_cond->accept( *this );
     798                }
    761799
    762800                return node;
     
    800838        virtual const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
    801839                os << indent-1 << "target function: ";
    802                 safe_print( node->target_func );
     840                safe_print( node->target );
    803841
    804842                if ( !node->target_args.empty() ) {
     
    814852                }
    815853
    816                 if ( node->cond ) {
     854                if ( node->when_cond ) {
    817855                        os << indent-1 << "... with condition:" << endl;
    818                         node->cond->accept( *this );
    819                 }
    820 
     856                        node->when_cond->accept( *this );
     857                }
     858
     859                return node;
     860        }
     861
     862    virtual const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final {
     863                os << "Waituntil Statement" << endl;
     864                indent += 2;
     865                for( const auto & clause : node->clauses ) {
     866                        clause->accept( *this );
     867                }
     868        print(node);    // calls print( const ast::WaitStmt * node )
    821869                return node;
    822870        }
     
    16271675};
    16281676
     1677} // namespace
     1678
    16291679void print( ostream & os, const ast::Node * node, Indenter indent ) {
    16301680        Printer printer { os, indent, false };
     
    16371687}
    16381688
    1639 // Annoyingly these needed to be defined out of line to avoid undefined references.
    1640 // The size here needs to be explicit but at least the compiler will produce an error
    1641 // if the wrong size is specified
    1642 constexpr array<const char*, 3> Printer::Names::FuncSpecifiers;
    1643 constexpr array<const char*, 6> Printer::Names::StorageClasses;
    1644 constexpr array<const char*, 5> Printer::Names::Qualifiers;
     1689void print( ostream & os, Function::Specs specs ) {
     1690        print( os, specs, Names::FuncSpecifiers );
    16451691}
     1692
     1693void print( ostream & os, Storage::Classes storage ) {
     1694        print( os, storage, Names::StorageClasses );
     1695}
     1696
     1697void print( ostream & os, CV::Qualifiers qualifiers ) {
     1698        print( os, qualifiers, Names::Qualifiers );
     1699}
     1700
     1701} // namespace ast
  • src/AST/Print.hpp

    r34b4268 r24d6572  
    1616#pragma once
    1717
    18 #include <iostream>
    19 #include <utility>   // for forward
     18#include <iosfwd>
    2019
    21 #include "AST/Node.hpp"
     20#include "AST/Fwd.hpp"
    2221#include "Common/Indenter.h"
    2322
    2423namespace ast {
    25 
    26 class Decl;
    2724
    2825/// Print a node with the given indenter
     
    4441}
    4542
     43/// Print each cv-qualifier used in the set, followed by a space.
     44void print( std::ostream & os, CV::Qualifiers );
     45/// Print each function specifier used in the set, followed by a space.
     46void print( std::ostream & os, Function::Specs );
     47/// Print each storage class used in the set, followed by a space.
     48void print( std::ostream & os, Storage::Classes );
     49
    4650}
  • src/AST/Stmt.hpp

    r34b4268 r24d6572  
    1010// Created On       : Wed May  8 13:00:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Apr 20 14:34:00 2022
    13 // Update Count     : 36
     12// Last Modified On : Wed Apr  5 10:34:00 2023
     13// Update Count     : 37
    1414//
    1515
     
    205205};
    206206
     207// A while loop or a do-while loop:
     208enum WhileDoKind { While, DoWhile };
     209
    207210// While loop: while (...) ... else ... or do ... while (...) else ...;
    208211class WhileDoStmt final : public Stmt {
     
    212215        ptr<Stmt> else_;
    213216        std::vector<ptr<Stmt>> inits;
    214         bool isDoWhile;
     217        WhileDoKind isDoWhile;
    215218
    216219        WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body,
    217                                  const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )
     220                                 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} )
    218221                : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {}
    219222
    220223        WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_,
    221                                  const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )
     224                                 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} )
    222225                : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {}
    223226
     
    364367  public:
    365368        ptr<CompoundStmt> then;
    366         enum Type { None, Coroutine, Generator } type = None;
    367 
    368         SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, const std::vector<Label> && labels = {} )
    369                 : Stmt(loc, std::move(labels)), then(then), type(type) {}
     369        enum Kind { None, Coroutine, Generator } kind = None;
     370
     371        SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Kind kind, const std::vector<Label> && labels = {} )
     372                : Stmt(loc, std::move(labels)), then(then), kind(kind) {}
    370373
    371374        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     
    375378};
    376379
    377 // Waitfor statement: when (...) waitfor (... , ...) ... timeout(...) ... else ...
    378 class WaitForStmt final : public Stmt {
    379   public:
    380         std::vector<ptr<WaitForClause>> clauses;
    381         ptr<Expr> timeout_time;
     380// Base class of WaitFor/WaitUntil statements
     381// form: KEYWORD(...) ... timeout(...) ... else ...
     382class WaitStmt : public Stmt {
     383  public:
     384    ptr<Expr> timeout_time;
    382385        ptr<Stmt> timeout_stmt;
    383386        ptr<Expr> timeout_cond;
     
    385388        ptr<Expr> else_cond;
    386389
     390    WaitStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
     391                : Stmt(loc, std::move(labels)) {}
     392
     393  private:
     394    WaitStmt * clone() const override = 0;
     395        MUTATE_FRIEND
     396};
     397
     398// Base class for WaitFor/WaitUntil clauses
     399// form: when( when_cond ) KEYWORD( target ) stmt
     400class WhenClause : public StmtClause {
     401  public:
     402        ptr<Expr> target;
     403        ptr<Stmt> stmt;
     404        ptr<Expr> when_cond;
     405
     406        WhenClause( const CodeLocation & loc )
     407                : StmtClause( loc ) {}
     408
     409        const WhenClause * accept( Visitor & v ) const override { return v.visit( this ); }
     410  private:
     411        WhenClause * clone() const override { return new WhenClause{ *this }; }
     412        MUTATE_FRIEND
     413};
     414
     415// Waitfor statement: when (...) waitfor (... , ...) ... timeout(...) ... else ...
     416class WaitForStmt final : public WaitStmt {
     417  public:
     418        std::vector<ptr<WaitForClause>> clauses;
     419
    387420        WaitForStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
    388                 : Stmt(loc, std::move(labels)) {}
     421                : WaitStmt(loc, std::move(labels)) {}
    389422
    390423        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     
    394427};
    395428
    396 class WaitForClause final : public StmtClause {
    397   public:
    398         ptr<Expr> target_func;
     429// Clause in a waitfor statement: waitfor (..., ...) ...
     430class WaitForClause final : public WhenClause {
     431  public:
    399432        std::vector<ptr<Expr>> target_args;
    400         ptr<Stmt> stmt;
    401         ptr<Expr> cond;
    402433
    403434        WaitForClause( const CodeLocation & loc )
    404                 : StmtClause( loc ) {}
     435                : WhenClause( loc ) {}
    405436
    406437        const WaitForClause * accept( Visitor & v ) const override { return v.visit( this ); }
    407438  private:
    408439        WaitForClause * clone() const override { return new WaitForClause{ *this }; }
     440        MUTATE_FRIEND
     441};
     442
     443// waituntil statement: when (...) waituntil (...) ... timeout(...) ... else ...
     444class WaitUntilStmt final : public WaitStmt {
     445  public:
     446    // Non-ast node used during compilation to store data needed to generate predicates
     447    //    and set initial status values for clauses
     448    // Used to create a tree corresponding to the structure of the clauses in a WaitUntil
     449    struct ClauseNode {
     450        enum Op { AND, OR, LEFT_OR, LEAF, ELSE, TIMEOUT } op; // operation/type tag
     451        // LEFT_OR used with TIMEOUT/ELSE to indicate that we ignore right hand side after parsing
     452
     453        ClauseNode * left;
     454        ClauseNode * right;
     455        WhenClause * leaf;  // only set if this node is a leaf (points into vector of clauses)
     456
     457        bool ambiguousWhen; // used to paint nodes of predicate tree based on when() clauses
     458        bool whenState;     // used to track if when_cond is toggled on or off for generating init values
     459        bool childOfAnd;      // true on leaf nodes that are children of AND, false otherwise
     460
     461        ClauseNode( Op op, ClauseNode * left, ClauseNode * right )
     462            : op(op), left(left), right(right), leaf(nullptr),
     463            ambiguousWhen(false), whenState(true), childOfAnd(false) {}
     464        ClauseNode( Op op, WhenClause * leaf )
     465            : op(op), left(nullptr), right(nullptr), leaf(leaf),
     466            ambiguousWhen(false), whenState(true), childOfAnd(false) {}
     467        ClauseNode( WhenClause * leaf ) : ClauseNode(LEAF, leaf) {}
     468       
     469        ~ClauseNode() {
     470            if ( left ) delete left;
     471            if ( right ) delete right;
     472        }
     473    };
     474
     475        std::vector<ptr<WhenClause>> clauses;
     476    ClauseNode * predicateTree;
     477
     478        WaitUntilStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
     479                : WaitStmt(loc, std::move(labels)) {}
     480
     481    ~WaitUntilStmt() { delete predicateTree; }
     482
     483        const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
     484  private:
     485        WaitUntilStmt * clone() const override { return new WaitUntilStmt{ *this }; }
    409486        MUTATE_FRIEND
    410487};
     
    454531        MUTATE_FRIEND
    455532};
     533
    456534} // namespace ast
    457535
  • src/AST/SymbolTable.cpp

    r34b4268 r24d6572  
    1818#include <cassert>
    1919
     20#include "Copy.hpp"
     21#include <iostream>
     22#include <algorithm>
     23
    2024#include "Decl.hpp"
    2125#include "Expr.hpp"
    2226#include "Inspect.hpp"
    2327#include "Type.hpp"
    24 #include "CodeGen/OperatorTable.h"  // for isCtorDtorAssign
     28#include "CodeGen/OperatorTable.h"         // for isCtorDtorAssign
    2529#include "Common/SemanticError.h"
    2630#include "Common/Stats/Counter.h"
     
    2832#include "InitTweak/InitTweak.h"
    2933#include "ResolvExpr/Cost.h"
    30 #include "ResolvExpr/typeops.h"
     34#include "ResolvExpr/CandidateFinder.hpp"  // for referenceToRvalueConversion
     35#include "ResolvExpr/Unify.h"
    3136#include "SymTab/Mangler.h"
    3237
     
    6974        if ( baseExpr ) {
    7075                if (baseExpr->env) {
    71                         Expr * base = shallowCopy(baseExpr);
     76                        Expr * base = deepCopy(baseExpr);
    7277                        const TypeSubstitution * subs = baseExpr->env;
    7378                        base->env = nullptr;
     
    193198                        out.push_back(decl.second);
    194199                }
     200
     201                // std::cerr << otypeKey << ' ' << out.size() << std::endl;
    195202        }
    196203
     
    259266void SymbolTable::addId( const DeclWithType * decl, const Expr * baseExpr ) {
    260267        // default handling of conflicts is to raise an error
    261         addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
     268        addIdCommon( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
    262269}
    263270
    264271void SymbolTable::addDeletedId( const DeclWithType * decl, const Decl * deleter ) {
    265272        // default handling of conflicts is to raise an error
    266         addId( decl, OnConflict::error(), nullptr, deleter );
     273        addIdCommon( decl, OnConflict::error(), nullptr, deleter );
    267274}
    268275
     
    276283                } else {
    277284                        // typedef redeclarations are errors only if types are different
    278                         if ( ! ResolvExpr::typesCompatible( existing->base, added->base, SymbolTable{} ) ) {
     285                        if ( ! ResolvExpr::typesCompatible( existing->base, added->base ) ) {
    279286                                SemanticError( added->location, "redeclaration of " + added->name );
    280287                        }
     
    641648        } else if ( existing.id->linkage.is_mangled
    642649                        || ResolvExpr::typesCompatible(
    643                                 added->get_type(), existing.id->get_type(), SymbolTable{} ) ) {
     650                                added->get_type(), existing.id->get_type() ) ) {
    644651
    645652                // it is a conflict if one declaration is deleted and the other is not
     
    676683}
    677684
    678 void SymbolTable::addId(
    679                 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,
    680                 const Decl * deleter ) {
     685void SymbolTable::addIdCommon(
     686                const DeclWithType * decl, SymbolTable::OnConflict handleConflicts,
     687                const Expr * baseExpr, const Decl * deleter ) {
    681688        SpecialFunctionKind kind = getSpecialFunctionKind(decl->name);
    682689        if (kind == NUMBER_OF_KINDS) { // not a special decl
    683                 addId(decl, decl->name, idTable, handleConflicts, baseExpr, deleter);
     690                addIdToTable(decl, decl->name, idTable, handleConflicts, baseExpr, deleter);
    684691        }
    685692        else {
     
    694701                        assertf(false, "special decl with non-function type");
    695702                }
    696                 addId(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter);
    697         }
    698 }
    699 
    700 void SymbolTable::addId(
    701                 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,
    702                 const Decl * deleter ) {
     703                addIdToTable(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter);
     704        }
     705}
     706
     707void SymbolTable::addIdToTable(
     708                const DeclWithType * decl, const std::string & lookupKey,
     709                IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts,
     710                const Expr * baseExpr, const Decl * deleter ) {
    703711        ++*stats().add_calls;
    704712        const std::string &name = decl->name;
     
    777785void SymbolTable::addMembers(
    778786                const AggregateDecl * aggr, const Expr * expr, SymbolTable::OnConflict handleConflicts ) {
    779         for ( const Decl * decl : aggr->members ) {
    780                 if ( auto dwt = dynamic_cast< const DeclWithType * >( decl ) ) {
    781                         addId( dwt, handleConflicts, expr );
    782                         if ( dwt->name == "" ) {
    783                                 const Type * t = dwt->get_type()->stripReferences();
    784                                 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {
    785                                         if ( ! dynamic_cast<const StructInstType *>(rty)
    786                                                 && ! dynamic_cast<const UnionInstType *>(rty) ) continue;
    787                                         ResolvExpr::Cost cost = ResolvExpr::Cost::zero;
    788                                         ast::ptr<ast::TypeSubstitution> tmp = expr->env;
    789                                         expr = mutate_field(expr, &Expr::env, nullptr);
    790                                         const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost );
    791                                         base = mutate_field(base, &Expr::env, tmp);
    792 
    793                                         addMembers(
    794                                                 rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts );
    795                                 }
    796                         }
     787        for ( const ptr<Decl> & decl : aggr->members ) {
     788                auto dwt = decl.as<DeclWithType>();
     789                if ( nullptr == dwt ) continue;
     790                addIdCommon( dwt, handleConflicts, expr );
     791                // Inline through unnamed struct/union members.
     792                if ( "" != dwt->name ) continue;
     793                const Type * t = dwt->get_type()->stripReferences();
     794                if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {
     795                        if ( ! dynamic_cast<const StructInstType *>(rty)
     796                                && ! dynamic_cast<const UnionInstType *>(rty) ) continue;
     797                        ResolvExpr::Cost cost = ResolvExpr::Cost::zero;
     798                        ast::ptr<ast::TypeSubstitution> tmp = expr->env;
     799                        expr = mutate_field(expr, &Expr::env, nullptr);
     800                        const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost );
     801                        base = mutate_field(base, &Expr::env, tmp);
     802
     803                        addMembers(
     804                                rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts );
    797805                }
    798806        }
  • src/AST/SymbolTable.hpp

    r34b4268 r24d6572  
    192192
    193193        /// common code for addId, addDeletedId, etc.
    194         void addId(
    195                 const DeclWithType * decl, OnConflict handleConflicts, const Expr * baseExpr = nullptr,
    196                 const Decl * deleter = nullptr );
     194        void addIdCommon(
     195                const DeclWithType * decl, OnConflict handleConflicts,
     196                const Expr * baseExpr = nullptr, const Decl * deleter = nullptr );
    197197
    198198        /// common code for addId when special decls are placed into separate tables
    199         void addId(
    200                 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & idTable, OnConflict handleConflicts,
     199        void addIdToTable(
     200                const DeclWithType * decl, const std::string & lookupKey,
     201                IdTable::Ptr & idTable, OnConflict handleConflicts,
    201202                const Expr * baseExpr = nullptr, const Decl * deleter = nullptr);
    202        
     203
    203204        /// adds all of the members of the Aggregate (addWith helper)
    204205        void addMembers( const AggregateDecl * aggr, const Expr * expr, OnConflict handleConflicts );
  • src/AST/TranslationUnit.hpp

    r34b4268 r24d6572  
    1010// Created On       : Tue Jun 11 15:30:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Mar 11 11:19:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Thr Mar  9 16:41:00 2023
     13// Update Count     : 2
    1414//
    1515
     
    1717
    1818#include <map>
    19 #include <vector>
     19#include <list>
    2020
    2121#include "Fwd.hpp"
     
    2828
    2929        ptr<Type> sizeType;
    30         const FunctionDecl * dereference;
    31         const StructDecl * dtorStruct;
    32         const FunctionDecl * dtorDestroy;
     30        const FunctionDecl * dereference = nullptr;
     31        const StructDecl * dtorStruct = nullptr;
     32        const FunctionDecl * dtorDestroy = nullptr;
    3333};
    3434
  • src/AST/Type.cpp

    r34b4268 r24d6572  
    1010// Created On       : Mon May 13 15:00:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Nov 24  9:49:00 2022
    13 // Update Count     : 6
     12// Last Modified On : Thu Apr  6 15:59:00 2023
     13// Update Count     : 7
    1414//
    1515
     
    199199
    200200TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q )
    201 : Type( q ), types( std::move(ts) ), members() {
    202         // This constructor is awkward. `TupleType` needs to contain objects so that members can be
    203         // named, but members without initializer nodes end up getting constructors, which breaks
    204         // things. This happens because the object decls have to be visited so that their types are
    205         // kept in sync with the types listed here. Ultimately, the types listed here should perhaps
    206         // be eliminated and replaced with a list-view over members. The temporary solution is to
    207         // make a `ListInit` with `maybeConstructed = false`, so when the object is visited it is not
    208         // constructed. Potential better solutions include:
    209         //   a) Separate `TupleType` from its declarations, into `TupleDecl` and `Tuple{Inst?}Type`,
    210         //      similar to the aggregate types.
    211         //   b) Separate initializer nodes better, e.g. add a `MaybeConstructed` node that is replaced
    212         //      by `genInit`, rather than the current boolean flag.
    213         members.reserve( types.size() );
    214         for ( const Type * ty : types ) {
    215                 members.emplace_back( new ObjectDecl{
    216                         CodeLocation(), "", ty, new ListInit( CodeLocation(), {}, {}, NoConstruct ),
    217                         Storage::Classes{}, Linkage::Cforall } );
    218         }
    219 }
     201: Type( q ), types( std::move(ts) ) {}
    220202
    221203bool isUnboundType(const Type * type) {
  • src/AST/Type.hpp

    r34b4268 r24d6572  
    1010// Created On       : Thu May 9 10:00:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thu Nov 24  9:47:00 2022
    13 // Update Count     : 8
     12// Last Modified On : Thu Apr  6 15:58:00 2023
     13// Update Count     : 9
    1414//
    1515
     
    265265};
    266266
    267 /// Function variable arguments flag
    268 enum ArgumentFlag { FixedArgs, VariableArgs };
    269 
    270267/// Type of a function `[R1, R2](*)(P1, P2, P3)`
    271268class FunctionType final : public Type {
     
    462459public:
    463460        std::vector<ptr<Type>> types;
    464         std::vector<ptr<Decl>> members;
    465461
    466462        TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} );
  • src/AST/TypeEnvironment.cpp

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

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

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

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

    r34b4268 r24d6572  
    5050    virtual const ast::FinallyClause *    visit( const ast::FinallyClause        * ) = 0;
    5151    virtual const ast::Stmt *             visit( const ast::SuspendStmt          * ) = 0;
     52    virtual const ast::WhenClause *       visit( const ast::WhenClause           * ) = 0;
    5253    virtual const ast::Stmt *             visit( const ast::WaitForStmt          * ) = 0;
    5354    virtual const ast::WaitForClause *    visit( const ast::WaitForClause        * ) = 0;
     55    virtual const ast::Stmt *             visit( const ast::WaitUntilStmt        * ) = 0;
    5456    virtual const ast::Decl *             visit( const ast::WithStmt             * ) = 0;
    5557    virtual const ast::NullStmt *         visit( const ast::NullStmt             * ) = 0;
  • src/AST/porting.md

    r34b4268 r24d6572  
    213213* `get_statement()` exclusively used for code location, replaced with `CodeLocation` field
    214214
    215 `CaseStmt`
     215`CaseStmt` => `CaseClause`
    216216* `_isDefault` has been removed
    217217  * `isDefault` calculates value from `cond`
     
    227227* `block` -> `body` and `finallyBlock` -> `finally`
    228228
    229 `ThrowStmt` `CatchStmt`
     229`ThrowStmt` and `CatchStmt` => `CatchClause`
    230230* moved `Kind` enums to shared `ast::ExceptionKind` enum
    231231
    232 `FinallyStmt`
     232`FinallyStmt` => `FinallyClause`
    233233* `block` -> `body`
    234234
     
    280280* Template class, with specializations and using to implement some other types:
    281281  * `StructInstType`, `UnionInstType` & `EnumInstType`
     282  * `baseStruct`, `baseUnion` & `baseEnum` => `base`
    282283
    283284`TypeInstType`
  • src/CodeGen/CodeGenerator.cc

    r34b4268 r24d6572  
    1717#include <cassert>                   // for assert, assertf
    1818#include <list>                      // for _List_iterator, list, list<>::it...
     19#include <sstream>                   // for stringstream
    1920
    2021#include "AST/Decl.hpp"              // for DeclWithType
    2122#include "Common/UniqueName.h"       // for UniqueName
    22 #include "Common/utility.h"          // for CodeLocation, toString
    2323#include "GenType.h"                 // for genType
    2424#include "InitTweak/InitTweak.h"     // for getPointerBase
     
    273273        }
    274274
     275        template<typename pass_type>
     276        inline void genEnumInitializer( PassVisitor<pass_type> * visitor, Type * baseType, std::ostream & output,
     277        Initializer * init, long long * cur_val, Options options) {
     278                auto baseTypeAsBasic = baseType ? dynamic_cast<BasicType *>( baseType ) : nullptr;
     279                if ( init ) { // If value has an explicit initiazatior
     280                        output << " = ";
     281                        output << "(" << genType(baseType, "", options) << ")";
     282                        init->accept( *visitor );
     283                        if ( baseTypeAsBasic && baseTypeAsBasic->isInteger() ) { // if it is an integral type and initilizer offered,
     284                        // need to update the cur_val
     285                                Expression* expr = ((SingleInit *)(init))->value;
     286                                while ( auto temp = dynamic_cast<CastExpr *>(expr) ) { // unwrap introduced cast
     287                                        expr = temp->arg;
     288                                }
     289                                *cur_val = ((ConstantExpr *)expr)->constant.get_ival()+1;
     290                        }
     291                } else if ( baseTypeAsBasic && baseTypeAsBasic->isInteger() ) { // integral implicitly init to cur_val + 1
     292                        output << " = " << "(" << genType(baseType, "", options) << ")";
     293                        output << (*cur_val)++;
     294                }
     295        }
     296
    275297        void CodeGenerator::postvisit( EnumDecl * enumDecl ) {
    276298                extension( enumDecl );
    277299                std::list< Declaration* > &memb = enumDecl->get_members();
    278300                if (enumDecl->base && ! memb.empty()) {
    279                         unsigned long long last_val = -1; // if the first enum value has no explicit initializer,
    280                         // as other
     301                        long long cur_val = 0;
    281302                        for ( std::list< Declaration* >::iterator i = memb.begin(); i != memb.end();  i++) {
    282303                                ObjectDecl * obj = dynamic_cast< ObjectDecl* >( *i );
    283304                                assert( obj );
    284305                                output << "static ";
    285                                 output << genType(enumDecl->base, "", options) << " const ";
    286                                 output << mangleName( obj ) << " ";
    287                                 output << " = ";
    288                                 output << "(" << genType(enumDecl->base, "", options) << ")";
    289                                 if ( (BasicType *)(enumDecl->base) && ((BasicType *)(enumDecl->base))->isWholeNumber() ) {
    290                                         if ( obj->get_init() ) {
    291                                                 obj->get_init()->accept( *visitor );
    292                                                 Expression* expr = ((SingleInit *)(obj->init))->value;
    293                                                 while ( auto temp = dynamic_cast<CastExpr *>(expr) ) {
    294                                                         expr = temp->arg;
    295                                                 }
    296                                                 last_val = ((ConstantExpr *)expr)->constant.get_ival();
    297                                         } else {
    298                                                 output << ++last_val;
    299                                         } // if
    300                                 } else {
    301                                         if ( obj->get_init() ) {
    302                                                 obj->get_init()->accept( *visitor );
    303                                         } else {
    304                                                 // Should not reach here!
    305                                         }
    306                                 }
     306                                output << genType(enumDecl->base, mangleName( obj ), options);
     307                                genEnumInitializer( visitor, enumDecl->base, output, obj->get_init(), &cur_val, options);
    307308                                output << ";" << endl;
    308309                        } // for
  • src/CodeGen/GenType.cc

    r34b4268 r24d6572  
    255255        void GenType::postvisit( EnumInstType * enumInst ) {
    256256                if ( enumInst->baseEnum && enumInst->baseEnum->base ) {
    257                         typeString = genType(enumInst->baseEnum->base, "", options) + typeString;
     257                        typeString = genType(enumInst->baseEnum->base, typeString, options);
    258258                } else {
    259259                        typeString = enumInst->name + " " + typeString;
  • src/Common/CodeLocationTools.cpp

    r34b4268 r24d6572  
    128128    macro(FinallyClause, FinallyClause) \
    129129    macro(SuspendStmt, Stmt) \
     130    macro(WhenClause, WhenClause) \
    130131    macro(WaitForStmt, Stmt) \
    131132    macro(WaitForClause, WaitForClause) \
     133    macro(WaitUntilStmt, Stmt) \
    132134    macro(WithStmt, Decl) \
    133135    macro(NullStmt, NullStmt) \
     
    208210
    209211struct LeafKindVisitor : public ast::Visitor {
    210         LeafKind kind;
     212        LeafKind result;
    211213
    212214#define VISIT(node_type, return_type) \
    213215        const ast::return_type * visit( const ast::node_type * ) final { \
    214                 kind = LeafKind::node_type; \
     216                result = LeafKind::node_type; \
    215217                return nullptr; \
    216218        }
     
    222224
    223225LeafKind get_leaf_kind( ast::Node const * node ) {
    224         LeafKindVisitor visitor;
    225         node->accept( visitor );
    226         return visitor.kind;
     226        return ast::Pass<LeafKindVisitor>::read( node );
    227227}
    228228
  • src/Common/DeclStats.cpp

    r34b4268 r24d6572  
    2323#include <iostream>
    2424#include <map>
     25#include <sstream>
    2526#include <unordered_map>
    2627#include <unordered_set>
  • src/Common/Eval.cc

    r34b4268 r24d6572  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // utility.h --
     7// Eval.cc -- Evaluate parts of the ast at compile time.
    88//
    99// Author           : Richard C. Bilson
     
    1313// Update Count     : 119
    1414//
     15
     16#include "Eval.h"
    1517
    1618#include <utility> // for pair
  • src/Common/ResolvProtoDump.cpp

    r34b4268 r24d6572  
    1919#include <iostream>
    2020#include <set>
     21#include <sstream>
    2122#include <unordered_set>
    2223
     
    2627#include "AST/Type.hpp"
    2728#include "CodeGen/OperatorTable.h"
    28 #include "Common/utility.h"
    2929
    3030namespace {
  • src/Common/ScopedMap.h

    r34b4268 r24d6572  
    3737                template<typename N>
    3838                Scope(N && n) : map(), note(std::forward<N>(n)) {}
    39                
     39
    4040                Scope() = default;
    4141                Scope(const Scope &) = default;
     
    4646        typedef std::vector< Scope > ScopeList;
    4747
    48         ScopeList scopes; ///< scoped list of maps
     48        /// Scoped list of maps.
     49        ScopeList scopes;
    4950public:
    5051        typedef typename MapType::key_type key_type;
     
    5859        typedef typename MapType::const_pointer const_pointer;
    5960
    60         class iterator : public std::iterator< std::bidirectional_iterator_tag, value_type > {
    61         friend class ScopedMap;
    62         friend class const_iterator;
    63                 typedef typename ScopedMap::MapType::iterator wrapped_iterator;
    64                 typedef typename ScopedMap::ScopeList scope_list;
    65                 typedef typename scope_list::size_type size_type;
    66 
    67                 /// Checks if this iterator points to a valid item
    68                 bool is_valid() const {
    69                         return it != (*scopes)[level].map.end();
    70                 }
    71 
    72                 /// Increments on invalid
    73                 iterator & next_valid() {
    74                         if ( ! is_valid() ) { ++(*this); }
    75                         return *this;
    76                 }
    77 
    78                 /// Decrements on invalid
    79                 iterator & prev_valid() {
    80                         if ( ! is_valid() ) { --(*this); }
    81                         return *this;
    82                 }
    83 
    84                 iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel)
    85                         : scopes(&_scopes), it(_it), level(inLevel) {}
    86         public:
    87                 iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
    88                 iterator & operator= (const iterator & that) {
    89                         scopes = that.scopes; level = that.level; it = that.it;
    90                         return *this;
    91                 }
    92 
    93                 reference operator* () { return *it; }
    94                 pointer operator-> () const { return it.operator->(); }
    95 
    96                 iterator & operator++ () {
    97                         if ( it == (*scopes)[level].map.end() ) {
    98                                 if ( level == 0 ) return *this;
    99                                 --level;
    100                                 it = (*scopes)[level].map.begin();
    101                         } else {
    102                                 ++it;
    103                         }
    104                         return next_valid();
    105                 }
    106                 iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
    107 
    108                 iterator & operator-- () {
    109                         // may fail if this is the begin iterator; allowed by STL spec
    110                         if ( it == (*scopes)[level].map.begin() ) {
    111                                 ++level;
    112                                 it = (*scopes)[level].map.end();
    113                         }
    114                         --it;
    115                         return prev_valid();
    116                 }
    117                 iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
    118 
    119                 bool operator== (const iterator & that) const {
    120                         return scopes == that.scopes && level == that.level && it == that.it;
    121                 }
    122                 bool operator!= (const iterator & that) const { return !( *this == that ); }
    123 
    124                 size_type get_level() const { return level; }
    125 
    126                 Note & get_note() { return (*scopes)[level].note; }
    127                 const Note & get_note() const { return (*scopes)[level].note; }
    128 
    129         private:
    130                 scope_list *scopes;
    131                 wrapped_iterator it;
    132                 size_type level;
    133         };
    134 
    135         class const_iterator : public std::iterator< std::bidirectional_iterator_tag,
    136                                                      value_type > {
    137         friend class ScopedMap;
    138                 typedef typename ScopedMap::MapType::iterator wrapped_iterator;
    139                 typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator;
    140                 typedef typename ScopedMap::ScopeList scope_list;
    141                 typedef typename scope_list::size_type size_type;
    142 
    143                 /// Checks if this iterator points to a valid item
    144                 bool is_valid() const {
    145                         return it != (*scopes)[level].map.end();
    146                 }
    147 
    148                 /// Increments on invalid
    149                 const_iterator & next_valid() {
    150                         if ( ! is_valid() ) { ++(*this); }
    151                         return *this;
    152                 }
    153 
    154                 /// Decrements on invalid
    155                 const_iterator & prev_valid() {
    156                         if ( ! is_valid() ) { --(*this); }
    157                         return *this;
    158                 }
    159 
    160                 const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel)
    161                         : scopes(&_scopes), it(_it), level(inLevel) {}
    162         public:
    163                 const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
    164                 const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
    165                 const_iterator & operator= (const iterator & that) {
    166                         scopes = that.scopes; level = that.level; it = that.it;
    167                         return *this;
    168                 }
    169                 const_iterator & operator= (const const_iterator & that) {
    170                         scopes = that.scopes; level = that.level; it = that.it;
    171                         return *this;
    172                 }
    173 
    174                 const_reference operator* () { return *it; }
    175                 const_pointer operator-> () { return it.operator->(); }
    176 
    177                 const_iterator & operator++ () {
    178                         if ( it == (*scopes)[level].map.end() ) {
    179                                 if ( level == 0 ) return *this;
    180                                 --level;
    181                                 it = (*scopes)[level].map.begin();
    182                         } else {
    183                                 ++it;
    184                         }
    185                         return next_valid();
    186                 }
    187                 const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
    188 
    189                 const_iterator & operator-- () {
    190                         // may fail if this is the begin iterator; allowed by STL spec
    191                         if ( it == (*scopes)[level].map.begin() ) {
    192                                 ++level;
    193                                 it = (*scopes)[level].map.end();
    194                         }
    195                         --it;
    196                         return prev_valid();
    197                 }
    198                 const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
    199 
    200                 bool operator== (const const_iterator & that) const {
    201                         return scopes == that.scopes && level == that.level && it == that.it;
    202                 }
    203                 bool operator!= (const const_iterator & that) const { return !( *this == that ); }
    204 
    205                 size_type get_level() const { return level; }
    206 
    207                 const Note & get_note() const { return (*scopes)[level].note; }
    208 
    209         private:
    210                 scope_list const *scopes;
    211                 wrapped_const_iterator it;
    212                 size_type level;
    213         };
     61        // Both iterator types are complete bidrectional iterators, see below.
     62        class iterator;
     63        class const_iterator;
    21464
    21565        /// Starts a new scope
     
    297147        }
    298148
    299         template< typename value_type_t >
    300         std::pair< iterator, bool > insert( iterator at, value_type_t && value ) {
    301                 MapType & scope = (*at.scopes)[ at.level ].map;
    302                 std::pair< typename MapType::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) );
    303                 return std::make_pair( iterator(scopes, std::move( res.first ), at.level), std::move( res.second ) );
    304         }
    305 
    306149        template< typename value_t >
    307150        std::pair< iterator, bool > insert( const Key & key, value_t && value ) { return insert( std::make_pair( key, std::forward<value_t>( value ) ) ); }
     
    324167        }
    325168
    326         iterator erase( iterator pos ) {
    327                 MapType & scope = (*pos.scopes)[ pos.level ].map;
    328                 const typename iterator::wrapped_iterator & new_it = scope.erase( pos.it );
    329                 iterator it( *pos.scopes, new_it, pos.level );
    330                 return it.next_valid();
     169        /// Erases element with key in the innermost scope that has it.
     170        size_type erase( const Key & key ) {
     171                for ( auto it = scopes.rbegin() ; it != scopes.rend() ; ++it ) {
     172                        size_type i = it->map.erase( key );
     173                        if ( 0 != i ) return i;
     174                }
     175                return 0;
    331176        }
    332177
     
    343188                return c;
    344189        }
     190
     191        bool contains( const Key & key ) const {
     192                return find( key ) != cend();
     193        }
     194};
     195
     196template<typename Key, typename Value, typename Note>
     197class ScopedMap<Key, Value, Note>::iterator :
     198                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     199        friend class ScopedMap;
     200        friend class const_iterator;
     201        typedef typename ScopedMap::MapType::iterator wrapped_iterator;
     202        typedef typename ScopedMap::ScopeList scope_list;
     203        typedef typename scope_list::size_type size_type;
     204
     205        /// Checks if this iterator points to a valid item
     206        bool is_valid() const {
     207                return it != (*scopes)[level].map.end();
     208        }
     209
     210        /// Increments on invalid
     211        iterator & next_valid() {
     212                if ( ! is_valid() ) { ++(*this); }
     213                return *this;
     214        }
     215
     216        /// Decrements on invalid
     217        iterator & prev_valid() {
     218                if ( ! is_valid() ) { --(*this); }
     219                return *this;
     220        }
     221
     222        iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel)
     223                : scopes(&_scopes), it(_it), level(inLevel) {}
     224public:
     225        iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     226        iterator & operator= (const iterator & that) {
     227                scopes = that.scopes; level = that.level; it = that.it;
     228                return *this;
     229        }
     230
     231        reference operator* () { return *it; }
     232        pointer operator-> () const { return it.operator->(); }
     233
     234        iterator & operator++ () {
     235                if ( it == (*scopes)[level].map.end() ) {
     236                        if ( level == 0 ) return *this;
     237                        --level;
     238                        it = (*scopes)[level].map.begin();
     239                } else {
     240                        ++it;
     241                }
     242                return next_valid();
     243        }
     244        iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
     245
     246        iterator & operator-- () {
     247                // may fail if this is the begin iterator; allowed by STL spec
     248                if ( it == (*scopes)[level].map.begin() ) {
     249                        ++level;
     250                        it = (*scopes)[level].map.end();
     251                }
     252                --it;
     253                return prev_valid();
     254        }
     255        iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
     256
     257        bool operator== (const iterator & that) const {
     258                return scopes == that.scopes && level == that.level && it == that.it;
     259        }
     260        bool operator!= (const iterator & that) const { return !( *this == that ); }
     261
     262        size_type get_level() const { return level; }
     263
     264        Note & get_note() { return (*scopes)[level].note; }
     265        const Note & get_note() const { return (*scopes)[level].note; }
     266
     267private:
     268        scope_list *scopes;
     269        wrapped_iterator it;
     270        size_type level;
     271};
     272
     273template<typename Key, typename Value, typename Note>
     274class ScopedMap<Key, Value, Note>::const_iterator :
     275                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     276        friend class ScopedMap;
     277        typedef typename ScopedMap::MapType::iterator wrapped_iterator;
     278        typedef typename ScopedMap::MapType::const_iterator wrapped_const_iterator;
     279        typedef typename ScopedMap::ScopeList scope_list;
     280        typedef typename scope_list::size_type size_type;
     281
     282        /// Checks if this iterator points to a valid item
     283        bool is_valid() const {
     284                return it != (*scopes)[level].map.end();
     285        }
     286
     287        /// Increments on invalid
     288        const_iterator & next_valid() {
     289                if ( ! is_valid() ) { ++(*this); }
     290                return *this;
     291        }
     292
     293        /// Decrements on invalid
     294        const_iterator & prev_valid() {
     295                if ( ! is_valid() ) { --(*this); }
     296                return *this;
     297        }
     298
     299        const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel)
     300                : scopes(&_scopes), it(_it), level(inLevel) {}
     301public:
     302        const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     303        const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}
     304        const_iterator & operator= (const iterator & that) {
     305                scopes = that.scopes; level = that.level; it = that.it;
     306                return *this;
     307        }
     308        const_iterator & operator= (const const_iterator & that) {
     309                scopes = that.scopes; level = that.level; it = that.it;
     310                return *this;
     311        }
     312
     313        const_reference operator* () { return *it; }
     314        const_pointer operator-> () { return it.operator->(); }
     315
     316        const_iterator & operator++ () {
     317                if ( it == (*scopes)[level].map.end() ) {
     318                        if ( level == 0 ) return *this;
     319                        --level;
     320                        it = (*scopes)[level].map.begin();
     321                } else {
     322                        ++it;
     323                }
     324                return next_valid();
     325        }
     326        const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
     327
     328        const_iterator & operator-- () {
     329                // may fail if this is the begin iterator; allowed by STL spec
     330                if ( it == (*scopes)[level].map.begin() ) {
     331                        ++level;
     332                        it = (*scopes)[level].map.end();
     333                }
     334                --it;
     335                return prev_valid();
     336        }
     337        const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
     338
     339        bool operator== (const const_iterator & that) const {
     340                return scopes == that.scopes && level == that.level && it == that.it;
     341        }
     342        bool operator!= (const const_iterator & that) const { return !( *this == that ); }
     343
     344        size_type get_level() const { return level; }
     345
     346        const Note & get_note() const { return (*scopes)[level].note; }
     347
     348private:
     349        scope_list const *scopes;
     350        wrapped_const_iterator it;
     351        size_type level;
    345352};
    346353
  • src/Common/SemanticError.h

    r34b4268 r24d6572  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed May  4 14:08:26 2022
    13 // Update Count     : 35
     12// Last Modified On : Sat Feb 25 12:01:31 2023
     13// Update Count     : 37
    1414//
    1515
     
    5454
    5555constexpr WarningData WarningFormats[] = {
    56         {"self-assign"            , Severity::Warn    , "self assignment of expression: %s"                          },
    57         {"reference-conversion"   , Severity::Warn    , "rvalue to reference conversion of rvalue: %s"               },
    58         {"qualifiers-zero_t-one_t", Severity::Warn    , "questionable use of type qualifier %s with %s"              },
    59         {"aggregate-forward-decl" , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
    60         {"superfluous-decl"       , Severity::Warn    , "declaration does not allocate storage: %s"                  },
    61         {"superfluous-else"       , Severity::Warn    , "else clause never executed for empty loop conditional"      },
    62         {"gcc-attributes"         , Severity::Warn    , "invalid attribute: %s"                                      },
    63         {"c++-like-copy"          , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
     56        {"self-assign"              , Severity::Warn    , "self assignment of expression: %s"                          },
     57        {"reference-conversion"     , Severity::Warn    , "rvalue to reference conversion of rvalue: %s"               },
     58        {"qualifiers-zero_t-one_t"  , Severity::Warn    , "questionable use of type qualifier(s) with %s"              },
     59        {"aggregate-forward-decl"   , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
     60        {"superfluous-decl"         , Severity::Warn    , "declaration does not allocate storage: %s"                  },
     61        {"superfluous-else"         , Severity::Warn    , "else clause never executed for empty loop conditional"      },
     62        {"gcc-attributes"           , Severity::Warn    , "invalid attribute: %s"                                      },
     63        {"c++-like-copy"            , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
     64        {"depreciated-trait-syntax" , Severity::Warn    , "trait type-parameters are now specified using the forall clause" },
    6465};
    6566
     
    7374        GccAttributes,
    7475        CppCopy,
     76        DeprecTraitSyntax,
    7577        NUMBER_OF_WARNINGS, // This MUST be the last warning
    7678};
  • src/Common/module.mk

    r34b4268 r24d6572  
    2020        Common/CodeLocationTools.hpp \
    2121        Common/CodeLocationTools.cpp \
    22         Common/CompilerError.h \
    23         Common/Debug.h \
    2422        Common/DeclStats.hpp \
    2523        Common/DeclStats.cpp \
    2624        Common/ErrorObjects.h \
    2725        Common/Eval.cc \
     26        Common/Eval.h \
    2827        Common/Examine.cc \
    2928        Common/Examine.h \
     
    3130        Common/Indenter.h \
    3231        Common/Indenter.cc \
     32        Common/Iterate.hpp \
    3333        Common/PassVisitor.cc \
    3434        Common/PassVisitor.h \
     
    5252        Common/Stats/Time.cc \
    5353        Common/Stats/Time.h \
    54         Common/UnimplementedError.h \
     54        Common/ToString.hpp \
    5555        Common/UniqueName.cc \
    5656        Common/UniqueName.h \
  • src/Common/utility.h

    r34b4268 r24d6572  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // utility.h --
     7// utility.h -- General utilities used across the compiler.
    88//
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Mon Apr 25 14:26:00 2022
    13 // Update Count     : 51
     12// Last Modified On : Fri Feb 17 15:25:00 2023
     13// Update Count     : 53
    1414//
    1515
     
    1919#include <cctype>
    2020#include <algorithm>
    21 #include <functional>
    2221#include <iostream>
    23 #include <iterator>
    2422#include <list>
    2523#include <memory>
    26 #include <sstream>
    2724#include <string>
    2825#include <type_traits>
    29 #include <utility>
    3026#include <vector>
    3127#include <cstring>                                                                              // memcmp
     
    4945                return 0;
    5046        } // if
    51 }
    52 
    53 template< typename T, typename U >
    54 struct maybeBuild_t {
    55         static T * doit( const U *orig ) {
    56                 if ( orig ) {
    57                         return orig->build();
    58                 } else {
    59                         return 0;
    60                 } // if
    61         }
    62 };
    63 
    64 template< typename T, typename U >
    65 static inline T * maybeBuild( const U *orig ) {
    66         return maybeBuild_t<T,U>::doit(orig);
    67 }
    68 
    69 template< typename T, typename U >
    70 static inline T * maybeMoveBuild( const U *orig ) {
    71         T* ret = maybeBuild<T>(orig);
    72         delete orig;
    73         return ret;
    7447}
    7548
     
    168141        splice( src, dst );
    169142        dst.swap( src );
    170 }
    171 
    172 template < typename T >
    173 void toString_single( std::ostream & os, const T & value ) {
    174         os << value;
    175 }
    176 
    177 template < typename T, typename... Params >
    178 void toString_single( std::ostream & os, const T & value, const Params & ... params ) {
    179         os << value;
    180         toString_single( os, params ... );
    181 }
    182 
    183 template < typename ... Params >
    184 std::string toString( const Params & ... params ) {
    185         std::ostringstream os;
    186         toString_single( os, params... );
    187         return os.str();
    188 }
    189 
    190 #define toCString( ... ) toString( __VA_ARGS__ ).c_str()
    191 
    192 // replace element of list with all elements of another list
    193 template< typename T >
    194 void replace( std::list< T > &org, typename std::list< T >::iterator pos, std::list< T > &with ) {
    195         typename std::list< T >::iterator next = pos; advance( next, 1 );
    196 
    197         //if ( next != org.end() ) {
    198         org.erase( pos );
    199         org.splice( next, with );
    200         //}
    201 
    202         return;
    203 }
    204 
    205 // replace range of a list with a single element
    206 template< typename T >
    207 void replace( std::list< T > &org, typename std::list< T >::iterator begin, typename std::list< T >::iterator end, const T & with ) {
    208         org.insert( begin, with );
    209         org.erase( begin, end );
    210143}
    211144
     
    236169}
    237170
    238 template< typename... Args >
    239 auto zip(Args&&... args) -> decltype(zipWith(std::forward<Args>(args)..., std::make_pair)) {
    240   return zipWith(std::forward<Args>(args)..., std::make_pair);
    241 }
    242 
    243 template< class InputIterator1, class InputIterator2, class OutputIterator, class BinFunction >
    244 void zipWith( InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2, OutputIterator out, BinFunction func ) {
    245         while ( b1 != e1 && b2 != e2 )
    246                 *out++ = func(*b1++, *b2++);
    247 }
    248 
    249 // it's nice to actually be able to increment iterators by an arbitrary amount
    250 template< class InputIt, class Distance >
    251 InputIt operator+( InputIt it, Distance n ) {
    252         advance(it, n);
    253         return it;
    254 }
    255 
    256 template< typename T >
    257 void warn_single( const T & arg ) {
    258         std::cerr << arg << std::endl;
    259 }
    260 
    261 template< typename T, typename... Params >
    262 void warn_single(const T & arg, const Params & ... params ) {
    263         std::cerr << arg;
    264         warn_single( params... );
    265 }
    266 
    267 template< typename... Params >
    268 void warn( const Params & ... params ) {
    269         std::cerr << "Warning: ";
    270         warn_single( params... );
    271 }
    272 
    273171// determines if pref is a prefix of str
    274172static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int start = 0 ) {
    275173        if ( pref.size() > str.size() ) return false;
    276     return 0 == memcmp( str.c_str() + start, pref.c_str(), pref.size() );
    277         // return prefix == full.substr(0, prefix.size()); // for future, requires c++17
    278 }
    279 
    280 // -----------------------------------------------------------------------------
    281 // Ref Counted Singleton class
    282 // Objects that inherit from this class will have at most one reference to it
    283 // but if all references die, the object will be deleted.
    284 
    285 template< typename ThisType >
    286 class RefCountSingleton {
    287   public:
    288         static std::shared_ptr<ThisType> get() {
    289                 if( global_instance.expired() ) {
    290                         std::shared_ptr<ThisType> new_instance = std::make_shared<ThisType>();
    291                         global_instance = new_instance;
    292                         return std::move(new_instance);
    293                 }
    294                 return global_instance.lock();
    295         }
    296   private:
    297         static std::weak_ptr<ThisType> global_instance;
    298 };
    299 
    300 template< typename ThisType >
    301 std::weak_ptr<ThisType> RefCountSingleton<ThisType>::global_instance;
     174        return pref == str.substr(start, pref.size());
     175}
    302176
    303177// -----------------------------------------------------------------------------
     
    356230        ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } }
    357231};
    358 
    359 // -----------------------------------------------------------------------------
    360 // Helper struct and function to support
    361 // for ( val : reverseIterate( container ) ) {}
    362 // syntax to have a for each that iterates backwards
    363 
    364 template< typename T >
    365 struct reverse_iterate_t {
    366         T& ref;
    367 
    368         reverse_iterate_t( T & ref ) : ref(ref) {}
    369 
    370         // this does NOT work on const T!!!
    371         // typedef typename T::reverse_iterator iterator;
    372         auto begin() { return ref.rbegin(); }
    373         auto end() { return ref.rend(); }
    374 };
    375 
    376 template< typename T >
    377 reverse_iterate_t< T > reverseIterate( T & ref ) {
    378         return reverse_iterate_t< T >( ref );
    379 }
    380 
    381 template< typename T >
    382 struct enumerate_t {
    383         template<typename val_t>
    384         struct value_t {
    385                 val_t & val;
    386                 size_t idx;
    387         };
    388 
    389         template< typename iter_t, typename val_t >
    390         struct iterator_t {
    391                 iter_t it;
    392                 size_t idx;
    393 
    394                 iterator_t( iter_t _it, size_t _idx ) : it(_it), idx(_idx) {}
    395 
    396                 value_t<val_t> operator*() const { return value_t<val_t>{ *it, idx }; }
    397 
    398                 bool operator==(const iterator_t & o) const { return o.it == it; }
    399                 bool operator!=(const iterator_t & o) const { return o.it != it; }
    400 
    401                 iterator_t & operator++() {
    402                         it++;
    403                         idx++;
    404                         return *this;
    405                 }
    406 
    407                 using difference_type   = typename std::iterator_traits< iter_t >::difference_type;
    408                 using value_type        = value_t<val_t>;
    409                 using pointer           = value_t<val_t> *;
    410                 using reference         = value_t<val_t> &;
    411                 using iterator_category = std::forward_iterator_tag;
    412         };
    413 
    414         T & ref;
    415 
    416         using iterator = iterator_t< typename T::iterator, typename T::value_type >;
    417         using const_iterator = iterator_t< typename T::const_iterator, const typename T::value_type >;
    418 
    419         iterator begin() { return iterator( ref.begin(), 0 ); }
    420         iterator end()   { return iterator( ref.end(), ref.size() ); }
    421 
    422         const_iterator begin() const { return const_iterator( ref.cbegin(), 0 ); }
    423         const_iterator end()   const { return const_iterator( ref.cend(), ref.size() ); }
    424 
    425         const_iterator cbegin() const { return const_iterator( ref.cbegin(), 0 ); }
    426         const_iterator cend()   const { return const_iterator( ref.cend(), ref.size() ); }
    427 };
    428 
    429 template< typename T >
    430 enumerate_t<T> enumerate( T & ref ) {
    431         return enumerate_t< T >{ ref };
    432 }
    433 
    434 template< typename T >
    435 const enumerate_t< const T > enumerate( const T & ref ) {
    436         return enumerate_t< const T >{ ref };
    437 }
    438 
    439 template< typename OutType, typename Range, typename Functor >
    440 OutType map_range( const Range& range, Functor&& functor ) {
    441         OutType out;
    442 
    443         std::transform(
    444                 begin( range ),
    445                 end( range ),
    446                 std::back_inserter( out ),
    447                 std::forward< Functor >( functor )
    448         );
    449 
    450         return out;
    451 }
    452 
    453 // -----------------------------------------------------------------------------
    454 // Helper struct and function to support:
    455 // for ( auto val : group_iterate( container1, container2, ... ) ) { ... }
    456 // This iteraters through multiple containers of the same size.
    457 
    458 template<typename... Args>
    459 class group_iterate_t {
    460         using Iterables = std::tuple<Args...>;
    461         Iterables iterables;
    462 
    463         // Getting the iterator and value types this way preserves const.
    464         template<size_t I> using Iter = decltype(std::get<I>(iterables).begin());
    465         template<size_t I> using Data = decltype(*std::get<I>(iterables).begin());
    466         template<typename> struct base_iterator;
    467 
    468         // This inner template puts the sequence of `0, 1, ... sizeof...(Args)-1`
    469         // into a pack. These are the indexes into the tuples, so unpacking can
    470         // go over each element of the tuple.
    471         // The std::integer_sequence is just used to build that sequence.
    472         // A library reference will probably explain it better than I can.
    473         template<std::size_t... Indices>
    474         struct base_iterator<std::integer_sequence<std::size_t, Indices...>> {
    475                 using value_type = std::tuple< Data<Indices>... >;
    476                 std::tuple<Iter<Indices>...> iterators;
    477 
    478                 base_iterator( Iter<Indices>... is ) : iterators( is... ) {}
    479                 base_iterator operator++() {
    480                         return base_iterator( ++std::get<Indices>( iterators )... );
    481                 }
    482                 bool operator!=( const base_iterator& other ) const {
    483                         return iterators != other.iterators;
    484                 }
    485                 value_type operator*() const {
    486                         return std::tie( *std::get<Indices>( iterators )... );
    487                 }
    488 
    489                 static base_iterator make_begin( Iterables & data ) {
    490                         return base_iterator( std::get<Indices>( data ).begin()... );
    491                 }
    492                 static base_iterator make_end( Iterables & data ) {
    493                         return base_iterator( std::get<Indices>( data ).end()... );
    494                 }
    495         };
    496 
    497 public:
    498         group_iterate_t( const Args &... args ) : iterables( args... ) {}
    499 
    500         using iterator = base_iterator<decltype(
    501                 std::make_integer_sequence<std::size_t, sizeof...(Args)>())>;
    502 
    503         iterator begin() { return iterator::make_begin( iterables ); }
    504         iterator end() { return iterator::make_end( iterables ); }
    505 };
    506 
    507 // Helpers for the bounds checks (the non-varatic part of group_iterate):
    508 static inline void runGroupBoundsCheck(size_t size0, size_t size1) {
    509         assertf( size0 == size1,
    510                 "group iteration requires containers of the same size: <%zd, %zd>.",
    511                 size0, size1 );
    512 }
    513 
    514 static inline void runGroupBoundsCheck(size_t size0, size_t size1, size_t size2) {
    515         assertf( size0 == size1 && size1 == size2,
    516                 "group iteration requires containers of the same size: <%zd, %zd, %zd>.",
    517                 size0, size1, size2 );
    518 }
    519 
    520 /// Performs bounds check to ensure that all arguments are of the same length.
    521 template< typename... Args >
    522 group_iterate_t<Args...> group_iterate( Args &&... args ) {
    523         runGroupBoundsCheck( args.size()... );
    524         return group_iterate_t<Args...>( std::forward<Args>( args )... );
    525 }
    526 
    527 /// Does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.
    528 template< typename... Args >
    529 group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) {
    530         return group_iterate_t<Args...>( std::forward<Args>( args )... );
    531 }
    532 
    533 // -----------------------------------------------------------------------------
    534 // Helper struct and function to support
    535 // for ( val : lazy_map( container1, f ) ) {}
    536 // syntax to have a for each that iterates a container, mapping each element by applying f
    537 template< typename T, typename Func >
    538 struct lambda_iterate_t {
    539         const T & ref;
    540         std::function<Func> f;
    541 
    542         struct iterator {
    543                 typedef decltype(begin(ref)) Iter;
    544                 Iter it;
    545                 std::function<Func> f;
    546                 iterator( Iter it, std::function<Func> f ) : it(it), f(f) {}
    547                 iterator & operator++() {
    548                         ++it; return *this;
    549                 }
    550                 bool operator!=( const iterator &other ) const { return it != other.it; }
    551                 auto operator*() const -> decltype(f(*it)) { return f(*it); }
    552         };
    553 
    554         lambda_iterate_t( const T & ref, std::function<Func> f ) : ref(ref), f(f) {}
    555 
    556         auto begin() const -> decltype(iterator(std::begin(ref), f)) { return iterator(std::begin(ref), f); }
    557         auto end() const   -> decltype(iterator(std::end(ref), f)) { return iterator(std::end(ref), f); }
    558 };
    559 
    560 template< typename... Args >
    561 lambda_iterate_t<Args...> lazy_map( const Args &... args ) {
    562         return lambda_iterate_t<Args...>( args...);
    563 }
    564232
    565233// -----------------------------------------------------------------------------
     
    583251} // ilog2
    584252
    585 // -----------------------------------------------------------------------------
    586 /// evaluates expr as a long long int. If second is false, expr could not be evaluated
    587 std::pair<long long int, bool> eval(const Expression * expr);
    588 
    589 namespace ast {
    590         class Expr;
    591 }
    592 
    593 std::pair<long long int, bool> eval(const ast::Expr * expr);
    594 
    595 // -----------------------------------------------------------------------------
    596 /// Reorders the input range in-place so that the minimal-value elements according to the
    597 /// comparator are in front;
    598 /// returns the iterator after the last minimal-value element.
    599 template<typename Iter, typename Compare>
    600 Iter sort_mins( Iter begin, Iter end, Compare& lt ) {
    601         if ( begin == end ) return end;
    602 
    603         Iter min_pos = begin;
    604         for ( Iter i = begin + 1; i != end; ++i ) {
    605                 if ( lt( *i, *min_pos ) ) {
    606                         // new minimum cost; swap into first position
    607                         min_pos = begin;
    608                         std::iter_swap( min_pos, i );
    609                 } else if ( ! lt( *min_pos, *i ) ) {
    610                         // duplicate minimum cost; swap into next minimum position
    611                         ++min_pos;
    612                         std::iter_swap( min_pos, i );
    613                 }
    614         }
    615         return ++min_pos;
    616 }
    617 
    618 template<typename Iter, typename Compare>
    619 inline Iter sort_mins( Iter begin, Iter end, Compare&& lt ) {
    620         return sort_mins( begin, end, lt );
    621 }
    622 
    623 /// sort_mins defaulted to use std::less
    624 template<typename Iter>
    625 inline Iter sort_mins( Iter begin, Iter end ) {
    626         return sort_mins( begin, end, std::less<typename std::iterator_traits<Iter>::value_type>{} );
    627 }
    628 
    629253// Local Variables: //
    630254// tab-width: 4 //
  • src/CompilationState.cc

    r34b4268 r24d6572  
    99// Author           : Rob Schluntz
    1010// Created On       : Mon Ju1 30 10:47:01 2018
    11 // Last Modified By : Henry Xue
    12 // Last Modified On : Tue Jul 20 04:27:35 2021
    13 // Update Count     : 5
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Apr 10 19:12:50 2023
     13// Update Count     : 6
    1414//
    1515
     
    2727        expraltp = false,
    2828        genericsp = false,
     29        invariant = false,
    2930        libcfap = false,
    3031        nopreludep = false,
     
    3334        useNewAST = true,
    3435        nomainp = false,
    35         parsep = false,
    3636        resolvep = false,
    3737        resolvprotop = false,
  • src/CompilationState.h

    r34b4268 r24d6572  
    99// Author           : Rob Schluntz
    1010// Created On       : Mon Ju1 30 10:47:01 2018
    11 // Last Modified By : Henry Xue
    12 // Last Modified On : Tue Jul 20 04:27:35 2021
    13 // Update Count     : 5
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Apr 10 19:12:53 2023
     13// Update Count     : 6
    1414//
    1515
     
    2626        expraltp,
    2727        genericsp,
     28        invariant,
    2829        libcfap,
    2930        nopreludep,
     
    3233        useNewAST,
    3334        nomainp,
    34         parsep,
    3535        resolvep,
    3636        resolvprotop,
  • src/Concurrency/KeywordsNew.cpp

    r34b4268 r24d6572  
    779779
    780780const ast::Stmt * SuspendKeyword::postvisit( const ast::SuspendStmt * stmt ) {
    781         switch ( stmt->type ) {
     781        switch ( stmt->kind ) {
    782782        case ast::SuspendStmt::None:
    783783                // Use the context to determain the implicit target.
  • src/Concurrency/WaitforNew.cpp

    r34b4268 r24d6572  
    305305
    306306        const ast::VariableExpr * variableExpr =
    307                 clause->target_func.as<ast::VariableExpr>();
     307                clause->target.as<ast::VariableExpr>();
    308308        ast::Expr * castExpr = new ast::CastExpr(
    309309                location,
    310310                new ast::CastExpr(
    311311                        location,
    312                         clause->target_func,
     312                        clause->target,
    313313                        ast::deepCopy( variableExpr->result.get() ),
    314314                        ast::GeneratedCast ),
     
    325325
    326326        ResolveContext context{ symtab, transUnit().global };
    327         out->push_back( maybeCond( location, clause->cond.get(), {
     327        out->push_back( maybeCond( location, clause->when_cond.get(), {
    328328                makeAccStmt( location, acceptables, index, "is_dtor",
    329                         detectIsDtor( location, clause->target_func ), context ),
     329                        detectIsDtor( location, clause->target ), context ),
    330330                makeAccStmt( location, acceptables, index, "func",
    331331                        funcExpr, context ),
  • src/Concurrency/module.mk

    r34b4268 r24d6572  
    1616
    1717SRC += \
     18        Concurrency/Actors.cpp \
     19        Concurrency/Actors.hpp \
    1820        Concurrency/KeywordsNew.cpp \
    1921        Concurrency/Keywords.cc \
     
    2123        Concurrency/WaitforNew.cpp \
    2224        Concurrency/Waitfor.cc \
    23         Concurrency/Waitfor.h
     25        Concurrency/Waitfor.h \
     26        Concurrency/Waituntil.cpp \
     27        Concurrency/Waituntil.hpp
  • src/ControlStruct/ExceptDeclNew.cpp

    r34b4268 r24d6572  
    1616#include "ExceptDecl.h"
    1717
     18#include <sstream>
     19
     20#include "AST/Copy.hpp"
    1821#include "AST/Decl.hpp"
    1922#include "AST/Pass.hpp"
  • src/ControlStruct/ExceptTranslateNew.cpp

    r34b4268 r24d6572  
    314314                nullptr,
    315315                ast::Storage::Classes{},
    316                 ast::Linkage::Cforall
     316                ast::Linkage::Cforall,
     317                {},
     318                { ast::Function::Inline }
    317319        );
    318320}
  • src/ControlStruct/MLEMutator.cc

    r34b4268 r24d6572  
    2525#include <memory>                          // for allocator_traits<>::value_...
    2626
    27 #include "Common/utility.h"                // for toString, operator+
     27#include "Common/ToString.hpp"             // for toString
    2828#include "ControlStruct/LabelGenerator.h"  // for LabelGenerator
    2929#include "MLEMutator.h"
  • src/GenPoly/Box.cc

    r34b4268 r24d6572  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 23:40:34 2019
    13 // Update Count     : 347
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Dec 19 16:36:00 2022
     13// Update Count     : 348
    1414//
     15
     16#include "Box.h"
    1517
    1618#include <algorithm>                     // for mismatch
     
    2426#include <utility>                       // for pair
    2527
    26 #include "Box.h"
    27 
    2828#include "CodeGen/OperatorTable.h"
    2929#include "Common/PassVisitor.h"          // for PassVisitor
     
    3131#include "Common/SemanticError.h"        // for SemanticError
    3232#include "Common/UniqueName.h"           // for UniqueName
    33 #include "Common/utility.h"              // for toString
     33#include "Common/ToString.hpp"           // for toCString
    3434#include "FindFunction.h"                // for findFunction, findAndReplace...
    3535#include "GenPoly/ErasableScopedMap.h"   // for ErasableScopedMap<>::const_i...
     
    3737#include "InitTweak/InitTweak.h"         // for getFunctionName, isAssignment
    3838#include "Lvalue.h"                      // for generalizedLvalue
    39 #include "ResolvExpr/typeops.h"          // for typesCompatible
     39#include "ResolvExpr/Unify.h"            // for typesCompatible
    4040#include "ScopedSet.h"                   // for ScopedSet, ScopedSet<>::iter...
    4141#include "ScrubTyVars.h"                 // for ScrubTyVars
     
    7272                };
    7373
     74                /// Updates the call sites of polymorphic functions.
    7475                /// Replaces polymorphic return types with out-parameters,
    7576                /// replaces calls to polymorphic functions with adapter calls,
    7677                /// and adds appropriate type variables to the function call.
    77                 class Pass1 final : public BoxPass, public WithConstTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<Pass1>, public WithShortCircuiting {
     78                class CallAdapter final : public BoxPass, public WithConstTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<CallAdapter>, public WithShortCircuiting {
    7879                  public:
    79                         Pass1();
    80 
     80                        CallAdapter();
     81
     82                        void premutate( Declaration * declaration );
    8183                        void premutate( FunctionDecl * functionDecl );
    8284                        void premutate( TypeDecl * typeDecl );
     
    138140                };
    139141
     142                /// Updates declarations (and types) that require adapters.
    140143                /// * Moves polymorphic returns in function types to pointer-type parameters
    141144                /// * adds type size and assertion parameters to parameter lists
    142                 struct Pass2 final : public BoxPass, public WithGuards {
     145                struct DeclAdapter final : public BoxPass, public WithGuards {
    143146                        void handleAggDecl();
    144147
     
    210213                };
    211214
     215                /// Erases unneeded/unwanted polymorphic information.
    212216                /// Replaces initialization of polymorphic values with alloca,
    213217                /// declaration of dtype/ftype with appropriate void expression,
    214218                /// sizeof expressions of polymorphic types with the proper variable,
    215219                /// and strips fields from generic struct declarations.
    216                 struct Pass3 final : public BoxPass, public WithGuards {
    217                         template< typename DeclClass >
    218                         void handleDecl( DeclClass * decl, Type * type );
    219 
     220                struct Eraser final {
    220221                        void premutate( ObjectDecl * objectDecl );
    221222                        void premutate( FunctionDecl * functionDecl );
     
    223224                        void premutate( StructDecl * structDecl );
    224225                        void premutate( UnionDecl * unionDecl );
    225                         void premutate( TypeDecl * typeDecl );
    226                         void premutate( PointerType * pointerType );
    227                         void premutate( FunctionType * funcType );
    228226                };
    229227        } // anonymous namespace
     
    231229        void box( std::list< Declaration *>& translationUnit ) {
    232230                PassVisitor<LayoutFunctionBuilder> layoutBuilder;
    233                 PassVisitor<Pass1> pass1;
    234                 PassVisitor<Pass2> pass2;
     231                PassVisitor<CallAdapter> callAdapter;
     232                PassVisitor<DeclAdapter> declAdapter;
    235233                PassVisitor<PolyGenericCalculator> polyCalculator;
    236                 PassVisitor<Pass3> pass3;
     234                PassVisitor<Eraser> eraser;
    237235
    238236                acceptAll( translationUnit, layoutBuilder );
    239                 mutateAll( translationUnit, pass1 );
    240                 mutateAll( translationUnit, pass2 );
     237                mutateAll( translationUnit, callAdapter );
     238                mutateAll( translationUnit, declAdapter );
    241239                mutateAll( translationUnit, polyCalculator );
    242                 mutateAll( translationUnit, pass3 );
     240                mutateAll( translationUnit, eraser );
    243241        }
    244242
    245         ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
     243////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////
    246244
    247245        /// Get a list of type declarations that will affect a layout function
     
    423421        }
    424422
    425         ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
     423////////////////////////////////////////////// CallAdapter //////////////////////////////////////
    426424
    427425        namespace {
    428426                std::string makePolyMonoSuffix( FunctionType const * function, const TyVarMap &tyVars ) {
    429                         std::stringstream name;
    430 
    431427                        // NOTE: this function previously used isPolyObj, which failed to produce
    432428                        // the correct thing in some situations. It's not clear to me why this wasn't working.
     
    435431                        // to take those polymorphic types as pointers. Therefore, there can be two different functions
    436432                        // with the same mangled name, so we need to further mangle the names.
     433                        std::stringstream name;
    437434                        for ( DeclarationWithType const * const ret : function->returnVals ) {
    438                                 if ( isPolyType( ret->get_type(), tyVars ) ) {
    439                                         name << "P";
    440                                 } else {
    441                                         name << "M";
    442                                 }
    443                         }
    444                         name << "_";
     435                                name << ( isPolyType( ret->get_type(), tyVars ) ? 'P' : 'M' );
     436                        }
     437                        name << '_';
    445438                        for ( DeclarationWithType const * const arg : function->parameters ) {
    446                                 if ( isPolyType( arg->get_type(), tyVars ) ) {
    447                                         name << "P";
    448                                 } else {
    449                                         name << "M";
    450                                 }
    451                         } // for
     439                                name << ( isPolyType( arg->get_type(), tyVars ) ? 'P' : 'M' );
     440                        }
    452441                        return name.str();
    453442                }
     
    465454                Type *replaceWithConcrete( Type *type, TypeSubstitution const * env, bool doClone = true );
    466455
    467                 Pass1::Pass1() : tempNamer( "_temp" ) {}
    468 
    469                 void Pass1::premutate( FunctionDecl *functionDecl ) {
     456                CallAdapter::CallAdapter() : tempNamer( "_temp" ) {}
     457
     458                void CallAdapter::premutate( Declaration * ) {
     459                        // Prevent type declaration information from leaking out.
     460                        GuardScope( scopeTyVars );
     461                }
     462
     463                void CallAdapter::premutate( FunctionDecl *functionDecl ) {
    470464                        if ( functionDecl->get_statements() ) {         // empty routine body ?
    471465                                // std::cerr << "mutating function: " << functionDecl->get_mangleName() << std::endl;
     
    500494                                for ( FunctionType const * const funType : functions ) {
    501495                                        std::string mangleName = mangleAdapterName( funType, scopeTyVars );
    502                                         if ( adapters.find( mangleName ) == adapters.end() ) {
     496                                        if ( !adapters.contains( mangleName ) ) {
    503497                                                std::string adapterName = makeAdapterName( mangleName );
    504498                                                adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, new ObjectDecl( adapterName, Type::StorageClasses(), LinkageSpec::C, nullptr, new PointerType( Type::Qualifiers(), makeAdapterType( funType, scopeTyVars ) ), nullptr ) ) );
     
    509503                }
    510504
    511                 void Pass1::premutate( TypeDecl *typeDecl ) {
     505                void CallAdapter::premutate( TypeDecl *typeDecl ) {
    512506                        addToTyVarMap( typeDecl, scopeTyVars );
    513507                }
    514508
    515                 void Pass1::premutate( CommaExpr *commaExpr ) {
     509                void CallAdapter::premutate( CommaExpr *commaExpr ) {
    516510                        // Attempting to find application expressions that were mutated by the copy constructor passes
    517511                        // to use an explicit return variable, so that the variable can be reused as a parameter to the
     
    531525                }
    532526
    533                 std::list< Expression *>::iterator Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
     527                std::list< Expression *>::iterator CallAdapter::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
    534528                        Type *polyType = isPolyType( parmType, exprTyVars );
    535529                        if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     
    558552                }
    559553
    560                 std::list< Expression *>::iterator Pass1::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars ) {
     554                std::list< Expression *>::iterator CallAdapter::passTypeVars( ApplicationExpr *appExpr, Type *polyRetType, const TyVarMap &exprTyVars ) {
    561555                        assert( env );
    562556                        std::list< Expression *>::iterator arg = appExpr->args.begin();
     
    568562                        // even when converted to strings, sort in the original order.
    569563                        // (At least, that is the best explination I have.)
    570                         for ( std::pair<std::string, TypeDecl::Data> const & tyParam : exprTyVars ) {
     564                        for ( std::pair<const std::string, TypeDecl::Data> const & tyParam : exprTyVars ) {
    571565                                if ( !tyParam.second.isComplete ) continue;
    572566                                Type *concrete = env->lookup( tyParam.first );
     
    611605                }
    612606
    613                 ObjectDecl *Pass1::makeTemporary( Type *type ) {
     607                ObjectDecl *CallAdapter::makeTemporary( Type *type ) {
    614608                        ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, type, 0 );
    615609                        stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
     
    617611                }
    618612
    619                 Expression *Pass1::addRetParam( ApplicationExpr *appExpr, Type *retType ) {
     613                Expression *CallAdapter::addRetParam( ApplicationExpr *appExpr, Type *retType ) {
    620614                        // Create temporary to hold return value of polymorphic function and produce that temporary as a result
    621615                        // using a comma expression.
     
    680674                }
    681675
    682                 Expression *Pass1::addDynRetParam( ApplicationExpr *appExpr, Type *dynType ) {
     676                Expression *CallAdapter::addDynRetParam( ApplicationExpr *appExpr, Type *dynType ) {
    683677                        Type *concrete = replaceWithConcrete( dynType, env );
    684678                        // add out-parameter for return value
     
    686680                }
    687681
    688                 Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function ) {
     682                Expression *CallAdapter::applyAdapter( ApplicationExpr *appExpr, FunctionType *function ) {
    689683                        Expression *ret = appExpr;
    690684                        if ( isDynRet( function, scopeTyVars ) ) {
     
    735729                }
    736730
    737                 void Pass1::boxParam( Expression *&arg, Type *param, const TyVarMap &exprTyVars ) {
     731                void CallAdapter::boxParam( Expression *&arg, Type *param, const TyVarMap &exprTyVars ) {
    738732                        assertf( arg->result, "arg does not have result: %s", toString( arg ).c_str() );
    739733                        addCast( arg, param, exprTyVars );
     
    770764                }
    771765
    772                 void Pass1::boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars ) {
     766                void CallAdapter::boxParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *function, const TyVarMap &exprTyVars ) {
    773767                        for ( DeclarationWithType * param : function->parameters ) {
    774768                                assertf( arg != appExpr->args.end(), "boxParams: missing argument for param %s to %s in %s", toString( param ).c_str(), toString( function ).c_str(), toString( appExpr ).c_str() );
     
    778772                }
    779773
    780                 void Pass1::addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars ) {
     774                void CallAdapter::addInferredParams( ApplicationExpr *appExpr, std::list< Expression *>::iterator arg, FunctionType *functionType, const TyVarMap &tyVars ) {
    781775                        for ( TypeDecl * const tyVar : functionType->forall ) {
    782776                                for ( DeclarationWithType * const assert : tyVar->assertions ) {
     
    846840                }
    847841
    848                 FunctionDecl *Pass1::makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
     842                FunctionDecl *CallAdapter::makeAdapter( FunctionType const *adaptee, FunctionType *realType, const std::string &mangleName, const TyVarMap &tyVars ) {
    849843                        FunctionType *adapterType = makeAdapterType( adaptee, tyVars );
    850844                        adapterType = ScrubTyVars::scrub( adapterType, tyVars );
     
    906900                }
    907901
    908                 void Pass1::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
     902                void CallAdapter::passAdapters( ApplicationExpr * appExpr, FunctionType * functionType, const TyVarMap & exprTyVars ) {
    909903                        // collect a list of function types passed as parameters or implicit parameters (assertions)
    910904                        std::list<FunctionType const *> functions;
     
    923917
    924918                        for ( FunctionType const * const funType : functions ) {
    925                                 FunctionType *originalFunction = funType->clone();
    926                                 FunctionType *realFunction = funType->clone();
    927                                 std::string mangleName = SymTab::Mangler::mangle( realFunction );
     919                                std::string mangleName = SymTab::Mangler::mangle( funType );
    928920
    929921                                // only attempt to create an adapter or pass one as a parameter if we haven't already done so for this
    930922                                // pre-substitution parameter function type.
    931923                                // The second part of the insert result is "is the value new".
    932                                 if ( adaptersDone.insert( mangleName ).second ) {
    933 
    934                                         // apply substitution to type variables to figure out what the adapter's type should look like
    935                                         assert( env );
    936                                         env->apply( realFunction );
    937                                         mangleName = SymTab::Mangler::mangle( realFunction );
    938                                         mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
    939 
    940                                         typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
    941                                         AdapterIter adapter = adapters.find( mangleName );
    942                                         if ( adapter == adapters.end() ) {
    943                                                 // adapter has not been created yet in the current scope, so define it
    944                                                 FunctionDecl *newAdapter = makeAdapter( funType, realFunction, mangleName, exprTyVars );
    945                                                 std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
    946                                                 adapter = answer.first;
    947                                                 stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) );
    948                                         } // if
    949                                         assert( adapter != adapters.end() );
    950 
    951                                         // add the appropriate adapter as a parameter
    952                                         appExpr->get_args().push_front( new VariableExpr( adapter->second ) );
     924                                if ( !adaptersDone.insert( mangleName ).second ) continue;
     925
     926                                // Apply substitution to type variables to figure out what the adapter's type should look like.
     927                                assert( env );
     928                                FunctionType *realType = funType->clone();
     929                                env->apply( realType );
     930                                mangleName = SymTab::Mangler::mangle( realType );
     931                                mangleName += makePolyMonoSuffix( funType, exprTyVars );
     932
     933                                typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
     934                                AdapterIter adapter = adapters.find( mangleName );
     935                                if ( adapter == adapters.end() ) {
     936                                        // Adapter has not been created yet in the current scope, so define it.
     937                                        FunctionDecl *newAdapter = makeAdapter( funType, realType, mangleName, exprTyVars );
     938                                        std::pair< AdapterIter, bool > answer = adapters.insert( mangleName, newAdapter );
     939                                        adapter = answer.first;
     940                                        stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) );
    953941                                } // if
     942                                assert( adapter != adapters.end() );
     943
     944                                // Add the appropriate adapter as a parameter.
     945                                appExpr->args.push_front( new VariableExpr( adapter->second ) );
    954946                        } // for
    955947                } // passAdapters
     
    974966                }
    975967
    976                 Expression *Pass1::handleIntrinsics( ApplicationExpr *appExpr ) {
     968                Expression *CallAdapter::handleIntrinsics( ApplicationExpr *appExpr ) {
    977969                        if ( VariableExpr *varExpr = dynamic_cast< VariableExpr *>( appExpr->function ) ) {
    978970                                if ( varExpr->var->linkage == LinkageSpec::Intrinsic ) {
     
    10971089                }
    10981090
    1099                 Expression *Pass1::postmutate( ApplicationExpr *appExpr ) {
     1091                Expression *CallAdapter::postmutate( ApplicationExpr *appExpr ) {
    11001092                        // std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl;
    11011093                        // for ( auto tyVar : scopeTyVars ) {
     
    11691161                }
    11701162
    1171                 Expression * Pass1::postmutate( UntypedExpr *expr ) {
     1163                Expression * CallAdapter::postmutate( UntypedExpr *expr ) {
    11721164                        if ( isPolyDeref( expr, scopeTyVars, env ) ) {
    11731165                                Expression *ret = expr->args.front();
     
    11791171                }
    11801172
    1181                 void Pass1::premutate( AddressExpr * ) { visit_children = false; }
    1182 
    1183                 Expression * Pass1::postmutate( AddressExpr * addrExpr ) {
     1173                void CallAdapter::premutate( AddressExpr * ) { visit_children = false; }
     1174
     1175                Expression * CallAdapter::postmutate( AddressExpr * addrExpr ) {
    11841176                        assert( addrExpr->arg->result && ! addrExpr->arg->result->isVoid() );
    11851177
     
    12121204                }
    12131205
    1214                 void Pass1::premutate( ReturnStmt *returnStmt ) {
     1206                void CallAdapter::premutate( ReturnStmt *returnStmt ) {
    12151207                        if ( retval && returnStmt->expr ) {
    12161208                                assert( returnStmt->expr->result && ! returnStmt->expr->result->isVoid() );
     
    12201212                }
    12211213
    1222                 void Pass1::premutate( PointerType *pointerType ) {
     1214                void CallAdapter::premutate( PointerType *pointerType ) {
    12231215                        GuardScope( scopeTyVars );
    12241216                        makeTyVarMap( pointerType, scopeTyVars );
    12251217                }
    12261218
    1227                 void Pass1::premutate( FunctionType *functionType ) {
     1219                void CallAdapter::premutate( FunctionType *functionType ) {
    12281220                        GuardScope( scopeTyVars );
    12291221                        makeTyVarMap( functionType, scopeTyVars );
    12301222                }
    12311223
    1232                 void Pass1::beginScope() {
     1224                void CallAdapter::beginScope() {
    12331225                        adapters.beginScope();
    12341226                }
    12351227
    1236                 void Pass1::endScope() {
     1228                void CallAdapter::endScope() {
    12371229                        adapters.endScope();
    12381230                }
    12391231
    1240 ////////////////////////////////////////// Pass2 ////////////////////////////////////////////////////
    1241 
    1242                 void Pass2::addAdapters( FunctionType *functionType ) {
     1232////////////////////////////////////////// DeclAdapter //////////////////////////////////////////
     1233
     1234                void DeclAdapter::addAdapters( FunctionType *functionType ) {
    12431235                        std::list< FunctionType const *> functions;
    12441236                        for ( DeclarationWithType * const arg : functionType->parameters ) {
     
    12601252                }
    12611253
    1262                 DeclarationWithType * Pass2::postmutate( FunctionDecl *functionDecl ) {
     1254                DeclarationWithType * DeclAdapter::postmutate( FunctionDecl *functionDecl ) {
    12631255                        FunctionType * ftype = functionDecl->type;
    12641256                        if ( ! ftype->returnVals.empty() && functionDecl->statements ) {
     
    12851277                }
    12861278
    1287                 void Pass2::premutate( StructDecl * ) {
     1279                void DeclAdapter::premutate( StructDecl * ) {
    12881280                        // prevent tyVars from leaking into containing scope
    12891281                        GuardScope( scopeTyVars );
    12901282                }
    12911283
    1292                 void Pass2::premutate( UnionDecl * ) {
     1284                void DeclAdapter::premutate( UnionDecl * ) {
    12931285                        // prevent tyVars from leaking into containing scope
    12941286                        GuardScope( scopeTyVars );
    12951287                }
    12961288
    1297                 void Pass2::premutate( TraitDecl * ) {
     1289                void DeclAdapter::premutate( TraitDecl * ) {
    12981290                        // prevent tyVars from leaking into containing scope
    12991291                        GuardScope( scopeTyVars );
    13001292                }
    13011293
    1302                 void Pass2::premutate( TypeDecl *typeDecl ) {
     1294                void DeclAdapter::premutate( TypeDecl *typeDecl ) {
    13031295                        addToTyVarMap( typeDecl, scopeTyVars );
    13041296                }
    13051297
    1306                 void Pass2::premutate( PointerType *pointerType ) {
     1298                void DeclAdapter::premutate( PointerType *pointerType ) {
    13071299                        GuardScope( scopeTyVars );
    13081300                        makeTyVarMap( pointerType, scopeTyVars );
    13091301                }
    13101302
    1311                 void Pass2::premutate( FunctionType *funcType ) {
     1303                void DeclAdapter::premutate( FunctionType *funcType ) {
    13121304                        GuardScope( scopeTyVars );
    13131305                        makeTyVarMap( funcType, scopeTyVars );
     
    13931385                }
    13941386
    1395 ////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////////////////////////
     1387////////////////////////////////////////// PolyGenericCalculator ////////////////////////////////
    13961388
    13971389                PolyGenericCalculator::PolyGenericCalculator()
     
    14741466                        // make sure that any type information passed into the function is accounted for
    14751467                        for ( DeclarationWithType * const fnParam : funcType->get_parameters() ) {
    1476                                 // condition here duplicates that in Pass2::mutate( FunctionType* )
     1468                                // condition here duplicates that in DeclAdapter::mutate( FunctionType* )
    14771469                                Type *polyType = isPolyType( fnParam->get_type(), scopeTyVars );
    14781470                                if ( polyType && ! dynamic_cast< TypeInstType* >( polyType ) ) {
     
    15011493                                        if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
    15021494                                                // do not try to monomorphize generic parameters
    1503                                                 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() && ! genericParams.count( typeInst->name ) ) {
     1495                                                if ( scopeTyVars.contains( typeInst->get_name() ) && ! genericParams.count( typeInst->name ) ) {
    15041496                                                        // polymorphic aggregate members should be converted into monomorphic members.
    15051497                                                        // Using char[size_T] here respects the expected sizing rules of an aggregate type.
     
    17101702
    17111703                        if ( auto typeInst = dynamic_cast< TypeInstType const * >( ty ) ) {
    1712                                 if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() ) {
     1704                                if ( scopeTyVars.contains( typeInst->get_name() ) ) {
    17131705                                        // NOTE assumes here that getting put in the scopeTyVars included having the layout variables set
    17141706                                        return true;
     
    17181710                                // check if this type already has a layout generated for it
    17191711                                std::string typeName = mangleType( ty );
    1720                                 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     1712                                if ( knownLayouts.contains( typeName ) ) return true;
    17211713
    17221714                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     
    17551747                                // check if this type already has a layout generated for it
    17561748                                std::string typeName = mangleType( ty );
    1757                                 if ( knownLayouts.find( typeName ) != knownLayouts.end() ) return true;
     1749                                if ( knownLayouts.contains( typeName ) ) return true;
    17581750
    17591751                                // check if any of the type parameters have dynamic layout; if none do, this type is (or will be) monomorphized
     
    18461838                        } else {
    18471839                                std::string offsetName = offsetofName( mangleType( ty ) );
    1848                                 if ( knownOffsets.find( offsetName ) != knownOffsets.end() ) {
     1840                                if ( knownOffsets.contains( offsetName ) ) {
    18491841                                        // use the already-generated offsets for this type
    18501842                                        ret = new NameExpr( offsetName );
     
    18841876                }
    18851877
    1886 ////////////////////////////////////////// Pass3 ////////////////////////////////////////////////////
    1887 
    1888                 template< typename DeclClass >
    1889                 void Pass3::handleDecl( DeclClass * decl, Type * type ) {
    1890                         GuardScope( scopeTyVars );
    1891                         makeTyVarMap( type, scopeTyVars );
    1892                         ScrubTyVars::scrubAll( decl );
    1893                 }
    1894 
    1895                 void Pass3::premutate( ObjectDecl * objectDecl ) {
    1896                         handleDecl( objectDecl, objectDecl->type );
    1897                 }
    1898 
    1899                 void Pass3::premutate( FunctionDecl * functionDecl ) {
    1900                         handleDecl( functionDecl, functionDecl->type );
    1901                 }
    1902 
    1903                 void Pass3::premutate( TypedefDecl * typedefDecl ) {
    1904                         handleDecl( typedefDecl, typedefDecl->base );
     1878////////////////////////////////////////// Eraser ///////////////////////////////////////////////
     1879
     1880                void Eraser::premutate( ObjectDecl * objectDecl ) {
     1881                        ScrubTyVars::scrubAll( objectDecl );
     1882                }
     1883
     1884                void Eraser::premutate( FunctionDecl * functionDecl ) {
     1885                        ScrubTyVars::scrubAll( functionDecl );
     1886                }
     1887
     1888                void Eraser::premutate( TypedefDecl * typedefDecl ) {
     1889                        ScrubTyVars::scrubAll( typedefDecl );
    19051890                }
    19061891
    19071892                /// Strips the members from a generic aggregate
    1908                 void stripGenericMembers(AggregateDecl * decl) {
     1893                static void stripGenericMembers( AggregateDecl * decl ) {
    19091894                        if ( ! decl->parameters.empty() ) decl->members.clear();
    19101895                }
    19111896
    1912                 void Pass3::premutate( StructDecl * structDecl ) {
     1897                void Eraser::premutate( StructDecl * structDecl ) {
    19131898                        stripGenericMembers( structDecl );
    19141899                }
    19151900
    1916                 void Pass3::premutate( UnionDecl * unionDecl ) {
     1901                void Eraser::premutate( UnionDecl * unionDecl ) {
    19171902                        stripGenericMembers( unionDecl );
    1918                 }
    1919 
    1920                 void Pass3::premutate( TypeDecl * typeDecl ) {
    1921                         addToTyVarMap( typeDecl, scopeTyVars );
    1922                 }
    1923 
    1924                 void Pass3::premutate( PointerType * pointerType ) {
    1925                         GuardScope( scopeTyVars );
    1926                         makeTyVarMap( pointerType, scopeTyVars );
    1927                 }
    1928 
    1929                 void Pass3::premutate( FunctionType * functionType ) {
    1930                         GuardScope( scopeTyVars );
    1931                         makeTyVarMap( functionType, scopeTyVars );
    19321903                }
    19331904        } // anonymous namespace
     
    19391910// compile-command: "make install" //
    19401911// End: //
    1941 
  • src/GenPoly/ErasableScopedMap.h

    r34b4268 r24d6572  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ScopedMap.h --
     7// ErasableScopedMap.h --
    88//
    99// Author           : Aaron B. Moss
     
    5151        typedef typename Scope::const_pointer const_pointer;
    5252
    53         // Both iterator types are complete bidirection iterators, defined below.
     53        // Both iterator types are complete bidirectional iterators, see below.
    5454        class iterator;
    5555        class const_iterator;
     
    118118        std::pair< iterator, bool > insert( const Key &key, const Value &value ) { return insert( std::make_pair( key, value ) ); }
    119119
     120        Value& operator[] ( const Key &key ) {
     121                iterator slot = find( key );
     122                if ( slot != end() ) return slot->second;
     123                return insert( key, Value() ).first->second;
     124        }
     125
    120126        /// Marks the given element as erased from this scope inward; returns 1 for erased an element, 0 otherwise
    121127        size_type erase( const Key &key ) {
     
    130136        }
    131137
    132         Value& operator[] ( const Key &key ) {
    133                 iterator slot = find( key );
    134                 if ( slot != end() ) return slot->second;
    135                 return insert( key, Value() ).first->second;
     138        bool contains( const Key & key ) const {
     139                return find( key ) != cend();
    136140        }
    137141};
  • src/GenPoly/FindFunction.cc

    r34b4268 r24d6572  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Rob Schluntz
    12 // Last Modified On : Fri Feb 05 12:22:20 2016
    13 // Update Count     : 6
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Oct  7 17:05:20 2022
     13// Update Count     : 7
    1414//
    1515
     
    1818#include <utility>                      // for pair
    1919
     20#include "AST/Pass.hpp"                 // for Pass
     21#include "AST/Type.hpp"
    2022#include "Common/PassVisitor.h"         // for PassVisitor
    2123#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::iterator
     
    8991                handleForall( pointerType->get_forall() );
    9092        }
     93
     94namespace {
     95
     96struct FindFunctionCore :
     97                public ast::WithGuards,
     98                public ast::WithShortCircuiting,
     99                public ast::WithVisitorRef<FindFunctionCore> {
     100        FindFunctionCore(
     101                std::vector<ast::ptr<ast::FunctionType>> & functions,
     102                const TypeVarMap & typeVars, FindFunctionPred predicate,
     103                bool replaceMode );
     104
     105        void previsit( ast::FunctionType const * type );
     106        ast::Type const * postvisit( ast::FunctionType const * type );
     107        void previsit( ast::PointerType const * type );
     108private:
     109        void handleForall( const ast::FunctionType::ForallList & forall );
     110
     111        std::vector<ast::ptr<ast::FunctionType>> &functions;
     112        TypeVarMap typeVars;
     113        FindFunctionPred predicate;
     114        bool replaceMode;
     115};
     116
     117FindFunctionCore::FindFunctionCore(
     118                std::vector<ast::ptr<ast::FunctionType>> & functions,
     119                const TypeVarMap &typeVars, FindFunctionPred predicate,
     120                bool replaceMode ) :
     121        functions( functions ), typeVars( typeVars ),
     122        predicate( predicate ), replaceMode( replaceMode ) {}
     123
     124void FindFunctionCore::handleForall( const ast::FunctionType::ForallList & forall ) {
     125        for ( const ast::ptr<ast::TypeInstType> & td : forall ) {
     126                TypeVarMap::iterator var = typeVars.find( *td );
     127                if ( var != typeVars.end() ) {
     128                        typeVars.erase( var->first );
     129                } // if
     130        } // for
     131}
     132
     133void FindFunctionCore::previsit( ast::FunctionType const * type ) {
     134        visit_children = false;
     135        GuardScope( typeVars );
     136        handleForall( type->forall );
     137        //ast::accept_all( type->returns, *visitor );
     138        // This might have to become ast::mutate_each with return.
     139        ast::accept_each( type->returns, *visitor );
     140}
     141
     142ast::Type const * FindFunctionCore::postvisit( ast::FunctionType const * type ) {
     143        ast::Type const * ret = type;
     144        if ( predicate( type, typeVars ) ) {
     145                functions.push_back( type );
     146                if ( replaceMode ) {
     147                        // replace type parameters in function type with void*
     148                        ret = scrubTypeVars( ast::deepCopy( type ), typeVars );
     149                } // if
     150        } // if
     151        return ret;
     152}
     153
     154void FindFunctionCore::previsit( ast::PointerType const * /*type*/ ) {
     155        GuardScope( typeVars );
     156        //handleForall( type->forall );
     157}
     158
     159} // namespace
     160
     161void findFunction( const ast::Type * type,
     162                std::vector<ast::ptr<ast::FunctionType>> & functions,
     163                const TypeVarMap & typeVars, FindFunctionPred predicate ) {
     164        ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, false );
     165        type->accept( pass );
     166        //(void)type;
     167        //(void)functions;
     168        //(void)typeVars;
     169        //(void)predicate;
     170}
     171
     172const ast::Type * findAndReplaceFunction( const ast::Type * type,
     173                std::vector<ast::ptr<ast::FunctionType>> & functions,
     174                const TypeVarMap & typeVars, FindFunctionPred predicate ) {
     175        ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, true );
     176        return type->accept( pass );
     177        //(void)functions;
     178        //(void)typeVars;
     179        //(void)predicate;
     180        //return type;
     181}
     182
    91183} // namespace GenPoly
    92184
  • src/GenPoly/FindFunction.h

    r34b4268 r24d6572  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:23:36 2017
    13 // Update Count     : 2
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Oct  7 10:30:00 2022
     13// Update Count     : 3
    1414//
    1515
     
    3030        /// like `findFunction`, but also replaces the function type with void ()(void)
    3131        void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
     32
     33typedef bool (*FindFunctionPred)( const ast::FunctionType *, const TypeVarMap & );
     34
     35/// Recursively walks `type`, placing all functions that match `predicate`
     36/// under `typeVars` into `functions`.
     37void findFunction( const ast::Type * type,
     38                std::vector<ast::ptr<ast::FunctionType>> & functions,
     39                const TypeVarMap & typeVars, FindFunctionPred predicate );
     40/// Like findFunction, but also replaces the function type with `void ()(void)`.
     41const ast::Type * findAndReplaceFunction( const ast::Type * type,
     42                std::vector<ast::ptr<ast::FunctionType>> & functions,
     43                const TypeVarMap & typeVars, FindFunctionPred predicate );
     44
    3245} // namespace GenPoly
    3346
  • src/GenPoly/GenPoly.cc

    r34b4268 r24d6572  
    2424#include <vector>                       // for vector
    2525
     26#include "AST/Expr.hpp"
    2627#include "AST/Type.hpp"
     28#include "AST/TypeSubstitution.hpp"
    2729#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    2830#include "ResolvExpr/typeops.h"         // for flatten
     
    170172
    171173                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
    172                         if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) {
     174                        if ( tyVars.contains( typeInst->get_name() ) ) {
    173175                                return type;
    174176                        }
     
    187189
    188190                if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    189                         return tyVars.find(typeInst->typeString()) != tyVars.end() ? type : nullptr;
     191                        if ( tyVars.contains( typeInst->typeString() ) ) return type;
    190192                } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
    191193                        return isPolyType( arrayType->base, env );
     
    203205
    204206        if ( auto inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
    205                 if ( typeVars.find( *inst ) != typeVars.end() ) return type;
     207                if ( typeVars.contains( *inst ) ) return type;
    206208        } else if ( auto array = dynamic_cast< const ast::ArrayType * >( type ) ) {
    207209                return isPolyType( array->base, subst );
     
    272274                return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
    273275        }
     276
     277const ast::BaseInstType *isDynRet( const ast::FunctionType * func ) {
     278        if ( func->returns.empty() ) return nullptr;
     279
     280        TypeVarMap forallTypes = { ast::TypeData() };
     281        makeTypeVarMap( func, forallTypes );
     282        return isDynType( func->returns.front(), forallTypes );
     283}
    274284
    275285        bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) {
     
    317327                return 0;
    318328        }
     329
     330const ast::Type * isPolyPtr(
     331                const ast::Type * type, const TypeVarMap & typeVars,
     332                const ast::TypeSubstitution * typeSubs ) {
     333        type = replaceTypeInst( type, typeSubs );
     334
     335        if ( auto * ptr = dynamic_cast<ast::PointerType const *>( type ) ) {
     336                return isPolyType( ptr->base, typeVars, typeSubs );
     337        }
     338        return nullptr;
     339}
    319340
    320341        Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) {
     
    391412
    392413                if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) {
    393                         if ( tyVars.find( typeInstType->get_name() ) != tyVars.end() ) {
     414                        if ( tyVars.contains( typeInstType->get_name() ) ) {
    394415                                return true;
    395416                        }
     
    490511                }
    491512
     513                /// Flattens a list of types.
     514                // There is another flattenList in Unify.
    492515                void flattenList( vector<ast::ptr<ast::Type>> const & src,
    493516                                vector<ast::ptr<ast::Type>> & out ) {
     
    792815        }
    793816
     817void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) {
     818        typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) );
     819}
     820
    794821void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ) {
    795         typeVars.insert( *type, ast::TypeData( type->base ) );
     822        typeVars.insert( ast::TypeEnvKey( *type ), ast::TypeData( type->base ) );
    796823}
    797824
     
    818845}
    819846
     847void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ) {
     848        for ( auto & typeDecl : decl->type_params ) {
     849                addToTypeVarMap( typeDecl, typeVars );
     850        }
     851}
     852
    820853        void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {
    821854                for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {
  • src/GenPoly/GenPoly.h

    r34b4268 r24d6572  
    111111        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap );
    112112        void addToTypeVarMap( const ast::TypeDecl * type, TypeVarMap & typeVars );
     113        void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars );
    113114
    114115        /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap`
    115116        void makeTyVarMap( Type *type, TyVarMap &tyVarMap );
    116117        void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars );
     118        void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars );
    117119
    118120        /// Prints type variable map
  • src/GenPoly/InstantiateGeneric.cc

    r34b4268 r24d6572  
    2828#include "GenPoly.h"                   // for isPolyType, typesPolyCompatible
    2929#include "InitTweak/InitTweak.h"
    30 #include "ResolvExpr/typeops.h"
     30#include "ResolvExpr/AdjustExprType.hpp"  // for adjustExprType
     31#include "ResolvExpr/Unify.h"          // for typesCompatible
    3132#include "ScopedSet.h"                 // for ScopedSet, ScopedSet<>::iterator
    3233#include "ScrubTyVars.h"               // for ScrubTyVars
  • src/GenPoly/InstantiateGenericNew.cpp

    r34b4268 r24d6572  
    3232#include "GenPoly/GenPoly.h"           // for isPolyType, typesPolyCompatible
    3333#include "GenPoly/ScrubTyVars.h"       // for scrubAll
    34 #include "ResolvExpr/typeops.h"        // for typesCompatible
     34#include "ResolvExpr/AdjustExprType.hpp"  // for adjustExprType
     35#include "ResolvExpr/Unify.h"          // for typesCompatible
    3536
    3637namespace GenPoly {
     
    361362                        ResolvExpr::typesCompatible(
    362363                                memberExpr->result,
    363                                 memberExpr->member->get_type(), ast::SymbolTable() ) ) {
     364                                memberExpr->member->get_type() ) ) {
    364365                return memberExpr;
    365366        }
  • src/GenPoly/Lvalue.cc

    r34b4268 r24d6572  
    1717#include <string>                        // for string
    1818
     19#include "Common/ToString.hpp"           // for toCString
    1920#include "Common/UniqueName.h"
    2021#include "Common/PassVisitor.h"
  • src/GenPoly/LvalueNew.cpp

    r34b4268 r24d6572  
    2525#include "AST/Pass.hpp"
    2626#include "Common/SemanticError.h"      // for SemanticWarning
     27#include "Common/ToString.hpp"         // for toCString
    2728#include "Common/UniqueName.h"         // for UniqueName
    2829#include "GenPoly/GenPoly.h"           // for genFunctionType
     
    358359                                !ResolvExpr::typesCompatible(
    359360                                        srcType,
    360                                         strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base,
    361                                         ast::SymbolTable() ) ) {
     361                                        strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base ) ) {
    362362                        // Must keep cast if cast-to type is different from the actual type.
    363363                        return ast::mutate_field( expr, &ast::CastExpr::arg, ret );
     
    376376                if ( !ResolvExpr::typesCompatibleIgnoreQualifiers(
    377377                                dstType->stripReferences(),
    378                                 srcType->stripReferences(),
    379                                 ast::SymbolTable() ) ) {
     378                                srcType->stripReferences() ) ) {
    380379                        return ast::mutate_field( expr, &ast::CastExpr::arg, ret );
    381380                }
     
    392391                                ResolvExpr::typesCompatible(
    393392                                        expr->result,
    394                                         expr->arg->result, ast::SymbolTable() ) ) {
     393                                        expr->arg->result ) ) {
    395394                        PRINT(
    396395                                std::cerr << "types are compatible, removing cast: " << expr << '\n';
     
    589588                ast::OpenVarSet openVars;
    590589                ResolvExpr::unify( ret->arg2->result, ret->arg3->result, newEnv,
    591                         needAssertions, haveAssertions, openVars,
    592                         ast::SymbolTable(), common );
     590                        needAssertions, haveAssertions, openVars, common );
    593591                ret->result = common ? common : ast::deepCopy( ret->arg2->result );
    594592                return ret;
  • src/GenPoly/ScopedSet.h

    r34b4268 r24d6572  
    2121
    2222namespace GenPoly {
    23         /// A set where the items are placed into nested scopes;
    24         /// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
    25         template<typename Value>
    26         class ScopedSet {
    27                 typedef std::set< Value > Scope;
    28                 typedef std::vector< Scope > ScopeList;
    29 
    30                 ScopeList scopes; ///< scoped list of sets
    31         public:
    32                 typedef typename Scope::key_type key_type;
    33                 typedef typename Scope::value_type value_type;
    34                 typedef typename ScopeList::size_type size_type;
    35                 typedef typename ScopeList::difference_type difference_type;
    36                 typedef typename Scope::reference reference;
    37                 typedef typename Scope::const_reference const_reference;
    38                 typedef typename Scope::pointer pointer;
    39                 typedef typename Scope::const_pointer const_pointer;
    40 
    41                 class iterator : public std::iterator< std::bidirectional_iterator_tag,
    42                                                        value_type > {
    43                 friend class ScopedSet;
    44                 friend class const_iterator;
    45                         typedef typename std::set< Value >::iterator wrapped_iterator;
    46                         typedef typename std::vector< std::set< Value > > scope_list;
    47                         typedef typename scope_list::size_type size_type;
    48 
    49                         /// Checks if this iterator points to a valid item
    50                         bool is_valid() const {
    51                                 return it != (*scopes)[i].end();
    52                         }
    53 
    54                         /// Increments on invalid
    55                         iterator& next_valid() {
    56                                 if ( ! is_valid() ) { ++(*this); }
    57                                 return *this;
    58                         }
    59 
    60                         /// Decrements on invalid
    61                         iterator& prev_valid() {
    62                                 if ( ! is_valid() ) { --(*this); }
    63                                 return *this;
    64                         }
    65 
    66                         iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
    67                                 : scopes(&_scopes), it(_it), i(_i) {}
    68                 public:
    69                         iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    70                         iterator& operator= (const iterator &that) {
    71                                 scopes = that.scopes; i = that.i; it = that.it;
    72                                 return *this;
    73                         }
    74 
    75                         reference operator* () { return *it; }
    76                         pointer operator-> () { return it.operator->(); }
    77 
    78                         iterator& operator++ () {
    79                                 if ( it == (*scopes)[i].end() ) {
    80                                         if ( i == 0 ) return *this;
    81                                         --i;
    82                                         it = (*scopes)[i].begin();
    83                                 } else {
    84                                         ++it;
    85                                 }
    86                                 return next_valid();
    87                         }
    88                         iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
    89 
    90                         iterator& operator-- () {
    91                                 // may fail if this is the begin iterator; allowed by STL spec
    92                                 if ( it == (*scopes)[i].begin() ) {
    93                                         ++i;
    94                                         it = (*scopes)[i].end();
    95                                 }
    96                                 --it;
    97                                 return prev_valid();
    98                         }
    99                         iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
    100 
    101                         bool operator== (const iterator &that) {
    102                                 return scopes == that.scopes && i == that.i && it == that.it;
    103                         }
    104                         bool operator!= (const iterator &that) { return !( *this == that ); }
    105 
    106                         size_type get_level() const { return i; }
    107 
    108                 private:
    109                         scope_list const *scopes;
    110                         wrapped_iterator it;
    111                         size_type i;
    112                 };
    113 
    114                 class const_iterator : public std::iterator< std::bidirectional_iterator_tag,
    115                                                              value_type > {
    116                 friend class ScopedSet;
    117                         typedef typename std::set< Value >::iterator wrapped_iterator;
    118                         typedef typename std::set< Value >::const_iterator wrapped_const_iterator;
    119                         typedef typename std::vector< std::set< Value > > scope_list;
    120                         typedef typename scope_list::size_type size_type;
    121 
    122                         /// Checks if this iterator points to a valid item
    123                         bool is_valid() const {
    124                                 return it != (*scopes)[i].end();
    125                         }
    126 
    127                         /// Increments on invalid
    128                         const_iterator& next_valid() {
    129                                 if ( ! is_valid() ) { ++(*this); }
    130                                 return *this;
    131                         }
    132 
    133                         /// Decrements on invalid
    134                         const_iterator& prev_valid() {
    135                                 if ( ! is_valid() ) { --(*this); }
    136                                 return *this;
    137                         }
    138 
    139                         const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
    140                                 : scopes(&_scopes), it(_it), i(_i) {}
    141                 public:
    142                         const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    143                         const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
    144                         const_iterator& operator= (const iterator &that) {
    145                                 scopes = that.scopes; i = that.i; it = that.it;
    146                                 return *this;
    147                         }
    148                         const_iterator& operator= (const const_iterator &that) {
    149                                 scopes = that.scopes; i = that.i; it = that.it;
    150                                 return *this;
    151                         }
    152 
    153                         const_reference operator* () { return *it; }
    154                         const_pointer operator-> () { return it.operator->(); }
    155 
    156                         const_iterator& operator++ () {
    157                                 if ( it == (*scopes)[i].end() ) {
    158                                         if ( i == 0 ) return *this;
    159                                         --i;
    160                                         it = (*scopes)[i].begin();
    161                                 } else {
    162                                         ++it;
    163                                 }
    164                                 return next_valid();
    165                         }
    166                         const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
    167 
    168                         const_iterator& operator-- () {
    169                                 // may fail if this is the begin iterator; allowed by STL spec
    170                                 if ( it == (*scopes)[i].begin() ) {
    171                                         ++i;
    172                                         it = (*scopes)[i].end();
    173                                 }
    174                                 --it;
    175                                 return prev_valid();
    176                         }
    177                         const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
    178 
    179                         bool operator== (const const_iterator &that) {
    180                                 return scopes == that.scopes && i == that.i && it == that.it;
    181                         }
    182                         bool operator!= (const const_iterator &that) { return !( *this == that ); }
    183 
    184                         size_type get_level() const { return i; }
    185 
    186                 private:
    187                         scope_list const *scopes;
    188                         wrapped_const_iterator it;
    189                         size_type i;
    190                 };
    191 
    192                 /// Starts a new scope
    193                 void beginScope() {
    194                         Scope scope;
    195                         scopes.push_back(scope);
    196                 }
    197 
    198                 /// Ends a scope; invalidates any iterators pointing to elements of that scope
    199                 void endScope() {
    200                         scopes.pop_back();
    201                 }
    202 
    203                 /// Default constructor initializes with one scope
    204                 ScopedSet() { beginScope(); }
    205 
    206                 iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    207                 const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    208                 const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
    209                 iterator end() { return iterator(scopes, scopes[0].end(), 0); }
    210                 const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
    211                 const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
    212 
    213                 /// Gets the index of the current scope (counted from 1)
    214                 size_type currentScope() const { return scopes.size(); }
    215 
    216                 /// Finds the given key in the outermost scope it occurs; returns end() for none such
    217                 iterator find( const Value &key ) {
    218                         for ( size_type i = scopes.size() - 1; ; --i ) {
    219                                 typename Scope::iterator val = scopes[i].find( key );
    220                                 if ( val != scopes[i].end() ) return iterator( scopes, val, i );
    221                                 if ( i == 0 ) break;
    222                         }
    223                         return end();
    224                 }
    225                 const_iterator find( const Value &key ) const {
    226                         return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
    227                 }
    228 
    229                 /// Finds the given key in the outermost scope inside the given scope where it occurs
    230                 iterator findNext( const_iterator &it, const Value &key ) {
    231                         if ( it.i == 0 ) return end();
     23
     24/// A set where the items are placed into nested scopes;
     25/// inserted items are placed into the innermost scope, lookup looks from the innermost scope outward
     26template<typename Value>
     27class ScopedSet {
     28        typedef std::set< Value > Scope;
     29        typedef std::vector< Scope > ScopeList;
     30
     31        /// Scoped list of sets.
     32        ScopeList scopes;
     33public:
     34        typedef typename Scope::key_type key_type;
     35        typedef typename Scope::value_type value_type;
     36        typedef typename ScopeList::size_type size_type;
     37        typedef typename ScopeList::difference_type difference_type;
     38        typedef typename Scope::reference reference;
     39        typedef typename Scope::const_reference const_reference;
     40        typedef typename Scope::pointer pointer;
     41        typedef typename Scope::const_pointer const_pointer;
     42
     43        // Both iterator types are complete bidirectional iterators, see below.
     44        class iterator;
     45        class const_iterator;
     46
     47        /// Starts a new scope
     48        void beginScope() {
     49                Scope scope;
     50                scopes.push_back(scope);
     51        }
     52
     53        /// Ends a scope; invalidates any iterators pointing to elements of that scope
     54        void endScope() {
     55                scopes.pop_back();
     56        }
     57
     58        /// Default constructor initializes with one scope
     59        ScopedSet() { beginScope(); }
     60
     61        iterator begin() { return iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     62        const_iterator begin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     63        const_iterator cbegin() const { return const_iterator(scopes, scopes.back().begin(), scopes.size()-1).next_valid(); }
     64        iterator end() { return iterator(scopes, scopes[0].end(), 0); }
     65        const_iterator end() const { return const_iterator(scopes, scopes[0].end(), 0); }
     66        const_iterator cend() const { return const_iterator(scopes, scopes[0].end(), 0); }
     67
     68        /// Gets the index of the current scope (counted from 1)
     69        size_type currentScope() const { return scopes.size(); }
     70
     71        /// Finds the given key in the outermost scope it occurs; returns end() for none such
     72        iterator find( const Value &key ) {
     73                for ( size_type i = scopes.size() - 1; ; --i ) {
     74                        typename Scope::iterator val = scopes[i].find( key );
     75                        if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     76                        if ( i == 0 ) break;
     77                }
     78                return end();
     79        }
     80        const_iterator find( const Value &key ) const {
     81                return const_iterator( const_cast< ScopedSet< Value >* >(this)->find( key ) );
     82        }
     83
     84        /// Finds the given key in the outermost scope inside the given scope where it occurs
     85        iterator findNext( const_iterator &it, const Value &key ) {
     86                if ( it.i == 0 ) return end();
    23287                        for ( size_type i = it.i - 1; ; --i ) {
    233                                 typename Scope::iterator val = scopes[i].find( key );
    234                                 if ( val != scopes[i].end() ) return iterator( scopes, val, i );
    235                                 if ( i == 0 ) break;
    236                         }
    237                         return end();
    238                 }
    239                 const_iterator findNext( const_iterator &it, const Value &key ) const {
    240                         return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) );
    241                 }
    242 
    243                 /// Inserts the given value into the outermost scope
    244                 std::pair< iterator, bool > insert( const value_type &value ) {
    245                         std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
    246                         return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
    247                 }
    248 
    249         };
     88                        typename Scope::iterator val = scopes[i].find( key );
     89                        if ( val != scopes[i].end() ) return iterator( scopes, val, i );
     90                        if ( i == 0 ) break;
     91                }
     92                return end();
     93        }
     94        const_iterator findNext( const_iterator &it, const Value &key ) const {
     95                return const_iterator( const_cast< ScopedSet< Value >* >(this)->findNext( it, key ) );
     96        }
     97
     98        /// Inserts the given value into the outermost scope
     99        std::pair< iterator, bool > insert( const value_type &value ) {
     100                std::pair< typename Scope::iterator, bool > res = scopes.back().insert( value );
     101                return std::make_pair( iterator(scopes, res.first, scopes.size()-1), res.second );
     102        }
     103
     104        bool contains( const Value & key ) const {
     105                return find( key ) != cend();
     106        }
     107};
     108
     109template<typename Value>
     110class ScopedSet<Value>::iterator :
     111                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     112        friend class ScopedSet;
     113        friend class const_iterator;
     114        typedef typename std::set< Value >::iterator wrapped_iterator;
     115        typedef typename std::vector< std::set< Value > > scope_list;
     116        typedef typename scope_list::size_type size_type;
     117
     118        /// Checks if this iterator points to a valid item
     119        bool is_valid() const {
     120                return it != (*scopes)[i].end();
     121        }
     122
     123        /// Increments on invalid
     124        iterator& next_valid() {
     125                if ( ! is_valid() ) { ++(*this); }
     126                return *this;
     127        }
     128
     129        /// Decrements on invalid
     130        iterator& prev_valid() {
     131                if ( ! is_valid() ) { --(*this); }
     132                return *this;
     133        }
     134
     135        iterator(scope_list const &_scopes, const wrapped_iterator &_it, size_type _i)
     136                : scopes(&_scopes), it(_it), i(_i) {}
     137public:
     138        iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     139        iterator& operator= (const iterator &that) {
     140                scopes = that.scopes; i = that.i; it = that.it;
     141                return *this;
     142        }
     143
     144        reference operator* () { return *it; }
     145        pointer operator-> () { return it.operator->(); }
     146
     147        iterator& operator++ () {
     148                if ( it == (*scopes)[i].end() ) {
     149                        if ( i == 0 ) return *this;
     150                        --i;
     151                        it = (*scopes)[i].begin();
     152                } else {
     153                        ++it;
     154                }
     155                return next_valid();
     156        }
     157        iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; }
     158
     159        iterator& operator-- () {
     160                // may fail if this is the begin iterator; allowed by STL spec
     161                if ( it == (*scopes)[i].begin() ) {
     162                        ++i;
     163                        it = (*scopes)[i].end();
     164                }
     165                --it;
     166                return prev_valid();
     167        }
     168        iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; }
     169
     170        bool operator== (const iterator &that) {
     171                return scopes == that.scopes && i == that.i && it == that.it;
     172        }
     173        bool operator!= (const iterator &that) { return !( *this == that ); }
     174
     175        size_type get_level() const { return i; }
     176
     177private:
     178        scope_list const *scopes;
     179        wrapped_iterator it;
     180        size_type i;
     181};
     182
     183template<typename Value>
     184class ScopedSet<Value>::const_iterator :
     185                public std::iterator< std::bidirectional_iterator_tag, value_type > {
     186        friend class ScopedSet;
     187        typedef typename std::set< Value >::iterator wrapped_iterator;
     188        typedef typename std::set< Value >::const_iterator wrapped_const_iterator;
     189        typedef typename std::vector< std::set< Value > > scope_list;
     190        typedef typename scope_list::size_type size_type;
     191
     192        /// Checks if this iterator points to a valid item
     193        bool is_valid() const {
     194                return it != (*scopes)[i].end();
     195        }
     196
     197        /// Increments on invalid
     198        const_iterator& next_valid() {
     199                if ( ! is_valid() ) { ++(*this); }
     200                return *this;
     201        }
     202
     203        /// Decrements on invalid
     204        const_iterator& prev_valid() {
     205                if ( ! is_valid() ) { --(*this); }
     206                return *this;
     207        }
     208
     209        const_iterator(scope_list const &_scopes, const wrapped_const_iterator &_it, size_type _i)
     210                : scopes(&_scopes), it(_it), i(_i) {}
     211public:
     212        const_iterator(const iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     213        const_iterator(const const_iterator &that) : scopes(that.scopes), it(that.it), i(that.i) {}
     214        const_iterator& operator= (const iterator &that) {
     215                scopes = that.scopes; i = that.i; it = that.it;
     216                return *this;
     217        }
     218        const_iterator& operator= (const const_iterator &that) {
     219                scopes = that.scopes; i = that.i; it = that.it;
     220                return *this;
     221        }
     222
     223        const_reference operator* () { return *it; }
     224        const_pointer operator-> () { return it.operator->(); }
     225
     226        const_iterator& operator++ () {
     227                if ( it == (*scopes)[i].end() ) {
     228                        if ( i == 0 ) return *this;
     229                        --i;
     230                        it = (*scopes)[i].begin();
     231                } else {
     232                        ++it;
     233                }
     234                return next_valid();
     235        }
     236        const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; }
     237
     238        const_iterator& operator-- () {
     239                // may fail if this is the begin iterator; allowed by STL spec
     240                if ( it == (*scopes)[i].begin() ) {
     241                        ++i;
     242                        it = (*scopes)[i].end();
     243                }
     244                --it;
     245                return prev_valid();
     246        }
     247        const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; }
     248
     249        bool operator== (const const_iterator &that) {
     250                return scopes == that.scopes && i == that.i && it == that.it;
     251        }
     252        bool operator!= (const const_iterator &that) { return !( *this == that ); }
     253
     254        size_type get_level() const { return i; }
     255
     256private:
     257        scope_list const *scopes;
     258        wrapped_const_iterator it;
     259        size_type i;
     260};
     261
    250262} // namespace GenPoly
    251263
  • src/GenPoly/ScrubTyVars.cc

    r34b4268 r24d6572  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct  7 15:42:00 2022
    13 // Update Count     : 5
     12// Last Modified On : Wed Dec  7 17:01:00 2022
     13// Update Count     : 6
    1414//
    1515
     
    117117namespace {
    118118
    119 enum class ScrubMode {
    120         FromMap,
    121         DynamicFromMap,
    122         All,
    123 };
    124 
    125119struct ScrubTypeVars :
    126120        public ast::WithGuards,
     
    184178
    185179ast::Type const * ScrubTypeVars::postvisit( ast::TypeInstType const * type ) {
     180        ast::TypeDecl::Kind kind;
    186181        // This implies that mode == ScrubMode::All.
    187182        if ( !typeVars ) {
    188                 if ( ast::TypeDecl::Ftype == type->kind ) {
    189                         return new ast::PointerType(
    190                                 new ast::FunctionType( ast::FixedArgs ) );
    191                 } else {
    192                         return new ast::PointerType(
    193                                 new ast::VoidType( type->qualifiers ) );
    194                 }
    195         }
    196 
    197         auto typeVar = typeVars->find( *type );
    198         if ( typeVar == typeVars->end() ) {
    199                 return type;
    200         }
    201 
    202         switch ( typeVar->second.kind ) {
    203         case ::TypeDecl::Dtype:
    204         case ::TypeDecl::Ttype:
     183                kind = type->kind;
     184        } else {
     185                // Otherwise, only scrub the type var if it is in map.
     186                auto typeVar = typeVars->find( *type );
     187                if ( typeVar == typeVars->end() ) {
     188                        return type;
     189                }
     190                kind = typeVar->second.kind;
     191        }
     192
     193        switch ( kind ) {
     194        case ast::TypeDecl::Dtype:
     195        case ast::TypeDecl::Ttype:
    205196                return new ast::PointerType(
    206197                        new ast::VoidType( type->qualifiers ) );
    207         case ::TypeDecl::Ftype:
     198        case ast::TypeDecl::Ftype:
    208199                return new ast::PointerType(
    209200                        new ast::FunctionType( ast::VariableArgs ) );
    210201        default:
    211                 assertf( false,
    212                         "Unhandled type variable kind: %d", typeVar->second.kind );
     202                assertf( false, "Unhandled type variable kind: %d", kind );
    213203                throw; // Just in case the assert is removed, stop here.
    214204        }
     
    253243}
    254244
     245} // namespace
     246
    255247const ast::Node * scrubTypeVarsBase(
    256                 const ast::Node * target,
    257                 ScrubMode mode, const TypeVarMap * typeVars ) {
     248                const ast::Node * node, const TypeVarMap * typeVars, ScrubMode mode ) {
    258249        if ( ScrubMode::All == mode ) {
    259250                assert( nullptr == typeVars );
     
    262253        }
    263254        ast::Pass<ScrubTypeVars> visitor( mode, typeVars );
    264         return target->accept( visitor );
    265 }
    266 
    267 } // namespace
    268 
    269 template<>
    270 ast::Node const * scrubTypeVars<ast::Node>(
    271         const ast::Node * target, const TypeVarMap & typeVars ) {
    272         return scrubTypeVarsBase( target, ScrubMode::FromMap, &typeVars );
    273 }
    274 
    275 template<>
    276 ast::Node const * scrubTypeVarsDynamic<ast::Node>(
    277         ast::Node const * target, const TypeVarMap & typeVars ) {
    278         return scrubTypeVarsBase( target, ScrubMode::DynamicFromMap, &typeVars );
    279 }
    280 
    281 template<>
    282 ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target ) {
    283         return scrubTypeVarsBase( target, ScrubMode::All, nullptr );
     255        return node->accept( visitor );
    284256}
    285257
  • src/GenPoly/ScrubTyVars.h

    r34b4268 r24d6572  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Oct  7 15:51:00 2022
    13 // Update Count     : 4
     12// Last Modified On : Wed Dec  7 16:57:00 2022
     13// Update Count     : 5
    1414//
    1515
     
    109109        }
    110110
     111// ScrubMode and scrubTypeVarsBase are internal.
     112enum class ScrubMode { FromMap, DynamicFromMap, All };
     113
     114const ast::Node * scrubTypeVarsBase(
     115        const ast::Node * target, const TypeVarMap * typeVars, ScrubMode mode );
     116
     117
    111118/// For all polymorphic types with type variables in `typeVars`,
    112119/// replaces generic types, dtypes, and ftypes with the appropriate void type,
     
    116123                node_t const * target, const TypeVarMap & typeVars ) {
    117124        return strict_dynamic_cast<node_t const *>(
    118                         scrubTypeVars<ast::Node>( target, typeVars ) );
     125                        scrubTypeVarsBase( target, &typeVars, ScrubMode::FromMap ) );
    119126}
    120127
     
    123130/// and sizeof/alignof expressions with the proper variable.
    124131template<typename node_t>
    125 ast::Node const * scrubTypeVarsDynamic(
     132node_t const * scrubTypeVarsDynamic(
    126133                node_t const * target, const TypeVarMap & typeVars ) {
    127134        return strict_dynamic_cast<node_t const *>(
    128                         scrubTypeVarsDynamic<ast::Node>( target, typeVars ) );
     135                        scrubTypeVarsBase( target, &typeVars, ScrubMode::DynamicFromMap ) );
    129136}
    130137
     
    134141node_t const * scrubAllTypeVars( node_t const * target ) {
    135142        return strict_dynamic_cast<node_t const *>(
    136                         scrubAllTypeVars<ast::Node>( target ) );
     143                        scrubTypeVarsBase( target, nullptr, ScrubMode::All ) );
    137144}
    138 
    139 // We specialize for Node as a base case.
    140 template<>
    141 ast::Node const * scrubTypeVars<ast::Node>(
    142                 const ast::Node * target, const TypeVarMap & typeVars );
    143 
    144 template<>
    145 ast::Node const * scrubTypeVarsDynamic<ast::Node>(
    146                 ast::Node const * target, const TypeVarMap & typeVars );
    147 
    148 template<>
    149 ast::Node const * scrubAllTypeVars<ast::Node>( const ast::Node * target );
    150145
    151146} // namespace GenPoly
  • src/GenPoly/SpecializeNew.cpp

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

    r34b4268 r24d6572  
    3232#include "Common/PassVisitor.h"        // for PassVisitor, WithStmtsToAdd
    3333#include "Common/SemanticError.h"      // for SemanticError
     34#include "Common/ToString.hpp"         // for toCString
    3435#include "Common/UniqueName.h"         // for UniqueName
    35 #include "Common/utility.h"            // for CodeLocation, ValueGuard, toSt...
    3636#include "FixGlobalInit.h"             // for fixGlobalInit
    3737#include "GenInit.h"                   // for genCtorDtor
     
    3939#include "InitTweak.h"                 // for getFunctionName, getCallArg
    4040#include "ResolvExpr/Resolver.h"       // for findVoidExpression
    41 #include "ResolvExpr/typeops.h"        // for typesCompatible
     41#include "ResolvExpr/Unify.h"          // for typesCompatible
    4242#include "SymTab/Autogen.h"            // for genImplicitCall
    4343#include "SymTab/Indexer.h"            // for Indexer
     
    12331233                }
    12341234
    1235                 template< typename Visitor, typename... Params >
    1236                 void error( Visitor & v, CodeLocation loc, const Params &... params ) {
    1237                         SemanticErrorException err( loc, toString( params... ) );
    1238                         v.errors.append( err );
    1239                 }
    1240 
    12411235                template< typename... Params >
    12421236                void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) {
    1243                         // toggle warnings vs. errors here.
    1244                         // warn( params... );
    1245                         error( *this, loc, params... );
     1237                        SemanticErrorException err( loc, toString( params... ) );
     1238                        errors.append( err );
    12461239                }
    12471240
  • src/InitTweak/FixInitNew.cpp

    r34b4268 r24d6572  
    1414#include <utility>                     // for pair
    1515
     16#include "AST/DeclReplacer.hpp"
     17#include "AST/Expr.hpp"
    1618#include "AST/Inspect.hpp"             // for getFunction, getPointerBase, g...
     19#include "AST/Node.hpp"
     20#include "AST/Pass.hpp"
     21#include "AST/Print.hpp"
     22#include "AST/SymbolTable.hpp"
     23#include "AST/Type.hpp"
    1724#include "CodeGen/GenType.h"           // for genPrettyType
    1825#include "CodeGen/OperatorTable.h"
    19 #include "Common/CodeLocationTools.hpp"
    2026#include "Common/PassVisitor.h"        // for PassVisitor, WithStmtsToAdd
    2127#include "Common/SemanticError.h"      // for SemanticError
     28#include "Common/ToString.hpp"         // for toCString
    2229#include "Common/UniqueName.h"         // for UniqueName
    23 #include "Common/utility.h"            // for CodeLocation, ValueGuard, toSt...
    2430#include "FixGlobalInit.h"             // for fixGlobalInit
    2531#include "GenInit.h"                   // for genCtorDtor
    2632#include "GenPoly/GenPoly.h"           // for getFunctionType
    2733#include "ResolvExpr/Resolver.h"       // for findVoidExpression
    28 #include "ResolvExpr/typeops.h"        // for typesCompatible
     34#include "ResolvExpr/Unify.h"          // for typesCompatible
    2935#include "SymTab/Autogen.h"            // for genImplicitCall
     36#include "SymTab/GenImplicitCall.hpp"  // for genImplicitCall
    3037#include "SymTab/Indexer.h"            // for Indexer
    3138#include "SymTab/Mangler.h"            // for Mangler
     
    4552#include "Validate/FindSpecialDecls.h" // for dtorStmt, dtorStructDestroy
    4653
    47 #include "AST/Expr.hpp"
    48 #include "AST/Node.hpp"
    49 #include "AST/Pass.hpp"
    50 #include "AST/Print.hpp"
    51 #include "AST/SymbolTable.hpp"
    52 #include "AST/Type.hpp"
    53 #include "AST/DeclReplacer.hpp"
    54 
    5554extern bool ctordtorp; // print all debug
    5655extern bool ctorp; // print ctor debug
     
    6362namespace InitTweak {
    6463namespace {
     64
     65        // Shallow copy the pointer list for return.
     66        std::vector<ast::ptr<ast::TypeDecl>> getGenericParams( const ast::Type * t ) {
     67                if ( auto inst = dynamic_cast<const ast::StructInstType *>( t ) ) {
     68                        return inst->base->params;
     69                }
     70                if ( auto inst = dynamic_cast<const ast::UnionInstType *>( t ) ) {
     71                        return inst->base->params;
     72                }
     73                return {};
     74        }
     75
     76        /// Given type T, generate type of default ctor/dtor, i.e. function type void (*) (T &).
     77        ast::FunctionDecl * genDefaultFunc(
     78                        const CodeLocation loc,
     79                        const std::string fname,
     80                        const ast::Type * paramType,
     81                        bool maybePolymorphic = true) {
     82                std::vector<ast::ptr<ast::TypeDecl>> typeParams;
     83                if ( maybePolymorphic ) typeParams = getGenericParams( paramType );
     84                auto dstParam = new ast::ObjectDecl( loc,
     85                        "_dst",
     86                        new ast::ReferenceType( paramType ),
     87                        nullptr,
     88                        {},
     89                        ast::Linkage::Cforall
     90                );
     91                return new ast::FunctionDecl( loc,
     92                        fname,
     93                        std::move(typeParams),
     94                        {dstParam},
     95                        {},
     96                        new ast::CompoundStmt(loc),
     97                        {},
     98                        ast::Linkage::Cforall
     99                );
     100        }
     101
    65102        struct SelfAssignChecker {
    66103                void previsit( const ast::ApplicationExpr * appExpr );
     
    107144        private:
    108145                /// hack to implement WithTypeSubstitution while conforming to mutation safety.
    109                 ast::TypeSubstitution * env;
    110                 bool                    envModified;
     146                ast::TypeSubstitution * env         = nullptr;
     147                bool                    envModified = false;
    111148        };
    112149
     
    121158                void previsit( const ast::FunctionDecl * ) { visit_children = false; }
    122159
    123           protected:
     160        protected:
    124161                ObjectSet curVars;
    125162        };
     
    202239
    203240                SemanticErrorException errors;
    204           private:
     241        private:
    205242                template< typename... Params >
    206243                void emit( CodeLocation, const Params &... params );
     
    288325                static UniqueName dtorNamer( "__cleanup_dtor" );
    289326                std::string name = dtorNamer.newName();
    290                 ast::FunctionDecl * dtorFunc = SymTab::genDefaultFunc( loc, name, objDecl->type->stripReferences(), false );
     327                ast::FunctionDecl * dtorFunc = genDefaultFunc( loc, name, objDecl->type->stripReferences(), false );
    291328                stmtsToAdd.push_back( new ast::DeclStmt(loc, dtorFunc ) );
    292329
     
    522559        {
    523560                static UniqueName tempNamer("_tmp_cp");
    524                 assert( env );
    525561                const CodeLocation loc = impCpCtorExpr->location;
    526562                // CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; )
     
    534570
    535571                // xxx - this originally mutates arg->result in place. is it correct?
     572                assert( env );
    536573                result = env->applyFree( result.get() ).node;
    537574                auto mutResult = result.get_and_mutate();
     
    10801117        void InsertDtors::previsit( const ast::BranchStmt * stmt ) {
    10811118                switch( stmt->kind ) {
    1082                   case ast::BranchStmt::Continue:
    1083                   case ast::BranchStmt::Break:
     1119                case ast::BranchStmt::Continue:
     1120                case ast::BranchStmt::Break:
    10841121                        // could optimize the break/continue case, because the S_L-S_G check is unnecessary (this set should
    10851122                        // always be empty), but it serves as a small sanity check.
    1086                   case ast::BranchStmt::Goto:
     1123                case ast::BranchStmt::Goto:
    10871124                        handleGoto( stmt );
    10881125                        break;
    1089                   default:
     1126                default:
    10901127                        assert( false );
    10911128                } // switch
     
    13031340        }
    13041341
    1305         template< typename Visitor, typename... Params >
    1306         void error( Visitor & v, CodeLocation loc, const Params &... params ) {
    1307                 SemanticErrorException err( loc, toString( params... ) );
    1308                 v.errors.append( err );
    1309         }
    1310 
    13111342        template< typename... Params >
    13121343        void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) {
    1313                 // toggle warnings vs. errors here.
    1314                 // warn( params... );
    1315                 error( *this, loc, params... );
     1344                SemanticErrorException err( loc, toString( params... ) );
     1345                errors.append( err );
    13161346        }
    13171347
     
    13191349                // xxx - functions returning ast::ptr seems wrong...
    13201350                auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } );
    1321                 // Fix CodeLocation (at least until resolver is fixed).
    1322                 auto fix = localFillCodeLocations( untypedExpr->location, res.release() );
    1323                 return strict_dynamic_cast<const ast::Expr *>( fix );
     1351                return res.release();
    13241352        }
    13251353
  • src/InitTweak/GenInit.cc

    r34b4268 r24d6572  
    3131#include "Common/PassVisitor.h"        // for PassVisitor, WithGuards, WithShort...
    3232#include "Common/SemanticError.h"      // for SemanticError
     33#include "Common/ToString.hpp"         // for toCString
    3334#include "Common/UniqueName.h"         // for UniqueName
    3435#include "Common/utility.h"            // for ValueGuard, maybeClone
     
    3839#include "ResolvExpr/Resolver.h"
    3940#include "SymTab/Autogen.h"            // for genImplicitCall
     41#include "SymTab/GenImplicitCall.hpp"  // for genImplicitCall
    4042#include "SymTab/Mangler.h"            // for Mangler
    4143#include "SynTree/LinkageSpec.h"       // for isOverridable, C
  • src/InitTweak/InitTweak.cc

    r34b4268 r24d6572  
    3535#include "GenPoly/GenPoly.h"       // for getFunctionType
    3636#include "InitTweak.h"
    37 #include "ResolvExpr/typeops.h"    // for typesCompatibleIgnoreQualifiers
     37#include "ResolvExpr/Unify.h"      // for typesCompatibleIgnoreQualifiers
    3838#include "SymTab/Autogen.h"
    3939#include "SymTab/Indexer.h"        // for Indexer
     
    10661066        const ast::Type * t2 = ftype->params.back();
    10671067
    1068         return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable() );
     1068        return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2 );
    10691069}
    10701070
  • src/MakeLibCfaNew.cpp

    r34b4268 r24d6572  
    1616#include "MakeLibCfa.h"
    1717
     18#include "AST/Copy.hpp"
    1819#include "AST/Fwd.hpp"
    1920#include "AST/Pass.hpp"
  • src/Parser/DeclarationNode.cc

    r34b4268 r24d6572  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 12:34:05 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Aug  8 17:07:00 2022
    13 // Update Count     : 1185
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thr Apr 20 11:46:00 2023
     13// Update Count     : 1393
    1414//
     15
     16#include "DeclarationNode.h"
    1517
    1618#include <cassert>                 // for assert, assertf, strict_dynamic_cast
     
    2123#include <string>                  // for string, operator+, allocator, char...
    2224
     25#include "AST/Attribute.hpp"       // for Attribute
     26#include "AST/Copy.hpp"            // for shallowCopy
     27#include "AST/Decl.hpp"            // for Decl
     28#include "AST/Expr.hpp"            // for Expr
     29#include "AST/Print.hpp"           // for print
     30#include "AST/Stmt.hpp"            // for AsmStmt, DirectiveStmt
     31#include "AST/StorageClasses.hpp"  // for Storage::Class
     32#include "AST/Type.hpp"            // for Type
     33#include "Common/CodeLocation.h"   // for CodeLocation
     34#include "Common/Iterate.hpp"      // for reverseIterate
    2335#include "Common/SemanticError.h"  // for SemanticError
    2436#include "Common/UniqueName.h"     // for UniqueName
    25 #include "Common/utility.h"        // for maybeClone, maybeBuild, CodeLocation
    26 #include "Parser/ParseNode.h"      // for DeclarationNode, ExpressionNode
    27 #include "SynTree/LinkageSpec.h"   // for Spec, linkageName, Cforall
    28 #include "SynTree/Attribute.h"     // for Attribute
    29 #include "SynTree/Declaration.h"   // for TypeDecl, ObjectDecl, InlineMemberDecl, Declaration
    30 #include "SynTree/Expression.h"    // for Expression, ConstantExpr
    31 #include "SynTree/Statement.h"     // for AsmStmt
    32 #include "SynTree/Type.h"          // for Type, Type::StorageClasses, Type::...
     37#include "Common/utility.h"        // for maybeClone
     38#include "Parser/ExpressionNode.h" // for ExpressionNode
     39#include "Parser/InitializerNode.h"// for InitializerNode
     40#include "Parser/StatementNode.h"  // for StatementNode
    3341#include "TypeData.h"              // for TypeData, TypeData::Aggregate_t
    3442#include "TypedefTable.h"          // for TypedefTable
     
    4149
    4250// These must harmonize with the corresponding DeclarationNode enumerations.
    43 const char * DeclarationNode::basicTypeNames[] = { "void", "_Bool", "char", "int", "int128",
    44                                                                                                    "float", "double", "long double", "float80", "float128",
    45                                                                                                    "_float16", "_float32", "_float32x", "_float64", "_float64x", "_float128", "_float128x", "NoBasicTypeNames" };
    46 const char * DeclarationNode::complexTypeNames[] = { "_Complex", "NoComplexTypeNames", "_Imaginary" }; // Imaginary unsupported => parse, but make invisible and print error message
    47 const char * DeclarationNode::signednessNames[] = { "signed", "unsigned", "NoSignednessNames" };
    48 const char * DeclarationNode::lengthNames[] = { "short", "long", "long long", "NoLengthNames" };
    49 const char * DeclarationNode::builtinTypeNames[] = { "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames" };
     51const char * DeclarationNode::basicTypeNames[] = {
     52        "void", "_Bool", "char", "int", "int128",
     53        "float", "double", "long double", "float80", "float128",
     54        "_float16", "_float32", "_float32x", "_float64", "_float64x", "_float128", "_float128x", "NoBasicTypeNames"
     55};
     56const char * DeclarationNode::complexTypeNames[] = {
     57        "_Complex", "NoComplexTypeNames", "_Imaginary"
     58}; // Imaginary unsupported => parse, but make invisible and print error message
     59const char * DeclarationNode::signednessNames[] = {
     60        "signed", "unsigned", "NoSignednessNames"
     61};
     62const char * DeclarationNode::lengthNames[] = {
     63        "short", "long", "long long", "NoLengthNames"
     64};
     65const char * DeclarationNode::builtinTypeNames[] = {
     66        "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames"
     67};
    5068
    5169UniqueName DeclarationNode::anonymous( "__anonymous" );
    5270
    53 extern LinkageSpec::Spec linkage;                                               // defined in parser.yy
     71extern ast::Linkage::Spec linkage;                                              // defined in parser.yy
    5472
    5573DeclarationNode::DeclarationNode() :
     
    5775
    5876//      variable.name = nullptr;
    59         variable.tyClass = TypeDecl::NUMBER_OF_KINDS;
     77        variable.tyClass = ast::TypeDecl::NUMBER_OF_KINDS;
    6078        variable.assertions = nullptr;
    6179        variable.initializer = nullptr;
    6280
    63 //      attr.name = nullptr;
    64         attr.expr = nullptr;
    65         attr.type = nullptr;
    66 
    6781        assert.condition = nullptr;
    6882        assert.message = nullptr;
     
    7084
    7185DeclarationNode::~DeclarationNode() {
    72 //      delete attr.name;
    73         delete attr.expr;
    74         delete attr.type;
    75 
    7686//      delete variable.name;
    7787        delete variable.assertions;
    7888        delete variable.initializer;
    7989
    80 //      delete type;
     90//      delete type;
    8191        delete bitfieldWidth;
    8292
     
    103113        newnode->hasEllipsis = hasEllipsis;
    104114        newnode->linkage = linkage;
    105         newnode->asmName = maybeClone( asmName );
    106         cloneAll( attributes, newnode->attributes );
     115        newnode->asmName = maybeCopy( asmName );
     116        newnode->attributes = attributes;
    107117        newnode->initializer = maybeClone( initializer );
    108118        newnode->extension = extension;
     
    115125        newnode->variable.initializer = maybeClone( variable.initializer );
    116126
    117 //      newnode->attr.name = attr.name ? new string( *attr.name ) : nullptr;
    118         newnode->attr.expr = maybeClone( attr.expr );
    119         newnode->attr.type = maybeClone( attr.type );
    120 
    121127        newnode->assert.condition = maybeClone( assert.condition );
    122         newnode->assert.message = maybeClone( assert.message );
     128        newnode->assert.message = maybeCopy( assert.message );
    123129        return newnode;
    124130} // DeclarationNode::clone
     
    130136        } // if
    131137
    132         if ( linkage != LinkageSpec::Cforall ) {
    133                 os << LinkageSpec::name( linkage ) << " ";
    134         } // if
    135 
    136         storageClasses.print( os );
    137         funcSpecs.print( os );
     138        if ( linkage != ast::Linkage::Cforall ) {
     139                os << ast::Linkage::name( linkage ) << " ";
     140        } // if
     141
     142        ast::print( os, storageClasses );
     143        ast::print( os, funcSpecs );
    138144
    139145        if ( type ) {
     
    154160        } // if
    155161
    156         for ( Attribute * attr: reverseIterate( attributes ) ) {
    157                 os << string( indent + 2, ' ' ) << "attr " << attr->name.c_str();
    158         } // for
     162        if ( ! attributes.empty() ) {
     163                os << string( indent + 2, ' ' ) << "with attributes " << endl;
     164                for ( ast::ptr<ast::Attribute> const & attr : reverseIterate( attributes ) ) {
     165                        os << string( indent + 4, ' ' ) << attr->name.c_str() << endl;
     166                } // for
     167        } // if
    159168
    160169        os << endl;
     
    168177}
    169178
    170 DeclarationNode * DeclarationNode::newStorageClass( Type::StorageClasses sc ) {
     179DeclarationNode * DeclarationNode::newStorageClass( ast::Storage::Classes sc ) {
    171180        DeclarationNode * newnode = new DeclarationNode;
    172181        newnode->storageClasses = sc;
     
    174183} // DeclarationNode::newStorageClass
    175184
    176 DeclarationNode * DeclarationNode::newFuncSpecifier( Type::FuncSpecifiers fs ) {
     185DeclarationNode * DeclarationNode::newFuncSpecifier( ast::Function::Specs fs ) {
    177186        DeclarationNode * newnode = new DeclarationNode;
    178187        newnode->funcSpecs = fs;
     
    180189} // DeclarationNode::newFuncSpecifier
    181190
    182 DeclarationNode * DeclarationNode::newTypeQualifier( Type::Qualifiers tq ) {
     191DeclarationNode * DeclarationNode::newTypeQualifier( ast::CV::Qualifiers tq ) {
    183192        DeclarationNode * newnode = new DeclarationNode;
    184193        newnode->type = new TypeData();
     
    240249}
    241250
    242 DeclarationNode * DeclarationNode::newAggregate( AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
     251DeclarationNode * DeclarationNode::newAggregate( ast::AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {
    243252        DeclarationNode * newnode = new DeclarationNode;
    244253        newnode->type = new TypeData( TypeData::Aggregate );
    245254        newnode->type->aggregate.kind = kind;
    246         newnode->type->aggregate.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
     255        newnode->type->aggregate.anon = name == nullptr;
     256        newnode->type->aggregate.name = newnode->type->aggregate.anon ? new string( DeclarationNode::anonymous.newName() ) : name;
    247257        newnode->type->aggregate.actuals = actuals;
    248258        newnode->type->aggregate.fields = fields;
     
    250260        newnode->type->aggregate.tagged = false;
    251261        newnode->type->aggregate.parent = nullptr;
    252         newnode->type->aggregate.anon = name == nullptr;
    253262        return newnode;
    254263} // DeclarationNode::newAggregate
     
    257266        DeclarationNode * newnode = new DeclarationNode;
    258267        newnode->type = new TypeData( TypeData::Enum );
    259         newnode->type->enumeration.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
     268        newnode->type->enumeration.anon = name == nullptr;
     269        newnode->type->enumeration.name = newnode->type->enumeration.anon ? new string( DeclarationNode::anonymous.newName() ) : name;
    260270        newnode->type->enumeration.constants = constants;
    261271        newnode->type->enumeration.body = body;
    262         newnode->type->enumeration.anon = name == nullptr;
    263272        newnode->type->enumeration.typed = typed;
    264273        newnode->type->enumeration.hiding = hiding;
    265         if ( base && base->type)  {
     274        if ( base && base->type )  {
    266275                newnode->type->base = base->type;
    267276        } // if
     
    269278        return newnode;
    270279} // DeclarationNode::newEnum
    271 
    272 
    273280
    274281DeclarationNode * DeclarationNode::newName( const string * name ) {
     
    323330} // DeclarationNode::newFromTypeGen
    324331
    325 DeclarationNode * DeclarationNode::newTypeParam( TypeDecl::Kind tc, const string * name ) {
     332DeclarationNode * DeclarationNode::newTypeParam( ast::TypeDecl::Kind tc, const string * name ) {
    326333        DeclarationNode * newnode = newName( name );
    327334        newnode->type = nullptr;
     
    335342        newnode->type = new TypeData( TypeData::Aggregate );
    336343        newnode->type->aggregate.name = name;
    337         newnode->type->aggregate.kind = AggregateDecl::Trait;
     344        newnode->type->aggregate.kind = ast::AggregateDecl::Trait;
    338345        newnode->type->aggregate.params = params;
    339346        newnode->type->aggregate.fields = asserts;
     
    345352        newnode->type = new TypeData( TypeData::AggregateInst );
    346353        newnode->type->aggInst.aggregate = new TypeData( TypeData::Aggregate );
    347         newnode->type->aggInst.aggregate->aggregate.kind = AggregateDecl::Trait;
     354        newnode->type->aggInst.aggregate->aggregate.kind = ast::AggregateDecl::Trait;
    348355        newnode->type->aggInst.aggregate->aggregate.name = name;
    349356        newnode->type->aggInst.params = params;
     
    380387        newnode->type->array.dimension = size;
    381388        newnode->type->array.isStatic = isStatic;
    382         if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType<ConstantExpr * >() ) {
     389        if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType<ast::ConstantExpr *>() ) {
    383390                newnode->type->array.isVarLen = false;
    384391        } else {
     
    450457        DeclarationNode * newnode = new DeclarationNode;
    451458        newnode->type = nullptr;
    452         std::list< Expression * > exprs;
     459        std::vector<ast::ptr<ast::Expr>> exprs;
    453460        buildList( expr, exprs );
    454         newnode->attributes.push_back( new Attribute( *name, exprs ) );
     461        newnode->attributes.push_back(
     462                new ast::Attribute( *name, std::move( exprs ) ) );
    455463        delete name;
    456464        return newnode;
     
    469477}
    470478
    471 DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, Expression * message ) {
     479DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, ast::Expr * message ) {
    472480        DeclarationNode * newnode = new DeclarationNode;
    473481        newnode->assert.condition = condition;
     
    476484}
    477485
    478 
    479 void appendError( string & dst, const string & src ) {
     486static void appendError( string & dst, const string & src ) {
    480487        if ( src.empty() ) return;
    481488        if ( dst.empty() ) { dst = src; return; }
     
    484491
    485492void DeclarationNode::checkQualifiers( const TypeData * src, const TypeData * dst ) {
    486         const Type::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization
    487 
    488         if ( (qsrc & qdst).any() ) {                                            // duplicates ?
    489                 for ( unsigned int i = 0; i < Type::NumTypeQualifier; i += 1 ) { // find duplicates
    490                         if ( qsrc[i] && qdst[i] ) {
    491                                 appendError( error, string( "duplicate " ) + Type::QualifiersNames[i] );
    492                         } // if
    493                 } // for
     493        const ast::CV::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization
     494        const ast::CV::Qualifiers duplicates = qsrc & qdst;
     495
     496        if ( duplicates.any() ) {
     497                std::stringstream str;
     498                str << "duplicate ";
     499                ast::print( str, duplicates );
     500                str << "qualifier(s)";
     501                appendError( error, str.str() );
    494502        } // for
    495503} // DeclarationNode::checkQualifiers
    496504
    497505void DeclarationNode::checkSpecifiers( DeclarationNode * src ) {
    498         if ( (funcSpecs & src->funcSpecs).any() ) {                     // duplicates ?
    499                 for ( unsigned int i = 0; i < Type::NumFuncSpecifier; i += 1 ) { // find duplicates
    500                         if ( funcSpecs[i] && src->funcSpecs[i] ) {
    501                                 appendError( error, string( "duplicate " ) + Type::FuncSpecifiersNames[i] );
    502                         } // if
    503                 } // for
    504         } // if
    505 
    506         if ( storageClasses.any() && src->storageClasses.any() ) { // any reason to check ?
    507                 if ( (storageClasses & src->storageClasses ).any() ) { // duplicates ?
    508                         for ( unsigned int i = 0; i < Type::NumStorageClass; i += 1 ) { // find duplicates
    509                                 if ( storageClasses[i] && src->storageClasses[i] ) {
    510                                         appendError( error, string( "duplicate " ) + Type::StorageClassesNames[i] );
    511                                 } // if
    512                         } // for
    513                         // src is the new item being added and has a single bit
    514                 } else if ( ! src->storageClasses.is_threadlocal_any() ) { // conflict ?
    515                         appendError( error, string( "conflicting " ) + Type::StorageClassesNames[storageClasses.ffs()] +
    516                                                  " & " + Type::StorageClassesNames[src->storageClasses.ffs()] );
    517                         src->storageClasses.reset();                            // FIX to preserve invariant of one basic storage specifier
    518                 } // if
     506        ast::Function::Specs fsDups = funcSpecs & src->funcSpecs;
     507        if ( fsDups.any() ) {
     508                std::stringstream str;
     509                str << "duplicate ";
     510                ast::print( str, fsDups );
     511                str << "function specifier(s)";
     512                appendError( error, str.str() );
     513        } // if
     514
     515        // Skip if everything is unset.
     516        if ( storageClasses.any() && src->storageClasses.any() ) {
     517                ast::Storage::Classes dups = storageClasses & src->storageClasses;
     518                // Check for duplicates.
     519                if ( dups.any() ) {
     520                        std::stringstream str;
     521                        str << "duplicate ";
     522                        ast::print( str, dups );
     523                        str << "storage class(es)";
     524                        appendError( error, str.str() );
     525                // Check for conflicts.
     526                } else if ( !src->storageClasses.is_threadlocal_any() ) {
     527                        std::stringstream str;
     528                        str << "conflicting ";
     529                        ast::print( str, ast::Storage::Classes( 1 << storageClasses.ffs() ) );
     530                        str << "& ";
     531                        ast::print( str, ast::Storage::Classes( 1 << src->storageClasses.ffs() ) );
     532                        str << "storage classes";
     533                        appendError( error, str.str() );
     534                        // FIX to preserve invariant of one basic storage specifier
     535                        src->storageClasses.reset();
     536                }
    519537        } // if
    520538
     
    526544        storageClasses |= q->storageClasses;
    527545
    528         for ( Attribute * attr: reverseIterate( q->attributes ) ) {
    529                 attributes.push_front( attr->clone() );
    530         } // for
     546        std::vector<ast::ptr<ast::Attribute>> tmp;
     547        tmp.reserve( q->attributes.size() );
     548        for ( auto const & attr : q->attributes ) {
     549                tmp.emplace_back( ast::shallowCopy( attr.get() ) );
     550        }
     551        spliceBegin( attributes, tmp );
     552
    531553        return this;
    532554} // DeclarationNode::copySpecifiers
     
    576598
    577599        checkQualifiers( type, q->type );
    578         if ( (builtin == Zero || builtin == One) && q->type->qualifiers.val != 0 && error.length() == 0 ) {
    579                 SemanticWarning( yylloc, Warning::BadQualifiersZeroOne, Type::QualifiersNames[ilog2( q->type->qualifiers.val )], builtinTypeNames[builtin] );
     600        if ( (builtin == Zero || builtin == One) && q->type->qualifiers.any() && error.length() == 0 ) {
     601                SemanticWarning( yylloc, Warning::BadQualifiersZeroOne, builtinTypeNames[builtin] );
    580602        } // if
    581603        addQualifiersToType( q->type, type );
     
    598620        } else {
    599621                switch ( dst->kind ) {
    600                   case TypeData::Unknown:
     622                case TypeData::Unknown:
    601623                        src->qualifiers |= dst->qualifiers;
    602624                        dst = src;
    603625                        src = nullptr;
    604626                        break;
    605                   case TypeData::Basic:
     627                case TypeData::Basic:
    606628                        dst->qualifiers |= src->qualifiers;
    607629                        if ( src->kind != TypeData::Unknown ) {
     
    631653                        } // if
    632654                        break;
    633                   default:
     655                default:
    634656                        switch ( src->kind ) {
    635                           case TypeData::Aggregate:
    636                           case TypeData::Enum:
     657                        case TypeData::Aggregate:
     658                        case TypeData::Enum:
    637659                                dst->base = new TypeData( TypeData::AggregateInst );
    638660                                dst->base->aggInst.aggregate = src;
     
    643665                                src = nullptr;
    644666                                break;
    645                           default:
     667                        default:
    646668                                if ( dst->forall ) {
    647669                                        dst->forall->appendList( src->forall );
     
    714736
    715737DeclarationNode * DeclarationNode::addAssertions( DeclarationNode * assertions ) {
    716         if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) {
    717                 if ( variable.assertions ) {
    718                         variable.assertions->appendList( assertions );
    719                 } else {
    720                         variable.assertions = assertions;
    721                 } // if
    722                 return this;
     738        if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) {
     739                if ( variable.assertions ) {
     740                        variable.assertions->appendList( assertions );
     741                } else {
     742                        variable.assertions = assertions;
     743                } // if
     744                return this;
    723745        } // if
    724746
    725747        assert( type );
    726748        switch ( type->kind ) {
    727           case TypeData::Symbolic:
     749        case TypeData::Symbolic:
    728750                if ( type->symbolic.assertions ) {
    729751                        type->symbolic.assertions->appendList( assertions );
     
    732754                } // if
    733755                break;
    734           default:
     756        default:
    735757                assert( false );
    736758        } // switch
     
    796818DeclarationNode * DeclarationNode::copyAttribute( DeclarationNode * a ) {
    797819        if ( a ) {
    798                 for ( Attribute *attr: reverseIterate( a->attributes ) ) {
    799                         attributes.push_front( attr );
    800                 } // for
     820                spliceBegin( attributes, a->attributes );
    801821                a->attributes.clear();
    802822        } // if
     
    831851                if ( type ) {
    832852                        switch ( type->kind ) {
    833                           case TypeData::Aggregate:
    834                           case TypeData::Enum:
     853                        case TypeData::Aggregate:
     854                        case TypeData::Enum:
    835855                                p->type->base = new TypeData( TypeData::AggregateInst );
    836856                                p->type->base->aggInst.aggregate = type;
     
    841861                                break;
    842862
    843                           default:
     863                        default:
    844864                                p->type->base = type;
    845865                        } // switch
     
    863883
    864884DeclarationNode * DeclarationNode::addNewArray( DeclarationNode * a ) {
    865   if ( ! a ) return this;
     885        if ( ! a ) return this;
    866886        assert( a->type->kind == TypeData::Array );
    867887        TypeData * lastArray = findLast( a->type );
    868888        if ( type ) {
    869889                switch ( type->kind ) {
    870                   case TypeData::Aggregate:
    871                   case TypeData::Enum:
     890                case TypeData::Aggregate:
     891                case TypeData::Enum:
    872892                        lastArray->base = new TypeData( TypeData::AggregateInst );
    873893                        lastArray->base->aggInst.aggregate = type;
     
    877897                        lastArray->base->qualifiers |= type->qualifiers;
    878898                        break;
    879                   default:
     899                default:
    880900                        lastArray->base = type;
    881901                } // switch
     
    919939
    920940DeclarationNode * DeclarationNode::addTypeInitializer( DeclarationNode * init ) {
    921         assertf( variable.tyClass != TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." );
     941        assertf( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." );
    922942        variable.initializer = init;
    923943        return this;
     
    9831003}
    9841004
    985 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList ) {
     1005// If a typedef wraps an anonymous declaration, name the inner declaration
     1006// so it has a consistent name across translation units.
     1007static void nameTypedefedDecl(
     1008                DeclarationNode * innerDecl,
     1009                const DeclarationNode * outerDecl ) {
     1010        TypeData * outer = outerDecl->type;
     1011        assert( outer );
     1012        // First make sure this is a typedef:
     1013        if ( outer->kind != TypeData::Symbolic || !outer->symbolic.isTypedef ) {
     1014                return;
     1015        }
     1016        TypeData * inner = innerDecl->type;
     1017        assert( inner );
     1018        // Always clear any CVs associated with the aggregate:
     1019        inner->qualifiers.reset();
     1020        // Handle anonymous aggregates: typedef struct { int i; } foo
     1021        if ( inner->kind == TypeData::Aggregate && inner->aggregate.anon ) {
     1022                delete inner->aggregate.name;
     1023                inner->aggregate.name = new string( "__anonymous_" + *outerDecl->name );
     1024                inner->aggregate.anon = false;
     1025                assert( outer->base );
     1026                delete outer->base->aggInst.aggregate->aggregate.name;
     1027                outer->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *outerDecl->name );
     1028                outer->base->aggInst.aggregate->aggregate.anon = false;
     1029                outer->base->aggInst.aggregate->qualifiers.reset();
     1030        // Handle anonymous enumeration: typedef enum { A, B, C } foo
     1031        } else if ( inner->kind == TypeData::Enum && inner->enumeration.anon ) {
     1032                delete inner->enumeration.name;
     1033                inner->enumeration.name = new string( "__anonymous_" + *outerDecl->name );
     1034                inner->enumeration.anon = false;
     1035                assert( outer->base );
     1036                delete outer->base->aggInst.aggregate->enumeration.name;
     1037                outer->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *outerDecl->name );
     1038                outer->base->aggInst.aggregate->enumeration.anon = false;
     1039                // No qualifiers.reset() here.
     1040        }
     1041}
     1042
     1043// This code handles a special issue with the attribute transparent_union.
     1044//
     1045//    typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union ))
     1046//
     1047// Here the attribute aligned goes with the typedef_name, so variables declared of this type are
     1048// aligned.  However, the attribute transparent_union must be moved from the typedef_name to
     1049// alias union U.  Currently, this is the only know attribute that must be moved from typedef to
     1050// alias.
     1051static void moveUnionAttribute( ast::Decl * decl, ast::UnionDecl * unionDecl ) {
     1052        if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) {
     1053                // Is the typedef alias a union aggregate?
     1054                if ( nullptr == unionDecl ) return;
     1055
     1056                // If typedef is an alias for a union, then its alias type was hoisted above and remembered.
     1057                if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) {
     1058                        auto instType = ast::mutate( unionInstType );
     1059                        // Remove all transparent_union attributes from typedef and move to alias union.
     1060                        for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) {
     1061                                assert( *attr );
     1062                                if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) {
     1063                                        unionDecl->attributes.emplace_back( attr->release() );
     1064                                        attr = instType->attributes.erase( attr );
     1065                                } else {
     1066                                        attr++;
     1067                                }
     1068                        }
     1069                        typedefDecl->base = instType;
     1070                }
     1071        }
     1072}
     1073
     1074// Get the non-anonymous name of the instance type of the declaration,
     1075// if one exists.
     1076static const std::string * getInstTypeOfName( ast::Decl * decl ) {
     1077        if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {
     1078                if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) {
     1079                        if ( aggr->name.find("anonymous") == std::string::npos ) {
     1080                                return &aggr->name;
     1081                        }
     1082                }
     1083        }
     1084        return nullptr;
     1085}
     1086
     1087void buildList( DeclarationNode * firstNode,
     1088                std::vector<ast::ptr<ast::Decl>> & outputList ) {
    9861089        SemanticErrorException errors;
    987         std::back_insert_iterator< std::list< Declaration * > > out( outputList );
    988 
    989         for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
     1090        std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList );
     1091
     1092        for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
    9901093                try {
    991                         bool extracted = false;
    992                         bool anon = false;
     1094                        bool extracted_named = false;
     1095                        ast::UnionDecl * unionDecl = nullptr;
     1096
    9931097                        if ( DeclarationNode * extr = cur->extractAggregate() ) {
    994                                 // handle the case where a structure declaration is contained within an object or type declaration
    995                                 Declaration * decl = extr->build();
    996                                 if ( decl ) {
    997                                         // hoist the structure declaration
    998                                         decl->location = cur->location;
    999                                         * out++ = decl;
     1098                                assert( cur->type );
     1099                                nameTypedefedDecl( extr, cur );
     1100
     1101                                if ( ast::Decl * decl = extr->build() ) {
     1102                                        // Remember the declaration if it is a union aggregate ?
     1103                                        unionDecl = dynamic_cast<ast::UnionDecl *>( decl );
     1104
     1105                                        *out++ = decl;
    10001106
    10011107                                        // need to remember the cases where a declaration contains an anonymous aggregate definition
    1002                                         extracted = true;
    10031108                                        assert( extr->type );
    10041109                                        if ( extr->type->kind == TypeData::Aggregate ) {
    1005                                                 anon = extr->type->aggregate.anon;
     1110                                                // typedef struct { int A } B is the only case?
     1111                                                extracted_named = !extr->type->aggregate.anon;
    10061112                                        } else if ( extr->type->kind == TypeData::Enum ) {
    1007                                                 // xxx - is it useful to have an implicit anonymous enum member?
    1008                                                 anon = extr->type->enumeration.anon;
     1113                                                // typedef enum { A } B is the only case?
     1114                                                extracted_named = !extr->type->enumeration.anon;
     1115                                        } else {
     1116                                                extracted_named = true;
    10091117                                        }
    10101118                                } // if
     
    10121120                        } // if
    10131121
    1014                         Declaration * decl = cur->build();
    1015                         if ( decl ) {
    1016                                 // don't include anonymous declaration for named aggregates, but do include them for anonymous aggregates, e.g.:
    1017                                 // struct S {
    1018                                 //   struct T { int x; }; // no anonymous member
    1019                                 //   struct { int y; };   // anonymous member
    1020                                 //   struct T;            // anonymous member
    1021                                 // };
    1022                                 if ( ! (extracted && decl->name == "" && ! anon && ! cur->get_inLine()) ) {
    1023                                         if ( decl->name == "" ) {
    1024                                                 if ( DeclarationWithType * dwt = dynamic_cast<DeclarationWithType *>( decl ) ) {
    1025                                                         if ( ReferenceToType * aggr = dynamic_cast<ReferenceToType *>( dwt->get_type() ) ) {
    1026                                                                 if ( aggr->name.find("anonymous") == std::string::npos ) {
    1027                                                                         if ( ! cur->get_inLine() ) {
    1028                                                                                 // temporary: warn about anonymous member declarations of named types, since
    1029                                                                                 // this conflicts with the syntax for the forward declaration of an anonymous type
    1030                                                                                 SemanticWarning( cur->location, Warning::AggrForwardDecl, aggr->name.c_str() );
    1031                                                                         } // if
    1032                                                                 } // if
    1033                                                         } // if
    1034                                                 } // if
    1035                                         } // if
    1036                                         decl->location = cur->location;
    1037                                         *out++ = decl;
     1122                        if ( ast::Decl * decl = cur->build() ) {
     1123                                moveUnionAttribute( decl, unionDecl );
     1124
     1125                                if ( "" == decl->name && !cur->get_inLine() ) {
     1126                                        // Don't include anonymous declaration for named aggregates,
     1127                                        // but do include them for anonymous aggregates, e.g.:
     1128                                        // struct S {
     1129                                        //   struct T { int x; }; // no anonymous member
     1130                                        //   struct { int y; };   // anonymous member
     1131                                        //   struct T;            // anonymous member
     1132                                        // };
     1133                                        if ( extracted_named ) {
     1134                                                continue;
     1135                                        }
     1136
     1137                                        if ( auto name = getInstTypeOfName( decl ) ) {
     1138                                                // Temporary: warn about anonymous member declarations of named types, since
     1139                                                // this conflicts with the syntax for the forward declaration of an anonymous type.
     1140                                                SemanticWarning( cur->location, Warning::AggrForwardDecl, name->c_str() );
     1141                                        }
    10381142                                } // if
     1143                                *out++ = decl;
    10391144                        } // if
    1040                 } catch( SemanticErrorException & e ) {
     1145                } catch ( SemanticErrorException & e ) {
    10411146                        errors.append( e );
    10421147                } // try
     
    10491154
    10501155// currently only builds assertions, function parameters, and return values
    1051 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList ) {
     1156void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) {
    10521157        SemanticErrorException errors;
    1053         std::back_insert_iterator< std::list< DeclarationWithType * > > out( outputList );
    1054 
    1055         for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
     1158        std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList );
     1159
     1160        for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur ) ) {
    10561161                try {
    1057                         Declaration * decl = cur->build();
    1058                         assert( decl );
    1059                         if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
     1162                        ast::Decl * decl = cur->build();
     1163                        assertf( decl, "buildList: build for ast::DeclWithType." );
     1164                        if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) {
    10601165                                dwt->location = cur->location;
    10611166                                *out++ = dwt;
    1062                         } else if ( StructDecl * agg = dynamic_cast< StructDecl * >( decl ) ) {
     1167                        } else if ( ast::StructDecl * agg = dynamic_cast<ast::StructDecl *>( decl ) ) {
    10631168                                // e.g., int foo(struct S) {}
    1064                                 StructInstType * inst = new StructInstType( Type::Qualifiers(), agg->name );
    1065                                 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
    1066                                 obj->location = cur->location;
     1169                                auto inst = new ast::StructInstType( agg->name );
     1170                                auto obj = new ast::ObjectDecl( cur->location, "", inst );
     1171                                obj->linkage = linkage;
    10671172                                *out++ = obj;
    10681173                                delete agg;
    1069                         } else if ( UnionDecl * agg = dynamic_cast< UnionDecl * >( decl ) ) {
     1174                        } else if ( ast::UnionDecl * agg = dynamic_cast<ast::UnionDecl *>( decl ) ) {
    10701175                                // e.g., int foo(union U) {}
    1071                                 UnionInstType * inst = new UnionInstType( Type::Qualifiers(), agg->name );
    1072                                 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
    1073                                 obj->location = cur->location;
     1176                                auto inst = new ast::UnionInstType( agg->name );
     1177                                auto obj = new ast::ObjectDecl( cur->location,
     1178                                        "", inst, nullptr, ast::Storage::Classes(),
     1179                                        linkage );
    10741180                                *out++ = obj;
    1075                         } else if ( EnumDecl * agg = dynamic_cast< EnumDecl * >( decl ) ) {
     1181                        } else if ( ast::EnumDecl * agg = dynamic_cast<ast::EnumDecl *>( decl ) ) {
    10761182                                // e.g., int foo(enum E) {}
    1077                                 EnumInstType * inst = new EnumInstType( Type::Qualifiers(), agg->name );
    1078                                 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
    1079                                 obj->location = cur->location;
     1183                                auto inst = new ast::EnumInstType( agg->name );
     1184                                auto obj = new ast::ObjectDecl( cur->location,
     1185                                        "",
     1186                                        inst,
     1187                                        nullptr,
     1188                                        ast::Storage::Classes(),
     1189                                        linkage
     1190                                );
    10801191                                *out++ = obj;
     1192                        } else {
     1193                                assertf( false, "buildList: Could not convert to ast::DeclWithType." );
    10811194                        } // if
    1082                 } catch( SemanticErrorException & e ) {
     1195                } catch ( SemanticErrorException & e ) {
    10831196                        errors.append( e );
    10841197                } // try
     
    10901203} // buildList
    10911204
    1092 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList ) {
     1205void buildTypeList( const DeclarationNode * firstNode,
     1206                std::vector<ast::ptr<ast::Type>> & outputList ) {
    10931207        SemanticErrorException errors;
    1094         std::back_insert_iterator< std::list< Type * > > out( outputList );
    1095         const DeclarationNode * cur = firstNode;
    1096 
    1097         while ( cur ) {
     1208        std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList );
     1209
     1210        for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) {
    10981211                try {
    10991212                        * out++ = cur->buildType();
    1100                 } catch( SemanticErrorException & e ) {
     1213                } catch ( SemanticErrorException & e ) {
    11011214                        errors.append( e );
    11021215                } // try
    1103                 cur = dynamic_cast< DeclarationNode * >( cur->get_next() );
    1104         } // while
     1216        } // for
    11051217
    11061218        if ( ! errors.isEmpty() ) {
     
    11091221} // buildTypeList
    11101222
    1111 Declaration * DeclarationNode::build() const {
     1223ast::Decl * DeclarationNode::build() const {
    11121224        if ( ! error.empty() ) SemanticError( this, error + " in declaration of " );
    11131225
    11141226        if ( asmStmt ) {
    1115                 return new AsmDecl( strict_dynamic_cast<AsmStmt *>( asmStmt->build() ) );
     1227                auto stmt = strict_dynamic_cast<ast::AsmStmt *>( asmStmt->build() );
     1228                return new ast::AsmDecl( stmt->location, stmt );
    11161229        } // if
    11171230        if ( directiveStmt ) {
    1118                 return new DirectiveDecl( strict_dynamic_cast<DirectiveStmt *>( directiveStmt->build() ) );
    1119         } // if
    1120 
    1121         if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) {
     1231                auto stmt = strict_dynamic_cast<ast::DirectiveStmt *>( directiveStmt->build() );
     1232                return new ast::DirectiveDecl( stmt->location, stmt );
     1233        } // if
     1234
     1235        if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) {
    11221236                // otype is internally converted to dtype + otype parameters
    1123                 static const TypeDecl::Kind kindMap[] = { TypeDecl::Dtype, TypeDecl::Dtype, TypeDecl::Dtype, TypeDecl::Ftype, TypeDecl::Ttype, TypeDecl::Dimension };
    1124                 static_assert( sizeof(kindMap) / sizeof(kindMap[0]) == TypeDecl::NUMBER_OF_KINDS, "DeclarationNode::build: kindMap is out of sync." );
     1237                static const ast::TypeDecl::Kind kindMap[] = { ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Ftype, ast::TypeDecl::Ttype, ast::TypeDecl::Dimension };
     1238                static_assert( sizeof(kindMap) / sizeof(kindMap[0]) == ast::TypeDecl::NUMBER_OF_KINDS, "DeclarationNode::build: kindMap is out of sync." );
    11251239                assertf( variable.tyClass < sizeof(kindMap)/sizeof(kindMap[0]), "Variable's tyClass is out of bounds." );
    1126                 TypeDecl * ret = new TypeDecl( *name, Type::StorageClasses(), nullptr, kindMap[ variable.tyClass ], variable.tyClass == TypeDecl::Otype || variable.tyClass == TypeDecl::DStype, variable.initializer ? variable.initializer->buildType() : nullptr );
    1127                 buildList( variable.assertions, ret->get_assertions() );
     1240                ast::TypeDecl * ret = new ast::TypeDecl( location,
     1241                        *name,
     1242                        ast::Storage::Classes(),
     1243                        (ast::Type *)nullptr,
     1244                        kindMap[ variable.tyClass ],
     1245                        variable.tyClass == ast::TypeDecl::Otype || variable.tyClass == ast::TypeDecl::DStype,
     1246                        variable.initializer ? variable.initializer->buildType() : nullptr
     1247                );
     1248                buildList( variable.assertions, ret->assertions );
    11281249                return ret;
    11291250        } // if
     
    11471268                } // if
    11481269                bool isDelete = initializer && initializer->get_isDelete();
    1149                 Declaration * decl = buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, isDelete ? nullptr : maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
     1270                ast::Decl * decl = buildDecl(
     1271                        type,
     1272                        name ? *name : string( "" ),
     1273                        storageClasses,
     1274                        maybeBuild( bitfieldWidth ),
     1275                        funcSpecs,
     1276                        linkage,
     1277                        asmName,
     1278                        isDelete ? nullptr : maybeBuild( initializer ),
     1279                        copy( attributes )
     1280                )->set_extension( extension );
    11501281                if ( isDelete ) {
    1151                         DeclarationWithType * dwt = strict_dynamic_cast<DeclarationWithType *>( decl );
     1282                        auto dwt = strict_dynamic_cast<ast::DeclWithType *>( decl );
    11521283                        dwt->isDeleted = true;
    11531284                }
     
    11561287
    11571288        if ( assert.condition ) {
    1158                 return new StaticAssertDecl( maybeBuild< Expression >( assert.condition ), strict_dynamic_cast< ConstantExpr * >( maybeClone( assert.message ) ) );
     1289                auto cond = maybeBuild( assert.condition );
     1290                auto msg = strict_dynamic_cast<ast::ConstantExpr *>( maybeCopy( assert.message ) );
     1291                return new ast::StaticAssertDecl( location, cond, msg );
    11591292        }
    11601293
     
    11671300        } // if
    11681301        if ( enumInLine ) {
    1169                 return new InlineMemberDecl( *name, storageClasses, linkage, nullptr );
     1302                return new ast::InlineMemberDecl( location,
     1303                        *name, (ast::Type*)nullptr, storageClasses, linkage );
    11701304        } // if
    11711305        assertf( name, "ObjectDecl must a have name\n" );
    1172         return (new ObjectDecl( *name, storageClasses, linkage, maybeBuild< Expression >( bitfieldWidth ), nullptr, maybeBuild< Initializer >( initializer ) ))->set_asmName( asmName )->set_extension( extension );
    1173 }
    1174 
    1175 Type * DeclarationNode::buildType() const {
     1306        auto ret = new ast::ObjectDecl( location,
     1307                *name,
     1308                (ast::Type*)nullptr,
     1309                maybeBuild( initializer ),
     1310                storageClasses,
     1311                linkage,
     1312                maybeBuild( bitfieldWidth )
     1313        );
     1314        ret->asmName = asmName;
     1315        ret->extension = extension;
     1316        return ret;
     1317}
     1318
     1319ast::Type * DeclarationNode::buildType() const {
    11761320        assert( type );
    11771321
    1178         if ( attr.expr ) {
    1179                 return new AttrType( buildQualifiers( type ), *name, attr.expr->build(), attributes );
    1180         } else if ( attr.type ) {
    1181                 return new AttrType( buildQualifiers( type ), *name, attr.type->buildType(), attributes );
    1182         } // if
    1183 
    11841322        switch ( type->kind ) {
    1185           case TypeData::Enum:
    1186           case TypeData::Aggregate: {
    1187                   ReferenceToType * ret = buildComAggInst( type, attributes, linkage );
    1188                   buildList( type->aggregate.actuals, ret->get_parameters() );
    1189                   return ret;
    1190           }
    1191           case TypeData::Symbolic: {
    1192                   TypeInstType * ret = new TypeInstType( buildQualifiers( type ), *type->symbolic.name, false, attributes );
    1193                   buildList( type->symbolic.actuals, ret->get_parameters() );
    1194                   return ret;
    1195           }
    1196           default:
    1197                 Type * simpletypes = typebuild( type );
    1198                 simpletypes->get_attributes() = attributes;             // copy because member is const
     1323        case TypeData::Enum:
     1324        case TypeData::Aggregate: {
     1325                ast::BaseInstType * ret =
     1326                        buildComAggInst( type, copy( attributes ), linkage );
     1327                buildList( type->aggregate.actuals, ret->params );
     1328                return ret;
     1329        }
     1330        case TypeData::Symbolic: {
     1331                ast::TypeInstType * ret = new ast::TypeInstType(
     1332                        *type->symbolic.name,
     1333                        // This is just a default, the true value is not known yet.
     1334                        ast::TypeDecl::Dtype,
     1335                        buildQualifiers( type ),
     1336                        copy( attributes ) );
     1337                buildList( type->symbolic.actuals, ret->params );
     1338                return ret;
     1339        }
     1340        default:
     1341                ast::Type * simpletypes = typebuild( type );
     1342                // copy because member is const
     1343                simpletypes->attributes = attributes;
    11991344                return simpletypes;
    12001345        } // switch
  • src/Parser/ExpressionNode.cc

    r34b4268 r24d6572  
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat May 16 13:17:07 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug  7 09:18:56 2021
    13 // Update Count     : 1077
    14 //
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Apr  4 11:07:00 2023
     13// Update Count     : 1083
     14//
     15
     16#include "ExpressionNode.h"
    1517
    1618#include <cassert>                 // for assert
     
    2123#include <string>                  // for string, operator+, operator==
    2224
     25#include "AST/Expr.hpp"            // for NameExpr
     26#include "AST/Type.hpp"            // for BaseType, SueInstType
    2327#include "Common/SemanticError.h"  // for SemanticError
    2428#include "Common/utility.h"        // for maybeMoveBuild, maybeBuild, CodeLo...
    25 #include "ParseNode.h"             // for ExpressionNode, maybeMoveBuildType
    26 #include "SynTree/Constant.h"      // for Constant
    27 #include "SynTree/Declaration.h"   // for EnumDecl, StructDecl, UnionDecl
    28 #include "SynTree/Expression.h"    // for Expression, ConstantExpr, NameExpr
    29 #include "SynTree/Statement.h"     // for CompoundStmt, Statement
    30 #include "SynTree/Type.h"          // for BasicType, Type, Type::Qualifiers
     29#include "DeclarationNode.h"       // for DeclarationNode
     30#include "InitializerNode.h"       // for InitializerNode
    3131#include "parserutility.h"         // for notZeroExpr
    32 
    33 class Initializer;
    3432
    3533using namespace std;
     
    4846// because the CONT rule is NOT triggered if the pattern is empty. Hence, constants are reparsed here to determine their
    4947// type.
    50 
    51 extern const Type::Qualifiers noQualifiers;                             // no qualifiers on constants
    5248
    5349// static inline bool checkH( char c ) { return c == 'h' || c == 'H'; }
     
    7167        size_t end = str.length() - 1;
    7268        if ( posn == end ) { type = 3; return; }                        // no length after 'l' => long
    73        
     69
    7470        string::size_type next = posn + 1;                                      // advance to length
    7571        if ( str[next] == '3' ) {                                                       // 32
     
    122118                if ( str[i] == '1' ) v |= 1;
    123119                i += 1;
    124           if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
     120                if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
    125121                v <<= 1;
    126122        } // for
    127123} // scanbin
    128124
    129 Expression * build_constantInteger( string & str ) {
    130         static const BasicType::Kind kind[2][6] = {
     125ast::Expr * build_constantInteger(
     126                const CodeLocation & location, string & str ) {
     127        static const ast::BasicType::Kind kind[2][6] = {
    131128                // short (h) must be before char (hh) because shorter type has the longer suffix
    132                 { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */ BasicType::LongLongSignedInt, },
    133                 { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */ BasicType::LongLongUnsignedInt, },
     129                { ast::BasicType::ShortSignedInt, ast::BasicType::SignedChar, ast::BasicType::SignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */ ast::BasicType::LongLongSignedInt, },
     130                { ast::BasicType::ShortUnsignedInt, ast::BasicType::UnsignedChar, ast::BasicType::UnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */ ast::BasicType::LongLongUnsignedInt, },
    134131        };
    135132
     
    141138        string str2( "0x0" );
    142139        unsigned long long int v, v2 = 0;                                       // converted integral value
    143         Expression * ret, * ret2;
     140        ast::Expr * ret, * ret2;
    144141
    145142        int type = -1;                                                                          // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
     
    149146        // special constants
    150147        if ( str == "0" ) {
    151                 ret = new ConstantExpr( Constant( (Type *)new ZeroType( noQualifiers ), str, (unsigned long long int)0 ) );
     148                ret = new ast::ConstantExpr( location, new ast::ZeroType(), str, 0 );
    152149                goto CLEANUP;
    153150        } // if
    154151        if ( str == "1" ) {
    155                 ret = new ConstantExpr( Constant( (Type *)new OneType( noQualifiers ), str, (unsigned long long int)1 ) );
     152                ret = new ast::ConstantExpr( location, new ast::OneType(), str, 1 );
    156153                goto CLEANUP;
    157154        } // if
    158 
    159         string::size_type posn;
    160155
    161156        // 'u' can appear before or after length suffix
     
    166161        } else {
    167162                // At least one digit in integer constant, so safe to backup while looking for suffix.
    168 
    169                 posn = str.find_last_of( "pP" );                                // pointer value
    170                 if ( posn != string::npos ) { ltype = 5; str.erase( posn, 1 ); goto FINI; }
    171 
    172                 posn = str.find_last_of( "zZ" );                                // size_t
    173                 if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; }
    174 
    175                 posn = str.rfind( "hh" );                                               // char
    176                 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
    177 
    178                 posn = str.rfind( "HH" );                                               // char
    179                 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
    180 
    181                 posn = str.find_last_of( "hH" );                                // short
    182                 if ( posn != string::npos ) { type = 0; str.erase( posn, 1 ); goto FINI; }
    183 
    184                 posn = str.find_last_of( "nN" );                                // int (natural number)
    185                 if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; }
    186 
    187                 if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; }
    188 
    189                 lnthSuffix( str, type, ltype );                                 // must be after check for "ll"
    190           FINI: ;
     163                // This declaration and the comma expressions in the conditions mimic
     164                // the declare and check pattern allowed in later compiler versions.
     165                // (Only some early compilers/C++ standards do not support it.)
     166                string::size_type posn;
     167                // pointer value
     168                if ( posn = str.find_last_of( "pP" ), posn != string::npos ) {
     169                        ltype = 5; str.erase( posn, 1 );
     170                // size_t
     171                } else if ( posn = str.find_last_of( "zZ" ), posn != string::npos ) {
     172                        Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 );
     173                // signed char
     174                } else if ( posn = str.rfind( "hh" ), posn != string::npos ) {
     175                        type = 1; str.erase( posn, 2 );
     176                // signed char
     177                } else if ( posn = str.rfind( "HH" ), posn != string::npos ) {
     178                        type = 1; str.erase( posn, 2 );
     179                // short
     180                } else if ( posn = str.find_last_of( "hH" ), posn != string::npos ) {
     181                        type = 0; str.erase( posn, 1 );
     182                // int (natural number)
     183                } else if ( posn = str.find_last_of( "nN" ), posn != string::npos ) {
     184                        type = 2; str.erase( posn, 1 );
     185                } else if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) {
     186                        type = 4;
     187                } else {
     188                        lnthSuffix( str, type, ltype );
     189                } // if
    191190        } // if
    192191
     
    196195        if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target " + str );
    197196#endif // ! __SIZEOF_INT128__
    198        
     197
    199198        if ( str[0] == '0' ) {                                                          // radix character ?
    200199                dec = false;
     
    206205                                unsigned int len = str.length();
    207206                                if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large " + str );
    208                           if ( len <= (2 + 16) ) goto FHEX1;            // hex digits < 2^64
    209                                 str2 = "0x" + str.substr( len - 16 );
    210                                 sscanf( (char *)str2.c_str(), "%llx", &v2 );
    211                                 str = str.substr( 0, len - 16 );
    212                           FHEX1: ;
     207                                // hex digits < 2^64
     208                                if ( len > (2 + 16) ) {
     209                                        str2 = "0x" + str.substr( len - 16 );
     210                                        sscanf( (char *)str2.c_str(), "%llx", &v2 );
     211                                        str = str.substr( 0, len - 16 );
     212                                } // if
    213213                                sscanf( (char *)str.c_str(), "%llx", &v );
    214214#endif // __SIZEOF_INT128__
     
    301301
    302302        // Constant type is correct for overload resolving.
    303         ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][type] ), str, v ) );
     303        ret = new ast::ConstantExpr( location,
     304                new ast::BasicType( kind[Unsigned][type] ), str, v );
    304305        if ( Unsigned && type < 2 ) {                                           // hh or h, less than int ?
    305306                // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values.
    306                 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
     307                ret = new ast::CastExpr( location,
     308                        ret,
     309                        new ast::BasicType( kind[Unsigned][type] ),
     310                        ast::ExplicitCast );
    307311        } else if ( ltype != -1 ) {                                                     // explicit length ?
    308312                if ( ltype == 6 ) {                                                             // int128, (int128)constant
    309 //                      ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false );
    310                         ret2 = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::LongLongSignedInt ), str2, v2 ) );
    311                         ret = build_compoundLiteral( DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ),
    312                                                                                  new InitializerNode( (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true ) );
     313                        ret2 = new ast::ConstantExpr( location,
     314                                new ast::BasicType( ast::BasicType::LongLongSignedInt ),
     315                                str2,
     316                                v2 );
     317                        ret = build_compoundLiteral( location,
     318                                DeclarationNode::newBasicType(
     319                                        DeclarationNode::Int128
     320                                )->addType(
     321                                        DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ),
     322                                new InitializerNode(
     323                                        (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true )
     324                        );
    313325                } else {                                                                                // explicit length, (length_type)constant
    314                         ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false );
     326                        ret = new ast::CastExpr( location,
     327                                ret,
     328                                new ast::TypeInstType( lnthsInt[Unsigned][ltype], ast::TypeDecl::Dtype ),
     329                                ast::ExplicitCast );
    315330                        if ( ltype == 5 ) {                                                     // pointer, intptr( (uintptr_t)constant )
    316                                 ret = build_func( new ExpressionNode( build_varref( new string( "intptr" ) ) ), new ExpressionNode( ret ) );
     331                                ret = build_func( location,
     332                                        new ExpressionNode(
     333                                                build_varref( location, new string( "intptr" ) ) ),
     334                                        new ExpressionNode( ret ) );
    317335                        } // if
    318336                } // if
     
    358376
    359377
    360 Expression * build_constantFloat( string & str ) {
    361         static const BasicType::Kind kind[2][12] = {
    362                 { BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128, BasicType::uFloat128x },
    363                 { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::NUMBER_OF_BASIC_TYPES, BasicType::NUMBER_OF_BASIC_TYPES, BasicType::uFloat16Complex, BasicType::uFloat32Complex, BasicType::uFloat32xComplex, BasicType::uFloat64Complex, BasicType::uFloat64xComplex, BasicType::uFloat128Complex, BasicType::uFloat128xComplex },
     378ast::Expr * build_constantFloat(
     379                const CodeLocation & location, string & str ) {
     380        static const ast::BasicType::Kind kind[2][12] = {
     381                { ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x },
     382                { ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, ast::BasicType::NUMBER_OF_BASIC_TYPES, ast::BasicType::NUMBER_OF_BASIC_TYPES, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex },
    364383        };
    365384
     
    398417
    399418        assert( 0 <= type && type < 12 );
    400         Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[complx][type] ), str, v ) );
    401         if ( explnth ) {                                                                        // explicit length ?
    402                 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[complx][type] ), false );
     419        ast::Expr * ret = new ast::ConstantExpr( location,
     420                new ast::BasicType( kind[complx][type] ),
     421                str,
     422                v );
     423        // explicit length ?
     424        if ( explnth ) {
     425                ret = new ast::CastExpr( location,
     426                        ret,
     427                        new ast::BasicType( kind[complx][type] ),
     428                        ast::ExplicitCast );
    403429        } // if
    404430
     
    415441} // sepString
    416442
    417 Expression * build_constantChar( string & str ) {
     443ast::Expr * build_constantChar( const CodeLocation & location, string & str ) {
    418444        string units;                                                                           // units
    419445        sepString( str, units, '\'' );                                          // separate constant from units
    420446
    421         Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::Char ), str, (unsigned long long int)(unsigned char)str[1] ) );
     447        ast::Expr * ret = new ast::ConstantExpr( location,
     448                new ast::BasicType( ast::BasicType::Char ),
     449                str,
     450                (unsigned long long int)(unsigned char)str[1] );
    422451        if ( units.length() != 0 ) {
    423                 ret = new UntypedExpr( new NameExpr( units ), { ret } );
     452                ret = new ast::UntypedExpr( location,
     453                        new ast::NameExpr( location, units ),
     454                        { ret } );
    424455        } // if
    425456
     
    428459} // build_constantChar
    429460
    430 Expression * build_constantStr( string & str ) {
     461ast::Expr * build_constantStr(
     462                const CodeLocation & location,
     463                string & str ) {
    431464        assert( str.length() > 0 );
    432465        string units;                                                                           // units
    433466        sepString( str, units, '"' );                                           // separate constant from units
    434467
    435         Type * strtype;
     468        ast::Type * strtype;
    436469        switch ( str[0] ) {                                                                     // str has >= 2 characters, i.e, null string "" => safe to look at subscripts 0/1
    437           case 'u':
     470        case 'u':
    438471                if ( str[1] == '8' ) goto Default;                              // utf-8 characters => array of char
    439472                // lookup type of associated typedef
    440                 strtype = new TypeInstType( Type::Qualifiers( ), "char16_t", false );
     473                strtype = new ast::TypeInstType( "char16_t", ast::TypeDecl::Dtype );
    441474                break;
    442           case 'U':
    443                 strtype = new TypeInstType( Type::Qualifiers( ), "char32_t", false );
     475        case 'U':
     476                strtype = new ast::TypeInstType( "char32_t", ast::TypeDecl::Dtype );
    444477                break;
    445           case 'L':
    446                 strtype = new TypeInstType( Type::Qualifiers( ), "wchar_t", false );
     478        case 'L':
     479                strtype = new ast::TypeInstType( "wchar_t", ast::TypeDecl::Dtype );
    447480                break;
    448           Default:                                                                                      // char default string type
    449           default:
    450                 strtype = new BasicType( Type::Qualifiers( ), BasicType::Char );
     481        Default:                                                                                        // char default string type
     482        default:
     483                strtype = new ast::BasicType( ast::BasicType::Char );
    451484        } // switch
    452         ArrayType * at = new ArrayType( noQualifiers, strtype,
    453                                                                         new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"'
    454                                                                         false, false );
    455         Expression * ret = new ConstantExpr( Constant( at, str, std::nullopt ) );
     485        ast::ArrayType * at = new ast::ArrayType(
     486                strtype,
     487                // Length is adjusted: +1 for '\0' and -2 for '"'
     488                ast::ConstantExpr::from_ulong( location, str.size() + 1 - 2 ),
     489                ast::FixedLen,
     490                ast::DynamicDim );
     491        ast::Expr * ret = new ast::ConstantExpr( location, at, str, std::nullopt );
    456492        if ( units.length() != 0 ) {
    457                 ret = new UntypedExpr( new NameExpr( units ), { ret } );
     493                ret = new ast::UntypedExpr( location,
     494                        new ast::NameExpr( location, units ),
     495                        { ret } );
    458496        } // if
    459497
     
    462500} // build_constantStr
    463501
    464 Expression * build_field_name_FLOATING_FRACTIONconstant( const string & str ) {
     502ast::Expr * build_field_name_FLOATING_FRACTIONconstant(
     503                const CodeLocation & location, const string & str ) {
    465504        if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) SemanticError( yylloc, "invalid tuple index " + str );
    466         Expression * ret = build_constantInteger( *new string( str.substr(1) ) );
     505        ast::Expr * ret = build_constantInteger( location,
     506                *new string( str.substr(1) ) );
    467507        delete &str;
    468508        return ret;
    469509} // build_field_name_FLOATING_FRACTIONconstant
    470510
    471 Expression * build_field_name_FLOATING_DECIMALconstant( const string & str ) {
     511ast::Expr * build_field_name_FLOATING_DECIMALconstant(
     512                const CodeLocation & location, const string & str ) {
    472513        if ( str[str.size() - 1] != '.' ) SemanticError( yylloc, "invalid tuple index " + str );
    473         Expression * ret = build_constantInteger( *new string( str.substr( 0, str.size()-1 ) ) );
     514        ast::Expr * ret = build_constantInteger(
     515                location, *new string( str.substr( 0, str.size()-1 ) ) );
    474516        delete &str;
    475517        return ret;
    476518} // build_field_name_FLOATING_DECIMALconstant
    477519
    478 Expression * build_field_name_FLOATINGconstant( const string & str ) {
     520ast::Expr * build_field_name_FLOATINGconstant( const CodeLocation & location,
     521                const string & str ) {
    479522        // str is of the form A.B -> separate at the . and return member expression
    480523        int a, b;
     
    482525        stringstream ss( str );
    483526        ss >> a >> dot >> b;
    484         UntypedMemberExpr * ret = new UntypedMemberExpr( new ConstantExpr( Constant::from_int( b ) ), new ConstantExpr( Constant::from_int( a ) ) );
     527        auto ret = new ast::UntypedMemberExpr( location,
     528                ast::ConstantExpr::from_int( location, b ),
     529                ast::ConstantExpr::from_int( location, a )
     530        );
    485531        delete &str;
    486532        return ret;
    487533} // build_field_name_FLOATINGconstant
    488534
    489 Expression * make_field_name_fraction_constants( Expression * fieldName, Expression * fracts ) {
    490         if ( fracts ) {
    491                 if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( fracts ) ) {
    492                         memberExpr->set_member( make_field_name_fraction_constants( fieldName, memberExpr->get_aggregate() ) );
    493                         return memberExpr;
    494                 } else {
    495                         return new UntypedMemberExpr( fracts, fieldName );
    496                 } // if
    497         } // if
    498         return fieldName;
     535ast::Expr * make_field_name_fraction_constants( const CodeLocation & location,
     536                ast::Expr * fieldName,
     537                ast::Expr * fracts ) {
     538        if ( nullptr == fracts ) {
     539                return fieldName;
     540        } else if ( auto memberExpr = dynamic_cast<ast::UntypedMemberExpr *>( fracts ) ) {
     541                memberExpr->member = make_field_name_fraction_constants( location,
     542                        fieldName,
     543                        ast::mutate( memberExpr->aggregate.get() ) );
     544                return memberExpr;
     545        } else {
     546                return new ast::UntypedMemberExpr( location, fracts, fieldName );
     547        } // if
    499548} // make_field_name_fraction_constants
    500549
    501 Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts ) {
    502         return make_field_name_fraction_constants( fieldName, maybeMoveBuild< Expression >( fracts ) );
     550ast::Expr * build_field_name_fraction_constants( const CodeLocation & location,
     551                ast::Expr * fieldName,
     552                ExpressionNode * fracts ) {
     553        return make_field_name_fraction_constants( location, fieldName, maybeMoveBuild( fracts ) );
    503554} // build_field_name_fraction_constants
    504555
    505 NameExpr * build_varref( const string * name ) {
    506         NameExpr * expr = new NameExpr( *name );
     556ast::NameExpr * build_varref( const CodeLocation & location,
     557                const string * name ) {
     558        ast::NameExpr * expr = new ast::NameExpr( location, *name );
    507559        delete name;
    508560        return expr;
    509561} // build_varref
    510562
    511 QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name ) {
    512         Declaration * newDecl = maybeBuild< Declaration >(decl_node);
    513         if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) {
    514                 const Type * t = newDeclWithType->get_type();
    515                 if ( t ) {
    516                         if ( const TypeInstType * typeInst = dynamic_cast<const TypeInstType *>( t ) ) {
    517                                 newDecl= new EnumDecl( typeInst->name );
     563ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location,
     564                const DeclarationNode * decl_node,
     565                const ast::NameExpr * name ) {
     566        ast::Decl * newDecl = maybeBuild( decl_node );
     567        if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) {
     568                if ( const ast::Type * t = newDeclWithType->get_type() ) {
     569                        if ( auto typeInst = dynamic_cast<const ast::TypeInstType *>( t ) ) {
     570                                newDecl = new ast::EnumDecl( location, typeInst->name );
    518571                        }
    519572                }
    520573        }
    521         return new QualifiedNameExpr( newDecl, name->name );
     574        return new ast::QualifiedNameExpr( location, newDecl, name->name );
    522575}
    523576
    524 QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl_node, const NameExpr * name ) {
    525         EnumDecl * newDecl = const_cast< EnumDecl * >( decl_node );
    526         return new QualifiedNameExpr( newDecl, name->name );
     577ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location,
     578                const ast::EnumDecl * decl,
     579                const ast::NameExpr * name ) {
     580        return new ast::QualifiedNameExpr( location, decl, name->name );
    527581}
    528582
    529 DimensionExpr * build_dimensionref( const string * name ) {
    530         DimensionExpr * expr = new DimensionExpr( *name );
     583ast::DimensionExpr * build_dimensionref( const CodeLocation & location,
     584                const string * name ) {
     585        ast::DimensionExpr * expr = new ast::DimensionExpr( location, *name );
    531586        delete name;
    532587        return expr;
     
    544599}; // OperName
    545600
    546 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node, CastExpr::CastKind kind ) {
    547         Type * targetType = maybeMoveBuildType( decl_node );
    548         if ( dynamic_cast< VoidType * >( targetType ) ) {
     601ast::Expr * build_cast( const CodeLocation & location,
     602                DeclarationNode * decl_node,
     603                ExpressionNode * expr_node,
     604                ast::CastExpr::CastKind kind ) {
     605        ast::Type * targetType = maybeMoveBuildType( decl_node );
     606        if ( dynamic_cast<ast::VoidType *>( targetType ) ) {
    549607                delete targetType;
    550                 return new CastExpr( maybeMoveBuild< Expression >(expr_node), false, kind );
     608                return new ast::CastExpr( location,
     609                        maybeMoveBuild( expr_node ),
     610                        ast::ExplicitCast, kind );
    551611        } else {
    552                 return new CastExpr( maybeMoveBuild< Expression >(expr_node), targetType, false, kind );
     612                return new ast::CastExpr( location,
     613                        maybeMoveBuild( expr_node ),
     614                        targetType,
     615                        ast::ExplicitCast, kind );
    553616        } // if
    554617} // build_cast
    555618
    556 Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node ) {
    557         return new KeywordCastExpr( maybeMoveBuild< Expression >(expr_node), target );
     619ast::Expr * build_keyword_cast( const CodeLocation & location,
     620                ast::AggregateDecl::Aggregate target,
     621                ExpressionNode * expr_node ) {
     622        return new ast::KeywordCastExpr( location,
     623                maybeMoveBuild( expr_node ),
     624                target
     625        );
    558626}
    559627
    560 Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) {
    561         return new VirtualCastExpr( maybeMoveBuild< Expression >( expr_node ), maybeMoveBuildType( decl_node ) );
     628ast::Expr * build_virtual_cast( const CodeLocation & location,
     629                DeclarationNode * decl_node,
     630                ExpressionNode * expr_node ) {
     631        return new ast::VirtualCastExpr( location,
     632                maybeMoveBuild( expr_node ),
     633                maybeMoveBuildType( decl_node )
     634        );
    562635} // build_virtual_cast
    563636
    564 Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member ) {
    565         return new UntypedMemberExpr( member, maybeMoveBuild< Expression >(expr_node) );
     637ast::Expr * build_fieldSel( const CodeLocation & location,
     638                ExpressionNode * expr_node,
     639                ast::Expr * member ) {
     640        return new ast::UntypedMemberExpr( location,
     641                member,
     642                maybeMoveBuild( expr_node )
     643        );
    566644} // build_fieldSel
    567645
    568 Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member ) {
    569         UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
     646ast::Expr * build_pfieldSel( const CodeLocation & location,
     647                ExpressionNode * expr_node,
     648                ast::Expr * member ) {
     649        auto deref = new ast::UntypedExpr( location,
     650                new ast::NameExpr( location, "*?" )
     651        );
    570652        deref->location = expr_node->location;
    571         deref->get_args().push_back( maybeMoveBuild< Expression >(expr_node) );
    572         UntypedMemberExpr * ret = new UntypedMemberExpr( member, deref );
     653        deref->args.push_back( maybeMoveBuild( expr_node ) );
     654        auto ret = new ast::UntypedMemberExpr( location, member, deref );
    573655        return ret;
    574656} // build_pfieldSel
    575657
    576 Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member ) {
    577         Expression * ret = new UntypedOffsetofExpr( maybeMoveBuildType( decl_node ), member->get_name() );
     658ast::Expr * build_offsetOf( const CodeLocation & location,
     659                DeclarationNode * decl_node,
     660                ast::NameExpr * member ) {
     661        ast::Expr * ret = new ast::UntypedOffsetofExpr( location,
     662                maybeMoveBuildType( decl_node ),
     663                member->name
     664        );
     665        ret->result = new ast::BasicType( ast::BasicType::LongUnsignedInt );
    578666        delete member;
    579667        return ret;
    580668} // build_offsetOf
    581669
    582 Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind ) {
    583         return new LogicalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), notZeroExpr( maybeMoveBuild< Expression >(expr_node2) ), kind );
     670ast::Expr * build_and_or( const CodeLocation & location,
     671                ExpressionNode * expr_node1,
     672                ExpressionNode * expr_node2,
     673                ast::LogicalFlag flag ) {
     674        return new ast::LogicalExpr( location,
     675                notZeroExpr( maybeMoveBuild( expr_node1 ) ),
     676                notZeroExpr( maybeMoveBuild( expr_node2 ) ),
     677                flag
     678        );
    584679} // build_and_or
    585680
    586 Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node ) {
    587         list< Expression * > args;
    588         args.push_back( maybeMoveBuild< Expression >(expr_node) );
    589         return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
     681ast::Expr * build_unary_val( const CodeLocation & location,
     682                OperKinds op,
     683                ExpressionNode * expr_node ) {
     684        std::vector<ast::ptr<ast::Expr>> args;
     685        args.push_back( maybeMoveBuild( expr_node ) );
     686        return new ast::UntypedExpr( location,
     687                new ast::NameExpr( location, OperName[ (int)op ] ),
     688                std::move( args )
     689        );
    590690} // build_unary_val
    591691
    592 Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) {
    593         list< Expression * > args;
    594         args.push_back(  maybeMoveBuild< Expression >(expr_node) ); // xxx -- this is exactly the same as the val case now, refactor this code.
    595         return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
    596 } // build_unary_ptr
    597 
    598 Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) {
    599         list< Expression * > args;
    600         args.push_back( maybeMoveBuild< Expression >(expr_node1) );
    601         args.push_back( maybeMoveBuild< Expression >(expr_node2) );
    602         return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
     692ast::Expr * build_binary_val( const CodeLocation & location,
     693                OperKinds op,
     694                ExpressionNode * expr_node1,
     695                ExpressionNode * expr_node2 ) {
     696        std::vector<ast::ptr<ast::Expr>> args;
     697        args.push_back( maybeMoveBuild( expr_node1 ) );
     698        args.push_back( maybeMoveBuild( expr_node2 ) );
     699        return new ast::UntypedExpr( location,
     700                new ast::NameExpr( location, OperName[ (int)op ] ),
     701                std::move( args )
     702        );
    603703} // build_binary_val
    604704
    605 Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) {
    606         list< Expression * > args;
    607         args.push_back( maybeMoveBuild< Expression >(expr_node1) );
    608         args.push_back( maybeMoveBuild< Expression >(expr_node2) );
    609         return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
    610 } // build_binary_ptr
    611 
    612 Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 ) {
    613         return new ConditionalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), maybeMoveBuild< Expression >(expr_node2), maybeMoveBuild< Expression >(expr_node3) );
     705ast::Expr * build_cond( const CodeLocation & location,
     706                ExpressionNode * expr_node1,
     707                ExpressionNode * expr_node2,
     708                ExpressionNode * expr_node3 ) {
     709        return new ast::ConditionalExpr( location,
     710                notZeroExpr( maybeMoveBuild( expr_node1 ) ),
     711                maybeMoveBuild( expr_node2 ),
     712                maybeMoveBuild( expr_node3 )
     713        );
    614714} // build_cond
    615715
    616 Expression * build_tuple( ExpressionNode * expr_node ) {
    617         list< Expression * > exprs;
     716ast::Expr * build_tuple( const CodeLocation & location,
     717                ExpressionNode * expr_node ) {
     718        std::vector<ast::ptr<ast::Expr>> exprs;
    618719        buildMoveList( expr_node, exprs );
    619         return new UntypedTupleExpr( exprs );;
     720        return new ast::UntypedTupleExpr( location, std::move( exprs ) );
    620721} // build_tuple
    621722
    622 Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node ) {
    623         list< Expression * > args;
     723ast::Expr * build_func( const CodeLocation & location,
     724                ExpressionNode * function,
     725                ExpressionNode * expr_node ) {
     726        std::vector<ast::ptr<ast::Expr>> args;
    624727        buildMoveList( expr_node, args );
    625         return new UntypedExpr( maybeMoveBuild< Expression >(function), args );
     728        return new ast::UntypedExpr( location,
     729                maybeMoveBuild( function ),
     730                std::move( args )
     731        );
    626732} // build_func
    627733
    628 Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids ) {
    629         Declaration * newDecl = maybeBuild< Declaration >(decl_node); // compound literal type
    630         if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) { // non-sue compound-literal type
    631                 return new CompoundLiteralExpr( newDeclWithType->get_type(), maybeMoveBuild< Initializer >(kids) );
     734ast::Expr * build_compoundLiteral( const CodeLocation & location,
     735                DeclarationNode * decl_node,
     736                InitializerNode * kids ) {
     737        // compound literal type
     738        ast::Decl * newDecl = maybeBuild( decl_node );
     739        // non-sue compound-literal type
     740        if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) {
     741                return new ast::CompoundLiteralExpr( location,
     742                        newDeclWithType->get_type(),
     743                        maybeMoveBuild( kids ) );
    632744        // these types do not have associated type information
    633         } else if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( newDecl )  ) {
    634                 if ( newDeclStructDecl->has_body() ) {
    635                         return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl ), maybeMoveBuild< Initializer >(kids) );
     745        } else if ( auto newDeclStructDecl = dynamic_cast<ast::StructDecl *>( newDecl ) ) {
     746                if ( newDeclStructDecl->body ) {
     747                        return new ast::CompoundLiteralExpr( location,
     748                                new ast::StructInstType( newDeclStructDecl ),
     749                                maybeMoveBuild( kids ) );
    636750                } else {
    637                         return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybeMoveBuild< Initializer >(kids) );
    638                 } // if
    639         } else if ( UnionDecl * newDeclUnionDecl = dynamic_cast< UnionDecl * >( newDecl )  ) {
    640                 if ( newDeclUnionDecl->has_body() ) {
    641                         return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl ), maybeMoveBuild< Initializer >(kids) );
     751                        return new ast::CompoundLiteralExpr( location,
     752                                new ast::StructInstType( newDeclStructDecl->name ),
     753                                maybeMoveBuild( kids ) );
     754                } // if
     755        } else if ( auto newDeclUnionDecl = dynamic_cast<ast::UnionDecl *>( newDecl )  ) {
     756                if ( newDeclUnionDecl->body ) {
     757                        return new ast::CompoundLiteralExpr( location,
     758                                new ast::UnionInstType( newDeclUnionDecl ),
     759                                maybeMoveBuild( kids ) );
    642760                } else {
    643                         return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybeMoveBuild< Initializer >(kids) );
    644                 } // if
    645         } else if ( EnumDecl * newDeclEnumDecl = dynamic_cast< EnumDecl * >( newDecl )  ) {
    646                 if ( newDeclEnumDecl->has_body() ) {
    647                         return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl ), maybeMoveBuild< Initializer >(kids) );
     761                        return new ast::CompoundLiteralExpr( location,
     762                                new ast::UnionInstType( newDeclUnionDecl->name ),
     763                                maybeMoveBuild( kids ) );
     764                } // if
     765        } else if ( auto newDeclEnumDecl = dynamic_cast<ast::EnumDecl *>( newDecl )  ) {
     766                if ( newDeclEnumDecl->body ) {
     767                        return new ast::CompoundLiteralExpr( location,
     768                                new ast::EnumInstType( newDeclEnumDecl ),
     769                                maybeMoveBuild( kids ) );
    648770                } else {
    649                         return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild< Initializer >(kids) );
     771                        return new ast::CompoundLiteralExpr( location,
     772                                new ast::EnumInstType( newDeclEnumDecl->name ),
     773                                maybeMoveBuild( kids ) );
    650774                } // if
    651775        } else {
     
    656780// Local Variables: //
    657781// tab-width: 4 //
    658 // mode: c++ //
    659 // compile-command: "make install" //
    660782// End: //
  • src/Parser/InitializerNode.cc

    r34b4268 r24d6572  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 13:20:24 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 28 23:27:20 2017
    13 // Update Count     : 26
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Apr  4 11:18:00 2023
     13// Update Count     : 27
    1414//
     15
     16#include "InitializerNode.h"
    1517
    1618#include <iostream>                // for operator<<, ostream, basic_ostream
     
    1820#include <string>                  // for operator<<, string
    1921
     22#include "AST/Expr.hpp"            // for Expr
     23#include "AST/Init.hpp"            // for Designator, Init, ListInit, Sing...
     24#include "Common/SemanticError.h"  // for SemanticError
     25#include "Common/utility.h"        // for maybeBuild
     26#include "ExpressionNode.h"        // for ExpressionNode
     27#include "DeclarationNode.h"       // for buildList
     28
    2029using namespace std;
    2130
    22 #include "Common/SemanticError.h"  // for SemanticError
    23 #include "Common/utility.h"        // for maybeBuild
    24 #include "ParseNode.h"             // for InitializerNode, ExpressionNode
    25 #include "SynTree/Expression.h"    // for Expression
    26 #include "SynTree/Initializer.h"   // for Initializer, ListInit, SingleInit
     31static ast::ConstructFlag toConstructFlag( bool maybeConstructed ) {
     32        return maybeConstructed ? ast::MaybeConstruct : ast::NoConstruct;
     33}
    2734
    2835InitializerNode::InitializerNode( ExpressionNode * _expr, bool aggrp, ExpressionNode * des )
     
    3340        if ( kids )
    3441                set_last( nullptr );
    35 } // InitializerNode::InitializerNode
     42} // InitializerNode::InitializerNode
    3643
    3744InitializerNode::InitializerNode( InitializerNode * init, bool aggrp, ExpressionNode * des )
     
    8592} // InitializerNode::printOneLine
    8693
    87 Initializer * InitializerNode::build() const {
     94ast::Init * InitializerNode::build() const {
    8895        assertf( ! isDelete, "Should not build delete stmt InitializerNode" );
    8996        if ( aggregate ) {
    9097                // steal designators from children
    91                 std::list< Designation * > designlist;
     98                std::vector<ast::ptr<ast::Designation>> designlist;
    9299                InitializerNode * child = next_init();
    93                 for ( ; child != nullptr; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) {
    94                         std::list< Expression * > desList;
    95                         buildList< Expression, ExpressionNode >( child->designator, desList );
    96                         designlist.push_back( new Designation( desList ) );
     100                for ( ; child != nullptr ; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) {
     101                        std::deque<ast::ptr<ast::Expr>> desList;
     102                        buildList( child->designator, desList );
     103                        designlist.push_back(
     104                                new ast::Designation( location, std::move( desList ) ) );
    97105                } // for
    98                 std::list< Initializer * > initlist;
    99                 buildList< Initializer, InitializerNode >( next_init(), initlist );
    100                 return new ListInit( initlist, designlist, maybeConstructed );
    101         } else {
    102                 if ( get_expression() ) {
    103                         assertf( get_expression()->expr, "The expression of initializer must have value" );
    104                         return new SingleInit( maybeBuild< Expression >( get_expression() ), maybeConstructed );
    105                 } // if
     106                std::vector<ast::ptr<ast::Init>> initlist;
     107                buildList( next_init(), initlist );
     108                return new ast::ListInit( location,
     109                        std::move( initlist ),
     110                        std::move( designlist ),
     111                        toConstructFlag( maybeConstructed )
     112                );
     113        } else if ( get_expression() ) {
     114                assertf( get_expression()->expr, "The expression of initializer must have value" );
     115                return new ast::SingleInit( location,
     116                        maybeBuild( get_expression() ),
     117                        toConstructFlag( maybeConstructed )
     118                );
    106119        } // if
    107120        return nullptr;
  • src/Parser/ParseNode.h

    r34b4268 r24d6572  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 13:28:16 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Nov  2 21:27:07 2022
    13 // Update Count     : 939
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Apr  3 17:55:00 2023
     13// Update Count     : 942
    1414//
    1515
     
    2424#include <string>                  // for string
    2525
     26#include "AST/Expr.hpp"            // for Expr, NameExpr LogicalFlag
     27#include "AST/Fwd.hpp"             // for ptr, Decl, DeclWithType,
     28#include "AST/Stmt.hpp"            // for Stmt
    2629#include "Common/CodeLocation.h"   // for CodeLocation
    2730#include "Common/SemanticError.h"  // for SemanticError
    2831#include "Common/UniqueName.h"     // for UniqueName
    29 #include "Common/utility.h"        // for maybeClone, maybeBuild
    30 #include "SynTree/LinkageSpec.h"   // for Spec
    31 #include "SynTree/Declaration.h"   // for Aggregate
    32 #include "SynTree/Expression.h"    // for Expression, ConstantExpr (ptr only)
    33 #include "SynTree/Label.h"         // for Label
    34 #include "SynTree/Statement.h"     // for Statement, BranchStmt, BranchStmt:...
    35 #include "SynTree/Type.h"          // for Type, Type::FuncSpecifiers, Type::...
     32#include "Common/utility.h"        // for maybeClone
     33#include "Parser/parserutility.h"  // for maybeBuild, maybeCopy
    3634
    3735class Attribute;
     
    4038class DeclarationWithType;
    4139class Initializer;
     40class InitializerNode;
    4241class ExpressionNode;
    4342struct StatementNode;
     
    8281}; // ParseNode
    8382
    84 //##############################################################################
    85 
    86 class InitializerNode : public ParseNode {
    87   public:
    88         InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr );
    89         InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );
    90         InitializerNode( bool isDelete );
    91         ~InitializerNode();
    92         virtual InitializerNode * clone() const { assert( false ); return nullptr; }
    93 
    94         ExpressionNode * get_expression() const { return expr; }
    95 
    96         InitializerNode * set_designators( ExpressionNode * des ) { designator = des; return this; }
    97         ExpressionNode * get_designators() const { return designator; }
    98 
    99         InitializerNode * set_maybeConstructed( bool value ) { maybeConstructed = value; return this; }
    100         bool get_maybeConstructed() const { return maybeConstructed; }
    101 
    102         bool get_isDelete() const { return isDelete; }
    103 
    104         InitializerNode * next_init() const { return kids; }
    105 
    106         void print( std::ostream & os, int indent = 0 ) const;
    107         void printOneLine( std::ostream & ) const;
    108 
    109         virtual Initializer * build() const;
    110   private:
    111         ExpressionNode * expr;
    112         bool aggregate;
    113         ExpressionNode * designator;                                            // may be list
    114         InitializerNode * kids;
    115         bool maybeConstructed;
    116         bool isDelete;
    117 }; // InitializerNode
    118 
    119 //##############################################################################
    120 
    121 class ExpressionNode final : public ParseNode {
    122   public:
    123         ExpressionNode( Expression * expr = nullptr ) : expr( expr ) {}
    124         virtual ~ExpressionNode() {}
    125         virtual ExpressionNode * clone() const override { return expr ? static_cast<ExpressionNode*>((new ExpressionNode( expr->clone() ))->set_next( maybeClone( get_next() ) )) : nullptr; }
    126 
    127         bool get_extension() const { return extension; }
    128         ExpressionNode * set_extension( bool exten ) { extension = exten; return this; }
    129 
    130         virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {
    131                 os << expr.get();
    132         }
    133         void printOneLine( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const {}
    134 
    135         template<typename T>
    136         bool isExpressionType() const { return nullptr != dynamic_cast<T>(expr.get()); }
    137 
    138         Expression * build() const { return const_cast<ExpressionNode *>(this)->expr.release(); }
    139 
    140         std::unique_ptr<Expression> expr;                                       // public because of lifetime implications
    141   private:
    142         bool extension = false;
    143 }; // ExpressionNode
    144 
    145 template< typename T >
    146 struct maybeBuild_t< Expression, T > {
    147         static inline Expression * doit( const T * orig ) {
    148                 if ( orig ) {
    149                         Expression * p = orig->build();
    150                         p->set_extension( orig->get_extension() );
    151                         p->location = orig->location;
    152                         return p;
    153                 } else {
    154                         return nullptr;
    155                 } // if
    156         }
    157 };
    158 
    15983// Must harmonize with OperName.
    16084enum class OperKinds {
     
    17296
    17397struct LabelNode {
    174         std::list< Label > labels;
     98        std::vector<ast::Label> labels;
    17599};
    176100
    177 Expression * build_constantInteger( std::string & str ); // these 4 routines modify the string
    178 Expression * build_constantFloat( std::string & str );
    179 Expression * build_constantChar( std::string & str );
    180 Expression * build_constantStr( std::string & str );
    181 Expression * build_field_name_FLOATING_FRACTIONconstant( const std::string & str );
    182 Expression * build_field_name_FLOATING_DECIMALconstant( const std::string & str );
    183 Expression * build_field_name_FLOATINGconstant( const std::string & str );
    184 Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts );
    185 
    186 NameExpr * build_varref( const std::string * name );
    187 QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name );
    188 QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl, const NameExpr * name );
    189 DimensionExpr * build_dimensionref( const std::string * name );
    190 
    191 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node, CastExpr::CastKind kind = CastExpr::Default );
    192 Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node );
    193 Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node );
    194 Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member );
    195 Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member );
    196 Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member );
    197 Expression * build_and( ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
    198 Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind );
    199 Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node );
    200 Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node );
    201 Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
    202 Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );
    203 Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 );
    204 Expression * build_tuple( ExpressionNode * expr_node = nullptr );
    205 Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node );
    206 Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids );
    207 
    208 //##############################################################################
    209 
    210 struct TypeData;
    211 
    212 struct DeclarationNode : public ParseNode {
    213         // These enumerations must harmonize with their names in DeclarationNode.cc.
    214         enum BasicType { Void, Bool, Char, Int, Int128,
    215                                          Float, Double, LongDouble, uuFloat80, uuFloat128,
    216                                          uFloat16, uFloat32, uFloat32x, uFloat64, uFloat64x, uFloat128, uFloat128x, NoBasicType };
    217         static const char * basicTypeNames[];
    218         enum ComplexType { Complex, NoComplexType, Imaginary }; // Imaginary unsupported => parse, but make invisible and print error message
    219         static const char * complexTypeNames[];
    220         enum Signedness { Signed, Unsigned, NoSignedness };
    221         static const char * signednessNames[];
    222         enum Length { Short, Long, LongLong, NoLength };
    223         static const char * lengthNames[];
    224         enum BuiltinType { Valist, AutoType, Zero, One, NoBuiltinType };
    225         static const char * builtinTypeNames[];
    226 
    227         static DeclarationNode * newStorageClass( Type::StorageClasses );
    228         static DeclarationNode * newFuncSpecifier( Type::FuncSpecifiers );
    229         static DeclarationNode * newTypeQualifier( Type::Qualifiers );
    230         static DeclarationNode * newBasicType( BasicType );
    231         static DeclarationNode * newComplexType( ComplexType );
    232         static DeclarationNode * newSignedNess( Signedness );
    233         static DeclarationNode * newLength( Length );
    234         static DeclarationNode * newBuiltinType( BuiltinType );
    235         static DeclarationNode * newForall( DeclarationNode * );
    236         static DeclarationNode * newFromTypedef( const std::string * );
    237         static DeclarationNode * newFromGlobalScope();
    238         static DeclarationNode * newQualifiedType( DeclarationNode *, DeclarationNode * );
    239         static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );
    240         static DeclarationNode * newAggregate( AggregateDecl::Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );
    241         static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base = nullptr, EnumHiding hiding = EnumHiding::Visible );
    242         static DeclarationNode * newEnumConstant( const std::string * name, ExpressionNode * constant );
    243         static DeclarationNode * newEnumValueGeneric( const std::string * name, InitializerNode * init );
    244         static DeclarationNode * newEnumInLine( const std::string name );
    245         static DeclarationNode * newName( const std::string * );
    246         static DeclarationNode * newFromTypeGen( const std::string *, ExpressionNode * params );
    247         static DeclarationNode * newTypeParam( TypeDecl::Kind, const std::string * );
    248         static DeclarationNode * newTrait( const std::string * name, DeclarationNode * params, DeclarationNode * asserts );
    249         static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );
    250         static DeclarationNode * newTypeDecl( const std::string * name, DeclarationNode * typeParams );
    251         static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind );
    252         static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic );
    253         static DeclarationNode * newVarArray( DeclarationNode * qualifiers );
    254         static DeclarationNode * newBitfield( ExpressionNode * size );
    255         static DeclarationNode * newTuple( DeclarationNode * members );
    256         static DeclarationNode * newTypeof( ExpressionNode * expr, bool basetypeof = false );
    257         static DeclarationNode * newVtableType( DeclarationNode * expr );
    258         static DeclarationNode * newAttribute( const std::string *, ExpressionNode * expr = nullptr ); // gcc attributes
    259         static DeclarationNode * newDirectiveStmt( StatementNode * stmt ); // gcc external directive statement
    260         static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement
    261         static DeclarationNode * newStaticAssert( ExpressionNode * condition, Expression * message );
    262 
    263         DeclarationNode();
    264         ~DeclarationNode();
    265         DeclarationNode * clone() const override;
    266 
    267         DeclarationNode * addQualifiers( DeclarationNode * );
    268         void checkQualifiers( const TypeData *, const TypeData * );
    269         void checkSpecifiers( DeclarationNode * );
    270         DeclarationNode * copySpecifiers( DeclarationNode * );
    271         DeclarationNode * addType( DeclarationNode * );
    272         DeclarationNode * addTypedef();
    273         DeclarationNode * addEnumBase( DeclarationNode * );
    274         DeclarationNode * addAssertions( DeclarationNode * );
    275         DeclarationNode * addName( std::string * );
    276         DeclarationNode * addAsmName( DeclarationNode * );
    277         DeclarationNode * addBitfield( ExpressionNode * size );
    278         DeclarationNode * addVarArgs();
    279         DeclarationNode * addFunctionBody( StatementNode * body, ExpressionNode * with = nullptr );
    280         DeclarationNode * addOldDeclList( DeclarationNode * list );
    281         DeclarationNode * setBase( TypeData * newType );
    282         DeclarationNode * copyAttribute( DeclarationNode * attr );
    283         DeclarationNode * addPointer( DeclarationNode * qualifiers );
    284         DeclarationNode * addArray( DeclarationNode * array );
    285         DeclarationNode * addNewPointer( DeclarationNode * pointer );
    286         DeclarationNode * addNewArray( DeclarationNode * array );
    287         DeclarationNode * addParamList( DeclarationNode * list );
    288         DeclarationNode * addIdList( DeclarationNode * list ); // old-style functions
    289         DeclarationNode * addInitializer( InitializerNode * init );
    290         DeclarationNode * addTypeInitializer( DeclarationNode * init );
    291 
    292         DeclarationNode * cloneType( std::string * newName );
    293         DeclarationNode * cloneBaseType( DeclarationNode * newdecl );
    294 
    295         DeclarationNode * appendList( DeclarationNode * node ) {
    296                 return (DeclarationNode *)set_last( node );
    297         }
    298 
    299         virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;
    300         virtual void printList( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;
    301 
    302         Declaration * build() const;
    303         Type * buildType() const;
    304 
    305         LinkageSpec::Spec get_linkage() const { return linkage; }
    306         DeclarationNode * extractAggregate() const;
    307         bool has_enumeratorValue() const { return (bool)enumeratorValue; }
    308         ExpressionNode * consume_enumeratorValue() const { return const_cast<DeclarationNode *>(this)->enumeratorValue.release(); }
    309 
    310         bool get_extension() const { return extension; }
    311         DeclarationNode * set_extension( bool exten ) { extension = exten; return this; }
    312 
    313         bool get_inLine() const { return inLine; }
    314         DeclarationNode * set_inLine( bool inL ) { inLine = inL; return this; }
    315 
    316         DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }
    317 
    318         struct Variable_t {
    319 //              const std::string * name;
    320                 TypeDecl::Kind tyClass;
    321                 DeclarationNode * assertions;
    322                 DeclarationNode * initializer;
    323         };
    324         Variable_t variable;
    325 
    326         struct Attr_t {
    327 //              const std::string * name;
    328                 ExpressionNode * expr;
    329                 DeclarationNode * type;
    330         };
    331         Attr_t attr;
    332 
    333         struct StaticAssert_t {
    334                 ExpressionNode * condition;
    335                 Expression * message;
    336         };
    337         StaticAssert_t assert;
    338 
    339         BuiltinType builtin = NoBuiltinType;
    340 
    341         TypeData * type = nullptr;
    342 
    343         bool inLine = false;
    344         bool enumInLine = false;
    345         Type::FuncSpecifiers funcSpecs;
    346         Type::StorageClasses storageClasses;
    347 
    348         ExpressionNode * bitfieldWidth = nullptr;
    349         std::unique_ptr<ExpressionNode> enumeratorValue;
    350         bool hasEllipsis = false;
    351         LinkageSpec::Spec linkage;
    352         Expression * asmName = nullptr;
    353         std::list< Attribute * > attributes;
    354         InitializerNode * initializer = nullptr;
    355         bool extension = false;
    356         std::string error;
    357         StatementNode * asmStmt = nullptr;
    358         StatementNode * directiveStmt = nullptr;
    359 
    360         static UniqueName anonymous;
    361 }; // DeclarationNode
    362 
    363 Type * buildType( TypeData * type );
    364 
    365 static inline Type * maybeMoveBuildType( const DeclarationNode * orig ) {
    366         Type * ret = orig ? orig->buildType() : nullptr;
    367         delete orig;
    368         return ret;
    369 }
    370 
    371 //##############################################################################
    372 
    373 struct StatementNode final : public ParseNode {
    374         StatementNode() { stmt = nullptr; }
    375         StatementNode( Statement * stmt ) : stmt( stmt ) {}
    376         StatementNode( DeclarationNode * decl );
    377         virtual ~StatementNode() {}
    378 
    379         virtual StatementNode * clone() const final { assert( false ); return nullptr; }
    380         Statement * build() const { return const_cast<StatementNode *>(this)->stmt.release(); }
    381 
    382         virtual StatementNode * add_label( const std::string * name, DeclarationNode * attr = nullptr ) {
    383                 stmt->get_labels().emplace_back( * name, nullptr, attr ? std::move( attr->attributes ) : std::list< Attribute * > {} );
    384                 delete attr;
    385                 delete name;
    386                 return this;
    387         }
    388 
    389         virtual StatementNode * append_last_case( StatementNode * );
    390 
    391         virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {
    392                 os << stmt.get() << std::endl;
    393         }
    394 
    395         std::unique_ptr<Statement> stmt;
    396 }; // StatementNode
    397 
    398 Statement * build_expr( ExpressionNode * ctl );
    399 
    400 struct CondCtl {
    401         CondCtl( DeclarationNode * decl, ExpressionNode * condition ) :
    402                 init( decl ? new StatementNode( decl ) : nullptr ), condition( condition ) {}
    403 
    404         StatementNode * init;
    405         ExpressionNode * condition;
    406 };
    407 
    408 struct ForCtrl {
    409         ForCtrl( ExpressionNode * expr, ExpressionNode * condition, ExpressionNode * change ) :
    410                 init( new StatementNode( build_expr( expr ) ) ), condition( condition ), change( change ) {}
    411         ForCtrl( DeclarationNode * decl, ExpressionNode * condition, ExpressionNode * change ) :
    412                 init( new StatementNode( decl ) ), condition( condition ), change( change ) {}
    413 
    414         StatementNode * init;
    415         ExpressionNode * condition;
    416         ExpressionNode * change;
    417 };
    418 
    419 Expression * build_if_control( CondCtl * ctl, std::list< Statement * > & init );
    420 Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ );
    421 Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );
    422 Statement * build_case( ExpressionNode * ctl );
    423 Statement * build_default();
    424 Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );
    425 Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );
    426 Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ = nullptr );
    427 Statement * build_branch( BranchStmt::Type kind );
    428 Statement * build_branch( std::string * identifier, BranchStmt::Type kind );
    429 Statement * build_computedgoto( ExpressionNode * ctl );
    430 Statement * build_return( ExpressionNode * ctl );
    431 Statement * build_throw( ExpressionNode * ctl );
    432 Statement * build_resume( ExpressionNode * ctl );
    433 Statement * build_resume_at( ExpressionNode * ctl , ExpressionNode * target );
    434 Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ );
    435 Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body );
    436 Statement * build_finally( StatementNode * stmt );
    437 Statement * build_compound( StatementNode * first );
    438 StatementNode * maybe_build_compound( StatementNode * first );
    439 Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr );
    440 Statement * build_directive( std::string * directive );
    441 SuspendStmt * build_suspend( StatementNode *, SuspendStmt::Type = SuspendStmt::None);
    442 WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when );
    443 WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when, WaitForStmt * existing );
    444 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when );
    445 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_stmt, ExpressionNode * else_when );
    446 Statement * build_with( ExpressionNode * exprs, StatementNode * stmt );
    447 Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt );
    448 
    449 //##############################################################################
    450 
    451 template< typename SynTreeType, typename NodeType, template< typename, typename...> class Container, typename... Args >
    452 void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > & outputList ) {
    453         SemanticErrorException errors;
    454         std::back_insert_iterator< Container< SynTreeType *, Args... > > out( outputList );
    455         const NodeType * cur = firstNode;
    456 
    457         while ( cur ) {
    458                 try {
    459                         SynTreeType * result = dynamic_cast< SynTreeType * >( maybeBuild< typename std::pointer_traits< decltype(cur->build())>::element_type >( cur ) );
    460                         if ( result ) {
    461                                 result->location = cur->location;
    462                                 * out++ = result;
    463                         } else {
    464                                 SemanticError( cur->location, "type specifier declaration in forall clause is currently unimplemented." );
    465                         } // if
    466                 } catch( SemanticErrorException & e ) {
    467                         errors.append( e );
    468                 } // try
    469                 const ParseNode * temp = (cur->get_next());
    470                 cur = dynamic_cast< const NodeType * >( temp ); // should not return nullptr
    471                 if ( ! cur && temp ) {                                                  // non-homogeneous nodes ?
    472                         SemanticError( temp->location, "internal error, non-homogeneous nodes founds in buildList processing." );
    473                 } // if
    474         } // while
    475         if ( ! errors.isEmpty() ) {
    476                 throw errors;
    477         } // if
    478 }
    479 
    480 // in DeclarationNode.cc
    481 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList );
    482 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList );
    483 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList );
    484 
    485 template< typename SynTreeType, typename NodeType >
    486 void buildMoveList( const NodeType * firstNode, std::list< SynTreeType * > & outputList ) {
    487         buildList( firstNode, outputList );
    488         delete firstNode;
    489 }
    490 
    491 // in ParseNode.cc
    492101std::ostream & operator<<( std::ostream & out, const ParseNode * node );
    493102
  • src/Parser/ParserTypes.h

    r34b4268 r24d6572  
    44// The contents of this file are covered under the licence agreement in the
    55// file "LICENCE" distributed with Cforall.
    6 // 
    7 // parser.hh -- 
    8 // 
     6//
     7// parser.hh --
     8//
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Sep 22 08:58:10 2001
  • src/Parser/StatementNode.cc

    r34b4268 r24d6572  
    1010// Author           : Rodolfo G. Esteves
    1111// Created On       : Sat May 16 14:59:41 2015
    12 // Last Modified By : Peter A. Buhr
    13 // Last Modified On : Wed Feb  2 20:29:30 2022
    14 // Update Count     : 425
     12// Last Modified By : Andrew Beach
     13// Last Modified On : Tue Apr 11 10:16:00 2023
     14// Update Count     : 428
    1515//
    1616
     17#include "StatementNode.h"
     18
    1719#include <cassert>                 // for assert, strict_dynamic_cast, assertf
    18 #include <list>                    // for list
    1920#include <memory>                  // for unique_ptr
    2021#include <string>                  // for string
    2122
     23#include "AST/Label.hpp"           // for Label
     24#include "AST/Stmt.hpp"            // for Stmt, AsmStmt, BranchStmt, CaseCla...
    2225#include "Common/SemanticError.h"  // for SemanticError
    2326#include "Common/utility.h"        // for maybeMoveBuild, maybeBuild
    24 #include "ParseNode.h"             // for StatementNode, ExpressionNode, bui...
    25 #include "SynTree/Expression.h"    // for Expression, ConstantExpr
    26 #include "SynTree/Label.h"         // for Label, noLabels
    27 #include "SynTree/Declaration.h"
    28 #include "SynTree/Statement.h"     // for Statement, BranchStmt, CaseStmt
     27#include "DeclarationNode.h"       // for DeclarationNode
     28#include "ExpressionNode.h"        // for ExpressionNode
    2929#include "parserutility.h"         // for notZeroExpr
    3030
     
    3333using namespace std;
    3434
     35// Some helpers for cases that really want a single node but check for lists.
     36static const ast::Stmt * buildMoveSingle( StatementNode * node ) {
     37        std::vector<ast::ptr<ast::Stmt>> list;
     38        buildMoveList( node, list );
     39        assertf( list.size() == 1, "CFA Internal Error: Extra/Missing Nodes" );
     40        return list.front().release();
     41}
     42
     43static const ast::Stmt * buildMoveOptional( StatementNode * node ) {
     44        std::vector<ast::ptr<ast::Stmt>> list;
     45        buildMoveList( node, list );
     46        assertf( list.size() <= 1, "CFA Internal Error: Extra Nodes" );
     47        return list.empty() ? nullptr : list.front().release();
     48}
    3549
    3650StatementNode::StatementNode( DeclarationNode * decl ) {
     
    3852        DeclarationNode * agg = decl->extractAggregate();
    3953        if ( agg ) {
    40                 StatementNode * nextStmt = new StatementNode( new DeclStmt( maybeBuild< Declaration >( decl ) ) );
     54                StatementNode * nextStmt = new StatementNode(
     55                        new ast::DeclStmt( decl->location, maybeBuild( decl ) ) );
    4156                set_next( nextStmt );
    4257                if ( decl->get_next() ) {
     
    5166                agg = decl;
    5267        } // if
    53         stmt.reset( new DeclStmt( maybeMoveBuild< Declaration >(agg) ) );
     68        // Local copy to avoid accessing the pointer after it is moved from.
     69        CodeLocation declLocation = agg->location;
     70        stmt.reset( new ast::DeclStmt( declLocation, maybeMoveBuild( agg ) ) );
    5471} // StatementNode::StatementNode
    5572
    56 StatementNode * StatementNode::append_last_case( StatementNode * stmt ) {
    57         StatementNode * prev = this;
     73StatementNode * StatementNode::add_label(
     74                const CodeLocation & location,
     75                const std::string * name,
     76                DeclarationNode * attr ) {
     77        stmt->labels.emplace_back( location,
     78                *name,
     79                attr ? std::move( attr->attributes )
     80                        : std::vector<ast::ptr<ast::Attribute>>{} );
     81        delete attr;
     82        delete name;
     83        return this;
     84}
     85
     86ClauseNode * ClauseNode::append_last_case( StatementNode * stmt ) {
     87        ClauseNode * prev = this;
    5888        // find end of list and maintain previous pointer
    59         for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) {
    60                 StatementNode * node = strict_dynamic_cast< StatementNode * >(curr);
    61                 assert( dynamic_cast< CaseStmt * >(node->stmt.get()) );
     89        for ( ClauseNode * curr = prev; curr != nullptr; curr = (ClauseNode *)curr->get_next() ) {
     90                ClauseNode * node = strict_dynamic_cast< ClauseNode * >(curr);
     91                assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) );
    6292                prev = curr;
    6393        } // for
     94        ClauseNode * node = dynamic_cast< ClauseNode * >(prev);
    6495        // convert from StatementNode list to Statement list
    65         StatementNode * node = dynamic_cast< StatementNode * >(prev);
    66         list< Statement * > stmts;
     96        std::vector<ast::ptr<ast::Stmt>> stmts;
    6797        buildMoveList( stmt, stmts );
    6898        // splice any new Statements to end of current Statements
    69         CaseStmt * caseStmt = dynamic_cast< CaseStmt * >(node->stmt.get());
    70         caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts );
     99        auto caseStmt = strict_dynamic_cast<ast::CaseClause *>( node->clause.get() );
     100        for ( auto const & newStmt : stmts ) {
     101                caseStmt->stmts.emplace_back( newStmt );
     102        }
     103        stmts.clear();
    71104        return this;
    72 } // StatementNode::append_last_case
    73 
    74 Statement * build_expr( ExpressionNode * ctl ) {
    75         Expression * e = maybeMoveBuild< Expression >( ctl );
    76 
    77         if ( e ) return new ExprStmt( e );
    78         else return new NullStmt();
     105} // ClauseNode::append_last_case
     106
     107ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) {
     108        if ( ast::Expr * e = maybeMoveBuild( ctl ) ) {
     109                return new ast::ExprStmt( location, e );
     110        } else {
     111                return new ast::NullStmt( location );
     112        }
    79113} // build_expr
    80114
    81 Expression * build_if_control( CondCtl * ctl, list< Statement * > & init ) {
    82         if ( ctl->init != 0 ) {
    83                 buildMoveList( ctl->init, init );
     115static ast::Expr * build_if_control( CondCtl * ctl,
     116                std::vector<ast::ptr<ast::Stmt>> & inits ) {
     117        assert( inits.empty() );
     118        if ( nullptr != ctl->init ) {
     119                buildMoveList( ctl->init, inits );
    84120        } // if
    85121
    86         Expression * cond = nullptr;
     122        ast::Expr * cond = nullptr;
    87123        if ( ctl->condition ) {
    88124                // compare the provided condition against 0
    89                 cond = notZeroExpr( maybeMoveBuild< Expression >(ctl->condition) );
     125                cond = notZeroExpr( maybeMoveBuild( ctl->condition ) );
    90126        } else {
    91                 for ( Statement * stmt : init ) {
     127                for ( ast::ptr<ast::Stmt> & stmt : inits ) {
    92128                        // build the && of all of the declared variables compared against 0
    93                         DeclStmt * declStmt = strict_dynamic_cast< DeclStmt * >( stmt );
    94                         DeclarationWithType * dwt = strict_dynamic_cast< DeclarationWithType * >( declStmt->decl );
    95                         Expression * nze = notZeroExpr( new VariableExpr( dwt ) );
    96                         cond = cond ? new LogicalExpr( cond, nze, true ) : nze;
     129                        auto declStmt = stmt.strict_as<ast::DeclStmt>();
     130                        auto dwt = declStmt->decl.strict_as<ast::DeclWithType>();
     131                        ast::Expr * nze = notZeroExpr( new ast::VariableExpr( dwt->location, dwt ) );
     132                        cond = cond ? new ast::LogicalExpr( dwt->location, cond, nze, ast::AndExpr ) : nze;
    97133                }
    98134        }
     
    101137} // build_if_control
    102138
    103 Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {
    104         list< Statement * > astinit;                                            // maybe empty
    105         Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
    106 
    107         Statement * astthen, * astelse = nullptr;
    108         list< Statement * > aststmt;
    109         buildMoveList< Statement, StatementNode >( then, aststmt );
    110         assert( aststmt.size() == 1 );
    111         astthen = aststmt.front();
    112 
    113         if ( else_ ) {
    114                 list< Statement * > aststmt;
    115                 buildMoveList< Statement, StatementNode >( else_, aststmt );
    116                 assert( aststmt.size() == 1 );
    117                 astelse = aststmt.front();
    118         } // if
    119 
    120         return new IfStmt( astcond, astthen, astelse, astinit );
     139ast::Stmt * build_if( const CodeLocation & location, CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {
     140        std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
     141        ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
     142
     143        ast::Stmt const * astthen = buildMoveSingle( then );
     144        ast::Stmt const * astelse = buildMoveOptional( else_ );
     145
     146        return new ast::IfStmt( location, astcond, astthen, astelse,
     147                std::move( astinit )
     148        );
    121149} // build_if
    122150
    123 Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) {
    124         list< Statement * > aststmt;
    125         buildMoveList< Statement, StatementNode >( stmt, aststmt );
    126         if ( ! isSwitch ) {                                                                     // choose statement
    127                 for ( Statement * stmt : aststmt ) {
    128                         CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt );
    129                         if ( ! caseStmt->stmts.empty() ) {                      // code after "case" => end of case list
    130                                 CompoundStmt * block = strict_dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() );
    131                                 block->kids.push_back( new BranchStmt( "", BranchStmt::Break ) );
     151ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, ClauseNode * stmt ) {
     152        std::vector<ast::ptr<ast::CaseClause>> aststmt;
     153        buildMoveList( stmt, aststmt );
     154        // If it is not a switch it is a choose statement.
     155        if ( ! isSwitch ) {
     156                for ( ast::ptr<ast::CaseClause> & stmt : aststmt ) {
     157                        // Code after "case" is the end of case list.
     158                        if ( !stmt->stmts.empty() ) {
     159                                auto mutStmt = ast::mutate( stmt.get() );
     160                                // I believe the stmts are actually always one block.
     161                                auto stmts = mutStmt->stmts.front().get_and_mutate();
     162                                auto block = strict_dynamic_cast<ast::CompoundStmt *>( stmts );
     163                                block->kids.push_back( new ast::BranchStmt( block->location,
     164                                        ast::BranchStmt::Break,
     165                                        ast::Label( block->location ) ) );
     166                                stmt = mutStmt;
    132167                        } // if
    133168                } // for
    134169        } // if
    135170        // aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements
    136         return new SwitchStmt( maybeMoveBuild< Expression >(ctl), aststmt );
     171        return new ast::SwitchStmt( location,
     172                maybeMoveBuild( ctl ), std::move( aststmt ) );
    137173} // build_switch
    138174
    139 Statement * build_case( ExpressionNode * ctl ) {
    140         return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to
     175ast::CaseClause * build_case( const CodeLocation & location, ExpressionNode * ctl ) {
     176        // stmt starts empty and then added to
     177        auto expr = maybeMoveBuild( ctl );
     178        return new ast::CaseClause( location, expr, {} );
    141179} // build_case
    142180
    143 Statement * build_default() {
    144         return new CaseStmt( nullptr, {}, true );                       // stmt starts empty and then added to
     181ast::CaseClause * build_default( const CodeLocation & location ) {
     182        // stmt starts empty and then added to
     183        return new ast::CaseClause( location, nullptr, {} );
    145184} // build_default
    146185
    147 Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {
    148         list< Statement * > astinit;                                            // maybe empty
    149         Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
    150 
    151         list< Statement * > aststmt;                                            // loop body, compound created if empty
    152         buildMoveList< Statement, StatementNode >( stmt, aststmt );
    153         assert( aststmt.size() == 1 );
    154 
    155         list< Statement * > astelse;                                            // else clause, maybe empty
    156         buildMoveList< Statement, StatementNode >( else_, astelse );
    157 
    158         return new WhileDoStmt( astcond, aststmt.front(), astelse.front(), astinit, false );
     186ast::Stmt * build_while( const CodeLocation & location, CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {
     187        std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
     188        ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
     189
     190        return new ast::WhileDoStmt( location,
     191                astcond,
     192                buildMoveSingle( stmt ),
     193                buildMoveOptional( else_ ),
     194                std::move( astinit ),
     195                ast::While
     196        );
    159197} // build_while
    160198
    161 Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {
    162         list< Statement * > aststmt;                                            // loop body, compound created if empty
    163         buildMoveList< Statement, StatementNode >( stmt, aststmt );
    164         assert( aststmt.size() == 1 );                                          // compound created if empty
    165 
    166         list< Statement * > astelse;                                            // else clause, maybe empty
    167         buildMoveList< Statement, StatementNode >( else_, astelse );
    168 
     199ast::Stmt * build_do_while( const CodeLocation & location, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {
    169200        // do-while cannot have declarations in the contitional, so init is always empty
    170         return new WhileDoStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), aststmt.front(), astelse.front(), {}, true );
     201        return new ast::WhileDoStmt( location,
     202                notZeroExpr( maybeMoveBuild( ctl ) ),
     203                buildMoveSingle( stmt ),
     204                buildMoveOptional( else_ ),
     205                {},
     206                ast::DoWhile
     207        );
    171208} // build_do_while
    172209
    173 Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
    174         list< Statement * > astinit;                                            // maybe empty
     210ast::Stmt * build_for( const CodeLocation & location, ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
     211        std::vector<ast::ptr<ast::Stmt>> astinit;                                               // maybe empty
    175212        buildMoveList( forctl->init, astinit );
    176213
    177         Expression * astcond = nullptr;                                         // maybe empty
    178         astcond = notZeroExpr( maybeMoveBuild< Expression >(forctl->condition) );
    179 
    180         Expression * astincr = nullptr;                                         // maybe empty
    181         astincr = maybeMoveBuild< Expression >(forctl->change);
     214        ast::Expr * astcond = nullptr;                                          // maybe empty
     215        astcond = notZeroExpr( maybeMoveBuild( forctl->condition ) );
     216
     217        ast::Expr * astincr = nullptr;                                          // maybe empty
     218        astincr = maybeMoveBuild( forctl->change );
    182219        delete forctl;
    183220
    184         list< Statement * > aststmt;                                            // loop body, compound created if empty
    185         buildMoveList< Statement, StatementNode >( stmt, aststmt );
    186         assert( aststmt.size() == 1 );
    187 
    188         list< Statement * > astelse;                                            // else clause, maybe empty
    189         buildMoveList< Statement, StatementNode >( else_, astelse );
    190 
    191         return new ForStmt( astinit, astcond, astincr, aststmt.front(), astelse.front() );
     221        return new ast::ForStmt( location,
     222                std::move( astinit ),
     223                astcond,
     224                astincr,
     225                buildMoveSingle( stmt ),
     226                buildMoveOptional( else_ )
     227        );
    192228} // build_for
    193229
    194 Statement * build_branch( BranchStmt::Type kind ) {
    195         Statement * ret = new BranchStmt( "", kind );
    196         return ret;
     230ast::Stmt * build_branch( const CodeLocation & location, ast::BranchStmt::Kind kind ) {
     231        return new ast::BranchStmt( location,
     232                kind,
     233                ast::Label( location )
     234        );
    197235} // build_branch
    198236
    199 Statement * build_branch( string * identifier, BranchStmt::Type kind ) {
    200         Statement * ret = new BranchStmt( * identifier, kind );
     237ast::Stmt * build_branch( const CodeLocation & location, string * identifier, ast::BranchStmt::Kind kind ) {
     238        ast::Stmt * ret = new ast::BranchStmt( location,
     239                kind,
     240                ast::Label( location, *identifier )
     241        );
    201242        delete identifier;                                                                      // allocated by lexer
    202243        return ret;
    203244} // build_branch
    204245
    205 Statement * build_computedgoto( ExpressionNode * ctl ) {
    206         return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto );
     246ast::Stmt * build_computedgoto( ExpressionNode * ctl ) {
     247        ast::Expr * expr = maybeMoveBuild( ctl );
     248        return new ast::BranchStmt( expr->location, expr );
    207249} // build_computedgoto
    208250
    209 Statement * build_return( ExpressionNode * ctl ) {
    210         list< Expression * > exps;
     251ast::Stmt * build_return( const CodeLocation & location, ExpressionNode * ctl ) {
     252        std::vector<ast::ptr<ast::Expr>> exps;
    211253        buildMoveList( ctl, exps );
    212         return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr );
     254        return new ast::ReturnStmt( location,
     255                exps.size() > 0 ? exps.back().release() : nullptr
     256        );
    213257} // build_return
    214258
    215 Statement * build_throw( ExpressionNode * ctl ) {
    216         list< Expression * > exps;
     259static ast::Stmt * build_throw_stmt(
     260                const CodeLocation & location,
     261                ExpressionNode * ctl,
     262                ast::ExceptionKind kind ) {
     263        std::vector<ast::ptr<ast::Expr>> exps;
    217264        buildMoveList( ctl, exps );
    218265        assertf( exps.size() < 2, "CFA internal error: leaking memory" );
    219         return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr );
     266        return new ast::ThrowStmt( location,
     267                kind,
     268                !exps.empty() ? exps.back().release() : nullptr,
     269                (ast::Expr *)nullptr
     270        );
     271}
     272
     273ast::Stmt * build_throw( const CodeLocation & loc, ExpressionNode * ctl ) {
     274        return build_throw_stmt( loc, ctl, ast::Terminate );
    220275} // build_throw
    221276
    222 Statement * build_resume( ExpressionNode * ctl ) {
    223         list< Expression * > exps;
    224         buildMoveList( ctl, exps );
    225         assertf( exps.size() < 2, "CFA internal error: leaking memory" );
    226         return new ThrowStmt( ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr );
     277ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctl ) {
     278        return build_throw_stmt( loc, ctl, ast::Resume );
    227279} // build_resume
    228280
    229 Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
     281ast::Stmt * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {
    230282        (void)ctl;
    231283        (void)target;
     
    233285} // build_resume_at
    234286
    235 Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) {
    236         list< CatchStmt * > aststmt;
    237         buildMoveList< CatchStmt, StatementNode >( catch_, aststmt );
    238         CompoundStmt * tryBlock = strict_dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >(try_));
    239         FinallyStmt * finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_) );
    240         return new TryStmt( tryBlock, aststmt, finallyBlock );
     287ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, ClauseNode * catch_, ClauseNode * finally_ ) {
     288        std::vector<ast::ptr<ast::CatchClause>> aststmt;
     289        buildMoveList( catch_, aststmt );
     290        ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) );
     291        ast::FinallyClause * finallyBlock = nullptr;
     292        if ( finally_ ) {
     293                finallyBlock = dynamic_cast<ast::FinallyClause *>( finally_->clause.release() );
     294        }
     295        return new ast::TryStmt( location,
     296                tryBlock,
     297                std::move( aststmt ),
     298                finallyBlock
     299        );
    241300} // build_try
    242301
    243 Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
    244         list< Statement * > aststmt;
    245         buildMoveList< Statement, StatementNode >( body, aststmt );
    246         assert( aststmt.size() == 1 );
    247         return new CatchStmt( kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), aststmt.front() );
     302ast::CatchClause * build_catch( const CodeLocation & location, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
     303        return new ast::CatchClause( location,
     304                kind,
     305                maybeMoveBuild( decl ),
     306                maybeMoveBuild( cond ),
     307                buildMoveSingle( body )
     308        );
    248309} // build_catch
    249310
    250 Statement * build_finally( StatementNode * stmt ) {
    251         list< Statement * > aststmt;
    252         buildMoveList< Statement, StatementNode >( stmt, aststmt );
    253         assert( aststmt.size() == 1 );
    254         return new FinallyStmt( dynamic_cast< CompoundStmt * >( aststmt.front() ) );
     311ast::FinallyClause * build_finally( const CodeLocation & location, StatementNode * stmt ) {
     312        return new ast::FinallyClause( location,
     313                strict_dynamic_cast<const ast::CompoundStmt *>(
     314                        buildMoveSingle( stmt )
     315                )
     316        );
    255317} // build_finally
    256318
    257 SuspendStmt * build_suspend( StatementNode * then, SuspendStmt::Type type ) {
    258         auto node = new SuspendStmt();
    259 
    260         node->type = type;
    261 
    262         list< Statement * > stmts;
    263         buildMoveList< Statement, StatementNode >( then, stmts );
    264         if(!stmts.empty()) {
    265                 assert( stmts.size() == 1 );
    266                 node->then = dynamic_cast< CompoundStmt * >( stmts.front() );
    267         }
    268 
    269         return node;
    270 }
    271 
    272 WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when ) {
    273         auto node = new WaitForStmt();
    274 
    275         WaitForStmt::Target target;
    276         target.function = maybeBuild<Expression>( targetExpr );
     319ast::SuspendStmt * build_suspend( const CodeLocation & location, StatementNode * then, ast::SuspendStmt::Kind kind ) {
     320        return new ast::SuspendStmt( location,
     321                strict_dynamic_cast<const ast::CompoundStmt *, nullptr>(
     322                        buildMoveOptional( then )
     323                ),
     324                kind
     325        );
     326} // build_suspend
     327
     328ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
     329        auto clause = new ast::WaitForClause( location );
     330        clause->target = maybeBuild( targetExpr );
     331        clause->stmt = maybeMoveBuild( stmt );
     332        clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
    277333
    278334        ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
    279335        targetExpr->set_next( nullptr );
    280         buildMoveList< Expression >( next, target.arguments );
     336        buildMoveList( next, clause->target_args );
    281337
    282338        delete targetExpr;
    283339
    284         node->clauses.push_back( WaitForStmt::Clause{
    285                 target,
    286                 maybeMoveBuild<Statement >( stmt ),
    287                 notZeroExpr( maybeMoveBuild<Expression>( when ) )
    288         });
    289 
    290         return node;
     340        existing->clauses.insert( existing->clauses.begin(), clause );
     341
     342        return existing;
    291343} // build_waitfor
    292344
    293 WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when, WaitForStmt * node ) {
    294         WaitForStmt::Target target;
    295         target.function = maybeBuild<Expression>( targetExpr );
    296 
    297         ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
    298         targetExpr->set_next( nullptr );
    299         buildMoveList< Expression >( next, target.arguments );
    300 
    301         delete targetExpr;
    302 
    303         node->clauses.insert( node->clauses.begin(), WaitForStmt::Clause{
    304                 std::move( target ),
    305                 maybeMoveBuild<Statement >( stmt ),
    306                 notZeroExpr( maybeMoveBuild<Expression>( when ) )
    307         });
    308 
    309         return node;
    310 } // build_waitfor
    311 
    312 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when ) {
    313         auto node = new WaitForStmt();
    314 
    315         if( timeout ) {
    316                 node->timeout.time      = maybeMoveBuild<Expression>( timeout );
    317                 node->timeout.statement = maybeMoveBuild<Statement >( stmt    );
    318                 node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
    319         } else {
    320                 node->orelse.statement  = maybeMoveBuild<Statement >( stmt );
    321                 node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( when ) );
    322         } // if
    323 
    324         return node;
     345ast::WaitForStmt * build_waitfor_else( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) {
     346        existing->else_stmt = maybeMoveBuild( stmt );
     347        existing->else_cond = notZeroExpr( maybeMoveBuild( when ) );
     348
     349        (void)location;
     350        return existing;
     351} // build_waitfor_else
     352
     353ast::WaitForStmt * build_waitfor_timeout( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
     354        existing->timeout_time = maybeMoveBuild( timeout );
     355        existing->timeout_stmt = maybeMoveBuild( stmt );
     356        existing->timeout_cond = notZeroExpr( maybeMoveBuild( when ) );
     357
     358        (void)location;
     359        return existing;
    325360} // build_waitfor_timeout
    326361
    327 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when,  StatementNode * else_, ExpressionNode * else_when ) {
    328         auto node = new WaitForStmt();
    329 
    330         node->timeout.time      = maybeMoveBuild<Expression>( timeout );
    331         node->timeout.statement = maybeMoveBuild<Statement >( stmt    );
    332         node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
    333 
    334         node->orelse.statement  = maybeMoveBuild<Statement >( else_ );
    335         node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( else_when ) );
    336 
    337         return node;
    338 } // build_waitfor_timeout
    339 
    340 Statement * build_with( ExpressionNode * exprs, StatementNode * stmt ) {
    341         list< Expression * > e;
     362ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
     363    ast::WhenClause * clause = new ast::WhenClause( loc );
     364    clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
     365    clause->stmt = maybeMoveBuild( stmt );
     366    clause->target = maybeMoveBuild( targetExpr );
     367    return new ast::WaitUntilStmt::ClauseNode( clause );
     368}
     369ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation & loc, ExpressionNode * when, StatementNode * stmt ) {
     370    ast::WhenClause * clause = new ast::WhenClause( loc );
     371    clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
     372    clause->stmt = maybeMoveBuild( stmt );
     373    return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::ELSE, clause );
     374}
     375ast::WaitUntilStmt::ClauseNode * build_waituntil_timeout( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
     376    ast::WhenClause * clause = new ast::WhenClause( loc );
     377    clause->when_cond = notZeroExpr( maybeMoveBuild( when ) );
     378    clause->stmt = maybeMoveBuild( stmt );
     379    clause->target = maybeMoveBuild( timeout );
     380    return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::TIMEOUT, clause );
     381}
     382
     383ast::WaitUntilStmt * build_waituntil_stmt( const CodeLocation & loc, ast::WaitUntilStmt::ClauseNode * root ) {
     384    ast::WaitUntilStmt * retStmt = new ast::WaitUntilStmt( loc );
     385    retStmt->predicateTree = root;
     386   
     387    // iterative tree traversal
     388    std::vector<ast::WaitUntilStmt::ClauseNode *> nodeStack; // stack needed for iterative traversal
     389    ast::WaitUntilStmt::ClauseNode * currNode = nullptr;
     390    ast::WaitUntilStmt::ClauseNode * lastInternalNode = nullptr;
     391    ast::WaitUntilStmt::ClauseNode * cleanup = nullptr; // used to cleanup removed else/timeout
     392    nodeStack.push_back(root);
     393
     394    do {
     395        currNode = nodeStack.back();
     396        nodeStack.pop_back(); // remove node since it will be processed
     397
     398        switch (currNode->op) {
     399            case ast::WaitUntilStmt::ClauseNode::LEAF:
     400                retStmt->clauses.push_back(currNode->leaf);
     401                break;
     402            case ast::WaitUntilStmt::ClauseNode::ELSE:
     403                retStmt->else_stmt = currNode->leaf->stmt
     404                    ? ast::deepCopy( currNode->leaf->stmt )
     405                    : nullptr;
     406               
     407                retStmt->else_cond = currNode->leaf->when_cond
     408                    ? ast::deepCopy( currNode->leaf->when_cond )
     409                    : nullptr;
     410
     411                delete currNode->leaf;
     412                break;
     413            case ast::WaitUntilStmt::ClauseNode::TIMEOUT:
     414                retStmt->timeout_time = currNode->leaf->target
     415                    ? ast::deepCopy( currNode->leaf->target )
     416                    : nullptr;
     417                retStmt->timeout_stmt = currNode->leaf->stmt
     418                    ? ast::deepCopy( currNode->leaf->stmt )
     419                    : nullptr;
     420                retStmt->timeout_cond = currNode->leaf->when_cond
     421                    ? ast::deepCopy( currNode->leaf->when_cond )
     422                    : nullptr;
     423
     424                delete currNode->leaf;
     425                break;
     426            default:
     427                nodeStack.push_back( currNode->right ); // process right after left
     428                nodeStack.push_back( currNode->left );
     429
     430                // Cut else/timeout out of the tree
     431                if ( currNode->op == ast::WaitUntilStmt::ClauseNode::LEFT_OR ) {
     432                    if ( lastInternalNode )
     433                        lastInternalNode->right = currNode->left;
     434                    else    // if not set then root is LEFT_OR
     435                        retStmt->predicateTree = currNode->left;
     436   
     437                    currNode->left = nullptr;
     438                    cleanup = currNode;
     439                }
     440               
     441                lastInternalNode = currNode;
     442                break;
     443        }
     444    } while ( !nodeStack.empty() );
     445
     446    if ( cleanup ) delete cleanup;
     447
     448    return retStmt;
     449}
     450
     451ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
     452        std::vector<ast::ptr<ast::Expr>> e;
    342453        buildMoveList( exprs, e );
    343         Statement * s = maybeMoveBuild<Statement>( stmt );
    344         return new DeclStmt( new WithStmt( e, s ) );
     454        ast::Stmt * s = maybeMoveBuild( stmt );
     455        return new ast::DeclStmt( location, new ast::WithStmt( location, std::move( e ), s ) );
    345456} // build_with
    346457
    347 Statement * build_compound( StatementNode * first ) {
    348         CompoundStmt * cs = new CompoundStmt();
    349         buildMoveList( first, cs->get_kids() );
     458ast::Stmt * build_compound( const CodeLocation & location, StatementNode * first ) {
     459        auto cs = new ast::CompoundStmt( location );
     460        buildMoveList( first, cs->kids );
    350461        return cs;
    351462} // build_compound
     
    355466// statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a
    356467// conical form for code generation.
    357 StatementNode * maybe_build_compound( StatementNode * first ) {
     468StatementNode * maybe_build_compound( const CodeLocation & location, StatementNode * first ) {
    358469        // Optimization: if the control-structure statement is a compound statement, do not wrap it.
    359470        // e.g., if (...) {...} do not wrap the existing compound statement.
    360         if ( ! dynamic_cast<CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
    361                 CompoundStmt * cs = new CompoundStmt();
    362                 buildMoveList( first, cs->get_kids() );
    363                 return new StatementNode( cs );
     471        if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
     472                return new StatementNode( build_compound( location, first ) );
    364473        } // if
    365474        return first;
     
    367476
    368477// Question
    369 Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
    370         list< Expression * > out, in;
    371         list< ConstantExpr * > clob;
     478ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
     479        std::vector<ast::ptr<ast::Expr>> out, in;
     480        std::vector<ast::ptr<ast::ConstantExpr>> clob;
    372481
    373482        buildMoveList( output, out );
    374483        buildMoveList( input, in );
    375484        buildMoveList( clobber, clob );
    376         return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels );
     485        return new ast::AsmStmt( location,
     486                is_volatile,
     487                maybeMoveBuild( instruction ),
     488                std::move( out ),
     489                std::move( in ),
     490                std::move( clob ),
     491                gotolabels ? gotolabels->labels : std::vector<ast::Label>()
     492        );
    377493} // build_asm
    378494
    379 Statement * build_directive( string * directive ) {
    380         return new DirectiveStmt( *directive );
     495ast::Stmt * build_directive( const CodeLocation & location, string * directive ) {
     496        auto stmt = new ast::DirectiveStmt( location, *directive );
     497        delete directive;
     498        return stmt;
    381499} // build_directive
    382500
    383 Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt ) {
    384         list< Expression * > expList;
     501ast::Stmt * build_mutex( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
     502        std::vector<ast::ptr<ast::Expr>> expList;
    385503        buildMoveList( exprs, expList );
    386         Statement * body = maybeMoveBuild<Statement>( stmt );
    387         return new MutexStmt( body, expList );
     504        ast::Stmt * body = maybeMoveBuild( stmt );
     505        return new ast::MutexStmt( location, body, std::move( expList ) );
    388506} // build_mutex
    389507
  • src/Parser/TypeData.cc

    r34b4268 r24d6572  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 15:12:51 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 10 22:36:52 2022
    13 // Update Count     : 677
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Apr  4 13:39:00 2023
     13// Update Count     : 680
    1414//
     15
     16#include "TypeData.h"
    1517
    1618#include <cassert>                 // for assert
    1719#include <ostream>                 // for operator<<, ostream, basic_ostream
    1820
     21#include "AST/Decl.hpp"            // for AggregateDecl, ObjectDecl, TypeDe...
     22#include "AST/Init.hpp"            // for SingleInit, ListInit
     23#include "AST/Print.hpp"           // for print
    1924#include "Common/SemanticError.h"  // for SemanticError
    20 #include "Common/utility.h"        // for maybeClone, maybeBuild, maybeMoveB...
    21 #include "Parser/ParseNode.h"      // for DeclarationNode, ExpressionNode
    22 #include "SynTree/Declaration.h"   // for TypeDecl, ObjectDecl, FunctionDecl
    23 #include "SynTree/Expression.h"    // for Expression, ConstantExpr (ptr only)
    24 #include "SynTree/Initializer.h"   // for SingleInit, Initializer (ptr only)
    25 #include "SynTree/Statement.h"     // for CompoundStmt, Statement
    26 #include "SynTree/Type.h"          // for BasicType, Type, Type::ForallList
    27 #include "TypeData.h"
     25#include "Common/utility.h"        // for splice, spliceBegin
     26#include "Parser/ExpressionNode.h" // for ExpressionNode
     27#include "Parser/StatementNode.h"  // for StatementNode
    2828
    2929class Attribute;
     
    3333TypeData::TypeData( Kind k ) : location( yylloc ), kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ {
    3434        switch ( kind ) {
    35           case Unknown:
    36           case Pointer:
    37           case Reference:
    38           case EnumConstant:
    39           case GlobalScope:
    40                 // nothing else to initialize
    41                 break;
    42           case Basic:
    43                 // basic = new Basic_t;
    44                 break;
    45           case Array:
    46                 // array = new Array_t;
     35        case Unknown:
     36        case Pointer:
     37        case Reference:
     38        case EnumConstant:
     39        case GlobalScope:
     40        case Basic:
     41                // No unique data to initialize.
     42                break;
     43        case Array:
    4744                array.dimension = nullptr;
    4845                array.isVarLen = false;
    4946                array.isStatic = false;
    5047                break;
    51           case Function:
    52                 // function = new Function_t;
     48        case Function:
    5349                function.params = nullptr;
    5450                function.idList = nullptr;
     
    5753                function.withExprs = nullptr;
    5854                break;
    59                 // Enum is an Aggregate, so both structures are initialized together.
    60           case Enum:
    61                 // enumeration = new Enumeration_t;
     55        case Enum:
    6256                enumeration.name = nullptr;
    6357                enumeration.constants = nullptr;
     
    6559                enumeration.anon = false;
    6660                break;
    67           case Aggregate:
    68                 // aggregate = new Aggregate_t;
    69                 aggregate.kind = AggregateDecl::NoAggregate;
     61        case Aggregate:
     62                aggregate.kind = ast::AggregateDecl::NoAggregate;
    7063                aggregate.name = nullptr;
    7164                aggregate.params = nullptr;
     
    7770                aggregate.anon = false;
    7871                break;
    79           case AggregateInst:
    80                 // aggInst = new AggInst_t;
     72        case AggregateInst:
    8173                aggInst.aggregate = nullptr;
    8274                aggInst.params = nullptr;
    8375                aggInst.hoistType = false;
    8476                break;
    85           case Symbolic:
    86           case SymbolicInst:
    87                 // symbolic = new Symbolic_t;
     77        case Symbolic:
     78        case SymbolicInst:
    8879                symbolic.name = nullptr;
    8980                symbolic.params = nullptr;
     
    9182                symbolic.assertions = nullptr;
    9283                break;
    93           case Tuple:
    94                 // tuple = new Tuple_t;
     84        case Tuple:
    9585                tuple = nullptr;
    9686                break;
    97           case Typeof:
    98           case Basetypeof:
    99                 // typeexpr = new Typeof_t;
     87        case Typeof:
     88        case Basetypeof:
    10089                typeexpr = nullptr;
    10190                break;
    102           case Vtable:
    103                 break;
    104           case Builtin:
    105                 // builtin = new Builtin_t;
    106                 case Qualified:
     91        case Vtable:
     92        case Builtin:
     93                // No unique data to initialize.
     94                break;
     95        case Qualified:
    10796                qualified.parent = nullptr;
    10897                qualified.child = nullptr;
     
    117106
    118107        switch ( kind ) {
    119           case Unknown:
    120           case Pointer:
    121           case Reference:
    122           case EnumConstant:
    123           case GlobalScope:
    124                 // nothing to destroy
    125                 break;
    126           case Basic:
    127                 // delete basic;
    128                 break;
    129           case Array:
     108        case Unknown:
     109        case Pointer:
     110        case Reference:
     111        case EnumConstant:
     112        case GlobalScope:
     113        case Basic:
     114                // No unique data to deconstruct.
     115                break;
     116        case Array:
    130117                delete array.dimension;
    131                 // delete array;
    132                 break;
    133           case Function:
     118                break;
     119        case Function:
    134120                delete function.params;
    135121                delete function.idList;
     
    137123                delete function.body;
    138124                delete function.withExprs;
    139                 // delete function;
    140                 break;
    141           case Aggregate:
     125                break;
     126        case Aggregate:
    142127                delete aggregate.name;
    143128                delete aggregate.params;
    144129                delete aggregate.actuals;
    145130                delete aggregate.fields;
    146                 // delete aggregate;
    147                 break;
    148           case AggregateInst:
     131                break;
     132        case AggregateInst:
    149133                delete aggInst.aggregate;
    150134                delete aggInst.params;
    151                 // delete aggInst;
    152                 break;
    153           case Enum:
     135                break;
     136        case Enum:
    154137                delete enumeration.name;
    155138                delete enumeration.constants;
    156                 // delete enumeration;
    157                 break;
    158           case Symbolic:
    159           case SymbolicInst:
     139                break;
     140        case Symbolic:
     141        case SymbolicInst:
    160142                delete symbolic.name;
    161143                delete symbolic.params;
    162144                delete symbolic.actuals;
    163145                delete symbolic.assertions;
    164                 // delete symbolic;
    165                 break;
    166           case Tuple:
    167                 // delete tuple->members;
     146                break;
     147        case Tuple:
    168148                delete tuple;
    169149                break;
    170           case Typeof:
    171           case Basetypeof:
    172                 // delete typeexpr->expr;
     150        case Typeof:
     151        case Basetypeof:
    173152                delete typeexpr;
    174153                break;
    175           case Vtable:
    176                 break;
    177           case Builtin:
    178                 // delete builtin;
    179                 break;
    180           case Qualified:
     154        case Vtable:
     155        case Builtin:
     156                // No unique data to deconstruct.
     157                break;
     158        case Qualified:
    181159                delete qualified.parent;
    182160                delete qualified.child;
     161                break;
    183162        } // switch
    184163} // TypeData::~TypeData
     
    192171
    193172        switch ( kind ) {
    194           case Unknown:
    195           case EnumConstant:
    196           case Pointer:
    197           case Reference:
    198           case GlobalScope:
     173        case Unknown:
     174        case EnumConstant:
     175        case Pointer:
     176        case Reference:
     177        case GlobalScope:
    199178                // nothing else to copy
    200179                break;
    201           case Basic:
     180        case Basic:
    202181                newtype->basictype = basictype;
    203182                newtype->complextype = complextype;
     
    205184                newtype->length = length;
    206185                break;
    207           case Array:
     186        case Array:
    208187                newtype->array.dimension = maybeClone( array.dimension );
    209188                newtype->array.isVarLen = array.isVarLen;
    210189                newtype->array.isStatic = array.isStatic;
    211190                break;
    212           case Function:
     191        case Function:
    213192                newtype->function.params = maybeClone( function.params );
    214193                newtype->function.idList = maybeClone( function.idList );
     
    217196                newtype->function.withExprs = maybeClone( function.withExprs );
    218197                break;
    219           case Aggregate:
     198        case Aggregate:
    220199                newtype->aggregate.kind = aggregate.kind;
    221200                newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr;
     
    228207                newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr;
    229208                break;
    230           case AggregateInst:
     209        case AggregateInst:
    231210                newtype->aggInst.aggregate = maybeClone( aggInst.aggregate );
    232211                newtype->aggInst.params = maybeClone( aggInst.params );
    233212                newtype->aggInst.hoistType = aggInst.hoistType;
    234213                break;
    235           case Enum:
     214        case Enum:
    236215                newtype->enumeration.name = enumeration.name ? new string( *enumeration.name ) : nullptr;
    237216                newtype->enumeration.constants = maybeClone( enumeration.constants );
     
    239218                newtype->enumeration.anon = enumeration.anon;
    240219                break;
    241           case Symbolic:
    242           case SymbolicInst:
     220        case Symbolic:
     221        case SymbolicInst:
    243222                newtype->symbolic.name = symbolic.name ? new string( *symbolic.name ) : nullptr;
    244223                newtype->symbolic.params = maybeClone( symbolic.params );
     
    247226                newtype->symbolic.isTypedef = symbolic.isTypedef;
    248227                break;
    249           case Tuple:
     228        case Tuple:
    250229                newtype->tuple = maybeClone( tuple );
    251230                break;
    252           case Typeof:
    253           case Basetypeof:
     231        case Typeof:
     232        case Basetypeof:
    254233                newtype->typeexpr = maybeClone( typeexpr );
    255234                break;
    256           case Vtable:
    257                 break;
    258           case Builtin:
     235        case Vtable:
     236                break;
     237        case Builtin:
    259238                assert( builtintype == DeclarationNode::Zero || builtintype == DeclarationNode::One );
    260239                newtype->builtintype = builtintype;
    261240                break;
    262                 case Qualified:
     241        case Qualified:
    263242                newtype->qualified.parent = maybeClone( qualified.parent );
    264243                newtype->qualified.child = maybeClone( qualified.child );
     
    270249
    271250void TypeData::print( ostream &os, int indent ) const {
    272         for ( int i = 0; i < Type::NumTypeQualifier; i += 1 ) {
    273                 if ( qualifiers[i] ) os << Type::QualifiersNames[ i ] << ' ';
    274         } // for
     251        ast::print( os, qualifiers );
    275252
    276253        if ( forall ) {
     
    280257
    281258        switch ( kind ) {
    282           case Basic:
     259        case Basic:
    283260                if ( signedness != DeclarationNode::NoSignedness ) os << DeclarationNode::signednessNames[ signedness ] << " ";
    284261                if ( length != DeclarationNode::NoLength ) os << DeclarationNode::lengthNames[ length ] << " ";
     
    286263                if ( basictype != DeclarationNode::NoBasicType ) os << DeclarationNode::basicTypeNames[ basictype ] << " ";
    287264                break;
    288           case Pointer:
     265        case Pointer:
    289266                os << "pointer ";
    290267                if ( base ) {
     
    293270                } // if
    294271                break;
    295           case Reference:
     272        case Reference:
    296273                os << "reference ";
    297274                if ( base ) {
     
    300277                } // if
    301278                break;
    302           case Array:
     279        case Array:
    303280                if ( array.isStatic ) {
    304281                        os << "static ";
     
    316293                } // if
    317294                break;
    318           case Function:
     295        case Function:
    319296                os << "function" << endl;
    320297                if ( function.params ) {
     
    344321                } // if
    345322                break;
    346           case Aggregate:
    347                 os << AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl;
     323        case Aggregate:
     324                os << ast::AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl;
    348325                if ( aggregate.params ) {
    349326                        os << string( indent + 2, ' ' ) << "with type parameters" << endl;
     
    362339                } // if
    363340                break;
    364           case AggregateInst:
     341        case AggregateInst:
    365342                if ( aggInst.aggregate ) {
    366343                        os << "instance of " ;
     
    374351                } // if
    375352                break;
    376           case Enum:
    377                 os << "enumeration ";
     353        case Enum:
     354                os << "enumeration " << *enumeration.name << endl;;
    378355                if ( enumeration.constants ) {
    379356                        os << "with constants" << endl;
     
    388365                } // if
    389366                break;
    390           case EnumConstant:
     367        case EnumConstant:
    391368                os << "enumeration constant ";
    392369                break;
    393           case Symbolic:
     370        case Symbolic:
    394371                if ( symbolic.isTypedef ) {
    395372                        os << "typedef definition ";
     
    411388                } // if
    412389                break;
    413           case SymbolicInst:
     390        case SymbolicInst:
    414391                os << *symbolic.name;
    415392                if ( symbolic.actuals ) {
     
    419396                } // if
    420397                break;
    421           case Tuple:
     398        case Tuple:
    422399                os << "tuple ";
    423400                if ( tuple ) {
     
    426403                } // if
    427404                break;
    428           case Basetypeof:
     405        case Basetypeof:
    429406                os << "base-";
    430407                #if defined(__GNUC__) && __GNUC__ >= 7
     
    432409                #endif
    433410                // FALL THROUGH
    434           case Typeof:
     411        case Typeof:
    435412                os << "type-of expression ";
    436413                if ( typeexpr ) {
     
    438415                } // if
    439416                break;
    440           case Vtable:
     417        case Vtable:
    441418                os << "vtable";
    442419                break;
    443           case Builtin:
     420        case Builtin:
    444421                os << DeclarationNode::builtinTypeNames[builtintype];
    445422                break;
    446           case GlobalScope:
    447                 break;
    448           case Qualified:
     423        case GlobalScope:
     424                break;
     425        case Qualified:
    449426                qualified.parent->print( os );
    450427                os << ".";
    451428                qualified.child->print( os );
    452429                break;
    453           case Unknown:
     430        case Unknown:
    454431                os << "entity of unknown type ";
    455432                break;
    456           default:
     433        default:
    457434                os << "internal error: TypeData::print " << kind << endl;
    458435                assert( false );
     
    462439const std::string * TypeData::leafName() const {
    463440        switch ( kind ) {
    464           case Unknown:
    465           case Pointer:
    466           case Reference:
    467           case EnumConstant:
    468           case GlobalScope:
    469           case Array:
    470           case Basic:
    471           case Function:
    472           case AggregateInst:
    473           case Tuple:
    474           case Typeof:
    475           case Basetypeof:
    476           case Builtin:
    477           case Vtable:
     441        case Unknown:
     442        case Pointer:
     443        case Reference:
     444        case EnumConstant:
     445        case GlobalScope:
     446        case Array:
     447        case Basic:
     448        case Function:
     449        case AggregateInst:
     450        case Tuple:
     451        case Typeof:
     452        case Basetypeof:
     453        case Builtin:
     454        case Vtable:
    478455                assertf(false, "Tried to get leaf name from kind without a name: %d", kind);
    479456                break;
    480           case Aggregate:
     457        case Aggregate:
    481458                return aggregate.name;
    482           case Enum:
     459        case Enum:
    483460                return enumeration.name;
    484           case Symbolic:
    485           case SymbolicInst:
     461        case Symbolic:
     462        case SymbolicInst:
    486463                return symbolic.name;
    487           case Qualified:
     464        case Qualified:
    488465                return qualified.child->leafName();
    489466        } // switch
     
    492469
    493470
    494 template< typename ForallList >
    495 void buildForall( const DeclarationNode * firstNode, ForallList &outputList ) {
    496         buildList( firstNode, outputList );
     471void buildForall(
     472                const DeclarationNode * firstNode,
     473                std::vector<ast::ptr<ast::TypeInstType>> &outputList ) {
     474        {
     475                std::vector<ast::ptr<ast::Type>> tmpList;
     476                buildTypeList( firstNode, tmpList );
     477                for ( auto tmp : tmpList ) {
     478                        outputList.emplace_back(
     479                                strict_dynamic_cast<const ast::TypeInstType *>(
     480                                        tmp.release() ) );
     481                }
     482        }
    497483        auto n = firstNode;
    498         for ( typename ForallList::iterator i = outputList.begin(); i != outputList.end(); ++i, n = (DeclarationNode*)n->get_next() ) {
    499                 TypeDecl * td = static_cast<TypeDecl *>(*i);
    500                 if ( n->variable.tyClass == TypeDecl::Otype ) {
    501                         // add assertion parameters to `type' tyvars in reverse order
    502                         // add dtor:  void ^?{}(T *)
    503                         FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false );
    504                         dtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
    505                         td->get_assertions().push_front( new FunctionDecl( "^?{}", Type::StorageClasses(), LinkageSpec::Cforall, dtorType, nullptr ) );
    506 
    507                         // add copy ctor:  void ?{}(T *, T)
    508                         FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false );
    509                         copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
    510                         copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
    511                         td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, copyCtorType, nullptr ) );
    512 
    513                         // add default ctor:  void ?{}(T *)
    514                         FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false );
    515                         ctorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
    516                         td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, ctorType, nullptr ) );
    517 
    518                         // add assignment operator:  T * ?=?(T *, T)
    519                         FunctionType * assignType = new FunctionType( Type::Qualifiers(), false );
    520                         assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) );
    521                         assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
    522                         assignType->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) );
    523                         td->get_assertions().push_front( new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Cforall, assignType, nullptr ) );
    524                 } // if
     484        for ( auto i = outputList.begin() ;
     485                        i != outputList.end() ;
     486                        ++i, n = (DeclarationNode*)n->get_next() ) {
     487                // Only the object type class adds additional assertions.
     488                if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
     489                        continue;
     490                }
     491
     492                ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
     493                std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
     494                auto mutTypeDecl = ast::mutate( td );
     495                const CodeLocation & location = mutTypeDecl->location;
     496                *i = mutTypeDecl;
     497
     498                // add assertion parameters to `type' tyvars in reverse order
     499                // add assignment operator:  T * ?=?(T *, T)
     500                newAssertions.push_back( new ast::FunctionDecl(
     501                        location,
     502                        "?=?",
     503                        {}, // forall
     504                        {}, // assertions
     505                        {
     506                                new ast::ObjectDecl(
     507                                        location,
     508                                        "",
     509                                        new ast::ReferenceType( i->get() ),
     510                                        (ast::Init *)nullptr,
     511                                        ast::Storage::Classes(),
     512                                        ast::Linkage::Cforall,
     513                                        (ast::Expr *)nullptr
     514                                ),
     515                                new ast::ObjectDecl(
     516                                        location,
     517                                        "",
     518                                        i->get(),
     519                                        (ast::Init *)nullptr,
     520                                        ast::Storage::Classes(),
     521                                        ast::Linkage::Cforall,
     522                                        (ast::Expr *)nullptr
     523                                ),
     524                        }, // params
     525                        {
     526                                new ast::ObjectDecl(
     527                                        location,
     528                                        "",
     529                                        i->get(),
     530                                        (ast::Init *)nullptr,
     531                                        ast::Storage::Classes(),
     532                                        ast::Linkage::Cforall,
     533                                        (ast::Expr *)nullptr
     534                                ),
     535                        }, // returns
     536                        (ast::CompoundStmt *)nullptr,
     537                        ast::Storage::Classes(),
     538                        ast::Linkage::Cforall
     539                ) );
     540
     541                // add default ctor:  void ?{}(T *)
     542                newAssertions.push_back( new ast::FunctionDecl(
     543                        location,
     544                        "?{}",
     545                        {}, // forall
     546                        {}, // assertions
     547                        {
     548                                new ast::ObjectDecl(
     549                                        location,
     550                                        "",
     551                                        new ast::ReferenceType( i->get() ),
     552                                        (ast::Init *)nullptr,
     553                                        ast::Storage::Classes(),
     554                                        ast::Linkage::Cforall,
     555                                        (ast::Expr *)nullptr
     556                                ),
     557                        }, // params
     558                        {}, // returns
     559                        (ast::CompoundStmt *)nullptr,
     560                        ast::Storage::Classes(),
     561                        ast::Linkage::Cforall
     562                ) );
     563
     564                // add copy ctor:  void ?{}(T *, T)
     565                newAssertions.push_back( new ast::FunctionDecl(
     566                        location,
     567                        "?{}",
     568                        {}, // forall
     569                        {}, // assertions
     570                        {
     571                                new ast::ObjectDecl(
     572                                        location,
     573                                        "",
     574                                        new ast::ReferenceType( i->get() ),
     575                                        (ast::Init *)nullptr,
     576                                        ast::Storage::Classes(),
     577                                        ast::Linkage::Cforall,
     578                                        (ast::Expr *)nullptr
     579                                ),
     580                                new ast::ObjectDecl(
     581                                        location,
     582                                        "",
     583                                        i->get(),
     584                                        (ast::Init *)nullptr,
     585                                        ast::Storage::Classes(),
     586                                        ast::Linkage::Cforall,
     587                                        (ast::Expr *)nullptr
     588                                ),
     589                        }, // params
     590                        {}, // returns
     591                        (ast::CompoundStmt *)nullptr,
     592                        ast::Storage::Classes(),
     593                        ast::Linkage::Cforall
     594                ) );
     595
     596                // add dtor:  void ^?{}(T *)
     597                newAssertions.push_back( new ast::FunctionDecl(
     598                        location,
     599                        "^?{}",
     600                        {}, // forall
     601                        {}, // assertions
     602                        {
     603                                new ast::ObjectDecl(
     604                                        location,
     605                                        "",
     606                                        new ast::ReferenceType( i->get() ),
     607                                        (ast::Init *)nullptr,
     608                                        ast::Storage::Classes(),
     609                                        ast::Linkage::Cforall,
     610                                        (ast::Expr *)nullptr
     611                                ),
     612                        }, // params
     613                        {}, // returns
     614                        (ast::CompoundStmt *)nullptr,
     615                        ast::Storage::Classes(),
     616                        ast::Linkage::Cforall
     617                ) );
     618
     619                spliceBegin( mutTypeDecl->assertions, newAssertions );
     620        } // for
     621}
     622
     623
     624void buildForall(
     625                const DeclarationNode * firstNode,
     626                std::vector<ast::ptr<ast::TypeDecl>> &outputForall ) {
     627        buildList( firstNode, outputForall );
     628        auto n = firstNode;
     629        for ( auto i = outputForall.begin() ;
     630                        i != outputForall.end() ;
     631                        ++i, n = (DeclarationNode*)n->get_next() ) {
     632                // Only the object type class adds additional assertions.
     633                if ( n->variable.tyClass != ast::TypeDecl::Otype ) {
     634                        continue;
     635                }
     636
     637                ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>();
     638                std::vector<ast::ptr<ast::DeclWithType>> newAssertions;
     639                auto mutTypeDecl = ast::mutate( td );
     640                const CodeLocation & location = mutTypeDecl->location;
     641                *i = mutTypeDecl;
     642
     643                // add assertion parameters to `type' tyvars in reverse order
     644                // add assignment operator:  T * ?=?(T *, T)
     645                newAssertions.push_back( new ast::FunctionDecl(
     646                        location,
     647                        "?=?",
     648                        {}, // forall
     649                        {}, // assertions
     650                        {
     651                                new ast::ObjectDecl(
     652                                        location,
     653                                        "",
     654                                        new ast::ReferenceType( new ast::TypeInstType( td->name, *i ) ),
     655                                        (ast::Init *)nullptr,
     656                                        ast::Storage::Classes(),
     657                                        ast::Linkage::Cforall,
     658                                        (ast::Expr *)nullptr
     659                                ),
     660                                new ast::ObjectDecl(
     661                                        location,
     662                                        "",
     663                                        new ast::TypeInstType( td->name, *i ),
     664                                        (ast::Init *)nullptr,
     665                                        ast::Storage::Classes(),
     666                                        ast::Linkage::Cforall,
     667                                        (ast::Expr *)nullptr
     668                                ),
     669                        }, // params
     670                        {
     671                                new ast::ObjectDecl(
     672                                        location,
     673                                        "",
     674                                        new ast::TypeInstType( td->name, *i ),
     675                                        (ast::Init *)nullptr,
     676                                        ast::Storage::Classes(),
     677                                        ast::Linkage::Cforall,
     678                                        (ast::Expr *)nullptr
     679                                ),
     680                        }, // returns
     681                        (ast::CompoundStmt *)nullptr,
     682                        ast::Storage::Classes(),
     683                        ast::Linkage::Cforall
     684                ) );
     685
     686                // add default ctor:  void ?{}(T *)
     687                newAssertions.push_back( new ast::FunctionDecl(
     688                        location,
     689                        "?{}",
     690                        {}, // forall
     691                        {}, // assertions
     692                        {
     693                                new ast::ObjectDecl(
     694                                        location,
     695                                        "",
     696                                        new ast::ReferenceType(
     697                                                new ast::TypeInstType( td->name, i->get() ) ),
     698                                        (ast::Init *)nullptr,
     699                                        ast::Storage::Classes(),
     700                                        ast::Linkage::Cforall,
     701                                        (ast::Expr *)nullptr
     702                                ),
     703                        }, // params
     704                        {}, // returns
     705                        (ast::CompoundStmt *)nullptr,
     706                        ast::Storage::Classes(),
     707                        ast::Linkage::Cforall
     708                ) );
     709
     710                // add copy ctor:  void ?{}(T *, T)
     711                newAssertions.push_back( new ast::FunctionDecl(
     712                        location,
     713                        "?{}",
     714                        {}, // forall
     715                        {}, // assertions
     716                        {
     717                                new ast::ObjectDecl(
     718                                        location,
     719                                        "",
     720                                        new ast::ReferenceType(
     721                                                new ast::TypeInstType( td->name, *i ) ),
     722                                        (ast::Init *)nullptr,
     723                                        ast::Storage::Classes(),
     724                                        ast::Linkage::Cforall,
     725                                        (ast::Expr *)nullptr
     726                                ),
     727                                new ast::ObjectDecl(
     728                                        location,
     729                                        "",
     730                                        new ast::TypeInstType( td->name, *i ),
     731                                        (ast::Init *)nullptr,
     732                                        ast::Storage::Classes(),
     733                                        ast::Linkage::Cforall,
     734                                        (ast::Expr *)nullptr
     735                                ),
     736                        }, // params
     737                        {}, // returns
     738                        (ast::CompoundStmt *)nullptr,
     739                        ast::Storage::Classes(),
     740                        ast::Linkage::Cforall
     741                ) );
     742
     743                // add dtor:  void ^?{}(T *)
     744                newAssertions.push_back( new ast::FunctionDecl(
     745                        location,
     746                        "^?{}",
     747                        {}, // forall
     748                        {}, // assertions
     749                        {
     750                                new ast::ObjectDecl(
     751                                        location,
     752                                        "",
     753                                        new ast::ReferenceType(
     754                                                new ast::TypeInstType( i->get() )
     755                                        ),
     756                                        (ast::Init *)nullptr,
     757                                        ast::Storage::Classes(),
     758                                        ast::Linkage::Cforall,
     759                                        (ast::Expr *)nullptr
     760                                ),
     761                        }, // params
     762                        {}, // returns
     763                        (ast::CompoundStmt *)nullptr,
     764                        ast::Storage::Classes(),
     765                        ast::Linkage::Cforall
     766                ) );
     767
     768                spliceBegin( mutTypeDecl->assertions, newAssertions );
    525769        } // for
    526770} // buildForall
    527771
    528772
    529 Type * typebuild( const TypeData * td ) {
     773ast::Type * typebuild( const TypeData * td ) {
    530774        assert( td );
    531775        switch ( td->kind ) {
    532           case TypeData::Unknown:
     776        case TypeData::Unknown:
    533777                // fill in implicit int
    534                 return new BasicType( buildQualifiers( td ), BasicType::SignedInt );
    535           case TypeData::Basic:
     778                return new ast::BasicType(
     779                        ast::BasicType::SignedInt,
     780                        buildQualifiers( td )
     781                );
     782        case TypeData::Basic:
    536783                return buildBasicType( td );
    537           case TypeData::Pointer:
     784        case TypeData::Pointer:
    538785                return buildPointer( td );
    539           case TypeData::Array:
     786        case TypeData::Array:
    540787                return buildArray( td );
    541           case TypeData::Reference:
     788        case TypeData::Reference:
    542789                return buildReference( td );
    543           case TypeData::Function:
    544                 return buildFunction( td );
    545           case TypeData::AggregateInst:
     790        case TypeData::Function:
     791                return buildFunctionType( td );
     792        case TypeData::AggregateInst:
    546793                return buildAggInst( td );
    547           case TypeData::EnumConstant:
    548                 return new EnumInstType( buildQualifiers( td ), "" );
    549           case TypeData::SymbolicInst:
     794        case TypeData::EnumConstant:
     795                return new ast::EnumInstType( "", buildQualifiers( td ) );
     796        case TypeData::SymbolicInst:
    550797                return buildSymbolicInst( td );
    551           case TypeData::Tuple:
     798        case TypeData::Tuple:
    552799                return buildTuple( td );
    553           case TypeData::Typeof:
    554           case TypeData::Basetypeof:
     800        case TypeData::Typeof:
     801        case TypeData::Basetypeof:
    555802                return buildTypeof( td );
    556           case TypeData::Vtable:
     803        case TypeData::Vtable:
    557804                return buildVtable( td );
    558           case TypeData::Builtin:
     805        case TypeData::Builtin:
    559806                switch ( td->builtintype ) {
    560                   case DeclarationNode::Zero:
    561                         return new ZeroType( noQualifiers );
    562                   case DeclarationNode::One:
    563                         return new OneType( noQualifiers );
    564                   default:
    565                         return new VarArgsType( buildQualifiers( td ) );
     807                case DeclarationNode::Zero:
     808                        return new ast::ZeroType();
     809                case DeclarationNode::One:
     810                        return new ast::OneType();
     811                default:
     812                        return new ast::VarArgsType( buildQualifiers( td ) );
    566813                } // switch
    567           case TypeData::GlobalScope:
    568                 return new GlobalScopeType();
    569           case TypeData::Qualified:
    570                 return new QualifiedType( buildQualifiers( td ), typebuild( td->qualified.parent ), typebuild( td->qualified.child ) );
    571           case TypeData::Symbolic:
    572           case TypeData::Enum:
    573           case TypeData::Aggregate:
     814        case TypeData::GlobalScope:
     815                return new ast::GlobalScopeType();
     816        case TypeData::Qualified:
     817                return new ast::QualifiedType(
     818                        typebuild( td->qualified.parent ),
     819                        typebuild( td->qualified.child ),
     820                        buildQualifiers( td )
     821                );
     822        case TypeData::Symbolic:
     823        case TypeData::Enum:
     824        case TypeData::Aggregate:
    574825                assert( false );
    575826        } // switch
     
    583834
    584835        switch ( td->kind ) {
    585           case TypeData::Aggregate:
     836        case TypeData::Aggregate:
    586837                if ( ! toplevel && td->aggregate.body ) {
    587838                        ret = td->clone();
    588839                } // if
    589840                break;
    590           case TypeData::Enum:
     841        case TypeData::Enum:
    591842                if ( ! toplevel && td->enumeration.body ) {
    592843                        ret = td->clone();
    593844                } // if
    594845                break;
    595           case TypeData::AggregateInst:
     846        case TypeData::AggregateInst:
    596847                if ( td->aggInst.aggregate ) {
    597848                        ret = typeextractAggregate( td->aggInst.aggregate, false );
    598849                } // if
    599850                break;
    600           default:
     851        default:
    601852                if ( td->base ) {
    602853                        ret = typeextractAggregate( td->base, false );
     
    607858
    608859
    609 Type::Qualifiers buildQualifiers( const TypeData * td ) {
     860ast::CV::Qualifiers buildQualifiers( const TypeData * td ) {
    610861        return td->qualifiers;
    611862} // buildQualifiers
     
    616867} // genTSError
    617868
    618 Type * buildBasicType( const TypeData * td ) {
    619         BasicType::Kind ret;
     869ast::Type * buildBasicType( const TypeData * td ) {
     870        ast::BasicType::Kind ret;
    620871
    621872        switch ( td->basictype ) {
    622           case DeclarationNode::Void:
     873        case DeclarationNode::Void:
    623874                if ( td->signedness != DeclarationNode::NoSignedness ) {
    624875                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
     
    627878                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
    628879                } // if
    629                 return new VoidType( buildQualifiers( td ) );
    630                 break;
    631 
    632           case DeclarationNode::Bool:
     880                return new ast::VoidType( buildQualifiers( td ) );
     881                break;
     882
     883        case DeclarationNode::Bool:
    633884                if ( td->signedness != DeclarationNode::NoSignedness ) {
    634885                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
     
    638889                } // if
    639890
    640                 ret = BasicType::Bool;
    641                 break;
    642 
    643           case DeclarationNode::Char:
     891                ret = ast::BasicType::Bool;
     892                break;
     893
     894        case DeclarationNode::Char:
    644895                // C11 Standard 6.2.5.15: The three types char, signed char, and unsigned char are collectively called the
    645896                // character types. The implementation shall define char to have the same range, representation, and behavior as
    646897                // either signed char or unsigned char.
    647                 static BasicType::Kind chartype[] = { BasicType::SignedChar, BasicType::UnsignedChar, BasicType::Char };
     898                static ast::BasicType::Kind chartype[] = { ast::BasicType::SignedChar, ast::BasicType::UnsignedChar, ast::BasicType::Char };
    648899
    649900                if ( td->length != DeclarationNode::NoLength ) {
     
    654905                break;
    655906
    656           case DeclarationNode::Int:
    657                 static BasicType::Kind inttype[2][4] = {
    658                         { BasicType::ShortSignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, BasicType::SignedInt },
    659                         { BasicType::ShortUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, BasicType::UnsignedInt },
     907        case DeclarationNode::Int:
     908                static ast::BasicType::Kind inttype[2][4] = {
     909                        { ast::BasicType::ShortSignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, ast::BasicType::SignedInt },
     910                        { ast::BasicType::ShortUnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, ast::BasicType::UnsignedInt },
    660911                };
    661912
    662           Integral: ;
     913        Integral: ;
    663914                if ( td->signedness == DeclarationNode::NoSignedness ) {
    664915                        const_cast<TypeData *>(td)->signedness = DeclarationNode::Signed;
     
    667918                break;
    668919
    669           case DeclarationNode::Int128:
    670                 ret = td->signedness == DeclarationNode::Unsigned ? BasicType::UnsignedInt128 : BasicType::SignedInt128;
     920        case DeclarationNode::Int128:
     921                ret = td->signedness == DeclarationNode::Unsigned ? ast::BasicType::UnsignedInt128 : ast::BasicType::SignedInt128;
    671922                if ( td->length != DeclarationNode::NoLength ) {
    672923                        genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype );
     
    674925                break;
    675926
    676           case DeclarationNode::Float:
    677           case DeclarationNode::Double:
    678           case DeclarationNode::LongDouble:                                     // not set until below
    679           case DeclarationNode::uuFloat80:
    680           case DeclarationNode::uuFloat128:
    681           case DeclarationNode::uFloat16:
    682           case DeclarationNode::uFloat32:
    683           case DeclarationNode::uFloat32x:
    684           case DeclarationNode::uFloat64:
    685           case DeclarationNode::uFloat64x:
    686           case DeclarationNode::uFloat128:
    687           case DeclarationNode::uFloat128x:
    688                 static BasicType::Kind floattype[2][12] = {
    689                         { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, (BasicType::Kind)-1, (BasicType::Kind)-1, BasicType::uFloat16Complex, BasicType::uFloat32Complex, BasicType::uFloat32xComplex, BasicType::uFloat64Complex, BasicType::uFloat64xComplex, BasicType::uFloat128Complex, BasicType::uFloat128xComplex, },
    690                         { BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128, BasicType::uFloat128x, },
     927        case DeclarationNode::Float:
     928        case DeclarationNode::Double:
     929        case DeclarationNode::LongDouble:                                       // not set until below
     930        case DeclarationNode::uuFloat80:
     931        case DeclarationNode::uuFloat128:
     932        case DeclarationNode::uFloat16:
     933        case DeclarationNode::uFloat32:
     934        case DeclarationNode::uFloat32x:
     935        case DeclarationNode::uFloat64:
     936        case DeclarationNode::uFloat64x:
     937        case DeclarationNode::uFloat128:
     938        case DeclarationNode::uFloat128x:
     939                static ast::BasicType::Kind floattype[2][12] = {
     940                        { ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, (ast::BasicType::Kind)-1, (ast::BasicType::Kind)-1, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex, },
     941                        { ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x, },
    691942                };
    692943
    693           FloatingPoint: ;
     944        FloatingPoint: ;
    694945                if ( td->signedness != DeclarationNode::NoSignedness ) {
    695946                        genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype );
     
    715966                break;
    716967
    717           case DeclarationNode::NoBasicType:
     968        case DeclarationNode::NoBasicType:
    718969                // No basic type in declaration => default double for Complex/Imaginary and int type for integral types
    719970                if ( td->complextype == DeclarationNode::Complex || td->complextype == DeclarationNode::Imaginary ) {
     
    724975                const_cast<TypeData *>(td)->basictype = DeclarationNode::Int;
    725976                goto Integral;
    726           default:
    727                 assertf( false, "unknown basic type" );
     977        default:
     978                assertf( false, "unknown basic type" );
    728979                return nullptr;
    729980        } // switch
    730981
    731         BasicType * bt = new BasicType( buildQualifiers( td ), ret );
    732         buildForall( td->forall, bt->get_forall() );
     982        ast::BasicType * bt = new ast::BasicType( ret, buildQualifiers( td ) );
    733983        return bt;
    734984} // buildBasicType
    735985
    736986
    737 PointerType * buildPointer( const TypeData * td ) {
    738         PointerType * pt;
     987ast::PointerType * buildPointer( const TypeData * td ) {
     988        ast::PointerType * pt;
    739989        if ( td->base ) {
    740                 pt = new PointerType( buildQualifiers( td ), typebuild( td->base ) );
     990                pt = new ast::PointerType(
     991                        typebuild( td->base ),
     992                        buildQualifiers( td )
     993                );
    741994        } else {
    742                 pt = new PointerType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
     995                pt = new ast::PointerType(
     996                        new ast::BasicType( ast::BasicType::SignedInt ),
     997                        buildQualifiers( td )
     998                );
    743999        } // if
    744         buildForall( td->forall, pt->get_forall() );
    7451000        return pt;
    7461001} // buildPointer
    7471002
    7481003
    749 ArrayType * buildArray( const TypeData * td ) {
    750         ArrayType * at;
     1004ast::ArrayType * buildArray( const TypeData * td ) {
     1005        ast::ArrayType * at;
    7511006        if ( td->base ) {
    752                 at = new ArrayType( buildQualifiers( td ), typebuild( td->base ), maybeBuild< Expression >( td->array.dimension ),
    753                                                         td->array.isVarLen, td->array.isStatic );
     1007                at = new ast::ArrayType(
     1008                        typebuild( td->base ),
     1009                        maybeBuild( td->array.dimension ),
     1010                        td->array.isVarLen ? ast::VariableLen : ast::FixedLen,
     1011                        td->array.isStatic ? ast::StaticDim : ast::DynamicDim,
     1012                        buildQualifiers( td )
     1013                );
    7541014        } else {
    755                 at = new ArrayType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ),
    756                                                         maybeBuild< Expression >( td->array.dimension ), td->array.isVarLen, td->array.isStatic );
     1015                at = new ast::ArrayType(
     1016                        new ast::BasicType( ast::BasicType::SignedInt ),
     1017                        maybeBuild( td->array.dimension ),
     1018                        td->array.isVarLen ? ast::VariableLen : ast::FixedLen,
     1019                        td->array.isStatic ? ast::StaticDim : ast::DynamicDim,
     1020                        buildQualifiers( td )
     1021                );
    7571022        } // if
    758         buildForall( td->forall, at->get_forall() );
    7591023        return at;
    7601024} // buildArray
    7611025
    7621026
    763 ReferenceType * buildReference( const TypeData * td ) {
    764         ReferenceType * rt;
     1027ast::ReferenceType * buildReference( const TypeData * td ) {
     1028        ast::ReferenceType * rt;
    7651029        if ( td->base ) {
    766                 rt = new ReferenceType( buildQualifiers( td ), typebuild( td->base ) );
     1030                rt = new ast::ReferenceType(
     1031                        typebuild( td->base ),
     1032                        buildQualifiers( td )
     1033                );
    7671034        } else {
    768                 rt = new ReferenceType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
     1035                rt = new ast::ReferenceType(
     1036                        new ast::BasicType( ast::BasicType::SignedInt ),
     1037                        buildQualifiers( td )
     1038                );
    7691039        } // if
    770         buildForall( td->forall, rt->get_forall() );
    7711040        return rt;
    7721041} // buildReference
    7731042
    7741043
    775 AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
     1044ast::AggregateDecl * buildAggregate( const TypeData * td, std::vector<ast::ptr<ast::Attribute>> attributes, ast::Linkage::Spec linkage ) {
    7761045        assert( td->kind == TypeData::Aggregate );
    777         AggregateDecl * at;
     1046        ast::AggregateDecl * at;
    7781047        switch ( td->aggregate.kind ) {
    779           case AggregateDecl::Struct:
    780           case AggregateDecl::Coroutine:
    781           case AggregateDecl::Exception:
    782           case AggregateDecl::Generator:
    783           case AggregateDecl::Monitor:
    784           case AggregateDecl::Thread:
    785                 at = new StructDecl( *td->aggregate.name, td->aggregate.kind, attributes, linkage );
    786                 buildForall( td->aggregate.params, at->get_parameters() );
    787                 break;
    788           case AggregateDecl::Union:
    789                 at = new UnionDecl( *td->aggregate.name, attributes, linkage );
    790                 buildForall( td->aggregate.params, at->get_parameters() );
    791                 break;
    792           case AggregateDecl::Trait:
    793                 at = new TraitDecl( *td->aggregate.name, attributes, linkage );
    794                 buildList( td->aggregate.params, at->get_parameters() );
    795                 break;
    796           default:
     1048        case ast::AggregateDecl::Struct:
     1049        case ast::AggregateDecl::Coroutine:
     1050        case ast::AggregateDecl::Exception:
     1051        case ast::AggregateDecl::Generator:
     1052        case ast::AggregateDecl::Monitor:
     1053        case ast::AggregateDecl::Thread:
     1054                at = new ast::StructDecl( td->location,
     1055                        *td->aggregate.name,
     1056                        td->aggregate.kind,
     1057                        std::move( attributes ),
     1058                        linkage
     1059                );
     1060                buildForall( td->aggregate.params, at->params );
     1061                break;
     1062        case ast::AggregateDecl::Union:
     1063                at = new ast::UnionDecl( td->location,
     1064                        *td->aggregate.name,
     1065                        std::move( attributes ),
     1066                        linkage
     1067                );
     1068                buildForall( td->aggregate.params, at->params );
     1069                break;
     1070        case ast::AggregateDecl::Trait:
     1071                at = new ast::TraitDecl( td->location,
     1072                        *td->aggregate.name,
     1073                        std::move( attributes ),
     1074                        linkage
     1075                );
     1076                buildList( td->aggregate.params, at->params );
     1077                break;
     1078        default:
    7971079                assert( false );
    7981080        } // switch
    7991081
    800         buildList( td->aggregate.fields, at->get_members() );
     1082        buildList( td->aggregate.fields, at->members );
    8011083        at->set_body( td->aggregate.body );
    8021084
     
    8051087
    8061088
    807 ReferenceToType * buildComAggInst( const TypeData * type, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
     1089ast::BaseInstType * buildComAggInst(
     1090                const TypeData * type,
     1091                std::vector<ast::ptr<ast::Attribute>> && attributes,
     1092                ast::Linkage::Spec linkage ) {
    8081093        switch ( type->kind ) {
    809           case TypeData::Enum: {
    810                   if ( type->enumeration.body ) {
    811                           EnumDecl * typedecl = buildEnum( type, attributes, linkage );
    812                           return new EnumInstType( buildQualifiers( type ), typedecl );
    813                   } else {
    814                           return new EnumInstType( buildQualifiers( type ), *type->enumeration.name );
    815                   } // if
    816           }
    817           case TypeData::Aggregate: {
    818                   ReferenceToType * ret;
    819                   if ( type->aggregate.body ) {
    820                           AggregateDecl * typedecl = buildAggregate( type, attributes, linkage );
    821                           switch ( type->aggregate.kind ) {
    822                                 case AggregateDecl::Struct:
    823                                 case AggregateDecl::Coroutine:
    824                                 case AggregateDecl::Monitor:
    825                                 case AggregateDecl::Thread:
    826                                   ret = new StructInstType( buildQualifiers( type ), (StructDecl *)typedecl );
    827                                   break;
    828                                 case AggregateDecl::Union:
    829                                   ret = new UnionInstType( buildQualifiers( type ), (UnionDecl *)typedecl );
    830                                   break;
    831                                 case AggregateDecl::Trait:
    832                                   assert( false );
    833                                   //ret = new TraitInstType( buildQualifiers( type ), (TraitDecl *)typedecl );
    834                                   break;
    835                                 default:
    836                                   assert( false );
    837                           } // switch
    838                   } else {
    839                           switch ( type->aggregate.kind ) {
    840                                 case AggregateDecl::Struct:
    841                                 case AggregateDecl::Coroutine:
    842                                 case AggregateDecl::Monitor:
    843                                 case AggregateDecl::Thread:
    844                                   ret = new StructInstType( buildQualifiers( type ), *type->aggregate.name );
    845                                   break;
    846                                 case AggregateDecl::Union:
    847                                   ret = new UnionInstType( buildQualifiers( type ), *type->aggregate.name );
    848                                   break;
    849                                 case AggregateDecl::Trait:
    850                                   ret = new TraitInstType( buildQualifiers( type ), *type->aggregate.name );
    851                                   break;
    852                                 default:
    853                                   assert( false );
    854                           } // switch
    855                   } // if
    856                   return ret;
    857           }
    858           default:
     1094        case TypeData::Enum:
     1095                if ( type->enumeration.body ) {
     1096                        ast::EnumDecl * typedecl =
     1097                                buildEnum( type, std::move( attributes ), linkage );
     1098                        return new ast::EnumInstType(
     1099                                typedecl,
     1100                                buildQualifiers( type )
     1101                        );
     1102                } else {
     1103                        return new ast::EnumInstType(
     1104                                *type->enumeration.name,
     1105                                buildQualifiers( type )
     1106                        );
     1107                } // if
     1108                break;
     1109        case TypeData::Aggregate:
     1110                if ( type->aggregate.body ) {
     1111                        ast::AggregateDecl * typedecl =
     1112                                buildAggregate( type, std::move( attributes ), linkage );
     1113                        switch ( type->aggregate.kind ) {
     1114                        case ast::AggregateDecl::Struct:
     1115                        case ast::AggregateDecl::Coroutine:
     1116                        case ast::AggregateDecl::Monitor:
     1117                        case ast::AggregateDecl::Thread:
     1118                                return new ast::StructInstType(
     1119                                        strict_dynamic_cast<ast::StructDecl *>( typedecl ),
     1120                                        buildQualifiers( type )
     1121                                );
     1122                        case ast::AggregateDecl::Union:
     1123                                return new ast::UnionInstType(
     1124                                        strict_dynamic_cast<ast::UnionDecl *>( typedecl ),
     1125                                        buildQualifiers( type )
     1126                                );
     1127                        case ast::AggregateDecl::Trait:
     1128                                assert( false );
     1129                                break;
     1130                        default:
     1131                                assert( false );
     1132                        } // switch
     1133                } else {
     1134                        switch ( type->aggregate.kind ) {
     1135                        case ast::AggregateDecl::Struct:
     1136                        case ast::AggregateDecl::Coroutine:
     1137                        case ast::AggregateDecl::Monitor:
     1138                        case ast::AggregateDecl::Thread:
     1139                                return new ast::StructInstType(
     1140                                        *type->aggregate.name,
     1141                                        buildQualifiers( type )
     1142                                );
     1143                        case ast::AggregateDecl::Union:
     1144                                return new ast::UnionInstType(
     1145                                        *type->aggregate.name,
     1146                                        buildQualifiers( type )
     1147                                );
     1148                        case ast::AggregateDecl::Trait:
     1149                                return new ast::TraitInstType(
     1150                                        *type->aggregate.name,
     1151                                        buildQualifiers( type )
     1152                                );
     1153                        default:
     1154                                assert( false );
     1155                        } // switch
     1156                        break;
     1157                } // if
     1158                break;
     1159        default:
    8591160                assert( false );
    8601161        } // switch
     1162        assert( false );
    8611163} // buildAggInst
    8621164
    8631165
    864 ReferenceToType * buildAggInst( const TypeData * td ) {
     1166ast::BaseInstType * buildAggInst( const TypeData * td ) {
    8651167        assert( td->kind == TypeData::AggregateInst );
    8661168
    867         // ReferenceToType * ret = buildComAggInst( td->aggInst.aggregate, std::list< Attribute * >() );
    868         ReferenceToType * ret = nullptr;
     1169        ast::BaseInstType * ret = nullptr;
    8691170        TypeData * type = td->aggInst.aggregate;
    8701171        switch ( type->kind ) {
    871           case TypeData::Enum: {
    872                   return new EnumInstType( buildQualifiers( type ), *type->enumeration.name );
    873           }
    874           case TypeData::Aggregate: {
    875                   switch ( type->aggregate.kind ) {
    876                         case AggregateDecl::Struct:
    877                         case AggregateDecl::Coroutine:
    878                         case AggregateDecl::Monitor:
    879                         case AggregateDecl::Thread:
    880                           ret = new StructInstType( buildQualifiers( type ), *type->aggregate.name );
    881                           break;
    882                         case AggregateDecl::Union:
    883                           ret = new UnionInstType( buildQualifiers( type ), *type->aggregate.name );
    884                           break;
    885                         case AggregateDecl::Trait:
    886                           ret = new TraitInstType( buildQualifiers( type ), *type->aggregate.name );
    887                           break;
    888                         default:
    889                           assert( false );
    890                   } // switch
    891           }
    892           break;
    893           default:
     1172        case TypeData::Enum:
     1173                return new ast::EnumInstType(
     1174                        *type->enumeration.name,
     1175                        buildQualifiers( type )
     1176                );
     1177        case TypeData::Aggregate:
     1178                switch ( type->aggregate.kind ) {
     1179                case ast::AggregateDecl::Struct:
     1180                case ast::AggregateDecl::Coroutine:
     1181                case ast::AggregateDecl::Monitor:
     1182                case ast::AggregateDecl::Thread:
     1183                        ret = new ast::StructInstType(
     1184                                *type->aggregate.name,
     1185                                buildQualifiers( type )
     1186                        );
     1187                        break;
     1188                case ast::AggregateDecl::Union:
     1189                        ret = new ast::UnionInstType(
     1190                                *type->aggregate.name,
     1191                                buildQualifiers( type )
     1192                        );
     1193                        break;
     1194                case ast::AggregateDecl::Trait:
     1195                        ret = new ast::TraitInstType(
     1196                                *type->aggregate.name,
     1197                                buildQualifiers( type )
     1198                        );
     1199                        break;
     1200                default:
     1201                        assert( false );
     1202                } // switch
     1203                break;
     1204        default:
    8941205                assert( false );
    8951206        } // switch
    8961207
    897         ret->set_hoistType( td->aggInst.hoistType );
    898         buildList( td->aggInst.params, ret->get_parameters() );
    899         buildForall( td->forall, ret->get_forall() );
     1208        ret->hoistType = td->aggInst.hoistType;
     1209        buildList( td->aggInst.params, ret->params );
    9001210        return ret;
    9011211} // buildAggInst
    9021212
    9031213
    904 NamedTypeDecl * buildSymbolic( const TypeData * td, std::list< Attribute * > attributes, const string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage ) {
     1214ast::NamedTypeDecl * buildSymbolic(
     1215                const TypeData * td,
     1216                std::vector<ast::ptr<ast::Attribute>> attributes,
     1217                const std::string & name,
     1218                ast::Storage::Classes scs,
     1219                ast::Linkage::Spec linkage ) {
    9051220        assert( td->kind == TypeData::Symbolic );
    906         NamedTypeDecl * ret;
     1221        ast::NamedTypeDecl * ret;
    9071222        assert( td->base );
    9081223        if ( td->symbolic.isTypedef ) {
    909                 ret = new TypedefDecl( name, td->location, scs, typebuild( td->base ), linkage );
     1224                ret = new ast::TypedefDecl(
     1225                        td->location,
     1226                        name,
     1227                        scs,
     1228                        typebuild( td->base ),
     1229                        linkage
     1230                );
    9101231        } else {
    911                 ret = new TypeDecl( name, scs, typebuild( td->base ), TypeDecl::Dtype, true );
     1232                ret = new ast::TypeDecl(
     1233                        td->location,
     1234                        name,
     1235                        scs,
     1236                        typebuild( td->base ),
     1237                        ast::TypeDecl::Dtype,
     1238                        true
     1239                );
    9121240        } // if
    913         buildList( td->symbolic.assertions, ret->get_assertions() );
    914         ret->base->attributes.splice( ret->base->attributes.end(), attributes );
     1241        buildList( td->symbolic.assertions, ret->assertions );
     1242        splice( ret->base.get_and_mutate()->attributes, attributes );
    9151243        return ret;
    9161244} // buildSymbolic
    9171245
    9181246
    919 EnumDecl * buildEnum( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {
     1247ast::EnumDecl * buildEnum(
     1248                const TypeData * td,
     1249                std::vector<ast::ptr<ast::Attribute>> && attributes,
     1250                ast::Linkage::Spec linkage ) {
    9201251        assert( td->kind == TypeData::Enum );
    921         Type * baseType = td->base ? typebuild(td->base) : nullptr;
    922         EnumDecl * ret = new EnumDecl( *td->enumeration.name, attributes, td->enumeration.typed, linkage, baseType );
    923         buildList( td->enumeration.constants, ret->get_members() );
    924         list< Declaration * >::iterator members = ret->get_members().begin();
    925         ret->hide = td->enumeration.hiding == EnumHiding::Hide ? EnumDecl::EnumHiding::Hide : EnumDecl::EnumHiding::Visible;
     1252        ast::Type * baseType = td->base ? typebuild(td->base) : nullptr;
     1253        ast::EnumDecl * ret = new ast::EnumDecl(
     1254                td->location,
     1255                *td->enumeration.name,
     1256                td->enumeration.typed,
     1257                std::move( attributes ),
     1258                linkage,
     1259                baseType
     1260        );
     1261        buildList( td->enumeration.constants, ret->members );
     1262        auto members = ret->members.begin();
     1263        ret->hide = td->enumeration.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible;
    9261264        for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) {
    9271265                if ( cur->enumInLine ) {
     
    9301268                        SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." );
    9311269                } else if ( cur->has_enumeratorValue() ) {
    932                         ObjectDecl * member = dynamic_cast< ObjectDecl * >(* members);
    933                         member->set_init( new SingleInit( maybeMoveBuild< Expression >( cur->consume_enumeratorValue() ) ) );
     1270                        ast::Decl * member = members->get_and_mutate();
     1271                        ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member );
     1272                        object->init = new ast::SingleInit(
     1273                                td->location,
     1274                                maybeMoveBuild( cur->consume_enumeratorValue() ),
     1275                                ast::NoConstruct
     1276                        );
    9341277                } else if ( !cur->initializer ) {
    935                         if ( baseType && (!dynamic_cast<BasicType *>(baseType) || !dynamic_cast<BasicType *>(baseType)->isWholeNumber())) {
     1278                        if ( baseType && (!dynamic_cast<ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) {
    9361279                                SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." );
    9371280                        }
     
    9401283                // if
    9411284        } // for
    942         ret->set_body( td->enumeration.body );
     1285        ret->body = td->enumeration.body;
    9431286        return ret;
    9441287} // buildEnum
    9451288
    9461289
    947 TypeInstType * buildSymbolicInst( const TypeData * td ) {
     1290ast::TypeInstType * buildSymbolicInst( const TypeData * td ) {
    9481291        assert( td->kind == TypeData::SymbolicInst );
    949         TypeInstType * ret = new TypeInstType( buildQualifiers( td ), *td->symbolic.name, false );
    950         buildList( td->symbolic.actuals, ret->get_parameters() );
    951         buildForall( td->forall, ret->get_forall() );
     1292        ast::TypeInstType * ret = new ast::TypeInstType(
     1293                *td->symbolic.name,
     1294                ast::TypeDecl::Dtype,
     1295                buildQualifiers( td )
     1296        );
     1297        buildList( td->symbolic.actuals, ret->params );
    9521298        return ret;
    9531299} // buildSymbolicInst
    9541300
    9551301
    956 TupleType * buildTuple( const TypeData * td ) {
     1302ast::TupleType * buildTuple( const TypeData * td ) {
    9571303        assert( td->kind == TypeData::Tuple );
    958         std::list< Type * > types;
     1304        std::vector<ast::ptr<ast::Type>> types;
    9591305        buildTypeList( td->tuple, types );
    960         TupleType * ret = new TupleType( buildQualifiers( td ), types );
    961         buildForall( td->forall, ret->get_forall() );
     1306        ast::TupleType * ret = new ast::TupleType(
     1307                std::move( types ),
     1308                buildQualifiers( td )
     1309        );
    9621310        return ret;
    9631311} // buildTuple
    9641312
    9651313
    966 TypeofType * buildTypeof( const TypeData * td ) {
     1314ast::TypeofType * buildTypeof( const TypeData * td ) {
    9671315        assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof );
    9681316        assert( td->typeexpr );
    969         // assert( td->typeexpr->expr );
    970         return new TypeofType{ buildQualifiers( td ), td->typeexpr->build(), td->kind == TypeData::Basetypeof };
     1317        return new ast::TypeofType(
     1318                td->typeexpr->build(),
     1319                td->kind == TypeData::Typeof
     1320                        ? ast::TypeofType::Typeof : ast::TypeofType::Basetypeof,
     1321                buildQualifiers( td )
     1322        );
    9711323} // buildTypeof
    9721324
    9731325
    974 VTableType * buildVtable( const TypeData * td ) {
     1326ast::VTableType * buildVtable( const TypeData * td ) {
    9751327        assert( td->base );
    976         return new VTableType{ buildQualifiers( td ), typebuild( td->base ) };
     1328        return new ast::VTableType(
     1329                typebuild( td->base ),
     1330                buildQualifiers( td )
     1331        );
    9771332} // buildVtable
    9781333
    9791334
    980 Declaration * buildDecl( const TypeData * td, const string &name, Type::StorageClasses scs, Expression * bitfieldWidth, Type::FuncSpecifiers funcSpec, LinkageSpec::Spec linkage, Expression *asmName, Initializer * init, std::list< Attribute * > attributes ) {
     1335ast::FunctionDecl * buildFunctionDecl(
     1336                const TypeData * td,
     1337                const string &name,
     1338                ast::Storage::Classes scs,
     1339                ast::Function::Specs funcSpec,
     1340                ast::Linkage::Spec linkage,
     1341                ast::Expr * asmName,
     1342                std::vector<ast::ptr<ast::Attribute>> && attributes ) {
     1343        assert( td->kind == TypeData::Function );
     1344        // For some reason FunctionDecl takes a bool instead of an ArgumentFlag.
     1345        bool isVarArgs = !td->function.params || td->function.params->hasEllipsis;
     1346        ast::CV::Qualifiers cvq = buildQualifiers( td );
     1347        std::vector<ast::ptr<ast::TypeDecl>> forall;
     1348        std::vector<ast::ptr<ast::DeclWithType>> assertions;
     1349        std::vector<ast::ptr<ast::DeclWithType>> params;
     1350        std::vector<ast::ptr<ast::DeclWithType>> returns;
     1351        buildList( td->function.params, params );
     1352        buildForall( td->forall, forall );
     1353        // Functions do not store their assertions there anymore.
     1354        for ( ast::ptr<ast::TypeDecl> & type_param : forall ) {
     1355                auto mut = type_param.get_and_mutate();
     1356                splice( assertions, mut->assertions );
     1357        }
     1358        if ( td->base ) {
     1359                switch ( td->base->kind ) {
     1360                case TypeData::Tuple:
     1361                        buildList( td->base->tuple, returns );
     1362                        break;
     1363                default:
     1364                        returns.push_back( dynamic_cast<ast::DeclWithType *>(
     1365                                buildDecl(
     1366                                        td->base,
     1367                                        "",
     1368                                        ast::Storage::Classes(),
     1369                                        (ast::Expr *)nullptr, // bitfieldWidth
     1370                                        ast::Function::Specs(),
     1371                                        ast::Linkage::Cforall,
     1372                                        (ast::Expr *)nullptr // asmName
     1373                                )
     1374                        ) );
     1375                } // switch
     1376        } else {
     1377                returns.push_back( new ast::ObjectDecl(
     1378                        td->location,
     1379                        "",
     1380                        new ast::BasicType( ast::BasicType::SignedInt ),
     1381                        (ast::Init *)nullptr,
     1382                        ast::Storage::Classes(),
     1383                        ast::Linkage::Cforall
     1384                ) );
     1385        } // if
     1386        ast::Stmt * stmt = maybeBuild( td->function.body );
     1387        ast::CompoundStmt * body = dynamic_cast<ast::CompoundStmt *>( stmt );
     1388        ast::FunctionDecl * decl = new ast::FunctionDecl( td->location,
     1389                name,
     1390                std::move( forall ),
     1391                std::move( assertions ),
     1392                std::move( params ),
     1393                std::move( returns ),
     1394                body,
     1395                scs,
     1396                linkage,
     1397                std::move( attributes ),
     1398                funcSpec,
     1399                (isVarArgs) ? ast::VariableArgs : ast::FixedArgs
     1400        );
     1401        buildList( td->function.withExprs, decl->withExprs );
     1402        decl->asmName = asmName;
     1403        // This may be redundant on a declaration.
     1404        decl->type.get_and_mutate()->qualifiers = cvq;
     1405        return decl;
     1406} // buildFunctionDecl
     1407
     1408
     1409ast::Decl * buildDecl(
     1410                const TypeData * td,
     1411                const string &name,
     1412                ast::Storage::Classes scs,
     1413                ast::Expr * bitfieldWidth,
     1414                ast::Function::Specs funcSpec,
     1415                ast::Linkage::Spec linkage,
     1416                ast::Expr * asmName,
     1417                ast::Init * init,
     1418                std::vector<ast::ptr<ast::Attribute>> && attributes ) {
    9811419        if ( td->kind == TypeData::Function ) {
    9821420                if ( td->function.idList ) {                                    // KR function ?
     
    9841422                } // if
    9851423
    986                 FunctionDecl * decl;
    987                 Statement * stmt = maybeBuild<Statement>( td->function.body );
    988                 CompoundStmt * body = dynamic_cast< CompoundStmt * >( stmt );
    989                 decl = new FunctionDecl( name, scs, linkage, buildFunction( td ), body, attributes, funcSpec );
    990                 buildList( td->function.withExprs, decl->withExprs );
    991                 return decl->set_asmName( asmName );
     1424                return buildFunctionDecl(
     1425                        td, name, scs, funcSpec, linkage,
     1426                        asmName, std::move( attributes ) );
    9921427        } else if ( td->kind == TypeData::Aggregate ) {
    993                 return buildAggregate( td, attributes, linkage );
     1428                return buildAggregate( td, std::move( attributes ), linkage );
    9941429        } else if ( td->kind == TypeData::Enum ) {
    995                 return buildEnum( td, attributes, linkage );
     1430                return buildEnum( td, std::move( attributes ), linkage );
    9961431        } else if ( td->kind == TypeData::Symbolic ) {
    997                 return buildSymbolic( td, attributes, name, scs, linkage );
     1432                return buildSymbolic( td, std::move( attributes ), name, scs, linkage );
    9981433        } else {
    999                 return (new ObjectDecl( name, scs, linkage, bitfieldWidth, typebuild( td ), init, attributes ))->set_asmName( asmName );
     1434                auto ret = new ast::ObjectDecl( td->location,
     1435                        name,
     1436                        typebuild( td ),
     1437                        init,
     1438                        scs,
     1439                        linkage,
     1440                        bitfieldWidth,
     1441                        std::move( attributes )
     1442                );
     1443                ret->asmName = asmName;
     1444                return ret;
    10001445        } // if
    10011446        return nullptr;
     
    10031448
    10041449
    1005 FunctionType * buildFunction( const TypeData * td ) {
     1450ast::FunctionType * buildFunctionType( const TypeData * td ) {
    10061451        assert( td->kind == TypeData::Function );
    1007         FunctionType * ft = new FunctionType( buildQualifiers( td ), ! td->function.params || td->function.params->hasEllipsis );
    1008         buildList( td->function.params, ft->parameters );
     1452        ast::FunctionType * ft = new ast::FunctionType(
     1453                ( !td->function.params || td->function.params->hasEllipsis )
     1454                        ? ast::VariableArgs : ast::FixedArgs,
     1455                buildQualifiers( td )
     1456        );
     1457        buildTypeList( td->function.params, ft->params );
    10091458        buildForall( td->forall, ft->forall );
    10101459        if ( td->base ) {
    10111460                switch ( td->base->kind ) {
    1012                   case TypeData::Tuple:
    1013                         buildList( td->base->tuple, ft->returnVals );
     1461                case TypeData::Tuple:
     1462                        buildTypeList( td->base->tuple, ft->returns );
    10141463                        break;
    1015                   default:
    1016                         ft->get_returnVals().push_back( dynamic_cast< DeclarationWithType * >( buildDecl( td->base, "", Type::StorageClasses(), nullptr, Type::FuncSpecifiers(), LinkageSpec::Cforall, nullptr ) ) );
     1464                default:
     1465                        ft->returns.push_back( typebuild( td->base ) );
     1466                        break;
    10171467                } // switch
    10181468        } else {
    1019                 ft->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ) );
     1469                ft->returns.push_back(
     1470                        new ast::BasicType( ast::BasicType::SignedInt ) );
    10201471        } // if
    10211472        return ft;
    1022 } // buildFunction
     1473} // buildFunctionType
    10231474
    10241475
     
    10511502                                param->type = decl->type;                               // set copy declaration type to parameter type
    10521503                                decl->type = nullptr;                                   // reset declaration type
    1053                                 param->attributes.splice( param->attributes.end(), decl->attributes ); // copy and reset attributes from declaration to parameter
     1504                                // Copy and reset attributes from declaration to parameter:
     1505                                splice( param->attributes, decl->attributes );
    10541506                        } // if
    10551507                } // for
  • src/Parser/TypeData.h

    r34b4268 r24d6572  
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat May 16 15:18:36 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 10 22:18:49 2022
    13 // Update Count     : 203
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Mar  1 10:44:00 2023
     13// Update Count     : 206
    1414//
    1515
    1616#pragma once
    1717
    18 #include <iosfwd>                                                                               // for ostream
    19 #include <list>                                                                                 // for list
    20 #include <string>                                                                               // for string
     18#include <iosfwd>                                   // for ostream
     19#include <list>                                     // for list
     20#include <string>                                   // for string
    2121
    22 #include "ParseNode.h"                                                                  // for DeclarationNode, DeclarationNode::Ag...
    23 #include "SynTree/LinkageSpec.h"                                                // for Spec
    24 #include "SynTree/Type.h"                                                               // for Type, ReferenceToType (ptr only)
    25 #include "SynTree/SynTree.h"                                                    // for Visitor Nodes
     22#include "AST/Type.hpp"                             // for Type
     23#include "DeclarationNode.h"                        // for DeclarationNode
    2624
    2725struct TypeData {
     
    3028
    3129        struct Aggregate_t {
    32                 AggregateDecl::Aggregate kind;
     30                ast::AggregateDecl::Aggregate kind;
    3331                const std::string * name = nullptr;
    3432                DeclarationNode * params = nullptr;
     
    3735                bool body;
    3836                bool anon;
    39 
    4037                bool tagged;
    4138                const std::string * parent = nullptr;
     
    9491        DeclarationNode::BuiltinType builtintype = DeclarationNode::NoBuiltinType;
    9592
    96         Type::Qualifiers qualifiers;
     93        ast::CV::Qualifiers qualifiers;
    9794        DeclarationNode * forall = nullptr;
    9895
     
    115112};
    116113
    117 Type * typebuild( const TypeData * );
     114ast::Type * typebuild( const TypeData * );
    118115TypeData * typeextractAggregate( const TypeData * td, bool toplevel = true );
    119 Type::Qualifiers buildQualifiers( const TypeData * td );
    120 Type * buildBasicType( const TypeData * );
    121 PointerType * buildPointer( const TypeData * );
    122 ArrayType * buildArray( const TypeData * );
    123 ReferenceType * buildReference( const TypeData * );
    124 AggregateDecl * buildAggregate( const TypeData *, std::list< Attribute * > );
    125 ReferenceToType * buildComAggInst( const TypeData *, std::list< Attribute * > attributes, LinkageSpec::Spec linkage );
    126 ReferenceToType * buildAggInst( const TypeData * );
    127 TypeDecl * buildVariable( const TypeData * );
    128 EnumDecl * buildEnum( const TypeData *, std::list< Attribute * >, LinkageSpec::Spec );
    129 TypeInstType * buildSymbolicInst( const TypeData * );
    130 TupleType * buildTuple( const TypeData * );
    131 TypeofType * buildTypeof( const TypeData * );
    132 VTableType * buildVtable( const TypeData * );
    133 Declaration * buildDecl( const TypeData *, const std::string &, Type::StorageClasses, Expression *, Type::FuncSpecifiers funcSpec, LinkageSpec::Spec, Expression * asmName,
    134                                                  Initializer * init = nullptr, std::list< class Attribute * > attributes = std::list< class Attribute * >() );
    135 FunctionType * buildFunction( const TypeData * );
    136 Declaration * addEnumBase( Declaration *, const TypeData * );
     116ast::CV::Qualifiers buildQualifiers( const TypeData * td );
     117ast::Type * buildBasicType( const TypeData * );
     118ast::PointerType * buildPointer( const TypeData * );
     119ast::ArrayType * buildArray( const TypeData * );
     120ast::ReferenceType * buildReference( const TypeData * );
     121ast::AggregateDecl * buildAggregate( const TypeData *, std::vector<ast::ptr<ast::Attribute>> );
     122ast::BaseInstType * buildComAggInst( const TypeData *, std::vector<ast::ptr<ast::Attribute>> && attributes, ast::Linkage::Spec linkage );
     123ast::BaseInstType * buildAggInst( const TypeData * );
     124ast::TypeDecl * buildVariable( const TypeData * );
     125ast::EnumDecl * buildEnum( const TypeData *, std::vector<ast::ptr<ast::Attribute>> &&, ast::Linkage::Spec );
     126ast::TypeInstType * buildSymbolicInst( const TypeData * );
     127ast::TupleType * buildTuple( const TypeData * );
     128ast::TypeofType * buildTypeof( const TypeData * );
     129ast::VTableType * buildVtable( const TypeData * );
     130ast::Decl * buildDecl(
     131        const TypeData *, const std::string &, ast::Storage::Classes, ast::Expr *,
     132        ast::Function::Specs funcSpec, ast::Linkage::Spec, ast::Expr * asmName,
     133        ast::Init * init = nullptr, std::vector<ast::ptr<ast::Attribute>> && attributes = std::vector<ast::ptr<ast::Attribute>>() );
     134ast::FunctionType * buildFunctionType( const TypeData * );
     135ast::Decl * addEnumBase( Declaration *, const TypeData * );
    137136void buildKRFunction( const TypeData::Function_t & function );
    138137
  • src/Parser/TypedefTable.cc

    r34b4268 r24d6572  
    1616
    1717#include "TypedefTable.h"
    18 #include <cassert>                                                                              // for assert
    19 #include <iostream>
     18
     19#include <cassert>                                // for assert
     20#include <string>                                 // for string
     21#include <iostream>                               // for iostream
     22
     23#include "ExpressionNode.h"                       // for LabelNode
     24#include "ParserTypes.h"                          // for Token
     25#include "StatementNode.h"                        // for CondCtl, ForCtrl
     26// This (generated) header must come late as it is missing includes.
     27#include "parser.hh"              // for IDENTIFIER, TYPEDEFname, TYPEGENname
     28
    2029using namespace std;
    2130
    2231#if 0
    2332#define debugPrint( code ) code
     33
     34static const char *kindName( int kind ) {
     35        switch ( kind ) {
     36        case IDENTIFIER: return "identifier";
     37        case TYPEDIMname: return "typedim";
     38        case TYPEDEFname: return "typedef";
     39        case TYPEGENname: return "typegen";
     40        default:
     41                cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;
     42                abort();
     43        } // switch
     44} // kindName
    2445#else
    2546#define debugPrint( code )
    2647#endif
    27 
    28 using namespace std;                                                                    // string, iostream
    29 
    30 debugPrint(
    31         static const char *kindName( int kind ) {
    32                 switch ( kind ) {
    33                   case IDENTIFIER: return "identifier";
    34                   case TYPEDIMname: return "typedim";
    35                   case TYPEDEFname: return "typedef";
    36                   case TYPEGENname: return "typegen";
    37                   default:
    38                         cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;
    39                         abort();
    40                 } // switch
    41         } // kindName
    42 );
    4348
    4449TypedefTable::~TypedefTable() {
     
    7883                typedefTable.addToEnclosingScope( name, kind, "MTD" );
    7984        } // if
     85} // TypedefTable::makeTypedef
     86
     87void TypedefTable::makeTypedef( const string & name ) {
     88        return makeTypedef( name, TYPEDEFname );
    8089} // TypedefTable::makeTypedef
    8190
  • src/Parser/TypedefTable.h

    r34b4268 r24d6572  
    1919
    2020#include "Common/ScopedMap.h"                                                   // for ScopedMap
    21 #include "ParserTypes.h"
    22 #include "parser.hh"                                                                    // for IDENTIFIER, TYPEDEFname, TYPEGENname
    2321
    2422class TypedefTable {
    2523        struct Note { size_t level; bool forall; };
    2624        typedef ScopedMap< std::string, int, Note > KindTable;
    27         KindTable kindTable;   
     25        KindTable kindTable;
    2826        unsigned int level = 0;
    2927  public:
     
    3331        bool existsCurr( const std::string & identifier ) const;
    3432        int isKind( const std::string & identifier ) const;
    35         void makeTypedef( const std::string & name, int kind = TYPEDEFname );
     33        void makeTypedef( const std::string & name, int kind );
     34        void makeTypedef( const std::string & name );
    3635        void addToScope( const std::string & identifier, int kind, const char * );
    3736        void addToEnclosingScope( const std::string & identifier, int kind, const char * );
  • src/Parser/lex.ll

    r34b4268 r24d6572  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Thu Oct 13 20:46:04 2022
    13  * Update Count     : 764
     12 * Last Modified On : Tue May  2 08:45:21 2023
     13 * Update Count     : 769
    1414 */
    1515
     
    2323// line-number directives) and C/C++ style comments, which are ignored.
    2424
    25 //**************************** Includes and Defines ****************************
     25// *************************** Includes and Defines ****************************
    2626
    2727#ifdef __clang__
     
    4444
    4545#include "config.h"                                                                             // configure info
     46#include "DeclarationNode.h"                            // for DeclarationNode
     47#include "ExpressionNode.h"                             // for LabelNode
     48#include "InitializerNode.h"                            // for InitializerNode
    4649#include "ParseNode.h"
     50#include "ParserTypes.h"                                // for Token
     51#include "StatementNode.h"                              // for CondCtl, ForCtrl
    4752#include "TypedefTable.h"
     53// This (generated) header must come late as it is missing includes.
     54#include "parser.hh"                                    // generated info
    4855
    4956string * build_postfix_name( string * name );
     
    214221__alignof               { KEYWORD_RETURN(ALIGNOF); }                    // GCC
    215222__alignof__             { KEYWORD_RETURN(ALIGNOF); }                    // GCC
     223and                             { QKEYWORD_RETURN(WAND); }                              // CFA
    216224asm                             { KEYWORD_RETURN(ASM); }
    217225__asm                   { KEYWORD_RETURN(ASM); }                                // GCC
     
    250258enable                  { KEYWORD_RETURN(ENABLE); }                             // CFA
    251259enum                    { KEYWORD_RETURN(ENUM); }
     260exception               { KEYWORD_RETURN(EXCEPTION); }                  // CFA
    252261__extension__   { KEYWORD_RETURN(EXTENSION); }                  // GCC
    253 exception               { KEYWORD_RETURN(EXCEPTION); }                  // CFA
    254262extern                  { KEYWORD_RETURN(EXTERN); }
    255263fallthrough             { KEYWORD_RETURN(FALLTHROUGH); }                // CFA
     
    340348vtable                  { KEYWORD_RETURN(VTABLE); }                             // CFA
    341349waitfor                 { KEYWORD_RETURN(WAITFOR); }                    // CFA
     350waituntil               { KEYWORD_RETURN(WAITUNTIL); }                  // CFA
    342351when                    { KEYWORD_RETURN(WHEN); }                               // CFA
    343352while                   { KEYWORD_RETURN(WHILE); }
     
    502511        SemanticErrorThrow = true;
    503512        cerr << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1
    504                  << ": " << ErrorHelpers::error_str() << errmsg << " at token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
     513                 << ": " << ErrorHelpers::error_str() << errmsg << " before token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
    505514}
    506515
  • src/Parser/module.mk

    r34b4268 r24d6572  
    2121SRC += \
    2222       Parser/DeclarationNode.cc \
     23       Parser/DeclarationNode.h \
    2324       Parser/ExpressionNode.cc \
     25       Parser/ExpressionNode.h \
    2426       Parser/InitializerNode.cc \
     27       Parser/InitializerNode.h \
    2528       Parser/lex.ll \
    2629       Parser/ParseNode.cc \
     
    3033       Parser/parserutility.cc \
    3134       Parser/parserutility.h \
     35       Parser/RunParser.cpp \
     36       Parser/RunParser.hpp \
    3237       Parser/StatementNode.cc \
     38       Parser/StatementNode.h \
    3339       Parser/TypeData.cc \
    3440       Parser/TypeData.h \
  • src/Parser/parser.yy

    r34b4268 r24d6572  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Nov 21 22:34:30 2022
    13 // Update Count     : 5848
     12// Last Modified On : Wed Apr 26 16:45:37 2023
     13// Update Count     : 6330
    1414//
    1515
     
    4444
    4545#include <cstdio>
     46#include <sstream>
    4647#include <stack>
    4748using namespace std;
    4849
    49 #include "SynTree/Declaration.h"
    50 #include "ParseNode.h"
     50#include "SynTree/Type.h"                               // for Type
     51#include "DeclarationNode.h"                            // for DeclarationNode, ...
     52#include "ExpressionNode.h"                             // for ExpressionNode, ...
     53#include "InitializerNode.h"                            // for InitializerNode, ...
     54#include "ParserTypes.h"
     55#include "StatementNode.h"                              // for build_...
    5156#include "TypedefTable.h"
    5257#include "TypeData.h"
    53 #include "SynTree/LinkageSpec.h"
    5458#include "Common/SemanticError.h"                                               // error_str
    5559#include "Common/utility.h"                                                             // for maybeMoveBuild, maybeBuild, CodeLo...
    5660
    57 #include "SynTree/Attribute.h"     // for Attribute
     61#include "SynTree/Attribute.h"                                                  // for Attribute
    5862
    5963// lex uses __null in a boolean context, it's fine.
     
    6367
    6468extern DeclarationNode * parseTree;
    65 extern LinkageSpec::Spec linkage;
     69extern ast::Linkage::Spec linkage;
    6670extern TypedefTable typedefTable;
    6771
    68 stack<LinkageSpec::Spec> linkageStack;
     72stack<ast::Linkage::Spec> linkageStack;
    6973
    7074bool appendStr( string & to, string & from ) {
     
    199203} // fieldDecl
    200204
    201 #define NEW_ZERO new ExpressionNode( build_constantInteger( *new string( "0" ) ) )
    202 #define NEW_ONE  new ExpressionNode( build_constantInteger( *new string( "1" ) ) )
     205#define NEW_ZERO new ExpressionNode( build_constantInteger( yylloc, *new string( "0" ) ) )
     206#define NEW_ONE  new ExpressionNode( build_constantInteger( yylloc, *new string( "1" ) ) )
    203207#define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right)
    204208#define MISSING_ANON_FIELD "Missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body."
     
    206210#define MISSING_HIGH "Missing high value for down-to range so index is uninitialized."
    207211
    208 ForCtrl * forCtrl( DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
     212static ForCtrl * makeForCtrl(
     213                const CodeLocation & location,
     214                DeclarationNode * init,
     215                enum OperKinds compop,
     216                ExpressionNode * comp,
     217                ExpressionNode * inc ) {
     218        // Wrap both comp/inc if they are non-null.
     219        if ( comp ) comp = new ExpressionNode( build_binary_val( location,
     220                compop,
     221                new ExpressionNode( build_varref( location, new string( *init->name ) ) ),
     222                comp ) );
     223        if ( inc ) inc = new ExpressionNode( build_binary_val( location,
     224                // choose += or -= for upto/downto
     225                compop == OperKinds::LThan || compop == OperKinds::LEThan ? OperKinds::PlusAssn : OperKinds::MinusAssn,
     226                new ExpressionNode( build_varref( location, new string( *init->name ) ) ),
     227                inc ) );
     228        // The StatementNode call frees init->name, it must happen later.
     229        return new ForCtrl( new StatementNode( init ), comp, inc );
     230}
     231
     232ForCtrl * forCtrl( const CodeLocation & location, DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
    209233        if ( index->initializer ) {
    210234                SemanticError( yylloc, "Direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." );
     
    213237                SemanticError( yylloc, "Multiple loop indexes disallowed in for-loop declaration." );
    214238        } // if
    215         return new ForCtrl( index->addInitializer( new InitializerNode( start ) ),
    216                 // NULL comp/inc => leave blank
    217                 comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index->name ) ) ), comp ) ) : nullptr,
    218                 inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto
    219                                                         OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index->name ) ) ), inc ) ) : nullptr );
     239        DeclarationNode * initDecl = index->addInitializer( new InitializerNode( start ) );
     240        return makeForCtrl( location, initDecl, compop, comp, inc );
    220241} // forCtrl
    221242
    222 ForCtrl * forCtrl( ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
    223         ConstantExpr * constant = dynamic_cast<ConstantExpr *>(type->expr.get());
    224         if ( constant && (constant->get_constant()->get_value() == "0" || constant->get_constant()->get_value() == "1") ) {
    225                 type = new ExpressionNode( new CastExpr( maybeMoveBuild<Expression>(type), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ) );
     243ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
     244        ast::ConstantExpr * constant = dynamic_cast<ast::ConstantExpr *>(type->expr.get());
     245        if ( constant && (constant->rep == "0" || constant->rep == "1") ) {
     246                type = new ExpressionNode( new ast::CastExpr( location, maybeMoveBuild(type), new ast::BasicType( ast::BasicType::SignedInt ) ) );
    226247        } // if
    227 //      type = new ExpressionNode( build_func( new ExpressionNode( build_varref( new string( "__for_control_index_constraints__" ) ) ), type ) );
    228         return new ForCtrl(
    229                 distAttr( DeclarationNode::newTypeof( type, true ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ),
    230                 // NULL comp/inc => leave blank
    231                 comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index ) ) ), comp ) ) : nullptr,
    232                 inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto
    233                                                         OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index ) ) ), inc ) ) : nullptr );
     248        DeclarationNode * initDecl = distAttr(
     249                DeclarationNode::newTypeof( type, true ),
     250                DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) )
     251        );
     252        return makeForCtrl( location, initDecl, compop, comp, inc );
    234253} // forCtrl
    235254
    236 ForCtrl * forCtrl( ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
    237         if ( NameExpr * identifier = dynamic_cast<NameExpr *>(index->expr.get()) ) {
    238                 return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
    239         } else if ( CommaExpr * commaExpr = dynamic_cast<CommaExpr *>(index->expr.get()) ) {
    240                 if ( NameExpr * identifier = dynamic_cast<NameExpr *>(commaExpr->arg1 ) ) {
    241                         return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
     255ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {
     256        if ( auto identifier = dynamic_cast<ast::NameExpr *>(index->expr.get()) ) {
     257                return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc );
     258        } else if ( auto commaExpr = dynamic_cast<ast::CommaExpr *>( index->expr.get() ) ) {
     259                if ( auto identifier = commaExpr->arg1.as<ast::NameExpr>() ) {
     260                        return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc );
    242261                } else {
    243262                        SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr;
     
    281300%union {
    282301        Token tok;
    283         ParseNode * pn;
    284         ExpressionNode * en;
     302        ExpressionNode * expr;
    285303        DeclarationNode * decl;
    286         AggregateDecl::Aggregate aggKey;
    287         TypeDecl::Kind tclass;
    288         StatementNode * sn;
    289         WaitForStmt * wfs;
    290         Expression * constant;
     304        ast::AggregateDecl::Aggregate aggKey;
     305        ast::TypeDecl::Kind tclass;
     306        StatementNode * stmt;
     307        ClauseNode * clause;
     308        ast::WaitForStmt * wfs;
     309    ast::WaitUntilStmt::ClauseNode * wucn;
    291310        CondCtl * ifctl;
    292         ForCtrl * fctl;
    293         OperKinds compop;
    294         LabelNode * label;
    295         InitializerNode * in;
    296         OperKinds op;
     311        ForCtrl * forctl;
     312        LabelNode * labels;
     313        InitializerNode * init;
     314        OperKinds oper;
    297315        std::string * str;
    298         bool flag;
    299         EnumHiding hide;
    300         CatchStmt::Kind catch_kind;
    301         GenericExpr * genexpr;
     316        bool is_volatile;
     317        EnumHiding enum_hiding;
     318        ast::ExceptionKind except_kind;
     319        ast::GenericExpr * genexpr;
    302320}
    303321
    304 //************************* TERMINAL TOKENS ********************************
     322// ************************ TERMINAL TOKENS ********************************
    305323
    306324// keywords
     
    331349%token ATTRIBUTE EXTENSION                                                              // GCC
    332350%token IF ELSE SWITCH CASE DEFAULT DO WHILE FOR BREAK CONTINUE GOTO RETURN
    333 %token CHOOSE FALLTHRU FALLTHROUGH WITH WHEN WAITFOR    // CFA
     351%token CHOOSE FALLTHRU FALLTHROUGH WITH WHEN WAITFOR WAITUNTIL // CFA
    334352%token DISABLE ENABLE TRY THROW THROWRESUME AT                  // CFA
    335353%token ASM                                                                                              // C99, extension ISO/IEC 9899:1999 Section J.5.10(1)
     
    337355
    338356// names and constants: lexer differentiates between identifier and typedef names
    339 %token<tok> IDENTIFIER          QUOTED_IDENTIFIER       TYPEDIMname             TYPEDEFname             TYPEGENname
    340 %token<tok> TIMEOUT                     WOR                                     CATCH                   RECOVER                 CATCHRESUME             FIXUP           FINALLY         // CFA
     357%token<tok> IDENTIFIER          TYPEDIMname             TYPEDEFname             TYPEGENname
     358%token<tok> TIMEOUT                     WAND    WOR                     CATCH                   RECOVER                 CATCHRESUME             FIXUP           FINALLY         // CFA
    341359%token<tok> INTEGERconstant     CHARACTERconstant       STRINGliteral
    342360%token<tok> DIRECTIVE
     
    364382%type<tok> identifier                                   identifier_at                           identifier_or_type_name         attr_name
    365383%type<tok> quasi_keyword
    366 %type<constant> string_literal
     384%type<expr> string_literal
    367385%type<str> string_literal_list
    368386
    369 %type<hide> hide_opt                                    visible_hide_opt
     387%type<enum_hiding> hide_opt                                     visible_hide_opt
    370388
    371389// expressions
    372 %type<en> constant
    373 %type<en> tuple                                                 tuple_expression_list
    374 %type<op> ptrref_operator                               unary_operator                          assignment_operator                     simple_assignment_operator      compound_assignment_operator
    375 %type<en> primary_expression                    postfix_expression                      unary_expression
    376 %type<en> cast_expression_list                  cast_expression                         exponential_expression          multiplicative_expression       additive_expression
    377 %type<en> shift_expression                              relational_expression           equality_expression
    378 %type<en> AND_expression                                exclusive_OR_expression         inclusive_OR_expression
    379 %type<en> logical_AND_expression                logical_OR_expression
    380 %type<en> conditional_expression                constant_expression                     assignment_expression           assignment_expression_opt
    381 %type<en> comma_expression                              comma_expression_opt
    382 %type<en> argument_expression_list_opt  argument_expression_list        argument_expression                     default_initializer_opt
     390%type<expr> constant
     391%type<expr> tuple                                                       tuple_expression_list
     392%type<oper> ptrref_operator                             unary_operator                          assignment_operator                     simple_assignment_operator      compound_assignment_operator
     393%type<expr> primary_expression                  postfix_expression                      unary_expression
     394%type<expr> cast_expression_list                        cast_expression                         exponential_expression          multiplicative_expression       additive_expression
     395%type<expr> shift_expression                            relational_expression           equality_expression
     396%type<expr> AND_expression                              exclusive_OR_expression         inclusive_OR_expression
     397%type<expr> logical_AND_expression              logical_OR_expression
     398%type<expr> conditional_expression              constant_expression                     assignment_expression           assignment_expression_opt
     399%type<expr> comma_expression                            comma_expression_opt
     400%type<expr> argument_expression_list_opt        argument_expression_list        argument_expression                     default_initializer_opt
    383401%type<ifctl> conditional_declaration
    384 %type<fctl> for_control_expression              for_control_expression_list
    385 %type<compop> upupeq updown updowneq downupdowneq
    386 %type<en> subrange
     402%type<forctl> for_control_expression            for_control_expression_list
     403%type<oper> upupeq updown updowneq downupdowneq
     404%type<expr> subrange
    387405%type<decl> asm_name_opt
    388 %type<en> asm_operands_opt                              asm_operands_list                       asm_operand
    389 %type<label> label_list
    390 %type<en> asm_clobbers_list_opt
    391 %type<flag> asm_volatile_opt
    392 %type<en> handler_predicate_opt
     406%type<expr> asm_operands_opt                            asm_operands_list                       asm_operand
     407%type<labels> label_list
     408%type<expr> asm_clobbers_list_opt
     409%type<is_volatile> asm_volatile_opt
     410%type<expr> handler_predicate_opt
    393411%type<genexpr> generic_association              generic_assoc_list
    394412
    395413// statements
    396 %type<sn> statement                                             labeled_statement                       compound_statement
    397 %type<sn> statement_decl                                statement_decl_list                     statement_list_nodecl
    398 %type<sn> selection_statement                   if_statement
    399 %type<sn> switch_clause_list_opt                switch_clause_list
    400 %type<en> case_value
    401 %type<sn> case_clause                                   case_value_list                         case_label                                      case_label_list
    402 %type<sn> iteration_statement                   jump_statement
    403 %type<sn> expression_statement                  asm_statement
    404 %type<sn> with_statement
    405 %type<en> with_clause_opt
    406 %type<sn> exception_statement                   handler_clause                          finally_clause
    407 %type<catch_kind> handler_key
    408 %type<sn> mutex_statement
    409 %type<en> when_clause                                   when_clause_opt                         waitfor                                         timeout
    410 %type<sn> waitfor_statement
    411 %type<wfs> waitfor_clause
     414%type<stmt> statement                                           labeled_statement                       compound_statement
     415%type<stmt> statement_decl                              statement_decl_list                     statement_list_nodecl
     416%type<stmt> selection_statement                 if_statement
     417%type<clause> switch_clause_list_opt            switch_clause_list
     418%type<expr> case_value
     419%type<clause> case_clause                               case_value_list                         case_label                                      case_label_list
     420%type<stmt> iteration_statement                 jump_statement
     421%type<stmt> expression_statement                        asm_statement
     422%type<stmt> with_statement
     423%type<expr> with_clause_opt
     424%type<stmt> exception_statement
     425%type<clause> handler_clause                    finally_clause
     426%type<except_kind> handler_key
     427%type<stmt> mutex_statement
     428%type<expr> when_clause                                 when_clause_opt                         waitfor         waituntil               timeout
     429%type<stmt> waitfor_statement                           waituntil_statement
     430%type<wfs> wor_waitfor_clause
     431%type<wucn> waituntil_clause                    wand_waituntil_clause       wor_waituntil_clause
    412432
    413433// declarations
     
    421441%type<decl> assertion assertion_list assertion_list_opt
    422442
    423 %type<en> bit_subrange_size_opt bit_subrange_size
     443%type<expr> bit_subrange_size_opt bit_subrange_size
    424444
    425445%type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type
     
    434454
    435455%type<decl> enumerator_list enum_type enum_type_nobody
    436 %type<in> enumerator_value_opt
     456%type<init> enumerator_value_opt
    437457
    438458%type<decl> external_definition external_definition_list external_definition_list_opt
     
    441461
    442462%type<decl> field_declaration_list_opt field_declaration field_declaring_list_opt field_declarator field_abstract_list_opt field_abstract
    443 %type<en> field field_name_list field_name fraction_constants_opt
     463%type<expr> field field_name_list field_name fraction_constants_opt
    444464
    445465%type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr
     
    482502%type<decl> typedef_name typedef_declaration typedef_expression
    483503
    484 %type<decl> variable_type_redeclarator type_ptr type_array type_function
     504%type<decl> variable_type_redeclarator variable_type_ptr variable_type_array variable_type_function
     505%type<decl> general_function_declarator function_type_redeclarator function_type_array function_type_no_ptr function_type_ptr
    485506
    486507%type<decl> type_parameter_redeclarator type_parameter_ptr type_parameter_array type_parameter_function
     
    489510%type<decl> type_parameter type_parameter_list type_initializer_opt
    490511
    491 %type<en> type_parameters_opt type_list array_type_list
     512%type<expr> type_parameters_opt type_list array_type_list
    492513
    493514%type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list
     
    500521
    501522// initializers
    502 %type<in>  initializer initializer_list_opt initializer_opt
     523%type<init>  initializer initializer_list_opt initializer_opt
    503524
    504525// designators
    505 %type<en>  designator designator_list designation
     526%type<expr>  designator designator_list designation
    506527
    507528
     
    512533// Similar issues exit with the waitfor statement.
    513534
    514 // Order of these lines matters (low-to-high precedence). THEN is left associative over WOR/TIMEOUT/ELSE, WOR is left
    515 // associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.
     535// Order of these lines matters (low-to-high precedence). THEN is left associative over WAND/WOR/TIMEOUT/ELSE, WAND/WOR
     536// is left associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.
    516537%precedence THEN                // rule precedence for IF/WAITFOR statement
     538%precedence ANDAND              // token precedence for start of WAND in WAITFOR statement
     539%precedence WAND                // token precedence for start of WAND in WAITFOR statement
     540%precedence OROR                // token precedence for start of WOR in WAITFOR statement
    517541%precedence WOR                 // token precedence for start of WOR in WAITFOR statement
    518542%precedence TIMEOUT             // token precedence for start of TIMEOUT in WAITFOR statement
     
    592616constant:
    593617                // ENUMERATIONconstant is not included here; it is treated as a variable with type "enumeration constant".
    594         INTEGERconstant                                                         { $$ = new ExpressionNode( build_constantInteger( *$1 ) ); }
    595         | FLOATING_DECIMALconstant                                      { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }
    596         | FLOATING_FRACTIONconstant                                     { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }
    597         | FLOATINGconstant                                                      { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }
    598         | CHARACTERconstant                                                     { $$ = new ExpressionNode( build_constantChar( *$1 ) ); }
     618        INTEGERconstant                                                         { $$ = new ExpressionNode( build_constantInteger( yylloc, *$1 ) ); }
     619        | FLOATING_DECIMALconstant                                      { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
     620        | FLOATING_FRACTIONconstant                                     { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
     621        | FLOATINGconstant                                                      { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
     622        | CHARACTERconstant                                                     { $$ = new ExpressionNode( build_constantChar( yylloc, *$1 ) ); }
    599623        ;
    600624
    601625quasi_keyword:                                                                                  // CFA
    602626        TIMEOUT
     627        | WAND
    603628        | WOR
    604629        | CATCH
     
    621646
    622647string_literal:
    623         string_literal_list                                                     { $$ = build_constantStr( *$1 ); }
     648        string_literal_list                                                     { $$ = new ExpressionNode( build_constantStr( yylloc, *$1 ) ); }
    624649        ;
    625650
     
    638663primary_expression:
    639664        IDENTIFIER                                                                                      // typedef name cannot be used as a variable name
    640                 { $$ = new ExpressionNode( build_varref( $1 ) ); }
     665                { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
    641666        | quasi_keyword
    642                 { $$ = new ExpressionNode( build_varref( $1 ) ); }
     667                { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
    643668        | TYPEDIMname                                                                           // CFA, generic length argument
    644669                // { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( DeclarationNode::newFromTypedef( $1 ) ) ) ); }
    645670                // { $$ = new ExpressionNode( build_varref( $1 ) ); }
    646                 { $$ = new ExpressionNode( build_dimensionref( $1 ) ); }
     671                { $$ = new ExpressionNode( build_dimensionref( yylloc, $1 ) ); }
    647672        | tuple
    648673        | '(' comma_expression ')'
    649674                { $$ = $2; }
    650675        | '(' compound_statement ')'                                            // GCC, lambda expression
    651                 { $$ = new ExpressionNode( new StmtExpr( dynamic_cast<CompoundStmt *>(maybeMoveBuild<Statement>($2) ) ) ); }
     676                { $$ = new ExpressionNode( new ast::StmtExpr( yylloc, dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( $2 ) ) ) ); }
    652677        | type_name '.' identifier                                                      // CFA, nested type
    653                 { $$ = new ExpressionNode( build_qualified_expr( $1, build_varref( $3 ) ) ); }
     678                { $$ = new ExpressionNode( build_qualified_expr( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
    654679        | type_name '.' '[' field_name_list ']'                         // CFA, nested type / tuple field selector
    655680                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     
    657682                {
    658683                        // add the missing control expression to the GenericExpr and return it
    659                         $5->control = maybeMoveBuild<Expression>( $3 );
     684                        $5->control = maybeMoveBuild( $3 );
    660685                        $$ = new ExpressionNode( $5 );
    661686                }
     
    683708                {
    684709                        // steal the association node from the singleton and delete the wrapper
    685                         $1->associations.splice($1->associations.end(), $3->associations);
     710                        assert( 1 == $3->associations.size() );
     711                        $1->associations.push_back( $3->associations.front() );
    686712                        delete $3;
    687713                        $$ = $1;
     
    693719                {
    694720                        // create a GenericExpr wrapper with one association pair
    695                         $$ = new GenericExpr( nullptr, { { maybeMoveBuildType($1), maybeMoveBuild<Expression>( $3 ) } } );
     721                        $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuildType( $1 ), maybeMoveBuild( $3 ) } } );
    696722                }
    697723        | DEFAULT ':' assignment_expression
    698                 { $$ = new GenericExpr( nullptr, { { maybeMoveBuild<Expression>( $3 ) } } ); }
     724                { $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuild( $3 ) } } ); }
    699725        ;
    700726
     
    705731                // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts.
    706732                // Current: Commas in subscripts make tuples.
    707                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
     733                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
    708734        | postfix_expression '[' assignment_expression ']'
    709735                // CFA, comma_expression disallowed in this context because it results in a common user error: subscripting a
     
    711737                // little advantage to this feature and many disadvantages. It is possible to write x[(i,j)] in CFA, which is
    712738                // equivalent to the old x[i,j].
    713                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
     739                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
    714740        | constant '[' assignment_expression ']'                        // 3[a], 'a'[a], 3.5[a]
    715                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
     741                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
    716742        | string_literal '[' assignment_expression ']'          // "abc"[3], 3["abc"]
    717                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); }
     743                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
    718744        | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call
    719745                {
    720746                        Token fn;
    721747                        fn.str = new std::string( "?{}" );                      // location undefined - use location of '{'?
    722                         $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
     748                        $$ = new ExpressionNode( new ast::ConstructorExpr( yylloc, build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
    723749                }
    724750        | postfix_expression '(' argument_expression_list_opt ')'
    725                 { $$ = new ExpressionNode( build_func( $1, $3 ) ); }
     751                { $$ = new ExpressionNode( build_func( yylloc, $1, $3 ) ); }
    726752        | VA_ARG '(' primary_expression ',' declaration_specifier_nobody abstract_parameter_declarator_opt ')'
    727753                // { SemanticError( yylloc, "va_arg is currently unimplemented." ); $$ = nullptr; }
    728                 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( new string( "__builtin_va_arg") ) ),
     754                { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, new string( "__builtin_va_arg") ) ),
    729755                                                                                           (ExpressionNode *)($3->set_last( (ExpressionNode *)($6 ? $6->addType( $5 ) : $5) )) ) ); }
    730756        | postfix_expression '`' identifier                                     // CFA, postfix call
    731                 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), $1 ) ); }
     757                { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
    732758        | constant '`' identifier                                                       // CFA, postfix call
    733                 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), $1 ) ); }
     759                { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
    734760        | string_literal '`' identifier                                         // CFA, postfix call
    735                 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), new ExpressionNode( $1 ) ) ); }
     761                { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
    736762        | postfix_expression '.' identifier
    737                 { $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); }
     763                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
    738764        | postfix_expression '.' INTEGERconstant                        // CFA, tuple index
    739                 { $$ = new ExpressionNode( build_fieldSel( $1, build_constantInteger( *$3 ) ) ); }
     765                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); }
    740766        | postfix_expression FLOATING_FRACTIONconstant          // CFA, tuple index
    741                 { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant( *$2 ) ) ); }
     767                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 ) ) ); }
    742768        | postfix_expression '.' '[' field_name_list ']'        // CFA, tuple field selector
    743                 { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
     769                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
    744770        | postfix_expression '.' aggregate_control
    745                 { $$ = new ExpressionNode( build_keyword_cast( $3, $1 ) ); }
     771                { $$ = new ExpressionNode( build_keyword_cast( yylloc, $3, $1 ) ); }
    746772        | postfix_expression ARROW identifier
    747                 { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); }
     773                { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
    748774        | postfix_expression ARROW INTEGERconstant                      // CFA, tuple index
    749                 { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); }
     775                { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); }
    750776        | postfix_expression ARROW '[' field_name_list ']'      // CFA, tuple field selector
    751                 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
     777                { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
    752778        | postfix_expression ICR
    753                 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::IncrPost, $1 ) ); }
     779                { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::IncrPost, $1 ) ); }
    754780        | postfix_expression DECR
    755                 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::DecrPost, $1 ) ); }
     781                { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::DecrPost, $1 ) ); }
    756782        | '(' type_no_function ')' '{' initializer_list_opt comma_opt '}' // C99, compound-literal
    757                 { $$ = new ExpressionNode( build_compoundLiteral( $2, new InitializerNode( $5, true ) ) ); }
     783                { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, new InitializerNode( $5, true ) ) ); }
    758784        | '(' type_no_function ')' '@' '{' initializer_list_opt comma_opt '}' // CFA, explicit C compound-literal
    759                 { $$ = new ExpressionNode( build_compoundLiteral( $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }
     785                { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }
    760786        | '^' primary_expression '{' argument_expression_list_opt '}' // CFA, destructor call
    761787                {
    762788                        Token fn;
    763789                        fn.str = new string( "^?{}" );                          // location undefined
    764                         $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );
     790                        $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );
    765791                }
    766792        ;
     
    781807        '@'                                                                                                     // CFA, default parameter
    782808                { SemanticError( yylloc, "Default parameter for argument is currently unimplemented." ); $$ = nullptr; }
    783                 // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
     809                // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
    784810        | assignment_expression
    785811        ;
     
    793819        field_name
    794820        | FLOATING_DECIMALconstant field
    795                 { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), maybeMoveBuild<Expression>( $2 ) ) ); }
     821                { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), maybeMoveBuild( $2 ) ) ); }
    796822        | FLOATING_DECIMALconstant '[' field_name_list ']'
    797                 { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), build_tuple( $3 ) ) ); }
     823                { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), build_tuple( yylloc, $3 ) ) ); }
    798824        | field_name '.' field
    799                 { $$ = new ExpressionNode( build_fieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
     825                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }
    800826        | field_name '.' '[' field_name_list ']'
    801                 { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
     827                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
    802828        | field_name ARROW field
    803                 { $$ = new ExpressionNode( build_pfieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
     829                { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }
    804830        | field_name ARROW '[' field_name_list ']'
    805                 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
     831                { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
    806832        ;
    807833
    808834field_name:
    809835        INTEGERconstant fraction_constants_opt
    810                 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_constantInteger( *$1 ), $2 ) ); }
     836                { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_constantInteger( yylloc, *$1 ), $2 ) ); }
    811837        | FLOATINGconstant fraction_constants_opt
    812                 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); }
     838                { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_field_name_FLOATINGconstant( yylloc, *$1 ), $2 ) ); }
    813839        | identifier_at fraction_constants_opt                          // CFA, allow anonymous fields
    814840                {
    815                         $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) );
     841                        $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_varref( yylloc, $1 ), $2 ) );
    816842                }
    817843        ;
     
    822848        | fraction_constants_opt FLOATING_FRACTIONconstant
    823849                {
    824                         Expression * constant = build_field_name_FLOATING_FRACTIONconstant( *$2 );
    825                         $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( $1, constant ) ) : new ExpressionNode( constant );
     850                        ast::Expr * constant = build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 );
     851                        $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( yylloc, $1, constant ) ) : new ExpressionNode( constant );
    826852                }
    827853        ;
     
    833859        | constant
    834860        | string_literal
    835                 { $$ = new ExpressionNode( $1 ); }
     861                { $$ = $1; }
    836862        | EXTENSION cast_expression                                                     // GCC
    837863                { $$ = $2->set_extension( true ); }
     
    842868                {
    843869                        switch ( $1 ) {
    844                           case OperKinds::AddressOf:
    845                                 $$ = new ExpressionNode( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) );
     870                        case OperKinds::AddressOf:
     871                                $$ = new ExpressionNode( new ast::AddressExpr( maybeMoveBuild( $2 ) ) );
    846872                                break;
    847                           case OperKinds::PointTo:
    848                                 $$ = new ExpressionNode( build_unary_val( $1, $2 ) );
     873                        case OperKinds::PointTo:
     874                                $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) );
    849875                                break;
    850                           case OperKinds::And:
    851                                 $$ = new ExpressionNode( new AddressExpr( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) ) );
     876                        case OperKinds::And:
     877                                $$ = new ExpressionNode( new ast::AddressExpr( new ast::AddressExpr( maybeMoveBuild( $2 ) ) ) );
    852878                                break;
    853                           default:
     879                        default:
    854880                                assert( false );
    855881                        }
    856882                }
    857883        | unary_operator cast_expression
    858                 { $$ = new ExpressionNode( build_unary_val( $1, $2 ) ); }
     884                { $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) ); }
    859885        | ICR unary_expression
    860                 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::Incr, $2 ) ); }
     886                { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Incr, $2 ) ); }
    861887        | DECR unary_expression
    862                 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::Decr, $2 ) ); }
     888                { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Decr, $2 ) ); }
    863889        | SIZEOF unary_expression
    864                 { $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuild<Expression>( $2 ) ) ); }
     890                { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
    865891        | SIZEOF '(' type_no_function ')'
    866                 { $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuildType( $3 ) ) ); }
     892                { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
    867893        | ALIGNOF unary_expression                                                      // GCC, variable alignment
    868                 { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuild<Expression>( $2 ) ) ); }
     894                { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
    869895        | ALIGNOF '(' type_no_function ')'                                      // GCC, type alignment
    870                 { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuildType( $3 ) ) ); }
     896                { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
    871897        | OFFSETOF '(' type_no_function ',' identifier ')'
    872                 { $$ = new ExpressionNode( build_offsetOf( $3, build_varref( $5 ) ) ); }
     898                { $$ = new ExpressionNode( build_offsetOf( yylloc, $3, build_varref( yylloc, $5 ) ) ); }
    873899        | TYPEID '(' type_no_function ')'
    874900                {
     
    895921        unary_expression
    896922        | '(' type_no_function ')' cast_expression
    897                 { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
     923                { $$ = new ExpressionNode( build_cast( yylloc, $2, $4 ) ); }
    898924        | '(' aggregate_control '&' ')' cast_expression         // CFA
    899                 { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
     925                { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); }
    900926        | '(' aggregate_control '*' ')' cast_expression         // CFA
    901                 { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
     927                { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); }
    902928        | '(' VIRTUAL ')' cast_expression                                       // CFA
    903                 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $4 ), maybeMoveBuildType( nullptr ) ) ); }
     929                { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $4 ), maybeMoveBuildType( nullptr ) ) ); }
    904930        | '(' VIRTUAL type_no_function ')' cast_expression      // CFA
    905                 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $5 ), maybeMoveBuildType( $3 ) ) ); }
     931                { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); }
    906932        | '(' RETURN type_no_function ')' cast_expression       // CFA
    907                 { $$ = new ExpressionNode( build_cast( $3, $5, CastExpr::Return ) ); }
     933                { $$ = new ExpressionNode( build_cast( yylloc, $3, $5, ast::CastExpr::Return ) ); }
    908934        | '(' COERCE type_no_function ')' cast_expression       // CFA
    909935                { SemanticError( yylloc, "Coerce cast is currently unimplemented." ); $$ = nullptr; }
     
    911937                { SemanticError( yylloc, "Qualifier cast is currently unimplemented." ); $$ = nullptr; }
    912938//      | '(' type_no_function ')' tuple
    913 //              { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
     939//              { $$ = new ast::ExpressionNode( build_cast( yylloc, $2, $4 ) ); }
    914940        ;
    915941
     
    929955        cast_expression
    930956        | exponential_expression '\\' cast_expression
    931                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Exp, $1, $3 ) ); }
     957                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Exp, $1, $3 ) ); }
    932958        ;
    933959
     
    935961        exponential_expression
    936962        | multiplicative_expression '*' exponential_expression
    937                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Mul, $1, $3 ) ); }
     963                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mul, $1, $3 ) ); }
    938964        | multiplicative_expression '/' exponential_expression
    939                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Div, $1, $3 ) ); }
     965                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Div, $1, $3 ) ); }
    940966        | multiplicative_expression '%' exponential_expression
    941                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Mod, $1, $3 ) ); }
     967                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mod, $1, $3 ) ); }
    942968        ;
    943969
     
    945971        multiplicative_expression
    946972        | additive_expression '+' multiplicative_expression
    947                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Plus, $1, $3 ) ); }
     973                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Plus, $1, $3 ) ); }
    948974        | additive_expression '-' multiplicative_expression
    949                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Minus, $1, $3 ) ); }
     975                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Minus, $1, $3 ) ); }
    950976        ;
    951977
     
    953979        additive_expression
    954980        | shift_expression LS additive_expression
    955                 { $$ = new ExpressionNode( build_binary_val( OperKinds::LShift, $1, $3 ) ); }
     981                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LShift, $1, $3 ) ); }
    956982        | shift_expression RS additive_expression
    957                 { $$ = new ExpressionNode( build_binary_val( OperKinds::RShift, $1, $3 ) ); }
     983                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::RShift, $1, $3 ) ); }
    958984        ;
    959985
     
    961987        shift_expression
    962988        | relational_expression '<' shift_expression
    963                 { $$ = new ExpressionNode( build_binary_val( OperKinds::LThan, $1, $3 ) ); }
     989                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LThan, $1, $3 ) ); }
    964990        | relational_expression '>' shift_expression
    965                 { $$ = new ExpressionNode( build_binary_val( OperKinds::GThan, $1, $3 ) ); }
     991                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GThan, $1, $3 ) ); }
    966992        | relational_expression LE shift_expression
    967                 { $$ = new ExpressionNode( build_binary_val( OperKinds::LEThan, $1, $3 ) ); }
     993                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LEThan, $1, $3 ) ); }
    968994        | relational_expression GE shift_expression
    969                 { $$ = new ExpressionNode( build_binary_val( OperKinds::GEThan, $1, $3 ) ); }
     995                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GEThan, $1, $3 ) ); }
    970996        ;
    971997
     
    973999        relational_expression
    9741000        | equality_expression EQ relational_expression
    975                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Eq, $1, $3 ) ); }
     1001                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Eq, $1, $3 ) ); }
    9761002        | equality_expression NE relational_expression
    977                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Neq, $1, $3 ) ); }
     1003                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Neq, $1, $3 ) ); }
    9781004        ;
    9791005
     
    9811007        equality_expression
    9821008        | AND_expression '&' equality_expression
    983                 { $$ = new ExpressionNode( build_binary_val( OperKinds::BitAnd, $1, $3 ) ); }
     1009                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitAnd, $1, $3 ) ); }
    9841010        ;
    9851011
     
    9871013        AND_expression
    9881014        | exclusive_OR_expression '^' AND_expression
    989                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Xor, $1, $3 ) ); }
     1015                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Xor, $1, $3 ) ); }
    9901016        ;
    9911017
     
    9931019        exclusive_OR_expression
    9941020        | inclusive_OR_expression '|' exclusive_OR_expression
    995                 { $$ = new ExpressionNode( build_binary_val( OperKinds::BitOr, $1, $3 ) ); }
     1021                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitOr, $1, $3 ) ); }
    9961022        ;
    9971023
     
    9991025        inclusive_OR_expression
    10001026        | logical_AND_expression ANDAND inclusive_OR_expression
    1001                 { $$ = new ExpressionNode( build_and_or( $1, $3, true ) ); }
     1027                { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::AndExpr ) ); }
    10021028        ;
    10031029
     
    10051031        logical_AND_expression
    10061032        | logical_OR_expression OROR logical_AND_expression
    1007                 { $$ = new ExpressionNode( build_and_or( $1, $3, false ) ); }
     1033                { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::OrExpr ) ); }
    10081034        ;
    10091035
     
    10111037        logical_OR_expression
    10121038        | logical_OR_expression '?' comma_expression ':' conditional_expression
    1013                 { $$ = new ExpressionNode( build_cond( $1, $3, $5 ) ); }
     1039                { $$ = new ExpressionNode( build_cond( yylloc, $1, $3, $5 ) ); }
    10141040                // FIX ME: computes $1 twice
    10151041        | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand
    1016                 { $$ = new ExpressionNode( build_cond( $1, $1, $4 ) ); }
     1042                { $$ = new ExpressionNode( build_cond( yylloc, $1, $1, $4 ) ); }
    10171043        ;
    10181044
     
    10291055//                              SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;
    10301056//                      } else {
    1031                                 $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) );
     1057                                $$ = new ExpressionNode( build_binary_val( yylloc, $2, $1, $3 ) );
    10321058//                      } // if
    10331059                }
     
    10741100//              { $$ = new ExpressionNode( build_tuple( $3 ) ); }
    10751101        '[' ',' tuple_expression_list ']'
    1076                 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }
     1102                { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }
    10771103        | '[' push assignment_expression pop ',' tuple_expression_list ']'
    1078                 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $6 ) ) )); }
     1104                { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $6 ) ) )); }
    10791105        ;
    10801106
     
    10921118        assignment_expression
    10931119        | comma_expression ',' assignment_expression
    1094                 { $$ = new ExpressionNode( new CommaExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }
     1120                { $$ = new ExpressionNode( new ast::CommaExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
    10951121        ;
    10961122
     
    11131139        | mutex_statement
    11141140        | waitfor_statement
     1141        | waituntil_statement
    11151142        | exception_statement
    11161143        | enable_disable_statement
     
    11181145        | asm_statement
    11191146        | DIRECTIVE
    1120                 { $$ = new StatementNode( build_directive( $1 ) ); }
     1147                { $$ = new StatementNode( build_directive( yylloc, $1 ) ); }
    11211148        ;
    11221149
     
    11241151                // labels cannot be identifiers 0 or 1
    11251152        identifier_or_type_name ':' attribute_list_opt statement
    1126                 { $$ = $4->add_label( $1, $3 ); }
     1153                { $$ = $4->add_label( yylloc, $1, $3 ); }
    11271154        | identifier_or_type_name ':' attribute_list_opt error // syntax error
    11281155                {
     
    11361163compound_statement:
    11371164        '{' '}'
    1138                 { $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); }
     1165                { $$ = new StatementNode( build_compound( yylloc, (StatementNode *)0 ) ); }
    11391166        | '{' push
    11401167          local_label_declaration_opt                                           // GCC, local labels appear at start of block
    11411168          statement_decl_list                                                           // C99, intermix declarations and statements
    11421169          pop '}'
    1143                 { $$ = new StatementNode( build_compound( $4 ) ); }
     1170                { $$ = new StatementNode( build_compound( yylloc, $4 ) ); }
    11441171        ;
    11451172
     
    11721199expression_statement:
    11731200        comma_expression_opt ';'
    1174                 { $$ = new StatementNode( build_expr( $1 ) ); }
    1175         | MUTEX '(' ')' comma_expression ';'
    1176                 { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); }
     1201                { $$ = new StatementNode( build_expr( yylloc, $1 ) ); }
    11771202        ;
    11781203
     
    11831208                { $$ = $2; }
    11841209        | SWITCH '(' comma_expression ')' case_clause
    1185                 { $$ = new StatementNode( build_switch( true, $3, $5 ) ); }
     1210                { $$ = new StatementNode( build_switch( yylloc, true, $3, $5 ) ); }
    11861211        | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
    11871212                {
    1188                         StatementNode *sw = new StatementNode( build_switch( true, $3, $8 ) );
     1213                        StatementNode *sw = new StatementNode( build_switch( yylloc, true, $3, $8 ) );
    11891214                        // The semantics of the declaration list is changed to include associated initialization, which is performed
    11901215                        // *before* the transfer to the appropriate case clause by hoisting the declarations into a compound
     
    11921217                        // therefore, are removed from the grammar even though C allows it. The change also applies to choose
    11931218                        // statement.
    1194                         $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
     1219                        $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    11951220                }
    11961221        | SWITCH '(' comma_expression ')' '{' error '}'         // CFA, syntax error
    11971222                { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; }
    11981223        | CHOOSE '(' comma_expression ')' case_clause           // CFA
    1199                 { $$ = new StatementNode( build_switch( false, $3, $5 ) ); }
     1224                { $$ = new StatementNode( build_switch( yylloc, false, $3, $5 ) ); }
    12001225        | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
    12011226                {
    1202                         StatementNode *sw = new StatementNode( build_switch( false, $3, $8 ) );
    1203                         $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
     1227                        StatementNode *sw = new StatementNode( build_switch( yylloc, false, $3, $8 ) );
     1228                        $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    12041229                }
    12051230        | CHOOSE '(' comma_expression ')' '{' error '}'         // CFA, syntax error
     
    12101235        IF '(' conditional_declaration ')' statement            %prec THEN
    12111236                // explicitly deal with the shift/reduce conflict on if/else
    1212                 { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), nullptr ) ); }
     1237                { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), nullptr ) ); }
    12131238        | IF '(' conditional_declaration ')' statement ELSE statement
    1214                 { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), maybe_build_compound( $7 ) ) ); }
     1239                { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc, $7 ) ) ); }
    12151240        ;
    12161241
     
    12241249        | declaration comma_expression                                          // semi-colon separated
    12251250                { $$ = new CondCtl( $1, $2 ); }
    1226         ;
     1251        ;
    12271252
    12281253// CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a case
     
    12321257        constant_expression                                                     { $$ = $1; }
    12331258        | constant_expression ELLIPSIS constant_expression      // GCC, subrange
    1234                 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }
     1259                { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
    12351260        | subrange                                                                                      // CFA, subrange
    12361261        ;
    12371262
    12381263case_value_list:                                                                                // CFA
    1239         case_value                                                                      { $$ = new StatementNode( build_case( $1 ) ); }
     1264        case_value                                                                      { $$ = new ClauseNode( build_case( yylloc, $1 ) ); }
    12401265                // convert case list, e.g., "case 1, 3, 5:" into "case 1: case 3: case 5"
    1241         | case_value_list ',' case_value                        { $$ = (StatementNode *)($1->set_last( new StatementNode( build_case( $3 ) ) ) ); }
     1266        | case_value_list ',' case_value                        { $$ = $1->set_last( new ClauseNode( build_case( yylloc, $3 ) ) ); }
    12421267        ;
    12431268
     
    12481273        | CASE case_value_list error                                            // syntax error
    12491274                { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; }
    1250         | DEFAULT ':'                                                           { $$ = new StatementNode( build_default() ); }
     1275        | DEFAULT ':'                                                           { $$ = new ClauseNode( build_default( yylloc ) ); }
    12511276                // A semantic check is required to ensure only one default clause per switch/choose statement.
    12521277        | DEFAULT error                                                                         //  syntax error
     
    12561281case_label_list:                                                                                // CFA
    12571282        case_label
    1258         | case_label_list case_label                            { $$ = (StatementNode *)( $1->set_last( $2 )); }
     1283        | case_label_list case_label                            { $$ = $1->set_last( $2 ); }
    12591284        ;
    12601285
    12611286case_clause:                                                                                    // CFA
    1262         case_label_list statement                                       { $$ = $1->append_last_case( maybe_build_compound( $2 ) ); }
     1287        case_label_list statement                                       { $$ = $1->append_last_case( maybe_build_compound( yylloc, $2 ) ); }
    12631288        ;
    12641289
     
    12711296switch_clause_list:                                                                             // CFA
    12721297        case_label_list statement_list_nodecl
    1273                 { $$ = $1->append_last_case( new StatementNode( build_compound( $2 ) ) ); }
     1298                { $$ = $1->append_last_case( new StatementNode( build_compound( yylloc, $2 ) ) ); }
    12741299        | switch_clause_list case_label_list statement_list_nodecl
    1275                 { $$ = (StatementNode *)( $1->set_last( $2->append_last_case( new StatementNode( build_compound( $3 ) ) ) ) ); }
     1300                { $$ = $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3 ) ) ) ); }
    12761301        ;
    12771302
    12781303iteration_statement:
    12791304        WHILE '(' ')' statement                                                         %prec THEN // CFA => while ( 1 )
    1280                 { $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) ); }
     1305                { $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) ); }
    12811306        | WHILE '(' ')' statement ELSE statement                        // CFA
    12821307                {
    1283                         $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) );
    1284                         SemanticWarning( yylloc, Warning::SuperfluousElse, "" );
     1308                        $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) );
     1309                        SemanticWarning( yylloc, Warning::SuperfluousElse );
    12851310                }
    12861311        | WHILE '(' conditional_declaration ')' statement       %prec THEN
    1287                 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
     1312                { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
    12881313        | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA
    1289                 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); }
     1314                { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); }
    12901315        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
    1291                 { $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) ); }
     1316                { $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) ); }
    12921317        | DO statement WHILE '(' ')' ELSE statement                     // CFA
    12931318                {
    1294                         $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) );
    1295                         SemanticWarning( yylloc, Warning::SuperfluousElse, "" );
     1319                        $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) );
     1320                        SemanticWarning( yylloc, Warning::SuperfluousElse );
    12961321                }
    12971322        | DO statement WHILE '(' comma_expression ')' ';'
    1298                 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
     1323                { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ) ) ); }
    12991324        | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
    1300                 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); }
     1325                { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ), $8 ) ); }
    13011326        | FOR '(' ')' statement                                                         %prec THEN // CFA => for ( ;; )
    1302                 { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); }
     1327                { $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) ); }
    13031328        | FOR '(' ')' statement ELSE statement                          // CFA
    13041329                {
    1305                         $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) );
    1306                         SemanticWarning( yylloc, Warning::SuperfluousElse, "" );
     1330                        $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) );
     1331                        SemanticWarning( yylloc, Warning::SuperfluousElse );
    13071332                }
    13081333        | FOR '(' for_control_expression_list ')' statement     %prec THEN
    1309                 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
     1334                { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
    13101335        | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
    1311                 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); }
     1336                { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); }
    13121337        ;
    13131338
     
    13231348                        if ( $1->condition ) {
    13241349                                if ( $3->condition ) {
    1325                                         $1->condition->expr.reset( new LogicalExpr( $1->condition->expr.release(), $3->condition->expr.release(), true ) );
     1350                                        $1->condition->expr.reset( new ast::LogicalExpr( yylloc, $1->condition->expr.release(), $3->condition->expr.release(), ast::AndExpr ) );
    13261351                                } // if
    13271352                        } else $1->condition = $3->condition;
    13281353                        if ( $1->change ) {
    13291354                                if ( $3->change ) {
    1330                                         $1->change->expr.reset( new CommaExpr( $1->change->expr.release(), $3->change->expr.release() ) );
     1355                                        $1->change->expr.reset( new ast::CommaExpr( yylloc, $1->change->expr.release(), $3->change->expr.release() ) );
    13311356                                } // if
    13321357                        } else $1->change = $3->change;
     
    13371362for_control_expression:
    13381363        ';' comma_expression_opt ';' comma_expression_opt
    1339                 { $$ = new ForCtrl( (ExpressionNode * )nullptr, $2, $4 ); }
     1364                { $$ = new ForCtrl( nullptr, $2, $4 ); }
    13401365        | comma_expression ';' comma_expression_opt ';' comma_expression_opt
    1341                 { $$ = new ForCtrl( $1, $3, $5 ); }
     1366                {
     1367                        StatementNode * init = $1 ? new StatementNode( new ast::ExprStmt( yylloc, maybeMoveBuild( $1 ) ) ) : nullptr;
     1368                        $$ = new ForCtrl( init, $3, $5 );
     1369                }
    13421370        | declaration comma_expression_opt ';' comma_expression_opt // C99, declaration has ';'
    1343                 { $$ = new ForCtrl( $1, $2, $4 ); }
     1371                { $$ = new ForCtrl( new StatementNode( $1 ), $2, $4 ); }
    13441372
    13451373        | '@' ';' comma_expression                                                      // CFA, empty loop-index
    1346                 { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, nullptr ); }
     1374                { $$ = new ForCtrl( nullptr, $3, nullptr ); }
    13471375        | '@' ';' comma_expression ';' comma_expression         // CFA, empty loop-index
    1348                 { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, $5 ); }
     1376                { $$ = new ForCtrl( nullptr, $3, $5 ); }
    13491377
    13501378        | comma_expression                                                                      // CFA, anonymous loop-index
    1351                 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }
     1379                { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }
    13521380        | downupdowneq comma_expression                                         // CFA, anonymous loop-index
    1353                 { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }
     1381                { $$ = forCtrl( yylloc, $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }
    13541382
    13551383        | comma_expression updowneq comma_expression            // CFA, anonymous loop-index
    1356                 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }
     1384                { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }
    13571385        | '@' updowneq comma_expression                                         // CFA, anonymous loop-index
    13581386                {
    13591387                        if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1360                         else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );
     1388                        else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );
    13611389                }
    13621390        | comma_expression updowneq '@'                                         // CFA, anonymous loop-index
     
    13661394                }
    13671395        | comma_expression updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index
    1368                 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }
     1396                { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }
    13691397        | '@' updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index
    13701398                {
    13711399                        if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1372                         else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );
     1400                        else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );
    13731401                }
    13741402        | comma_expression updowneq '@' '~' comma_expression // CFA, anonymous loop-index
     
    13891417
    13901418        | comma_expression ';' comma_expression                         // CFA
    1391                 { $$ = forCtrl( $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }
     1419                { $$ = forCtrl( yylloc, $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }
    13921420        | comma_expression ';' downupdowneq comma_expression // CFA
    1393                 { $$ = forCtrl( $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }
     1421                { $$ = forCtrl( yylloc, $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }
    13941422
    13951423        | comma_expression ';' comma_expression updowneq comma_expression // CFA
    1396                 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }
     1424                { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }
    13971425        | comma_expression ';' '@' updowneq comma_expression // CFA
    13981426                {
    13991427                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1400                         else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, NEW_ONE );
     1428                        else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, NEW_ONE );
    14011429                }
    14021430        | comma_expression ';' comma_expression updowneq '@' // CFA
     
    14041432                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14051433                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1406                         else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, NEW_ONE );
     1434                        else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, NEW_ONE );
    14071435                }
    14081436        | comma_expression ';' '@' updowneq '@'                         // CFA, error
     
    14101438
    14111439        | comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA
    1412                 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }
     1440                { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }
    14131441        | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, error
    14141442                {
    14151443                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1416                         else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, $7 );
     1444                        else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, $7 );
    14171445                }
    14181446        | comma_expression ';' comma_expression updowneq '@' '~' comma_expression // CFA
     
    14201448                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14211449                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1422                         else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, $7 );
     1450                        else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, $7 );
    14231451                }
    14241452        | comma_expression ';' comma_expression updowneq comma_expression '~' '@' // CFA
    1425                 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }
     1453                { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }
    14261454        | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, error
    14271455                {
    14281456                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1429                         else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, nullptr );
     1457                        else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, nullptr );
    14301458                }
    14311459        | comma_expression ';' comma_expression updowneq '@' '~' '@' // CFA
     
    14331461                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14341462                        else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1435                         else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, nullptr );
     1463                        else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, nullptr );
    14361464                }
    14371465        | comma_expression ';' '@' updowneq '@' '~' '@' // CFA
     
    14391467
    14401468        | declaration comma_expression                                          // CFA
    1441                 { $$ = forCtrl( $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }
     1469                { $$ = forCtrl( yylloc, $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }
    14421470        | declaration downupdowneq comma_expression                     // CFA
    1443                 { $$ = forCtrl( $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }
     1471                { $$ = forCtrl( yylloc, $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }
    14441472
    14451473        | declaration comma_expression updowneq comma_expression // CFA
    1446                 { $$ = forCtrl( $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }
     1474                { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }
    14471475        | declaration '@' updowneq comma_expression                     // CFA
    14481476                {
    14491477                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1450                         else $$ = forCtrl( $1, $4, $3, nullptr, NEW_ONE );
     1478                        else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, NEW_ONE );
    14511479                }
    14521480        | declaration comma_expression updowneq '@'                     // CFA
     
    14541482                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14551483                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1456                         else $$ = forCtrl( $1, $2, $3, nullptr, NEW_ONE );
     1484                        else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, NEW_ONE );
    14571485                }
    14581486
    14591487        | declaration comma_expression updowneq comma_expression '~' comma_expression // CFA
    1460                 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }
     1488                { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }
    14611489        | declaration '@' updowneq comma_expression '~' comma_expression // CFA
    14621490                {
    14631491                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1464                         else $$ = forCtrl( $1, $4, $3, nullptr, $6 );
     1492                        else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, $6 );
    14651493                }
    14661494        | declaration comma_expression updowneq '@' '~' comma_expression // CFA
     
    14681496                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14691497                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1470                         else $$ = forCtrl( $1, $2, $3, nullptr, $6 );
     1498                        else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, $6 );
    14711499                }
    14721500        | declaration comma_expression updowneq comma_expression '~' '@' // CFA
    1473                 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }
     1501                { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }
    14741502        | declaration '@' updowneq comma_expression '~' '@' // CFA
    14751503                {
    14761504                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1477                         else $$ = forCtrl( $1, $4, $3, nullptr, nullptr );
     1505                        else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, nullptr );
    14781506                }
    14791507        | declaration comma_expression updowneq '@' '~' '@'     // CFA
     
    14811509                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14821510                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1483                         else $$ = forCtrl( $1, $2, $3, nullptr, nullptr );
     1511                        else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, nullptr );
    14841512                }
    14851513        | declaration '@' updowneq '@' '~' '@'                          // CFA, error
     
    14961524                        SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr;
    14971525                }
    1498         ;
     1526        ;
    14991527
    15001528downupdowneq:
     
    15051533        | ErangeDownEq
    15061534                { $$ = OperKinds::GEThan; }
    1507         ;
     1535        ;
    15081536
    15091537updown:
     
    15121540        | ErangeDown
    15131541                { $$ = OperKinds::GThan; }
    1514         ;
     1542        ;
    15151543
    15161544updowneq:
     
    15201548        | ErangeDownEq
    15211549                { $$ = OperKinds::GEThan; }
    1522         ;
     1550        ;
    15231551
    15241552jump_statement:
    15251553        GOTO identifier_or_type_name ';'
    1526                 { $$ = new StatementNode( build_branch( $2, BranchStmt::Goto ) ); }
     1554                { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Goto ) ); }
    15271555        | GOTO '*' comma_expression ';'                                         // GCC, computed goto
    15281556                // The syntax for the GCC computed goto violates normal expression precedence, e.g., goto *i+3; => goto *(i+3);
     
    15311559                // A semantic check is required to ensure fallthru appears only in the body of a choose statement.
    15321560        | fall_through_name ';'                                                         // CFA
    1533                 { $$ = new StatementNode( build_branch( BranchStmt::FallThrough ) ); }
     1561                { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThrough ) ); }
    15341562        | fall_through_name identifier_or_type_name ';'         // CFA
    1535                 { $$ = new StatementNode( build_branch( $2, BranchStmt::FallThrough ) ); }
     1563                { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::FallThrough ) ); }
    15361564        | fall_through_name DEFAULT ';'                                         // CFA
    1537                 { $$ = new StatementNode( build_branch( BranchStmt::FallThroughDefault ) ); }
     1565                { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThroughDefault ) ); }
    15381566        | CONTINUE ';'
    15391567                // A semantic check is required to ensure this statement appears only in the body of an iteration statement.
    1540                 { $$ = new StatementNode( build_branch( BranchStmt::Continue ) ); }
     1568                { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Continue ) ); }
    15411569        | CONTINUE identifier_or_type_name ';'                          // CFA, multi-level continue
    15421570                // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and
    15431571                // the target of the transfer appears only at the start of an iteration statement.
    1544                 { $$ = new StatementNode( build_branch( $2, BranchStmt::Continue ) ); }
     1572                { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Continue ) ); }
    15451573        | BREAK ';'
    15461574                // A semantic check is required to ensure this statement appears only in the body of an iteration statement.
    1547                 { $$ = new StatementNode( build_branch( BranchStmt::Break ) ); }
     1575                { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Break ) ); }
    15481576        | BREAK identifier_or_type_name ';'                                     // CFA, multi-level exit
    15491577                // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and
    15501578                // the target of the transfer appears only at the start of an iteration statement.
    1551                 { $$ = new StatementNode( build_branch( $2, BranchStmt::Break ) ); }
     1579                { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Break ) ); }
    15521580        | RETURN comma_expression_opt ';'
    1553                 { $$ = new StatementNode( build_return( $2 ) ); }
     1581                { $$ = new StatementNode( build_return( yylloc, $2 ) ); }
    15541582        | RETURN '{' initializer_list_opt comma_opt '}' ';'
    15551583                { SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; }
    15561584        | SUSPEND ';'
    1557                 { $$ = new StatementNode( build_suspend( nullptr ) ); }
     1585                { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::None ) ); }
    15581586        | SUSPEND compound_statement
    1559                 { $$ = new StatementNode( build_suspend( $2 ) ); }
     1587                { $$ = new StatementNode( build_suspend( yylloc, $2, ast::SuspendStmt::None ) ); }
    15601588        | SUSPEND COROUTINE ';'
    1561                 { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Coroutine ) ); }
     1589                { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Coroutine ) ); }
    15621590        | SUSPEND COROUTINE compound_statement
    1563                 { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Coroutine ) ); }
     1591                { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Coroutine ) ); }
    15641592        | SUSPEND GENERATOR ';'
    1565                 { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Generator ) ); }
     1593                { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Generator ) ); }
    15661594        | SUSPEND GENERATOR compound_statement
    1567                 { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Generator ) ); }
     1595                { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Generator ) ); }
    15681596        | THROW assignment_expression_opt ';'                           // handles rethrow
    1569                 { $$ = new StatementNode( build_throw( $2 ) ); }
     1597                { $$ = new StatementNode( build_throw( yylloc, $2 ) ); }
    15701598        | THROWRESUME assignment_expression_opt ';'                     // handles reresume
    1571                 { $$ = new StatementNode( build_resume( $2 ) ); }
     1599                { $$ = new StatementNode( build_resume( yylloc, $2 ) ); }
    15721600        | THROWRESUME assignment_expression_opt AT assignment_expression ';' // handles reresume
    15731601                { $$ = new StatementNode( build_resume_at( $2, $4 ) ); }
     
    15811609with_statement:
    15821610        WITH '(' tuple_expression_list ')' statement
    1583                 { $$ = new StatementNode( build_with( $3, $5 ) ); }
    1584         ;
    1585 
    1586 // If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so change syntax to "with mutex".
     1611                { $$ = new StatementNode( build_with( yylloc, $3, $5 ) ); }
     1612        ;
     1613
     1614// If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so possibly change syntax to "with mutex".
    15871615mutex_statement:
    1588         MUTEX '(' argument_expression_list ')' statement
    1589                 { $$ = new StatementNode( build_mutex( $3, $5 ) ); }
     1616        MUTEX '(' argument_expression_list_opt ')' statement
     1617                {
     1618                        if ( ! $3 ) { SemanticError( yylloc, "mutex argument list cannot be empty." ); $$ = nullptr; }
     1619                        $$ = new StatementNode( build_mutex( yylloc, $3, $5 ) );
     1620                }
    15901621        ;
    15911622
     
    15981629                { $$ = nullptr; }
    15991630        | when_clause
    1600         ;
    1601 
    1602 waitfor:
    1603         WAITFOR '(' cast_expression ')'
    1604                 { $$ = $3; }
    1605 //      | WAITFOR '(' cast_expression ',' argument_expression_list_opt ')'
    1606 //              { $$ = (ExpressionNode *)$3->set_last( $5 ); }
    1607         | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
    1608                 { $$ = (ExpressionNode *)($3->set_last( $5 )); }
    16091631        ;
    16101632
     
    16171639
    16181640timeout:
    1619         TIMEOUT '(' comma_expression ')'                        { $$ = $3; }
    1620         ;
    1621 
    1622 waitfor_clause:
     1641        TIMEOUT '(' comma_expression ')'                        { $$ = $3; }
     1642        ;
     1643
     1644wor:
     1645        OROR
     1646        | WOR
     1647
     1648waitfor:
     1649        WAITFOR '(' cast_expression ')'
     1650                { $$ = $3; }
     1651        | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
     1652                { $$ = (ExpressionNode *)($3->set_last( $5 )); }
     1653        ;
     1654
     1655wor_waitfor_clause:
    16231656        when_clause_opt waitfor statement                                       %prec THEN
    1624                 { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1 ); }
    1625         | when_clause_opt waitfor statement WOR waitfor_clause
    1626                 { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1, $5 ); }
    1627         | when_clause_opt timeout statement                                     %prec THEN
    1628                 { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1 ); }
    1629         | when_clause_opt ELSE statement
    1630                 { $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); }
     1657                // Called first: create header for WaitForStmt.
     1658                { $$ = build_waitfor( yylloc, new ast::WaitForStmt( yylloc ), $1, $2, maybe_build_compound( yylloc, $3 ) ); }
     1659        | wor_waitfor_clause wor when_clause_opt waitfor statement
     1660                { $$ = build_waitfor( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); }
     1661        | wor_waitfor_clause wor when_clause_opt ELSE statement
     1662                { $$ = build_waitfor_else( yylloc, $1, $3, maybe_build_compound( yylloc, $5 ) ); }
     1663        | wor_waitfor_clause wor when_clause_opt timeout statement      %prec THEN
     1664                { $$ = build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); }
    16311665        // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    1632         | when_clause_opt timeout statement WOR ELSE statement // syntax error
     1666        | wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
    16331667                { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    1634         | when_clause_opt timeout statement WOR when_clause ELSE statement
    1635                 { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1, maybe_build_compound( $7 ), $5 ); }
     1668        | wor_waitfor_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
     1669                { $$ = build_waitfor_else( yylloc, build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ), $7, maybe_build_compound( yylloc, $9 ) ); }
    16361670        ;
    16371671
    16381672waitfor_statement:
    1639         when_clause_opt waitfor statement                                       %prec THEN
    1640                 { $$ = new StatementNode( build_waitfor( $2, $3, $1 ) ); }
    1641         | when_clause_opt waitfor statement WOR waitfor_clause
    1642                 { $$ = new StatementNode( build_waitfor( $2, $3, $1, $5 ) ); }
     1673        wor_waitfor_clause                                                                      %prec THEN
     1674                { $$ = new StatementNode( $1 ); }
     1675        ;
     1676
     1677wand:
     1678        ANDAND
     1679        | WAND
     1680        ;
     1681
     1682waituntil:
     1683        WAITUNTIL '(' comma_expression ')'
     1684                { $$ = $3; }
     1685        ;
     1686
     1687waituntil_clause:
     1688        when_clause_opt waituntil statement
     1689                { $$ = build_waituntil_clause( yylloc, $1, $2, maybe_build_compound( yylloc, $3 ) ); }
     1690        | '(' wor_waituntil_clause ')'
     1691                { $$ = $2; }
     1692        ;
     1693
     1694wand_waituntil_clause:
     1695        waituntil_clause                                                                        %prec THEN
     1696                { $$ = $1; }
     1697        | waituntil_clause wand wand_waituntil_clause
     1698                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::AND, $1, $3 ); }
     1699        ;
     1700
     1701wor_waituntil_clause:
     1702        wand_waituntil_clause
     1703                { $$ = $1; }
     1704        | wor_waituntil_clause wor wand_waituntil_clause
     1705                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR, $1, $3 ); }
     1706        | wor_waituntil_clause wor when_clause_opt ELSE statement
     1707                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_else( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
     1708        | wor_waituntil_clause wor when_clause_opt timeout statement    %prec THEN
     1709                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ) ); }
     1710        // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
     1711        | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
     1712                { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
     1713        | wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
     1714                { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1,
     1715                new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::OR,
     1716                    build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ),
     1717                    build_waituntil_else( yylloc, $7, maybe_build_compound( yylloc, $9 ) ) ) ); }
     1718        ;
     1719
     1720waituntil_statement:
     1721        wor_waituntil_clause                                                            %prec THEN
     1722                // SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement.
     1723                {
     1724            $$ = new StatementNode( build_waituntil_stmt( yylloc, $1 ) );
     1725            // $$ = new StatementNode( build_compound( yylloc, nullptr ) );
     1726        }
    16431727        ;
    16441728
    16451729exception_statement:
    1646         TRY compound_statement handler_clause                                   %prec THEN
    1647                 { $$ = new StatementNode( build_try( $2, $3, 0 ) ); }
     1730        TRY compound_statement handler_clause                                   %prec THEN
     1731                { $$ = new StatementNode( build_try( yylloc, $2, $3, nullptr ) ); }
    16481732        | TRY compound_statement finally_clause
    1649                 { $$ = new StatementNode( build_try( $2, 0, $3 ) ); }
     1733                { $$ = new StatementNode( build_try( yylloc, $2, nullptr, $3 ) ); }
    16501734        | TRY compound_statement handler_clause finally_clause
    1651                 { $$ = new StatementNode( build_try( $2, $3, $4 ) ); }
     1735                { $$ = new StatementNode( build_try( yylloc, $2, $3, $4 ) ); }
    16521736        ;
    16531737
    16541738handler_clause:
    16551739        handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
    1656                 { $$ = new StatementNode( build_catch( $1, $4, $6, $8 ) ); }
     1740                { $$ = new ClauseNode( build_catch( yylloc, $1, $4, $6, $8 ) ); }
    16571741        | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
    1658                 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch( $2, $5, $7, $9 ) ) ); }
     1742                { $$ = $1->set_last( new ClauseNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); }
    16591743        ;
    16601744
     
    16661750
    16671751handler_key:
    1668         CATCH                                                                           { $$ = CatchStmt::Terminate; }
    1669         | RECOVER                                                                       { $$ = CatchStmt::Terminate; }
    1670         | CATCHRESUME                                                           { $$ = CatchStmt::Resume; }
    1671         | FIXUP                                                                         { $$ = CatchStmt::Resume; }
     1752        CATCH                                                                           { $$ = ast::Terminate; }
     1753        | RECOVER                                                                       { $$ = ast::Terminate; }
     1754        | CATCHRESUME                                                           { $$ = ast::Resume; }
     1755        | FIXUP                                                                         { $$ = ast::Resume; }
    16721756        ;
    16731757
    16741758finally_clause:
    1675         FINALLY compound_statement                                      { $$ = new StatementNode( build_finally( $2 ) ); }
     1759        FINALLY compound_statement                                      { $$ = new ClauseNode( build_finally( yylloc, $2 ) ); }
    16761760        ;
    16771761
     
    16991783asm_statement:
    17001784        ASM asm_volatile_opt '(' string_literal ')' ';'
    1701                 { $$ = new StatementNode( build_asm( $2, $4, 0 ) ); }
     1785                { $$ = new StatementNode( build_asm( yylloc, $2, $4, nullptr ) ); }
    17021786        | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ')' ';' // remaining GCC
    1703                 { $$ = new StatementNode( build_asm( $2, $4, $6 ) ); }
     1787                { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6 ) ); }
    17041788        | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ')' ';'
    1705                 { $$ = new StatementNode( build_asm( $2, $4, $6, $8 ) ); }
     1789                { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8 ) ); }
    17061790        | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ':' asm_clobbers_list_opt ')' ';'
    1707                 { $$ = new StatementNode( build_asm( $2, $4, $6, $8, $10 ) ); }
     1791                { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8, $10 ) ); }
    17081792        | ASM asm_volatile_opt GOTO '(' string_literal ':' ':' asm_operands_opt ':' asm_clobbers_list_opt ':' label_list ')' ';'
    1709                 { $$ = new StatementNode( build_asm( $2, $5, 0, $8, $10, $12 ) ); }
     1793                { $$ = new StatementNode( build_asm( yylloc, $2, $5, nullptr, $8, $10, $12 ) ); }
    17101794        ;
    17111795
     
    17311815asm_operand:                                                                                    // GCC
    17321816        string_literal '(' constant_expression ')'
    1733                 { $$ = new ExpressionNode( new AsmExpr( nullptr, $1, maybeMoveBuild<Expression>( $3 ) ) ); }
     1817                { $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
    17341818        | '[' IDENTIFIER ']' string_literal '(' constant_expression ')'
    1735                 { $$ = new ExpressionNode( new AsmExpr( $2, $4, maybeMoveBuild<Expression>( $6 ) ) ); }
     1819                {
     1820                        $$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, maybeMoveBuild( $4 ), maybeMoveBuild( $6 ) ) );
     1821                        delete $2.str;
     1822                }
    17361823        ;
    17371824
     
    17401827                { $$ = nullptr; }                                                               // use default argument
    17411828        | string_literal
    1742                 { $$ = new ExpressionNode( $1 ); }
     1829                { $$ = $1; }
    17431830        | asm_clobbers_list_opt ',' string_literal
    1744                 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( $3 ) )); }
     1831                { $$ = (ExpressionNode *)( $1->set_last( $3 ) ); }
    17451832        ;
    17461833
     
    17481835        identifier
    17491836                {
    1750                         $$ = new LabelNode(); $$->labels.push_back( *$1 );
     1837                        $$ = new LabelNode(); $$->labels.emplace_back( yylloc, *$1 );
    17511838                        delete $1;                                                                      // allocated by lexer
    17521839                }
    17531840        | label_list ',' identifier
    17541841                {
    1755                         $$ = $1; $1->labels.push_back( *$3 );
     1842                        $$ = $1; $1->labels.emplace_back( yylloc, *$3 );
    17561843                        delete $3;                                                                      // allocated by lexer
    17571844                }
     
    18041891                {
    18051892                        // printf( "C_DECLARATION1 %p %s\n", $$, $$->name ? $$->name->c_str() : "(nil)" );
    1806                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     1893                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    18071894                        //   printf( "\tattr %s\n", attr->name.c_str() );
    18081895                        // } // for
     
    18141901static_assert:
    18151902        STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
    1816                 { $$ = DeclarationNode::newStaticAssert( $3, $5 ); }
     1903                { $$ = DeclarationNode::newStaticAssert( $3, maybeMoveBuild( $5 ) ); }
    18171904        | STATICASSERT '(' constant_expression ')' ';'          // CFA
    1818                 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( *new string( "\"\"" ) ) ); }
     1905                { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( yylloc, *new string( "\"\"" ) ) ); }
    18191906
    18201907// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
     
    18801967//      '[' ']' identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' // S/R conflict
    18811968//              {
    1882 //                      $$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, 0, true );
     1969//                      $$ = DeclarationNode::newFunction( $3, DeclarationNode::newTuple( 0 ), $6, nullptr, true );
    18831970//              }
    18841971//      '[' ']' identifier '(' push cfa_parameter_ellipsis_list_opt pop ')'
    18851972//              {
    18861973//                      typedefTable.setNextIdentifier( *$5 );
    1887 //                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
     1974//                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
    18881975//              }
    18891976//      | '[' ']' TYPEDEFname '(' push cfa_parameter_ellipsis_list_opt pop ')'
    18901977//              {
    18911978//                      typedefTable.setNextIdentifier( *$5 );
    1892 //                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, 0, true );
     1979//                      $$ = DeclarationNode::newFunction( $5, DeclarationNode::newTuple( 0 ), $8, nullptr, true );
    18931980//              }
    18941981//      | '[' ']' typegen_name
     
    19021989        cfa_abstract_tuple identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
    19031990                // To obtain LR(1 ), this rule must be factored out from function return type (see cfa_abstract_declarator).
    1904                 { $$ = DeclarationNode::newFunction( $2, $1, $5, 0 )->addQualifiers( $8 ); }
     1991                { $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
    19051992        | cfa_function_return identifier_or_type_name '(' push cfa_parameter_ellipsis_list_opt pop ')' attribute_list_opt
    1906                 { $$ = DeclarationNode::newFunction( $2, $1, $5, 0 )->addQualifiers( $8 ); }
     1993                { $$ = DeclarationNode::newFunction( $2, $1, $5, nullptr )->addQualifiers( $8 ); }
    19071994        ;
    19081995
     
    19402027                {
    19412028                        typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "4" );
    1942                         $$ = $3->addType( $2 )->addTypedef();
     2029                        if ( $2->type->forall || ($2->type->kind == TypeData::Aggregate && $2->type->aggregate.params) ) {
     2030                                SemanticError( yylloc, "forall qualifier in typedef is currently unimplemented." ); $$ = nullptr;
     2031                        } else $$ = $3->addType( $2 )->addTypedef(); // watchout frees $2 and $3
    19432032                }
    19442033        | typedef_declaration pop ',' push declarator
     
    19482037                }
    19492038        | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 )
    1950                 {
    1951                         typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "6" );
    1952                         $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef();
    1953                 }
     2039                { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
    19542040        | type_specifier TYPEDEF declarator
    1955                 {
    1956                         typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "7" );
    1957                         $$ = $3->addType( $1 )->addTypedef();
    1958                 }
     2041                { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
    19592042        | type_specifier TYPEDEF type_qualifier_list declarator
    1960                 {
    1961                         typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "8" );
    1962                         $$ = $4->addQualifiers( $1 )->addTypedef()->addType( $1 );
    1963                 }
     2043                { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
    19642044        ;
    19652045
     
    19682048        TYPEDEF identifier '=' assignment_expression
    19692049                {
    1970                         SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
     2050                        SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
    19712051                }
    19722052        | typedef_expression pop ',' push identifier '=' assignment_expression
    19732053                {
    1974                         SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
     2054                        SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
    19752055                }
    19762056        ;
     
    19822062        | typedef_expression                                                            // deprecated GCC, naming expression type
    19832063        | sue_declaration_specifier
     2064                {
     2065                        assert( $1->type );
     2066                        if ( $1->type->qualifiers.any() ) {                     // CV qualifiers ?
     2067                                SemanticError( yylloc, "Useless type qualifier(s) in empty declaration." ); $$ = nullptr;
     2068                        }
     2069                        // enums are never empty declarations because there must have at least one enumeration.
     2070                        if ( $1->type->kind == TypeData::AggregateInst && $1->storageClasses.any() ) { // storage class ?
     2071                                SemanticError( yylloc, "Useless storage qualifier(s) in empty aggregate declaration." ); $$ = nullptr;
     2072                        }
     2073                }
    19842074        ;
    19852075
     
    19872077                // A semantic check is required to ensure asm_name only appears on declarations with implicit or explicit static
    19882078                // storage-class
    1989         declarator asm_name_opt initializer_opt
     2079        variable_declarator asm_name_opt initializer_opt
    19902080                { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); }
     2081        | variable_type_redeclarator asm_name_opt initializer_opt
     2082                { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); }
     2083
     2084        | general_function_declarator asm_name_opt
     2085                { $$ = $1->addAsmName( $2 )->addInitializer( nullptr ); }
     2086        | general_function_declarator asm_name_opt '=' VOID
     2087                { $$ = $1->addAsmName( $2 )->addInitializer( new InitializerNode( true ) ); }
     2088
    19912089        | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
    19922090                { $$ = $1->appendList( $4->addQualifiers( $3 )->addAsmName( $5 )->addInitializer( $6 ) ); }
    19932091        ;
    19942092
     2093general_function_declarator:
     2094        function_type_redeclarator
     2095        | function_declarator
     2096        ;
     2097
    19952098declaration_specifier:                                                                  // type specifier + storage class
    19962099        basic_declaration_specifier
     2100        | type_declaration_specifier
    19972101        | sue_declaration_specifier
    1998         | type_declaration_specifier
     2102        | sue_declaration_specifier invalid_types
     2103                {
     2104                        SemanticError( yylloc, ::toString( "Missing ';' after end of ",
     2105                                $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ),
     2106                                " declaration" ) );
     2107                        $$ = nullptr;
     2108                }
     2109        ;
     2110
     2111invalid_types:
     2112        aggregate_key
     2113        | basic_type_name
     2114        | indirect_type
    19992115        ;
    20002116
     
    20132129        basic_type_specifier
    20142130        | sue_type_specifier
    2015                 {
    2016                         // printf( "sue_type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2017                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    2018                         //   printf( "\tattr %s\n", attr->name.c_str() );
    2019                         // } // for
    2020                 }
    20212131        | type_type_specifier
    20222132        ;
     
    20652175                { $$ = DeclarationNode::newTypeQualifier( Type::Atomic ); }
    20662176        | forall
     2177                { $$ = DeclarationNode::newForall( $1 ); }
    20672178        ;
    20682179
    20692180forall:
    20702181        FORALL '(' type_parameter_list ')'                                      // CFA
    2071                 { $$ = DeclarationNode::newForall( $3 ); }
     2182                { $$ = $3; }
    20722183        ;
    20732184
     
    22262337                { $$ = DeclarationNode::newTypeof( $3 ); }
    22272338        | BASETYPEOF '(' type ')'                                                       // CFA: basetypeof( x ) y;
    2228                 { $$ = DeclarationNode::newTypeof( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ), true ); }
     2339                { $$ = DeclarationNode::newTypeof( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ), true ); }
    22292340        | BASETYPEOF '(' comma_expression ')'                           // CFA: basetypeof( a+b ) y;
    22302341                { $$ = DeclarationNode::newTypeof( $3, true ); }
     
    22392350                {
    22402351                        // printf( "sue_declaration_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2241                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2352                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    22422353                        //   printf( "\tattr %s\n", attr->name.c_str() );
    22432354                        // } // for
     
    22552366                {
    22562367                        // printf( "sue_type_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2257                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2368                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    22582369                        //   printf( "\tattr %s\n", attr->name.c_str() );
    22592370                        // } // for
     
    23332444                {
    23342445                        // printf( "elaborated_type %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2335                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2446                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    23362447                        //   printf( "\tattr %s\n", attr->name.c_str() );
    23372448                        // } // for
     
    23572468          '{' field_declaration_list_opt '}' type_parameters_opt
    23582469                {
    2359                         // printf( "aggregate_type1 %s\n", $3.str->c_str() );
    2360                         // if ( $2 )
    2361                         //      for ( Attribute * attr: reverseIterate( $2->attributes ) ) {
    2362                         //              printf( "copySpecifiers12 %s\n", attr->name.c_str() );
    2363                         //      } // for
    23642470                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
    2365                         // printf( "aggregate_type2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2366                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    2367                         //      printf( "aggregate_type3 %s\n", attr->name.c_str() );
    2368                         // } // for
    23692471                }
    23702472        | aggregate_key attribute_list_opt TYPEDEFname          // unqualified type name
     
    23752477          '{' field_declaration_list_opt '}' type_parameters_opt
    23762478                {
    2377                         // printf( "AGG3\n" );
    23782479                        DeclarationNode::newFromTypedef( $3 );
    23792480                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
     
    23862487          '{' field_declaration_list_opt '}' type_parameters_opt
    23872488                {
    2388                         // printf( "AGG4\n" );
    23892489                        DeclarationNode::newFromTypeGen( $3, nullptr );
    23902490                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
     
    24132513                        // switched to a TYPEGENname. Link any generic arguments from typegen_name to new generic declaration and
    24142514                        // delete newFromTypeGen.
    2415                         $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 );
    2416                         $3->type->symbolic.name = nullptr;
    2417                         $3->type->symbolic.actuals = nullptr;
    2418                         delete $3;
     2515                        if ( $3->type->kind == TypeData::SymbolicInst && ! $3->type->symbolic.isTypedef ) {
     2516                                $$ = $3->addQualifiers( $2 );
     2517                        } else {
     2518                                $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 );
     2519                                $3->type->symbolic.name = nullptr;                      // copied to $$
     2520                                $3->type->symbolic.actuals = nullptr;
     2521                                delete $3;
     2522                        }
    24192523                }
    24202524        ;
     
    24272531aggregate_data:
    24282532        STRUCT vtable_opt
    2429                 { $$ = AggregateDecl::Struct; }
     2533                { $$ = ast::AggregateDecl::Struct; }
    24302534        | UNION
    2431                 { $$ = AggregateDecl::Union; }
     2535                { $$ = ast::AggregateDecl::Union; }
    24322536        | EXCEPTION                                                                                     // CFA
    2433                 { $$ = AggregateDecl::Exception; }
    2434           //            { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
     2537                { $$ = ast::AggregateDecl::Exception; }
     2538          //            { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = ast::AggregateDecl::NoAggregate; }
    24352539        ;
    24362540
    24372541aggregate_control:                                                                              // CFA
    24382542        MONITOR
    2439                 { $$ = AggregateDecl::Monitor; }
     2543                { $$ = ast::AggregateDecl::Monitor; }
    24402544        | MUTEX STRUCT
    2441                 { $$ = AggregateDecl::Monitor; }
     2545                { $$ = ast::AggregateDecl::Monitor; }
    24422546        | GENERATOR
    2443                 { $$ = AggregateDecl::Generator; }
     2547                { $$ = ast::AggregateDecl::Generator; }
    24442548        | MUTEX GENERATOR
    2445                 { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
     2549                {
     2550                        SemanticError( yylloc, "monitor generator is currently unimplemented." );
     2551                        $$ = ast::AggregateDecl::NoAggregate;
     2552                }
    24462553        | COROUTINE
    2447                 { $$ = AggregateDecl::Coroutine; }
     2554                { $$ = ast::AggregateDecl::Coroutine; }
    24482555        | MUTEX COROUTINE
    2449                 { SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
     2556                {
     2557                        SemanticError( yylloc, "monitor coroutine is currently unimplemented." );
     2558                        $$ = ast::AggregateDecl::NoAggregate;
     2559                }
    24502560        | THREAD
    2451                 { $$ = AggregateDecl::Thread; }
     2561                { $$ = ast::AggregateDecl::Thread; }
    24522562        | MUTEX THREAD
    2453                 { SemanticError( yylloc, "monitor thread is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
     2563                {
     2564                        SemanticError( yylloc, "monitor thread is currently unimplemented." );
     2565                        $$ = ast::AggregateDecl::NoAggregate;
     2566                }
    24542567        ;
    24552568
     
    24672580                        $$ = fieldDecl( $1, $2 );
    24682581                        // printf( "type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2469                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2582                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    24702583                        //   printf( "\tattr %s\n", attr->name.c_str() );
    24712584                        // } // for
     
    24732586        | EXTENSION type_specifier field_declaring_list_opt ';' // GCC
    24742587                { $$ = fieldDecl( $2, $3 ); distExt( $$ ); }
     2588        | STATIC type_specifier field_declaring_list_opt ';' // CFA
     2589                { SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; }
    24752590        | INLINE type_specifier field_abstract_list_opt ';'     // CFA
    24762591                {
     
    24832598                }
    24842599        | INLINE aggregate_control ';'                                          // CFA
    2485                 { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }
     2600                { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }
    24862601        | typedef_declaration ';'                                                       // CFA
    24872602        | cfa_field_declaring_list ';'                                          // CFA, new style field declaration
     
    25092624                { $$ = $1->addBitfield( $2 ); }
    25102625        | variable_type_redeclarator bit_subrange_size_opt
     2626                // A semantic check is required to ensure bit_subrange only appears on integral types.
     2627                { $$ = $1->addBitfield( $2 ); }
     2628        | function_type_redeclarator bit_subrange_size_opt
    25112629                // A semantic check is required to ensure bit_subrange only appears on integral types.
    25122630                { $$ = $1->addBitfield( $2 ); }
     
    25632681                { $$ = DeclarationNode::newEnum( $3->name, $6, true, false, nullptr, $4 )->addQualifiers( $2 ); }
    25642682        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}'
    2565                 {
    2566                         if ( $3->storageClasses.val != 0 || $3->type->qualifiers.val != 0 )
     2683                {
     2684                        if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() )
    25672685                        { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    25682686
     
    25752693        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt
    25762694                {
    2577                         if ( $3->storageClasses.val != 0 || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
     2695                        if ( $3->storageClasses.any() || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    25782696                        typedefTable.makeTypedef( *$6 );
    25792697                }
     
    26092727enum_type_nobody:                                                                               // enum - {...}
    26102728        ENUM attribute_list_opt identifier
    2611                 { typedefTable.makeTypedef( *$3 ); $$ = DeclarationNode::newEnum( $3, 0, false, false )->addQualifiers( $2 ); }
     2729                { typedefTable.makeTypedef( *$3 ); $$ = DeclarationNode::newEnum( $3, nullptr, false, false )->addQualifiers( $2 ); }
    26122730        | ENUM attribute_list_opt type_name
    2613                 { typedefTable.makeTypedef( *$3->type->symbolic.name ); $$ = DeclarationNode::newEnum( $3->type->symbolic.name, 0, false, false )->addQualifiers( $2 ); }
     2731                { typedefTable.makeTypedef( *$3->type->symbolic.name ); $$ = DeclarationNode::newEnum( $3->type->symbolic.name, nullptr, false, false )->addQualifiers( $2 ); }
    26142732        ;
    26152733
     
    27512869type_no_function:                                                                               // sizeof, alignof, cast (constructor)
    27522870        cfa_abstract_declarator_tuple                                           // CFA
    2753         | type_specifier
     2871        | type_specifier                                                                        // cannot be type_specifier_nobody, e.g., (struct S {}){} is a thing
    27542872        | type_specifier abstract_declarator
    27552873                { $$ = $2->addType( $1 ); }
     
    27962914        designator_list ':'                                                                     // C99, CFA uses ":" instead of "="
    27972915        | identifier_at ':'                                                                     // GCC, field name
    2798                 { $$ = new ExpressionNode( build_varref( $1 ) ); }
     2916                { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
    27992917        ;
    28002918
     
    28082926designator:
    28092927        '.' identifier_at                                                                       // C99, field name
    2810                 { $$ = new ExpressionNode( build_varref( $2 ) ); }
     2928                { $$ = new ExpressionNode( build_varref( yylloc, $2 ) ); }
    28112929        | '[' push assignment_expression pop ']'                        // C99, single array element
    28122930                // assignment_expression used instead of constant_expression because of shift/reduce conflicts with tuple.
     
    28152933                { $$ = $3; }
    28162934        | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements
    2817                 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $3 ), maybeMoveBuild<Expression>( $5 ) ) ); }
     2935                { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $3 ), maybeMoveBuild( $5 ) ) ); }
    28182936        | '.' '[' push field_name_list pop ']'                          // CFA, tuple field selector
    28192937                { $$ = $4; }
     
    28552973                {
    28562974                        typedefTable.addToScope( *$2, TYPEDEFname, "9" );
    2857                         if ( $1 == TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }
    2858                         if ( $1 == TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }
    2859                         if ( $1 == TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }
     2975                        if ( $1 == ast::TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }
     2976                        if ( $1 == ast::TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }
     2977                        if ( $1 == ast::TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }
    28602978                }
    28612979          type_initializer_opt assertion_list_opt
     
    28682986                {
    28692987                        typedefTable.addToScope( *$2, TYPEDIMname, "9" );
    2870                         $$ = DeclarationNode::newTypeParam( TypeDecl::Dimension, $2 );
     2988                        $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dimension, $2 );
    28712989                }
    28722990        // | type_specifier identifier_parameter_declarator
    28732991        | assertion_list
    2874                 { $$ = DeclarationNode::newTypeParam( TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }
     2992                { $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }
    28752993        ;
    28762994
    28772995new_type_class:                                                                                 // CFA
    28782996        // empty
    2879                 { $$ = TypeDecl::Otype; }
     2997                { $$ = ast::TypeDecl::Otype; }
    28802998        | '&'
    2881                 { $$ = TypeDecl::Dtype; }
     2999                { $$ = ast::TypeDecl::Dtype; }
    28823000        | '*'
    2883                 { $$ = TypeDecl::DStype; }                                              // dtype + sized
     3001                { $$ = ast::TypeDecl::DStype; }                                         // dtype + sized
    28843002        // | '(' '*' ')'
    2885         //      { $$ = TypeDecl::Ftype; }
     3003        //      { $$ = ast::TypeDecl::Ftype; }
    28863004        | ELLIPSIS
    2887                 { $$ = TypeDecl::Ttype; }
     3005                { $$ = ast::TypeDecl::Ttype; }
    28883006        ;
    28893007
    28903008type_class:                                                                                             // CFA
    28913009        OTYPE
    2892                 { $$ = TypeDecl::Otype; }
     3010                { $$ = ast::TypeDecl::Otype; }
    28933011        | DTYPE
    2894                 { $$ = TypeDecl::Dtype; }
     3012                { $$ = ast::TypeDecl::Dtype; }
    28953013        | FTYPE
    2896                 { $$ = TypeDecl::Ftype; }
     3014                { $$ = ast::TypeDecl::Ftype; }
    28973015        | TTYPE
    2898                 { $$ = TypeDecl::Ttype; }
     3016                { $$ = ast::TypeDecl::Ttype; }
    28993017        ;
    29003018
     
    29223040type_list:                                                                                              // CFA
    29233041        type
    2924                 { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
     3042                { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
    29253043        | assignment_expression
    29263044        | type_list ',' type
    2927                 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
     3045                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
    29283046        | type_list ',' assignment_expression
    29293047                { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
     
    29503068                {
    29513069                        typedefTable.addToEnclosingScope( *$1, TYPEDEFname, "10" );
    2952                         $$ = DeclarationNode::newTypeDecl( $1, 0 );
     3070                        $$ = DeclarationNode::newTypeDecl( $1, nullptr );
    29533071                }
    29543072        | identifier_or_type_name '(' type_parameter_list ')'
     
    29613079trait_specifier:                                                                                // CFA
    29623080        TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}'
    2963                 { $$ = DeclarationNode::newTrait( $2, $4, 0 ); }
     3081                {
     3082                        SemanticWarning( yylloc, Warning::DeprecTraitSyntax );
     3083                        $$ = DeclarationNode::newTrait( $2, $4, nullptr );
     3084                }
     3085        | forall TRAIT identifier_or_type_name '{' '}'          // alternate
     3086                { $$ = DeclarationNode::newTrait( $3, $1, nullptr ); }
    29643087        | TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
    2965                 { $$ = DeclarationNode::newTrait( $2, $4, $8 ); }
     3088                {
     3089                        SemanticWarning( yylloc, Warning::DeprecTraitSyntax );
     3090                        $$ = DeclarationNode::newTrait( $2, $4, $8 );
     3091                }
     3092        | forall TRAIT identifier_or_type_name '{' push trait_declaration_list pop '}' // alternate
     3093                { $$ = DeclarationNode::newTrait( $3, $1, $6 ); }
    29663094        ;
    29673095
     
    30223150external_definition:
    30233151        DIRECTIVE
    3024                 { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( $1 ) ) ); }
     3152                { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( yylloc, $1 ) ) ); }
    30253153        | declaration
     3154                {
     3155                        // Variable declarations of anonymous types requires creating a unique type-name across multiple translation
     3156                        // unit, which is a dubious task, especially because C uses name rather than structural typing; hence it is
     3157                        // disallowed at the moment.
     3158                        if ( $1->linkage == ast::Linkage::Cforall && ! $1->storageClasses.is_static && $1->type && $1->type->kind == TypeData::AggregateInst ) {
     3159                                if ( $1->type->aggInst.aggregate->kind == TypeData::Enum && $1->type->aggInst.aggregate->enumeration.anon ) {
     3160                                        SemanticError( yylloc, "extern anonymous enumeration is currently unimplemented." ); $$ = nullptr;
     3161                                } else if ( $1->type->aggInst.aggregate->aggregate.anon ) { // handles struct or union
     3162                                        SemanticError( yylloc, "extern anonymous struct/union is currently unimplemented." ); $$ = nullptr;
     3163                                }
     3164                        }
     3165                }
    30263166        | IDENTIFIER IDENTIFIER
    30273167                { IdentifierBeforeIdentifier( *$1.str, *$2.str, " declaration" ); $$ = nullptr; }
     
    30433183                }
    30443184        | ASM '(' string_literal ')' ';'                                        // GCC, global assembler statement
    3045                 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, 0 ) ) ); }
     3185                { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( yylloc, false, $3, nullptr ) ) ); }
    30463186        | EXTERN STRINGliteral
    30473187                {
    30483188                        linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
    3049                         linkage = LinkageSpec::update( yylloc, linkage, $2 );
     3189                        linkage = ast::Linkage::update( yylloc, linkage, $2 );
    30503190                }
    30513191          up external_definition down
     
    30583198                {
    30593199                        linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
    3060                         linkage = LinkageSpec::update( yylloc, linkage, $2 );
     3200                        linkage = ast::Linkage::update( yylloc, linkage, $2 );
    30613201                }
    30623202          '{' up external_definition_list_opt down '}'
     
    30693209        | type_qualifier_list
    30703210                {
    3071                         if ( $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
     3211                        if ( $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    30723212                        if ( $1->type->forall ) forall = true;          // remember generic type
    30733213                }
     
    30753215                {
    30763216                        distQual( $5, $1 );
    3077                         forall = false;
     3217                        forall = false;
    30783218                        $$ = $5;
    30793219                }
    30803220        | declaration_qualifier_list
    30813221                {
    3082                         if ( $1->type && $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
     3222                        if ( $1->type && $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    30833223                        if ( $1->type && $1->type->forall ) forall = true; // remember generic type
    30843224                }
     
    30863226                {
    30873227                        distQual( $5, $1 );
    3088                         forall = false;
     3228                        forall = false;
    30893229                        $$ = $5;
    30903230                }
    30913231        | declaration_qualifier_list type_qualifier_list
    30923232                {
    3093                         if ( ($1->type && $1->type->qualifiers.val) || ($2->type && $2->type->qualifiers.val) ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
     3233                        if ( ($1->type && $1->type->qualifiers.any()) || ($2->type && $2->type->qualifiers.any()) ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    30943234                        if ( ($1->type && $1->type->forall) || ($2->type && $2->type->forall) ) forall = true; // remember generic type
    30953235                }
     
    30973237                {
    30983238                        distQual( $6, $1->addQualifiers( $2 ) );
    3099                         forall = false;
     3239                        forall = false;
    31003240                        $$ = $6;
    31013241                }
     
    31413281                        $$ = $2->addFunctionBody( $4, $3 )->addType( $1 );
    31423282                }
    3143         | declaration_specifier variable_type_redeclarator with_clause_opt compound_statement
     3283        | declaration_specifier function_type_redeclarator with_clause_opt compound_statement
    31443284                {
    31453285                        rebindForall( $1, $2 );
     
    31773317        | variable_type_redeclarator
    31783318        | function_declarator
     3319        | function_type_redeclarator
    31793320        ;
    31803321
    31813322subrange:
    31823323        constant_expression '~' constant_expression                     // CFA, integer subrange
    3183                 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }
     3324                { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
    31843325        ;
    31853326
     
    31903331                {
    31913332                        DeclarationNode * name = new DeclarationNode();
    3192                         name->asmName = $3;
     3333                        name->asmName = maybeMoveBuild( $3 );
    31933334                        $$ = name->addQualifiers( $5 );
    31943335                }
     
    32873428variable_ptr:
    32883429        ptrref_operator variable_declarator
    3289                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     3430                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    32903431        | ptrref_operator type_qualifier_list variable_declarator
    32913432                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    33033444        | '(' attribute_list variable_ptr ')' array_dimension
    33043445                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
    3305         | '(' variable_array ')' multi_array_dimension          // redundant parenthesis
     3446        | '(' variable_array ')' multi_array_dimension          // redundant parenthesis
    33063447                { $$ = $2->addArray( $4 ); }
    33073448        | '(' attribute_list variable_array ')' multi_array_dimension // redundant parenthesis
     
    33513492function_ptr:
    33523493        ptrref_operator function_declarator
    3353                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     3494                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    33543495        | ptrref_operator type_qualifier_list function_declarator
    33553496                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    34033544KR_function_ptr:
    34043545        ptrref_operator KR_function_declarator
    3405                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     3546                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    34063547        | ptrref_operator type_qualifier_list KR_function_declarator
    34073548                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    34273568        ;
    34283569
    3429 // This pattern parses a declaration for a variable or function prototype that redefines a type name, e.g.:
     3570// This pattern parses a declaration for a variable that redefines a type name, e.g.:
    34303571//
    34313572//              typedef int foo;
     
    34333574//                 int foo; // redefine typedef name in new scope
    34343575//              }
    3435 //
    3436 // The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
    3437 // and functions versus pointers to arrays and functions.
    34383576
    34393577paren_type:
     
    34503588        paren_type attribute_list_opt
    34513589                { $$ = $1->addQualifiers( $2 ); }
    3452         | type_ptr
    3453         | type_array attribute_list_opt
     3590        | variable_type_ptr
     3591        | variable_type_array attribute_list_opt
    34543592                { $$ = $1->addQualifiers( $2 ); }
    3455         | type_function attribute_list_opt
     3593        | variable_type_function attribute_list_opt
    34563594                { $$ = $1->addQualifiers( $2 ); }
    34573595        ;
    34583596
    3459 type_ptr:
     3597variable_type_ptr:
    34603598        ptrref_operator variable_type_redeclarator
    3461                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     3599                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    34623600        | ptrref_operator type_qualifier_list variable_type_redeclarator
    34633601                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    3464         | '(' type_ptr ')' attribute_list_opt                           // redundant parenthesis
     3602        | '(' variable_type_ptr ')' attribute_list_opt          // redundant parenthesis
    34653603                { $$ = $2->addQualifiers( $4 ); }
    3466         | '(' attribute_list type_ptr ')' attribute_list_opt // redundant parenthesis
     3604        | '(' attribute_list variable_type_ptr ')' attribute_list_opt // redundant parenthesis
    34673605                { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); }
    34683606        ;
    34693607
    3470 type_array:
     3608variable_type_array:
    34713609        paren_type array_dimension
    34723610                { $$ = $1->addArray( $2 ); }
    3473         | '(' type_ptr ')' array_dimension
     3611        | '(' variable_type_ptr ')' array_dimension
    34743612                { $$ = $2->addArray( $4 ); }
    3475         | '(' attribute_list type_ptr ')' array_dimension
     3613        | '(' attribute_list variable_type_ptr ')' array_dimension
    34763614                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
    3477         | '(' type_array ')' multi_array_dimension                      // redundant parenthesis
     3615        | '(' variable_type_array ')' multi_array_dimension     // redundant parenthesis
    34783616                { $$ = $2->addArray( $4 ); }
    3479         | '(' attribute_list type_array ')' multi_array_dimension // redundant parenthesis
     3617        | '(' attribute_list variable_type_array ')' multi_array_dimension // redundant parenthesis
    34803618                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
    3481         | '(' type_array ')'                                                            // redundant parenthesis
     3619        | '(' variable_type_array ')'                                           // redundant parenthesis
    34823620                { $$ = $2; }
    3483         | '(' attribute_list type_array ')'                                     // redundant parenthesis
     3621        | '(' attribute_list variable_type_array ')'            // redundant parenthesis
    34843622                { $$ = $3->addQualifiers( $2 ); }
    34853623        ;
    34863624
    3487 type_function:
     3625variable_type_function:
     3626        '(' variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     3627                { $$ = $2->addParamList( $6 ); }
     3628        | '(' attribute_list variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     3629                { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); }
     3630        | '(' variable_type_function ')'                                        // redundant parenthesis
     3631                { $$ = $2; }
     3632        | '(' attribute_list variable_type_function ')'         // redundant parenthesis
     3633                { $$ = $3->addQualifiers( $2 ); }
     3634        ;
     3635
     3636// This pattern parses a declaration for a function prototype that redefines a type name.  It precludes declaring an
     3637// array of functions versus a pointer to an array of functions, and returning arrays and functions versus pointers to
     3638// arrays and functions.
     3639
     3640function_type_redeclarator:
     3641        function_type_no_ptr attribute_list_opt
     3642                { $$ = $1->addQualifiers( $2 ); }
     3643        | function_type_ptr
     3644        | function_type_array attribute_list_opt
     3645                { $$ = $1->addQualifiers( $2 ); }
     3646        ;
     3647
     3648function_type_no_ptr:
    34883649        paren_type '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    34893650                { $$ = $1->addParamList( $4 ); }
    3490         | '(' type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     3651        | '(' function_type_ptr ')' '(' push parameter_type_list_opt pop ')'
    34913652                { $$ = $2->addParamList( $6 ); }
    3492         | '(' attribute_list type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     3653        | '(' attribute_list function_type_ptr ')' '(' push parameter_type_list_opt pop ')'
    34933654                { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); }
    3494         | '(' type_function ')'                                                         // redundant parenthesis
     3655        | '(' function_type_no_ptr ')'                                          // redundant parenthesis
    34953656                { $$ = $2; }
    3496         | '(' attribute_list type_function ')'                          // redundant parenthesis
     3657        | '(' attribute_list function_type_no_ptr ')'           // redundant parenthesis
     3658                { $$ = $3->addQualifiers( $2 ); }
     3659        ;
     3660
     3661function_type_ptr:
     3662        ptrref_operator function_type_redeclarator
     3663                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3664        | ptrref_operator type_qualifier_list function_type_redeclarator
     3665                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     3666        | '(' function_type_ptr ')' attribute_list_opt
     3667                { $$ = $2->addQualifiers( $4 ); }
     3668        | '(' attribute_list function_type_ptr ')' attribute_list_opt
     3669                { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); }
     3670        ;
     3671
     3672function_type_array:
     3673        '(' function_type_ptr ')' array_dimension
     3674                { $$ = $2->addArray( $4 ); }
     3675        | '(' attribute_list function_type_ptr ')' array_dimension
     3676                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
     3677        | '(' function_type_array ')' multi_array_dimension     // redundant parenthesis
     3678                { $$ = $2->addArray( $4 ); }
     3679        | '(' attribute_list function_type_array ')' multi_array_dimension // redundant parenthesis
     3680                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
     3681        | '(' function_type_array ')'                                           // redundant parenthesis
     3682                { $$ = $2; }
     3683        | '(' attribute_list function_type_array ')'            // redundant parenthesis
    34973684                { $$ = $3->addQualifiers( $2 ); }
    34983685        ;
     
    35173704identifier_parameter_ptr:
    35183705        ptrref_operator identifier_parameter_declarator
    3519                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     3706                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    35203707        | ptrref_operator type_qualifier_list identifier_parameter_declarator
    35213708                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    35743761type_parameter_ptr:
    35753762        ptrref_operator type_parameter_redeclarator
    3576                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     3763                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    35773764        | ptrref_operator type_qualifier_list type_parameter_redeclarator
    35783765                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    36173804abstract_ptr:
    36183805        ptrref_operator
    3619                 { $$ = DeclarationNode::newPointer( 0, $1 ); }
     3806                { $$ = DeclarationNode::newPointer( nullptr, $1 ); }
    36203807        | ptrref_operator type_qualifier_list
    36213808                { $$ = DeclarationNode::newPointer( $2, $1 ); }
    36223809        | ptrref_operator abstract_declarator
    3623                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     3810                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    36243811        | ptrref_operator type_qualifier_list abstract_declarator
    36253812                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    36503837                // Only the first dimension can be empty.
    36513838        '[' ']'
    3652                 { $$ = DeclarationNode::newArray( 0, 0, false ); }
     3839                { $$ = DeclarationNode::newArray( nullptr, nullptr, false ); }
    36533840        | '[' ']' multi_array_dimension
    3654                 { $$ = DeclarationNode::newArray( 0, 0, false )->addArray( $3 ); }
     3841                { $$ = DeclarationNode::newArray( nullptr, nullptr, false )->addArray( $3 ); }
    36553842                // Cannot use constant_expression because of tuples => semantic check
    36563843        | '[' push assignment_expression pop ',' comma_expression ']' // CFA
    3657                 { $$ = DeclarationNode::newArray( $3, 0, false )->addArray( DeclarationNode::newArray( $6, 0, false ) ); }
     3844                { $$ = DeclarationNode::newArray( $3, nullptr, false )->addArray( DeclarationNode::newArray( $6, nullptr, false ) ); }
    36583845                // { SemanticError( yylloc, "New array dimension is currently unimplemented." ); $$ = nullptr; }
    36593846        | '[' push array_type_list pop ']'                                      // CFA
     
    36643851array_type_list:
    36653852        basic_type_name
    3666                 { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
     3853                { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
    36673854        | type_name
    3668                 { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
     3855                { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
    36693856        | assignment_expression upupeq assignment_expression
    36703857        | array_type_list ',' basic_type_name
    3671                 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
    3672         | array_type_list ',' type_name 
    3673                 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
     3858                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
     3859        | array_type_list ',' type_name
     3860                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
    36743861        | array_type_list ',' assignment_expression upupeq assignment_expression
    36753862        ;
     
    36803867        | ErangeUpEq
    36813868                { $$ = OperKinds::LEThan; }
    3682         ;
     3869        ;
    36833870
    36843871multi_array_dimension:
    36853872        '[' push assignment_expression pop ']'
    3686                 { $$ = DeclarationNode::newArray( $3, 0, false ); }
     3873                { $$ = DeclarationNode::newArray( $3, nullptr, false ); }
    36873874        | '[' push '*' pop ']'                                                          // C99
    36883875                { $$ = DeclarationNode::newVarArray( 0 ); }
    36893876        | multi_array_dimension '[' push assignment_expression pop ']'
    3690                 { $$ = $1->addArray( DeclarationNode::newArray( $4, 0, false ) ); }
     3877                { $$ = $1->addArray( DeclarationNode::newArray( $4, nullptr, false ) ); }
    36913878        | multi_array_dimension '[' push '*' pop ']'            // C99
    36923879                { $$ = $1->addArray( DeclarationNode::newVarArray( 0 ) ); }
     
    37853972array_parameter_1st_dimension:
    37863973        '[' ']'
    3787                 { $$ = DeclarationNode::newArray( 0, 0, false ); }
     3974                { $$ = DeclarationNode::newArray( nullptr, nullptr, false ); }
    37883975                // multi_array_dimension handles the '[' '*' ']' case
    37893976        | '[' push type_qualifier_list '*' pop ']'                      // remaining C99
    37903977                { $$ = DeclarationNode::newVarArray( $3 ); }
    37913978        | '[' push type_qualifier_list pop ']'
    3792                 { $$ = DeclarationNode::newArray( 0, $3, false ); }
     3979                { $$ = DeclarationNode::newArray( nullptr, $3, false ); }
    37933980                // multi_array_dimension handles the '[' assignment_expression ']' case
    37943981        | '[' push type_qualifier_list assignment_expression pop ']'
     
    38194006variable_abstract_ptr:
    38204007        ptrref_operator
    3821                 { $$ = DeclarationNode::newPointer( 0, $1 ); }
     4008                { $$ = DeclarationNode::newPointer( nullptr, $1 ); }
    38224009        | ptrref_operator type_qualifier_list
    38234010                { $$ = DeclarationNode::newPointer( $2, $1 ); }
    38244011        | ptrref_operator variable_abstract_declarator
    3825                 { $$ = $2->addPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     4012                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    38264013        | ptrref_operator type_qualifier_list variable_abstract_declarator
    38274014                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     
    38654052                // No SUE declaration in parameter list.
    38664053        ptrref_operator type_specifier_nobody
    3867                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     4054                { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    38684055        | type_qualifier_list ptrref_operator type_specifier_nobody
    38694056                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    38704057        | ptrref_operator cfa_abstract_function
    3871                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     4058                { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    38724059        | type_qualifier_list ptrref_operator cfa_abstract_function
    38734060                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    38744061        | ptrref_operator cfa_identifier_parameter_declarator_tuple
    3875                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     4062                { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    38764063        | type_qualifier_list ptrref_operator cfa_identifier_parameter_declarator_tuple
    38774064                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
     
    38824069                // shift/reduce conflict with new-style empty (void) function return type.
    38834070        '[' ']' type_specifier_nobody
    3884                 { $$ = $3->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     4071                { $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
    38854072        | cfa_array_parameter_1st_dimension type_specifier_nobody
    38864073                { $$ = $2->addNewArray( $1 ); }
    38874074        | '[' ']' multi_array_dimension type_specifier_nobody
    3888                 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     4075                { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
    38894076        | cfa_array_parameter_1st_dimension multi_array_dimension type_specifier_nobody
    38904077                { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
     
    38934080
    38944081        | '[' ']' cfa_identifier_parameter_ptr
    3895                 { $$ = $3->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     4082                { $$ = $3->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
    38964083        | cfa_array_parameter_1st_dimension cfa_identifier_parameter_ptr
    38974084                { $$ = $2->addNewArray( $1 ); }
    38984085        | '[' ']' multi_array_dimension cfa_identifier_parameter_ptr
    3899                 { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( 0, 0, false ) ); }
     4086                { $$ = $4->addNewArray( $3 )->addNewArray( DeclarationNode::newArray( nullptr, nullptr, false ) ); }
    39004087        | cfa_array_parameter_1st_dimension multi_array_dimension cfa_identifier_parameter_ptr
    39014088                { $$ = $3->addNewArray( $2 )->addNewArray( $1 ); }
     
    39534140cfa_abstract_ptr:                                                                               // CFA
    39544141        ptrref_operator type_specifier
    3955                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     4142                { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    39564143        | type_qualifier_list ptrref_operator type_specifier
    39574144                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    39584145        | ptrref_operator cfa_abstract_function
    3959                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     4146                { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    39604147        | type_qualifier_list ptrref_operator cfa_abstract_function
    39614148                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
    39624149        | ptrref_operator cfa_abstract_declarator_tuple
    3963                 { $$ = $2->addNewPointer( DeclarationNode::newPointer( 0, $1 ) ); }
     4150                { $$ = $2->addNewPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    39644151        | type_qualifier_list ptrref_operator cfa_abstract_declarator_tuple
    39654152                { $$ = $3->addNewPointer( DeclarationNode::newPointer( $1, $2 ) ); }
  • src/Parser/parserutility.cc

    r34b4268 r24d6572  
    1010// Created On       : Sat May 16 15:30:39 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tus Jul 18 10:12:00 2017
    13 // Update Count     : 8
     12// Last Modified On : Wed Mar  1 10:42:00 2023
     13// Update Count     : 9
    1414//
    1515
     
    1919#include <string>                // for string
    2020
    21 #include "SynTree/Constant.h"    // for Constant
    22 #include "SynTree/Expression.h"  // for UntypedExpr, CastExpr, ConstantExpr
    23 #include "SynTree/Type.h"        // for BasicType, ZeroType, BasicType::Kind...
     21#include "AST/Expr.hpp"          // for UntypedExpr, CastExpr, ConstantExpr
     22#include "AST/Type.hpp"          // for BasicType, ZeroType, BasicType::Kind...
    2423
    2524// rewrite
     
    2827//    if ( (int)(x != 0) ) ...
    2928
    30 Expression *notZeroExpr( Expression *orig ) {
    31         if( !orig ) return nullptr;
    32         UntypedExpr *comparison = new UntypedExpr( new NameExpr( "?!=?" ) );
    33         comparison->get_args().push_back( orig );
    34         comparison->get_args().push_back( new ConstantExpr( Constant( new ZeroType( noQualifiers ), "0", (unsigned long long int)0 ) ) );
    35         return new CastExpr( comparison, new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
     29ast::Expr * notZeroExpr( ast::Expr * orig ) {
     30        return ( !orig ) ? nullptr : new ast::CastExpr( orig->location,
     31                ast::UntypedExpr::createCall( orig->location,
     32                        "?!=?",
     33                        {
     34                                orig,
     35                                new ast::ConstantExpr( orig->location,
     36                                        new ast::ZeroType(),
     37                                        "0",
     38                                        std::optional<unsigned long long>( 0 )
     39                                ),
     40                        }
     41                ),
     42                new ast::BasicType( ast::BasicType::SignedInt )
     43        );
    3644}
    3745
  • src/Parser/parserutility.h

    r34b4268 r24d6572  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // parserutility.h --
     7// parserutility.h -- Collected utilities for the parser.
    88//
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Sat May 16 15:31:46 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:32:58 2017
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Apr  4 14:03:00 2023
     13// Update Count     : 7
    1414//
    1515
    1616#pragma once
    1717
    18 class Expression;
     18#include "AST/Copy.hpp"            // for shallowCopy
     19namespace ast {
     20        class Expr;
     21}
    1922
    20 Expression *notZeroExpr( Expression *orig );
     23ast::Expr * notZeroExpr( ast::Expr *orig );
     24
     25template< typename T >
     26static inline auto maybeBuild( T * orig ) -> decltype(orig->build()) {
     27        return (orig) ? orig->build() : nullptr;
     28}
     29
     30template< typename T >
     31static inline auto maybeMoveBuild( T * orig ) -> decltype(orig->build()) {
     32        auto ret = maybeBuild<T>(orig);
     33        delete orig;
     34        return ret;
     35}
     36
     37template<typename node_t>
     38node_t * maybeCopy( node_t const * node ) {
     39        return node ? ast::shallowCopy( node ) : nullptr;
     40}
    2141
    2242// Local Variables: //
  • src/ResolvExpr/AlternativeFinder.cc

    r34b4268 r24d6572  
    1414//
    1515
     16#include "AlternativeFinder.h"
     17
    1618#include <algorithm>               // for copy
    1719#include <cassert>                 // for strict_dynamic_cast, assert, assertf
     
    2628
    2729#include "CompilationState.h"      // for resolvep
     30#include "AdjustExprType.hpp"      // for adjustExprType
    2831#include "Alternative.h"           // for AltList, Alternative
    29 #include "AlternativeFinder.h"
    3032#include "AST/Expr.hpp"
    3133#include "AST/SymbolTable.hpp"
    3234#include "AST/Type.hpp"
     35#include "CastCost.hpp"            // for castCost
    3336#include "Common/SemanticError.h"  // for SemanticError
    3437#include "Common/utility.h"        // for deleteAll, printAll, CodeLocation
     38#include "ConversionCost.h"        // for conversionCost
    3539#include "Cost.h"                  // for Cost, Cost::zero, operator<<, Cost...
    3640#include "ExplodedActual.h"        // for ExplodedActual
    3741#include "InitTweak/InitTweak.h"   // for getFunctionName
     42#include "PolyCost.hpp"            // for polyCost
    3843#include "RenameVars.h"            // for RenameVars, global_renamer
    3944#include "ResolveAssertions.h"     // for resolveAssertions
    4045#include "ResolveTypeof.h"         // for resolveTypeof
    4146#include "Resolver.h"              // for resolveStmtExpr
     47#include "SpecCost.hpp"            // for specCost
    4248#include "SymTab/Indexer.h"        // for Indexer
    4349#include "SymTab/Mangler.h"        // for Mangler
     
    5157#include "Tuples/Explode.h"        // for explode
    5258#include "Tuples/Tuples.h"         // for isTtype, handleTupleAssignment
     59#include "typeops.h"               // for combos
    5360#include "Unify.h"                 // for unify
    54 #include "typeops.h"               // for adjustExprType, polyCost, castCost
    5561
    5662#define PRINT( text ) if ( resolvep ) { text }
  • src/ResolvExpr/AlternativeFinder.h

    r34b4268 r24d6572  
    3434namespace ResolvExpr {
    3535        struct ArgPack;
     36
     37        Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue,
     38                const SymTab::Indexer & indexer, const TypeEnvironment & env );
     39
     40        void referenceToRvalueConversion( Expression *& expr, Cost & cost );
    3641
    3742        /// First index is which argument, second index is which alternative for that argument,
  • src/ResolvExpr/Candidate.cpp

    r34b4268 r24d6572  
    1717
    1818#include <iostream>
     19#include <sstream>
    1920
    2021#include "AST/Print.hpp"
     
    4445        sorted.reserve(cands.size());
    4546        for(const auto & c : cands) {
    46                 std::stringstream ss;
     47                std::ostringstream ss;
    4748                print( ss, *c, indent );
    4849                sorted.push_back(ss.str());
  • src/ResolvExpr/CandidateFinder.cpp

    r34b4268 r24d6572  
    2323#include <vector>
    2424
     25#include "AdjustExprType.hpp"
    2526#include "Candidate.hpp"
    2627#include "CompilationState.h"
    2728#include "Cost.h"
     29#include "CastCost.hpp"
     30#include "PolyCost.hpp"
     31#include "SpecCost.hpp"
     32#include "ConversionCost.h"
    2833#include "ExplodedArg.hpp"
    2934#include "RenameVars.h"           // for renameTyVars
     
    403408                                                        unify(
    404409                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
    405                                                                 newResult.open, symtab )
     410                                                                newResult.open )
    406411                                                ) {
    407412                                                        finalResults.emplace_back( std::move( newResult ) );
     
    474479                                )
    475480
    476                                 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {
     481                                if ( unify( paramType, argType, env, need, have, open ) ) {
    477482                                        unsigned nextExpl = results[i].nextExpl + 1;
    478483                                        if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }
     
    493498                                        ast::OpenVarSet open = results[i].open;
    494499
    495                                         if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
     500                                        if ( unify( paramType, cnst->result, env, need, have, open ) ) {
    496501                                                results.emplace_back(
    497502                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ),
     
    536541
    537542                                // attempt to unify types
    538                                 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {
     543                                if ( unify( paramType, argType, env, need, have, open ) ) {
    539544                                        // add new result
    540545                                        results.emplace_back(
     
    703708                                if ( selfFinder.strictMode ) {
    704709                                        if ( ! unifyExact(
    705                                                 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, noWiden(), symtab ) // xxx - is no widening correct?
     710                                                returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, noWiden() ) // xxx - is no widening correct?
    706711                                        ) {
    707712                                                // unification failed, do not pursue this candidate
     
    711716                                else {
    712717                                        if ( ! unify(
    713                                                 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
     718                                                returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen )
    714719                                        ) {
    715720                                                // unification failed, do not pursue this candidate
     
    11561161
    11571162                                // unification run for side-effects
    1158                                 unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
     1163                                unify( toType, cand->expr->result, cand->env, need, have, open );
    11591164                                Cost thisCost =
    11601165                                        (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast)
     
    14971502                                                if (
    14981503                                                        unify(
    1499                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1504                                                                r2->expr->result, r3->expr->result, env, need, have, open,
    15001505                                                                common )
    15011506                                                ) {
     
    15711576                                        if (
    15721577                                                unify(
    1573                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1578                                                        r1->expr->result, r2->expr->result, env, need, have, open,
    15741579                                                        common )
    15751580                                        ) {
     
    16771682
    16781683                                        // unification run for side-effects
    1679                                         bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab );
     1684                                        bool canUnify = unify( toType, cand->expr->result, env, need, have, open );
    16801685                                        (void) canUnify;
    16811686                                        Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
  • src/ResolvExpr/CandidateFinder.hpp

    r34b4268 r24d6572  
    6565        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    6666
     67/// Create an expression that preforms reference to rvalue conversion on
     68/// the given expression and update the cost of the expression.
     69const ast::Expr * referenceToRvalueConversion(
     70        const ast::Expr * expr, Cost & cost );
     71
    6772} // namespace ResolvExpr
    6873
  • src/ResolvExpr/CastCost.cc

    r34b4268 r24d6572  
    1313// Update Count     : 9
    1414//
     15
     16#include "CastCost.hpp"
    1517
    1618#include <cassert>                       // for assert
     
    2224#include "ConversionCost.h"              // for ConversionCost
    2325#include "Cost.h"                        // for Cost, Cost::infinity
     26#include "ResolvExpr/ConversionCost.h"   // for conversionCost
     27#include "ResolvExpr/PtrsCastable.hpp"   // for ptrsCastable
    2428#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment, EqvClass
     29#include "ResolvExpr/typeops.h"          // for ptrsCastable
     30#include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
    2531#include "SymTab/Indexer.h"              // for Indexer
    2632#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
    2733#include "SynTree/Type.h"                // for PointerType, Type, TypeInstType
    28 #include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
    2934
    3035#if 0
     
    160165                                if (
    161166                                        pointerType->qualifiers <= ptr->qualifiers
    162                                         && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab, env )
     167                                        && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, env )
    163168                                ) {
    164169                                        cost = Cost::safe;
     
    227232        )
    228233
    229         if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
     234        if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) {
    230235                PRINT( std::cerr << "compatible!" << std::endl; )
    231236                if (dynamic_cast<const ast::ZeroType *>(dst) || dynamic_cast<const ast::OneType *>(dst)) {
  • src/ResolvExpr/CommonType.cc

    r34b4268 r24d6572  
    1414//
    1515
     16#include "CommonType.hpp"
     17
    1618#include <cassert>                       // for strict_dynamic_cast
    1719#include <map>                           // for _Rb_tree_const_iterator
     
    1921
    2022#include "AST/Decl.hpp"
     23#include "AST/Pass.hpp"
    2124#include "AST/Type.hpp"
    2225#include "Common/PassVisitor.h"
     
    673676                const ast::Type * type2;
    674677                WidenMode widen;
    675                 const ast::SymbolTable & symtab;
    676678                ast::TypeEnvironment & tenv;
    677679                const ast::OpenVarSet & open;
     
    683685
    684686                CommonType_new(
    685                         const ast::Type * t2, WidenMode w, const ast::SymbolTable & st,
     687                        const ast::Type * t2, WidenMode w,
    686688                        ast::TypeEnvironment & env, const ast::OpenVarSet & o,
    687689                        ast::AssertionSet & need, ast::AssertionSet & have )
    688                 : type2( t2 ), widen( w ), symtab( st ), tenv( env ), open( o ), need (need), have (have) ,result() {}
     690                : type2( t2 ), widen( w ), tenv( env ), open( o ), need (need), have (have) ,result() {}
    689691
    690692                void previsit( const ast::Node * ) { visit_children = false; }
     
    764766                                        ast::AssertionSet need, have;
    765767                                        if ( ! tenv.bindVar(
    766                                                 var, voidPtr->base, entry->second, need, have, open, widen, symtab )
     768                                                var, voidPtr->base, entry->second, need, have, open, widen )
    767769                                        ) return;
    768770                                }
     
    777779                                ast::OpenVarSet newOpen{ open };
    778780                                if (enumInst->base->base
    779                                 && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen, symtab)) {
     781                                && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen)) {
    780782                                        result = type1;
    781783                                        return true;
     
    814816
    815817                                        ast::OpenVarSet newOpen{ open };
    816                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     818                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() ) ) {
    817819                                                result = pointer;
    818820                                                if ( q1.val != q2.val ) {
     
    857859                                                                if (unifyExact(
    858860                                                                        arg1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open,
    859                                                                         noWiden(), symtab )) {
     861                                                                        noWiden() )) {
    860862                                                                                break;
    861863
     
    866868                                                                if (unifyExact(
    867869                                                                        tupleFromTypes( crnt1, end1 ), arg2, tenv, need, have, open,
    868                                                                         noWiden(), symtab )) {
     870                                                                        noWiden() )) {
    869871                                                                                break;
    870872
     
    890892
    891893                                                                                if ( ! unifyExact(
    892                                                                                         base1, base2, tenv, need, have, open, noWiden(), symtab )
     894                                                                                        base1, base2, tenv, need, have, open, noWiden() )
    893895                                                                                ) return;
    894896                                                                        }       
     
    910912
    911913                                                                                if ( ! unifyExact(
    912                                                                                         base1, base2, tenv, need, have, open, noWiden(), symtab )
     914                                                                                        base1, base2, tenv, need, have, open, noWiden() )
    913915                                                                                ) return;
    914916                                                                        }       
     
    918920                                                        }
    919921                                                        else if (! unifyExact(
    920                                                                 arg1, arg2, tenv, need, have, open, noWiden(), symtab )) return;
     922                                                                arg1, arg2, tenv, need, have, open, noWiden() )) return;
    921923
    922924                                                        ++crnt1; ++crnt2;
     
    928930                                                        if (! unifyExact(
    929931                                                                t1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open,
    930                                                                 noWiden(), symtab )) return;
     932                                                                noWiden() )) return;
    931933                                                } else if ( crnt2 != end2 ) {
    932934                                                        // try unifying empty tuple with ttype
     
    935937                                                        if (! unifyExact(
    936938                                                                tupleFromTypes( crnt1, end1 ), t2, tenv, need, have, open,
    937                                                                 noWiden(), symtab )) return;
     939                                                                noWiden() )) return;
    938940                                                }
    939941                                                if ((f1->returns.size() == 0 && f2->returns.size() == 0)
    940                                                   || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden(), symtab))) {
     942                                                  || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden()))) {
    941943                                                        result = pointer;
    942944
     
    995997
    996998                                        ast::OpenVarSet newOpen{ open };
    997                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
     999                                        if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() ) ) {
    9981000                                                result = ref;
    9991001                                                if ( q1.val != q2.val ) {
     
    10101012                        } else {
    10111013                                if (!dynamic_cast<const ast::EnumInstType *>(type2))
    1012                                         result = commonType( type2, ref, tenv, need, have, open, widen, symtab );
     1014                                        result = commonType( type2, ref, tenv, need, have, open, widen );
    10131015                        }
    10141016                }
     
    10281030                void postvisit( const ast::EnumInstType * enumInst ) {
    10291031                        if (!dynamic_cast<const ast::EnumInstType *>(type2))
    1030                                 result = commonType( type2, enumInst, tenv, need, have, open, widen, symtab);
     1032                                result = commonType( type2, enumInst, tenv, need, have, open, widen);
    10311033                }
    10321034
    10331035                void postvisit( const ast::TraitInstType * ) {}
    10341036
    1035                 void postvisit( const ast::TypeInstType * inst ) {
    1036                         if ( ! widen.first ) return;
    1037                         if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
    1038                                 if ( const ast::Type * base =
    1039                                                 strict_dynamic_cast< const ast::TypeDecl * >( nt )->base
    1040                                 ) {
    1041                                         ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers;
    1042 
    1043                                         // force t{1,2} to be cloned if their qualifiers must be mutated
    1044                                         ast::ptr< ast::Type > t1{ base }, t2{ type2 };
    1045                                         reset_qualifiers( t1, q1 );
    1046                                         reset_qualifiers( t2 );
    1047 
    1048                                         ast::OpenVarSet newOpen{ open };
    1049                                         if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) {
    1050                                                 result = type2;
    1051                                                 reset_qualifiers( result, q1 | q2 );
    1052                                         } else {
    1053                                                 tryResolveWithTypedEnum( t1 );
    1054                                         }
    1055                                 }
    1056                         }
    1057                 }
     1037                void postvisit( const ast::TypeInstType * inst ) {}
    10581038
    10591039                void postvisit( const ast::TupleType * tuple) {
     
    11181098                ast::ptr< ast::Type > handleReference(
    11191099                        const ast::ptr< ast::Type > & t1, const ast::ptr< ast::Type > & t2, WidenMode widen,
    1120                         const ast::SymbolTable & symtab, ast::TypeEnvironment & env,
     1100                        ast::TypeEnvironment & env,
    11211101                        const ast::OpenVarSet & open
    11221102                ) {
     
    11261106
    11271107                        // need unify to bind type variables
    1128                         if ( unify( t1, t2, env, have, need, newOpen, symtab, common ) ) {
     1108                        if ( unify( t1, t2, env, have, need, newOpen, common ) ) {
    11291109                                ast::CV::Qualifiers q1 = t1->qualifiers, q2 = t2->qualifiers;
    11301110                                PRINT(
     
    11501130                        const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
    11511131                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1152                         const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab
     1132                        const ast::OpenVarSet & open, WidenMode widen
    11531133        ) {
    11541134                unsigned depth1 = type1->referenceDepth();
     
    11651145                        if ( depth1 > depth2 ) {
    11661146                                assert( ref1 );
    1167                                 result = handleReference( ref1->base, type2, widen, symtab, env, open );
     1147                                result = handleReference( ref1->base, type2, widen, env, open );
    11681148                        } else {  // implies depth1 < depth2
    11691149                                assert( ref2 );
    1170                                 result = handleReference( type1, ref2->base, widen, symtab, env, open );
     1150                                result = handleReference( type1, ref2->base, widen, env, open );
    11711151                        }
    11721152
     
    11861166                }
    11871167                // otherwise both are reference types of the same depth and this is handled by the visitor
    1188                 ast::Pass<CommonType_new> visitor{ type2, widen, symtab, env, open, need, have };
     1168                ast::Pass<CommonType_new> visitor{ type2, widen, env, open, need, have };
    11891169                type1->accept( visitor );
    1190                 ast::ptr< ast::Type > result = visitor.core.result;
    1191 
    1192                 // handling for opaque type declarations (?)
    1193                 if ( ! result && widen.second ) {
    1194                         if ( const ast::TypeInstType * inst = type2.as< ast::TypeInstType >() ) {
    1195                                 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) {
    1196                                         auto type = strict_dynamic_cast< const ast::TypeDecl * >( nt );
    1197                                         if ( type->base ) {
    1198                                                 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
    1199                                                 ast::OpenVarSet newOpen{ open };
    1200 
    1201                                                 // force t{1,2} to be cloned if its qualifiers must be stripped, so that
    1202                                                 // type1 and type->base are left unchanged; calling convention forces
    1203                                                 // {type1,type->base}->strong_ref >= 1
    1204                                                 ast::ptr<ast::Type> t1{ type1 }, t2{ type->base };
    1205                                                 reset_qualifiers( t1 );
    1206                                                 reset_qualifiers( t2, q1 );
    1207 
    1208                                                 if ( unifyExact( t1, t2, env, have, need, newOpen, noWiden(), symtab ) ) {
    1209                                                         result = t1;
    1210                                                         reset_qualifiers( result, q1 | q2 );
    1211                                                 }
    1212                                         }
    1213                                 }
    1214                         }
    1215                 }
    1216 
    1217                 return result;
     1170                // ast::ptr< ast::Type > result = visitor.core.result;
     1171
     1172                return visitor.core.result;
    12181173        }
    12191174
  • src/ResolvExpr/ConversionCost.cc

    r34b4268 r24d6572  
    2222#include "ResolvExpr/Cost.h"             // for Cost
    2323#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    24 #include "ResolvExpr/Unify.h"
     24#include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
     25#include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
    2526#include "SymTab/Indexer.h"              // for Indexer
    2627#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
    2728#include "SynTree/Type.h"                // for Type, BasicType, TypeInstType
    28 #include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
    2929
    3030
     
    532532                }
    533533        }
    534         if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
     534        if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) {
    535535                return Cost::zero;
    536536        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
     
    566566                        ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
    567567                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
    568                                         srcAsRef->base, dstAsRef->base, symtab, env ) ) {
     568                                        srcAsRef->base, dstAsRef->base, env ) ) {
    569569                                if ( tq1 == tq2 ) {
    570570                                        return Cost::zero;
     
    587587                const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
    588588                assert( dstAsRef );
    589                 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
     589                if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, env ) ) {
    590590                        if ( srcIsLvalue ) {
    591591                                if ( src->qualifiers == dstAsRef->base->qualifiers ) {
     
    653653                ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
    654654                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
    655                                 pointerType->base, dstAsPtr->base, symtab, env ) ) {
     655                                pointerType->base, dstAsPtr->base, env ) ) {
    656656                        if ( tq1 == tq2 ) {
    657657                                cost = Cost::zero;
  • src/ResolvExpr/ConversionCost.h

    r34b4268 r24d6572  
    3232namespace ResolvExpr {
    3333        class TypeEnvironment;
     34
     35        Cost conversionCost(
     36                const Type * src, const Type * dest, bool srcIsLvalue,
     37                const SymTab::Indexer & indexer, const TypeEnvironment & env );
    3438
    3539        typedef std::function<Cost(const Type *, const Type *, bool,
     
    8084        const ast::SymbolTable &, const ast::TypeEnvironment &)>;
    8185
     86Cost conversionCost(
     87        const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
     88        const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
     89
     90Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
     91        bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
     92        PtrsCalculation func );
     93
    8294#warning when the old ConversionCost is removed, get ride of the _new suffix.
    8395class ConversionCost_new : public ast::WithShortCircuiting {
     
    119131};
    120132
    121 Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dest,
    122         bool srcIsLvalue, const ast::SymbolTable & indexer, const ast::TypeEnvironment & env,
    123         PtrsCalculation func );
    124 
    125133} // namespace ResolvExpr
    126134
  • src/ResolvExpr/CurrentObject.cc

    r34b4268 r24d6572  
    99// Author           : Rob Schluntz
    1010// Created On       : Tue Jun 13 15:28:32 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul  1 09:16:01 2022
    13 // Update Count     : 15
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Apr 10  9:40:00 2023
     13// Update Count     : 18
    1414//
    1515
     
    2626#include "AST/Init.hpp"                // for Designation
    2727#include "AST/Node.hpp"                // for readonly
    28 #include "AST/Print.hpp"                // for readonly
     28#include "AST/Print.hpp"               // for readonly
    2929#include "AST/Type.hpp"
     30#include "Common/Eval.h"               // for eval
    3031#include "Common/Indenter.h"           // for Indenter, operator<<
    3132#include "Common/SemanticError.h"      // for SemanticError
     
    592593
    593594namespace ast {
     595        /// Iterates members of a type by initializer.
     596        class MemberIterator {
     597        public:
     598                virtual ~MemberIterator() {}
     599
     600                /// Internal set position based on iterator ranges.
     601                virtual void setPosition(
     602                        std::deque< ptr< Expr > >::const_iterator it,
     603                        std::deque< ptr< Expr > >::const_iterator end ) = 0;
     604
     605                /// Walks the current object using the given designators as a guide.
     606                void setPosition( const std::deque< ptr< Expr > > & designators ) {
     607                        setPosition( designators.begin(), designators.end() );
     608                }
     609
     610                /// Retrieve the list of possible (Type,Designation) pairs for the
     611                /// current position in the current object.
     612                virtual std::deque< InitAlternative > operator* () const = 0;
     613
     614                /// True if the iterator is not currently at the end.
     615                virtual operator bool() const = 0;
     616
     617                /// Moves the iterator by one member in the current object.
     618                virtual MemberIterator & bigStep() = 0;
     619
     620                /// Moves the iterator by one member in the current subobject.
     621                virtual MemberIterator & smallStep() = 0;
     622
     623                /// The type of the current object.
     624                virtual const Type * getType() = 0;
     625
     626                /// The type of the current subobject.
     627                virtual const Type * getNext() = 0;
     628
     629                /// Helper for operator*; aggregates must add designator to each init
     630                /// alternative, but adding designators in operator* creates duplicates.
     631                virtual std::deque< InitAlternative > first() const = 0;
     632        };
     633
    594634        /// create a new MemberIterator that traverses a type correctly
    595635        MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );
     
    631671        };
    632672
    633         /// Iterates array types
    634         class ArrayIterator final : public MemberIterator {
     673        /// Iterates over an indexed type:
     674        class IndexIterator : public MemberIterator {
     675        protected:
    635676                CodeLocation location;
    636                 const ArrayType * array = nullptr;
    637                 const Type * base = nullptr;
    638677                size_t index = 0;
    639678                size_t size = 0;
    640                 std::unique_ptr< MemberIterator > memberIter;
    641 
    642                 void setSize( const Expr * expr ) {
    643                         auto res = eval( expr );
    644                         if ( ! res.second ) {
    645                                 SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) );
    646                         }
    647                         size = res.first;
    648                 }
    649 
    650         public:
    651                 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) : location( loc ), array( at ), base( at->base ) {
    652                         PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    653                         memberIter.reset( createMemberIterator( loc, base ) );
    654                         if ( at->isVarLen ) {
    655                                 SemanticError( location, at, "VLA initialization does not support @=: " );
    656                         }
    657                         setSize( at->dimension );
    658                 }
     679                std::unique_ptr<MemberIterator> memberIter;
     680        public:
     681                IndexIterator( const CodeLocation & loc, size_t size ) :
     682                        location( loc ), size( size )
     683                {}
    659684
    660685                void setPosition( const Expr * expr ) {
     
    665690                        auto arg = eval( expr );
    666691                        index = arg.first;
    667                         return;
    668692
    669693                        // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
     
    683707
    684708                void setPosition(
    685                         std::deque< ptr< Expr > >::const_iterator begin,
    686                         std::deque< ptr< Expr > >::const_iterator end
     709                        std::deque<ast::ptr<ast::Expr>>::const_iterator begin,
     710                        std::deque<ast::ptr<ast::Expr>>::const_iterator end
    687711                ) override {
    688712                        if ( begin == end ) return;
     
    695719
    696720                operator bool() const override { return index < size; }
     721        };
     722
     723        /// Iterates over the members of array types:
     724        class ArrayIterator final : public IndexIterator {
     725                const ArrayType * array = nullptr;
     726                const Type * base = nullptr;
     727
     728                size_t getSize( const Expr * expr ) {
     729                        auto res = eval( expr );
     730                        if ( !res.second ) {
     731                                SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) );
     732                        }
     733                        return res.first;
     734                }
     735
     736        public:
     737                ArrayIterator( const CodeLocation & loc, const ArrayType * at ) :
     738                                IndexIterator( loc, getSize( at->dimension) ),
     739                                array( at ), base( at->base ) {
     740                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
     741                        memberIter.reset( createMemberIterator( loc, base ) );
     742                        if ( at->isVarLen ) {
     743                                SemanticError( location, at, "VLA initialization does not support @=: " );
     744                        }
     745                }
    697746
    698747                ArrayIterator & bigStep() override {
     
    833882
    834883                const Type * getNext() final {
    835                         return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr;
     884                        bool hasMember = memberIter && *memberIter;
     885                        return hasMember ? memberIter->getType() : nullptr;
    836886                }
    837887
     
    897947        };
    898948
    899         class TupleIterator final : public AggregateIterator {
    900         public:
    901                 TupleIterator( const CodeLocation & loc, const TupleType * inst )
    902                 : AggregateIterator(
    903                         loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members
    904                 ) {}
    905 
    906                 operator bool() const override {
    907                         return curMember != members.end() || (memberIter && *memberIter);
     949        /// Iterates across the positions in a tuple:
     950        class TupleIterator final : public IndexIterator {
     951                ast::TupleType const * const tuple;
     952
     953                const ast::Type * typeAtIndex() const {
     954                        assert( index < size );
     955                        return tuple->types[ index ].get();
     956                }
     957
     958        public:
     959                TupleIterator( const CodeLocation & loc, const TupleType * type )
     960                : IndexIterator( loc, type->size() ), tuple( type ) {
     961                        PRINT( std::cerr << "Creating tuple iterator: " << type << std::endl; )
     962                        memberIter.reset( createMemberIterator( loc, typeAtIndex() ) );
    908963                }
    909964
    910965                TupleIterator & bigStep() override {
    911                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    912                         atbegin = false;
    913                         memberIter = nullptr;
    914                         curType = nullptr;
    915                         while ( curMember != members.end() ) {
    916                                 ++curMember;
    917                                 if ( init() ) return *this;
    918                         }
     966                        ++index;
     967                        memberIter.reset( index < size ?
     968                                createMemberIterator( location, typeAtIndex() ) : nullptr );
    919969                        return *this;
     970                }
     971
     972                TupleIterator & smallStep() override {
     973                        if ( memberIter ) {
     974                                PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
     975                                memberIter->smallStep();
     976                                if ( !memberIter ) {
     977                                        PRINT( std::cerr << "has valid member iter" << std::endl; )
     978                                        return *this;
     979                                }
     980                        }
     981                        return bigStep();
     982                }
     983
     984                const ast::Type * getType() override {
     985                        return tuple;
     986                }
     987
     988                const ast::Type * getNext() override {
     989                        bool hasMember = memberIter && *memberIter;
     990                        return hasMember ? memberIter->getType() : nullptr;
     991                }
     992
     993                std::deque< InitAlternative > first() const override {
     994                        PRINT( std::cerr << "first in TupleIterator (" << index << "/" << size << ")" << std::endl; )
     995                        if ( memberIter && *memberIter ) {
     996                                std::deque< InitAlternative > ret = memberIter->first();
     997                                for ( InitAlternative & alt : ret ) {
     998                                        alt.designation.get_and_mutate()->designators.emplace_front(
     999                                                ConstantExpr::from_ulong( location, index ) );
     1000                                }
     1001                                return ret;
     1002                        }
     1003                        return {};
    9201004                }
    9211005        };
  • src/ResolvExpr/CurrentObject.h

    r34b4268 r24d6572  
    99// Author           : Rob Schluntz
    1010// Created On       : Thu Jun  8 11:07:25 2017
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:36:48 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Apr  6 16:14:00 2023
     13// Update Count     : 4
    1414//
    1515
     
    6565
    6666        /// Iterates members of a type by initializer
    67         class MemberIterator {
    68         public:
    69                 virtual ~MemberIterator() {}
    70 
    71                 /// Internal set position based on iterator ranges
    72                 virtual void setPosition(
    73                         std::deque< ptr< Expr > >::const_iterator it,
    74                         std::deque< ptr< Expr > >::const_iterator end ) = 0;
    75 
    76                 /// walks the current object using the given designators as a guide
    77                 void setPosition( const std::deque< ptr< Expr > > & designators ) {
    78                         setPosition( designators.begin(), designators.end() );
    79                 }
    80 
    81                 /// retrieve the list of possible (Type,Designation) pairs for the current position in the
    82                 /// current object
    83                 virtual std::deque< InitAlternative > operator* () const = 0;
    84 
    85                 /// true if the iterator is not currently at the end
    86                 virtual operator bool() const = 0;
    87 
    88                 /// moves the iterator by one member in the current object
    89                 virtual MemberIterator & bigStep() = 0;
    90 
    91                 /// moves the iterator by one member in the current subobject
    92                 virtual MemberIterator & smallStep() = 0;
    93 
    94                 /// the type of the current object
    95                 virtual const Type * getType() = 0;
    96 
    97                 /// the type of the current subobject
    98                 virtual const Type * getNext() = 0;
    99        
    100                 /// helper for operator*; aggregates must add designator to each init alternative, but
    101                 /// adding designators in operator* creates duplicates
    102                 virtual std::deque< InitAlternative > first() const = 0;
    103         };
     67        class MemberIterator;
    10468
    10569        /// Builds initializer lists in resolution
  • src/ResolvExpr/ExplodedArg.hpp

    r34b4268 r24d6572  
    3535        ExplodedArg() : env(), cost( Cost::zero ), exprs() {}
    3636        ExplodedArg( const Candidate & arg, const ast::SymbolTable & symtab );
    37        
     37
    3838        ExplodedArg( ExplodedArg && ) = default;
    3939        ExplodedArg & operator= ( ExplodedArg && ) = default;
  • src/ResolvExpr/PolyCost.cc

    r34b4268 r24d6572  
    1515
    1616#include "AST/SymbolTable.hpp"
     17#include "AST/Pass.hpp"
    1718#include "AST/Type.hpp"
    1819#include "AST/TypeEnvironment.hpp"
  • src/ResolvExpr/PtrsAssignable.cc

    r34b4268 r24d6572  
    1414//
    1515
    16 #include "typeops.h"
     16#include "PtrsAssignable.hpp"
    1717
    1818#include "AST/Pass.hpp"
  • src/ResolvExpr/PtrsCastable.cc

    r34b4268 r24d6572  
    1414//
    1515
     16#include "PtrsCastable.hpp"
     17
    1618#include "AST/Decl.hpp"
    1719#include "AST/Pass.hpp"
     
    1921#include "AST/TypeEnvironment.hpp"
    2022#include "Common/PassVisitor.h"
     23#include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
    2124#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    2225#include "SymTab/Indexer.h"              // for Indexer
     
    2427#include "SynTree/Type.h"                // for TypeInstType, Type, BasicType
    2528#include "SynTree/Visitor.h"             // for Visitor
    26 #include "typeops.h"                     // for ptrsAssignable
    2729
    2830namespace ResolvExpr {
     
    291293                return objectCast( src, env, symtab );
    292294        } else {
    293                 ast::Pass< PtrsCastable_new > ptrs{ dst, env, symtab };
    294                 src->accept( ptrs );
    295                 return ptrs.core.result;
     295                return ast::Pass<PtrsCastable_new>::read( src, dst, env, symtab );
    296296        }
    297297}
  • src/ResolvExpr/RenameVars.cc

    r34b4268 r24d6572  
    8383
    8484                const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
    85                         // rename
    8685                        auto it = idMap.find( type->name );
    87                         if ( it != idMap.end() ) {
    88                                 // unconditionally mutate because map will *always* have different name
    89                                 ast::TypeInstType * mut = ast::shallowCopy( type );
    90                                 // reconcile base node since some copies might have been made
    91                                 mut->base = it->second.base;
    92                                 mut->formal_usage = it->second.formal_usage;
    93                                 mut->expr_id = it->second.expr_id;
    94                     type = mut;
    95                         }
    96 
    97                         return type;
     86                        if ( it == idMap.end() ) return type;
     87
     88                        // Unconditionally mutate because map will *always* have different name.
     89                        ast::TypeInstType * mut = ast::shallowCopy( type );
     90                        // Reconcile base node since some copies might have been made.
     91                        mut->base = it->second.base;
     92                        mut->formal_usage = it->second.formal_usage;
     93                        mut->expr_id = it->second.expr_id;
     94                        return mut;
    9895                }
    9996
     
    187184
    188185const ast::Type * renameTyVars( const ast::Type * t, RenameMode mode, bool reset ) {
    189         // ast::Type *tc = ast::deepCopy(t);
    190186        ast::Pass<RenameVars_new> renamer;
    191187        renamer.core.mode = mode;
  • src/ResolvExpr/ResolveAssertions.cc

    r34b4268 r24d6572  
    2626#include <vector>                   // for vector
    2727
     28#include "AdjustExprType.hpp"       // for adjustExprType
    2829#include "Alternative.h"            // for Alternative, AssertionItem, AssertionList
    2930#include "Common/FilterCombos.h"    // for filterCombos
    3031#include "Common/Indenter.h"        // for Indenter
    31 #include "Common/utility.h"         // for sort_mins
    3232#include "GenPoly/GenPoly.h"        // for getFunctionType
     33#include "ResolvExpr/AlternativeFinder.h"  // for computeConversionCost
    3334#include "ResolvExpr/RenameVars.h"  // for renameTyVars
     35#include "SpecCost.hpp"             // for specCost
    3436#include "SymTab/Indexer.h"         // for Indexer
    3537#include "SymTab/Mangler.h"         // for Mangler
    3638#include "SynTree/Expression.h"     // for InferredParams
    3739#include "TypeEnvironment.h"        // for TypeEnvironment, etc.
    38 #include "typeops.h"                // for adjustExprType, specCost
    3940#include "Unify.h"                  // for unify
    4041
  • src/ResolvExpr/Resolver.cc

    r34b4268 r24d6572  
    3838#include "AST/SymbolTable.hpp"
    3939#include "AST/Type.hpp"
     40#include "Common/Eval.h"                 // for eval
     41#include "Common/Iterate.hpp"            // for group_iterate
    4042#include "Common/PassVisitor.h"          // for PassVisitor
    4143#include "Common/SemanticError.h"        // for SemanticError
    4244#include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
    43 #include "Common/utility.h"              // for ValueGuard, group_iterate
     45#include "Common/ToString.hpp"           // for toCString
    4446#include "InitTweak/GenInit.h"
    4547#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
     
    11071109                void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) {
    11081110                        if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
    1109                                 if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) {
     1111                                if ( typesCompatible( castExpr->arg->result, castExpr->result ) ) {
    11101112                                        // cast is to the same type as its argument, remove it
    11111113                                        swap_and_save_env( expr, castExpr->arg );
     
    17291731
    17301732                        // Find all candidates for a function in canonical form
    1731                         funcFinder.find( clause.target_func, ResolvMode::withAdjustment() );
     1733                        funcFinder.find( clause.target, ResolvMode::withAdjustment() );
    17321734
    17331735                        if ( funcFinder.candidates.empty() ) {
    17341736                                stringstream ss;
    17351737                                ss << "Use of undeclared indentifier '";
    1736                                 ss << clause.target_func.strict_as< ast::NameExpr >()->name;
     1738                                ss << clause.target.strict_as< ast::NameExpr >()->name;
    17371739                                ss << "' in call to waitfor";
    17381740                                SemanticError( stmt->location, ss.str() );
     
    18331835                                                                if (
    18341836                                                                        ! unify(
    1835                                                                                 arg->expr->result, *param, resultEnv, need, have, open,
    1836                                                                                 symtab )
     1837                                                                                arg->expr->result, *param, resultEnv, need, have, open )
    18371838                                                                ) {
    18381839                                                                        // Type doesn't match
     
    19211922                        auto clause2 = new ast::WaitForClause( clause.location );
    19221923
    1923                         clause2->target_func = funcCandidates.front()->expr;
     1924                        clause2->target = funcCandidates.front()->expr;
    19241925
    19251926                        clause2->target_args.reserve( clause.target_args.size() );
     
    19441945
    19451946                        // Resolve the conditions as if it were an IfStmt, statements normally
    1946                         clause2->cond = findSingleExpression( clause.cond, context );
     1947                        clause2->when_cond = findSingleExpression( clause.when_cond, context );
    19471948                        clause2->stmt = clause.stmt->accept( *visitor );
    19481949
  • src/ResolvExpr/Resolver.h

    r34b4268 r24d6572  
    3434        class Decl;
    3535        class DeletedExpr;
     36        class Expr;
    3637        class Init;
    3738        class StmtExpr;
  • src/ResolvExpr/SatisfyAssertions.cpp

    r34b4268 r24d6572  
    2424#include <vector>
    2525
     26#include "AdjustExprType.hpp"
    2627#include "Candidate.hpp"
    2728#include "CandidateFinder.hpp"
     29#include "CommonType.hpp"
    2830#include "Cost.h"
    2931#include "RenameVars.h"
     32#include "SpecCost.hpp"
    3033#include "typeops.h"
    3134#include "Unify.h"
     
    181184                                .strict_as<ast::FunctionType>()->params[0]
    182185                                .strict_as<ast::ReferenceType>()->base;
    183                         sat.cand->env.apply(thisArgType);
     186                        // sat.cand->env.apply(thisArgType);
     187
     188                        if (auto inst = thisArgType.as<ast::TypeInstType>()) {
     189                                auto cls = sat.cand->env.lookup(*inst);
     190                                if (cls && cls->bound) thisArgType = cls->bound;
     191                        }
    184192
    185193                        std::string otypeKey = "";
     
    218226                        ast::TypeEnvironment tempNewEnv {newEnv};
    219227
    220                         if ( unifyExact( toType, adjType, tempNewEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
     228                        if ( unifyExact( toType, adjType, tempNewEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
    221229                                // set up binding slot for recursive assertions
    222230                                ast::UniqueId crntResnSlot = 0;
     
    234242                                // newEnv = sat.cand->env;
    235243                                // newNeed.clear();
    236                                 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true}, sat.symtab ) ) {
     244                                if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) {
    237245                                        // set up binding slot for recursive assertions
    238246                                        ast::UniqueId crntResnSlot = 0;
     
    398406                        mergeOpenVars( open, i.match.open );
    399407
    400                         if ( ! env.combine( i.match.env, open, symtab ) ) return false;
     408                        if ( ! env.combine( i.match.env, open ) ) return false;
    401409
    402410                        crnt.emplace_back( i );
  • src/ResolvExpr/Unify.cc

    r34b4268 r24d6572  
    3333#include "AST/TypeEnvironment.hpp"
    3434#include "Common/PassVisitor.h"     // for PassVisitor
     35#include "CommonType.hpp"           // for commonType
    3536#include "FindOpenVars.h"           // for findOpenVars
     37#include "SpecCost.hpp"             // for SpecCost
    3638#include "SynTree/LinkageSpec.h"    // for C
    3739#include "SynTree/Constant.h"       // for Constant
     
    4345#include "Tuples/Tuples.h"          // for isTtype
    4446#include "TypeEnvironment.h"        // for EqvClass, AssertionSet, OpenVarSet
    45 #include "typeops.h"                // for flatten, occurs, commonType
     47#include "typeops.h"                // for flatten, occurs
    4648
    4749namespace ast {
     
    5052
    5153namespace SymTab {
    52 class Indexer;
     54        class Indexer;
    5355}  // namespace SymTab
    5456
     
    5658
    5759namespace ResolvExpr {
     60
     61// Template Helpers:
     62template< typename Iterator1, typename Iterator2 >
     63bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) {
     64        for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
     65                Type *commonType = 0;
     66                if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
     67                        return false;
     68                } // if
     69                commonTypes.push_back( commonType );
     70        } // for
     71        return ( list1Begin == list1End && list2Begin == list2End );
     72}
     73
     74template< typename Iterator1, typename Iterator2 >
     75bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
     76        std::list< Type* > commonTypes;
     77        if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions,  openVars, indexer, commonTypes ) ) {
     78                deleteAll( commonTypes );
     79                return true;
     80        } else {
     81                return false;
     82        } // if
     83}
    5884
    5985        struct Unify_old : public WithShortCircuiting {
     
    102128                const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    103129                ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    104                 WidenMode widen, const ast::SymbolTable & symtab );
     130                WidenMode widen );
    105131
    106132        bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     
    124150
    125151        bool typesCompatible(
    126                         const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
     152                        const ast::Type * first, const ast::Type * second,
    127153                        const ast::TypeEnvironment & env ) {
    128154                ast::TypeEnvironment newEnv;
     
    137163                findOpenVars( newSecond, open, closed, need, have, newEnv, FirstOpen );
    138164
    139                 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
     165                return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() );
    140166        }
    141167
     
    157183
    158184        bool typesCompatibleIgnoreQualifiers(
    159                         const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
     185                        const ast::Type * first, const ast::Type * second,
    160186                        const ast::TypeEnvironment & env ) {
    161187                ast::TypeEnvironment newEnv;
     
    190216                        subFirst,
    191217                        subSecond,
    192                         newEnv, need, have, open, noWiden(), symtab );
     218                        newEnv, need, have, open, noWiden() );
    193219        }
    194220
     
    760786                const ast::OpenVarSet & open;
    761787                WidenMode widen;
    762                 const ast::SymbolTable & symtab;
    763788        public:
    764789                static size_t traceId;
     
    767792                Unify_new(
    768793                        const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need,
    769                         ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen,
    770                         const ast::SymbolTable & symtab )
     794                        ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen )
    771795                : type2(type2), tenv(env), need(need), have(have), open(open), widen(widen),
    772                   symtab(symtab), result(false) {}
     796                result(false) {}
    773797
    774798                void previsit( const ast::Node * ) { visit_children = false; }
     
    788812                                result = unifyExact(
    789813                                        pointer->base, pointer2->base, tenv, need, have, open,
    790                                         noWiden(), symtab );
     814                                        noWiden());
    791815                        }
    792816                }
     
    811835
    812836                        result = unifyExact(
    813                                 array->base, array2->base, tenv, need, have, open, noWiden(),
    814                                 symtab );
     837                                array->base, array2->base, tenv, need, have, open, noWiden());
    815838                }
    816839
     
    818841                        if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
    819842                                result = unifyExact(
    820                                         ref->base, ref2->base, tenv, need, have, open, noWiden(),
    821                                         symtab );
     843                                        ref->base, ref2->base, tenv, need, have, open, noWiden());
    822844                        }
    823845                }
     
    828850                static bool unifyTypeList(
    829851                        Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
    830                         ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    831                         const ast::SymbolTable & symtab
     852                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open
    832853                ) {
    833854                        while ( crnt1 != end1 && crnt2 != end2 ) {
     
    842863                                        return unifyExact(
    843864                                                t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    844                                                 noWiden(), symtab );
     865                                                noWiden() );
    845866                                } else if ( ! isTuple1 && isTuple2 ) {
    846867                                        // combine remainder of list1, then unify
    847868                                        return unifyExact(
    848869                                                tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    849                                                 noWiden(), symtab );
     870                                                noWiden() );
    850871                                }
    851872
    852873                                if ( ! unifyExact(
    853                                         t1, t2, env, need, have, open, noWiden(), symtab )
     874                                        t1, t2, env, need, have, open, noWiden() )
    854875                                ) return false;
    855876
     
    865886                                return unifyExact(
    866887                                        t1, tupleFromTypes( crnt2, end2 ), env, need, have, open,
    867                                         noWiden(), symtab );
     888                                        noWiden() );
    868889                        } else if ( crnt2 != end2 ) {
    869890                                // try unifying empty tuple with ttype
     
    872893                                return unifyExact(
    873894                                        tupleFromTypes( crnt1, end1 ), t2, env, need, have, open,
    874                                         noWiden(), symtab );
     895                                        noWiden() );
    875896                        }
    876897
     
    882903                        const std::vector< ast::ptr< ast::Type > > & list2,
    883904                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    884                         const ast::OpenVarSet & open, const ast::SymbolTable & symtab
     905                        const ast::OpenVarSet & open
    885906                ) {
    886907                        return unifyTypeList(
    887                                 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
    888                                 symtab );
     908                                list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open);
    889909                }
    890910
     
    927947                        ) return;
    928948
    929                         if ( ! unifyTypeList( params, params2, tenv, need, have, open, symtab ) ) return;
     949                        if ( ! unifyTypeList( params, params2, tenv, need, have, open ) ) return;
    930950                        if ( ! unifyTypeList(
    931                                 func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
     951                                func->returns, func2->returns, tenv, need, have, open ) ) return;
    932952
    933953                        markAssertions( have, need, func );
     
    944964                        // check that the other type is compatible and named the same
    945965                        auto otherInst = dynamic_cast< const XInstType * >( other );
    946                         if (otherInst && inst->name == otherInst->name) this->result = otherInst;
     966                        if (otherInst && inst->name == otherInst->name)
     967                                this->result = otherInst;
    947968                        return otherInst;
    948969                }
     
    10001021
    10011022                                if ( ! unifyExact(
    1002                                                 pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) {
     1023                                                pty, pty2, tenv, need, have, open, noWiden() ) ) {
    10031024                                        result = false;
    10041025                                        return;
     
    10301051                void postvisit( const ast::TypeInstType * typeInst ) {
    10311052                        // assert( open.find( *typeInst ) == open.end() );
    1032                         handleRefType( typeInst, type2 );
     1053                        auto otherInst = dynamic_cast< const ast::TypeInstType * >( type2 );
     1054                        if (otherInst && typeInst->name == otherInst->name)
     1055                                this->result = otherInst;
     1056                        // return otherInst;
    10331057                }
    10341058
     
    10391063                        const std::vector< ast::ptr< ast::Type > > & list1,
    10401064                        const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env,
    1041                         ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    1042                         const ast::SymbolTable & symtab
     1065                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open
    10431066                ) {
    10441067                        auto crnt1 = list1.begin();
     
    10551078                                        return unifyExact(
    10561079                                                t1, tupleFromTypes( list2 ), env, need, have, open,
    1057                                                 noWiden(), symtab );
     1080                                                noWiden() );
    10581081                                } else if ( ! isTuple1 && isTuple2 ) {
    10591082                                        // combine entirety of list1, then unify
    10601083                                        return unifyExact(
    10611084                                                tupleFromTypes( list1 ), t2, env, need, have, open,
    1062                                                 noWiden(), symtab );
     1085                                                noWiden() );
    10631086                                }
    10641087
    10651088                                if ( ! unifyExact(
    1066                                         t1, t2, env, need, have, open, noWiden(), symtab )
     1089                                        t1, t2, env, need, have, open, noWiden() )
    10671090                                ) return false;
    10681091
     
    10781101                                return unifyExact(
    10791102                                                t1, tupleFromTypes( list2 ), env, need, have, open,
    1080                                                 noWiden(), symtab );
     1103                                                noWiden() );
    10811104                        } else if ( crnt2 != list2.end() ) {
    10821105                                // try unifying empty tuple with ttype
     
    10871110                                return unifyExact(
    10881111                                                tupleFromTypes( list1 ), t2, env, need, have, open,
    1089                                                 noWiden(), symtab );
     1112                                                noWiden() );
    10901113                        }
    10911114
     
    11061129                        auto types2 = flatten( flat2 );
    11071130
    1108                         result = unifyList( types, types2, tenv, need, have, open, symtab );
     1131                        result = unifyList( types, types2, tenv, need, have, open );
    11091132                }
    11101133
     
    11301153                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    11311154                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1132                         ast::OpenVarSet & open, const ast::SymbolTable & symtab
     1155                        ast::OpenVarSet & open
    11331156        ) {
    11341157                ast::ptr<ast::Type> common;
    1135                 return unify( type1, type2, env, need, have, open, symtab, common );
     1158                return unify( type1, type2, env, need, have, open, common );
    11361159        }
    11371160
     
    11391162                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    11401163                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1141                         ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common
     1164                        ast::OpenVarSet & open, ast::ptr<ast::Type> & common
    11421165        ) {
    11431166                ast::OpenVarSet closed;
     
    11451168                findOpenVars( type2, open, closed, need, have, env, FirstOpen );
    11461169                return unifyInexact(
    1147                         type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common );
     1170                        type1, type2, env, need, have, open, WidenMode{ true, true }, common );
    11481171        }
    11491172
     
    11511174                        const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    11521175                        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    1153                         WidenMode widen, const ast::SymbolTable & symtab
     1176                        WidenMode widen
    11541177        ) {
    11551178                if ( type1->qualifiers != type2->qualifiers ) return false;
     
    11701193                        return env.bindVarToVar(
    11711194                                var1, var2, ast::TypeData{ entry1->second, entry2->second }, need, have,
    1172                                 open, widen, symtab );
     1195                                open, widen );
    11731196                } else if ( isopen1 ) {
    1174                         return env.bindVar( var1, type2, entry1->second, need, have, open, widen, symtab );
     1197                        return env.bindVar( var1, type2, entry1->second, need, have, open, widen );
    11751198                } else if ( isopen2 ) {
    11761199                        return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab );
     
    11801203                        return env.bindVarToVar(
    11811204                                var1, var2, ast::TypeData{ var1->base->kind, var1->base->sized||var2->base->sized }, need, have,
    1182                                 open, widen, symtab );
     1205                                open, widen );
    11831206                } else if ( isopen1 ) {
    1184                         return env.bindVar( var1, type2, ast::TypeData{var1->base}, need, have, open, widen, symtab );
     1207                        return env.bindVar( var1, type2, ast::TypeData{var1->base}, need, have, open, widen );
    11851208                } else if ( isopen2 ) {
    1186                         return env.bindVar( var2, type1, ast::TypeData{var2->base}, need, have, open, widen, symtab );
     1209                        return env.bindVar( var2, type1, ast::TypeData{var2->base}, need, have, open, widen );
    11871210                }else {
    11881211                        return ast::Pass<Unify_new>::read(
    1189                                 type1, type2, env, need, have, open, widen, symtab );
     1212                                type1, type2, env, need, have, open, widen );
    11901213                }
    11911214               
     
    11951218                        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    11961219                        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    1197                         const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
     1220                        const ast::OpenVarSet & open, WidenMode widen,
    11981221                        ast::ptr<ast::Type> & common
    11991222        ) {
     
    12091232                ast::ptr< ast::Type > t2_(t2);
    12101233
    1211                 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
     1234                if ( unifyExact( t1, t2, env, need, have, open, widen ) ) {
    12121235                        // if exact unification on unqualified types, try to merge qualifiers
    12131236                        if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {
     
    12191242                        }
    12201243
    1221                 } else if (( common = commonType( t1, t2, env, need, have, open, widen, symtab ))) {
     1244                } else if (( common = commonType( t1, t2, env, need, have, open, widen ))) {
    12221245                        // no exact unification, but common type
    12231246                        auto c = shallowCopy(common.get());
  • src/ResolvExpr/Unify.h

    r34b4268 r24d6572  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 13:09:04 2015
    11 // Last Modified By : Aaron B. Moss
    12 // Last Modified On : Mon Jun 18 11:58:00 2018
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Jan 17 11:12:00 2023
     13// Update Count     : 5
    1414//
    1515
     
    3737
    3838namespace ResolvExpr {
    39         bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    40         bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    41         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    42         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
    4339
    44         template< typename Iterator1, typename Iterator2 >
    45         bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) {
    46                 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    47                         Type *commonType = 0;
    48                         if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    49                                 return false;
    50                         } // if
    51                         commonTypes.push_back( commonType );
    52                 } // for
    53                 if ( list1Begin != list1End || list2Begin != list2End ) {
    54                         return false;
    55                 } else {
    56                         return true;
    57                 } // if
    58         }
     40bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
     41bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
     42bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
     43bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
    5944
    60         template< typename Iterator1, typename Iterator2 >
    61         bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    62                 std::list< Type* > commonTypes;
    63                 if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) {
    64                         deleteAll( commonTypes );
    65                         return true;
    66                 } else {
    67                         return false;
    68                 } // if
    69         }
     45bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
     46bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
    7047
    71         bool unify(
    72                 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    73                 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    74                 ast::OpenVarSet & open, const ast::SymbolTable & symtab );
     48inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
     49        TypeEnvironment env;
     50        return typesCompatible( t1, t2, indexer, env );
     51}
    7552
    76         bool unify(
    77                 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    78                 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    79                 ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common );
     53inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
     54        TypeEnvironment env;
     55        return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
     56}
    8057
    81         bool unifyExact(
    82                 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    83                 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    84                 WidenMode widen, const ast::SymbolTable & symtab );
     58bool unify(
     59        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     60        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     61        ast::OpenVarSet & open );
    8562
    86         bool unifyInexact(
    87                 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
    88                 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    89                 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
    90                 ast::ptr<ast::Type> & common );
     63bool unify(
     64        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     65        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     66        ast::OpenVarSet & open, ast::ptr<ast::Type> & common );
     67
     68bool unifyExact(
     69        const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
     70        ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
     71        WidenMode widen );
     72
     73bool unifyInexact(
     74        const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
     75        ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
     76        const ast::OpenVarSet & open, WidenMode widen,
     77        ast::ptr<ast::Type> & common );
     78
     79bool typesCompatible(
     80        const ast::Type *, const ast::Type *,
     81        const ast::TypeEnvironment & env = {} );
     82
     83bool typesCompatibleIgnoreQualifiers(
     84        const ast::Type *, const ast::Type *,
     85        const ast::TypeEnvironment & env = {} );
     86
     87/// Creates the type represented by the list of returnVals in a FunctionType.
     88/// The caller owns the return value.
     89Type * extractResultType( FunctionType * functionType );
     90/// Creates or extracts the type represented by returns in a `FunctionType`.
     91ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func );
     92
     93std::vector<ast::ptr<ast::Type>> flattenList(
     94        const std::vector<ast::ptr<ast::Type>> & src, ast::TypeEnvironment & env
     95);
    9196
    9297} // namespace ResolvExpr
  • src/ResolvExpr/WidenMode.h

    r34b4268 r24d6572  
    1919        struct WidenMode {
    2020                WidenMode( bool first, bool second ): first( first ), second( second ) {}
    21                
     21
    2222                WidenMode &operator|=( const WidenMode &other ) {
    2323                        first |= other.first; second |= other.second; return *this;
     
    3535                        WidenMode newWM( *this ); newWM &= other; return newWM;
    3636                }
    37                
     37
    3838                operator bool() { return first && second; }
    3939
  • src/ResolvExpr/module.mk

    r34b4268 r24d6572  
    1717SRC_RESOLVEXPR = \
    1818      ResolvExpr/AdjustExprType.cc \
     19      ResolvExpr/AdjustExprType.hpp \
    1920      ResolvExpr/Alternative.cc \
    2021      ResolvExpr/AlternativeFinder.cc \
     
    2627      ResolvExpr/Candidate.hpp \
    2728      ResolvExpr/CastCost.cc \
     29      ResolvExpr/CastCost.hpp \
    2830      ResolvExpr/CommonType.cc \
     31      ResolvExpr/CommonType.hpp \
    2932      ResolvExpr/ConversionCost.cc \
    3033      ResolvExpr/ConversionCost.h \
     
    4043      ResolvExpr/Occurs.cc \
    4144      ResolvExpr/PolyCost.cc \
     45      ResolvExpr/PolyCost.hpp \
    4246      ResolvExpr/PtrsAssignable.cc \
     47      ResolvExpr/PtrsAssignable.hpp \
    4348      ResolvExpr/PtrsCastable.cc \
     49      ResolvExpr/PtrsCastable.hpp \
    4450      ResolvExpr/RenameVars.cc \
    4551      ResolvExpr/RenameVars.h \
     
    5460      ResolvExpr/SatisfyAssertions.hpp \
    5561      ResolvExpr/SpecCost.cc \
     62      ResolvExpr/SpecCost.hpp \
    5663      ResolvExpr/TypeEnvironment.cc \
    5764      ResolvExpr/TypeEnvironment.h \
  • src/ResolvExpr/typeops.h

    r34b4268 r24d6572  
    1010// Created On       : Sun May 17 07:28:22 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  1 09:45:00 2019
    13 // Update Count     : 6
     12// Last Modified On : Wed Jan 18 11:54:00 2023
     13// Update Count     : 7
    1414//
    1515
     
    1818#include <vector>
    1919
    20 #include "Cost.h"
    21 #include "TypeEnvironment.h"
    22 #include "WidenMode.h"
    23 #include "AST/Fwd.hpp"
    24 #include "AST/Node.hpp"
    25 #include "AST/SymbolTable.hpp"
    2620#include "AST/Type.hpp"
    27 #include "AST/TypeEnvironment.hpp"
    28 #include "SynTree/SynTree.h"
    2921#include "SynTree/Type.h"
    3022
     
    3426
    3527namespace ResolvExpr {
     28        class TypeEnvironment;
     29
    3630        // combos: takes a list of sets and returns a set of lists representing every possible way of forming a list by
    3731        // picking one element out of each set
     
    6155        }
    6256
    63         // in AdjustExprType.cc
    64         /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function
    65         void adjustExprType( Type *& type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
    66 
    67         /// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer
    68         void adjustExprType( Type *& type );
    69 
    70         template< typename ForwardIterator >
    71         void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer & indexer ) {
    72                 while ( begin != end ) {
    73                         adjustExprType( *begin++, env, indexer );
    74                 } // while
    75         }
    76 
    77         /// Replaces array types with equivalent pointer, and function types with a pointer-to-function
    78         const ast::Type * adjustExprType(
    79                 const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab );
    80 
    81         // in CastCost.cc
    82         Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue,
    83                 const SymTab::Indexer & indexer, const TypeEnvironment & env );
    84         Cost castCost(
    85                 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    86                 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    87 
    88         // in ConversionCost.cc
    89         Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue,
    90                 const SymTab::Indexer & indexer, const TypeEnvironment & env );
    91         Cost conversionCost(
    92                 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
    93                 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    94 
    95         // in AlternativeFinder.cc
    96         Cost computeConversionCost( Type * actualType, Type * formalType, bool actualIsLvalue,
    97                 const SymTab::Indexer & indexer, const TypeEnvironment & env );
    98 
    99         // in PtrsAssignable.cc
    100         int ptrsAssignable( const Type * src, const Type * dest, const TypeEnvironment & env );
    101         int ptrsAssignable( const ast::Type * src, const ast::Type * dst,
    102                 const ast::TypeEnvironment & env );
    103 
    104         // in PtrsCastable.cc
    105         int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment & env, const SymTab::Indexer & indexer );
    106         int ptrsCastable(
    107                 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    108                 const ast::TypeEnvironment & env );
    109 
    110         // in Unify.cc
    111         bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
    112         bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
    113 
    114         inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
    115                 TypeEnvironment env;
    116                 return typesCompatible( t1, t2, indexer, env );
    117         }
    118 
    119         inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
    120                 TypeEnvironment env;
    121                 return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
    122         }
    123 
    124         bool typesCompatible(
    125                 const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},
    126                 const ast::TypeEnvironment & env = {} );
    127 
    128         bool typesCompatibleIgnoreQualifiers(
    129                 const ast::Type *, const ast::Type *, const ast::SymbolTable &,
    130                 const ast::TypeEnvironment & env = {} );
    131 
    132         /// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value.
    133         Type * extractResultType( FunctionType * functionType );
    134         /// Creates or extracts the type represented by the list of returns in a `FunctionType`.
    135         ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func );
    136 
    137         // in CommonType.cc
    138         Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer & indexer, TypeEnvironment & env, const OpenVarSet & openVars );
    139         ast::ptr< ast::Type > commonType(
    140                 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
    141                         ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
    142                         const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab
    143         );
    144         // in Unify.cc
    145         std::vector< ast::ptr< ast::Type > > flattenList(
    146                 const std::vector< ast::ptr< ast::Type > > & src, ast::TypeEnvironment & env
    147         );
    148 
    149         // in PolyCost.cc
    150         int polyCost( Type * type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
    151         int polyCost(
    152                 const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
    153 
    154         // in SpecCost.cc
    155         int specCost( Type * type );
    156         int specCost( const ast::Type * type );
    157 
    15857        // in Occurs.cc
    15958        bool occurs( const Type * type, const std::string & varName, const TypeEnvironment & env );
     
    16867                return false;
    16968        }
    170 
    171         // in AlternativeFinder.cc
    172         void referenceToRvalueConversion( Expression *& expr, Cost & cost );
    173         // in CandidateFinder.cpp
    174         const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost );
    17569
    17670        /// flatten tuple type into list of types
     
    218112                }
    219113
    220 
    221114                return new ast::TupleType{ std::move(types) };
    222115        }
     
    227120                return tupleFromTypes( tys.begin(), tys.end() );
    228121        }
    229 
    230        
    231122
    232123        // in TypeEnvironment.cc
  • src/SymTab/Autogen.cc

    r34b4268 r24d6572  
    1010// Created On       : Thu Mar 03 15:45:56 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Apr 27 14:39:06 2018
    13 // Update Count     : 63
     12// Last Modified On : Fri Apr 14 15:03:00 2023
     13// Update Count     : 64
    1414//
    1515
     
    211211        }
    212212
    213         bool isUnnamedBitfield( const ast::ObjectDecl * obj ) {
    214                 return obj && obj->name.empty() && obj->bitfieldWidth;
    215         }
    216 
    217213        /// inserts a forward declaration for functionDecl into declsToAdd
    218214        void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
     
    234230        }
    235231
    236         // shallow copy the pointer list for return
    237         std::vector<ast::ptr<ast::TypeDecl>> getGenericParams (const ast::Type * t) {
    238                 if (auto structInst = dynamic_cast<const ast::StructInstType*>(t)) {
    239                         return structInst->base->params;
    240                 }
    241                 if (auto unionInst = dynamic_cast<const ast::UnionInstType*>(t)) {
    242                         return unionInst->base->params;
    243                 }
    244                 return {};
    245         }
    246 
    247232        /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
    248233        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
     
    256241                ftype->parameters.push_back( dstParam );
    257242                return ftype;
    258         }
    259 
    260         /// Given type T, generate type of default ctor/dtor, i.e. function type void (*) (T &).
    261         ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic) {
    262                 std::vector<ast::ptr<ast::TypeDecl>> typeParams;
    263                 if (maybePolymorphic) typeParams = getGenericParams(paramType);
    264                 auto dstParam = new ast::ObjectDecl(loc, "_dst", new ast::ReferenceType(paramType), nullptr, {}, ast::Linkage::Cforall);
    265                 return new ast::FunctionDecl(loc, fname, std::move(typeParams), {dstParam}, {}, new ast::CompoundStmt(loc), {}, ast::Linkage::Cforall);
    266243        }
    267244
  • src/SymTab/Autogen.h

    r34b4268 r24d6572  
    99// Author           : Rob Schluntz
    1010// Created On       : Sun May 17 21:53:34 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 16:38:06 2019
    13 // Update Count     : 16
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Apr 14 15:06:00 2023
     13// Update Count     : 17
    1414//
    1515
     
    2020#include <string>                 // for string
    2121
    22 #include "AST/Decl.hpp"
    23 #include "AST/Expr.hpp"
    24 #include "AST/Init.hpp"
    25 #include "AST/Node.hpp"
    26 #include "AST/Stmt.hpp"
    27 #include "AST/Type.hpp"
    2822#include "CodeGen/OperatorTable.h"
    2923#include "Common/UniqueName.h"    // for UniqueName
     
    4539        /// returns true if obj's name is the empty string and it has a bitfield width
    4640        bool isUnnamedBitfield( ObjectDecl * obj );
    47         bool isUnnamedBitfield( const ast::ObjectDecl * obj );
    4841
    4942        /// generate the type of an assignment function for paramType.
     
    5548        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
    5649
    57         ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true);
    58 
    5950        /// generate the type of a copy constructor for paramType.
    6051        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    6152        FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
    6253
    63         /// Enum for loop direction
    64         enum LoopDirection { LoopBackward, LoopForward };
    65 
    6654        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    6755        template< typename OutputIterator >
    6856        Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
    69 
    70         template< typename OutIter >
    71         ast::ptr< ast::Stmt > genCall(
    72                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    73                 const CodeLocation & loc, const std::string & fname, OutIter && out,
    74                 const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
    7557
    7658        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
     
    121103
    122104                *out++ = new ExprStmt( fExpr );
    123 
    124                 srcParam.clearArrayIndices();
    125 
    126                 return listInit;
    127         }
    128 
    129         /// inserts into out a generated call expression to function fname with arguments dstParam and
    130         /// srcParam. Should only be called with non-array types.
    131         /// optionally returns a statement which must be inserted prior to the containing loop, if
    132         /// there is one
    133         template< typename OutIter >
    134         ast::ptr< ast::Stmt > genScalarCall(
    135                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    136                 const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
    137                 const ast::Type * addCast = nullptr
    138         ) {
    139                 bool isReferenceCtorDtor = false;
    140                 if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
    141                         // reference constructors are essentially application of the rebind operator.
    142                         // apply & to both arguments, do not need a cast
    143                         fname = "?=?";
    144                         dstParam = new ast::AddressExpr{ dstParam };
    145                         addCast = nullptr;
    146                         isReferenceCtorDtor = true;
    147                 }
    148 
    149                 // want to be able to generate assignment, ctor, and dtor generically, so fname is one of
    150                 // "?=?", "?{}", or "^?{}"
    151                 ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } };
    152 
    153                 if ( addCast ) {
    154                         // cast to T& with qualifiers removed, so that qualified objects can be constructed and
    155                         // destructed with the same functions as non-qualified objects. Unfortunately, lvalue
    156                         // is considered a qualifier - for AddressExpr to resolve, its argument must have an
    157                         // lvalue-qualified type, so remove all qualifiers except lvalue.
    158                         // xxx -- old code actually removed lvalue too...
    159                         ast::ptr< ast::Type > guard = addCast;  // prevent castType from mutating addCast
    160                         ast::ptr< ast::Type > castType = addCast;
    161                         ast::remove_qualifiers(
    162                                 castType,
    163                                 ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );
    164                         dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };
    165                 }
    166                 fExpr->args.emplace_back( dstParam );
    167 
    168                 ast::ptr<ast::Stmt> listInit = srcParam.buildListInit( fExpr );
    169 
    170                 // fetch next set of arguments
    171                 ++srcParam;
    172 
    173                 // return if adding reference fails -- will happen on default ctor and dtor
    174                 if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;
    175 
    176                 std::vector< ast::ptr< ast::Expr > > args = *srcParam;
    177                 splice( fExpr->args, args );
    178 
    179                 *out++ = new ast::ExprStmt{ loc, fExpr };
    180105
    181106                srcParam.clearArrayIndices();
     
    248173        }
    249174
    250         /// Store in out a loop which calls fname on each element of the array with srcParam and
    251         /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
    252         template< typename OutIter >
    253         void genArrayCall(
    254                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    255                 const CodeLocation & loc, const std::string & fname, OutIter && out,
    256                 const ast::ArrayType * array, const ast::Type * addCast = nullptr,
    257                 LoopDirection forward = LoopForward
    258         ) {
    259                 static UniqueName indexName( "_index" );
    260 
    261                 // for a flexible array member nothing is done -- user must define own assignment
    262                 if ( ! array->dimension ) return;
    263 
    264                 if ( addCast ) {
    265                         // peel off array layer from cast
    266                         addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;
    267                 }
    268 
    269                 ast::ptr< ast::Expr > begin, end;
    270                 std::string cmp, update;
    271 
    272                 if ( forward ) {
    273                         // generate: for ( int i = 0; i < N; ++i )
    274                         begin = ast::ConstantExpr::from_int( loc, 0 );
    275                         end = array->dimension;
    276                         cmp = "?<?";
    277                         update = "++?";
    278                 } else {
    279                         // generate: for ( int i = N-1; i >= 0; --i )
    280                         begin = ast::UntypedExpr::createCall( loc, "?-?",
    281                                 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } );
    282                         end = ast::ConstantExpr::from_int( loc, 0 );
    283                         cmp = "?>=?";
    284                         update = "--?";
    285                 }
    286 
    287                 ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{
    288                         loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
    289                         new ast::SingleInit{ loc, begin } };
    290                 ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };
    291 
    292                 ast::ptr< ast::Expr > cond = ast::UntypedExpr::createCall(
    293                         loc, cmp, { indexVar, end } );
    294 
    295                 ast::ptr< ast::Expr > inc = ast::UntypedExpr::createCall(
    296                         loc, update, { indexVar } );
    297 
    298                 ast::ptr< ast::Expr > dstIndex = ast::UntypedExpr::createCall(
    299                         loc, "?[?]", { dstParam, indexVar } );
    300 
    301                 // srcParam must keep track of the array indices to build the source parameter and/or
    302                 // array list initializer
    303                 srcParam.addArrayIndex( indexVar, array->dimension );
    304 
    305                 // for stmt's body, eventually containing call
    306                 ast::CompoundStmt * body = new ast::CompoundStmt{ loc };
    307                 ast::ptr< ast::Stmt > listInit = genCall(
    308                         srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,
    309                         forward );
    310 
    311                 // block containing the stmt and index variable
    312                 ast::CompoundStmt * block = new ast::CompoundStmt{ loc };
    313                 block->push_back( new ast::DeclStmt{ loc, index } );
    314                 if ( listInit ) { block->push_back( listInit ); }
    315                 block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } );
    316 
    317                 *out++ = block;
    318         }
    319 
    320175        template< typename OutputIterator >
    321176        Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
     
    325180                } else {
    326181                        return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
    327                 }
    328         }
    329 
    330         template< typename OutIter >
    331         ast::ptr< ast::Stmt > genCall(
    332                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    333                 const CodeLocation & loc, const std::string & fname, OutIter && out,
    334                 const ast::Type * type, const ast::Type * addCast, LoopDirection forward
    335         ) {
    336                 if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
    337                         genArrayCall(
    338                                 srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,
    339                                 forward );
    340                         return {};
    341                 } else {
    342                         return genScalarCall(
    343                                 srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );
    344182                }
    345183        }
     
    379217        }
    380218
    381         static inline ast::ptr< ast::Stmt > genImplicitCall(
    382                 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
    383                 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
    384                 LoopDirection forward = LoopForward
    385         ) {
    386                 // unnamed bit fields are not copied as they cannot be accessed
    387                 if ( isUnnamedBitfield( obj ) ) return {};
    388 
    389                 ast::ptr< ast::Type > addCast;
    390                 if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
    391                         assert( dstParam->result );
    392                         addCast = dstParam->result;
    393                 }
    394 
    395                 std::vector< ast::ptr< ast::Stmt > > stmts;
    396                 genCall(
    397                         srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
    398 
    399                 if ( stmts.empty() ) {
    400                         return {};
    401                 } else if ( stmts.size() == 1 ) {
    402                         const ast::Stmt * callStmt = stmts.front();
    403                         if ( addCast ) {
    404                                 // implicitly generated ctor/dtor calls should be wrapped so that later passes are
    405                                 // aware they were generated.
    406                                 callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt };
    407                         }
    408                         return callStmt;
    409                 } else {
    410                         assert( false );
    411                         return {};
    412                 }
    413         }
    414219} // namespace SymTab
    415220
  • src/SymTab/FixFunction.cc

    r34b4268 r24d6572  
    2121#include "AST/Pass.hpp"
    2222#include "AST/Type.hpp"
    23 #include "Common/utility.h"       // for maybeClone, copy
     23#include "Common/utility.h"       // for copy
    2424#include "SynTree/Declaration.h"  // for FunctionDecl, ObjectDecl, Declarati...
    2525#include "SynTree/Expression.h"   // for Expression
  • src/SymTab/Indexer.cc

    r34b4268 r24d6572  
    3131#include "InitTweak/InitTweak.h"   // for isConstructor, isCopyFunction, isC...
    3232#include "Mangler.h"               // for Mangler
    33 #include "ResolvExpr/typeops.h"    // for typesCompatible
     33#include "ResolvExpr/AlternativeFinder.h"  // for referenceToRvalueConversion
     34#include "ResolvExpr/Unify.h"      // for typesCompatible
    3435#include "SynTree/LinkageSpec.h"   // for isMangled, isOverridable, Spec
    3536#include "SynTree/Constant.h"      // for Constant
  • src/SymTab/Mangler.cc

    r34b4268 r24d6572  
    2424#include "CodeGen/OperatorTable.h"       // for OperatorInfo, operatorLookup
    2525#include "Common/PassVisitor.h"
     26#include "Common/ToString.hpp"           // for toCString
    2627#include "Common/SemanticError.h"        // for SemanticError
    27 #include "Common/utility.h"              // for toString
    2828#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    2929#include "SynTree/LinkageSpec.h"         // for Spec, isOverridable, AutoGen, Int...
     
    439439                  private:
    440440                        void mangleDecl( const ast::DeclWithType *declaration );
    441                         void mangleRef( const ast::BaseInstType *refType, std::string prefix );
     441                        void mangleRef( const ast::BaseInstType *refType, const std::string & prefix );
    442442
    443443                        void printQualifiers( const ast::Type *type );
     
    535535                }
    536536
    537                 __attribute__((unused))
    538                 inline std::vector< ast::ptr< ast::Type > > getTypes( const std::vector< ast::ptr< ast::DeclWithType > > & decls ) {
    539                         std::vector< ast::ptr< ast::Type > > ret;
    540                         std::transform( decls.begin(), decls.end(), std::back_inserter( ret ),
    541                                                         std::mem_fun( &ast::DeclWithType::get_type ) );
    542                         return ret;
    543                 }
    544 
    545537                void Mangler_new::postvisit( const ast::FunctionType * functionType ) {
    546538                        printQualifiers( functionType );
     
    558550                }
    559551
    560                 void Mangler_new::mangleRef( const ast::BaseInstType * refType, std::string prefix ) {
     552                void Mangler_new::mangleRef(
     553                                const ast::BaseInstType * refType, const std::string & prefix ) {
    561554                        printQualifiers( refType );
    562555
    563556                        mangleName += prefix + std::to_string( refType->name.length() ) + refType->name;
    564557
    565                         if ( mangleGenericParams ) {
    566                                 if ( ! refType->params.empty() ) {
    567                                         mangleName += "_";
    568                                         for ( const ast::Expr * param : refType->params ) {
    569                                                 auto paramType = dynamic_cast< const ast::TypeExpr * >( param );
    570                                                 assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
    571                                                 maybeAccept( paramType->type.get(), *visitor );
    572                                         }
    573                                         mangleName += "_";
     558                        if ( mangleGenericParams && ! refType->params.empty() ) {
     559                                mangleName += "_";
     560                                for ( const ast::Expr * param : refType->params ) {
     561                                        auto paramType = dynamic_cast< const ast::TypeExpr * >( param );
     562                                        assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
     563                                        maybeAccept( paramType->type.get(), *visitor );
    574564                                }
     565                                mangleName += "_";
    575566                        }
    576567                }
     
    656647                }
    657648
     649                // For debugging:
    658650                __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
    659651                        for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
     
    665657                        // skip if not including qualifiers
    666658                        if ( typeMode ) return;
    667                         if ( auto ptype = dynamic_cast< const ast::FunctionType * >(type) ) {
    668                                 if ( ! ptype->forall.empty() ) {
    669                                         std::list< std::string > assertionNames;
    670                                         int dcount = 0, fcount = 0, vcount = 0, acount = 0;
    671                                         mangleName += Encoding::forall;
    672                                         for ( auto & decl : ptype->forall ) {
    673                                                 switch ( decl->kind ) {
    674                                                   case ast::TypeDecl::Kind::Dtype:
    675                                                         dcount++;
    676                                                         break;
    677                                                   case ast::TypeDecl::Kind::Ftype:
    678                                                         fcount++;
    679                                                         break;
    680                                                   case ast::TypeDecl::Kind::Ttype:
    681                                                         vcount++;
    682                                                         break;
    683                                                   default:
    684                                                         assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[decl->kind].c_str() );
    685                                                 } // switch
    686                                                 varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
    687                                         } // for
    688                                         for ( auto & assert : ptype->assertions ) {
    689                                                 assertionNames.push_back( ast::Pass<Mangler_new>::read(
    690                                                         assert->var.get(),
    691                                                         mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) );
    692                                                 acount++;
    693                                         } // for
    694                                         mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_";
    695                                         for(const auto & a : assertionNames) mangleName += a;
    696 //                                      std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
    697                                         mangleName += "_";
    698                                 } // if
     659                        auto funcType = dynamic_cast<const ast::FunctionType *>( type );
     660                        if ( funcType && !funcType->forall.empty() ) {
     661                                std::list< std::string > assertionNames;
     662                                int dcount = 0, fcount = 0, vcount = 0, acount = 0;
     663                                mangleName += Encoding::forall;
     664                                for ( auto & decl : funcType->forall ) {
     665                                        switch ( decl->kind ) {
     666                                        case ast::TypeDecl::Dtype:
     667                                                dcount++;
     668                                                break;
     669                                        case ast::TypeDecl::Ftype:
     670                                                fcount++;
     671                                                break;
     672                                        case ast::TypeDecl::Ttype:
     673                                                vcount++;
     674                                                break;
     675                                        default:
     676                                                assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[decl->kind].c_str() );
     677                                        } // switch
     678                                        varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
     679                                } // for
     680                                for ( auto & assert : funcType->assertions ) {
     681                                        assertionNames.push_back( ast::Pass<Mangler_new>::read(
     682                                                assert->var.get(),
     683                                                mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums ) );
     684                                        acount++;
     685                                } // for
     686                                mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_";
     687                                for ( const auto & a : assertionNames ) mangleName += a;
     688                                mangleName += "_";
    699689                        } // if
    700690                        if ( ! inFunctionType ) {
  • src/SymTab/Validate.cc

    r34b4268 r24d6572  
    5555#include "Common/ScopedMap.h"          // for ScopedMap
    5656#include "Common/SemanticError.h"      // for SemanticError
     57#include "Common/ToString.hpp"         // for toCString
    5758#include "Common/UniqueName.h"         // for UniqueName
    58 #include "Common/utility.h"            // for operator+, cloneAll, deleteAll
     59#include "Common/utility.h"            // for cloneAll, deleteAll
    5960#include "CompilationState.h"          // skip some passes in new-ast build
    6061#include "Concurrency/Keywords.h"      // for applyKeywords
     
    6364#include "InitTweak/GenInit.h"         // for fixReturnStatements
    6465#include "InitTweak/InitTweak.h"       // for isCtorDtorAssign
    65 #include "ResolvExpr/typeops.h"        // for typesCompatible
     66#include "ResolvExpr/typeops.h"        // for extractResultType
     67#include "ResolvExpr/Unify.h"          // for typesCompatible
    6668#include "ResolvExpr/Resolver.h"       // for findSingleExpression
    6769#include "ResolvExpr/ResolveTypeof.h"  // for resolveTypeof
     
    862864
    863865        void ReplaceTypedef::premutate( TypeDecl * typeDecl ) {
    864                 TypedefMap::iterator i = typedefNames.find( typeDecl->name );
    865                 if ( i != typedefNames.end() ) {
    866                         typedefNames.erase( i ) ;
    867                 } // if
    868 
     866                typedefNames.erase( typeDecl->name );
    869867                typedeclNames.insert( typeDecl->name, typeDecl );
    870868        }
  • src/SymTab/ValidateType.cc

    r34b4268 r24d6572  
    1818#include "CodeGen/OperatorTable.h"
    1919#include "Common/PassVisitor.h"
     20#include "Common/ToString.hpp"
    2021#include "SymTab/FixFunction.h"
    2122#include "SynTree/Declaration.h"
  • src/SymTab/module.mk

    r34b4268 r24d6572  
    2020        SymTab/FixFunction.cc \
    2121        SymTab/FixFunction.h \
     22        SymTab/GenImplicitCall.cpp \
     23        SymTab/GenImplicitCall.hpp \
    2224        SymTab/Indexer.cc \
    2325        SymTab/Indexer.h \
  • src/SynTree/AggregateDecl.cc

    r34b4268 r24d6572  
    1919
    2020#include "Attribute.h"           // for Attribute
     21#include "Common/Eval.h"         // for eval
    2122#include "Common/utility.h"      // for printAll, cloneAll, deleteAll
    2223#include "Declaration.h"         // for AggregateDecl, TypeDecl, Declaration
  • src/SynTree/ApplicationExpr.cc

    r34b4268 r24d6572  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // ApplicationExpr.cc.cc --
     7// ApplicationExpr.cc --
    88//
    99// Author           : Richard C. Bilson
     
    2626#include "Expression.h"          // for ParamEntry, ApplicationExpr, Expression
    2727#include "InitTweak/InitTweak.h" // for getFunction
    28 #include "ResolvExpr/typeops.h"  // for extractResultType
     28#include "ResolvExpr/Unify.h"    // for extractResultType
    2929#include "Type.h"                // for Type, PointerType, FunctionType
    3030
  • src/SynTree/BasicType.cc

    r34b4268 r24d6572  
    2929}
    3030
    31 bool BasicType::isWholeNumber() const {
    32         return kind == Bool ||
    33                 kind ==Char ||
    34                 kind == SignedChar ||
    35                 kind == UnsignedChar ||
    36                 kind == ShortSignedInt ||
    37                 kind == ShortUnsignedInt ||
    38                 kind == SignedInt ||
    39                 kind == UnsignedInt ||
    40                 kind == LongSignedInt ||
    41                 kind == LongUnsignedInt ||
    42                 kind == LongLongSignedInt ||
    43                 kind ==LongLongUnsignedInt ||
    44                 kind == SignedInt128 ||
    45                 kind == UnsignedInt128;
    46 }
    47 
    4831bool BasicType::isInteger() const {
    4932        return kind <= UnsignedInt128;
  • src/SynTree/FunctionDecl.cc

    r34b4268 r24d6572  
    8787        } // if
    8888
     89        if ( !withExprs.empty() ) {
     90                os << indent << "... with clause" << std::endl;
     91                os << indent + 1;
     92                printAll( withExprs, os, indent + 1 );
     93        }
     94
    8995        if ( statements ) {
    9096                os << indent << "... with body" << endl << indent+1;
  • src/SynTree/Type.cc

    r34b4268 r24d6572  
    1616
    1717#include "Attribute.h"                // for Attribute
     18#include "Common/ToString.hpp"        // for toCString
    1819#include "Common/utility.h"           // for cloneAll, deleteAll, printAll
    1920#include "InitTweak/InitTweak.h"      // for getPointerBase
     
    105106int Type::referenceDepth() const { return 0; }
    106107
     108AggregateDecl * Type::getAggr() const {
     109        assertf( false, "Non-aggregate type: %s", toCString( this ) );
     110}
     111
    107112TypeSubstitution Type::genericSubstitution() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
    108113
  • src/SynTree/Type.h

    r34b4268 r24d6572  
    99// Author           : Richard C. Bilson
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jul 14 15:40:00 2021
    13 // Update Count     : 171
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun Feb 19 22:37:10 2023
     13// Update Count     : 176
    1414//
    1515
     
    2323
    2424#include "BaseSyntaxNode.h"  // for BaseSyntaxNode
    25 #include "Common/utility.h"  // for operator+
     25#include "Common/Iterate.hpp"// for operator+
    2626#include "Mutator.h"         // for Mutator
    2727#include "SynTree.h"         // for AST nodes
     
    124124                bool operator!=( Qualifiers other ) const { return (val & Mask) != (other.val & Mask); }
    125125                bool operator<=( Qualifiers other ) const {
    126                         return is_const    <= other.is_const        //Any non-const converts to const without cost
    127                                         && is_volatile <= other.is_volatile     //Any non-volatile converts to volatile without cost
    128                                         && is_mutex    >= other.is_mutex        //Any mutex converts to non-mutex without cost
    129                                         && is_atomic   == other.is_atomic;      //No conversion from atomic to non atomic is free
     126                        return is_const    <= other.is_const        // Any non-const converts to const without cost
     127                                && is_volatile <= other.is_volatile             // Any non-volatile converts to volatile without cost
     128                                && is_mutex    >= other.is_mutex                // Any mutex converts to non-mutex without cost
     129                                && is_atomic   == other.is_atomic;              // No conversion from atomic to non atomic is free
    130130                }
    131131                bool operator<( Qualifiers other ) const { return *this != other && *this <= other; }
     
    185185        virtual bool isComplete() const { return true; }
    186186
    187         virtual AggregateDecl * getAggr() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
     187        virtual AggregateDecl * getAggr() const;
    188188
    189189        virtual TypeSubstitution genericSubstitution() const;
    190190
    191         virtual Type *clone() const = 0;
     191        virtual Type * clone() const = 0;
    192192        virtual void accept( Visitor & v ) = 0;
    193193        virtual void accept( Visitor & v ) const = 0;
    194         virtual Type *acceptMutator( Mutator & m ) = 0;
     194        virtual Type * acceptMutator( Mutator & m ) = 0;
    195195        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    196196};
     
    207207        virtual bool isComplete() const override { return false; }
    208208
    209         virtual VoidType *clone() const override { return new VoidType( *this ); }
    210         virtual void accept( Visitor & v ) override { v.visit( this ); }
    211         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    212         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     209        virtual VoidType * clone() const override { return new VoidType( *this ); }
     210        virtual void accept( Visitor & v ) override { v.visit( this ); }
     211        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     212        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    213213        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    214214};
     
    259259        // GENERATED END
    260260
    261         static const char *typeNames[];                                         // string names for basic types, MUST MATCH with Kind
     261        static const char * typeNames[];                                        // string names for basic types, MUST MATCH with Kind
    262262
    263263        BasicType( const Type::Qualifiers & tq, Kind bt, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     
    266266        void set_kind( Kind newValue ) { kind = newValue; }
    267267
    268         virtual BasicType *clone() const override { return new BasicType( *this ); }
    269         virtual void accept( Visitor & v ) override { v.visit( this ); }
    270         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    271         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    272         virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    273         bool isWholeNumber() const;
     268        virtual BasicType * clone() const override { return new BasicType( *this ); }
     269        virtual void accept( Visitor & v ) override { v.visit( this ); }
     270        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     271        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     272        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    274273        bool isInteger() const;
    275274};
     
    280279
    281280        // In C99, pointer types can be qualified in many ways e.g., int f( int a[ static 3 ] )
    282         Expression *dimension;
     281        Expression * dimension;
    283282        bool isVarLen;
    284283        bool isStatic;
    285284
    286         PointerType( const Type::Qualifiers & tq, Type *base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    287         PointerType( const Type::Qualifiers & tq, Type *base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     285        PointerType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     286        PointerType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    288287        PointerType( const PointerType& );
    289288        virtual ~PointerType();
    290289
    291         Type *get_base() { return base; }
    292         void set_base( Type *newValue ) { base = newValue; }
    293         Expression *get_dimension() { return dimension; }
    294         void set_dimension( Expression *newValue ) { dimension = newValue; }
     290        Type * get_base() { return base; }
     291        void set_base( Type * newValue ) { base = newValue; }
     292        Expression * get_dimension() { return dimension; }
     293        void set_dimension( Expression * newValue ) { dimension = newValue; }
    295294        bool get_isVarLen() { return isVarLen; }
    296295        void set_isVarLen( bool newValue ) { isVarLen = newValue; }
     
    302301        virtual bool isComplete() const override { return ! isVarLen; }
    303302
    304         virtual PointerType *clone() const override { return new PointerType( *this ); }
    305         virtual void accept( Visitor & v ) override { v.visit( this ); }
    306         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    307         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     303        virtual PointerType * clone() const override { return new PointerType( * this ); }
     304        virtual void accept( Visitor & v ) override { v.visit( this ); }
     305        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     306        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    308307        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    309308};
     
    311310class ArrayType : public Type {
    312311  public:
    313         Type *base;
    314         Expression *dimension;
     312        Type * base;
     313        Expression * dimension;
    315314        bool isVarLen;
    316315        bool isStatic;
    317316
    318         ArrayType( const Type::Qualifiers & tq, Type *base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     317        ArrayType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    319318        ArrayType( const ArrayType& );
    320319        virtual ~ArrayType();
    321320
    322         Type *get_base() { return base; }
    323         void set_base( Type *newValue ) { base = newValue; }
    324         Expression *get_dimension() { return dimension; }
    325         void set_dimension( Expression *newValue ) { dimension = newValue; }
     321        Type * get_base() { return base; }
     322        void set_base( Type * newValue ) { base = newValue; }
     323        Expression * get_dimension() { return dimension; }
     324        void set_dimension( Expression * newValue ) { dimension = newValue; }
    326325        bool get_isVarLen() { return isVarLen; }
    327326        void set_isVarLen( bool newValue ) { isVarLen = newValue; }
     
    334333        virtual bool isComplete() const override { return dimension || isVarLen; }
    335334
    336         virtual ArrayType *clone() const override { return new ArrayType( *this ); }
    337         virtual void accept( Visitor & v ) override { v.visit( this ); }
    338         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    339         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     335        virtual ArrayType * clone() const override { return new ArrayType( *this ); }
     336        virtual void accept( Visitor & v ) override { v.visit( this ); }
     337        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     338        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    340339        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    341340};
     
    349348        virtual ~QualifiedType();
    350349
    351         virtual QualifiedType *clone() const override { return new QualifiedType( *this ); }
    352         virtual void accept( Visitor & v ) override { v.visit( this ); }
    353         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    354         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     350        virtual QualifiedType * clone() const override { return new QualifiedType( *this ); }
     351        virtual void accept( Visitor & v ) override { v.visit( this ); }
     352        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     353        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    355354        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    356355};
     
    358357class ReferenceType : public Type {
    359358public:
    360         Type *base;
    361 
    362         ReferenceType( const Type::Qualifiers & tq, Type *base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     359        Type * base;
     360
     361        ReferenceType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    363362        ReferenceType( const ReferenceType & );
    364363        virtual ~ReferenceType();
    365364
    366         Type *get_base() { return base; }
    367         void set_base( Type *newValue ) { base = newValue; }
     365        Type * get_base() { return base; }
     366        void set_base( Type * newValue ) { base = newValue; }
    368367
    369368        virtual int referenceDepth() const override;
     
    376375        virtual TypeSubstitution genericSubstitution() const override;
    377376
    378         virtual ReferenceType *clone() const override { return new ReferenceType( *this ); }
    379         virtual void accept( Visitor & v ) override { v.visit( this ); }
    380         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    381         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     377        virtual ReferenceType * clone() const override { return new ReferenceType( *this ); }
     378        virtual void accept( Visitor & v ) override { v.visit( this ); }
     379        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     380        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    382381        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    383382};
     
    406405        bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; }
    407406
    408         virtual FunctionType *clone() const override { return new FunctionType( *this ); }
    409         virtual void accept( Visitor & v ) override { v.visit( this ); }
    410         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    411         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     407        virtual FunctionType * clone() const override { return new FunctionType( *this ); }
     408        virtual void accept( Visitor & v ) override { v.visit( this ); }
     409        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     410        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    412411        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    413412};
     
    415414class ReferenceToType : public Type {
    416415  public:
    417         std::list< Expression* > parameters;
     416        std::list< Expression * > parameters;
    418417        std::string name;
    419418        bool hoistType;
     
    429428        void set_hoistType( bool newValue ) { hoistType = newValue; }
    430429
    431         virtual ReferenceToType *clone() const override = 0;
     430        virtual ReferenceToType * clone() const override = 0;
    432431        virtual void accept( Visitor & v ) override = 0;
    433         virtual Type *acceptMutator( Mutator & m ) override = 0;
     432        virtual Type * acceptMutator( Mutator & m ) override = 0;
    434433        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    435434
     
    444443        // this decl is not "owned" by the struct inst; it is merely a pointer to elsewhere in the tree,
    445444        // where the structure used in this type is actually defined
    446         StructDecl *baseStruct;
     445        StructDecl * baseStruct;
    447446
    448447        StructInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ), baseStruct( 0 ) {}
     
    450449        StructInstType( const StructInstType & other ) : Parent( other ), baseStruct( other.baseStruct ) {}
    451450
    452         StructDecl *get_baseStruct() const { return baseStruct; }
    453         void set_baseStruct( StructDecl *newValue ) { baseStruct = newValue; }
     451        StructDecl * get_baseStruct() const { return baseStruct; }
     452        void set_baseStruct( StructDecl * newValue ) { baseStruct = newValue; }
    454453
    455454        /// Accesses generic parameters of base struct (NULL if none such)
     
    467466        void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override;
    468467
    469         virtual StructInstType *clone() const override { return new StructInstType( *this ); }
    470         virtual void accept( Visitor & v ) override { v.visit( this ); }
    471         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    472         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     468        virtual StructInstType * clone() const override { return new StructInstType( *this ); }
     469        virtual void accept( Visitor & v ) override { v.visit( this ); }
     470        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     471        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    473472
    474473        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    482481        // this decl is not "owned" by the union inst; it is merely a pointer to elsewhere in the tree,
    483482        // where the union used in this type is actually defined
    484         UnionDecl *baseUnion;
     483        UnionDecl * baseUnion;
    485484
    486485        UnionInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ), baseUnion( 0 ) {}
     
    488487        UnionInstType( const UnionInstType & other ) : Parent( other ), baseUnion( other.baseUnion ) {}
    489488
    490         UnionDecl *get_baseUnion() const { return baseUnion; }
     489        UnionDecl * get_baseUnion() const { return baseUnion; }
    491490        void set_baseUnion( UnionDecl * newValue ) { baseUnion = newValue; }
    492491
     
    505504        void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override;
    506505
    507         virtual UnionInstType *clone() const override { return new UnionInstType( *this ); }
    508         virtual void accept( Visitor & v ) override { v.visit( this ); }
    509         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    510         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     506        virtual UnionInstType * clone() const override { return new UnionInstType( *this ); }
     507        virtual void accept( Visitor & v ) override { v.visit( this ); }
     508        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     509        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    511510
    512511        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    520519        // this decl is not "owned" by the enum inst; it is merely a pointer to elsewhere in the tree,
    521520        // where the enum used in this type is actually defined
    522         EnumDecl *baseEnum = nullptr;
     521        EnumDecl * baseEnum = nullptr;
    523522
    524523        EnumInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ) {}
     
    526525        EnumInstType( const EnumInstType & other ) : Parent( other ), baseEnum( other.baseEnum ) {}
    527526
    528         EnumDecl *get_baseEnum() const { return baseEnum; }
    529         void set_baseEnum( EnumDecl *newValue ) { baseEnum = newValue; }
     527        EnumDecl * get_baseEnum() const { return baseEnum; }
     528        void set_baseEnum( EnumDecl * newValue ) { baseEnum = newValue; }
    530529
    531530        virtual bool isComplete() const override;
     
    533532        virtual AggregateDecl * getAggr() const override;
    534533
    535         virtual EnumInstType *clone() const override { return new EnumInstType( *this ); }
    536         virtual void accept( Visitor & v ) override { v.visit( this ); }
    537         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    538         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     534        virtual EnumInstType * clone() const override { return new EnumInstType( *this ); }
     535        virtual void accept( Visitor & v ) override { v.visit( this ); }
     536        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     537        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    539538
    540539        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    557556        virtual bool isComplete() const override;
    558557
    559         virtual TraitInstType *clone() const override { return new TraitInstType( *this ); }
    560         virtual void accept( Visitor & v ) override { v.visit( this ); }
    561         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    562         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     558        virtual TraitInstType * clone() const override { return new TraitInstType( *this ); }
     559        virtual void accept( Visitor & v ) override { v.visit( this ); }
     560        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     561        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    563562  private:
    564563        virtual std::string typeString() const override;
     
    570569        // this decl is not "owned" by the type inst; it is merely a pointer to elsewhere in the tree,
    571570        // where the type used here is actually defined
    572         TypeDecl *baseType;
     571        TypeDecl * baseType;
    573572        bool isFtype;
    574573
    575         TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl *baseType, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
     574        TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl * baseType, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    576575        TypeInstType( const Type::Qualifiers & tq, const std::string & name, bool isFtype, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    577576        TypeInstType( const TypeInstType & other );
    578577        ~TypeInstType();
    579578
    580         TypeDecl *get_baseType() const { return baseType; }
    581         void set_baseType( TypeDecl *newValue );
     579        TypeDecl * get_baseType() const { return baseType; }
     580        void set_baseType( TypeDecl * newValue );
    582581        bool get_isFtype() const { return isFtype; }
    583582        void set_isFtype( bool newValue ) { isFtype = newValue; }
     
    585584        virtual bool isComplete() const override;
    586585
    587         virtual TypeInstType *clone() const override { return new TypeInstType( *this ); }
    588         virtual void accept( Visitor & v ) override { v.visit( this ); }
    589         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    590         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     586        virtual TypeInstType * clone() const override { return new TypeInstType( *this ); }
     587        virtual void accept( Visitor & v ) override { v.visit( this ); }
     588        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     589        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    591590        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    592591  private:
     
    623622        // virtual bool isComplete() const override { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness
    624623
    625         virtual TupleType *clone() const override { return new TupleType( *this ); }
    626         virtual void accept( Visitor & v ) override { v.visit( this ); }
    627         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    628         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     624        virtual TupleType * clone() const override { return new TupleType( *this ); }
     625        virtual void accept( Visitor & v ) override { v.visit( this ); }
     626        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     627        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    629628        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    630629};
     
    632631class TypeofType : public Type {
    633632  public:
    634         Expression *expr;    ///< expression to take the type of
    635         bool is_basetypeof;  ///< true iff is basetypeof type
    636 
    637         TypeofType( const Type::Qualifiers & tq, Expression *expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    638         TypeofType( const Type::Qualifiers & tq, Expression *expr, bool is_basetypeof,
     633        Expression * expr;              ///< expression to take the type of
     634        bool is_basetypeof;             ///< true iff is basetypeof type
     635
     636        TypeofType( const Type::Qualifiers & tq, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     637        TypeofType( const Type::Qualifiers & tq, Expression * expr, bool is_basetypeof,
    639638                const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    640639        TypeofType( const TypeofType& );
    641640        virtual ~TypeofType();
    642641
    643         Expression *get_expr() const { return expr; }
    644         void set_expr( Expression *newValue ) { expr = newValue; }
     642        Expression * get_expr() const { return expr; }
     643        void set_expr( Expression * newValue ) { expr = newValue; }
    645644
    646645        virtual bool isComplete() const override { assert( false ); return false; }
    647646
    648         virtual TypeofType *clone() const override { return new TypeofType( *this ); }
    649         virtual void accept( Visitor & v ) override { v.visit( this ); }
    650         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    651         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     647        virtual TypeofType * clone() const override { return new TypeofType( *this ); }
     648        virtual void accept( Visitor & v ) override { v.visit( this ); }
     649        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     650        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    652651        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    653652};
     
    655654class VTableType : public Type {
    656655public:
    657         Type *base;
    658 
    659         VTableType( const Type::Qualifiers & tq, Type *base,
     656        Type * base;
     657
     658        VTableType( const Type::Qualifiers & tq, Type * base,
    660659                const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    661660        VTableType( const VTableType & );
    662661        virtual ~VTableType();
    663662
    664         Type *get_base() { return base; }
    665         void set_base( Type *newValue ) { base = newValue; }
    666 
    667         virtual VTableType *clone() const override { return new VTableType( *this ); }
    668         virtual void accept( Visitor & v ) override { v.visit( this ); }
    669         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    670         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     663        Type * get_base() { return base; }
     664        void set_base( Type * newValue ) { base = newValue; }
     665
     666        virtual VTableType * clone() const override { return new VTableType( *this ); }
     667        virtual void accept( Visitor & v ) override { v.visit( this ); }
     668        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     669        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    671670        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    672671};
     
    675674  public:
    676675        std::string name;
    677         Expression *expr;
    678         Type *type;
     676        Expression * expr;
     677        Type * type;
    679678        bool isType;
    680679
    681         AttrType( const Type::Qualifiers & tq, const std::string & name, Expression *expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    682         AttrType( const Type::Qualifiers & tq, const std::string & name, Type *type, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
     680        AttrType( const Type::Qualifiers & tq, const std::string & name, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     681        AttrType( const Type::Qualifiers & tq, const std::string & name, Type * type, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    683682        AttrType( const AttrType& );
    684683        virtual ~AttrType();
     
    686685        const std::string & get_name() const { return name; }
    687686        void set_name( const std::string & newValue ) { name = newValue; }
    688         Expression *get_expr() const { return expr; }
    689         void set_expr( Expression *newValue ) { expr = newValue; }
    690         Type *get_type() const { return type; }
    691         void set_type( Type *newValue ) { type = newValue; }
     687        Expression * get_expr() const { return expr; }
     688        void set_expr( Expression * newValue ) { expr = newValue; }
     689        Type * get_type() const { return type; }
     690        void set_type( Type * newValue ) { type = newValue; }
    692691        bool get_isType() const { return isType; }
    693692        void set_isType( bool newValue ) { isType = newValue; }
     
    695694        virtual bool isComplete() const override { assert( false ); } // xxx - not sure what to do here
    696695
    697         virtual AttrType *clone() const override { return new AttrType( *this ); }
    698         virtual void accept( Visitor & v ) override { v.visit( this ); }
    699         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    700         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     696        virtual AttrType * clone() const override { return new AttrType( *this ); }
     697        virtual void accept( Visitor & v ) override { v.visit( this ); }
     698        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     699        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    701700        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    702701};
     
    710709        virtual bool isComplete() const override{ return true; } // xxx - is this right?
    711710
    712         virtual VarArgsType *clone() const override { return new VarArgsType( *this ); }
    713         virtual void accept( Visitor & v ) override { v.visit( this ); }
    714         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    715         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     711        virtual VarArgsType * clone() const override { return new VarArgsType( *this ); }
     712        virtual void accept( Visitor & v ) override { v.visit( this ); }
     713        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     714        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    716715        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    717716};
     
    723722        ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    724723
    725         virtual ZeroType *clone() const override { return new ZeroType( *this ); }
    726         virtual void accept( Visitor & v ) override { v.visit( this ); }
    727         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    728         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     724        virtual ZeroType * clone() const override { return new ZeroType( *this ); }
     725        virtual void accept( Visitor & v ) override { v.visit( this ); }
     726        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     727        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    729728        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    730729};
     
    736735        OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    737736
    738         virtual OneType *clone() const override { return new OneType( *this ); }
    739         virtual void accept( Visitor & v ) override { v.visit( this ); }
    740         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    741         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     737        virtual OneType * clone() const override { return new OneType( *this ); }
     738        virtual void accept( Visitor & v ) override { v.visit( this ); }
     739        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     740        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    742741        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    743742};
     
    747746        GlobalScopeType();
    748747
    749         virtual GlobalScopeType *clone() const override { return new GlobalScopeType( *this ); }
    750         virtual void accept( Visitor & v ) override { v.visit( this ); }
    751         virtual void accept( Visitor & v ) const override { v.visit( this ); }
    752         virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
     748        virtual GlobalScopeType * clone() const override { return new GlobalScopeType( *this ); }
     749        virtual void accept( Visitor & v ) override { v.visit( this ); }
     750        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     751        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    753752        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    754753};
  • src/Tuples/Explode.cc

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

    r34b4268 r24d6572  
    2525
    2626#include "AST/Attribute.hpp"
     27#include "AST/Copy.hpp"
    2728#include "AST/Create.hpp"
    2829#include "AST/Decl.hpp"
     
    3940#include "InitTweak/GenInit.h"     // for fixReturnStatements
    4041#include "InitTweak/InitTweak.h"   // for isAssignment, isCopyConstructor
     42#include "SymTab/GenImplicitCall.hpp"  // for genImplicitCall
    4143#include "SymTab/Mangler.h"        // for Mangler
    4244#include "CompilationState.h"
    43 
    44 // TODO: The other new ast function should be moved over to this file.
    45 #include "SymTab/Autogen.h"
    4645
    4746namespace Validate {
     
    9493
    9594        const CodeLocation& getLocation() const { return getDecl()->location; }
    96         ast::FunctionDecl * genProto( const std::string& name,
     95        ast::FunctionDecl * genProto( std::string&& name,
    9796                std::vector<ast::ptr<ast::DeclWithType>>&& params,
    9897                std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const;
     
    322321void FuncGenerator::produceDecl( const ast::FunctionDecl * decl ) {
    323322        assert( nullptr != decl->stmts );
     323        const auto & oldParams = getGenericParams(type);
     324        assert( decl->type_params.size() == oldParams.size());
     325
     326        /*
     327        ast::DeclReplacer::TypeMap typeMap;
     328        for (auto it = oldParams.begin(), jt = decl->type_params.begin(); it != oldParams.end(); ++it, ++jt) {
     329                typeMap.emplace(*it, *jt);
     330        }
     331
     332        const ast::FunctionDecl * mut = strict_dynamic_cast<const ast::FunctionDecl *>(ast::DeclReplacer::replace(decl, typeMap));
     333        assert (mut == decl);
     334        */
    324335
    325336        definitions.push_back( decl );
     
    335346}
    336347
     348void replaceAll( std::vector<ast::ptr<ast::DeclWithType>> & dwts,
     349                const ast::DeclReplacer::TypeMap & map ) {
     350        for ( auto & dwt : dwts ) {
     351                dwt = strict_dynamic_cast<const ast::DeclWithType *>(
     352                                ast::DeclReplacer::replace( dwt, map ) );
     353        }
     354}
     355
    337356/// Generates a basic prototype function declaration.
    338 ast::FunctionDecl * FuncGenerator::genProto( const std::string& name,
     357ast::FunctionDecl * FuncGenerator::genProto( std::string&& name,
    339358                std::vector<ast::ptr<ast::DeclWithType>>&& params,
    340359                std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const {
     
    342361        // Handle generic prameters and assertions, if any.
    343362        auto const & old_type_params = getGenericParams( type );
     363        ast::DeclReplacer::TypeMap oldToNew;
    344364        std::vector<ast::ptr<ast::TypeDecl>> type_params;
    345365        std::vector<ast::ptr<ast::DeclWithType>> assertions;
     366
     367        ast::DeclReplacer::TypeMap typeMap;
    346368        for ( auto & old_param : old_type_params ) {
    347369                ast::TypeDecl * decl = ast::deepCopy( old_param );
    348                 for ( auto assertion : decl->assertions ) {
    349                         assertions.push_back( assertion );
    350                 }
    351                 decl->assertions.clear();
     370                decl->init = nullptr;
     371                splice( assertions, decl->assertions );
     372                oldToNew.emplace( std::make_pair( old_param, decl ) );
    352373                type_params.push_back( decl );
    353         }
    354         // TODO: The values in params and returns still may point at the old
    355         // generic params, that does not appear to be an issue but perhaps it
    356         // should be addressed.
     374                typeMap.emplace(old_param, decl);
     375        }
     376
     377        for (auto & param : params) {
     378                param = ast::DeclReplacer::replace(param, typeMap);
     379        }
     380        for (auto & param : returns) {
     381                param = ast::DeclReplacer::replace(param, typeMap);
     382        }
     383        replaceAll( params, oldToNew );
     384        replaceAll( returns, oldToNew );
     385        replaceAll( assertions, oldToNew );
    357386
    358387        ast::FunctionDecl * decl = new ast::FunctionDecl(
    359388                // Auto-generated routines use the type declaration's location.
    360389                getLocation(),
    361                 name,
     390                std::move( name ),
    362391                std::move( type_params ),
    363392                std::move( assertions ),
     
    423452        for ( unsigned int index = 0 ; index < fields ; ++index ) {
    424453                auto member = aggr->members[index].strict_as<ast::DeclWithType>();
    425                 if ( SymTab::isUnnamedBitfield(
     454                if ( ast::isUnnamedBitfield(
    426455                                dynamic_cast<const ast::ObjectDecl *>( member ) ) ) {
    427456                        if ( index == fields - 1 ) {
     
    515544        InitTweak::InitExpander_new srcParam( src );
    516545        // Assign to destination.
    517         ast::Expr * dstSelect = new ast::MemberExpr(
     546        ast::MemberExpr * dstSelect = new ast::MemberExpr(
    518547                location,
    519548                field,
     
    567596                }
    568597
    569                 ast::Expr * srcSelect = (srcParam) ? new ast::MemberExpr(
     598                ast::MemberExpr * srcSelect = (srcParam) ? new ast::MemberExpr(
    570599                        location, field, new ast::VariableExpr( location, srcParam )
    571600                ) : nullptr;
     
    599628                // Not sure why it could be null.
    600629                // Don't make a function for a parameter that is an unnamed bitfield.
    601                 if ( nullptr == field || SymTab::isUnnamedBitfield( field ) ) {
     630                if ( nullptr == field || ast::isUnnamedBitfield( field ) ) {
    602631                        continue;
    603632                // Matching Parameter: Initialize the field by copy.
  • src/Validate/FixQualifiedTypes.cpp

    r34b4268 r24d6572  
    1616#include "Validate/FixQualifiedTypes.hpp"
    1717
     18#include "AST/Copy.hpp"
     19#include "AST/LinkageSpec.hpp"             // for Linkage
    1820#include "AST/Pass.hpp"
    1921#include "AST/TranslationUnit.hpp"
     22#include "Common/ToString.hpp"             // for toString
     23#include "SymTab/Mangler.h"                // for Mangler
    2024#include "Validate/NoIdSymbolTable.hpp"
    21 #include "SymTab/Mangler.h"            // for Mangler
    22 #include "AST/LinkageSpec.hpp"                     // for Linkage
    2325
    2426namespace Validate {
  • src/Validate/FixReturnTypes.cpp

    r34b4268 r24d6572  
    2020#include "AST/Type.hpp"
    2121#include "CodeGen/CodeGenerator.h"
    22 #include "ResolvExpr/typeops.h"
     22#include "ResolvExpr/Unify.h"
    2323
    2424namespace ast {
  • src/Validate/ForallPointerDecay.cpp

    r34b4268 r24d6572  
    2222#include "CodeGen/OperatorTable.h"
    2323#include "Common/CodeLocation.h"
     24#include "Common/ToString.hpp"
    2425#include "SymTab/FixFunction.h"
    2526
  • src/Validate/GenericParameter.cpp

    r34b4268 r24d6572  
    1616#include "GenericParameter.hpp"
    1717
     18#include "AST/Copy.hpp"
    1819#include "AST/Decl.hpp"
    1920#include "AST/Expr.hpp"
  • src/Validate/HandleAttributes.cc

    r34b4268 r24d6572  
    1717
    1818#include "CompilationState.h"
     19#include "Common/Eval.h"
    1920#include "Common/PassVisitor.h"
     21#include "Common/ToString.hpp"
    2022#include "Common/SemanticError.h"
    2123#include "ResolvExpr/Resolver.h"
  • src/Validate/HoistStruct.cpp

    r34b4268 r24d6572  
    1616#include "Validate/HoistStruct.hpp"
    1717
     18#include <sstream>
     19
    1820#include "AST/Pass.hpp"
    1921#include "AST/TranslationUnit.hpp"
    20 #include "Common/utility.h"
    2122
    2223namespace Validate {
  • src/Validate/ReplaceTypedef.cpp

    r34b4268 r24d6572  
    1616#include "ReplaceTypedef.hpp"
    1717
     18#include "AST/Copy.hpp"
    1819#include "AST/Pass.hpp"
    1920#include "Common/ScopedMap.h"
    2021#include "Common/UniqueName.h"
    2122#include "Common/utility.h"
    22 #include "ResolvExpr/typeops.h"
     23#include "ResolvExpr/Unify.h"
    2324
    2425namespace Validate {
     
    149150                // constant/enumerator. The effort required to fix this corner case
    150151                // likely outweighs the utility of allowing it.
    151                 if ( !ResolvExpr::typesCompatible( t0, t1, ast::SymbolTable() )
     152                if ( !ResolvExpr::typesCompatible( t0, t1 )
    152153                                || ast::Pass<VarLenChecker>::read( t0 )
    153154                                || ast::Pass<VarLenChecker>::read( t1 ) ) {
     
    186187
    187188void ReplaceTypedefCore::previsit( ast::TypeDecl const * decl ) {
    188         TypedefMap::iterator iter = typedefNames.find( decl->name );
    189         if ( iter != typedefNames.end() ) {
    190                 typedefNames.erase( iter );
    191         }
     189        typedefNames.erase( decl->name );
    192190        typedeclNames.insert( decl->name, decl );
    193191}
  • src/Virtual/ExpandCasts.cc

    r34b4268 r24d6572  
    2020#include <string>                  // for string, allocator, operator==, ope...
    2121
     22#include "AST/Copy.hpp"
    2223#include "AST/Decl.hpp"
    2324#include "AST/Expr.hpp"
  • src/Virtual/module.mk

    r34b4268 r24d6572  
    1919        Virtual/ExpandCasts.h \
    2020        Virtual/Tables.cc \
    21         Virtual/Tables.h
     21        Virtual/Tables.h \
     22        Virtual/VirtualDtor.cpp \
     23        Virtual/VirtualDtor.hpp
  • src/include/cassert

    r34b4268 r24d6572  
    2020#include_next <cassert>
    2121
    22 #include <string>
    23 
    24 template < typename ... Params >
    25 std::string toString( const Params & ... params );
     22#include "Common/ToString.hpp"
    2623
    2724#ifdef NDEBUG
  • src/main.cc

    r34b4268 r24d6572  
    99// Author           : Peter Buhr and Rob Schluntz
    1010// Created On       : Fri May 15 23:12:02 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Oct  5 12:06:00 2022
    13 // Update Count     : 679
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Mon Apr 10 21:12:17 2023
     13// Update Count     : 682
    1414//
    1515
     
    3232
    3333#include "AST/Convert.hpp"
     34#include "AST/Pass.hpp"                     // for pass_visitor_stats
     35#include "AST/TranslationUnit.hpp"          // for TranslationUnit
     36#include "AST/Util.hpp"                     // for checkInvariants
    3437#include "CompilationState.h"
    3538#include "../config.h"                      // for CFA_LIBDIR
     
    4043#include "CodeTools/TrackLoc.h"             // for fillLocations
    4144#include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
    42 #include "Common/CompilerError.h"           // for CompilerError
    4345#include "Common/DeclStats.hpp"             // for printDeclStats
    4446#include "Common/ResolvProtoDump.hpp"       // for dumpAsResolverProto
    4547#include "Common/Stats.h"                   // for Stats
    46 #include "Common/UnimplementedError.h"      // for UnimplementedError
    4748#include "Common/utility.h"                 // for deleteAll, filter, printAll
     49#include "Concurrency/Actors.hpp"           // for implementActors
    4850#include "Concurrency/Keywords.h"           // for implementMutex, implement...
    4951#include "Concurrency/Waitfor.h"            // for generateWaitfor
     52#include "Concurrency/Waituntil.hpp"        // for generateWaitUntil
    5053#include "ControlStruct/ExceptDecl.h"       // for translateExcept
    5154#include "ControlStruct/ExceptTranslate.h"  // for translateThrows, translat...
     
    5962#include "InitTweak/GenInit.h"              // for genInit
    6063#include "MakeLibCfa.h"                     // for makeLibCfa
    61 #include "Parser/ParseNode.h"               // for DeclarationNode, buildList
    62 #include "Parser/TypedefTable.h"            // for TypedefTable
     64#include "Parser/RunParser.hpp"             // for buildList, dumpParseTree,...
    6365#include "ResolvExpr/CandidatePrinter.hpp"  // for printCandidates
    6466#include "ResolvExpr/Resolver.h"            // for resolve
     
    8486#include "Validate/VerifyCtorDtorAssign.hpp" // for verifyCtorDtorAssign
    8587#include "Virtual/ExpandCasts.h"            // for expandCasts
     88#include "Virtual/VirtualDtor.hpp"           // for implementVirtDtors
    8689
    8790static void NewPass( const char * const name ) {
     
    102105}
    103106
    104 #define PASS( name, pass )                  \
     107// Helpers for checkInvariant:
     108void checkInvariants( std::list< Declaration * > & ) {}
     109using ast::checkInvariants;
     110
     111#define PASS( name, pass, unit, ... )       \
    105112        if ( errorp ) { cerr << name << endl; } \
    106113        NewPass(name);                          \
    107114        Stats::Time::StartBlock(name);          \
    108         pass;                                   \
    109         Stats::Time::StopBlock();
    110 
    111 LinkageSpec::Spec linkage = LinkageSpec::Cforall;
    112 TypedefTable typedefTable;
    113 DeclarationNode * parseTree = nullptr;                                  // program parse tree
     115        pass(unit,##__VA_ARGS__);               \
     116        Stats::Time::StopBlock();               \
     117        if ( invariant ) {                      \
     118                checkInvariants(unit);              \
     119        }
     120
     121#define DUMP( cond, unit )                  \
     122        if ( cond ) {                           \
     123                dump(unit);                         \
     124                return EXIT_SUCCESS;                \
     125        }
    114126
    115127static bool waiting_for_gdb = false;                                    // flag to set cfa-cpp to wait for gdb on start
     
    118130
    119131static void parse_cmdline( int argc, char * argv[] );
    120 static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit = false );
    121132static void dump( list< Declaration * > & translationUnit, ostream & out = cout );
    122133static void dump( ast::TranslationUnit && transUnit, ostream & out = cout );
     
    234245        ostream * output = & cout;
    235246        list< Declaration * > translationUnit;
     247        ast::TranslationUnit transUnit;
    236248
    237249        Signal( SIGSEGV, sigSegvBusHandler, SA_SIGINFO );
     
    278290                        FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" );
    279291                        assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" );
    280                         parse( gcc_builtins, LinkageSpec::Compiler );
     292                        parse( gcc_builtins, ast::Linkage::Compiler );
    281293
    282294                        // read the extra prelude in, if not generating the cfa library
    283295                        FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" );
    284296                        assertf( extras, "cannot open extras.cf\n" );
    285                         parse( extras, LinkageSpec::BuiltinC );
     297                        parse( extras, ast::Linkage::BuiltinC );
    286298
    287299                        if ( ! libcfap ) {
     
    289301                                FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" );
    290302                                assertf( prelude, "cannot open prelude.cfa\n" );
    291                                 parse( prelude, LinkageSpec::Intrinsic );
     303                                parse( prelude, ast::Linkage::Intrinsic );
    292304
    293305                                // Read to cfa builtins, if not generating the cfa library
    294306                                FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" );
    295307                                assertf( builtins, "cannot open builtins.cf\n" );
    296                                 parse( builtins, LinkageSpec::BuiltinCFA );
    297                         } // if
    298                 } // if
    299 
    300                 parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, yydebug );
    301 
    302                 if ( parsep ) {
    303                         parseTree->printList( cout );
    304                         delete parseTree;
    305                         return EXIT_SUCCESS;
    306                 } // if
    307 
    308                 buildList( parseTree, translationUnit );
    309                 delete parseTree;
    310                 parseTree = nullptr;
    311 
    312                 if ( astp ) {
    313                         dump( translationUnit );
    314                         return EXIT_SUCCESS;
    315                 } // if
    316 
    317                 // Temporary: fill locations after parsing so that every node has a location, for early error messages.
    318                 // Eventually we should pass the locations from the parser to every node, but this quick and dirty solution
    319                 // works okay for now.
    320                 CodeTools::fillLocations( translationUnit );
     308                                parse( builtins, ast::Linkage::BuiltinCFA );
     309                        } // if
     310                } // if
     311
     312                parse( input, libcfap ? ast::Linkage::Intrinsic : ast::Linkage::Cforall, yydebug );
     313
     314                transUnit = buildUnit();
     315
     316                DUMP( astp, std::move( transUnit ) );
     317
    321318                Stats::Time::StopBlock();
    322319
     
    325322                        ast::pass_visitor_stats.max = Stats::Counters::build<Stats::Counters::MaxCounter<double>>("Max depth - New");
    326323                }
    327                 auto transUnit = convert( std::move( translationUnit ) );
    328 
    329                 forceFillCodeLocations( transUnit );
    330 
    331                 PASS( "Translate Exception Declarations", ControlStruct::translateExcept( transUnit ) );
    332                 if ( exdeclp ) {
    333                         dump( std::move( transUnit ) );
    334                         return EXIT_SUCCESS;
    335                 }
    336 
    337                 PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign( transUnit ) );
    338                 PASS( "Hoist Type Decls", Validate::hoistTypeDecls( transUnit ) );
    339                 // Hoist Type Decls pulls some declarations out of contexts where
    340                 // locations are not tracked. Perhaps they should be, but for now
    341                 // the full fill solves it.
    342                 forceFillCodeLocations( transUnit );
    343 
    344                 PASS( "Replace Typedefs", Validate::replaceTypedef( transUnit ) );
    345                 PASS( "Fix Return Types", Validate::fixReturnTypes( transUnit ) );
    346                 PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers( transUnit ) );
    347 
    348                 PASS( "Link Reference To Types", Validate::linkReferenceToTypes( transUnit ) );
    349 
    350                 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes( transUnit ) );
    351                 PASS( "Hoist Struct", Validate::hoistStruct( transUnit ) );
    352                 PASS( "Eliminate Typedef", Validate::eliminateTypedef( transUnit ) );
    353                 PASS( "Validate Generic Parameters", Validate::fillGenericParameters( transUnit ) );
    354                 PASS( "Translate Dimensions", Validate::translateDimensionParameters( transUnit ) );
    355                 PASS( "Check Function Returns", Validate::checkReturnStatements( transUnit ) );
    356                 PASS( "Fix Return Statements", InitTweak::fixReturnStatements( transUnit ) );
    357                 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) );
    358                 PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) );
    359                 PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls( transUnit ) );
    360 
    361                 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) );
    362 
    363                 PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) );
    364                 PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) );
    365                 PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) );
    366                 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) );
    367                 PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) );
    368                 PASS( "Fix Label Address", Validate::fixLabelAddresses( transUnit ) );
     324
     325                PASS( "Hoist Type Decls", Validate::hoistTypeDecls, transUnit );
     326
     327                PASS( "Translate Exception Declarations", ControlStruct::translateExcept, transUnit );
     328                DUMP( exdeclp, std::move( transUnit ) );
     329                PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign, transUnit );
     330                PASS( "Replace Typedefs", Validate::replaceTypedef, transUnit );
     331                PASS( "Fix Return Types", Validate::fixReturnTypes, transUnit );
     332                PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers, transUnit );
     333
     334                PASS( "Link Reference To Types", Validate::linkReferenceToTypes, transUnit );
     335
     336                PASS( "Fix Qualified Types", Validate::fixQualifiedTypes, transUnit );
     337                PASS( "Hoist Struct", Validate::hoistStruct, transUnit );
     338                PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit );
     339                PASS( "Validate Generic Parameters", Validate::fillGenericParameters, transUnit );
     340                PASS( "Translate Dimensions", Validate::translateDimensionParameters, transUnit );
     341                PASS( "Check Function Returns", Validate::checkReturnStatements, transUnit );
     342                PASS( "Fix Return Statements", InitTweak::fixReturnStatements, transUnit );
     343                PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords, transUnit );
     344                PASS( "Forall Pointer Decay", Validate::decayForallPointers, transUnit );
     345        PASS( "Implement Waituntil", Concurrency::generateWaitUntil, transUnit  );
     346                PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls, transUnit );
     347
     348                PASS( "Generate Autogen Routines", Validate::autogenerateRoutines, transUnit );
     349
     350                PASS( "Implement Actors", Concurrency::implementActors, transUnit );
     351                PASS( "Implement Virtual Destructors", Virtual::implementVirtDtors, transUnit );
     352                PASS( "Implement Mutex", Concurrency::implementMutex, transUnit );
     353                PASS( "Implement Thread Start", Concurrency::implementThreadStarter, transUnit );
     354                PASS( "Compound Literal", Validate::handleCompoundLiterals, transUnit );
     355                PASS( "Set Length From Initializer", Validate::setLengthFromInitializer, transUnit );
     356                PASS( "Find Global Decls", Validate::findGlobalDecls, transUnit );
     357                PASS( "Fix Label Address", Validate::fixLabelAddresses, transUnit );
    369358
    370359                if ( symtabp ) {
     
    377366                } // if
    378367
    379                 if ( validp ) {
    380                         dump( std::move( transUnit ) );
    381                         return EXIT_SUCCESS;
    382                 } // if
    383 
    384                 PASS( "Translate Throws", ControlStruct::translateThrows( transUnit ) );
    385                 PASS( "Fix Labels", ControlStruct::fixLabels( transUnit ) );
    386                 PASS( "Fix Names", CodeGen::fixNames( transUnit ) );
    387                 PASS( "Gen Init", InitTweak::genInit( transUnit ) );
    388                 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) );
     368                DUMP( validp, std::move( transUnit ) );
     369
     370                PASS( "Translate Throws", ControlStruct::translateThrows, transUnit );
     371                PASS( "Fix Labels", ControlStruct::fixLabels, transUnit );
     372                PASS( "Fix Names", CodeGen::fixNames, transUnit );
     373                PASS( "Gen Init", InitTweak::genInit, transUnit );
     374                PASS( "Expand Member Tuples" , Tuples::expandMemberTuples, transUnit );
    389375
    390376                if ( libcfap ) {
     
    398384                } // if
    399385
    400                 if ( bresolvep ) {
    401                         dump( std::move( transUnit ) );
    402                         return EXIT_SUCCESS;
    403                 } // if
     386                DUMP( bresolvep, std::move( transUnit ) );
    404387
    405388                if ( resolvprotop ) {
     
    408391                } // if
    409392
    410                 PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
    411                 if ( exprp ) {
    412                         dump( std::move( transUnit ) );
    413                         return EXIT_SUCCESS;
    414                 } // if
    415 
    416                 forceFillCodeLocations( transUnit );
    417 
    418                 PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));
     393                PASS( "Resolve", ResolvExpr::resolve, transUnit );
     394                DUMP( exprp, std::move( transUnit ) );
     395
     396                PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() );
    419397
    420398                // fix ObjectDecl - replaces ConstructorInit nodes
    421                 if ( ctorinitp ) {
    422                         dump( std::move( transUnit ) );
    423                         return EXIT_SUCCESS;
    424                 } // if
     399                DUMP( ctorinitp, std::move( transUnit ) );
    425400
    426401                // Currently not working due to unresolved issues with UniqueExpr
    427                 PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( transUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
    428 
    429                 PASS( "Translate Tries", ControlStruct::translateTries( transUnit ) );
    430                 PASS( "Gen Waitfor", Concurrency::generateWaitFor( transUnit ) );
     402                PASS( "Expand Unique Expr", Tuples::expandUniqueExpr, transUnit ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
     403
     404                PASS( "Translate Tries", ControlStruct::translateTries, transUnit );
     405                PASS( "Gen Waitfor", Concurrency::generateWaitFor, transUnit );
    431406
    432407                // Needs to happen before tuple types are expanded.
    433                 PASS( "Convert Specializations",  GenPoly::convertSpecializations( transUnit ) );
    434 
    435                 PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) );
    436 
    437                 if ( tuplep ) {
    438                         dump( std::move( transUnit ) );
    439                         return EXIT_SUCCESS;
    440                 } // if
     408                PASS( "Convert Specializations",  GenPoly::convertSpecializations, transUnit );
     409
     410                PASS( "Expand Tuples", Tuples::expandTuples, transUnit );
     411                DUMP( tuplep, std::move( transUnit ) );
    441412
    442413                // Must come after Translate Tries.
    443                 PASS( "Virtual Expand Casts", Virtual::expandCasts( transUnit ) );
    444 
    445                 PASS( "Instantiate Generics", GenPoly::instantiateGeneric( transUnit ) );
    446                 if ( genericsp ) {
    447                         dump( std::move( transUnit ) );
    448                         return EXIT_SUCCESS;
    449                 } // if
    450 
    451                 PASS( "Convert L-Value", GenPoly::convertLvalue( transUnit ) );
     414                PASS( "Virtual Expand Casts", Virtual::expandCasts, transUnit );
     415
     416                PASS( "Instantiate Generics", GenPoly::instantiateGeneric, transUnit );
     417                DUMP( genericsp, std::move( transUnit ) );
     418
     419                PASS( "Convert L-Value", GenPoly::convertLvalue, transUnit );
    452420
    453421                translationUnit = convert( std::move( transUnit ) );
    454422
    455                 if ( bboxp ) {
    456                         dump( translationUnit );
    457                         return EXIT_SUCCESS;
    458                 } // if
    459                 PASS( "Box", GenPoly::box( translationUnit ) );
    460 
    461                 PASS( "Link-Once", CodeGen::translateLinkOnce( translationUnit ) );
     423                DUMP( bboxp, translationUnit );
     424                PASS( "Box", GenPoly::box, translationUnit );
     425
     426                PASS( "Link-Once", CodeGen::translateLinkOnce, translationUnit );
    462427
    463428                // Code has been lowered to C, now we can start generation.
    464429
    465                 if ( bcodegenp ) {
    466                         dump( translationUnit );
    467                         return EXIT_SUCCESS;
    468                 } // if
     430                DUMP( bcodegenp, translationUnit );
    469431
    470432                if ( optind < argc ) {                                                  // any commands after the flags and input file ? => output file name
     
    473435
    474436                CodeTools::fillLocations( translationUnit );
    475                 PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) );
     437                PASS( "Code Gen", CodeGen::generate, translationUnit, *output, ! genproto, prettycodegenp, true, linemarks );
    476438
    477439                CodeGen::FixMain::fix( translationUnit, *output,
     
    483445                if ( errorp ) {
    484446                        cerr << "---AST at error:---" << endl;
    485                         dump( translationUnit, cerr );
     447                        // We check which section the errors came from without looking at
     448                        // transUnit because std::move means it could look like anything.
     449                        if ( !translationUnit.empty() ) {
     450                                dump( translationUnit, cerr );
     451                        } else {
     452                                dump( std::move( transUnit ), cerr );
     453                        }
    486454                        cerr << endl << "---End of AST, begin error message:---\n" << endl;
    487455                } // if
    488456                e.print();
    489                 if ( output != &cout ) {
    490                         delete output;
    491                 } // if
    492                 return EXIT_FAILURE;
    493         } catch ( UnimplementedError & e ) {
    494                 cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl;
    495                 if ( output != &cout ) {
    496                         delete output;
    497                 } // if
    498                 return EXIT_FAILURE;
    499         } catch ( CompilerError & e ) {
    500                 cerr << "Compiler Error: " << e.get_what() << endl;
    501                 cerr << "(please report bugs to [REDACTED])" << endl;
    502457                if ( output != &cout ) {
    503458                        delete output;
     
    528483
    529484
    530 static const char optstring[] = ":c:ghlLmNnpdP:S:twW:D:";
     485static const char optstring[] = ":c:ghilLmNnpdP:S:twW:D:";
    531486
    532487enum { PreludeDir = 128 };
     
    535490        { "gdb", no_argument, nullptr, 'g' },
    536491        { "help", no_argument, nullptr, 'h' },
     492        { "invariant", no_argument, nullptr, 'i' },
    537493        { "libcfa", no_argument, nullptr, 'l' },
    538494        { "linemarks", no_argument, nullptr, 'L' },
    539         { "no-main", no_argument, 0, 'm' },
     495        { "no-main", no_argument, nullptr, 'm' },
    540496        { "no-linemarks", no_argument, nullptr, 'N' },
    541497        { "no-prelude", no_argument, nullptr, 'n' },
     
    556512        "wait for gdb to attach",                                                       // -g
    557513        "print translator help message",                                        // -h
     514        "invariant checking during AST passes",                         // -i
    558515        "generate libcfa.c",                                                            // -l
    559516        "generate line marks",                                                          // -L
     
    587544        { "rproto", resolvprotop, true, "resolver-proto instance" },
    588545        { "rsteps", resolvep, true, "print resolver steps" },
    589         { "tree", parsep, true, "print parse tree" },
    590546        // code dumps
    591547        { "ast", astp, true, "print AST after parsing" },
     
    650606                        usage( argv );                                                          // no return
    651607                        break;
     608                  case 'i':                                                                             // invariant checking
     609                        invariant = true;
     610                        break;
    652611                  case 'l':                                                                             // generate libcfa.c
    653612                        libcfap = true;
     
    748707} // parse_cmdline
    749708
    750 static void parse( FILE * input, LinkageSpec::Spec linkage, bool shouldExit ) {
    751         extern int yyparse( void );
    752         extern FILE * yyin;
    753         extern int yylineno;
    754 
    755         ::linkage = linkage;                                                            // set globals
    756         yyin = input;
    757         yylineno = 1;
    758         int parseStatus = yyparse();
    759 
    760         fclose( input );
    761         if ( shouldExit || parseStatus != 0 ) {
    762                 exit( parseStatus );
    763         } // if
    764 } // parse
    765 
    766709static bool notPrelude( Declaration * decl ) {
    767710        return ! LinkageSpec::isBuiltin( decl->get_linkage() );
Note: See TracChangeset for help on using the changeset viewer.