Changeset b110bcc for src


Ignore:
Timestamp:
Apr 21, 2023, 5:36:12 PM (2 years ago)
Author:
JiadaL <j82liang@…>
Branches:
ADT, master
Children:
28f8f15, 6e4c44d
Parents:
2ed94a9 (diff), 699a97d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Location:
src
Files:
11 added
3 deleted
92 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Attribute.hpp

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

    r2ed94a9 rb110bcc  
    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;
     
    16831683                        GET_ACCEPT_V(attributes, Attribute),
    16841684                        { old->get_funcSpec().val },
    1685                         old->type->isVarArgs
     1685                        (old->type->isVarArgs) ? ast::VariableArgs : ast::FixedArgs
    16861686                };
    16871687
     
    19891989                        GET_ACCEPT_1(else_, Stmt),
    19901990                        GET_ACCEPT_V(initialization, Stmt),
    1991                         old->isDoWhile,
     1991                        (old->isDoWhile) ? ast::DoWhile : ast::While,
    19921992                        GET_LABELS_V(old->labels)
    19931993                );
     
    21312131        virtual void visit( const SuspendStmt * old ) override final {
    21322132                if ( inCache( old ) ) return;
    2133                 ast::SuspendStmt::Type type;
     2133                ast::SuspendStmt::Kind type;
    21342134                switch (old->type) {
    21352135                        case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break;
  • src/AST/Create.cpp

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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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.hpp

    r2ed94a9 rb110bcc  
    254254};
    255255
     256/// A name qualified by a namespace or type.
    256257class QualifiedNameExpr final : public Expr {
    257258public:
     
    259260        std::string name;
    260261
    261         QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 
     262        QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n )
    262263        : Expr( loc ), type_decl( d ), name( n ) {}
    263264
     
    621622};
    622623
     624/// A name that refers to a generic dimension parameter.
    623625class DimensionExpr final : public Expr {
    624626public:
     
    910912};
    911913
    912 
    913914}
    914915
  • src/AST/Fwd.hpp

    r2ed94a9 rb110bcc  
    1515
    1616#pragma once
     17
     18template<typename> struct bitfield;
    1719
    1820#include "AST/Node.hpp"
     
    147149class TranslationGlobal;
    148150
     151// For the following types, only use the using type.
     152namespace CV {
     153        struct qualifier_flags;
     154        using Qualifiers = bitfield<qualifier_flags>;
    149155}
     156namespace Function {
     157        struct spec_flags;
     158        using Specs = bitfield<spec_flags>;
     159}
     160namespace Storage {
     161        struct class_flags;
     162        using Classes = bitfield<class_flags>;
     163}
     164namespace Linkage {
     165        struct spec_flags;
     166        using Spec = bitfield<spec_flags>;
     167}
     168
     169}
  • src/AST/Init.hpp

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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/ParseNode.hpp

    r2ed94a9 rb110bcc  
    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.impl.hpp

    r2ed94a9 rb110bcc  
    2222#include "AST/TranslationUnit.hpp"
    2323#include "AST/TypeSubstitution.hpp"
     24#include "Common/Iterate.hpp"
    2425
    2526#define VISIT_START( node ) \
     
    20412042        if ( __visit_children() ) {
    20422043                maybe_accept( node, &TupleType::types );
    2043                 maybe_accept( node, &TupleType::members );
    20442044        }
    20452045
  • src/AST/Pass.proto.hpp

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

    r2ed94a9 rb110bcc  
    2929namespace ast {
    3030
    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         };
     31namespace {
     32
     33template<typename C, typename... T>
     34constexpr array<C, sizeof...(T)> make_array( T&&... values ) {
     35        return array<C, sizeof...(T)>{ std::forward<T>( values )... };
     36}
     37
     38namespace Names {
     39        static constexpr auto FuncSpecifiers = make_array<const char*>(
     40                "inline", "_Noreturn", "fortran"
     41        );
     42
     43        static constexpr auto StorageClasses = make_array<const char*>(
     44                "extern", "static", "auto", "register", "__thread", "_Thread_local"
     45        );
     46
     47        static constexpr auto Qualifiers = make_array<const char*>(
     48                "const", "restrict", "volatile", "mutex", "_Atomic"
     49        );
     50}
     51
     52template<typename bits_t, size_t N>
     53void print( ostream & os, const bits_t & bits,
     54                const array<const char *, N> & names ) {
     55        if ( !bits.any() ) return;
     56        for ( size_t i = 0 ; i < N ; i += 1 ) {
     57                if ( bits[i] ) {
     58                        os << names[i] << ' ';
     59                }
     60        }
    3761}
    3862
     
    80104        static const char* Names[];
    81105
    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 
    119106        void print( const std::vector<ast::Label> & labels ) {
    120107                if ( labels.empty() ) return;
     
    230217                }
    231218
    232                 print( node->storage );
     219                ast::print( os, node->storage );
    233220                os << node->typeString();
    234221
     
    272259
    273260        void preprint( const ast::Type * node ) {
    274                 print( node->qualifiers );
     261                ast::print( os, node->qualifiers );
    275262        }
    276263
     
    278265                print( node->forall );
    279266                print( node->assertions );
    280                 print( node->qualifiers );
     267                ast::print( os, node->qualifiers );
    281268        }
    282269
    283270        void preprint( const ast::BaseInstType * node ) {
    284271                print( node->attributes );
    285                 print( node->qualifiers );
     272                ast::print( os, node->qualifiers );
    286273        }
    287274
     
    294281                }
    295282
    296                 print( node->storage );
     283                ast::print( os, node->storage );
    297284
    298285                if ( node->type ) {
     
    338325                if ( ! short_mode ) printAll( node->attributes );
    339326
    340                 print( node->storage );
    341                 print( node->funcSpec );
    342 
    343 
     327                ast::print( os, node->storage );
     328                ast::print( os, node->funcSpec );
    344329
    345330                if ( node->type && node->isTypeFixed ) {
     
    384369                                --indent;
    385370                        }
     371                }
     372
     373                if ( ! node->withExprs.empty() ) {
     374                        // Not with a clause, but the 'with clause'.
     375                        ++indent;
     376                        os << " with clause" << endl << indent;
     377                        printAll( node->withExprs );
     378                        --indent;
    386379                }
    387380
     
    746739        virtual const ast::Stmt * visit( const ast::SuspendStmt * node ) override final {
    747740                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;
     741                switch (node->kind) {
     742                case ast::SuspendStmt::None     : os << " with implicit target"; break;
     743                case ast::SuspendStmt::Generator: os << " for generator"; break;
     744                case ast::SuspendStmt::Coroutine: os << " for coroutine"; break;
    752745                }
    753746                os << endl;
     
    16271620};
    16281621
     1622} // namespace
     1623
    16291624void print( ostream & os, const ast::Node * node, Indenter indent ) {
    16301625        Printer printer { os, indent, false };
     
    16371632}
    16381633
    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;
     1634void print( ostream & os, Function::Specs specs ) {
     1635        print( os, specs, Names::FuncSpecifiers );
    16451636}
     1637
     1638void print( ostream & os, Storage::Classes storage ) {
     1639        print( os, storage, Names::StorageClasses );
     1640}
     1641
     1642void print( ostream & os, CV::Qualifiers qualifiers ) {
     1643        print( os, qualifiers, Names::Qualifiers );
     1644}
     1645
     1646} // namespace ast
  • src/AST/Print.hpp

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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 ); }
     
    394397};
    395398
     399// Clause in a waitfor statement: waitfor (..., ...) ...
    396400class WaitForClause final : public StmtClause {
    397401  public:
     
    454458        MUTATE_FRIEND
    455459};
     460
    456461} // namespace ast
    457462
  • src/AST/SymbolTable.cpp

    r2ed94a9 rb110bcc  
    7070        if ( baseExpr ) {
    7171                if (baseExpr->env) {
    72                         Expr * base = shallowCopy(baseExpr);
     72                        Expr * base = deepCopy(baseExpr);
    7373                        const TypeSubstitution * subs = baseExpr->env;
    7474                        base->env = nullptr;
     
    260260void SymbolTable::addId( const DeclWithType * decl, const Expr * baseExpr ) {
    261261        // default handling of conflicts is to raise an error
    262         addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
     262        addIdCommon( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
    263263}
    264264
    265265void SymbolTable::addDeletedId( const DeclWithType * decl, const Decl * deleter ) {
    266266        // default handling of conflicts is to raise an error
    267         addId( decl, OnConflict::error(), nullptr, deleter );
     267        addIdCommon( decl, OnConflict::error(), nullptr, deleter );
    268268}
    269269
     
    677677}
    678678
    679 void SymbolTable::addId(
    680                 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,
    681                 const Decl * deleter ) {
     679void SymbolTable::addIdCommon(
     680                const DeclWithType * decl, SymbolTable::OnConflict handleConflicts,
     681                const Expr * baseExpr, const Decl * deleter ) {
    682682        SpecialFunctionKind kind = getSpecialFunctionKind(decl->name);
    683683        if (kind == NUMBER_OF_KINDS) { // not a special decl
    684                 addId(decl, decl->name, idTable, handleConflicts, baseExpr, deleter);
     684                addIdToTable(decl, decl->name, idTable, handleConflicts, baseExpr, deleter);
    685685        }
    686686        else {
     
    695695                        assertf(false, "special decl with non-function type");
    696696                }
    697                 addId(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter);
    698         }
    699 }
    700 
    701 void SymbolTable::addId(
    702                 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,
    703                 const Decl * deleter ) {
     697                addIdToTable(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter);
     698        }
     699}
     700
     701void SymbolTable::addIdToTable(
     702                const DeclWithType * decl, const std::string & lookupKey,
     703                IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts,
     704                const Expr * baseExpr, const Decl * deleter ) {
    704705        ++*stats().add_calls;
    705706        const std::string &name = decl->name;
     
    778779void SymbolTable::addMembers(
    779780                const AggregateDecl * aggr, const Expr * expr, SymbolTable::OnConflict handleConflicts ) {
    780         for ( const Decl * decl : aggr->members ) {
    781                 if ( auto dwt = dynamic_cast< const DeclWithType * >( decl ) ) {
    782                         addId( dwt, handleConflicts, expr );
    783                         if ( dwt->name == "" ) {
    784                                 const Type * t = dwt->get_type()->stripReferences();
    785                                 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {
    786                                         if ( ! dynamic_cast<const StructInstType *>(rty)
    787                                                 && ! dynamic_cast<const UnionInstType *>(rty) ) continue;
    788                                         ResolvExpr::Cost cost = ResolvExpr::Cost::zero;
    789                                         ast::ptr<ast::TypeSubstitution> tmp = expr->env;
    790                                         expr = mutate_field(expr, &Expr::env, nullptr);
    791                                         const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost );
    792                                         base = mutate_field(base, &Expr::env, tmp);
    793 
    794                                         addMembers(
    795                                                 rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts );
    796                                 }
    797                         }
     781        for ( const ptr<Decl> & decl : aggr->members ) {
     782                auto dwt = decl.as<DeclWithType>();
     783                if ( nullptr == dwt ) continue;
     784                addIdCommon( dwt, handleConflicts, expr );
     785                // Inline through unnamed struct/union members.
     786                if ( "" != dwt->name ) continue;
     787                const Type * t = dwt->get_type()->stripReferences();
     788                if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {
     789                        if ( ! dynamic_cast<const StructInstType *>(rty)
     790                                && ! dynamic_cast<const UnionInstType *>(rty) ) continue;
     791                        ResolvExpr::Cost cost = ResolvExpr::Cost::zero;
     792                        ast::ptr<ast::TypeSubstitution> tmp = expr->env;
     793                        expr = mutate_field(expr, &Expr::env, nullptr);
     794                        const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost );
     795                        base = mutate_field(base, &Expr::env, tmp);
     796
     797                        addMembers(
     798                                rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts );
    798799                }
    799800        }
  • src/AST/SymbolTable.hpp

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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 {
     
    460457public:
    461458        std::vector<ptr<Type>> types;
    462         std::vector<ptr<Decl>> members;
    463459
    464460        TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} );
  • src/AST/porting.md

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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
  • src/Common/CodeLocationTools.cpp

    r2ed94a9 rb110bcc  
    208208
    209209struct LeafKindVisitor : public ast::Visitor {
    210         LeafKind kind;
     210        LeafKind result;
    211211
    212212#define VISIT(node_type, return_type) \
    213213        const ast::return_type * visit( const ast::node_type * ) final { \
    214                 kind = LeafKind::node_type; \
     214                result = LeafKind::node_type; \
    215215                return nullptr; \
    216216        }
     
    222222
    223223LeafKind get_leaf_kind( ast::Node const * node ) {
    224         LeafKindVisitor visitor;
    225         node->accept( visitor );
    226         return visitor.kind;
     224        return ast::Pass<LeafKindVisitor>::read( node );
    227225}
    228226
  • src/Common/DeclStats.cpp

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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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/SemanticError.h

    r2ed94a9 rb110bcc  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 10:59:10 2023
    13 // Update Count     : 36
     12// Last Modified On : Sat Feb 25 12:01:31 2023
     13// Update Count     : 37
    1414//
    1515
     
    5656        {"self-assign"              , Severity::Warn    , "self assignment of expression: %s"                          },
    5757        {"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"              },
     58        {"qualifiers-zero_t-one_t"  , Severity::Warn    , "questionable use of type qualifier(s) with %s"              },
    5959        {"aggregate-forward-decl"   , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
    6060        {"superfluous-decl"         , Severity::Warn    , "declaration does not allocate storage: %s"                  },
  • src/Common/module.mk

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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,
  • src/CompilationState.h

    r2ed94a9 rb110bcc  
    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,
  • src/Concurrency/Actors.cpp

    r2ed94a9 rb110bcc  
    4545    // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass
    4646    void previsit( const StructDecl * decl ) {
    47         GuardValue(insideStruct);
    48         insideStruct = true;
    49         parentDecl = mutate( decl );
    50         if( decl->name == "actor" ) *actorDecl = decl;
    51         if( decl->name == "message" ) *msgDecl = decl;
    52         if( decl->name == "request" ) *requestDecl = decl;
     47        if ( !decl->body ) return;
     48        if ( decl->name == "actor" ) {
     49            actorStructDecls.insert( decl ); // skip inserting fwd decl
     50            *actorDecl = decl;
     51        } else if( decl->name == "message" ) {
     52            messageStructDecls.insert( decl ); // skip inserting fwd decl
     53            *msgDecl = decl;
     54        } else if( decl->name == "request" ) *requestDecl = decl;
     55        else {
     56            GuardValue(insideStruct);
     57            insideStruct = true;
     58            parentDecl = mutate( decl );
     59        }
    5360        }
    5461
     
    6471    }
    6572
    66     // this collects the valid actor and message struct decl pts
     73    // this collects the derived actor and message struct decl ptrs
    6774    void postvisit( const StructInstType * node ) {
    6875        if ( ! *actorDecl || ! *msgDecl ) return;
    6976        if ( insideStruct && !namedDecl ) {
    70             if ( node->aggr() == *actorDecl ) {
     77            auto actorIter = actorStructDecls.find( node->aggr() );   
     78            if ( actorIter != actorStructDecls.end() ) {
    7179                actorStructDecls.insert( parentDecl );
    72             } else if ( node->aggr() == *msgDecl ) {
     80                return;
     81            }
     82            auto messageIter = messageStructDecls.find( node->aggr() );
     83            if ( messageIter != messageStructDecls.end() ) {
    7384                messageStructDecls.insert( parentDecl );
    7485            }
     
    180191};
    181192
    182 #define __ALLOC 0 // C_TODO: complete swap to no-alloc version
    183 
    184 struct GenReceiveDecls : public ast::WithDeclsToAdd<> {
     193// generates the definitions of send operators for actors
     194// collects data needed for next pass that does the circular defn resolution
     195//     for message send operators (via table above)
     196struct GenFuncsCreateTables : public ast::WithDeclsToAdd<> {
    185197    unordered_set<const StructDecl *> & actorStructDecls;
    186198    unordered_set<const StructDecl *>  & messageStructDecls;
     
    191203    FwdDeclTable & forwardDecls;
    192204
     205    // generates the operator for actor message sends
    193206        void postvisit( const FunctionDecl * decl ) {
    194207        // return if not of the form receive( param1, param2 ) or if it is a forward decl
     
    209222        auto messageIter = messageStructDecls.find( arg2InstType->aggr() );
    210223        if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) {
    211 
    212             // check that we have found all the decls we need from <actor.hfa>
    213             if ( !*allocationDecl || !*requestDecl )
    214                 SemanticError( decl->location, "using actors requires a header, add #include <actor.hfa>\n" );
    215 
    216224            //////////////////////////////////////////////////////////////////////
    217225            // The following generates this send message operator routine for all receive(derived_actor &, derived_msg &) functions
    218226            /*
    219227                static inline derived_actor & ?|?( derived_actor & receiver, derived_msg & msg ) {
    220                     request * new_req = alloc();
     228                    request new_req;
    221229                    Allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;
    222230                    __receive_fn fn = (__receive_fn)my_work_fn;
    223                     (*new_req){ &receiver, &msg, fn };
    224                     send( receiver, *new_req );
     231                    new_req{ &receiver, &msg, fn };
     232                    send( receiver, new_req );
    225233                    return receiver;
    226234                }
    227             */ // C_TODO: update this with new no alloc version
     235            */
    228236            CompoundStmt * sendBody = new CompoundStmt( decl->location );
    229237
    230             #if __ALLOC
    231             // Generates: request * new_req = alloc();
    232             sendBody->push_back( new DeclStmt(
    233                 decl->location,
    234                 new ObjectDecl(
    235                     decl->location,
    236                     "new_req",
    237                     new PointerType( new StructInstType( *requestDecl ) ),
    238                     new SingleInit( decl->location, new UntypedExpr( decl->location, new NameExpr( decl->location, "alloc" ), {} ) )
    239                 )
    240             ));
    241             #else
    242238            // Generates: request new_req;
    243239            sendBody->push_back( new DeclStmt(
     
    249245                )
    250246            ));
    251             #endif
    252247           
    253248            // Function type is: Allocation (*)( derived_actor &, derived_msg & )
     
    268263            ));
    269264
    270             // Function type is: Allocation (*)( actor &, messsage & )
     265            // Function type is: Allocation (*)( actor &, message & )
    271266            FunctionType * genericReceive = new FunctionType();
    272267            genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) );
     
    274269            genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) );
    275270
    276             // Generates: Allocation (*fn)( actor &, messsage & ) = (Allocation (*)( actor &, messsage & ))my_work_fn;
     271            // Generates: Allocation (*fn)( actor &, message & ) = (Allocation (*)( actor &, message & ))my_work_fn;
    277272            // More readable synonymous code:
    278273            //     typedef Allocation (*__receive_fn)(actor &, message &);
     
    290285            ));
    291286
    292             #if __ALLOC
    293             // Generates: (*new_req){ &receiver, &msg, fn };
    294             sendBody->push_back( new ExprStmt(
    295                 decl->location,
    296                                 new UntypedExpr (
    297                     decl->location,
    298                                         new NameExpr( decl->location, "?{}" ),
    299                                         {
    300                                                 new UntypedExpr( decl->location, new NameExpr( decl->location, "*?" ), {  new NameExpr( decl->location, "new_req" ) } ),
    301                         new AddressExpr( new NameExpr( decl->location, "receiver" ) ),
    302                         new AddressExpr( new NameExpr( decl->location, "msg" ) ),
    303                         new NameExpr( decl->location, "fn" )
    304                                         }
    305                                 )
    306                         ));
    307 
    308             // Generates: send( receiver, *new_req );
    309             sendBody->push_back( new ExprStmt(
    310                 decl->location,
    311                                 new UntypedExpr (
    312                     decl->location,
    313                                         new NameExpr( decl->location, "send" ),
    314                                         {
    315                                                 {
    316                             new NameExpr( decl->location, "receiver" ),
    317                             new UntypedExpr( decl->location, new NameExpr( decl->location, "*?" ), {  new NameExpr( decl->location, "new_req" ) } )
    318                         }
    319                                         }
    320                                 )
    321                         ));
    322             #else
    323287            // Generates: new_req{ &receiver, &msg, fn };
    324288            sendBody->push_back( new ExprStmt(
     
    350314                                )
    351315                        ));
    352             #endif
    353316           
    354317            // Generates: return receiver;
     
    358321            FunctionDecl * sendOperatorFunction = new FunctionDecl(
    359322                decl->location,
    360                 "?|?",
     323                "?<<?",
    361324                {},                     // forall
    362325                {
     
    388351            // forward decls to resolve use before decl problem for '|' routines
    389352            forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) );
    390             // forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );
    391353
    392354            sendOperatorFunction->stmts = sendBody;
     
    396358
    397359  public:
    398     GenReceiveDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     360    GenFuncsCreateTables( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    399361        const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl,
    400362        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
     
    402364};
    403365
    404 struct GenFwdDecls : public ast::WithDeclsToAdd<> {
     366
     367// separate pass is needed since this pass resolves circular defn issues
     368// generates the forward declarations of the send operator for actor routines
     369struct FwdDeclOperator : public ast::WithDeclsToAdd<> {
    405370    unordered_set<const StructDecl *> & actorStructDecls;
    406371    unordered_set<const StructDecl *>  & messageStructDecls;
    407372    FwdDeclTable & forwardDecls;
    408373
     374    // handles forward declaring the message operator
    409375    void postvisit( const StructDecl * decl ) {
    410376        list<FunctionDecl *> toAddAfter;
     
    433399
    434400  public:
    435     GenFwdDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
    436         FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls),
    437         forwardDecls(forwardDecls) {}
     401    FwdDeclOperator( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,
     402        FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), forwardDecls(forwardDecls) {}
    438403};
    439404
     
    461426    Pass<CollectactorStructDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,
    462427        allocationDecl, actorDecl, msgDecl );
    463        
     428
     429    // check that we have found all the decls we need from <actor.hfa>, if not no need to run the rest of this pass
     430    if ( !allocationDeclPtr || !requestDeclPtr || !actorDeclPtr || !msgDeclPtr )
     431        return;
     432
    464433    // second pass locates all receive() routines that overload the generic receive fn
    465434    // it then generates the appropriate operator '|' send routines for the receive routines
    466     Pass<GenReceiveDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,
     435    Pass<GenFuncsCreateTables>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,
    467436        allocationDecl, actorDecl, msgDecl, forwardDecls );
    468437
    469438    // The third pass forward declares operator '|' send routines
    470     Pass<GenFwdDecls>::run( translationUnit, actorStructDecls, messageStructDecls, forwardDecls );
     439    Pass<FwdDeclOperator>::run( translationUnit, actorStructDecls, messageStructDecls, forwardDecls );
    471440}
    472441
  • src/Concurrency/Actors.hpp

    r2ed94a9 rb110bcc  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Keywords.h -- Implement concurrency constructs from their keywords.
     7// Actors.hpp -- Implement concurrency constructs from their keywords.
    88//
    99// Author           : Colby Parsons
  • src/Concurrency/KeywordsNew.cpp

    r2ed94a9 rb110bcc  
    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/ControlStruct/ExceptDeclNew.cpp

    r2ed94a9 rb110bcc  
    1515
    1616#include "ExceptDecl.h"
     17
     18#include <sstream>
    1719
    1820#include "AST/Decl.hpp"
  • src/ControlStruct/ExceptTranslateNew.cpp

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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...
     
    8080                        CallAdapter();
    8181
     82                        void premutate( Declaration * declaration );
    8283                        void premutate( FunctionDecl * functionDecl );
    8384                        void premutate( TypeDecl * typeDecl );
     
    454455
    455456                CallAdapter::CallAdapter() : tempNamer( "_temp" ) {}
     457
     458                void CallAdapter::premutate( Declaration * ) {
     459                        // Prevent type declaration information from leaking out.
     460                        GuardScope( scopeTyVars );
     461                }
    456462
    457463                void CallAdapter::premutate( FunctionDecl *functionDecl ) {
  • src/GenPoly/FindFunction.cc

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    275275        }
    276276
     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}
     284
    277285        bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) {
    278286//              if ( ! adaptee->get_returnVals().empty() && isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
     
    319327                return 0;
    320328        }
     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}
    321340
    322341        Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) {
     
    796815        }
    797816
     817void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) {
     818        typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) );
     819}
     820
    798821void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ) {
    799         typeVars.insert( *type, ast::TypeData( type->base ) );
     822        typeVars.insert( ast::TypeEnvKey( *type ), ast::TypeData( type->base ) );
    800823}
    801824
     
    822845}
    823846
     847void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ) {
     848        for ( auto & typeDecl : decl->type_params ) {
     849                addToTypeVarMap( typeDecl, typeVars );
     850        }
     851}
     852
    824853        void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {
    825854                for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {
  • src/GenPoly/GenPoly.h

    r2ed94a9 rb110bcc  
    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/Lvalue.cc

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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
  • src/InitTweak/FixInit.cc

    r2ed94a9 rb110bcc  
    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
     
    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

    r2ed94a9 rb110bcc  
    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
     
    2834#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

    r2ed94a9 rb110bcc  
    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/Parser/DeclarationNode.cc

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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 ) {
    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::Type * targetType = maybeMoveBuildType( decl_node );
     605        if ( dynamic_cast<ast::VoidType *>( targetType ) ) {
    549606                delete targetType;
    550                 return new CastExpr( maybeMoveBuild< Expression >(expr_node), false );
     607                return new ast::CastExpr( location,
     608                        maybeMoveBuild( expr_node ),
     609                        ast::ExplicitCast );
    551610        } else {
    552                 return new CastExpr( maybeMoveBuild< Expression >(expr_node), targetType, false );
     611                return new ast::CastExpr( location,
     612                        maybeMoveBuild( expr_node ),
     613                        targetType,
     614                        ast::ExplicitCast );
    553615        } // if
    554616} // build_cast
    555617
    556 Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node ) {
    557         return new KeywordCastExpr( maybeMoveBuild< Expression >(expr_node), target );
     618ast::Expr * build_keyword_cast( const CodeLocation & location,
     619                ast::AggregateDecl::Aggregate target,
     620                ExpressionNode * expr_node ) {
     621        return new ast::KeywordCastExpr( location,
     622                maybeMoveBuild( expr_node ),
     623                target
     624        );
    558625}
    559626
    560 Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) {
    561         return new VirtualCastExpr( maybeMoveBuild< Expression >( expr_node ), maybeMoveBuildType( decl_node ) );
     627ast::Expr * build_virtual_cast( const CodeLocation & location,
     628                DeclarationNode * decl_node,
     629                ExpressionNode * expr_node ) {
     630        return new ast::VirtualCastExpr( location,
     631                maybeMoveBuild( expr_node ),
     632                maybeMoveBuildType( decl_node )
     633        );
    562634} // build_virtual_cast
    563635
    564 Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member ) {
    565         return new UntypedMemberExpr( member, maybeMoveBuild< Expression >(expr_node) );
     636ast::Expr * build_fieldSel( const CodeLocation & location,
     637                ExpressionNode * expr_node,
     638                ast::Expr * member ) {
     639        return new ast::UntypedMemberExpr( location,
     640                member,
     641                maybeMoveBuild( expr_node )
     642        );
    566643} // build_fieldSel
    567644
    568 Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member ) {
    569         UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) );
     645ast::Expr * build_pfieldSel( const CodeLocation & location,
     646                ExpressionNode * expr_node,
     647                ast::Expr * member ) {
     648        auto deref = new ast::UntypedExpr( location,
     649                new ast::NameExpr( location, "*?" )
     650        );
    570651        deref->location = expr_node->location;
    571         deref->get_args().push_back( maybeMoveBuild< Expression >(expr_node) );
    572         UntypedMemberExpr * ret = new UntypedMemberExpr( member, deref );
     652        deref->args.push_back( maybeMoveBuild( expr_node ) );
     653        auto ret = new ast::UntypedMemberExpr( location, member, deref );
    573654        return ret;
    574655} // build_pfieldSel
    575656
    576 Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member ) {
    577         Expression * ret = new UntypedOffsetofExpr( maybeMoveBuildType( decl_node ), member->get_name() );
     657ast::Expr * build_offsetOf( const CodeLocation & location,
     658                DeclarationNode * decl_node,
     659                ast::NameExpr * member ) {
     660        ast::Expr * ret = new ast::UntypedOffsetofExpr( location,
     661                maybeMoveBuildType( decl_node ),
     662                member->name
     663        );
     664        ret->result = new ast::BasicType( ast::BasicType::LongUnsignedInt );
    578665        delete member;
    579666        return ret;
    580667} // build_offsetOf
    581668
    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 );
     669ast::Expr * build_and_or( const CodeLocation & location,
     670                ExpressionNode * expr_node1,
     671                ExpressionNode * expr_node2,
     672                ast::LogicalFlag flag ) {
     673        return new ast::LogicalExpr( location,
     674                notZeroExpr( maybeMoveBuild( expr_node1 ) ),
     675                notZeroExpr( maybeMoveBuild( expr_node2 ) ),
     676                flag
     677        );
    584678} // build_and_or
    585679
    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 );
     680ast::Expr * build_unary_val( const CodeLocation & location,
     681                OperKinds op,
     682                ExpressionNode * expr_node ) {
     683        std::vector<ast::ptr<ast::Expr>> args;
     684        args.push_back( maybeMoveBuild( expr_node ) );
     685        return new ast::UntypedExpr( location,
     686                new ast::NameExpr( location, OperName[ (int)op ] ),
     687                std::move( args )
     688        );
    590689} // build_unary_val
    591690
    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 );
     691ast::Expr * build_binary_val( const CodeLocation & location,
     692                OperKinds op,
     693                ExpressionNode * expr_node1,
     694                ExpressionNode * expr_node2 ) {
     695        std::vector<ast::ptr<ast::Expr>> args;
     696        args.push_back( maybeMoveBuild( expr_node1 ) );
     697        args.push_back( maybeMoveBuild( expr_node2 ) );
     698        return new ast::UntypedExpr( location,
     699                new ast::NameExpr( location, OperName[ (int)op ] ),
     700                std::move( args )
     701        );
    603702} // build_binary_val
    604703
    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) );
     704ast::Expr * build_cond( const CodeLocation & location,
     705                ExpressionNode * expr_node1,
     706                ExpressionNode * expr_node2,
     707                ExpressionNode * expr_node3 ) {
     708        return new ast::ConditionalExpr( location,
     709                notZeroExpr( maybeMoveBuild( expr_node1 ) ),
     710                maybeMoveBuild( expr_node2 ),
     711                maybeMoveBuild( expr_node3 )
     712        );
    614713} // build_cond
    615714
    616 Expression * build_tuple( ExpressionNode * expr_node ) {
    617         list< Expression * > exprs;
     715ast::Expr * build_tuple( const CodeLocation & location,
     716                ExpressionNode * expr_node ) {
     717        std::vector<ast::ptr<ast::Expr>> exprs;
    618718        buildMoveList( expr_node, exprs );
    619         return new UntypedTupleExpr( exprs );;
     719        return new ast::UntypedTupleExpr( location, std::move( exprs ) );
    620720} // build_tuple
    621721
    622 Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node ) {
    623         list< Expression * > args;
     722ast::Expr * build_func( const CodeLocation & location,
     723                ExpressionNode * function,
     724                ExpressionNode * expr_node ) {
     725        std::vector<ast::ptr<ast::Expr>> args;
    624726        buildMoveList( expr_node, args );
    625         return new UntypedExpr( maybeMoveBuild< Expression >(function), args );
     727        return new ast::UntypedExpr( location,
     728                maybeMoveBuild( function ),
     729                std::move( args )
     730        );
    626731} // build_func
    627732
    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) );
     733ast::Expr * build_compoundLiteral( const CodeLocation & location,
     734                DeclarationNode * decl_node,
     735                InitializerNode * kids ) {
     736        // compound literal type
     737        ast::Decl * newDecl = maybeBuild( decl_node );
     738        // non-sue compound-literal type
     739        if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) {
     740                return new ast::CompoundLiteralExpr( location,
     741                        newDeclWithType->get_type(),
     742                        maybeMoveBuild( kids ) );
    632743        // 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) );
     744        } else if ( auto newDeclStructDecl = dynamic_cast<ast::StructDecl *>( newDecl ) ) {
     745                if ( newDeclStructDecl->body ) {
     746                        return new ast::CompoundLiteralExpr( location,
     747                                new ast::StructInstType( newDeclStructDecl ),
     748                                maybeMoveBuild( kids ) );
    636749                } 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) );
     750                        return new ast::CompoundLiteralExpr( location,
     751                                new ast::StructInstType( newDeclStructDecl->name ),
     752                                maybeMoveBuild( kids ) );
     753                } // if
     754        } else if ( auto newDeclUnionDecl = dynamic_cast<ast::UnionDecl *>( newDecl )  ) {
     755                if ( newDeclUnionDecl->body ) {
     756                        return new ast::CompoundLiteralExpr( location,
     757                                new ast::UnionInstType( newDeclUnionDecl ),
     758                                maybeMoveBuild( kids ) );
    642759                } 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) );
     760                        return new ast::CompoundLiteralExpr( location,
     761                                new ast::UnionInstType( newDeclUnionDecl->name ),
     762                                maybeMoveBuild( kids ) );
     763                } // if
     764        } else if ( auto newDeclEnumDecl = dynamic_cast<ast::EnumDecl *>( newDecl )  ) {
     765                if ( newDeclEnumDecl->body ) {
     766                        return new ast::CompoundLiteralExpr( location,
     767                                new ast::EnumInstType( newDeclEnumDecl ),
     768                                maybeMoveBuild( kids ) );
    648769                } else {
    649                         return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild< Initializer >(kids) );
     770                        return new ast::CompoundLiteralExpr( location,
     771                                new ast::EnumInstType( newDeclEnumDecl->name ),
     772                                maybeMoveBuild( kids ) );
    650773                } // if
    651774        } else {
     
    656779// Local Variables: //
    657780// tab-width: 4 //
    658 // mode: c++ //
    659 // compile-command: "make install" //
    660781// End: //
  • src/Parser/InitializerNode.cc

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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 );
    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

    r2ed94a9 rb110bcc  
    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/RunParser.cpp

    r2ed94a9 rb110bcc  
    1010// Created On       : Mon Dec 19 11:00:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Dec 22 10:18:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Mon Mar  6  9:42:00 2023
     13// Update Count     : 3
    1414//
    1515
     
    2020#include "CodeTools/TrackLoc.h"             // for fillLocations
    2121#include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
    22 #include "Parser/ParseNode.h"               // for DeclarationNode, buildList
     22#include "Parser/DeclarationNode.h"         // for DeclarationNode, buildList
    2323#include "Parser/TypedefTable.h"            // for TypedefTable
    2424
    2525// Variables global to the parsing code.
    26 LinkageSpec::Spec linkage = LinkageSpec::Cforall;
     26ast::Linkage::Spec linkage = ast::Linkage::Cforall;
    2727TypedefTable typedefTable;
    2828DeclarationNode * parseTree = nullptr;
    2929
    30 void parse( FILE * input, LinkageSpec::Spec linkage, bool alwaysExit ) {
     30void parse( FILE * input, ast::Linkage::Spec linkage, bool alwaysExit ) {
    3131        extern int yyparse( void );
    3232        extern FILE * yyin;
     
    4646
    4747ast::TranslationUnit buildUnit(void) {
    48         std::list<Declaration *> translationUnit;
    49         buildList( parseTree, translationUnit );
    50 
     48        std::vector<ast::ptr<ast::Decl>> decls;
     49        buildList( parseTree, decls );
    5150        delete parseTree;
    5251        parseTree = nullptr;
    5352
    54         // When the parse/buildList code is translated to the new ast, these
    55         // fill passes (and the one after 'Hoist Type Decls') should be redundent
    56         // because the code locations should already be filled.
    57         CodeTools::fillLocations( translationUnit );
    58         ast::TranslationUnit transUnit = convert( std::move( translationUnit ) );
    59         forceFillCodeLocations( transUnit );
     53        ast::TranslationUnit transUnit;
     54        for ( auto decl : decls ) {
     55                transUnit.decls.emplace_back( std::move( decl ) );
     56        }
    6057        return transUnit;
    6158}
  • src/Parser/RunParser.hpp

    r2ed94a9 rb110bcc  
    1010// Created On       : Mon Dec 19 10:42:00 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Thr Dec 22 10:23:00 2022
    13 // Update Count     : 1
     12// Last Modified On : Thr Feb 16 10:08:00 2023
     13// Update Count     : 2
    1414//
    1515
     
    1818#include <iosfwd>                           // for ostream
    1919
    20 #include "SynTree/LinkageSpec.h"            // for Spec
     20#include "AST/LinkageSpec.hpp"              // for Spec
    2121namespace ast {
    2222        class TranslationUnit;
     
    2929/// The input file is closed when complete. Exits instead of returning on
    3030/// error or if alwaysExit is true.
    31 void parse( FILE * input, LinkageSpec::Spec linkage, bool alwaysExit = false );
     31void parse( FILE * input, ast::Linkage::Spec linkage, bool alwaysExit = false );
    3232
    3333/// Drain the internal accumulator of parsed code and build a translation
  • src/Parser/StatementNode.cc

    r2ed94a9 rb110bcc  
    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_func = maybeBuild( targetExpr );
     331        clause->stmt = maybeMoveBuild( stmt );
     332        clause->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::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
     363        std::vector<ast::ptr<ast::Expr>> e;
    342364        buildMoveList( exprs, e );
    343         Statement * s = maybeMoveBuild<Statement>( stmt );
    344         return new DeclStmt( new WithStmt( e, s ) );
     365        ast::Stmt * s = maybeMoveBuild( stmt );
     366        return new ast::DeclStmt( location, new ast::WithStmt( location, std::move( e ), s ) );
    345367} // build_with
    346368
    347 Statement * build_compound( StatementNode * first ) {
    348         CompoundStmt * cs = new CompoundStmt();
    349         buildMoveList( first, cs->get_kids() );
     369ast::Stmt * build_compound( const CodeLocation & location, StatementNode * first ) {
     370        auto cs = new ast::CompoundStmt( location );
     371        buildMoveList( first, cs->kids );
    350372        return cs;
    351373} // build_compound
     
    355377// statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a
    356378// conical form for code generation.
    357 StatementNode * maybe_build_compound( StatementNode * first ) {
     379StatementNode * maybe_build_compound( const CodeLocation & location, StatementNode * first ) {
    358380        // Optimization: if the control-structure statement is a compound statement, do not wrap it.
    359381        // 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 );
     382        if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr
     383                return new StatementNode( build_compound( location, first ) );
    364384        } // if
    365385        return first;
     
    367387
    368388// 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;
     389ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
     390        std::vector<ast::ptr<ast::Expr>> out, in;
     391        std::vector<ast::ptr<ast::ConstantExpr>> clob;
    372392
    373393        buildMoveList( output, out );
    374394        buildMoveList( input, in );
    375395        buildMoveList( clobber, clob );
    376         return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels );
     396        return new ast::AsmStmt( location,
     397                is_volatile,
     398                maybeMoveBuild( instruction ),
     399                std::move( out ),
     400                std::move( in ),
     401                std::move( clob ),
     402                gotolabels ? gotolabels->labels : std::vector<ast::Label>()
     403        );
    377404} // build_asm
    378405
    379 Statement * build_directive( string * directive ) {
    380         return new DirectiveStmt( *directive );
     406ast::Stmt * build_directive( const CodeLocation & location, string * directive ) {
     407        auto stmt = new ast::DirectiveStmt( location, *directive );
     408        delete directive;
     409        return stmt;
    381410} // build_directive
    382411
    383 Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt ) {
    384         list< Expression * > expList;
     412ast::Stmt * build_mutex( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) {
     413        std::vector<ast::ptr<ast::Expr>> expList;
    385414        buildMoveList( exprs, expList );
    386         Statement * body = maybeMoveBuild<Statement>( stmt );
    387         return new MutexStmt( body, expList );
     415        ast::Stmt * body = maybeMoveBuild( stmt );
     416        return new ast::MutexStmt( location, body, std::move( expList ) );
    388417} // build_mutex
    389418
  • src/Parser/TypeData.cc

    r2ed94a9 rb110bcc  
    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)->isInteger())) {
     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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    1010 * Created On       : Sat Sep 22 08:58:10 2001
    1111 * Last Modified By : Peter A. Buhr
    12  * Last Modified On : Mon Jan 30 19:03:34 2023
    13  * Update Count     : 767
     12 * Last Modified On : Sat Mar 25 08:09:03 2023
     13 * Update Count     : 768
    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
  • src/Parser/module.mk

    r2ed94a9 rb110bcc  
    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 \
     
    3336       Parser/RunParser.hpp \
    3437       Parser/StatementNode.cc \
     38       Parser/StatementNode.h \
    3539       Parser/TypeData.cc \
    3640       Parser/TypeData.h \
  • src/Parser/parser.yy

    r2ed94a9 rb110bcc  
    99// Author           : Peter A. Buhr
    1010// Created On       : Sat Sep  1 20:22:55 2001
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 21:36:16 2023
    13 // Update Count     : 5865
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Tue Apr  4 14:02:00 2023
     13// Update Count     : 6329
    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;
    291309        CondCtl * ifctl;
    292         ForCtrl * fctl;
    293         OperKinds compop;
    294         LabelNode * label;
    295         InitializerNode * in;
    296         OperKinds op;
     310        ForCtrl * forctl;
     311        LabelNode * labels;
     312        InitializerNode * init;
     313        OperKinds oper;
    297314        std::string * str;
    298         bool flag;
    299         EnumHiding hide;
    300         CatchStmt::Kind catch_kind;
    301         GenericExpr * genexpr;
     315        bool is_volatile;
     316        EnumHiding enum_hiding;
     317        ast::ExceptionKind except_kind;
     318        ast::GenericExpr * genexpr;
    302319}
    303320
    304 //************************* TERMINAL TOKENS ********************************
     321// ************************ TERMINAL TOKENS ********************************
    305322
    306323// keywords
     
    337354
    338355// 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
     356%token<tok> IDENTIFIER          TYPEDIMname             TYPEDEFname             TYPEGENname
     357%token<tok> TIMEOUT                     WAND    WOR                     CATCH                   RECOVER                 CATCHRESUME             FIXUP           FINALLY         // CFA
    341358%token<tok> INTEGERconstant     CHARACTERconstant       STRINGliteral
    342359%token<tok> DIRECTIVE
     
    364381%type<tok> identifier                                   identifier_at                           identifier_or_type_name         attr_name
    365382%type<tok> quasi_keyword
    366 %type<constant> string_literal
     383%type<expr> string_literal
    367384%type<str> string_literal_list
    368385
    369 %type<hide> hide_opt                                    visible_hide_opt
     386%type<enum_hiding> hide_opt                                     visible_hide_opt
    370387
    371388// 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
     389%type<expr> constant
     390%type<expr> tuple                                                       tuple_expression_list
     391%type<oper> ptrref_operator                             unary_operator                          assignment_operator                     simple_assignment_operator      compound_assignment_operator
     392%type<expr> primary_expression                  postfix_expression                      unary_expression
     393%type<expr> cast_expression_list                        cast_expression                         exponential_expression          multiplicative_expression       additive_expression
     394%type<expr> shift_expression                            relational_expression           equality_expression
     395%type<expr> AND_expression                              exclusive_OR_expression         inclusive_OR_expression
     396%type<expr> logical_AND_expression              logical_OR_expression
     397%type<expr> conditional_expression              constant_expression                     assignment_expression           assignment_expression_opt
     398%type<expr> comma_expression                            comma_expression_opt
     399%type<expr> argument_expression_list_opt        argument_expression_list        argument_expression                     default_initializer_opt
    383400%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
     401%type<forctl> for_control_expression            for_control_expression_list
     402%type<oper> upupeq updown updowneq downupdowneq
     403%type<expr> subrange
    387404%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
     405%type<expr> asm_operands_opt                            asm_operands_list                       asm_operand
     406%type<labels> label_list
     407%type<expr> asm_clobbers_list_opt
     408%type<is_volatile> asm_volatile_opt
     409%type<expr> handler_predicate_opt
    393410%type<genexpr> generic_association              generic_assoc_list
    394411
    395412// 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
     413%type<stmt> statement                                           labeled_statement                       compound_statement
     414%type<stmt> statement_decl                              statement_decl_list                     statement_list_nodecl
     415%type<stmt> selection_statement                 if_statement
     416%type<clause> switch_clause_list_opt            switch_clause_list
     417%type<expr> case_value
     418%type<clause> case_clause                               case_value_list                         case_label                                      case_label_list
     419%type<stmt> iteration_statement                 jump_statement
     420%type<stmt> expression_statement                        asm_statement
     421%type<stmt> with_statement
     422%type<expr> with_clause_opt
     423%type<stmt> exception_statement
     424%type<clause> handler_clause                    finally_clause
     425%type<except_kind> handler_key
     426%type<stmt> mutex_statement
     427%type<expr> when_clause                                 when_clause_opt                         waitfor         waituntil               timeout
     428%type<stmt> waitfor_statement                           waituntil_statement
     429%type<wfs> wor_waitfor_clause                   waituntil_clause                        wand_waituntil_clause   wor_waituntil_clause
    412430
    413431// declarations
     
    421439%type<decl> assertion assertion_list assertion_list_opt
    422440
    423 %type<en> bit_subrange_size_opt bit_subrange_size
     441%type<expr> bit_subrange_size_opt bit_subrange_size
    424442
    425443%type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type
     
    434452
    435453%type<decl> enumerator_list enum_type enum_type_nobody
    436 %type<in> enumerator_value_opt
     454%type<init> enumerator_value_opt
    437455
    438456%type<decl> external_definition external_definition_list external_definition_list_opt
     
    441459
    442460%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
     461%type<expr> field field_name_list field_name fraction_constants_opt
    444462
    445463%type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr
     
    482500%type<decl> typedef_name typedef_declaration typedef_expression
    483501
    484 %type<decl> variable_type_redeclarator type_ptr type_array type_function
     502%type<decl> variable_type_redeclarator variable_type_ptr variable_type_array variable_type_function
     503%type<decl> general_function_declarator function_type_redeclarator function_type_array function_type_no_ptr function_type_ptr
    485504
    486505%type<decl> type_parameter_redeclarator type_parameter_ptr type_parameter_array type_parameter_function
     
    489508%type<decl> type_parameter type_parameter_list type_initializer_opt
    490509
    491 %type<en> type_parameters_opt type_list array_type_list
     510%type<expr> type_parameters_opt type_list array_type_list
    492511
    493512%type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list
     
    500519
    501520// initializers
    502 %type<in>  initializer initializer_list_opt initializer_opt
     521%type<init>  initializer initializer_list_opt initializer_opt
    503522
    504523// designators
    505 %type<en>  designator designator_list designation
     524%type<expr>  designator designator_list designation
    506525
    507526
     
    512531// Similar issues exit with the waitfor statement.
    513532
    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.
     533// Order of these lines matters (low-to-high precedence). THEN is left associative over WAND/WOR/TIMEOUT/ELSE, WAND/WOR
     534// is left associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.
    516535%precedence THEN                // rule precedence for IF/WAITFOR statement
     536%precedence ANDAND              // token precedence for start of WAND in WAITFOR statement
     537%precedence WAND                // token precedence for start of WAND in WAITFOR statement
     538%precedence OROR                // token precedence for start of WOR in WAITFOR statement
    517539%precedence WOR                 // token precedence for start of WOR in WAITFOR statement
    518540%precedence TIMEOUT             // token precedence for start of TIMEOUT in WAITFOR statement
     
    592614constant:
    593615                // 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 ) ); }
     616        INTEGERconstant                                                         { $$ = new ExpressionNode( build_constantInteger( yylloc, *$1 ) ); }
     617        | FLOATING_DECIMALconstant                                      { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
     618        | FLOATING_FRACTIONconstant                                     { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
     619        | FLOATINGconstant                                                      { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); }
     620        | CHARACTERconstant                                                     { $$ = new ExpressionNode( build_constantChar( yylloc, *$1 ) ); }
    599621        ;
    600622
    601623quasi_keyword:                                                                                  // CFA
    602624        TIMEOUT
     625        | WAND
    603626        | WOR
    604627        | CATCH
     
    621644
    622645string_literal:
    623         string_literal_list                                                     { $$ = build_constantStr( *$1 ); }
     646        string_literal_list                                                     { $$ = new ExpressionNode( build_constantStr( yylloc, *$1 ) ); }
    624647        ;
    625648
     
    638661primary_expression:
    639662        IDENTIFIER                                                                                      // typedef name cannot be used as a variable name
    640                 { $$ = new ExpressionNode( build_varref( $1 ) ); }
     663                { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
    641664        | quasi_keyword
    642                 { $$ = new ExpressionNode( build_varref( $1 ) ); }
     665                { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
    643666        | TYPEDIMname                                                                           // CFA, generic length argument
    644667                // { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( DeclarationNode::newFromTypedef( $1 ) ) ) ); }
    645668                // { $$ = new ExpressionNode( build_varref( $1 ) ); }
    646                 { $$ = new ExpressionNode( build_dimensionref( $1 ) ); }
     669                { $$ = new ExpressionNode( build_dimensionref( yylloc, $1 ) ); }
    647670        | tuple
    648671        | '(' comma_expression ')'
    649672                { $$ = $2; }
    650673        | '(' compound_statement ')'                                            // GCC, lambda expression
    651                 { $$ = new ExpressionNode( new StmtExpr( dynamic_cast<CompoundStmt *>(maybeMoveBuild<Statement>($2) ) ) ); }
     674                { $$ = new ExpressionNode( new ast::StmtExpr( yylloc, dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( $2 ) ) ) ); }
    652675        | type_name '.' identifier                                                      // CFA, nested type
    653                 { $$ = new ExpressionNode( build_qualified_expr( $1, build_varref( $3 ) ) ); }
     676                { $$ = new ExpressionNode( build_qualified_expr( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
    654677        | type_name '.' '[' field_name_list ']'                         // CFA, nested type / tuple field selector
    655678                { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; }
     
    657680                {
    658681                        // add the missing control expression to the GenericExpr and return it
    659                         $5->control = maybeMoveBuild<Expression>( $3 );
     682                        $5->control = maybeMoveBuild( $3 );
    660683                        $$ = new ExpressionNode( $5 );
    661684                }
     
    683706                {
    684707                        // steal the association node from the singleton and delete the wrapper
    685                         $1->associations.splice($1->associations.end(), $3->associations);
     708                        assert( 1 == $3->associations.size() );
     709                        $1->associations.push_back( $3->associations.front() );
    686710                        delete $3;
    687711                        $$ = $1;
     
    693717                {
    694718                        // create a GenericExpr wrapper with one association pair
    695                         $$ = new GenericExpr( nullptr, { { maybeMoveBuildType($1), maybeMoveBuild<Expression>( $3 ) } } );
     719                        $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuildType( $1 ), maybeMoveBuild( $3 ) } } );
    696720                }
    697721        | DEFAULT ':' assignment_expression
    698                 { $$ = new GenericExpr( nullptr, { { maybeMoveBuild<Expression>( $3 ) } } ); }
     722                { $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuild( $3 ) } } ); }
    699723        ;
    700724
     
    705729                // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts.
    706730                // Current: Commas in subscripts make tuples.
    707                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
     731                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
    708732        | postfix_expression '[' assignment_expression ']'
    709733                // CFA, comma_expression disallowed in this context because it results in a common user error: subscripting a
     
    711735                // little advantage to this feature and many disadvantages. It is possible to write x[(i,j)] in CFA, which is
    712736                // equivalent to the old x[i,j].
    713                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
     737                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
    714738        | constant '[' assignment_expression ']'                        // 3[a], 'a'[a], 3.5[a]
    715                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
     739                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
    716740        | string_literal '[' assignment_expression ']'          // "abc"[3], 3["abc"]
    717                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); }
     741                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); }
    718742        | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call
    719743                {
    720744                        Token fn;
    721745                        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 ) ) ) );
     746                        $$ = new ExpressionNode( new ast::ConstructorExpr( yylloc, build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );
    723747                }
    724748        | postfix_expression '(' argument_expression_list_opt ')'
    725                 { $$ = new ExpressionNode( build_func( $1, $3 ) ); }
     749                { $$ = new ExpressionNode( build_func( yylloc, $1, $3 ) ); }
    726750        | VA_ARG '(' primary_expression ',' declaration_specifier_nobody abstract_parameter_declarator_opt ')'
    727751                // { SemanticError( yylloc, "va_arg is currently unimplemented." ); $$ = nullptr; }
    728                 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( new string( "__builtin_va_arg") ) ),
     752                { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, new string( "__builtin_va_arg") ) ),
    729753                                                                                           (ExpressionNode *)($3->set_last( (ExpressionNode *)($6 ? $6->addType( $5 ) : $5) )) ) ); }
    730754        | postfix_expression '`' identifier                                     // CFA, postfix call
    731                 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), $1 ) ); }
     755                { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
    732756        | constant '`' identifier                                                       // CFA, postfix call
    733                 { $$ = 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 ) ); }
    734758        | string_literal '`' identifier                                         // CFA, postfix call
    735                 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), new ExpressionNode( $1 ) ) ); }
     759                { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); }
    736760        | postfix_expression '.' identifier
    737                 { $$ = new ExpressionNode( build_fieldSel( $1, build_varref( $3 ) ) ); }
     761                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
    738762        | postfix_expression '.' INTEGERconstant                        // CFA, tuple index
    739                 { $$ = new ExpressionNode( build_fieldSel( $1, build_constantInteger( *$3 ) ) ); }
     763                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); }
    740764        | postfix_expression FLOATING_FRACTIONconstant          // CFA, tuple index
    741                 { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant( *$2 ) ) ); }
     765                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 ) ) ); }
    742766        | postfix_expression '.' '[' field_name_list ']'        // CFA, tuple field selector
    743                 { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
     767                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
    744768        | postfix_expression '.' aggregate_control
    745                 { $$ = new ExpressionNode( build_keyword_cast( $3, $1 ) ); }
     769                { $$ = new ExpressionNode( build_keyword_cast( yylloc, $3, $1 ) ); }
    746770        | postfix_expression ARROW identifier
    747                 { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref( $3 ) ) ); }
     771                { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); }
    748772        | postfix_expression ARROW INTEGERconstant                      // CFA, tuple index
    749                 { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger( *$3 ) ) ); }
     773                { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); }
    750774        | postfix_expression ARROW '[' field_name_list ']'      // CFA, tuple field selector
    751                 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
     775                { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
    752776        | postfix_expression ICR
    753                 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::IncrPost, $1 ) ); }
     777                { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::IncrPost, $1 ) ); }
    754778        | postfix_expression DECR
    755                 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::DecrPost, $1 ) ); }
     779                { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::DecrPost, $1 ) ); }
    756780        | '(' type_no_function ')' '{' initializer_list_opt comma_opt '}' // C99, compound-literal
    757                 { $$ = new ExpressionNode( build_compoundLiteral( $2, new InitializerNode( $5, true ) ) ); }
     781                { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, new InitializerNode( $5, true ) ) ); }
    758782        | '(' 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 ) ) ); }
     783                { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }
    760784        | '^' primary_expression '{' argument_expression_list_opt '}' // CFA, destructor call
    761785                {
    762786                        Token fn;
    763787                        fn.str = new string( "^?{}" );                          // location undefined
    764                         $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );
     788                        $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );
    765789                }
    766790        ;
     
    781805        '@'                                                                                                     // CFA, default parameter
    782806                { SemanticError( yylloc, "Default parameter for argument is currently unimplemented." ); $$ = nullptr; }
    783                 // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
     807                // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
    784808        | assignment_expression
    785809        ;
     
    793817        field_name
    794818        | FLOATING_DECIMALconstant field
    795                 { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), maybeMoveBuild<Expression>( $2 ) ) ); }
     819                { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), maybeMoveBuild( $2 ) ) ); }
    796820        | FLOATING_DECIMALconstant '[' field_name_list ']'
    797                 { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), build_tuple( $3 ) ) ); }
     821                { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), build_tuple( yylloc, $3 ) ) ); }
    798822        | field_name '.' field
    799                 { $$ = new ExpressionNode( build_fieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
     823                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }
    800824        | field_name '.' '[' field_name_list ']'
    801                 { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple( $4 ) ) ); }
     825                { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
    802826        | field_name ARROW field
    803                 { $$ = new ExpressionNode( build_pfieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }
     827                { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); }
    804828        | field_name ARROW '[' field_name_list ']'
    805                 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
     829                { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); }
    806830        ;
    807831
    808832field_name:
    809833        INTEGERconstant fraction_constants_opt
    810                 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_constantInteger( *$1 ), $2 ) ); }
     834                { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_constantInteger( yylloc, *$1 ), $2 ) ); }
    811835        | FLOATINGconstant fraction_constants_opt
    812                 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant( *$1 ), $2 ) ); }
     836                { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_field_name_FLOATINGconstant( yylloc, *$1 ), $2 ) ); }
    813837        | identifier_at fraction_constants_opt                          // CFA, allow anonymous fields
    814838                {
    815                         $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref( $1 ), $2 ) );
     839                        $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_varref( yylloc, $1 ), $2 ) );
    816840                }
    817841        ;
     
    822846        | fraction_constants_opt FLOATING_FRACTIONconstant
    823847                {
    824                         Expression * constant = build_field_name_FLOATING_FRACTIONconstant( *$2 );
    825                         $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( $1, constant ) ) : new ExpressionNode( constant );
     848                        ast::Expr * constant = build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 );
     849                        $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( yylloc, $1, constant ) ) : new ExpressionNode( constant );
    826850                }
    827851        ;
     
    833857        | constant
    834858        | string_literal
    835                 { $$ = new ExpressionNode( $1 ); }
     859                { $$ = $1; }
    836860        | EXTENSION cast_expression                                                     // GCC
    837861                { $$ = $2->set_extension( true ); }
     
    842866                {
    843867                        switch ( $1 ) {
    844                           case OperKinds::AddressOf:
    845                                 $$ = new ExpressionNode( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) );
     868                        case OperKinds::AddressOf:
     869                                $$ = new ExpressionNode( new ast::AddressExpr( maybeMoveBuild( $2 ) ) );
    846870                                break;
    847                           case OperKinds::PointTo:
    848                                 $$ = new ExpressionNode( build_unary_val( $1, $2 ) );
     871                        case OperKinds::PointTo:
     872                                $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) );
    849873                                break;
    850                           case OperKinds::And:
    851                                 $$ = new ExpressionNode( new AddressExpr( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) ) );
     874                        case OperKinds::And:
     875                                $$ = new ExpressionNode( new ast::AddressExpr( new ast::AddressExpr( maybeMoveBuild( $2 ) ) ) );
    852876                                break;
    853                           default:
     877                        default:
    854878                                assert( false );
    855879                        }
    856880                }
    857881        | unary_operator cast_expression
    858                 { $$ = new ExpressionNode( build_unary_val( $1, $2 ) ); }
     882                { $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) ); }
    859883        | ICR unary_expression
    860                 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::Incr, $2 ) ); }
     884                { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Incr, $2 ) ); }
    861885        | DECR unary_expression
    862                 { $$ = new ExpressionNode( build_unary_ptr( OperKinds::Decr, $2 ) ); }
     886                { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Decr, $2 ) ); }
    863887        | SIZEOF unary_expression
    864                 { $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuild<Expression>( $2 ) ) ); }
     888                { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
    865889        | SIZEOF '(' type_no_function ')'
    866                 { $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuildType( $3 ) ) ); }
     890                { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
    867891        | ALIGNOF unary_expression                                                      // GCC, variable alignment
    868                 { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuild<Expression>( $2 ) ) ); }
     892                { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
    869893        | ALIGNOF '(' type_no_function ')'                                      // GCC, type alignment
    870                 { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuildType( $3 ) ) ); }
     894                { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
    871895        | OFFSETOF '(' type_no_function ',' identifier ')'
    872                 { $$ = new ExpressionNode( build_offsetOf( $3, build_varref( $5 ) ) ); }
     896                { $$ = new ExpressionNode( build_offsetOf( yylloc, $3, build_varref( yylloc, $5 ) ) ); }
    873897        | TYPEID '(' type_no_function ')'
    874898                {
     
    895919        unary_expression
    896920        | '(' type_no_function ')' cast_expression
    897                 { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
     921                { $$ = new ExpressionNode( build_cast( yylloc, $2, $4 ) ); }
    898922        | '(' aggregate_control '&' ')' cast_expression         // CFA
    899                 { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
     923                { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); }
    900924        | '(' aggregate_control '*' ')' cast_expression         // CFA
    901                 { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }
     925                { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); }
    902926        | '(' VIRTUAL ')' cast_expression                                       // CFA
    903                 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $4 ), maybeMoveBuildType( nullptr ) ) ); }
     927                { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $4 ), maybeMoveBuildType( nullptr ) ) ); }
    904928        | '(' VIRTUAL type_no_function ')' cast_expression      // CFA
    905                 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $5 ), maybeMoveBuildType( $3 ) ) ); }
     929                { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); }
    906930        | '(' RETURN type_no_function ')' cast_expression       // CFA
    907931                { SemanticError( yylloc, "Return cast is currently unimplemented." ); $$ = nullptr; }
     
    911935                { SemanticError( yylloc, "Qualifier cast is currently unimplemented." ); $$ = nullptr; }
    912936//      | '(' type_no_function ')' tuple
    913 //              { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }
     937//              { $$ = new ast::ExpressionNode( build_cast( yylloc, $2, $4 ) ); }
    914938        ;
    915939
     
    929953        cast_expression
    930954        | exponential_expression '\\' cast_expression
    931                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Exp, $1, $3 ) ); }
     955                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Exp, $1, $3 ) ); }
    932956        ;
    933957
     
    935959        exponential_expression
    936960        | multiplicative_expression '*' exponential_expression
    937                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Mul, $1, $3 ) ); }
     961                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mul, $1, $3 ) ); }
    938962        | multiplicative_expression '/' exponential_expression
    939                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Div, $1, $3 ) ); }
     963                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Div, $1, $3 ) ); }
    940964        | multiplicative_expression '%' exponential_expression
    941                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Mod, $1, $3 ) ); }
     965                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mod, $1, $3 ) ); }
    942966        ;
    943967
     
    945969        multiplicative_expression
    946970        | additive_expression '+' multiplicative_expression
    947                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Plus, $1, $3 ) ); }
     971                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Plus, $1, $3 ) ); }
    948972        | additive_expression '-' multiplicative_expression
    949                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Minus, $1, $3 ) ); }
     973                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Minus, $1, $3 ) ); }
    950974        ;
    951975
     
    953977        additive_expression
    954978        | shift_expression LS additive_expression
    955                 { $$ = new ExpressionNode( build_binary_val( OperKinds::LShift, $1, $3 ) ); }
     979                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LShift, $1, $3 ) ); }
    956980        | shift_expression RS additive_expression
    957                 { $$ = new ExpressionNode( build_binary_val( OperKinds::RShift, $1, $3 ) ); }
     981                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::RShift, $1, $3 ) ); }
    958982        ;
    959983
     
    961985        shift_expression
    962986        | relational_expression '<' shift_expression
    963                 { $$ = new ExpressionNode( build_binary_val( OperKinds::LThan, $1, $3 ) ); }
     987                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LThan, $1, $3 ) ); }
    964988        | relational_expression '>' shift_expression
    965                 { $$ = new ExpressionNode( build_binary_val( OperKinds::GThan, $1, $3 ) ); }
     989                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GThan, $1, $3 ) ); }
    966990        | relational_expression LE shift_expression
    967                 { $$ = new ExpressionNode( build_binary_val( OperKinds::LEThan, $1, $3 ) ); }
     991                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LEThan, $1, $3 ) ); }
    968992        | relational_expression GE shift_expression
    969                 { $$ = new ExpressionNode( build_binary_val( OperKinds::GEThan, $1, $3 ) ); }
     993                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GEThan, $1, $3 ) ); }
    970994        ;
    971995
     
    973997        relational_expression
    974998        | equality_expression EQ relational_expression
    975                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Eq, $1, $3 ) ); }
     999                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Eq, $1, $3 ) ); }
    9761000        | equality_expression NE relational_expression
    977                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Neq, $1, $3 ) ); }
     1001                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Neq, $1, $3 ) ); }
    9781002        ;
    9791003
     
    9811005        equality_expression
    9821006        | AND_expression '&' equality_expression
    983                 { $$ = new ExpressionNode( build_binary_val( OperKinds::BitAnd, $1, $3 ) ); }
     1007                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitAnd, $1, $3 ) ); }
    9841008        ;
    9851009
     
    9871011        AND_expression
    9881012        | exclusive_OR_expression '^' AND_expression
    989                 { $$ = new ExpressionNode( build_binary_val( OperKinds::Xor, $1, $3 ) ); }
     1013                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Xor, $1, $3 ) ); }
    9901014        ;
    9911015
     
    9931017        exclusive_OR_expression
    9941018        | inclusive_OR_expression '|' exclusive_OR_expression
    995                 { $$ = new ExpressionNode( build_binary_val( OperKinds::BitOr, $1, $3 ) ); }
     1019                { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitOr, $1, $3 ) ); }
    9961020        ;
    9971021
     
    9991023        inclusive_OR_expression
    10001024        | logical_AND_expression ANDAND inclusive_OR_expression
    1001                 { $$ = new ExpressionNode( build_and_or( $1, $3, true ) ); }
     1025                { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::AndExpr ) ); }
    10021026        ;
    10031027
     
    10051029        logical_AND_expression
    10061030        | logical_OR_expression OROR logical_AND_expression
    1007                 { $$ = new ExpressionNode( build_and_or( $1, $3, false ) ); }
     1031                { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::OrExpr ) ); }
    10081032        ;
    10091033
     
    10111035        logical_OR_expression
    10121036        | logical_OR_expression '?' comma_expression ':' conditional_expression
    1013                 { $$ = new ExpressionNode( build_cond( $1, $3, $5 ) ); }
     1037                { $$ = new ExpressionNode( build_cond( yylloc, $1, $3, $5 ) ); }
    10141038                // FIX ME: computes $1 twice
    10151039        | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand
    1016                 { $$ = new ExpressionNode( build_cond( $1, $1, $4 ) ); }
     1040                { $$ = new ExpressionNode( build_cond( yylloc, $1, $1, $4 ) ); }
    10171041        ;
    10181042
     
    10291053//                              SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr;
    10301054//                      } else {
    1031                                 $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) );
     1055                                $$ = new ExpressionNode( build_binary_val( yylloc, $2, $1, $3 ) );
    10321056//                      } // if
    10331057                }
     
    10741098//              { $$ = new ExpressionNode( build_tuple( $3 ) ); }
    10751099        '[' ',' tuple_expression_list ']'
    1076                 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }
     1100                { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }
    10771101        | '[' push assignment_expression pop ',' tuple_expression_list ']'
    1078                 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $6 ) ) )); }
     1102                { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $6 ) ) )); }
    10791103        ;
    10801104
     
    10921116        assignment_expression
    10931117        | comma_expression ',' assignment_expression
    1094                 { $$ = new ExpressionNode( new CommaExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }
     1118                { $$ = new ExpressionNode( new ast::CommaExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
    10951119        ;
    10961120
     
    11131137        | mutex_statement
    11141138        | waitfor_statement
     1139        | waituntil_statement
    11151140        | exception_statement
    11161141        | enable_disable_statement
     
    11181143        | asm_statement
    11191144        | DIRECTIVE
    1120                 { $$ = new StatementNode( build_directive( $1 ) ); }
     1145                { $$ = new StatementNode( build_directive( yylloc, $1 ) ); }
    11211146        ;
    11221147
     
    11241149                // labels cannot be identifiers 0 or 1
    11251150        identifier_or_type_name ':' attribute_list_opt statement
    1126                 { $$ = $4->add_label( $1, $3 ); }
     1151                { $$ = $4->add_label( yylloc, $1, $3 ); }
    11271152        | identifier_or_type_name ':' attribute_list_opt error // syntax error
    11281153                {
     
    11361161compound_statement:
    11371162        '{' '}'
    1138                 { $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); }
     1163                { $$ = new StatementNode( build_compound( yylloc, (StatementNode *)0 ) ); }
    11391164        | '{' push
    11401165          local_label_declaration_opt                                           // GCC, local labels appear at start of block
    11411166          statement_decl_list                                                           // C99, intermix declarations and statements
    11421167          pop '}'
    1143                 { $$ = new StatementNode( build_compound( $4 ) ); }
     1168                { $$ = new StatementNode( build_compound( yylloc, $4 ) ); }
    11441169        ;
    11451170
     
    11721197expression_statement:
    11731198        comma_expression_opt ';'
    1174                 { $$ = new StatementNode( build_expr( $1 ) ); }
    1175         | MUTEX '(' ')' comma_expression ';'
    1176                 { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); }
     1199                { $$ = new StatementNode( build_expr( yylloc, $1 ) ); }
    11771200        ;
    11781201
     
    11831206                { $$ = $2; }
    11841207        | SWITCH '(' comma_expression ')' case_clause
    1185                 { $$ = new StatementNode( build_switch( true, $3, $5 ) ); }
     1208                { $$ = new StatementNode( build_switch( yylloc, true, $3, $5 ) ); }
    11861209        | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
    11871210                {
    1188                         StatementNode *sw = new StatementNode( build_switch( true, $3, $8 ) );
     1211                        StatementNode *sw = new StatementNode( build_switch( yylloc, true, $3, $8 ) );
    11891212                        // The semantics of the declaration list is changed to include associated initialization, which is performed
    11901213                        // *before* the transfer to the appropriate case clause by hoisting the declarations into a compound
     
    11921215                        // therefore, are removed from the grammar even though C allows it. The change also applies to choose
    11931216                        // statement.
    1194                         $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
     1217                        $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    11951218                }
    11961219        | SWITCH '(' comma_expression ')' '{' error '}'         // CFA, syntax error
    11971220                { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; }
    11981221        | CHOOSE '(' comma_expression ')' case_clause           // CFA
    1199                 { $$ = new StatementNode( build_switch( false, $3, $5 ) ); }
     1222                { $$ = new StatementNode( build_switch( yylloc, false, $3, $5 ) ); }
    12001223        | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA
    12011224                {
    1202                         StatementNode *sw = new StatementNode( build_switch( false, $3, $8 ) );
    1203                         $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
     1225                        StatementNode *sw = new StatementNode( build_switch( yylloc, false, $3, $8 ) );
     1226                        $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    12041227                }
    12051228        | CHOOSE '(' comma_expression ')' '{' error '}'         // CFA, syntax error
     
    12101233        IF '(' conditional_declaration ')' statement            %prec THEN
    12111234                // explicitly deal with the shift/reduce conflict on if/else
    1212                 { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), nullptr ) ); }
     1235                { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), nullptr ) ); }
    12131236        | IF '(' conditional_declaration ')' statement ELSE statement
    1214                 { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), maybe_build_compound( $7 ) ) ); }
     1237                { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc, $7 ) ) ); }
    12151238        ;
    12161239
     
    12241247        | declaration comma_expression                                          // semi-colon separated
    12251248                { $$ = new CondCtl( $1, $2 ); }
    1226         ;
     1249        ;
    12271250
    12281251// CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a case
     
    12321255        constant_expression                                                     { $$ = $1; }
    12331256        | constant_expression ELLIPSIS constant_expression      // GCC, subrange
    1234                 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }
     1257                { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
    12351258        | subrange                                                                                      // CFA, subrange
    12361259        ;
    12371260
    12381261case_value_list:                                                                                // CFA
    1239         case_value                                                                      { $$ = new StatementNode( build_case( $1 ) ); }
     1262        case_value                                                                      { $$ = new ClauseNode( build_case( yylloc, $1 ) ); }
    12401263                // 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 ) ) ) ); }
     1264        | case_value_list ',' case_value                        { $$ = $1->set_last( new ClauseNode( build_case( yylloc, $3 ) ) ); }
    12421265        ;
    12431266
     
    12481271        | CASE case_value_list error                                            // syntax error
    12491272                { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; }
    1250         | DEFAULT ':'                                                           { $$ = new StatementNode( build_default() ); }
     1273        | DEFAULT ':'                                                           { $$ = new ClauseNode( build_default( yylloc ) ); }
    12511274                // A semantic check is required to ensure only one default clause per switch/choose statement.
    12521275        | DEFAULT error                                                                         //  syntax error
     
    12561279case_label_list:                                                                                // CFA
    12571280        case_label
    1258         | case_label_list case_label                            { $$ = (StatementNode *)( $1->set_last( $2 )); }
     1281        | case_label_list case_label                            { $$ = $1->set_last( $2 ); }
    12591282        ;
    12601283
    12611284case_clause:                                                                                    // CFA
    1262         case_label_list statement                                       { $$ = $1->append_last_case( maybe_build_compound( $2 ) ); }
     1285        case_label_list statement                                       { $$ = $1->append_last_case( maybe_build_compound( yylloc, $2 ) ); }
    12631286        ;
    12641287
     
    12711294switch_clause_list:                                                                             // CFA
    12721295        case_label_list statement_list_nodecl
    1273                 { $$ = $1->append_last_case( new StatementNode( build_compound( $2 ) ) ); }
     1296                { $$ = $1->append_last_case( new StatementNode( build_compound( yylloc, $2 ) ) ); }
    12741297        | switch_clause_list case_label_list statement_list_nodecl
    1275                 { $$ = (StatementNode *)( $1->set_last( $2->append_last_case( new StatementNode( build_compound( $3 ) ) ) ) ); }
     1298                { $$ = $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3 ) ) ) ); }
    12761299        ;
    12771300
    12781301iteration_statement:
    12791302        WHILE '(' ')' statement                                                         %prec THEN // CFA => while ( 1 )
    1280                 { $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) ); }
     1303                { $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) ); }
    12811304        | WHILE '(' ')' statement ELSE statement                        // CFA
    12821305                {
    1283                         $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) );
    1284                         SemanticWarning( yylloc, Warning::SuperfluousElse, "" );
     1306                        $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) );
     1307                        SemanticWarning( yylloc, Warning::SuperfluousElse );
    12851308                }
    12861309        | WHILE '(' conditional_declaration ')' statement       %prec THEN
    1287                 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
     1310                { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
    12881311        | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA
    1289                 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); }
     1312                { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); }
    12901313        | DO statement WHILE '(' ')' ';'                                        // CFA => do while( 1 )
    1291                 { $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) ); }
     1314                { $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) ); }
    12921315        | DO statement WHILE '(' ')' ELSE statement                     // CFA
    12931316                {
    1294                         $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) );
    1295                         SemanticWarning( yylloc, Warning::SuperfluousElse, "" );
     1317                        $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) );
     1318                        SemanticWarning( yylloc, Warning::SuperfluousElse );
    12961319                }
    12971320        | DO statement WHILE '(' comma_expression ')' ';'
    1298                 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
     1321                { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ) ) ); }
    12991322        | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
    1300                 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); }
     1323                { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ), $8 ) ); }
    13011324        | FOR '(' ')' statement                                                         %prec THEN // CFA => for ( ;; )
    1302                 { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); }
     1325                { $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) ); }
    13031326        | FOR '(' ')' statement ELSE statement                          // CFA
    13041327                {
    1305                         $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) );
    1306                         SemanticWarning( yylloc, Warning::SuperfluousElse, "" );
     1328                        $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) );
     1329                        SemanticWarning( yylloc, Warning::SuperfluousElse );
    13071330                }
    13081331        | FOR '(' for_control_expression_list ')' statement     %prec THEN
    1309                 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
     1332                { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); }
    13101333        | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
    1311                 { $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); }
     1334                { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); }
    13121335        ;
    13131336
     
    13231346                        if ( $1->condition ) {
    13241347                                if ( $3->condition ) {
    1325                                         $1->condition->expr.reset( new LogicalExpr( $1->condition->expr.release(), $3->condition->expr.release(), true ) );
     1348                                        $1->condition->expr.reset( new ast::LogicalExpr( yylloc, $1->condition->expr.release(), $3->condition->expr.release(), ast::AndExpr ) );
    13261349                                } // if
    13271350                        } else $1->condition = $3->condition;
    13281351                        if ( $1->change ) {
    13291352                                if ( $3->change ) {
    1330                                         $1->change->expr.reset( new CommaExpr( $1->change->expr.release(), $3->change->expr.release() ) );
     1353                                        $1->change->expr.reset( new ast::CommaExpr( yylloc, $1->change->expr.release(), $3->change->expr.release() ) );
    13311354                                } // if
    13321355                        } else $1->change = $3->change;
     
    13371360for_control_expression:
    13381361        ';' comma_expression_opt ';' comma_expression_opt
    1339                 { $$ = new ForCtrl( (ExpressionNode * )nullptr, $2, $4 ); }
     1362                { $$ = new ForCtrl( nullptr, $2, $4 ); }
    13401363        | comma_expression ';' comma_expression_opt ';' comma_expression_opt
    1341                 { $$ = new ForCtrl( $1, $3, $5 ); }
     1364                {
     1365                        StatementNode * init = $1 ? new StatementNode( new ast::ExprStmt( yylloc, maybeMoveBuild( $1 ) ) ) : nullptr;
     1366                        $$ = new ForCtrl( init, $3, $5 );
     1367                }
    13421368        | declaration comma_expression_opt ';' comma_expression_opt // C99, declaration has ';'
    1343                 { $$ = new ForCtrl( $1, $2, $4 ); }
     1369                { $$ = new ForCtrl( new StatementNode( $1 ), $2, $4 ); }
    13441370
    13451371        | '@' ';' comma_expression                                                      // CFA, empty loop-index
    1346                 { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, nullptr ); }
     1372                { $$ = new ForCtrl( nullptr, $3, nullptr ); }
    13471373        | '@' ';' comma_expression ';' comma_expression         // CFA, empty loop-index
    1348                 { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, $5 ); }
     1374                { $$ = new ForCtrl( nullptr, $3, $5 ); }
    13491375
    13501376        | comma_expression                                                                      // CFA, anonymous loop-index
    1351                 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }
     1377                { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }
    13521378        | 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 ); }
     1379                { $$ = forCtrl( yylloc, $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }
    13541380
    13551381        | 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 ); }
     1382                { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }
    13571383        | '@' updowneq comma_expression                                         // CFA, anonymous loop-index
    13581384                {
    13591385                        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 );
     1386                        else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );
    13611387                }
    13621388        | comma_expression updowneq '@'                                         // CFA, anonymous loop-index
     
    13661392                }
    13671393        | 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 ); }
     1394                { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }
    13691395        | '@' updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index
    13701396                {
    13711397                        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 );
     1398                        else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );
    13731399                }
    13741400        | comma_expression updowneq '@' '~' comma_expression // CFA, anonymous loop-index
     
    13891415
    13901416        | comma_expression ';' comma_expression                         // CFA
    1391                 { $$ = forCtrl( $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }
     1417                { $$ = forCtrl( yylloc, $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }
    13921418        | 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 ); }
     1419                { $$ = forCtrl( yylloc, $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }
    13941420
    13951421        | 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 ); }
     1422                { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }
    13971423        | comma_expression ';' '@' updowneq comma_expression // CFA
    13981424                {
    13991425                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1400                         else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, NEW_ONE );
     1426                        else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, NEW_ONE );
    14011427                }
    14021428        | comma_expression ';' comma_expression updowneq '@' // CFA
     
    14041430                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14051431                        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 );
     1432                        else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, NEW_ONE );
    14071433                }
    14081434        | comma_expression ';' '@' updowneq '@'                         // CFA, error
     
    14101436
    14111437        | 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 ); }
     1438                { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }
    14131439        | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, error
    14141440                {
    14151441                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1416                         else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, $7 );
     1442                        else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, $7 );
    14171443                }
    14181444        | comma_expression ';' comma_expression updowneq '@' '~' comma_expression // CFA
     
    14201446                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14211447                        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 );
     1448                        else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, $7 );
    14231449                }
    14241450        | 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 ); }
     1451                { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }
    14261452        | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, error
    14271453                {
    14281454                        if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1429                         else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, nullptr );
     1455                        else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, nullptr );
    14301456                }
    14311457        | comma_expression ';' comma_expression updowneq '@' '~' '@' // CFA
     
    14331459                        if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14341460                        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 );
     1461                        else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, nullptr );
    14361462                }
    14371463        | comma_expression ';' '@' updowneq '@' '~' '@' // CFA
     
    14391465
    14401466        | declaration comma_expression                                          // CFA
    1441                 { $$ = forCtrl( $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }
     1467                { $$ = forCtrl( yylloc, $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }
    14421468        | declaration downupdowneq comma_expression                     // CFA
    1443                 { $$ = forCtrl( $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }
     1469                { $$ = forCtrl( yylloc, $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }
    14441470
    14451471        | declaration comma_expression updowneq comma_expression // CFA
    1446                 { $$ = forCtrl( $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }
     1472                { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }
    14471473        | declaration '@' updowneq comma_expression                     // CFA
    14481474                {
    14491475                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1450                         else $$ = forCtrl( $1, $4, $3, nullptr, NEW_ONE );
     1476                        else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, NEW_ONE );
    14511477                }
    14521478        | declaration comma_expression updowneq '@'                     // CFA
     
    14541480                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14551481                        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 );
     1482                        else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, NEW_ONE );
    14571483                }
    14581484
    14591485        | declaration comma_expression updowneq comma_expression '~' comma_expression // CFA
    1460                 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }
     1486                { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }
    14611487        | declaration '@' updowneq comma_expression '~' comma_expression // CFA
    14621488                {
    14631489                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1464                         else $$ = forCtrl( $1, $4, $3, nullptr, $6 );
     1490                        else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, $6 );
    14651491                }
    14661492        | declaration comma_expression updowneq '@' '~' comma_expression // CFA
     
    14681494                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14691495                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1470                         else $$ = forCtrl( $1, $2, $3, nullptr, $6 );
     1496                        else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, $6 );
    14711497                }
    14721498        | declaration comma_expression updowneq comma_expression '~' '@' // CFA
    1473                 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }
     1499                { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }
    14741500        | declaration '@' updowneq comma_expression '~' '@' // CFA
    14751501                {
    14761502                        if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; }
    1477                         else $$ = forCtrl( $1, $4, $3, nullptr, nullptr );
     1503                        else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, nullptr );
    14781504                }
    14791505        | declaration comma_expression updowneq '@' '~' '@'     // CFA
     
    14811507                        if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; }
    14821508                        else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }
    1483                         else $$ = forCtrl( $1, $2, $3, nullptr, nullptr );
     1509                        else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, nullptr );
    14841510                }
    14851511        | declaration '@' updowneq '@' '~' '@'                          // CFA, error
     
    14961522                        SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr;
    14971523                }
    1498         ;
     1524        ;
    14991525
    15001526downupdowneq:
     
    15051531        | ErangeDownEq
    15061532                { $$ = OperKinds::GEThan; }
    1507         ;
     1533        ;
    15081534
    15091535updown:
     
    15121538        | ErangeDown
    15131539                { $$ = OperKinds::GThan; }
    1514         ;
     1540        ;
    15151541
    15161542updowneq:
     
    15201546        | ErangeDownEq
    15211547                { $$ = OperKinds::GEThan; }
    1522         ;
     1548        ;
    15231549
    15241550jump_statement:
    15251551        GOTO identifier_or_type_name ';'
    1526                 { $$ = new StatementNode( build_branch( $2, BranchStmt::Goto ) ); }
     1552                { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Goto ) ); }
    15271553        | GOTO '*' comma_expression ';'                                         // GCC, computed goto
    15281554                // The syntax for the GCC computed goto violates normal expression precedence, e.g., goto *i+3; => goto *(i+3);
     
    15311557                // A semantic check is required to ensure fallthru appears only in the body of a choose statement.
    15321558        | fall_through_name ';'                                                         // CFA
    1533                 { $$ = new StatementNode( build_branch( BranchStmt::FallThrough ) ); }
     1559                { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThrough ) ); }
    15341560        | fall_through_name identifier_or_type_name ';'         // CFA
    1535                 { $$ = new StatementNode( build_branch( $2, BranchStmt::FallThrough ) ); }
     1561                { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::FallThrough ) ); }
    15361562        | fall_through_name DEFAULT ';'                                         // CFA
    1537                 { $$ = new StatementNode( build_branch( BranchStmt::FallThroughDefault ) ); }
     1563                { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThroughDefault ) ); }
    15381564        | CONTINUE ';'
    15391565                // 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 ) ); }
     1566                { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Continue ) ); }
    15411567        | CONTINUE identifier_or_type_name ';'                          // CFA, multi-level continue
    15421568                // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and
    15431569                // the target of the transfer appears only at the start of an iteration statement.
    1544                 { $$ = new StatementNode( build_branch( $2, BranchStmt::Continue ) ); }
     1570                { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Continue ) ); }
    15451571        | BREAK ';'
    15461572                // 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 ) ); }
     1573                { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Break ) ); }
    15481574        | BREAK identifier_or_type_name ';'                                     // CFA, multi-level exit
    15491575                // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and
    15501576                // the target of the transfer appears only at the start of an iteration statement.
    1551                 { $$ = new StatementNode( build_branch( $2, BranchStmt::Break ) ); }
     1577                { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Break ) ); }
    15521578        | RETURN comma_expression_opt ';'
    1553                 { $$ = new StatementNode( build_return( $2 ) ); }
     1579                { $$ = new StatementNode( build_return( yylloc, $2 ) ); }
    15541580        | RETURN '{' initializer_list_opt comma_opt '}' ';'
    15551581                { SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; }
    15561582        | SUSPEND ';'
    1557                 { $$ = new StatementNode( build_suspend( nullptr ) ); }
     1583                { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::None ) ); }
    15581584        | SUSPEND compound_statement
    1559                 { $$ = new StatementNode( build_suspend( $2 ) ); }
     1585                { $$ = new StatementNode( build_suspend( yylloc, $2, ast::SuspendStmt::None ) ); }
    15601586        | SUSPEND COROUTINE ';'
    1561                 { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Coroutine ) ); }
     1587                { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Coroutine ) ); }
    15621588        | SUSPEND COROUTINE compound_statement
    1563                 { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Coroutine ) ); }
     1589                { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Coroutine ) ); }
    15641590        | SUSPEND GENERATOR ';'
    1565                 { $$ = new StatementNode( build_suspend( nullptr, SuspendStmt::Generator ) ); }
     1591                { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Generator ) ); }
    15661592        | SUSPEND GENERATOR compound_statement
    1567                 { $$ = new StatementNode( build_suspend( $3, SuspendStmt::Generator ) ); }
     1593                { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Generator ) ); }
    15681594        | THROW assignment_expression_opt ';'                           // handles rethrow
    1569                 { $$ = new StatementNode( build_throw( $2 ) ); }
     1595                { $$ = new StatementNode( build_throw( yylloc, $2 ) ); }
    15701596        | THROWRESUME assignment_expression_opt ';'                     // handles reresume
    1571                 { $$ = new StatementNode( build_resume( $2 ) ); }
     1597                { $$ = new StatementNode( build_resume( yylloc, $2 ) ); }
    15721598        | THROWRESUME assignment_expression_opt AT assignment_expression ';' // handles reresume
    15731599                { $$ = new StatementNode( build_resume_at( $2, $4 ) ); }
     
    15811607with_statement:
    15821608        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".
     1609                { $$ = new StatementNode( build_with( yylloc, $3, $5 ) ); }
     1610        ;
     1611
     1612// If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so possibly change syntax to "with mutex".
    15871613mutex_statement:
    1588         MUTEX '(' argument_expression_list ')' statement
    1589                 { $$ = new StatementNode( build_mutex( $3, $5 ) ); }
     1614        MUTEX '(' argument_expression_list_opt ')' statement
     1615                {
     1616                        if ( ! $3 ) { SemanticError( yylloc, "mutex argument list cannot be empty." ); $$ = nullptr; }
     1617                        $$ = new StatementNode( build_mutex( yylloc, $3, $5 ) );
     1618                }
    15901619        ;
    15911620
     
    15981627                { $$ = nullptr; }
    15991628        | 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 )); }
    16091629        ;
    16101630
     
    16171637
    16181638timeout:
    1619         TIMEOUT '(' comma_expression ')'                        { $$ = $3; }
    1620         ;
    1621 
    1622 waitfor_clause:
     1639        TIMEOUT '(' comma_expression ')'                        { $$ = $3; }
     1640        ;
     1641
     1642wor:
     1643        OROR
     1644        | WOR
     1645
     1646waitfor:
     1647        WAITFOR '(' cast_expression ')'
     1648                { $$ = $3; }
     1649        | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
     1650                { $$ = (ExpressionNode *)($3->set_last( $5 )); }
     1651        ;
     1652
     1653wor_waitfor_clause:
    16231654        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 ); }
     1655                // Called first: create header for WaitForStmt.
     1656                { $$ = build_waitfor( yylloc, new ast::WaitForStmt( yylloc ), $1, $2, maybe_build_compound( yylloc, $3 ) ); }
     1657        | wor_waitfor_clause wor when_clause_opt waitfor statement
     1658                { $$ = build_waitfor( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); }
     1659        | wor_waitfor_clause wor when_clause_opt ELSE statement
     1660                { $$ = build_waitfor_else( yylloc, $1, $3, maybe_build_compound( yylloc, $5 ) ); }
     1661        | wor_waitfor_clause wor when_clause_opt timeout statement      %prec THEN
     1662                { $$ = build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); }
    16311663        // "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
     1664        | wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
    16331665                { 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 ); }
     1666        | wor_waitfor_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
     1667                { $$ = build_waitfor_else( yylloc, build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ), $7, maybe_build_compound( yylloc, $9 ) ); }
    16361668        ;
    16371669
    16381670waitfor_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 ) ); }
     1671        wor_waitfor_clause                                                                      %prec THEN
     1672                { $$ = new StatementNode( $1 ); }
     1673        ;
     1674
     1675wand:
     1676        ANDAND
     1677        | WAND
     1678        ;
     1679
     1680waituntil:
     1681        WAITUNTIL '(' cast_expression ')'
     1682                { $$ = $3; }
     1683        ;
     1684
     1685waituntil_clause:
     1686        when_clause_opt waituntil statement
     1687                { printf( "waituntil_clause 1\n" ); $$ = nullptr; }
     1688        | '(' wor_waituntil_clause ')'
     1689                { printf( "waituntil_clause 2\n" ); $$ = nullptr; }
     1690        ;
     1691
     1692wand_waituntil_clause:
     1693        waituntil_clause                                                                        %prec THEN
     1694                { printf( "wand_waituntil_clause 1\n" ); $$ = nullptr; }
     1695        | waituntil_clause wand wand_waituntil_clause
     1696                { printf( "wand_waituntil_clause 2\n" ); $$ = nullptr; }
     1697        ;
     1698
     1699wor_waituntil_clause:
     1700        wand_waituntil_clause
     1701                { printf( "wor_waituntil_clause 1\n" ); $$ = nullptr; }
     1702        | wor_waituntil_clause wor wand_waituntil_clause
     1703                { printf( "wor_waituntil_clause 2\n" ); $$ = nullptr; }
     1704        | wor_waituntil_clause wor when_clause_opt ELSE statement
     1705                { printf( "wor_waituntil_clause 3\n" ); $$ = nullptr; }
     1706        | wor_waituntil_clause wor when_clause_opt timeout statement    %prec THEN
     1707                { printf( "wor_waituntil_clause 4\n" ); $$ = nullptr; }
     1708        // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
     1709        | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
     1710                { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
     1711        | wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
     1712                { printf( "wor_waituntil_clause 6\n" ); $$ = nullptr; }
     1713        ;
     1714
     1715waituntil_statement:
     1716        wor_waituntil_clause                                                            %prec THEN
     1717                // SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement.
     1718                { $$ = new StatementNode( build_compound( yylloc, nullptr ) ); }
    16431719        ;
    16441720
    16451721exception_statement:
    1646         TRY compound_statement handler_clause                                   %prec THEN
    1647                 { $$ = new StatementNode( build_try( $2, $3, nullptr ) ); }
     1722        TRY compound_statement handler_clause                                   %prec THEN
     1723                { $$ = new StatementNode( build_try( yylloc, $2, $3, nullptr ) ); }
    16481724        | TRY compound_statement finally_clause
    1649                 { $$ = new StatementNode( build_try( $2, nullptr, $3 ) ); }
     1725                { $$ = new StatementNode( build_try( yylloc, $2, nullptr, $3 ) ); }
    16501726        | TRY compound_statement handler_clause finally_clause
    1651                 { $$ = new StatementNode( build_try( $2, $3, $4 ) ); }
     1727                { $$ = new StatementNode( build_try( yylloc, $2, $3, $4 ) ); }
    16521728        ;
    16531729
    16541730handler_clause:
    16551731        handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement
    1656                 { $$ = new StatementNode( build_catch( $1, $4, $6, $8 ) ); }
     1732                { $$ = new ClauseNode( build_catch( yylloc, $1, $4, $6, $8 ) ); }
    16571733        | 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 ) ) ); }
     1734                { $$ = $1->set_last( new ClauseNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); }
    16591735        ;
    16601736
     
    16661742
    16671743handler_key:
    1668         CATCH                                                                           { $$ = CatchStmt::Terminate; }
    1669         | RECOVER                                                                       { $$ = CatchStmt::Terminate; }
    1670         | CATCHRESUME                                                           { $$ = CatchStmt::Resume; }
    1671         | FIXUP                                                                         { $$ = CatchStmt::Resume; }
     1744        CATCH                                                                           { $$ = ast::Terminate; }
     1745        | RECOVER                                                                       { $$ = ast::Terminate; }
     1746        | CATCHRESUME                                                           { $$ = ast::Resume; }
     1747        | FIXUP                                                                         { $$ = ast::Resume; }
    16721748        ;
    16731749
    16741750finally_clause:
    1675         FINALLY compound_statement                                      { $$ = new StatementNode( build_finally( $2 ) ); }
     1751        FINALLY compound_statement                                      { $$ = new ClauseNode( build_finally( yylloc, $2 ) ); }
    16761752        ;
    16771753
     
    16991775asm_statement:
    17001776        ASM asm_volatile_opt '(' string_literal ')' ';'
    1701                 { $$ = new StatementNode( build_asm( $2, $4, nullptr ) ); }
     1777                { $$ = new StatementNode( build_asm( yylloc, $2, $4, nullptr ) ); }
    17021778        | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ')' ';' // remaining GCC
    1703                 { $$ = new StatementNode( build_asm( $2, $4, $6 ) ); }
     1779                { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6 ) ); }
    17041780        | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ')' ';'
    1705                 { $$ = new StatementNode( build_asm( $2, $4, $6, $8 ) ); }
     1781                { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8 ) ); }
    17061782        | 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 ) ); }
     1783                { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8, $10 ) ); }
    17081784        | ASM asm_volatile_opt GOTO '(' string_literal ':' ':' asm_operands_opt ':' asm_clobbers_list_opt ':' label_list ')' ';'
    1709                 { $$ = new StatementNode( build_asm( $2, $5, nullptr, $8, $10, $12 ) ); }
     1785                { $$ = new StatementNode( build_asm( yylloc, $2, $5, nullptr, $8, $10, $12 ) ); }
    17101786        ;
    17111787
     
    17311807asm_operand:                                                                                    // GCC
    17321808        string_literal '(' constant_expression ')'
    1733                 { $$ = new ExpressionNode( new AsmExpr( nullptr, $1, maybeMoveBuild<Expression>( $3 ) ) ); }
     1809                { $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
    17341810        | '[' IDENTIFIER ']' string_literal '(' constant_expression ')'
    1735                 { $$ = new ExpressionNode( new AsmExpr( $2, $4, maybeMoveBuild<Expression>( $6 ) ) ); }
     1811                {
     1812                        $$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, maybeMoveBuild( $4 ), maybeMoveBuild( $6 ) ) );
     1813                        delete $2.str;
     1814                }
    17361815        ;
    17371816
     
    17401819                { $$ = nullptr; }                                                               // use default argument
    17411820        | string_literal
    1742                 { $$ = new ExpressionNode( $1 ); }
     1821                { $$ = $1; }
    17431822        | asm_clobbers_list_opt ',' string_literal
    1744                 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( $3 ) )); }
     1823                { $$ = (ExpressionNode *)( $1->set_last( $3 ) ); }
    17451824        ;
    17461825
     
    17481827        identifier
    17491828                {
    1750                         $$ = new LabelNode(); $$->labels.push_back( *$1 );
     1829                        $$ = new LabelNode(); $$->labels.emplace_back( yylloc, *$1 );
    17511830                        delete $1;                                                                      // allocated by lexer
    17521831                }
    17531832        | label_list ',' identifier
    17541833                {
    1755                         $$ = $1; $1->labels.push_back( *$3 );
     1834                        $$ = $1; $1->labels.emplace_back( yylloc, *$3 );
    17561835                        delete $3;                                                                      // allocated by lexer
    17571836                }
     
    18041883                {
    18051884                        // printf( "C_DECLARATION1 %p %s\n", $$, $$->name ? $$->name->c_str() : "(nil)" );
    1806                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     1885                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    18071886                        //   printf( "\tattr %s\n", attr->name.c_str() );
    18081887                        // } // for
     
    18141893static_assert:
    18151894        STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
    1816                 { $$ = DeclarationNode::newStaticAssert( $3, $5 ); }
     1895                { $$ = DeclarationNode::newStaticAssert( $3, maybeMoveBuild( $5 ) ); }
    18171896        | STATICASSERT '(' constant_expression ')' ';'          // CFA
    1818                 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( *new string( "\"\"" ) ) ); }
     1897                { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( yylloc, *new string( "\"\"" ) ) ); }
    18191898
    18201899// C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
     
    19392018        TYPEDEF type_specifier declarator
    19402019                {
    1941                         // if type_specifier is an anon aggregate => name
    19422020                        typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "4" );
    1943                         $$ = $3->addType( $2 )->addTypedef();
     2021                        if ( $2->type->forall || ($2->type->kind == TypeData::Aggregate && $2->type->aggregate.params) ) {
     2022                                SemanticError( yylloc, "forall qualifier in typedef is currently unimplemented." ); $$ = nullptr;
     2023                        } else $$ = $3->addType( $2 )->addTypedef(); // watchout frees $2 and $3
    19442024                }
    19452025        | typedef_declaration pop ',' push declarator
     
    19492029                }
    19502030        | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 )
    1951                 {
    1952                         typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "6" );
    1953                         $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef();
    1954                 }
     2031                { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
    19552032        | type_specifier TYPEDEF declarator
    1956                 {
    1957                         typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "7" );
    1958                         $$ = $3->addType( $1 )->addTypedef();
    1959                 }
     2033                { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
    19602034        | type_specifier TYPEDEF type_qualifier_list declarator
    1961                 {
    1962                         typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "8" );
    1963                         $$ = $4->addQualifiers( $1 )->addTypedef()->addType( $1 );
    1964                 }
     2035                { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
    19652036        ;
    19662037
     
    19692040        TYPEDEF identifier '=' assignment_expression
    19702041                {
    1971                         SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
     2042                        SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
    19722043                }
    19732044        | typedef_expression pop ',' push identifier '=' assignment_expression
    19742045                {
    1975                         SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
     2046                        SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
    19762047                }
    19772048        ;
     
    19832054        | typedef_expression                                                            // deprecated GCC, naming expression type
    19842055        | sue_declaration_specifier
     2056                {
     2057                        assert( $1->type );
     2058                        if ( $1->type->qualifiers.any() ) {                     // CV qualifiers ?
     2059                                SemanticError( yylloc, "Useless type qualifier(s) in empty declaration." ); $$ = nullptr;
     2060                        }
     2061                        // enums are never empty declarations because there must have at least one enumeration.
     2062                        if ( $1->type->kind == TypeData::AggregateInst && $1->storageClasses.any() ) { // storage class ?
     2063                                SemanticError( yylloc, "Useless storage qualifier(s) in empty aggregate declaration." ); $$ = nullptr;
     2064                        }
     2065                }
    19852066        ;
    19862067
     
    19882069                // A semantic check is required to ensure asm_name only appears on declarations with implicit or explicit static
    19892070                // storage-class
    1990         declarator asm_name_opt initializer_opt
     2071        variable_declarator asm_name_opt initializer_opt
    19912072                { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); }
     2073        | variable_type_redeclarator asm_name_opt initializer_opt
     2074                { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); }
     2075
     2076        | general_function_declarator asm_name_opt
     2077                { $$ = $1->addAsmName( $2 )->addInitializer( nullptr ); }
     2078        | general_function_declarator asm_name_opt '=' VOID
     2079                { $$ = $1->addAsmName( $2 )->addInitializer( new InitializerNode( true ) ); }
     2080
    19922081        | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt
    19932082                { $$ = $1->appendList( $4->addQualifiers( $3 )->addAsmName( $5 )->addInitializer( $6 ) ); }
     2083        ;
     2084
     2085general_function_declarator:
     2086        function_type_redeclarator
     2087        | function_declarator
    19942088        ;
    19952089
     
    20002094        | sue_declaration_specifier invalid_types
    20012095                {
    2002                         SemanticError( yylloc,
    2003                                                   ::toString( "Missing ';' after end of ",
    2004                                                                           $1->type->enumeration.name ? "enum" : AggregateDecl::aggrString( $1->type->aggregate.kind ),
    2005                                                                           " declaration" ) );
     2096                        SemanticError( yylloc, ::toString( "Missing ';' after end of ",
     2097                                $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ),
     2098                                " declaration" ) );
    20062099                        $$ = nullptr;
    20072100                }
     
    20282121        basic_type_specifier
    20292122        | sue_type_specifier
    2030                 {
    2031                         // printf( "sue_type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2032                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    2033                         //   printf( "\tattr %s\n", attr->name.c_str() );
    2034                         // } // for
    2035                 }
    20362123        | type_type_specifier
    20372124        ;
     
    22422329                { $$ = DeclarationNode::newTypeof( $3 ); }
    22432330        | BASETYPEOF '(' type ')'                                                       // CFA: basetypeof( x ) y;
    2244                 { $$ = DeclarationNode::newTypeof( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ), true ); }
     2331                { $$ = DeclarationNode::newTypeof( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ), true ); }
    22452332        | BASETYPEOF '(' comma_expression ')'                           // CFA: basetypeof( a+b ) y;
    22462333                { $$ = DeclarationNode::newTypeof( $3, true ); }
     
    22552342                {
    22562343                        // printf( "sue_declaration_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2257                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2344                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    22582345                        //   printf( "\tattr %s\n", attr->name.c_str() );
    22592346                        // } // for
     
    22712358                {
    22722359                        // printf( "sue_type_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2273                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2360                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    22742361                        //   printf( "\tattr %s\n", attr->name.c_str() );
    22752362                        // } // for
     
    23492436                {
    23502437                        // printf( "elaborated_type %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2351                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2438                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    23522439                        //   printf( "\tattr %s\n", attr->name.c_str() );
    23532440                        // } // for
     
    23732460          '{' field_declaration_list_opt '}' type_parameters_opt
    23742461                {
    2375                         // printf( "aggregate_type1 %s\n", $3.str->c_str() );
    2376                         // if ( $2 )
    2377                         //      for ( Attribute * attr: reverseIterate( $2->attributes ) ) {
    2378                         //              printf( "copySpecifiers12 %s\n", attr->name.c_str() );
    2379                         //      } // for
    23802462                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
    2381                         // printf( "aggregate_type2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2382                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    2383                         //      printf( "aggregate_type3 %s\n", attr->name.c_str() );
    2384                         // } // for
    23852463                }
    23862464        | aggregate_key attribute_list_opt TYPEDEFname          // unqualified type name
     
    23912469          '{' field_declaration_list_opt '}' type_parameters_opt
    23922470                {
    2393                         // printf( "AGG3\n" );
    23942471                        DeclarationNode::newFromTypedef( $3 );
    23952472                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
     
    24022479          '{' field_declaration_list_opt '}' type_parameters_opt
    24032480                {
    2404                         // printf( "AGG4\n" );
    24052481                        DeclarationNode::newFromTypeGen( $3, nullptr );
    24062482                        $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 );
     
    24292505                        // switched to a TYPEGENname. Link any generic arguments from typegen_name to new generic declaration and
    24302506                        // delete newFromTypeGen.
    2431                         $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 );
    2432                         $3->type->symbolic.name = nullptr;
    2433                         $3->type->symbolic.actuals = nullptr;
    2434                         delete $3;
     2507                        if ( $3->type->kind == TypeData::SymbolicInst && ! $3->type->symbolic.isTypedef ) {
     2508                                $$ = $3->addQualifiers( $2 );
     2509                        } else {
     2510                                $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 );
     2511                                $3->type->symbolic.name = nullptr;                      // copied to $$
     2512                                $3->type->symbolic.actuals = nullptr;
     2513                                delete $3;
     2514                        }
    24352515                }
    24362516        ;
     
    24432523aggregate_data:
    24442524        STRUCT vtable_opt
    2445                 { $$ = AggregateDecl::Struct; }
     2525                { $$ = ast::AggregateDecl::Struct; }
    24462526        | UNION
    2447                 { $$ = AggregateDecl::Union; }
     2527                { $$ = ast::AggregateDecl::Union; }
    24482528        | EXCEPTION                                                                                     // CFA
    2449                 { $$ = AggregateDecl::Exception; }
    2450           //            { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
     2529                { $$ = ast::AggregateDecl::Exception; }
     2530          //            { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = ast::AggregateDecl::NoAggregate; }
    24512531        ;
    24522532
    24532533aggregate_control:                                                                              // CFA
    24542534        MONITOR
    2455                 { $$ = AggregateDecl::Monitor; }
     2535                { $$ = ast::AggregateDecl::Monitor; }
    24562536        | MUTEX STRUCT
    2457                 { $$ = AggregateDecl::Monitor; }
     2537                { $$ = ast::AggregateDecl::Monitor; }
    24582538        | GENERATOR
    2459                 { $$ = AggregateDecl::Generator; }
     2539                { $$ = ast::AggregateDecl::Generator; }
    24602540        | MUTEX GENERATOR
    2461                 { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
     2541                {
     2542                        SemanticError( yylloc, "monitor generator is currently unimplemented." );
     2543                        $$ = ast::AggregateDecl::NoAggregate;
     2544                }
    24622545        | COROUTINE
    2463                 { $$ = AggregateDecl::Coroutine; }
     2546                { $$ = ast::AggregateDecl::Coroutine; }
    24642547        | MUTEX COROUTINE
    2465                 { SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
     2548                {
     2549                        SemanticError( yylloc, "monitor coroutine is currently unimplemented." );
     2550                        $$ = ast::AggregateDecl::NoAggregate;
     2551                }
    24662552        | THREAD
    2467                 { $$ = AggregateDecl::Thread; }
     2553                { $$ = ast::AggregateDecl::Thread; }
    24682554        | MUTEX THREAD
    2469                 { SemanticError( yylloc, "monitor thread is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }
     2555                {
     2556                        SemanticError( yylloc, "monitor thread is currently unimplemented." );
     2557                        $$ = ast::AggregateDecl::NoAggregate;
     2558                }
    24702559        ;
    24712560
     
    24832572                        $$ = fieldDecl( $1, $2 );
    24842573                        // printf( "type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
    2485                         // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
     2574                        // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
    24862575                        //   printf( "\tattr %s\n", attr->name.c_str() );
    24872576                        // } // for
     
    24902579                { $$ = fieldDecl( $2, $3 ); distExt( $$ ); }
    24912580        | STATIC type_specifier field_declaring_list_opt ';' // CFA
    2492                 { SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; }
     2581                { SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; }
    24932582        | INLINE type_specifier field_abstract_list_opt ';'     // CFA
    24942583                {
     
    25012590                }
    25022591        | INLINE aggregate_control ';'                                          // CFA
    2503                 { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }
     2592                { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }
    25042593        | typedef_declaration ';'                                                       // CFA
    25052594        | cfa_field_declaring_list ';'                                          // CFA, new style field declaration
     
    25272616                { $$ = $1->addBitfield( $2 ); }
    25282617        | variable_type_redeclarator bit_subrange_size_opt
     2618                // A semantic check is required to ensure bit_subrange only appears on integral types.
     2619                { $$ = $1->addBitfield( $2 ); }
     2620        | function_type_redeclarator bit_subrange_size_opt
    25292621                // A semantic check is required to ensure bit_subrange only appears on integral types.
    25302622                { $$ = $1->addBitfield( $2 ); }
     
    25812673                { $$ = DeclarationNode::newEnum( $3->name, $6, true, false, nullptr, $4 )->addQualifiers( $2 ); }
    25822674        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}'
    2583                 {
    2584                         if ( $3->storageClasses.val != 0 || $3->type->qualifiers.val != 0 )
     2675                {
     2676                        if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() )
    25852677                        { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
    25862678
     
    25892681        | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt
    25902682                {
    2591                         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." ); }
     2683                        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." ); }
    25922684                        typedefTable.makeTypedef( *$6 );
    25932685                }
     
    27572849type_no_function:                                                                               // sizeof, alignof, cast (constructor)
    27582850        cfa_abstract_declarator_tuple                                           // CFA
    2759         | type_specifier
     2851        | type_specifier                                                                        // cannot be type_specifier_nobody, e.g., (struct S {}){} is a thing
    27602852        | type_specifier abstract_declarator
    27612853                { $$ = $2->addType( $1 ); }
     
    28022894        designator_list ':'                                                                     // C99, CFA uses ":" instead of "="
    28032895        | identifier_at ':'                                                                     // GCC, field name
    2804                 { $$ = new ExpressionNode( build_varref( $1 ) ); }
     2896                { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); }
    28052897        ;
    28062898
     
    28142906designator:
    28152907        '.' identifier_at                                                                       // C99, field name
    2816                 { $$ = new ExpressionNode( build_varref( $2 ) ); }
     2908                { $$ = new ExpressionNode( build_varref( yylloc, $2 ) ); }
    28172909        | '[' push assignment_expression pop ']'                        // C99, single array element
    28182910                // assignment_expression used instead of constant_expression because of shift/reduce conflicts with tuple.
     
    28212913                { $$ = $3; }
    28222914        | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements
    2823                 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $3 ), maybeMoveBuild<Expression>( $5 ) ) ); }
     2915                { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $3 ), maybeMoveBuild( $5 ) ) ); }
    28242916        | '.' '[' push field_name_list pop ']'                          // CFA, tuple field selector
    28252917                { $$ = $4; }
     
    28612953                {
    28622954                        typedefTable.addToScope( *$2, TYPEDEFname, "9" );
    2863                         if ( $1 == TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }
    2864                         if ( $1 == TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }
    2865                         if ( $1 == TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }
     2955                        if ( $1 == ast::TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }
     2956                        if ( $1 == ast::TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }
     2957                        if ( $1 == ast::TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }
    28662958                }
    28672959          type_initializer_opt assertion_list_opt
     
    28742966                {
    28752967                        typedefTable.addToScope( *$2, TYPEDIMname, "9" );
    2876                         $$ = DeclarationNode::newTypeParam( TypeDecl::Dimension, $2 );
     2968                        $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dimension, $2 );
    28772969                }
    28782970        // | type_specifier identifier_parameter_declarator
    28792971        | assertion_list
    2880                 { $$ = DeclarationNode::newTypeParam( TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }
     2972                { $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }
    28812973        ;
    28822974
    28832975new_type_class:                                                                                 // CFA
    28842976        // empty
    2885                 { $$ = TypeDecl::Otype; }
     2977                { $$ = ast::TypeDecl::Otype; }
    28862978        | '&'
    2887                 { $$ = TypeDecl::Dtype; }
     2979                { $$ = ast::TypeDecl::Dtype; }
    28882980        | '*'
    2889                 { $$ = TypeDecl::DStype; }                                              // dtype + sized
     2981                { $$ = ast::TypeDecl::DStype; }                                         // dtype + sized
    28902982        // | '(' '*' ')'
    2891         //      { $$ = TypeDecl::Ftype; }
     2983        //      { $$ = ast::TypeDecl::Ftype; }
    28922984        | ELLIPSIS
    2893                 { $$ = TypeDecl::Ttype; }
     2985                { $$ = ast::TypeDecl::Ttype; }
    28942986        ;
    28952987
    28962988type_class:                                                                                             // CFA
    28972989        OTYPE
    2898                 { $$ = TypeDecl::Otype; }
     2990                { $$ = ast::TypeDecl::Otype; }
    28992991        | DTYPE
    2900                 { $$ = TypeDecl::Dtype; }
     2992                { $$ = ast::TypeDecl::Dtype; }
    29012993        | FTYPE
    2902                 { $$ = TypeDecl::Ftype; }
     2994                { $$ = ast::TypeDecl::Ftype; }
    29032995        | TTYPE
    2904                 { $$ = TypeDecl::Ttype; }
     2996                { $$ = ast::TypeDecl::Ttype; }
    29052997        ;
    29062998
     
    29283020type_list:                                                                                              // CFA
    29293021        type
    2930                 { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
     3022                { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
    29313023        | assignment_expression
    29323024        | type_list ',' type
    2933                 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
     3025                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
    29343026        | type_list ',' assignment_expression
    29353027                { $$ = (ExpressionNode *)( $1->set_last( $3 )); }
     
    29683060        TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}'
    29693061                {
    2970                         SemanticWarning( yylloc, Warning::DeprecTraitSyntax, "" );
     3062                        SemanticWarning( yylloc, Warning::DeprecTraitSyntax );
    29713063                        $$ = DeclarationNode::newTrait( $2, $4, nullptr );
    29723064                }
     
    29753067        | TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}'
    29763068                {
    2977                         SemanticWarning( yylloc, Warning::DeprecTraitSyntax, "" );
     3069                        SemanticWarning( yylloc, Warning::DeprecTraitSyntax );
    29783070                        $$ = DeclarationNode::newTrait( $2, $4, $8 );
    29793071                }
     
    30383130external_definition:
    30393131        DIRECTIVE
    3040                 { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( $1 ) ) ); }
     3132                { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( yylloc, $1 ) ) ); }
    30413133        | declaration
     3134                {
     3135                        // Variable declarations of anonymous types requires creating a unique type-name across multiple translation
     3136                        // unit, which is a dubious task, especially because C uses name rather than structural typing; hence it is
     3137                        // disallowed at the moment.
     3138                        if ( $1->linkage == ast::Linkage::Cforall && ! $1->storageClasses.is_static && $1->type && $1->type->kind == TypeData::AggregateInst ) {
     3139                                if ( $1->type->aggInst.aggregate->kind == TypeData::Enum && $1->type->aggInst.aggregate->enumeration.anon ) {
     3140                                        SemanticError( yylloc, "extern anonymous enumeration is currently unimplemented." ); $$ = nullptr;
     3141                                } else if ( $1->type->aggInst.aggregate->aggregate.anon ) { // handles struct or union
     3142                                        SemanticError( yylloc, "extern anonymous struct/union is currently unimplemented." ); $$ = nullptr;
     3143                                }
     3144                        }
     3145                }
    30423146        | IDENTIFIER IDENTIFIER
    30433147                { IdentifierBeforeIdentifier( *$1.str, *$2.str, " declaration" ); $$ = nullptr; }
     
    30593163                }
    30603164        | ASM '(' string_literal ')' ';'                                        // GCC, global assembler statement
    3061                 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, nullptr ) ) ); }
     3165                { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( yylloc, false, $3, nullptr ) ) ); }
    30623166        | EXTERN STRINGliteral
    30633167                {
    30643168                        linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
    3065                         linkage = LinkageSpec::update( yylloc, linkage, $2 );
     3169                        linkage = ast::Linkage::update( yylloc, linkage, $2 );
    30663170                }
    30673171          up external_definition down
     
    30743178                {
    30753179                        linkageStack.push( linkage );                           // handle nested extern "C"/"Cforall"
    3076                         linkage = LinkageSpec::update( yylloc, linkage, $2 );
     3180                        linkage = ast::Linkage::update( yylloc, linkage, $2 );
    30773181                }
    30783182          '{' up external_definition_list_opt down '}'
     
    30853189        | type_qualifier_list
    30863190                {
    3087                         if ( $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
     3191                        if ( $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    30883192                        if ( $1->type->forall ) forall = true;          // remember generic type
    30893193                }
     
    30913195                {
    30923196                        distQual( $5, $1 );
    3093                         forall = false;
     3197                        forall = false;
    30943198                        $$ = $5;
    30953199                }
    30963200        | declaration_qualifier_list
    30973201                {
    3098                         if ( $1->type && $1->type->qualifiers.val ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
     3202                        if ( $1->type && $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }
    30993203                        if ( $1->type && $1->type->forall ) forall = true; // remember generic type
    31003204                }
     
    31023206                {
    31033207                        distQual( $5, $1 );
    3104                         forall = false;
     3208                        forall = false;
    31053209                        $$ = $5;
    31063210                }
    31073211        | declaration_qualifier_list type_qualifier_list
    31083212                {
    3109                         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." ); }
     3213                        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." ); }
    31103214                        if ( ($1->type && $1->type->forall) || ($2->type && $2->type->forall) ) forall = true; // remember generic type
    31113215                }
     
    31133217                {
    31143218                        distQual( $6, $1->addQualifiers( $2 ) );
    3115                         forall = false;
     3219                        forall = false;
    31163220                        $$ = $6;
    31173221                }
     
    31573261                        $$ = $2->addFunctionBody( $4, $3 )->addType( $1 );
    31583262                }
    3159         | declaration_specifier variable_type_redeclarator with_clause_opt compound_statement
     3263        | declaration_specifier function_type_redeclarator with_clause_opt compound_statement
    31603264                {
    31613265                        rebindForall( $1, $2 );
     
    31933297        | variable_type_redeclarator
    31943298        | function_declarator
     3299        | function_type_redeclarator
    31953300        ;
    31963301
    31973302subrange:
    31983303        constant_expression '~' constant_expression                     // CFA, integer subrange
    3199                 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }
     3304                { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); }
    32003305        ;
    32013306
     
    32063311                {
    32073312                        DeclarationNode * name = new DeclarationNode();
    3208                         name->asmName = $3;
     3313                        name->asmName = maybeMoveBuild( $3 );
    32093314                        $$ = name->addQualifiers( $5 );
    32103315                }
     
    33193424        | '(' attribute_list variable_ptr ')' array_dimension
    33203425                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
    3321         | '(' variable_array ')' multi_array_dimension          // redundant parenthesis
     3426        | '(' variable_array ')' multi_array_dimension          // redundant parenthesis
    33223427                { $$ = $2->addArray( $4 ); }
    33233428        | '(' attribute_list variable_array ')' multi_array_dimension // redundant parenthesis
     
    34433548        ;
    34443549
    3445 // This pattern parses a declaration for a variable or function prototype that redefines a type name, e.g.:
     3550// This pattern parses a declaration for a variable that redefines a type name, e.g.:
    34463551//
    34473552//              typedef int foo;
     
    34493554//                 int foo; // redefine typedef name in new scope
    34503555//              }
    3451 //
    3452 // The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays
    3453 // and functions versus pointers to arrays and functions.
    34543556
    34553557paren_type:
     
    34663568        paren_type attribute_list_opt
    34673569                { $$ = $1->addQualifiers( $2 ); }
    3468         | type_ptr
    3469         | type_array attribute_list_opt
     3570        | variable_type_ptr
     3571        | variable_type_array attribute_list_opt
    34703572                { $$ = $1->addQualifiers( $2 ); }
    3471         | type_function attribute_list_opt
     3573        | variable_type_function attribute_list_opt
    34723574                { $$ = $1->addQualifiers( $2 ); }
    34733575        ;
    34743576
    3475 type_ptr:
     3577variable_type_ptr:
    34763578        ptrref_operator variable_type_redeclarator
    34773579                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
    34783580        | ptrref_operator type_qualifier_list variable_type_redeclarator
    34793581                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
    3480         | '(' type_ptr ')' attribute_list_opt                           // redundant parenthesis
     3582        | '(' variable_type_ptr ')' attribute_list_opt          // redundant parenthesis
    34813583                { $$ = $2->addQualifiers( $4 ); }
    3482         | '(' attribute_list type_ptr ')' attribute_list_opt // redundant parenthesis
     3584        | '(' attribute_list variable_type_ptr ')' attribute_list_opt // redundant parenthesis
    34833585                { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); }
    34843586        ;
    34853587
    3486 type_array:
     3588variable_type_array:
    34873589        paren_type array_dimension
    34883590                { $$ = $1->addArray( $2 ); }
    3489         | '(' type_ptr ')' array_dimension
     3591        | '(' variable_type_ptr ')' array_dimension
    34903592                { $$ = $2->addArray( $4 ); }
    3491         | '(' attribute_list type_ptr ')' array_dimension
     3593        | '(' attribute_list variable_type_ptr ')' array_dimension
    34923594                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
    3493         | '(' type_array ')' multi_array_dimension                      // redundant parenthesis
     3595        | '(' variable_type_array ')' multi_array_dimension     // redundant parenthesis
    34943596                { $$ = $2->addArray( $4 ); }
    3495         | '(' attribute_list type_array ')' multi_array_dimension // redundant parenthesis
     3597        | '(' attribute_list variable_type_array ')' multi_array_dimension // redundant parenthesis
    34963598                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
    3497         | '(' type_array ')'                                                            // redundant parenthesis
     3599        | '(' variable_type_array ')'                                           // redundant parenthesis
    34983600                { $$ = $2; }
    3499         | '(' attribute_list type_array ')'                                     // redundant parenthesis
     3601        | '(' attribute_list variable_type_array ')'            // redundant parenthesis
    35003602                { $$ = $3->addQualifiers( $2 ); }
    35013603        ;
    35023604
    3503 type_function:
     3605variable_type_function:
     3606        '(' variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     3607                { $$ = $2->addParamList( $6 ); }
     3608        | '(' attribute_list variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     3609                { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); }
     3610        | '(' variable_type_function ')'                                        // redundant parenthesis
     3611                { $$ = $2; }
     3612        | '(' attribute_list variable_type_function ')'         // redundant parenthesis
     3613                { $$ = $3->addQualifiers( $2 ); }
     3614        ;
     3615
     3616// This pattern parses a declaration for a function prototype that redefines a type name.  It precludes declaring an
     3617// array of functions versus a pointer to an array of functions, and returning arrays and functions versus pointers to
     3618// arrays and functions.
     3619
     3620function_type_redeclarator:
     3621        function_type_no_ptr attribute_list_opt
     3622                { $$ = $1->addQualifiers( $2 ); }
     3623        | function_type_ptr
     3624        | function_type_array attribute_list_opt
     3625                { $$ = $1->addQualifiers( $2 ); }
     3626        ;
     3627
     3628function_type_no_ptr:
    35043629        paren_type '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
    35053630                { $$ = $1->addParamList( $4 ); }
    3506         | '(' type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     3631        | '(' function_type_ptr ')' '(' push parameter_type_list_opt pop ')'
    35073632                { $$ = $2->addParamList( $6 ); }
    3508         | '(' attribute_list type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)
     3633        | '(' attribute_list function_type_ptr ')' '(' push parameter_type_list_opt pop ')'
    35093634                { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); }
    3510         | '(' type_function ')'                                                         // redundant parenthesis
     3635        | '(' function_type_no_ptr ')'                                          // redundant parenthesis
    35113636                { $$ = $2; }
    3512         | '(' attribute_list type_function ')'                          // redundant parenthesis
     3637        | '(' attribute_list function_type_no_ptr ')'           // redundant parenthesis
     3638                { $$ = $3->addQualifiers( $2 ); }
     3639        ;
     3640
     3641function_type_ptr:
     3642        ptrref_operator function_type_redeclarator
     3643                { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); }
     3644        | ptrref_operator type_qualifier_list function_type_redeclarator
     3645                { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); }
     3646        | '(' function_type_ptr ')' attribute_list_opt
     3647                { $$ = $2->addQualifiers( $4 ); }
     3648        | '(' attribute_list function_type_ptr ')' attribute_list_opt
     3649                { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); }
     3650        ;
     3651
     3652function_type_array:
     3653        '(' function_type_ptr ')' array_dimension
     3654                { $$ = $2->addArray( $4 ); }
     3655        | '(' attribute_list function_type_ptr ')' array_dimension
     3656                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
     3657        | '(' function_type_array ')' multi_array_dimension     // redundant parenthesis
     3658                { $$ = $2->addArray( $4 ); }
     3659        | '(' attribute_list function_type_array ')' multi_array_dimension // redundant parenthesis
     3660                { $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
     3661        | '(' function_type_array ')'                                           // redundant parenthesis
     3662                { $$ = $2; }
     3663        | '(' attribute_list function_type_array ')'            // redundant parenthesis
    35133664                { $$ = $3->addQualifiers( $2 ); }
    35143665        ;
     
    36803831array_type_list:
    36813832        basic_type_name
    3682                 { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
     3833                { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
    36833834        | type_name
    3684                 { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( $1 ) ) ); }
     3835                { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); }
    36853836        | assignment_expression upupeq assignment_expression
    36863837        | array_type_list ',' basic_type_name
    3687                 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
    3688         | array_type_list ',' type_name 
    3689                 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr( maybeMoveBuildType( $3 ) ) ) )); }
     3838                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
     3839        | array_type_list ',' type_name
     3840                { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); }
    36903841        | array_type_list ',' assignment_expression upupeq assignment_expression
    36913842        ;
     
    36963847        | ErangeUpEq
    36973848                { $$ = OperKinds::LEThan; }
    3698         ;
     3849        ;
    36993850
    37003851multi_array_dimension:
  • src/Parser/parserutility.cc

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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/Candidate.cpp

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    5555namespace ResolvExpr {
    5656
     57/// Unique identifier for matching expression resolutions to their requesting expression
     58UniqueId globalResnSlot = 0;
     59
     60namespace {
     61        /// First index is which argument, second is which alternative, third is which exploded element
     62        using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >;
     63
     64        /// Returns a list of alternatives with the minimum cost in the given list
     65        CandidateList findMinCost( const CandidateList & candidates ) {
     66                CandidateList out;
     67                Cost minCost = Cost::infinity;
     68                for ( const CandidateRef & r : candidates ) {
     69                        if ( r->cost < minCost ) {
     70                                minCost = r->cost;
     71                                out.clear();
     72                                out.emplace_back( r );
     73                        } else if ( r->cost == minCost ) {
     74                                out.emplace_back( r );
     75                        }
     76                }
     77                return out;
     78        }
     79
     80        /// Computes conversion cost for a given expression to a given type
     81        const ast::Expr * computeExpressionConversionCost(
     82                const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost
     83        ) {
     84                Cost convCost = computeConversionCost(
     85                                arg->result, paramType, arg->get_lvalue(), symtab, env );
     86                outCost += convCost;
     87
     88                // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires
     89                // conversion. Ignore poly cost for now, since this requires resolution of the cast to
     90                // infer parameters and this does not currently work for the reason stated below
     91                Cost tmpCost = convCost;
     92                tmpCost.incPoly( -tmpCost.get_polyCost() );
     93                if ( tmpCost != Cost::zero ) {
     94                        ast::ptr< ast::Type > newType = paramType;
     95                        env.apply( newType );
     96                        return new ast::CastExpr{ arg, newType };
     97
     98                        // xxx - *should* be able to resolve this cast, but at the moment pointers are not
     99                        // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,
     100                        // once this is fixed it should be possible to resolve the cast.
     101                        // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,
     102                        // but it shouldn't be because this makes the conversion from DT* to DT* since
     103                        // commontype(zero_t, DT*) is DT*, rather than nothing
     104
     105                        // CandidateFinder finder{ symtab, env };
     106                        // finder.find( arg, ResolvMode::withAdjustment() );
     107                        // assertf( finder.candidates.size() > 0,
     108                        //      "Somehow castable expression failed to find alternatives." );
     109                        // assertf( finder.candidates.size() == 1,
     110                        //      "Somehow got multiple alternatives for known cast expression." );
     111                        // return finder.candidates.front()->expr;
     112                }
     113
     114                return arg;
     115        }
     116
     117        /// Computes conversion cost for a given candidate
     118        Cost computeApplicationConversionCost(
     119                CandidateRef cand, const ast::SymbolTable & symtab
     120        ) {
     121                auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();
     122                auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
     123                auto function = pointer->base.strict_as< ast::FunctionType >();
     124
     125                Cost convCost = Cost::zero;
     126                const auto & params = function->params;
     127                auto param = params.begin();
     128                auto & args = appExpr->args;
     129
     130                for ( unsigned i = 0; i < args.size(); ++i ) {
     131                        const ast::Type * argType = args[i]->result;
     132                        PRINT(
     133                                std::cerr << "arg expression:" << std::endl;
     134                                ast::print( std::cerr, args[i], 2 );
     135                                std::cerr << "--- results are" << std::endl;
     136                                ast::print( std::cerr, argType, 2 );
     137                        )
     138
     139                        if ( param == params.end() ) {
     140                                if ( function->isVarArgs ) {
     141                                        convCost.incUnsafe();
     142                                        PRINT( std::cerr << "end of params with varargs function: inc unsafe: "
     143                                                << convCost << std::endl; ; )
     144                                        // convert reference-typed expressions into value-typed expressions
     145                                        cand->expr = ast::mutate_field_index(
     146                                                appExpr, &ast::ApplicationExpr::args, i,
     147                                                referenceToRvalueConversion( args[i], convCost ) );
     148                                        continue;
     149                                } else return Cost::infinity;
     150                        }
     151
     152                        if ( auto def = args[i].as< ast::DefaultArgExpr >() ) {
     153                                // Default arguments should be free - don't include conversion cost.
     154                                // Unwrap them here because they are not relevant to the rest of the system
     155                                cand->expr = ast::mutate_field_index(
     156                                        appExpr, &ast::ApplicationExpr::args, i, def->expr );
     157                                ++param;
     158                                continue;
     159                        }
     160
     161                        // mark conversion cost and also specialization cost of param type
     162                        // const ast::Type * paramType = (*param)->get_type();
     163                        cand->expr = ast::mutate_field_index(
     164                                appExpr, &ast::ApplicationExpr::args, i,
     165                                computeExpressionConversionCost(
     166                                        args[i], *param, symtab, cand->env, convCost ) );
     167                        convCost.decSpec( specCost( *param ) );
     168                        ++param;  // can't be in for-loop update because of the continue
     169                }
     170
     171                if ( param != params.end() ) return Cost::infinity;
     172
     173                // specialization cost of return types can't be accounted for directly, it disables
     174                // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
     175                //
     176                //   forall(otype OS) {
     177                //     void ?|?(OS&, int);  // with newline
     178                //     OS&  ?|?(OS&, int);  // no newline, always chosen due to more specialization
     179                //   }
     180
     181                // mark type variable and specialization cost of forall clause
     182                convCost.incVar( function->forall.size() );
     183                convCost.decSpec( function->assertions.size() );
     184
     185                return convCost;
     186        }
     187
     188        void makeUnifiableVars(
     189                const ast::FunctionType * type, ast::OpenVarSet & unifiableVars,
     190                ast::AssertionSet & need
     191        ) {
     192                for ( auto & tyvar : type->forall ) {
     193                        unifiableVars[ *tyvar ] = ast::TypeData{ tyvar->base };
     194                }
     195                for ( auto & assn : type->assertions ) {
     196                        need[ assn ].isUsed = true;
     197                }
     198        }
     199
     200        /// Gets a default value from an initializer, nullptr if not present
     201        const ast::ConstantExpr * getDefaultValue( const ast::Init * init ) {
     202                if ( auto si = dynamic_cast< const ast::SingleInit * >( init ) ) {
     203                        if ( auto ce = si->value.as< ast::CastExpr >() ) {
     204                                return ce->arg.as< ast::ConstantExpr >();
     205                        } else {
     206                                return si->value.as< ast::ConstantExpr >();
     207                        }
     208                }
     209                return nullptr;
     210        }
     211
     212        /// State to iteratively build a match of parameter expressions to arguments
     213        struct ArgPack {
     214                std::size_t parent;          ///< Index of parent pack
     215                ast::ptr< ast::Expr > expr;  ///< The argument stored here
     216                Cost cost;                   ///< The cost of this argument
     217                ast::TypeEnvironment env;    ///< Environment for this pack
     218                ast::AssertionSet need;      ///< Assertions outstanding for this pack
     219                ast::AssertionSet have;      ///< Assertions found for this pack
     220                ast::OpenVarSet open;        ///< Open variables for this pack
     221                unsigned nextArg;            ///< Index of next argument in arguments list
     222                unsigned tupleStart;         ///< Number of tuples that start at this index
     223                unsigned nextExpl;           ///< Index of next exploded element
     224                unsigned explAlt;            ///< Index of alternative for nextExpl > 0
     225
     226                ArgPack()
     227                : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),
     228                  tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
     229
     230                ArgPack(
     231                        const ast::TypeEnvironment & env, const ast::AssertionSet & need,
     232                        const ast::AssertionSet & have, const ast::OpenVarSet & open )
     233                : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),
     234                  open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
     235
     236                ArgPack(
     237                        std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env,
     238                        ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open,
     239                        unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,
     240                        unsigned nextExpl = 0, unsigned explAlt = 0 )
     241                : parent(parent), expr( expr ), cost( cost ), env( std::move( env ) ), need( std::move( need ) ),
     242                  have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
     243                  nextExpl( nextExpl ), explAlt( explAlt ) {}
     244
     245                ArgPack(
     246                        const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,
     247                        ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )
     248                : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( std::move( env ) ),
     249                  need( std::move( need ) ), have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ),
     250                  tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}
     251
     252                /// true if this pack is in the middle of an exploded argument
     253                bool hasExpl() const { return nextExpl > 0; }
     254
     255                /// Gets the list of exploded candidates for this pack
     256                const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const {
     257                        return args[ nextArg-1 ][ explAlt ];
     258                }
     259
     260                /// Ends a tuple expression, consolidating the appropriate args
     261                void endTuple( const std::vector< ArgPack > & packs ) {
     262                        // add all expressions in tuple to list, summing cost
     263                        std::deque< const ast::Expr * > exprs;
     264                        const ArgPack * pack = this;
     265                        if ( expr ) { exprs.emplace_front( expr ); }
     266                        while ( pack->tupleStart == 0 ) {
     267                                pack = &packs[pack->parent];
     268                                exprs.emplace_front( pack->expr );
     269                                cost += pack->cost;
     270                        }
     271                        // reset pack to appropriate tuple
     272                        std::vector< ast::ptr< ast::Expr > > exprv( exprs.begin(), exprs.end() );
     273                        expr = new ast::TupleExpr{ expr->location, std::move( exprv ) };
     274                        tupleStart = pack->tupleStart - 1;
     275                        parent = pack->parent;
     276                }
     277        };
     278
     279        /// Instantiates an argument to match a parameter, returns false if no matching results left
     280        bool instantiateArgument(
     281                const CodeLocation & location,
     282                const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,
     283                std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,
     284                unsigned nTuples = 0
     285        ) {
     286                if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {
     287                        // paramType is a TupleType -- group args into a TupleExpr
     288                        ++nTuples;
     289                        for ( const ast::Type * type : *tupleType ) {
     290                                // xxx - dropping initializer changes behaviour from previous, but seems correct
     291                                // ^^^ need to handle the case where a tuple has a default argument
     292                                if ( ! instantiateArgument( location,
     293                                        type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
     294                                nTuples = 0;
     295                        }
     296                        // re-constitute tuples for final generation
     297                        for ( auto i = genStart; i < results.size(); ++i ) {
     298                                results[i].endTuple( results );
     299                        }
     300                        return true;
     301                } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {
     302                        // paramType is a ttype, consumes all remaining arguments
     303
     304                        // completed tuples; will be spliced to end of results to finish
     305                        std::vector< ArgPack > finalResults{};
     306
     307                        // iterate until all results completed
     308                        std::size_t genEnd;
     309                        ++nTuples;
     310                        do {
     311                                genEnd = results.size();
     312
     313                                // add another argument to results
     314                                for ( std::size_t i = genStart; i < genEnd; ++i ) {
     315                                        unsigned nextArg = results[i].nextArg;
     316
     317                                        // use next element of exploded tuple if present
     318                                        if ( results[i].hasExpl() ) {
     319                                                const ExplodedArg & expl = results[i].getExpl( args );
     320
     321                                                unsigned nextExpl = results[i].nextExpl + 1;
     322                                                if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }
     323
     324                                                results.emplace_back(
     325                                                        i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
     326                                                        copy( results[i].need ), copy( results[i].have ),
     327                                                        copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,
     328                                                        results[i].explAlt );
     329
     330                                                continue;
     331                                        }
     332
     333                                        // finish result when out of arguments
     334                                        if ( nextArg >= args.size() ) {
     335                                                ArgPack newResult{
     336                                                        results[i].env, results[i].need, results[i].have, results[i].open };
     337                                                newResult.nextArg = nextArg;
     338                                                const ast::Type * argType = nullptr;
     339
     340                                                if ( nTuples > 0 || ! results[i].expr ) {
     341                                                        // first iteration or no expression to clone,
     342                                                        // push empty tuple expression
     343                                                        newResult.parent = i;
     344                                                        newResult.expr = new ast::TupleExpr( location, {} );
     345                                                        argType = newResult.expr->result;
     346                                                } else {
     347                                                        // clone result to collect tuple
     348                                                        newResult.parent = results[i].parent;
     349                                                        newResult.cost = results[i].cost;
     350                                                        newResult.tupleStart = results[i].tupleStart;
     351                                                        newResult.expr = results[i].expr;
     352                                                        argType = newResult.expr->result;
     353
     354                                                        if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) {
     355                                                                // the case where a ttype value is passed directly is special,
     356                                                                // e.g. for argument forwarding purposes
     357                                                                // xxx - what if passing multiple arguments, last of which is
     358                                                                //       ttype?
     359                                                                // xxx - what would happen if unify was changed so that unifying
     360                                                                //       tuple
     361                                                                // types flattened both before unifying lists? then pass in
     362                                                                // TupleType (ttype) below.
     363                                                                --newResult.tupleStart;
     364                                                        } else {
     365                                                                // collapse leftover arguments into tuple
     366                                                                newResult.endTuple( results );
     367                                                                argType = newResult.expr->result;
     368                                                        }
     369                                                }
     370
     371                                                // check unification for ttype before adding to final
     372                                                if (
     373                                                        unify(
     374                                                                ttype, argType, newResult.env, newResult.need, newResult.have,
     375                                                                newResult.open, symtab )
     376                                                ) {
     377                                                        finalResults.emplace_back( std::move( newResult ) );
     378                                                }
     379
     380                                                continue;
     381                                        }
     382
     383                                        // add each possible next argument
     384                                        for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {
     385                                                const ExplodedArg & expl = args[nextArg][j];
     386
     387                                                // fresh copies of parent parameters for this iteration
     388                                                ast::TypeEnvironment env = results[i].env;
     389                                                ast::OpenVarSet open = results[i].open;
     390
     391                                                env.addActual( expl.env, open );
     392
     393                                                // skip empty tuple arguments by (nearly) cloning parent into next gen
     394                                                if ( expl.exprs.empty() ) {
     395                                                        results.emplace_back(
     396                                                                results[i], std::move( env ), copy( results[i].need ),
     397                                                                copy( results[i].have ), std::move( open ), nextArg + 1, expl.cost );
     398
     399                                                        continue;
     400                                                }
     401
     402                                                // add new result
     403                                                results.emplace_back(
     404                                                        i, expl.exprs.front(), std::move( env ), copy( results[i].need ),
     405                                                        copy( results[i].have ), std::move( open ), nextArg + 1, nTuples,
     406                                                        expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
     407                                        }
     408                                }
     409
     410                                // reset for next round
     411                                genStart = genEnd;
     412                                nTuples = 0;
     413                        } while ( genEnd != results.size() );
     414
     415                        // splice final results onto results
     416                        for ( std::size_t i = 0; i < finalResults.size(); ++i ) {
     417                                results.emplace_back( std::move( finalResults[i] ) );
     418                        }
     419                        return ! finalResults.empty();
     420                }
     421
     422                // iterate each current subresult
     423                std::size_t genEnd = results.size();
     424                for ( std::size_t i = genStart; i < genEnd; ++i ) {
     425                        unsigned nextArg = results[i].nextArg;
     426
     427                        // use remainder of exploded tuple if present
     428                        if ( results[i].hasExpl() ) {
     429                                const ExplodedArg & expl = results[i].getExpl( args );
     430                                const ast::Expr * expr = expl.exprs[ results[i].nextExpl ];
     431
     432                                ast::TypeEnvironment env = results[i].env;
     433                                ast::AssertionSet need = results[i].need, have = results[i].have;
     434                                ast::OpenVarSet open = results[i].open;
     435
     436                                const ast::Type * argType = expr->result;
     437
     438                                PRINT(
     439                                        std::cerr << "param type is ";
     440                                        ast::print( std::cerr, paramType );
     441                                        std::cerr << std::endl << "arg type is ";
     442                                        ast::print( std::cerr, argType );
     443                                        std::cerr << std::endl;
     444                                )
     445
     446                                if ( unify( paramType, argType, env, need, have, open, symtab ) ) {
     447                                        unsigned nextExpl = results[i].nextExpl + 1;
     448                                        if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }
     449
     450                                        results.emplace_back(
     451                                                i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), nextArg,
     452                                                nTuples, Cost::zero, nextExpl, results[i].explAlt );
     453                                }
     454
     455                                continue;
     456                        }
     457
     458                        // use default initializers if out of arguments
     459                        if ( nextArg >= args.size() ) {
     460                                if ( const ast::ConstantExpr * cnst = getDefaultValue( init ) ) {
     461                                        ast::TypeEnvironment env = results[i].env;
     462                                        ast::AssertionSet need = results[i].need, have = results[i].have;
     463                                        ast::OpenVarSet open = results[i].open;
     464
     465                                        if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
     466                                                results.emplace_back(
     467                                                        i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ),
     468                                                        std::move( need ), std::move( have ), std::move( open ), nextArg, nTuples );
     469                                        }
     470                                }
     471
     472                                continue;
     473                        }
     474
     475                        // Check each possible next argument
     476                        for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {
     477                                const ExplodedArg & expl = args[nextArg][j];
     478
     479                                // fresh copies of parent parameters for this iteration
     480                                ast::TypeEnvironment env = results[i].env;
     481                                ast::AssertionSet need = results[i].need, have = results[i].have;
     482                                ast::OpenVarSet open = results[i].open;
     483
     484                                env.addActual( expl.env, open );
     485
     486                                // skip empty tuple arguments by (nearly) cloning parent into next gen
     487                                if ( expl.exprs.empty() ) {
     488                                        results.emplace_back(
     489                                                results[i], std::move( env ), std::move( need ), std::move( have ), std::move( open ),
     490                                                nextArg + 1, expl.cost );
     491
     492                                        continue;
     493                                }
     494
     495                                // consider only first exploded arg
     496                                const ast::Expr * expr = expl.exprs.front();
     497                                const ast::Type * argType = expr->result;
     498
     499                                PRINT(
     500                                        std::cerr << "param type is ";
     501                                        ast::print( std::cerr, paramType );
     502                                        std::cerr << std::endl << "arg type is ";
     503                                        ast::print( std::cerr, argType );
     504                                        std::cerr << std::endl;
     505                                )
     506
     507                                // attempt to unify types
     508                                if ( unify( paramType, argType, env, need, have, open, symtab ) ) {
     509                                        // add new result
     510                                        results.emplace_back(
     511                                                i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
     512                                                nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
     513                                }
     514                        }
     515                }
     516
     517                // reset for next parameter
     518                genStart = genEnd;
     519
     520                return genEnd != results.size();  // were any new results added?
     521        }
     522
     523        /// Generate a cast expression from `arg` to `toType`
     524        const ast::Expr * restructureCast(
     525                ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
     526        ) {
     527                if (
     528                        arg->result->size() > 1
     529                        && ! toType->isVoid()
     530                        && ! dynamic_cast< const ast::ReferenceType * >( toType )
     531                ) {
     532                        // Argument is a tuple and the target type is neither void nor a reference. Cast each
     533                        // member of the tuple to its corresponding target type, producing the tuple of those
     534                        // cast expressions. If there are more components of the tuple than components in the
     535                        // target type, then excess components do not come out in the result expression (but
     536                        // UniqueExpr ensures that the side effects will still be produced)
     537                        if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
     538                                // expressions which may contain side effects require a single unique instance of
     539                                // the expression
     540                                arg = new ast::UniqueExpr{ arg->location, arg };
     541                        }
     542                        std::vector< ast::ptr< ast::Expr > > components;
     543                        for ( unsigned i = 0; i < toType->size(); ++i ) {
     544                                // cast each component
     545                                ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
     546                                components.emplace_back(
     547                                        restructureCast( idx, toType->getComponent( i ), isGenerated ) );
     548                        }
     549                        return new ast::TupleExpr{ arg->location, std::move( components ) };
     550                } else {
     551                        // handle normally
     552                        return new ast::CastExpr{ arg->location, arg, toType, isGenerated };
     553                }
     554        }
     555
     556        /// Gets the name from an untyped member expression (must be NameExpr)
     557        const std::string & getMemberName( const ast::UntypedMemberExpr * memberExpr ) {
     558                if ( memberExpr->member.as< ast::ConstantExpr >() ) {
     559                        SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );
     560                }
     561
     562                return memberExpr->member.strict_as< ast::NameExpr >()->name;
     563        }
     564
     565        /// Actually visits expressions to find their candidate interpretations
     566        class Finder final : public ast::WithShortCircuiting {
     567                const ResolveContext & context;
     568                const ast::SymbolTable & symtab;
     569        public:
     570                // static size_t traceId;
     571                CandidateFinder & selfFinder;
     572                CandidateList & candidates;
     573                const ast::TypeEnvironment & tenv;
     574                ast::ptr< ast::Type > & targetType;
     575
     576                enum Errors {
     577                        NotFound,
     578                        NoMatch,
     579                        ArgsToFew,
     580                        ArgsToMany,
     581                        RetsToFew,
     582                        RetsToMany,
     583                        NoReason
     584                };
     585
     586                struct {
     587                        Errors code = NotFound;
     588                } reason;
     589
     590                Finder( CandidateFinder & f )
     591                : context( f.context ), symtab( context.symtab ), selfFinder( f ),
     592                  candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {}
     593
     594                void previsit( const ast::Node * ) { visit_children = false; }
     595
     596                /// Convenience to add candidate to list
     597                template<typename... Args>
     598                void addCandidate( Args &&... args ) {
     599                        candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );
     600                        reason.code = NoReason;
     601                }
     602
     603                void postvisit( const ast::ApplicationExpr * applicationExpr ) {
     604                        addCandidate( applicationExpr, tenv );
     605                }
     606
     607                /// Set up candidate assertions for inference
     608                void inferParameters( CandidateRef & newCand, CandidateList & out );
     609
     610                /// Completes a function candidate with arguments located
     611                void validateFunctionCandidate(
     612                        const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
     613                        CandidateList & out );
     614
     615                /// Builds a list of candidates for a function, storing them in out
     616                void makeFunctionCandidates(
     617                        const CodeLocation & location,
     618                        const CandidateRef & func, const ast::FunctionType * funcType,
     619                        const ExplodedArgs_new & args, CandidateList & out );
     620
     621                /// Adds implicit struct-conversions to the alternative list
     622                void addAnonConversions( const CandidateRef & cand );
     623
     624                /// Adds aggregate member interpretations
     625                void addAggMembers(
     626                        const ast::BaseInstType * aggrInst, const ast::Expr * expr,
     627                        const Candidate & cand, const Cost & addedCost, const std::string & name
     628                );
     629
     630                /// Adds tuple member interpretations
     631                void addTupleMembers(
     632                        const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
     633                        const Cost & addedCost, const ast::Expr * member
     634                );
     635
     636                /// true if expression is an lvalue
     637                static bool isLvalue( const ast::Expr * x ) {
     638                        return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );
     639                }
     640
     641                void postvisit( const ast::UntypedExpr * untypedExpr );
     642                void postvisit( const ast::VariableExpr * variableExpr );
     643                void postvisit( const ast::ConstantExpr * constantExpr );
     644                void postvisit( const ast::SizeofExpr * sizeofExpr );
     645                void postvisit( const ast::AlignofExpr * alignofExpr );
     646                void postvisit( const ast::AddressExpr * addressExpr );
     647                void postvisit( const ast::LabelAddressExpr * labelExpr );
     648                void postvisit( const ast::CastExpr * castExpr );
     649                void postvisit( const ast::VirtualCastExpr * castExpr );
     650                void postvisit( const ast::KeywordCastExpr * castExpr );
     651                void postvisit( const ast::UntypedMemberExpr * memberExpr );
     652                void postvisit( const ast::MemberExpr * memberExpr );
     653                void postvisit( const ast::NameExpr * nameExpr );
     654                void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr );
     655                void postvisit( const ast::OffsetofExpr * offsetofExpr );
     656                void postvisit( const ast::OffsetPackExpr * offsetPackExpr );
     657                void postvisit( const ast::LogicalExpr * logicalExpr );
     658                void postvisit( const ast::ConditionalExpr * conditionalExpr );
     659                void postvisit( const ast::CommaExpr * commaExpr );
     660                void postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr );
     661                void postvisit( const ast::ConstructorExpr * ctorExpr );
     662                void postvisit( const ast::RangeExpr * rangeExpr );
     663                void postvisit( const ast::UntypedTupleExpr * tupleExpr );
     664                void postvisit( const ast::TupleExpr * tupleExpr );
     665                void postvisit( const ast::TupleIndexExpr * tupleExpr );
     666                void postvisit( const ast::TupleAssignExpr * tupleExpr );
     667                void postvisit( const ast::UniqueExpr * unqExpr );
     668                void postvisit( const ast::StmtExpr * stmtExpr );
     669                void postvisit( const ast::UntypedInitExpr * initExpr );
     670
     671                void postvisit( const ast::InitExpr * ) {
     672                        assertf( false, "CandidateFinder should never see a resolved InitExpr." );
     673                }
     674
     675                void postvisit( const ast::DeletedExpr * ) {
     676                        assertf( false, "CandidateFinder should never see a DeletedExpr." );
     677                }
     678
     679                void postvisit( const ast::GenericExpr * ) {
     680                        assertf( false, "_Generic is not yet supported." );
     681                }
     682        };
     683
     684        /// Set up candidate assertions for inference
     685        void Finder::inferParameters( CandidateRef & newCand, CandidateList & out ) {
     686                // Set need bindings for any unbound assertions
     687                UniqueId crntResnSlot = 0; // matching ID for this expression's assertions
     688                for ( auto & assn : newCand->need ) {
     689                        // skip already-matched assertions
     690                        if ( assn.second.resnSlot != 0 ) continue;
     691                        // assign slot for expression if needed
     692                        if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }
     693                        // fix slot to assertion
     694                        assn.second.resnSlot = crntResnSlot;
     695                }
     696                // pair slot to expression
     697                if ( crntResnSlot != 0 ) {
     698                        newCand->expr.get_and_mutate()->inferred.resnSlots().emplace_back( crntResnSlot );
     699                }
     700
     701                // add to output list; assertion satisfaction will occur later
     702                out.emplace_back( newCand );
     703        }
     704
     705        /// Completes a function candidate with arguments located
     706        void Finder::validateFunctionCandidate(
     707                const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
     708                CandidateList & out
     709        ) {
     710                ast::ApplicationExpr * appExpr =
     711                        new ast::ApplicationExpr{ func->expr->location, func->expr };
     712                // sum cost and accumulate arguments
     713                std::deque< const ast::Expr * > args;
     714                Cost cost = func->cost;
     715                const ArgPack * pack = &result;
     716                while ( pack->expr ) {
     717                        args.emplace_front( pack->expr );
     718                        cost += pack->cost;
     719                        pack = &results[pack->parent];
     720                }
     721                std::vector< ast::ptr< ast::Expr > > vargs( args.begin(), args.end() );
     722                appExpr->args = std::move( vargs );
     723                // build and validate new candidate
     724                auto newCand =
     725                        std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
     726                PRINT(
     727                        std::cerr << "instantiate function success: " << appExpr << std::endl;
     728                        std::cerr << "need assertions:" << std::endl;
     729                        ast::print( std::cerr, result.need, 2 );
     730                )
     731                inferParameters( newCand, out );
     732        }
     733
     734        /// Builds a list of candidates for a function, storing them in out
     735        void Finder::makeFunctionCandidates(
     736                const CodeLocation & location,
     737                const CandidateRef & func, const ast::FunctionType * funcType,
     738                const ExplodedArgs_new & args, CandidateList & out
     739        ) {
     740                ast::OpenVarSet funcOpen;
     741                ast::AssertionSet funcNeed, funcHave;
     742                ast::TypeEnvironment funcEnv{ func->env };
     743                makeUnifiableVars( funcType, funcOpen, funcNeed );
     744                // add all type variables as open variables now so that those not used in the
     745                // parameter list are still considered open
     746                funcEnv.add( funcType->forall );
     747
     748                if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) {
     749                        // attempt to narrow based on expected target type
     750                        const ast::Type * returnType = funcType->returns.front();
     751                        if ( ! unify(
     752                                returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
     753                        ) {
     754                                // unification failed, do not pursue this candidate
     755                                return;
     756                        }
     757                }
     758
     759                // iteratively build matches, one parameter at a time
     760                std::vector< ArgPack > results;
     761                results.emplace_back( funcEnv, funcNeed, funcHave, funcOpen );
     762                std::size_t genStart = 0;
     763
     764                // xxx - how to handle default arg after change to ftype representation?
     765                if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) {
     766                        if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) {
     767                                // function may have default args only if directly calling by name
     768                                // must use types on candidate however, due to RenameVars substitution
     769                                auto nParams = funcType->params.size();
     770
     771                                for (size_t i=0; i<nParams; ++i) {
     772                                        auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();
     773                                        if (!instantiateArgument( location,
     774                                                funcType->params[i], obj->init, args, results, genStart, symtab)) return;
     775                                }
     776                                goto endMatch;
     777                        }
     778                }
     779                for ( const auto & param : funcType->params ) {
     780                        // Try adding the arguments corresponding to the current parameter to the existing
     781                        // matches
     782                        // no default args for indirect calls
     783                        if ( ! instantiateArgument( location,
     784                                param, nullptr, args, results, genStart, symtab ) ) return;
     785                }
     786
     787                endMatch:
     788                if ( funcType->isVarArgs ) {
     789                        // append any unused arguments to vararg pack
     790                        std::size_t genEnd;
     791                        do {
     792                                genEnd = results.size();
     793
     794                                // iterate results
     795                                for ( std::size_t i = genStart; i < genEnd; ++i ) {
     796                                        unsigned nextArg = results[i].nextArg;
     797
     798                                        // use remainder of exploded tuple if present
     799                                        if ( results[i].hasExpl() ) {
     800                                                const ExplodedArg & expl = results[i].getExpl( args );
     801
     802                                                unsigned nextExpl = results[i].nextExpl + 1;
     803                                                if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }
     804
     805                                                results.emplace_back(
     806                                                        i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
     807                                                        copy( results[i].need ), copy( results[i].have ),
     808                                                        copy( results[i].open ), nextArg, 0, Cost::zero, nextExpl,
     809                                                        results[i].explAlt );
     810
     811                                                continue;
     812                                        }
     813
     814                                        // finish result when out of arguments
     815                                        if ( nextArg >= args.size() ) {
     816                                                validateFunctionCandidate( func, results[i], results, out );
     817
     818                                                continue;
     819                                        }
     820
     821                                        // add each possible next argument
     822                                        for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {
     823                                                const ExplodedArg & expl = args[nextArg][j];
     824
     825                                                // fresh copies of parent parameters for this iteration
     826                                                ast::TypeEnvironment env = results[i].env;
     827                                                ast::OpenVarSet open = results[i].open;
     828
     829                                                env.addActual( expl.env, open );
     830
     831                                                // skip empty tuple arguments by (nearly) cloning parent into next gen
     832                                                if ( expl.exprs.empty() ) {
     833                                                        results.emplace_back(
     834                                                                results[i], std::move( env ), copy( results[i].need ),
     835                                                                copy( results[i].have ), std::move( open ), nextArg + 1,
     836                                                                expl.cost );
     837
     838                                                        continue;
     839                                                }
     840
     841                                                // add new result
     842                                                results.emplace_back(
     843                                                        i, expl.exprs.front(), std::move( env ), copy( results[i].need ),
     844                                                        copy( results[i].have ), std::move( open ), nextArg + 1, 0, expl.cost,
     845                                                        expl.exprs.size() == 1 ? 0 : 1, j );
     846                                        }
     847                                }
     848
     849                                genStart = genEnd;
     850                        } while( genEnd != results.size() );
     851                } else {
     852                        // filter out the results that don't use all the arguments
     853                        for ( std::size_t i = genStart; i < results.size(); ++i ) {
     854                                ArgPack & result = results[i];
     855                                if ( ! result.hasExpl() && result.nextArg >= args.size() ) {
     856                                        validateFunctionCandidate( func, result, results, out );
     857                                }
     858                        }
     859                }
     860        }
     861
     862        /// Adds implicit struct-conversions to the alternative list
     863        void Finder::addAnonConversions( const CandidateRef & cand ) {
     864                // adds anonymous member interpretations whenever an aggregate value type is seen.
     865                // it's okay for the aggregate expression to have reference type -- cast it to the
     866                // base type to treat the aggregate as the referenced value
     867                ast::ptr< ast::Expr > aggrExpr( cand->expr );
     868                ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
     869                cand->env.apply( aggrType );
     870
     871                if ( aggrType.as< ast::ReferenceType >() ) {
     872                        aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
     873                }
     874
     875                if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) {
     876                        addAggMembers( structInst, aggrExpr, *cand, Cost::safe, "" );
     877                } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {
     878                        addAggMembers( unionInst, aggrExpr, *cand, Cost::safe, "" );
     879                }
     880        }
     881
     882        /// Adds aggregate member interpretations
     883        void Finder::addAggMembers(
     884                const ast::BaseInstType * aggrInst, const ast::Expr * expr,
     885                const Candidate & cand, const Cost & addedCost, const std::string & name
     886        ) {
     887                for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
     888                        auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
     889                        CandidateRef newCand = std::make_shared<Candidate>(
     890                                cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
     891                        // add anonymous member interpretations whenever an aggregate value type is seen
     892                        // as a member expression
     893                        addAnonConversions( newCand );
     894                        candidates.emplace_back( std::move( newCand ) );
     895                }
     896        }
     897
     898        /// Adds tuple member interpretations
     899        void Finder::addTupleMembers(
     900                const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
     901                const Cost & addedCost, const ast::Expr * member
     902        ) {
     903                if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {
     904                        // get the value of the constant expression as an int, must be between 0 and the
     905                        // length of the tuple to have meaning
     906                        long long val = constantExpr->intValue();
     907                        if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
     908                                addCandidate(
     909                                        cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
     910                                        addedCost );
     911                        }
     912                }
     913        }
     914
     915        void Finder::postvisit( const ast::UntypedExpr * untypedExpr ) {
     916                std::vector< CandidateFinder > argCandidates =
     917                        selfFinder.findSubExprs( untypedExpr->args );
     918
     919                // take care of possible tuple assignments
     920                // if not tuple assignment, handled as normal function call
     921                Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );
     922
     923                CandidateFinder funcFinder( context, tenv );
     924                if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) {
     925                        auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);
     926                        if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {
     927                                assertf(!argCandidates.empty(), "special function call without argument");
     928                                for (auto & firstArgCand: argCandidates[0]) {
     929                                        ast::ptr<ast::Type> argType = firstArgCand->expr->result;
     930                                        firstArgCand->env.apply(argType);
     931                                        // strip references
     932                                        // xxx - is this correct?
     933                                        while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base;
     934
     935                                        // convert 1-tuple to plain type
     936                                        if (auto tuple = argType.as<ast::TupleType>()) {
     937                                                if (tuple->size() == 1) {
     938                                                        argType = tuple->types[0];
     939                                                }
     940                                        }
     941
     942                                        // if argType is an unbound type parameter, all special functions need to be searched.
     943                                        if (isUnboundType(argType)) {
     944                                                funcFinder.otypeKeys.clear();
     945                                                break;
     946                                        }
     947
     948                                        if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer);                                             
     949                                        // else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) {
     950                                        //      const ast::EnumDecl * enumDecl = enumInst->base; // Here
     951                                        //      if ( const ast::Type* enumType = enumDecl->base ) {
     952                                        //              // instance of enum (T) is a instance of type (T)
     953                                        //              funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type));
     954                                        //      } else {
     955                                        //              // instance of an untyped enum is techically int
     956                                        //              funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type));
     957                                        //      }
     958                                        // }
     959                                        else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type));
     960                                }
     961                        }
     962                }
     963                // if candidates are already produced, do not fail
     964                // xxx - is it possible that handleTupleAssignment and main finder both produce candidates?
     965                // this means there exists ctor/assign functions with a tuple as first parameter.
     966                ResolvMode mode = {
     967                        true, // adjust
     968                        !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name
     969                        selfFinder.candidates.empty() // failfast if other options are not found
     970                };
     971                funcFinder.find( untypedExpr->func, mode );
     972                // short-circuit if no candidates
     973                // if ( funcFinder.candidates.empty() ) return;
     974
     975                reason.code = NoMatch;
     976
     977                // find function operators
     978                ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; // ??? why not ?{}
     979                CandidateFinder opFinder( context, tenv );
     980                // okay if there aren't any function operations
     981                opFinder.find( opExpr, ResolvMode::withoutFailFast() );
     982                PRINT(
     983                        std::cerr << "known function ops:" << std::endl;
     984                        print( std::cerr, opFinder.candidates, 1 );
     985                )
     986
     987                // pre-explode arguments
     988                ExplodedArgs_new argExpansions;
     989                for ( const CandidateFinder & args : argCandidates ) {
     990                        argExpansions.emplace_back();
     991                        auto & argE = argExpansions.back();
     992                        for ( const CandidateRef & arg : args ) { argE.emplace_back( *arg, symtab ); }
     993                }
     994
     995                // Find function matches
     996                CandidateList found;
     997                SemanticErrorException errors;
     998                for ( CandidateRef & func : funcFinder ) {
     999                        try {
     1000                                PRINT(
     1001                                        std::cerr << "working on alternative:" << std::endl;
     1002                                        print( std::cerr, *func, 2 );
     1003                                )
     1004
     1005                                // check if the type is a pointer to function
     1006                                const ast::Type * funcResult = func->expr->result->stripReferences();
     1007                                if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) {
     1008                                        if ( auto function = pointer->base.as< ast::FunctionType >() ) {
     1009                                                CandidateRef newFunc{ new Candidate{ *func } };
     1010                                                newFunc->expr =
     1011                                                        referenceToRvalueConversion( newFunc->expr, newFunc->cost );
     1012                                                makeFunctionCandidates( untypedExpr->location,
     1013                                                        newFunc, function, argExpansions, found );
     1014                                        }
     1015                                } else if (
     1016                                        auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
     1017                                ) {
     1018                                        if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) {
     1019                                                if ( auto function = clz->bound.as< ast::FunctionType >() ) {
     1020                                                        CandidateRef newFunc{ new Candidate{ *func } };
     1021                                                        newFunc->expr =
     1022                                                                referenceToRvalueConversion( newFunc->expr, newFunc->cost );
     1023                                                        makeFunctionCandidates( untypedExpr->location,
     1024                                                                newFunc, function, argExpansions, found );
     1025                                                }
     1026                                        }
     1027                                }
     1028                        } catch ( SemanticErrorException & e ) { errors.append( e ); }
     1029                }
     1030
     1031                // Find matches on function operators `?()`
     1032                if ( ! opFinder.candidates.empty() ) {
     1033                        // add exploded function alternatives to front of argument list
     1034                        std::vector< ExplodedArg > funcE;
     1035                        funcE.reserve( funcFinder.candidates.size() );
     1036                        for ( const CandidateRef & func : funcFinder ) {
     1037                                funcE.emplace_back( *func, symtab );
     1038                        }
     1039                        argExpansions.emplace_front( std::move( funcE ) );
     1040
     1041                        for ( const CandidateRef & op : opFinder ) {
     1042                                try {
     1043                                        // check if type is pointer-to-function
     1044                                        const ast::Type * opResult = op->expr->result->stripReferences();
     1045                                        if ( auto pointer = dynamic_cast< const ast::PointerType * >( opResult ) ) {
     1046                                                if ( auto function = pointer->base.as< ast::FunctionType >() ) {
     1047                                                        CandidateRef newOp{ new Candidate{ *op} };
     1048                                                        newOp->expr =
     1049                                                                referenceToRvalueConversion( newOp->expr, newOp->cost );
     1050                                                        makeFunctionCandidates( untypedExpr->location,
     1051                                                                newOp, function, argExpansions, found );
     1052                                                }
     1053                                        }
     1054                                } catch ( SemanticErrorException & e ) { errors.append( e ); }
     1055                        }
     1056                }
     1057
     1058                // Implement SFINAE; resolution errors are only errors if there aren't any non-error
     1059                // candidates
     1060                if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
     1061
     1062                // Compute conversion costs
     1063                for ( CandidateRef & withFunc : found ) {
     1064                        Cost cvtCost = computeApplicationConversionCost( withFunc, symtab );
     1065
     1066                        PRINT(
     1067                                auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >();
     1068                                auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
     1069                                auto function = pointer->base.strict_as< ast::FunctionType >();
     1070
     1071                                std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
     1072                                std::cerr << "parameters are:" << std::endl;
     1073                                ast::printAll( std::cerr, function->params, 2 );
     1074                                std::cerr << "arguments are:" << std::endl;
     1075                                ast::printAll( std::cerr, appExpr->args, 2 );
     1076                                std::cerr << "bindings are:" << std::endl;
     1077                                ast::print( std::cerr, withFunc->env, 2 );
     1078                                std::cerr << "cost is: " << withFunc->cost << std::endl;
     1079                                std::cerr << "cost of conversion is:" << cvtCost << std::endl;
     1080                        )
     1081
     1082                        if ( cvtCost != Cost::infinity ) {
     1083                                withFunc->cvtCost = cvtCost;
     1084                                candidates.emplace_back( std::move( withFunc ) );
     1085                        }
     1086                }
     1087                found = std::move( candidates );
     1088
     1089                // use a new list so that candidates are not examined by addAnonConversions twice
     1090                CandidateList winners = findMinCost( found );
     1091                promoteCvtCost( winners );
     1092
     1093                // function may return a struct/union value, in which case we need to add candidates
     1094                // for implicit conversions to each of the anonymous members, which must happen after
     1095                // `findMinCost`, since anon conversions are never the cheapest
     1096                for ( const CandidateRef & c : winners ) {
     1097                        addAnonConversions( c );
     1098                }
     1099                spliceBegin( candidates, winners );
     1100
     1101                if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
     1102                        // If resolution is unsuccessful with a target type, try again without, since it
     1103                        // will sometimes succeed when it wouldn't with a target type binding.
     1104                        // For example:
     1105                        //   forall( otype T ) T & ?[]( T *, ptrdiff_t );
     1106                        //   const char * x = "hello world";
     1107                        //   unsigned char ch = x[0];
     1108                        // Fails with simple return type binding (xxx -- check this!) as follows:
     1109                        // * T is bound to unsigned char
     1110                        // * (x: const char *) is unified with unsigned char *, which fails
     1111                        // xxx -- fix this better
     1112                        targetType = nullptr;
     1113                        postvisit( untypedExpr );
     1114                }
     1115        }
     1116
     1117        void Finder::postvisit( const ast::AddressExpr * addressExpr ) {
     1118                CandidateFinder finder( context, tenv );
     1119                finder.find( addressExpr->arg );
     1120
     1121                if ( finder.candidates.empty() ) return;
     1122
     1123                reason.code = NoMatch;
     1124
     1125                for ( CandidateRef & r : finder.candidates ) {
     1126                        if ( ! isLvalue( r->expr ) ) continue;
     1127                        addCandidate( *r, new ast::AddressExpr{ addressExpr->location, r->expr } );
     1128                }
     1129        }
     1130
     1131        void Finder::postvisit( const ast::LabelAddressExpr * labelExpr ) {
     1132                addCandidate( labelExpr, tenv );
     1133        }
     1134
     1135        void Finder::postvisit( const ast::CastExpr * castExpr ) {
     1136                ast::ptr< ast::Type > toType = castExpr->result;
     1137                assert( toType );
     1138                toType = resolveTypeof( toType, context );
     1139                toType = adjustExprType( toType, tenv, symtab );
     1140
     1141                CandidateFinder finder( context, tenv, toType );
     1142                finder.find( castExpr->arg, ResolvMode::withAdjustment() );
     1143
     1144                if ( !finder.candidates.empty() ) reason.code = NoMatch;
     1145
     1146                CandidateList matches;
     1147                for ( CandidateRef & cand : finder.candidates ) {
     1148                        ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
     1149                        ast::OpenVarSet open( cand->open );
     1150
     1151                        cand->env.extractOpenVars( open );
     1152
     1153                        // It is possible that a cast can throw away some values in a multiply-valued
     1154                        // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the
     1155                        // subexpression results that are cast directly. The candidate is invalid if it
     1156                        // has fewer results than there are types to cast to.
     1157                        int discardedValues = cand->expr->result->size() - toType->size();
     1158                        if ( discardedValues < 0 ) continue;
     1159
     1160                        // unification run for side-effects
     1161                        unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
     1162                        Cost thisCost =
     1163                                (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast)
     1164                                        ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env )
     1165                                        : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env );
     1166
     1167                        PRINT(
     1168                                std::cerr << "working on cast with result: " << toType << std::endl;
     1169                                std::cerr << "and expr type: " << cand->expr->result << std::endl;
     1170                                std::cerr << "env: " << cand->env << std::endl;
     1171                        )
     1172                        if ( thisCost != Cost::infinity ) {
     1173                                PRINT(
     1174                                        std::cerr << "has finite cost." << std::endl;
     1175                                )
     1176                                // count one safe conversion for each value that is thrown away
     1177                                thisCost.incSafe( discardedValues );
     1178                                CandidateRef newCand = std::make_shared<Candidate>(
     1179                                        restructureCast( cand->expr, toType, castExpr->isGenerated ),
     1180                                        copy( cand->env ), std::move( open ), std::move( need ), cand->cost,
     1181                                        cand->cost + thisCost );
     1182                                inferParameters( newCand, matches );
     1183                        }
     1184                }
     1185
     1186                // select first on argument cost, then conversion cost
     1187                CandidateList minArgCost = findMinCost( matches );
     1188                promoteCvtCost( minArgCost );
     1189                candidates = findMinCost( minArgCost );
     1190        }
     1191
     1192        void Finder::postvisit( const ast::VirtualCastExpr * castExpr ) {
     1193                assertf( castExpr->result, "Implicit virtual cast targets not yet supported." );
     1194                CandidateFinder finder( context, tenv );
     1195                // don't prune here, all alternatives guaranteed to have same type
     1196                finder.find( castExpr->arg, ResolvMode::withoutPrune() );
     1197                for ( CandidateRef & r : finder.candidates ) {
     1198                        addCandidate(
     1199                                *r,
     1200                                new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
     1201                }
     1202        }
     1203
     1204        void Finder::postvisit( const ast::KeywordCastExpr * castExpr ) {
     1205                const auto & loc = castExpr->location;
     1206                assertf( castExpr->result, "Cast target should have been set in Validate." );
     1207                auto ref = castExpr->result.strict_as<ast::ReferenceType>();
     1208                auto inst = ref->base.strict_as<ast::StructInstType>();
     1209                auto target = inst->base.get();
     1210
     1211                CandidateFinder finder( context, tenv );
     1212
     1213                auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) {
     1214                        for (auto & cand : found) {
     1215                                const ast::Type * expr = cand->expr->result.get();
     1216                                if (expect_ref) {
     1217                                        auto res = dynamic_cast<const ast::ReferenceType*>(expr);
     1218                                        if (!res) { continue; }
     1219                                        expr = res->base.get();
     1220                                }
     1221
     1222                                if (auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) {
     1223                                        auto td = cand->env.lookup(*insttype);
     1224                                        if (!td) { continue; }
     1225                                        expr = td->bound.get();
     1226                                }
     1227
     1228                                if (auto base = dynamic_cast<const ast::StructInstType*>(expr)) {
     1229                                        if (base->base == target) {
     1230                                                candidates.push_back( std::move(cand) );
     1231                                                reason.code = NoReason;
     1232                                        }
     1233                                }
     1234                        }
     1235                };
     1236
     1237                try {
     1238                        // Attempt 1 : turn (thread&)X into (thread$&)X.__thrd
     1239                        // Clone is purely for memory management
     1240                        std::unique_ptr<const ast::Expr> tech1 { new ast::UntypedMemberExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.field), castExpr->arg) };
     1241
     1242                        // don't prune here, since it's guaranteed all alternatives will have the same type
     1243                        finder.find( tech1.get(), ResolvMode::withoutPrune() );
     1244                        pick_alternatives(finder.candidates, false);
     1245
     1246                        return;
     1247                } catch(SemanticErrorException & ) {}
     1248
     1249                // Fallback : turn (thread&)X into (thread$&)get_thread(X)
     1250                std::unique_ptr<const ast::Expr> fallback { ast::UntypedExpr::createDeref(loc,  new ast::UntypedExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.getter), { castExpr->arg })) };
     1251                // don't prune here, since it's guaranteed all alternatives will have the same type
     1252                finder.find( fallback.get(), ResolvMode::withoutPrune() );
     1253
     1254                pick_alternatives(finder.candidates, true);
     1255
     1256                // Whatever happens here, we have no more fallbacks
     1257        }
     1258
     1259        void Finder::postvisit( const ast::UntypedMemberExpr * memberExpr ) {
     1260                CandidateFinder aggFinder( context, tenv );
     1261                aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
     1262                for ( CandidateRef & agg : aggFinder.candidates ) {
     1263                        // it's okay for the aggregate expression to have reference type -- cast it to the
     1264                        // base type to treat the aggregate as the referenced value
     1265                        Cost addedCost = Cost::zero;
     1266                        agg->expr = referenceToRvalueConversion( agg->expr, addedCost );
     1267
     1268                        // find member of the given type
     1269                        if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
     1270                                addAggMembers(
     1271                                        structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
     1272                        } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
     1273                                addAggMembers(
     1274                                        unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
     1275                        } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
     1276                                addTupleMembers( tupleType, agg->expr, *agg, addedCost, memberExpr->member );
     1277                        }
     1278                }
     1279        }
     1280
     1281        void Finder::postvisit( const ast::MemberExpr * memberExpr ) {
     1282                addCandidate( memberExpr, tenv );
     1283        }
     1284
     1285        void Finder::postvisit( const ast::NameExpr * nameExpr ) {
     1286                std::vector< ast::SymbolTable::IdData > declList;
     1287                if (!selfFinder.otypeKeys.empty()) {
     1288                        auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);
     1289                        assertf(kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS, "special lookup with non-special target: %s", nameExpr->name.c_str());
     1290
     1291                        for (auto & otypeKey: selfFinder.otypeKeys) {
     1292                                auto result = symtab.specialLookupId(kind, otypeKey);
     1293                                declList.insert(declList.end(), std::make_move_iterator(result.begin()), std::make_move_iterator(result.end()));
     1294                        }
     1295                } else {
     1296                        declList = symtab.lookupId( nameExpr->name );
     1297                }
     1298                PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
     1299
     1300                if ( declList.empty() ) return;
     1301
     1302                reason.code = NoMatch;
     1303
     1304                for ( auto & data : declList ) {
     1305                        Cost cost = Cost::zero;
     1306                        ast::Expr * newExpr = data.combine( nameExpr->location, cost );
     1307
     1308                        CandidateRef newCand = std::make_shared<Candidate>(
     1309                                newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
     1310                                cost );
     1311
     1312                        if (newCand->expr->env) {
     1313                                newCand->env.add(*newCand->expr->env);
     1314                                auto mutExpr = newCand->expr.get_and_mutate();
     1315                                mutExpr->env  = nullptr;
     1316                                newCand->expr = mutExpr;
     1317                        }
     1318
     1319                        PRINT(
     1320                                std::cerr << "decl is ";
     1321                                ast::print( std::cerr, data.id );
     1322                                std::cerr << std::endl;
     1323                                std::cerr << "newExpr is ";
     1324                                ast::print( std::cerr, newExpr );
     1325                                std::cerr << std::endl;
     1326                        )
     1327                        newCand->expr = ast::mutate_field(
     1328                                newCand->expr.get(), &ast::Expr::result,
     1329                                renameTyVars( newCand->expr->result ) );
     1330                        // add anonymous member interpretations whenever an aggregate value type is seen
     1331                        // as a name expression
     1332                        addAnonConversions( newCand );
     1333                        candidates.emplace_back( std::move( newCand ) );
     1334                }
     1335        }
     1336
     1337        void Finder::postvisit( const ast::VariableExpr * variableExpr ) {
     1338                // not sufficient to just pass `variableExpr` here, type might have changed since
     1339                // creation
     1340                addCandidate(
     1341                        new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
     1342        }
     1343
     1344        void Finder::postvisit( const ast::ConstantExpr * constantExpr ) {
     1345                addCandidate( constantExpr, tenv );
     1346        }
     1347
     1348        void Finder::postvisit( const ast::SizeofExpr * sizeofExpr ) {
     1349                if ( sizeofExpr->type ) {
     1350                        addCandidate(
     1351                                new ast::SizeofExpr{
     1352                                        sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) },
     1353                                tenv );
     1354                } else {
     1355                        // find all candidates for the argument to sizeof
     1356                        CandidateFinder finder( context, tenv );
     1357                        finder.find( sizeofExpr->expr );
     1358                        // find the lowest-cost candidate, otherwise ambiguous
     1359                        CandidateList winners = findMinCost( finder.candidates );
     1360                        if ( winners.size() != 1 ) {
     1361                                SemanticError(
     1362                                        sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
     1363                        }
     1364                        // return the lowest-cost candidate
     1365                        CandidateRef & choice = winners.front();
     1366                        choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
     1367                        choice->cost = Cost::zero;
     1368                        addCandidate( *choice, new ast::SizeofExpr{ sizeofExpr->location, choice->expr } );
     1369                }
     1370        }
     1371
     1372        void Finder::postvisit( const ast::AlignofExpr * alignofExpr ) {
     1373                if ( alignofExpr->type ) {
     1374                        addCandidate(
     1375                                new ast::AlignofExpr{
     1376                                        alignofExpr->location, resolveTypeof( alignofExpr->type, context ) },
     1377                                tenv );
     1378                } else {
     1379                        // find all candidates for the argument to alignof
     1380                        CandidateFinder finder( context, tenv );
     1381                        finder.find( alignofExpr->expr );
     1382                        // find the lowest-cost candidate, otherwise ambiguous
     1383                        CandidateList winners = findMinCost( finder.candidates );
     1384                        if ( winners.size() != 1 ) {
     1385                                SemanticError(
     1386                                        alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
     1387                        }
     1388                        // return the lowest-cost candidate
     1389                        CandidateRef & choice = winners.front();
     1390                        choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
     1391                        choice->cost = Cost::zero;
     1392                        addCandidate(
     1393                                *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
     1394                }
     1395        }
     1396
     1397        void Finder::postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {
     1398                const ast::BaseInstType * aggInst;
     1399                if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ;
     1400                else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ;
     1401                else return;
     1402
     1403                for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
     1404                        auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
     1405                        addCandidate(
     1406                                new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
     1407                }
     1408        }
     1409
     1410        void Finder::postvisit( const ast::OffsetofExpr * offsetofExpr ) {
     1411                addCandidate( offsetofExpr, tenv );
     1412        }
     1413
     1414        void Finder::postvisit( const ast::OffsetPackExpr * offsetPackExpr ) {
     1415                addCandidate( offsetPackExpr, tenv );
     1416        }
     1417
     1418        void Finder::postvisit( const ast::LogicalExpr * logicalExpr ) {
     1419                CandidateFinder finder1( context, tenv );
     1420                finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() );
     1421                if ( finder1.candidates.empty() ) return;
     1422
     1423                CandidateFinder finder2( context, tenv );
     1424                finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
     1425                if ( finder2.candidates.empty() ) return;
     1426
     1427                reason.code = NoMatch;
     1428
     1429                for ( const CandidateRef & r1 : finder1.candidates ) {
     1430                        for ( const CandidateRef & r2 : finder2.candidates ) {
     1431                                ast::TypeEnvironment env{ r1->env };
     1432                                env.simpleCombine( r2->env );
     1433                                ast::OpenVarSet open{ r1->open };
     1434                                mergeOpenVars( open, r2->open );
     1435                                ast::AssertionSet need;
     1436                                mergeAssertionSet( need, r1->need );
     1437                                mergeAssertionSet( need, r2->need );
     1438
     1439                                addCandidate(
     1440                                        new ast::LogicalExpr{
     1441                                                logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
     1442                                        std::move( env ), std::move( open ), std::move( need ), r1->cost + r2->cost );
     1443                        }
     1444                }
     1445        }
     1446
     1447        void Finder::postvisit( const ast::ConditionalExpr * conditionalExpr ) {
     1448                // candidates for condition
     1449                CandidateFinder finder1( context, tenv );
     1450                finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );
     1451                if ( finder1.candidates.empty() ) return;
     1452
     1453                // candidates for true result
     1454                CandidateFinder finder2( context, tenv );
     1455                finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );
     1456                if ( finder2.candidates.empty() ) return;
     1457
     1458                // candidates for false result
     1459                CandidateFinder finder3( context, tenv );
     1460                finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
     1461                if ( finder3.candidates.empty() ) return;
     1462
     1463                reason.code = NoMatch;
     1464
     1465                for ( const CandidateRef & r1 : finder1.candidates ) {
     1466                        for ( const CandidateRef & r2 : finder2.candidates ) {
     1467                                for ( const CandidateRef & r3 : finder3.candidates ) {
     1468                                        ast::TypeEnvironment env{ r1->env };
     1469                                        env.simpleCombine( r2->env );
     1470                                        env.simpleCombine( r3->env );
     1471                                        ast::OpenVarSet open{ r1->open };
     1472                                        mergeOpenVars( open, r2->open );
     1473                                        mergeOpenVars( open, r3->open );
     1474                                        ast::AssertionSet need;
     1475                                        mergeAssertionSet( need, r1->need );
     1476                                        mergeAssertionSet( need, r2->need );
     1477                                        mergeAssertionSet( need, r3->need );
     1478                                        ast::AssertionSet have;
     1479
     1480                                        // unify true and false results, then infer parameters to produce new
     1481                                        // candidates
     1482                                        ast::ptr< ast::Type > common;
     1483                                        if (
     1484                                                unify(
     1485                                                        r2->expr->result, r3->expr->result, env, need, have, open, symtab,
     1486                                                        common )
     1487                                        ) {
     1488                                                // generate typed expression
     1489                                                ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
     1490                                                        conditionalExpr->location, r1->expr, r2->expr, r3->expr };
     1491                                                newExpr->result = common ? common : r2->expr->result;
     1492                                                // convert both options to result type
     1493                                                Cost cost = r1->cost + r2->cost + r3->cost;
     1494                                                newExpr->arg2 = computeExpressionConversionCost(
     1495                                                        newExpr->arg2, newExpr->result, symtab, env, cost );
     1496                                                newExpr->arg3 = computeExpressionConversionCost(
     1497                                                        newExpr->arg3, newExpr->result, symtab, env, cost );
     1498                                                // output candidate
     1499                                                CandidateRef newCand = std::make_shared<Candidate>(
     1500                                                        newExpr, std::move( env ), std::move( open ), std::move( need ), cost );
     1501                                                inferParameters( newCand, candidates );
     1502                                        }
     1503                                }
     1504                        }
     1505                }
     1506        }
     1507
     1508        void Finder::postvisit( const ast::CommaExpr * commaExpr ) {
     1509                ast::TypeEnvironment env{ tenv };
     1510                ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env );
     1511
     1512                CandidateFinder finder2( context, env );
     1513                finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
     1514
     1515                for ( const CandidateRef & r2 : finder2.candidates ) {
     1516                        addCandidate( *r2, new ast::CommaExpr{ commaExpr->location, arg1, r2->expr } );
     1517                }
     1518        }
     1519
     1520        void Finder::postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ) {
     1521                addCandidate( ctorExpr, tenv );
     1522        }
     1523
     1524        void Finder::postvisit( const ast::ConstructorExpr * ctorExpr ) {
     1525                CandidateFinder finder( context, tenv );
     1526                finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() );
     1527                for ( CandidateRef & r : finder.candidates ) {
     1528                        addCandidate( *r, new ast::ConstructorExpr{ ctorExpr->location, r->expr } );
     1529                }
     1530        }
     1531
     1532        void Finder::postvisit( const ast::RangeExpr * rangeExpr ) {
     1533                // resolve low and high, accept candidates where low and high types unify
     1534                CandidateFinder finder1( context, tenv );
     1535                finder1.find( rangeExpr->low, ResolvMode::withAdjustment() );
     1536                if ( finder1.candidates.empty() ) return;
     1537
     1538                CandidateFinder finder2( context, tenv );
     1539                finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
     1540                if ( finder2.candidates.empty() ) return;
     1541
     1542                reason.code = NoMatch;
     1543
     1544                for ( const CandidateRef & r1 : finder1.candidates ) {
     1545                        for ( const CandidateRef & r2 : finder2.candidates ) {
     1546                                ast::TypeEnvironment env{ r1->env };
     1547                                env.simpleCombine( r2->env );
     1548                                ast::OpenVarSet open{ r1->open };
     1549                                mergeOpenVars( open, r2->open );
     1550                                ast::AssertionSet need;
     1551                                mergeAssertionSet( need, r1->need );
     1552                                mergeAssertionSet( need, r2->need );
     1553                                ast::AssertionSet have;
     1554
     1555                                ast::ptr< ast::Type > common;
     1556                                if (
     1557                                        unify(
     1558                                                r1->expr->result, r2->expr->result, env, need, have, open, symtab,
     1559                                                common )
     1560                                ) {
     1561                                        // generate new expression
     1562                                        ast::RangeExpr * newExpr =
     1563                                                new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
     1564                                        newExpr->result = common ? common : r1->expr->result;
     1565                                        // add candidate
     1566                                        CandidateRef newCand = std::make_shared<Candidate>(
     1567                                                newExpr, std::move( env ), std::move( open ), std::move( need ),
     1568                                                r1->cost + r2->cost );
     1569                                        inferParameters( newCand, candidates );
     1570                                }
     1571                        }
     1572                }
     1573        }
     1574
     1575        void Finder::postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
     1576                std::vector< CandidateFinder > subCandidates =
     1577                        selfFinder.findSubExprs( tupleExpr->exprs );
     1578                std::vector< CandidateList > possibilities;
     1579                combos( subCandidates.begin(), subCandidates.end(), back_inserter( possibilities ) );
     1580
     1581                for ( const CandidateList & subs : possibilities ) {
     1582                        std::vector< ast::ptr< ast::Expr > > exprs;
     1583                        exprs.reserve( subs.size() );
     1584                        for ( const CandidateRef & sub : subs ) { exprs.emplace_back( sub->expr ); }
     1585
     1586                        ast::TypeEnvironment env;
     1587                        ast::OpenVarSet open;
     1588                        ast::AssertionSet need;
     1589                        for ( const CandidateRef & sub : subs ) {
     1590                                env.simpleCombine( sub->env );
     1591                                mergeOpenVars( open, sub->open );
     1592                                mergeAssertionSet( need, sub->need );
     1593                        }
     1594
     1595                        addCandidate(
     1596                                new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) },
     1597                                std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) );
     1598                }
     1599        }
     1600
     1601        void Finder::postvisit( const ast::TupleExpr * tupleExpr ) {
     1602                addCandidate( tupleExpr, tenv );
     1603        }
     1604
     1605        void Finder::postvisit( const ast::TupleIndexExpr * tupleExpr ) {
     1606                addCandidate( tupleExpr, tenv );
     1607        }
     1608
     1609        void Finder::postvisit( const ast::TupleAssignExpr * tupleExpr ) {
     1610                addCandidate( tupleExpr, tenv );
     1611        }
     1612
     1613        void Finder::postvisit( const ast::UniqueExpr * unqExpr ) {
     1614                CandidateFinder finder( context, tenv );
     1615                finder.find( unqExpr->expr, ResolvMode::withAdjustment() );
     1616                for ( CandidateRef & r : finder.candidates ) {
     1617                        // ensure that the the id is passed on so that the expressions are "linked"
     1618                        addCandidate( *r, new ast::UniqueExpr{ unqExpr->location, r->expr, unqExpr->id } );
     1619                }
     1620        }
     1621
     1622        void Finder::postvisit( const ast::StmtExpr * stmtExpr ) {
     1623                addCandidate( resolveStmtExpr( stmtExpr, context ), tenv );
     1624        }
     1625
     1626        void Finder::postvisit( const ast::UntypedInitExpr * initExpr ) {
     1627                // handle each option like a cast
     1628                CandidateList matches;
     1629                PRINT(
     1630                        std::cerr << "untyped init expr: " << initExpr << std::endl;
     1631                )
     1632                // O(n^2) checks of d-types with e-types
     1633                for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) {
     1634                        // calculate target type
     1635                        const ast::Type * toType = resolveTypeof( initAlt.type, context );
     1636                        toType = adjustExprType( toType, tenv, symtab );
     1637                        // The call to find must occur inside this loop, otherwise polymorphic return
     1638                        // types are not bound to the initialization type, since return type variables are
     1639                        // only open for the duration of resolving the UntypedExpr.
     1640                        CandidateFinder finder( context, tenv, toType );
     1641                        finder.find( initExpr->expr, ResolvMode::withAdjustment() );
     1642                        for ( CandidateRef & cand : finder.candidates ) {
     1643                                if (reason.code == NotFound) reason.code = NoMatch;
     1644
     1645                                ast::TypeEnvironment env{ cand->env };
     1646                                ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
     1647                                ast::OpenVarSet open{ cand->open };
     1648
     1649                                PRINT(
     1650                                        std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
     1651                                )
     1652
     1653                                // It is possible that a cast can throw away some values in a multiply-valued
     1654                                // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of
     1655                                // the subexpression results that are cast directly. The candidate is invalid
     1656                                // if it has fewer results than there are types to cast to.
     1657                                int discardedValues = cand->expr->result->size() - toType->size();
     1658                                if ( discardedValues < 0 ) continue;
     1659
     1660                                // unification run for side-effects
     1661                                bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab );
     1662                                (void) canUnify;
     1663                                Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1664                                        symtab, env );
     1665                                PRINT(
     1666                                        Cost legacyCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
     1667                                                symtab, env );
     1668                                        std::cerr << "Considering initialization:";
     1669                                        std::cerr << std::endl << "  FROM: " << cand->expr->result << std::endl;
     1670                                        std::cerr << std::endl << "  TO: "   << toType             << std::endl;
     1671                                        std::cerr << std::endl << "  Unification " << (canUnify ? "succeeded" : "failed");
     1672                                        std::cerr << std::endl << "  Legacy cost " << legacyCost;
     1673                                        std::cerr << std::endl << "  New cost " << thisCost;
     1674                                        std::cerr << std::endl;
     1675                                )
     1676                                if ( thisCost != Cost::infinity ) {
     1677                                        // count one safe conversion for each value that is thrown away
     1678                                        thisCost.incSafe( discardedValues );
     1679                                        CandidateRef newCand = std::make_shared<Candidate>(
     1680                                                new ast::InitExpr{
     1681                                                        initExpr->location, restructureCast( cand->expr, toType ),
     1682                                                        initAlt.designation },
     1683                                                std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost );
     1684                                        inferParameters( newCand, matches );
     1685                                }
     1686                        }
     1687                }
     1688
     1689                // select first on argument cost, then conversion cost
     1690                CandidateList minArgCost = findMinCost( matches );
     1691                promoteCvtCost( minArgCost );
     1692                candidates = findMinCost( minArgCost );
     1693        }
     1694
     1695        // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder");
     1696        /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
     1697        /// return type. Skips ambiguous candidates.
     1698
     1699} // anonymous namespace
     1700
     1701bool CandidateFinder::pruneCandidates( CandidateList & candidates, CandidateList & out, std::vector<std::string> & errors ) {
     1702        struct PruneStruct {
     1703                CandidateRef candidate;
     1704                bool ambiguous;
     1705
     1706                PruneStruct() = default;
     1707                PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}
     1708        };
     1709
     1710        // find lowest-cost candidate for each type
     1711        std::unordered_map< std::string, PruneStruct > selected;
     1712        // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found
     1713        std::sort(candidates.begin(), candidates.end(), [](const CandidateRef & x, const CandidateRef & y){return x->cost < y->cost;});
     1714        for ( CandidateRef & candidate : candidates ) {
     1715                std::string mangleName;
     1716                {
     1717                        ast::ptr< ast::Type > newType = candidate->expr->result;
     1718                        assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
     1719                        candidate->env.apply( newType );
     1720                        mangleName = Mangle::mangle( newType );
     1721                }
     1722
     1723                auto found = selected.find( mangleName );
     1724                if (found != selected.end() && found->second.candidate->cost < candidate->cost) {
     1725                        PRINT(
     1726                                std::cerr << "cost " << candidate->cost << " loses to "
     1727                                        << found->second.candidate->cost << std::endl;
     1728                        )
     1729                        continue;
     1730                }
     1731
     1732                // xxx - when do satisfyAssertions produce more than 1 result?
     1733                // this should only happen when initial result type contains
     1734                // unbound type parameters, then it should never be pruned by
     1735                // the previous step, since renameTyVars guarantees the mangled name
     1736                // is unique.
     1737                CandidateList satisfied;
     1738                bool needRecomputeKey = false;
     1739                if (candidate->need.empty()) {
     1740                        satisfied.emplace_back(candidate);
     1741                }
     1742                else {
     1743                        satisfyAssertions(candidate, context.symtab, satisfied, errors);
     1744                        needRecomputeKey = true;
     1745                }
     1746
     1747                for (auto & newCand : satisfied) {
     1748                        // recomputes type key, if satisfyAssertions changed it
     1749                        if (needRecomputeKey)
     1750                        {
     1751                                ast::ptr< ast::Type > newType = newCand->expr->result;
     1752                                assertf(newCand->expr->result, "Result of expression %p for candidate is null", newCand->expr.get());
     1753                                newCand->env.apply( newType );
     1754                                mangleName = Mangle::mangle( newType );
     1755                        }
     1756                        auto found = selected.find( mangleName );
     1757                        if ( found != selected.end() ) {
     1758                                if ( newCand->cost < found->second.candidate->cost ) {
     1759                                        PRINT(
     1760                                                std::cerr << "cost " << newCand->cost << " beats "
     1761                                                        << found->second.candidate->cost << std::endl;
     1762                                        )
     1763
     1764                                        found->second = PruneStruct{ newCand };
     1765                                } else if ( newCand->cost == found->second.candidate->cost ) {
     1766                                        // if one of the candidates contains a deleted identifier, can pick the other,
     1767                                        // since deleted expressions should not be ambiguous if there is another option
     1768                                        // that is at least as good
     1769                                        if ( findDeletedExpr( newCand->expr ) ) {
     1770                                                // do nothing
     1771                                                PRINT( std::cerr << "candidate is deleted" << std::endl; )
     1772                                        } else if ( findDeletedExpr( found->second.candidate->expr ) ) {
     1773                                                PRINT( std::cerr << "current is deleted" << std::endl; )
     1774                                                found->second = PruneStruct{ newCand };
     1775                                        } else {
     1776                                                PRINT( std::cerr << "marking ambiguous" << std::endl; )
     1777                                                found->second.ambiguous = true;
     1778                                        }
     1779                                } else {
     1780                                        // xxx - can satisfyAssertions increase the cost?
     1781                                        PRINT(
     1782                                                std::cerr << "cost " << newCand->cost << " loses to "
     1783                                                        << found->second.candidate->cost << std::endl;
     1784                                        )
     1785                                }
     1786                        } else {
     1787                                selected.emplace_hint( found, mangleName, newCand );
     1788                        }
     1789                }
     1790        }
     1791
     1792        // report unambiguous min-cost candidates
     1793        // CandidateList out;
     1794        for ( auto & target : selected ) {
     1795                if ( target.second.ambiguous ) continue;
     1796
     1797                CandidateRef cand = target.second.candidate;
     1798
     1799                ast::ptr< ast::Type > newResult = cand->expr->result;
     1800                cand->env.applyFree( newResult );
     1801                cand->expr = ast::mutate_field(
     1802                        cand->expr.get(), &ast::Expr::result, std::move( newResult ) );
     1803
     1804                out.emplace_back( cand );
     1805        }
     1806        // if everything is lost in satisfyAssertions, report the error
     1807        return !selected.empty();
     1808}
     1809
     1810void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) {
     1811        // Find alternatives for expression
     1812        ast::Pass<Finder> finder{ *this };
     1813        expr->accept( finder );
     1814
     1815        if ( mode.failFast && candidates.empty() ) {
     1816                switch(finder.core.reason.code) {
     1817                case Finder::NotFound:
     1818                        { SemanticError( expr, "No alternatives for expression " ); break; }
     1819                case Finder::NoMatch:
     1820                        { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; }
     1821                case Finder::ArgsToFew:
     1822                case Finder::ArgsToMany:
     1823                case Finder::RetsToFew:
     1824                case Finder::RetsToMany:
     1825                case Finder::NoReason:
     1826                default:
     1827                        { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); }
     1828                }
     1829        }
     1830
     1831        /*
     1832        if ( mode.satisfyAssns || mode.prune ) {
     1833                // trim candidates to just those where the assertions are satisfiable
     1834                // - necessary pre-requisite to pruning
     1835                CandidateList satisfied;
     1836                std::vector< std::string > errors;
     1837                for ( CandidateRef & candidate : candidates ) {
     1838                        satisfyAssertions( candidate, localSyms, satisfied, errors );
     1839                }
     1840
     1841                // fail early if none such
     1842                if ( mode.failFast && satisfied.empty() ) {
     1843                        std::ostringstream stream;
     1844                        stream << "No alternatives with satisfiable assertions for " << expr << "\n";
     1845                        for ( const auto& err : errors ) {
     1846                                stream << err;
     1847                        }
     1848                        SemanticError( expr->location, stream.str() );
     1849                }
     1850
     1851                // reset candidates
     1852                candidates = move( satisfied );
     1853        }
     1854        */
     1855
     1856        if ( mode.prune ) {
     1857                // trim candidates to single best one
     1858                PRINT(
     1859                        std::cerr << "alternatives before prune:" << std::endl;
     1860                        print( std::cerr, candidates );
     1861                )
     1862
     1863                CandidateList pruned;
     1864                std::vector<std::string> errors;
     1865                bool found = pruneCandidates( candidates, pruned, errors );
     1866
     1867                if ( mode.failFast && pruned.empty() ) {
     1868                        std::ostringstream stream;
     1869                        if (found) {
     1870                                CandidateList winners = findMinCost( candidates );
     1871                                stream << "Cannot choose between " << winners.size() << " alternatives for "
     1872                                        "expression\n";
     1873                                ast::print( stream, expr );
     1874                                stream << " Alternatives are:\n";
     1875                                print( stream, winners, 1 );
     1876                                SemanticError( expr->location, stream.str() );
     1877                        }
     1878                        else {
     1879                                stream << "No alternatives with satisfiable assertions for " << expr << "\n";
     1880                                for ( const auto& err : errors ) {
     1881                                        stream << err;
     1882                                }
     1883                                SemanticError( expr->location, stream.str() );
     1884                        }
     1885                }
     1886
     1887                auto oldsize = candidates.size();
     1888                candidates = std::move( pruned );
     1889
     1890                PRINT(
     1891                        std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl;
     1892                )
     1893                PRINT(
     1894                        std::cerr << "there are " << candidates.size() << " alternatives after elimination"
     1895                                << std::endl;
     1896                )
     1897        }
     1898
     1899        // adjust types after pruning so that types substituted by pruneAlternatives are correctly
     1900        // adjusted
     1901        if ( mode.adjust ) {
     1902                for ( CandidateRef & r : candidates ) {
     1903                        r->expr = ast::mutate_field(
     1904                                r->expr.get(), &ast::Expr::result,
     1905                                adjustExprType( r->expr->result, r->env, context.symtab ) );
     1906                }
     1907        }
     1908
     1909        // Central location to handle gcc extension keyword, etc. for all expressions
     1910        for ( CandidateRef & r : candidates ) {
     1911                if ( r->expr->extension != expr->extension ) {
     1912                        r->expr.get_and_mutate()->extension = expr->extension;
     1913                }
     1914        }
     1915}
     1916
     1917std::vector< CandidateFinder > CandidateFinder::findSubExprs(
     1918        const std::vector< ast::ptr< ast::Expr > > & xs
     1919) {
     1920        std::vector< CandidateFinder > out;
     1921
     1922        for ( const auto & x : xs ) {
     1923                out.emplace_back( context, env );
     1924                out.back().find( x, ResolvMode::withAdjustment() );
     1925
     1926                PRINT(
     1927                        std::cerr << "findSubExprs" << std::endl;
     1928                        print( std::cerr, out.back().candidates );
     1929                )
     1930        }
     1931
     1932        return out;
     1933}
     1934
    571935const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) {
    581936        if ( expr->result.as< ast::ReferenceType >() ) {
     
    641942        return expr;
    651943}
    66 
    67 /// Unique identifier for matching expression resolutions to their requesting expression
    68 UniqueId globalResnSlot = 0;
    691944
    701945Cost computeConversionCost(
     
    931968}
    941969
    95 namespace {
    96         /// First index is which argument, second is which alternative, third is which exploded element
    97         using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >;
    98 
    99         /// Returns a list of alternatives with the minimum cost in the given list
    100         CandidateList findMinCost( const CandidateList & candidates ) {
    101                 CandidateList out;
    102                 Cost minCost = Cost::infinity;
    103                 for ( const CandidateRef & r : candidates ) {
    104                         if ( r->cost < minCost ) {
    105                                 minCost = r->cost;
    106                                 out.clear();
    107                                 out.emplace_back( r );
    108                         } else if ( r->cost == minCost ) {
    109                                 out.emplace_back( r );
    110                         }
    111                 }
    112                 return out;
    113         }
    114 
    115         /// Computes conversion cost for a given expression to a given type
    116         const ast::Expr * computeExpressionConversionCost(
    117                 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost
    118         ) {
    119                 Cost convCost = computeConversionCost(
    120                                 arg->result, paramType, arg->get_lvalue(), symtab, env );
    121                 outCost += convCost;
    122 
    123                 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires
    124                 // conversion. Ignore poly cost for now, since this requires resolution of the cast to
    125                 // infer parameters and this does not currently work for the reason stated below
    126                 Cost tmpCost = convCost;
    127                 tmpCost.incPoly( -tmpCost.get_polyCost() );
    128                 if ( tmpCost != Cost::zero ) {
    129                         ast::ptr< ast::Type > newType = paramType;
    130                         env.apply( newType );
    131                         return new ast::CastExpr{ arg, newType };
    132 
    133                         // xxx - *should* be able to resolve this cast, but at the moment pointers are not
    134                         // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,
    135                         // once this is fixed it should be possible to resolve the cast.
    136                         // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,
    137                         // but it shouldn't be because this makes the conversion from DT* to DT* since
    138                         // commontype(zero_t, DT*) is DT*, rather than nothing
    139 
    140                         // CandidateFinder finder{ symtab, env };
    141                         // finder.find( arg, ResolvMode::withAdjustment() );
    142                         // assertf( finder.candidates.size() > 0,
    143                         //      "Somehow castable expression failed to find alternatives." );
    144                         // assertf( finder.candidates.size() == 1,
    145                         //      "Somehow got multiple alternatives for known cast expression." );
    146                         // return finder.candidates.front()->expr;
    147                 }
    148 
    149                 return arg;
    150         }
    151 
    152         /// Computes conversion cost for a given candidate
    153         Cost computeApplicationConversionCost(
    154                 CandidateRef cand, const ast::SymbolTable & symtab
    155         ) {
    156                 auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();
    157                 auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    158                 auto function = pointer->base.strict_as< ast::FunctionType >();
    159 
    160                 Cost convCost = Cost::zero;
    161                 const auto & params = function->params;
    162                 auto param = params.begin();
    163                 auto & args = appExpr->args;
    164 
    165                 for ( unsigned i = 0; i < args.size(); ++i ) {
    166                         const ast::Type * argType = args[i]->result;
    167                         PRINT(
    168                                 std::cerr << "arg expression:" << std::endl;
    169                                 ast::print( std::cerr, args[i], 2 );
    170                                 std::cerr << "--- results are" << std::endl;
    171                                 ast::print( std::cerr, argType, 2 );
    172                         )
    173 
    174                         if ( param == params.end() ) {
    175                                 if ( function->isVarArgs ) {
    176                                         convCost.incUnsafe();
    177                                         PRINT( std::cerr << "end of params with varargs function: inc unsafe: "
    178                                                 << convCost << std::endl; ; )
    179                                         // convert reference-typed expressions into value-typed expressions
    180                                         cand->expr = ast::mutate_field_index(
    181                                                 appExpr, &ast::ApplicationExpr::args, i,
    182                                                 referenceToRvalueConversion( args[i], convCost ) );
    183                                         continue;
    184                                 } else return Cost::infinity;
    185                         }
    186 
    187                         if ( auto def = args[i].as< ast::DefaultArgExpr >() ) {
    188                                 // Default arguments should be free - don't include conversion cost.
    189                                 // Unwrap them here because they are not relevant to the rest of the system
    190                                 cand->expr = ast::mutate_field_index(
    191                                         appExpr, &ast::ApplicationExpr::args, i, def->expr );
    192                                 ++param;
    193                                 continue;
    194                         }
    195 
    196                         // mark conversion cost and also specialization cost of param type
    197                         // const ast::Type * paramType = (*param)->get_type();
    198                         cand->expr = ast::mutate_field_index(
    199                                 appExpr, &ast::ApplicationExpr::args, i,
    200                                 computeExpressionConversionCost(
    201                                         args[i], *param, symtab, cand->env, convCost ) );
    202                         convCost.decSpec( specCost( *param ) );
    203                         ++param;  // can't be in for-loop update because of the continue
    204                 }
    205 
    206                 if ( param != params.end() ) return Cost::infinity;
    207 
    208                 // specialization cost of return types can't be accounted for directly, it disables
    209                 // otherwise-identical calls, like this example based on auto-newline in the I/O lib:
    210                 //
    211                 //   forall(otype OS) {
    212                 //     void ?|?(OS&, int);  // with newline
    213                 //     OS&  ?|?(OS&, int);  // no newline, always chosen due to more specialization
    214                 //   }
    215 
    216                 // mark type variable and specialization cost of forall clause
    217                 convCost.incVar( function->forall.size() );
    218                 convCost.decSpec( function->assertions.size() );
    219 
    220                 return convCost;
    221         }
    222 
    223         void makeUnifiableVars(
    224                 const ast::FunctionType * type, ast::OpenVarSet & unifiableVars,
    225                 ast::AssertionSet & need
    226         ) {
    227                 for ( auto & tyvar : type->forall ) {
    228                         unifiableVars[ *tyvar ] = ast::TypeData{ tyvar->base };
    229                 }
    230                 for ( auto & assn : type->assertions ) {
    231                         need[ assn ].isUsed = true;
    232                 }
    233         }
    234 
    235         /// Gets a default value from an initializer, nullptr if not present
    236         const ast::ConstantExpr * getDefaultValue( const ast::Init * init ) {
    237                 if ( auto si = dynamic_cast< const ast::SingleInit * >( init ) ) {
    238                         if ( auto ce = si->value.as< ast::CastExpr >() ) {
    239                                 return ce->arg.as< ast::ConstantExpr >();
    240                         } else {
    241                                 return si->value.as< ast::ConstantExpr >();
    242                         }
    243                 }
    244                 return nullptr;
    245         }
    246 
    247         /// State to iteratively build a match of parameter expressions to arguments
    248         struct ArgPack {
    249                 std::size_t parent;          ///< Index of parent pack
    250                 ast::ptr< ast::Expr > expr;  ///< The argument stored here
    251                 Cost cost;                   ///< The cost of this argument
    252                 ast::TypeEnvironment env;    ///< Environment for this pack
    253                 ast::AssertionSet need;      ///< Assertions outstanding for this pack
    254                 ast::AssertionSet have;      ///< Assertions found for this pack
    255                 ast::OpenVarSet open;        ///< Open variables for this pack
    256                 unsigned nextArg;            ///< Index of next argument in arguments list
    257                 unsigned tupleStart;         ///< Number of tuples that start at this index
    258                 unsigned nextExpl;           ///< Index of next exploded element
    259                 unsigned explAlt;            ///< Index of alternative for nextExpl > 0
    260 
    261                 ArgPack()
    262                 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),
    263                   tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    264 
    265                 ArgPack(
    266                         const ast::TypeEnvironment & env, const ast::AssertionSet & need,
    267                         const ast::AssertionSet & have, const ast::OpenVarSet & open )
    268                 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),
    269                   open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}
    270 
    271                 ArgPack(
    272                         std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env,
    273                         ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open,
    274                         unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,
    275                         unsigned nextExpl = 0, unsigned explAlt = 0 )
    276                 : parent(parent), expr( expr ), cost( cost ), env( std::move( env ) ), need( std::move( need ) ),
    277                   have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),
    278                   nextExpl( nextExpl ), explAlt( explAlt ) {}
    279 
    280                 ArgPack(
    281                         const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,
    282                         ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )
    283                 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( std::move( env ) ),
    284                   need( std::move( need ) ), have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ),
    285                   tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}
    286 
    287                 /// true if this pack is in the middle of an exploded argument
    288                 bool hasExpl() const { return nextExpl > 0; }
    289 
    290                 /// Gets the list of exploded candidates for this pack
    291                 const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const {
    292                         return args[ nextArg-1 ][ explAlt ];
    293                 }
    294 
    295                 /// Ends a tuple expression, consolidating the appropriate args
    296                 void endTuple( const std::vector< ArgPack > & packs ) {
    297                         // add all expressions in tuple to list, summing cost
    298                         std::deque< const ast::Expr * > exprs;
    299                         const ArgPack * pack = this;
    300                         if ( expr ) { exprs.emplace_front( expr ); }
    301                         while ( pack->tupleStart == 0 ) {
    302                                 pack = &packs[pack->parent];
    303                                 exprs.emplace_front( pack->expr );
    304                                 cost += pack->cost;
    305                         }
    306                         // reset pack to appropriate tuple
    307                         std::vector< ast::ptr< ast::Expr > > exprv( exprs.begin(), exprs.end() );
    308                         expr = new ast::TupleExpr{ expr->location, std::move( exprv ) };
    309                         tupleStart = pack->tupleStart - 1;
    310                         parent = pack->parent;
    311                 }
    312         };
    313 
    314         /// Instantiates an argument to match a parameter, returns false if no matching results left
    315         bool instantiateArgument(
    316                 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,
    317                 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,
    318                 unsigned nTuples = 0
    319         ) {
    320                 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {
    321                         // paramType is a TupleType -- group args into a TupleExpr
    322                         ++nTuples;
    323                         for ( const ast::Type * type : *tupleType ) {
    324                                 // xxx - dropping initializer changes behaviour from previous, but seems correct
    325                                 // ^^^ need to handle the case where a tuple has a default argument
    326                                 if ( ! instantiateArgument(
    327                                         type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;
    328                                 nTuples = 0;
    329                         }
    330                         // re-constitute tuples for final generation
    331                         for ( auto i = genStart; i < results.size(); ++i ) {
    332                                 results[i].endTuple( results );
    333                         }
    334                         return true;
    335                 } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {
    336                         // paramType is a ttype, consumes all remaining arguments
    337 
    338                         // completed tuples; will be spliced to end of results to finish
    339                         std::vector< ArgPack > finalResults{};
    340 
    341                         // iterate until all results completed
    342                         std::size_t genEnd;
    343                         ++nTuples;
    344                         do {
    345                                 genEnd = results.size();
    346 
    347                                 // add another argument to results
    348                                 for ( std::size_t i = genStart; i < genEnd; ++i ) {
    349                                         unsigned nextArg = results[i].nextArg;
    350 
    351                                         // use next element of exploded tuple if present
    352                                         if ( results[i].hasExpl() ) {
    353                                                 const ExplodedArg & expl = results[i].getExpl( args );
    354 
    355                                                 unsigned nextExpl = results[i].nextExpl + 1;
    356                                                 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }
    357 
    358                                                 results.emplace_back(
    359                                                         i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
    360                                                         copy( results[i].need ), copy( results[i].have ),
    361                                                         copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,
    362                                                         results[i].explAlt );
    363 
    364                                                 continue;
    365                                         }
    366 
    367                                         // finish result when out of arguments
    368                                         if ( nextArg >= args.size() ) {
    369                                                 ArgPack newResult{
    370                                                         results[i].env, results[i].need, results[i].have, results[i].open };
    371                                                 newResult.nextArg = nextArg;
    372                                                 const ast::Type * argType = nullptr;
    373 
    374                                                 if ( nTuples > 0 || ! results[i].expr ) {
    375                                                         // first iteration or no expression to clone,
    376                                                         // push empty tuple expression
    377                                                         newResult.parent = i;
    378                                                         newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
    379                                                         argType = newResult.expr->result;
    380                                                 } else {
    381                                                         // clone result to collect tuple
    382                                                         newResult.parent = results[i].parent;
    383                                                         newResult.cost = results[i].cost;
    384                                                         newResult.tupleStart = results[i].tupleStart;
    385                                                         newResult.expr = results[i].expr;
    386                                                         argType = newResult.expr->result;
    387 
    388                                                         if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) {
    389                                                                 // the case where a ttype value is passed directly is special,
    390                                                                 // e.g. for argument forwarding purposes
    391                                                                 // xxx - what if passing multiple arguments, last of which is
    392                                                                 //       ttype?
    393                                                                 // xxx - what would happen if unify was changed so that unifying
    394                                                                 //       tuple
    395                                                                 // types flattened both before unifying lists? then pass in
    396                                                                 // TupleType (ttype) below.
    397                                                                 --newResult.tupleStart;
    398                                                         } else {
    399                                                                 // collapse leftover arguments into tuple
    400                                                                 newResult.endTuple( results );
    401                                                                 argType = newResult.expr->result;
    402                                                         }
    403                                                 }
    404 
    405                                                 // check unification for ttype before adding to final
    406                                                 if (
    407                                                         unify(
    408                                                                 ttype, argType, newResult.env, newResult.need, newResult.have,
    409                                                                 newResult.open, symtab )
    410                                                 ) {
    411                                                         finalResults.emplace_back( std::move( newResult ) );
    412                                                 }
    413 
    414                                                 continue;
    415                                         }
    416 
    417                                         // add each possible next argument
    418                                         for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {
    419                                                 const ExplodedArg & expl = args[nextArg][j];
    420 
    421                                                 // fresh copies of parent parameters for this iteration
    422                                                 ast::TypeEnvironment env = results[i].env;
    423                                                 ast::OpenVarSet open = results[i].open;
    424 
    425                                                 env.addActual( expl.env, open );
    426 
    427                                                 // skip empty tuple arguments by (nearly) cloning parent into next gen
    428                                                 if ( expl.exprs.empty() ) {
    429                                                         results.emplace_back(
    430                                                                 results[i], std::move( env ), copy( results[i].need ),
    431                                                                 copy( results[i].have ), std::move( open ), nextArg + 1, expl.cost );
    432 
    433                                                         continue;
    434                                                 }
    435 
    436                                                 // add new result
    437                                                 results.emplace_back(
    438                                                         i, expl.exprs.front(), std::move( env ), copy( results[i].need ),
    439                                                         copy( results[i].have ), std::move( open ), nextArg + 1, nTuples,
    440                                                         expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    441                                         }
    442                                 }
    443 
    444                                 // reset for next round
    445                                 genStart = genEnd;
    446                                 nTuples = 0;
    447                         } while ( genEnd != results.size() );
    448 
    449                         // splice final results onto results
    450                         for ( std::size_t i = 0; i < finalResults.size(); ++i ) {
    451                                 results.emplace_back( std::move( finalResults[i] ) );
    452                         }
    453                         return ! finalResults.empty();
    454                 }
    455 
    456                 // iterate each current subresult
    457                 std::size_t genEnd = results.size();
    458                 for ( std::size_t i = genStart; i < genEnd; ++i ) {
    459                         unsigned nextArg = results[i].nextArg;
    460 
    461                         // use remainder of exploded tuple if present
    462                         if ( results[i].hasExpl() ) {
    463                                 const ExplodedArg & expl = results[i].getExpl( args );
    464                                 const ast::Expr * expr = expl.exprs[ results[i].nextExpl ];
    465 
    466                                 ast::TypeEnvironment env = results[i].env;
    467                                 ast::AssertionSet need = results[i].need, have = results[i].have;
    468                                 ast::OpenVarSet open = results[i].open;
    469 
    470                                 const ast::Type * argType = expr->result;
    471 
    472                                 PRINT(
    473                                         std::cerr << "param type is ";
    474                                         ast::print( std::cerr, paramType );
    475                                         std::cerr << std::endl << "arg type is ";
    476                                         ast::print( std::cerr, argType );
    477                                         std::cerr << std::endl;
    478                                 )
    479 
    480                                 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {
    481                                         unsigned nextExpl = results[i].nextExpl + 1;
    482                                         if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }
    483 
    484                                         results.emplace_back(
    485                                                 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), nextArg,
    486                                                 nTuples, Cost::zero, nextExpl, results[i].explAlt );
    487                                 }
    488 
    489                                 continue;
    490                         }
    491 
    492                         // use default initializers if out of arguments
    493                         if ( nextArg >= args.size() ) {
    494                                 if ( const ast::ConstantExpr * cnst = getDefaultValue( init ) ) {
    495                                         ast::TypeEnvironment env = results[i].env;
    496                                         ast::AssertionSet need = results[i].need, have = results[i].have;
    497                                         ast::OpenVarSet open = results[i].open;
    498 
    499                                         if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {
    500                                                 results.emplace_back(
    501                                                         i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ),
    502                                                         std::move( need ), std::move( have ), std::move( open ), nextArg, nTuples );
    503                                         }
    504                                 }
    505 
    506                                 continue;
    507                         }
    508 
    509                         // Check each possible next argument
    510                         for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {
    511                                 const ExplodedArg & expl = args[nextArg][j];
    512 
    513                                 // fresh copies of parent parameters for this iteration
    514                                 ast::TypeEnvironment env = results[i].env;
    515                                 ast::AssertionSet need = results[i].need, have = results[i].have;
    516                                 ast::OpenVarSet open = results[i].open;
    517 
    518                                 env.addActual( expl.env, open );
    519 
    520                                 // skip empty tuple arguments by (nearly) cloning parent into next gen
    521                                 if ( expl.exprs.empty() ) {
    522                                         results.emplace_back(
    523                                                 results[i], std::move( env ), std::move( need ), std::move( have ), std::move( open ),
    524                                                 nextArg + 1, expl.cost );
    525 
    526                                         continue;
    527                                 }
    528 
    529                                 // consider only first exploded arg
    530                                 const ast::Expr * expr = expl.exprs.front();
    531                                 const ast::Type * argType = expr->result;
    532 
    533                                 PRINT(
    534                                         std::cerr << "param type is ";
    535                                         ast::print( std::cerr, paramType );
    536                                         std::cerr << std::endl << "arg type is ";
    537                                         ast::print( std::cerr, argType );
    538                                         std::cerr << std::endl;
    539                                 )
    540 
    541                                 // attempt to unify types
    542                                 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {
    543                                         // add new result
    544                                         results.emplace_back(
    545                                                 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),
    546                                                 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
    547                                 }
    548                         }
    549                 }
    550 
    551                 // reset for next parameter
    552                 genStart = genEnd;
    553 
    554                 return genEnd != results.size();  // were any new results added?
    555         }
    556 
    557         /// Generate a cast expression from `arg` to `toType`
    558         const ast::Expr * restructureCast(
    559                 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
    560         ) {
    561                 if (
    562                         arg->result->size() > 1
    563                         && ! toType->isVoid()
    564                         && ! dynamic_cast< const ast::ReferenceType * >( toType )
    565                 ) {
    566                         // Argument is a tuple and the target type is neither void nor a reference. Cast each
    567                         // member of the tuple to its corresponding target type, producing the tuple of those
    568                         // cast expressions. If there are more components of the tuple than components in the
    569                         // target type, then excess components do not come out in the result expression (but
    570                         // UniqueExpr ensures that the side effects will still be produced)
    571                         if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    572                                 // expressions which may contain side effects require a single unique instance of
    573                                 // the expression
    574                                 arg = new ast::UniqueExpr{ arg->location, arg };
    575                         }
    576                         std::vector< ast::ptr< ast::Expr > > components;
    577                         for ( unsigned i = 0; i < toType->size(); ++i ) {
    578                                 // cast each component
    579                                 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };
    580                                 components.emplace_back(
    581                                         restructureCast( idx, toType->getComponent( i ), isGenerated ) );
    582                         }
    583                         return new ast::TupleExpr{ arg->location, std::move( components ) };
    584                 } else {
    585                         // handle normally
    586                         return new ast::CastExpr{ arg->location, arg, toType, isGenerated };
    587                 }
    588         }
    589 
    590         /// Gets the name from an untyped member expression (must be NameExpr)
    591         const std::string & getMemberName( const ast::UntypedMemberExpr * memberExpr ) {
    592                 if ( memberExpr->member.as< ast::ConstantExpr >() ) {
    593                         SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );
    594                 }
    595 
    596                 return memberExpr->member.strict_as< ast::NameExpr >()->name;
    597         }
    598 
    599         /// Actually visits expressions to find their candidate interpretations
    600         class Finder final : public ast::WithShortCircuiting {
    601                 const ResolveContext & context;
    602                 const ast::SymbolTable & symtab;
    603         public:
    604                 // static size_t traceId;
    605                 CandidateFinder & selfFinder;
    606                 CandidateList & candidates;
    607                 const ast::TypeEnvironment & tenv;
    608                 ast::ptr< ast::Type > & targetType;
    609 
    610                 enum Errors {
    611                         NotFound,
    612                         NoMatch,
    613                         ArgsToFew,
    614                         ArgsToMany,
    615                         RetsToFew,
    616                         RetsToMany,
    617                         NoReason
    618                 };
    619 
    620                 struct {
    621                         Errors code = NotFound;
    622                 } reason;
    623 
    624                 Finder( CandidateFinder & f )
    625                 : context( f.context ), symtab( context.symtab ), selfFinder( f ),
    626                   candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {}
    627 
    628                 void previsit( const ast::Node * ) { visit_children = false; }
    629 
    630                 /// Convenience to add candidate to list
    631                 template<typename... Args>
    632                 void addCandidate( Args &&... args ) {
    633                         candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );
    634                         reason.code = NoReason;
    635                 }
    636 
    637                 void postvisit( const ast::ApplicationExpr * applicationExpr ) {
    638                         addCandidate( applicationExpr, tenv );
    639                 }
    640 
    641                 /// Set up candidate assertions for inference
    642                 void inferParameters( CandidateRef & newCand, CandidateList & out ) {
    643                         // Set need bindings for any unbound assertions
    644                         UniqueId crntResnSlot = 0; // matching ID for this expression's assertions
    645                         for ( auto & assn : newCand->need ) {
    646                                 // skip already-matched assertions
    647                                 if ( assn.second.resnSlot != 0 ) continue;
    648                                 // assign slot for expression if needed
    649                                 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }
    650                                 // fix slot to assertion
    651                                 assn.second.resnSlot = crntResnSlot;
    652                         }
    653                         // pair slot to expression
    654                         if ( crntResnSlot != 0 ) {
    655                                 newCand->expr.get_and_mutate()->inferred.resnSlots().emplace_back( crntResnSlot );
    656                         }
    657 
    658                         // add to output list; assertion satisfaction will occur later
    659                         out.emplace_back( newCand );
    660                 }
    661 
    662                 /// Completes a function candidate with arguments located
    663                 void validateFunctionCandidate(
    664                         const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,
    665                         CandidateList & out
    666                 ) {
    667                         ast::ApplicationExpr * appExpr =
    668                                 new ast::ApplicationExpr{ func->expr->location, func->expr };
    669                         // sum cost and accumulate arguments
    670                         std::deque< const ast::Expr * > args;
    671                         Cost cost = func->cost;
    672                         const ArgPack * pack = &result;
    673                         while ( pack->expr ) {
    674                                 args.emplace_front( pack->expr );
    675                                 cost += pack->cost;
    676                                 pack = &results[pack->parent];
    677                         }
    678                         std::vector< ast::ptr< ast::Expr > > vargs( args.begin(), args.end() );
    679                         appExpr->args = std::move( vargs );
    680                         // build and validate new candidate
    681                         auto newCand =
    682                                 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );
    683                         PRINT(
    684                                 std::cerr << "instantiate function success: " << appExpr << std::endl;
    685                                 std::cerr << "need assertions:" << std::endl;
    686                                 ast::print( std::cerr, result.need, 2 );
    687                         )
    688                         inferParameters( newCand, out );
    689                 }
    690 
    691                 /// Builds a list of candidates for a function, storing them in out
    692                 void makeFunctionCandidates(
    693                         const CandidateRef & func, const ast::FunctionType * funcType,
    694                         const ExplodedArgs_new & args, CandidateList & out
    695                 ) {
    696                         ast::OpenVarSet funcOpen;
    697                         ast::AssertionSet funcNeed, funcHave;
    698                         ast::TypeEnvironment funcEnv{ func->env };
    699                         makeUnifiableVars( funcType, funcOpen, funcNeed );
    700                         // add all type variables as open variables now so that those not used in the
    701                         // parameter list are still considered open
    702                         funcEnv.add( funcType->forall );
    703 
    704                         if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) {
    705                                 // attempt to narrow based on expected target type
    706                                 const ast::Type * returnType = funcType->returns.front();
    707                                 if ( ! unify(
    708                                         returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )
    709                                 ) {
    710                                         // unification failed, do not pursue this candidate
    711                                         return;
    712                                 }
    713                         }
    714 
    715                         // iteratively build matches, one parameter at a time
    716                         std::vector< ArgPack > results;
    717                         results.emplace_back( funcEnv, funcNeed, funcHave, funcOpen );
    718                         std::size_t genStart = 0;
    719 
    720                         // xxx - how to handle default arg after change to ftype representation?
    721                         if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) {
    722                                 if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) {
    723                                         // function may have default args only if directly calling by name
    724                                         // must use types on candidate however, due to RenameVars substitution
    725                                         auto nParams = funcType->params.size();
    726 
    727                                         for (size_t i=0; i<nParams; ++i) {
    728                                                 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();
    729                                                 if (!instantiateArgument(
    730                                                         funcType->params[i], obj->init, args, results, genStart, symtab)) return;
    731                                         }
    732                                         goto endMatch;
    733                                 }
    734                         }
    735                         for ( const auto & param : funcType->params ) {
    736                                 // Try adding the arguments corresponding to the current parameter to the existing
    737                                 // matches
    738                                 // no default args for indirect calls
    739                                 if ( ! instantiateArgument(
    740                                         param, nullptr, args, results, genStart, symtab ) ) return;
    741                         }
    742 
    743                         endMatch:
    744                         if ( funcType->isVarArgs ) {
    745                                 // append any unused arguments to vararg pack
    746                                 std::size_t genEnd;
    747                                 do {
    748                                         genEnd = results.size();
    749 
    750                                         // iterate results
    751                                         for ( std::size_t i = genStart; i < genEnd; ++i ) {
    752                                                 unsigned nextArg = results[i].nextArg;
    753 
    754                                                 // use remainder of exploded tuple if present
    755                                                 if ( results[i].hasExpl() ) {
    756                                                         const ExplodedArg & expl = results[i].getExpl( args );
    757 
    758                                                         unsigned nextExpl = results[i].nextExpl + 1;
    759                                                         if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }
    760 
    761                                                         results.emplace_back(
    762                                                                 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),
    763                                                                 copy( results[i].need ), copy( results[i].have ),
    764                                                                 copy( results[i].open ), nextArg, 0, Cost::zero, nextExpl,
    765                                                                 results[i].explAlt );
    766 
    767                                                         continue;
    768                                                 }
    769 
    770                                                 // finish result when out of arguments
    771                                                 if ( nextArg >= args.size() ) {
    772                                                         validateFunctionCandidate( func, results[i], results, out );
    773 
    774                                                         continue;
    775                                                 }
    776 
    777                                                 // add each possible next argument
    778                                                 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {
    779                                                         const ExplodedArg & expl = args[nextArg][j];
    780 
    781                                                         // fresh copies of parent parameters for this iteration
    782                                                         ast::TypeEnvironment env = results[i].env;
    783                                                         ast::OpenVarSet open = results[i].open;
    784 
    785                                                         env.addActual( expl.env, open );
    786 
    787                                                         // skip empty tuple arguments by (nearly) cloning parent into next gen
    788                                                         if ( expl.exprs.empty() ) {
    789                                                                 results.emplace_back(
    790                                                                         results[i], std::move( env ), copy( results[i].need ),
    791                                                                         copy( results[i].have ), std::move( open ), nextArg + 1,
    792                                                                         expl.cost );
    793 
    794                                                                 continue;
    795                                                         }
    796 
    797                                                         // add new result
    798                                                         results.emplace_back(
    799                                                                 i, expl.exprs.front(), std::move( env ), copy( results[i].need ),
    800                                                                 copy( results[i].have ), std::move( open ), nextArg + 1, 0, expl.cost,
    801                                                                 expl.exprs.size() == 1 ? 0 : 1, j );
    802                                                 }
    803                                         }
    804 
    805                                         genStart = genEnd;
    806                                 } while( genEnd != results.size() );
    807                         } else {
    808                                 // filter out the results that don't use all the arguments
    809                                 for ( std::size_t i = genStart; i < results.size(); ++i ) {
    810                                         ArgPack & result = results[i];
    811                                         if ( ! result.hasExpl() && result.nextArg >= args.size() ) {
    812                                                 validateFunctionCandidate( func, result, results, out );
    813                                         }
    814                                 }
    815                         }
    816                 }
    817 
    818                 /// Adds implicit struct-conversions to the alternative list
    819                 void addAnonConversions( const CandidateRef & cand ) {
    820                         // adds anonymous member interpretations whenever an aggregate value type is seen.
    821                         // it's okay for the aggregate expression to have reference type -- cast it to the
    822                         // base type to treat the aggregate as the referenced value
    823                         ast::ptr< ast::Expr > aggrExpr( cand->expr );
    824                         ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;
    825                         cand->env.apply( aggrType );
    826 
    827                         if ( aggrType.as< ast::ReferenceType >() ) {
    828                                 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };
    829                         }
    830 
    831                         if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) {
    832                                 addAggMembers( structInst, aggrExpr, *cand, Cost::safe, "" );
    833                         } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {
    834                                 addAggMembers( unionInst, aggrExpr, *cand, Cost::safe, "" );
    835                         }
    836                 }
    837 
    838                 /// Adds aggregate member interpretations
    839                 void addAggMembers(
    840                         const ast::BaseInstType * aggrInst, const ast::Expr * expr,
    841                         const Candidate & cand, const Cost & addedCost, const std::string & name
    842                 ) {
    843                         for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {
    844                                 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );
    845                                 CandidateRef newCand = std::make_shared<Candidate>(
    846                                         cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );
    847                                 // add anonymous member interpretations whenever an aggregate value type is seen
    848                                 // as a member expression
    849                                 addAnonConversions( newCand );
    850                                 candidates.emplace_back( std::move( newCand ) );
    851                         }
    852                 }
    853 
    854                 /// Adds tuple member interpretations
    855                 void addTupleMembers(
    856                         const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,
    857                         const Cost & addedCost, const ast::Expr * member
    858                 ) {
    859                         if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {
    860                                 // get the value of the constant expression as an int, must be between 0 and the
    861                                 // length of the tuple to have meaning
    862                                 long long val = constantExpr->intValue();
    863                                 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
    864                                         addCandidate(
    865                                                 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },
    866                                                 addedCost );
    867                                 }
    868                         }
    869                 }
    870 
    871                 void postvisit( const ast::UntypedExpr * untypedExpr ) {
    872                         std::vector< CandidateFinder > argCandidates =
    873                                 selfFinder.findSubExprs( untypedExpr->args );
    874 
    875                         // take care of possible tuple assignments
    876                         // if not tuple assignment, handled as normal function call
    877                         Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );
    878 
    879                         CandidateFinder funcFinder( context, tenv );
    880                         if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) {
    881                                 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);
    882                                 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {
    883                                         assertf(!argCandidates.empty(), "special function call without argument");
    884                                         for (auto & firstArgCand: argCandidates[0]) {
    885                                                 ast::ptr<ast::Type> argType = firstArgCand->expr->result;
    886                                                 firstArgCand->env.apply(argType);
    887                                                 // strip references
    888                                                 // xxx - is this correct?
    889                                                 while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base;
    890 
    891                                                 // convert 1-tuple to plain type
    892                                                 if (auto tuple = argType.as<ast::TupleType>()) {
    893                                                         if (tuple->size() == 1) {
    894                                                                 argType = tuple->types[0];
    895                                                         }
    896                                                 }
    897 
    898                                                 // if argType is an unbound type parameter, all special functions need to be searched.
    899                                                 if (isUnboundType(argType)) {
    900                                                         funcFinder.otypeKeys.clear();
    901                                                         break;
    902                                                 }
    903 
    904                                                 if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer);                                             
    905                                                 // else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) {
    906                                                 //      const ast::EnumDecl * enumDecl = enumInst->base; // Here
    907                                                 //      if ( const ast::Type* enumType = enumDecl->base ) {
    908                                                 //              // instance of enum (T) is a instance of type (T)
    909                                                 //              funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type));
    910                                                 //      } else {
    911                                                 //              // instance of an untyped enum is techically int
    912                                                 //              funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type));
    913                                                 //      }
    914                                                 // }
    915                                                 else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type));
    916                                         }
    917                                 }
    918                         }
    919                         // if candidates are already produced, do not fail
    920                         // xxx - is it possible that handleTupleAssignment and main finder both produce candidates?
    921                         // this means there exists ctor/assign functions with a tuple as first parameter.
    922                         ResolvMode mode = {
    923                                 true, // adjust
    924                                 !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name
    925                                 selfFinder.candidates.empty() // failfast if other options are not found
    926                         };
    927                         funcFinder.find( untypedExpr->func, mode );
    928                         // short-circuit if no candidates
    929                         // if ( funcFinder.candidates.empty() ) return;
    930 
    931                         reason.code = NoMatch;
    932 
    933                         // find function operators
    934                         ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; // ??? why not ?{}
    935                         CandidateFinder opFinder( context, tenv );
    936                         // okay if there aren't any function operations
    937                         opFinder.find( opExpr, ResolvMode::withoutFailFast() );
    938                         PRINT(
    939                                 std::cerr << "known function ops:" << std::endl;
    940                                 print( std::cerr, opFinder.candidates, 1 );
    941                         )
    942 
    943                         // pre-explode arguments
    944                         ExplodedArgs_new argExpansions;
    945                         for ( const CandidateFinder & args : argCandidates ) {
    946                                 argExpansions.emplace_back();
    947                                 auto & argE = argExpansions.back();
    948                                 for ( const CandidateRef & arg : args ) { argE.emplace_back( *arg, symtab ); }
    949                         }
    950 
    951                         // Find function matches
    952                         CandidateList found;
    953                         SemanticErrorException errors;
    954                         for ( CandidateRef & func : funcFinder ) {
    955                                 try {
    956                                         PRINT(
    957                                                 std::cerr << "working on alternative:" << std::endl;
    958                                                 print( std::cerr, *func, 2 );
    959                                         )
    960 
    961                                         // check if the type is a pointer to function
    962                                         const ast::Type * funcResult = func->expr->result->stripReferences();
    963                                         if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) {
    964                                                 if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    965                                                         CandidateRef newFunc{ new Candidate{ *func } };
    966                                                         newFunc->expr =
    967                                                                 referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    968                                                         makeFunctionCandidates( newFunc, function, argExpansions, found );
    969                                                 }
    970                                         } else if (
    971                                                 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )
    972                                         ) {
    973                                                 if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) {
    974                                                         if ( auto function = clz->bound.as< ast::FunctionType >() ) {
    975                                                                 CandidateRef newFunc{ new Candidate{ *func } };
    976                                                                 newFunc->expr =
    977                                                                         referenceToRvalueConversion( newFunc->expr, newFunc->cost );
    978                                                                 makeFunctionCandidates( newFunc, function, argExpansions, found );
    979                                                         }
    980                                                 }
    981                                         }
    982                                 } catch ( SemanticErrorException & e ) { errors.append( e ); }
    983                         }
    984 
    985                         // Find matches on function operators `?()`
    986                         if ( ! opFinder.candidates.empty() ) {
    987                                 // add exploded function alternatives to front of argument list
    988                                 std::vector< ExplodedArg > funcE;
    989                                 funcE.reserve( funcFinder.candidates.size() );
    990                                 for ( const CandidateRef & func : funcFinder ) {
    991                                         funcE.emplace_back( *func, symtab );
    992                                 }
    993                                 argExpansions.emplace_front( std::move( funcE ) );
    994 
    995                                 for ( const CandidateRef & op : opFinder ) {
    996                                         try {
    997                                                 // check if type is pointer-to-function
    998                                                 const ast::Type * opResult = op->expr->result->stripReferences();
    999                                                 if ( auto pointer = dynamic_cast< const ast::PointerType * >( opResult ) ) {
    1000                                                         if ( auto function = pointer->base.as< ast::FunctionType >() ) {
    1001                                                                 CandidateRef newOp{ new Candidate{ *op} };
    1002                                                                 newOp->expr =
    1003                                                                         referenceToRvalueConversion( newOp->expr, newOp->cost );
    1004                                                                 makeFunctionCandidates( newOp, function, argExpansions, found );
    1005                                                         }
    1006                                                 }
    1007                                         } catch ( SemanticErrorException & e ) { errors.append( e ); }
    1008                                 }
    1009                         }
    1010 
    1011                         // Implement SFINAE; resolution errors are only errors if there aren't any non-error
    1012                         // candidates
    1013                         if ( found.empty() && ! errors.isEmpty() ) { throw errors; }
    1014 
    1015                         // Compute conversion costs
    1016                         for ( CandidateRef & withFunc : found ) {
    1017                                 Cost cvtCost = computeApplicationConversionCost( withFunc, symtab );
    1018 
    1019                                 PRINT(
    1020                                         auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >();
    1021                                         auto pointer = appExpr->func->result.strict_as< ast::PointerType >();
    1022                                         auto function = pointer->base.strict_as< ast::FunctionType >();
    1023 
    1024                                         std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;
    1025                                         std::cerr << "parameters are:" << std::endl;
    1026                                         ast::printAll( std::cerr, function->params, 2 );
    1027                                         std::cerr << "arguments are:" << std::endl;
    1028                                         ast::printAll( std::cerr, appExpr->args, 2 );
    1029                                         std::cerr << "bindings are:" << std::endl;
    1030                                         ast::print( std::cerr, withFunc->env, 2 );
    1031                                         std::cerr << "cost is: " << withFunc->cost << std::endl;
    1032                                         std::cerr << "cost of conversion is:" << cvtCost << std::endl;
    1033                                 )
    1034 
    1035                                 if ( cvtCost != Cost::infinity ) {
    1036                                         withFunc->cvtCost = cvtCost;
    1037                                         candidates.emplace_back( std::move( withFunc ) );
    1038                                 }
    1039                         }
    1040                         found = std::move( candidates );
    1041 
    1042                         // use a new list so that candidates are not examined by addAnonConversions twice
    1043                         CandidateList winners = findMinCost( found );
    1044                         promoteCvtCost( winners );
    1045 
    1046                         // function may return a struct/union value, in which case we need to add candidates
    1047                         // for implicit conversions to each of the anonymous members, which must happen after
    1048                         // `findMinCost`, since anon conversions are never the cheapest
    1049                         for ( const CandidateRef & c : winners ) {
    1050                                 addAnonConversions( c );
    1051                         }
    1052                         spliceBegin( candidates, winners );
    1053 
    1054                         if ( candidates.empty() && targetType && ! targetType->isVoid() ) {
    1055                                 // If resolution is unsuccessful with a target type, try again without, since it
    1056                                 // will sometimes succeed when it wouldn't with a target type binding.
    1057                                 // For example:
    1058                                 //   forall( otype T ) T & ?[]( T *, ptrdiff_t );
    1059                                 //   const char * x = "hello world";
    1060                                 //   unsigned char ch = x[0];
    1061                                 // Fails with simple return type binding (xxx -- check this!) as follows:
    1062                                 // * T is bound to unsigned char
    1063                                 // * (x: const char *) is unified with unsigned char *, which fails
    1064                                 // xxx -- fix this better
    1065                                 targetType = nullptr;
    1066                                 postvisit( untypedExpr );
    1067                         }
    1068                 }
    1069 
    1070                 /// true if expression is an lvalue
    1071                 static bool isLvalue( const ast::Expr * x ) {
    1072                         return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );
    1073                 }
    1074 
    1075                 void postvisit( const ast::AddressExpr * addressExpr ) {
    1076                         CandidateFinder finder( context, tenv );
    1077                         finder.find( addressExpr->arg );
    1078 
    1079                         if( finder.candidates.empty() ) return;
    1080 
    1081                         reason.code = NoMatch;
    1082 
    1083                         for ( CandidateRef & r : finder.candidates ) {
    1084                                 if ( ! isLvalue( r->expr ) ) continue;
    1085                                 addCandidate( *r, new ast::AddressExpr{ addressExpr->location, r->expr } );
    1086                         }
    1087                 }
    1088 
    1089                 void postvisit( const ast::LabelAddressExpr * labelExpr ) {
    1090                         addCandidate( labelExpr, tenv );
    1091                 }
    1092 
    1093                 void postvisit( const ast::CastExpr * castExpr ) {
    1094                         ast::ptr< ast::Type > toType = castExpr->result;
    1095                         assert( toType );
    1096                         toType = resolveTypeof( toType, context );
    1097                         toType = adjustExprType( toType, tenv, symtab );
    1098 
    1099                         CandidateFinder finder( context, tenv, toType );
    1100                         finder.find( castExpr->arg, ResolvMode::withAdjustment() );
    1101 
    1102                         if( !finder.candidates.empty() ) reason.code = NoMatch;
    1103 
    1104                         CandidateList matches;
    1105                         for ( CandidateRef & cand : finder.candidates ) {
    1106                                 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
    1107                                 ast::OpenVarSet open( cand->open );
    1108 
    1109                                 cand->env.extractOpenVars( open );
    1110 
    1111                                 // It is possible that a cast can throw away some values in a multiply-valued
    1112                                 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the
    1113                                 // subexpression results that are cast directly. The candidate is invalid if it
    1114                                 // has fewer results than there are types to cast to.
    1115                                 int discardedValues = cand->expr->result->size() - toType->size();
    1116                                 if ( discardedValues < 0 ) continue;
    1117 
    1118                                 // unification run for side-effects
    1119                                 unify( toType, cand->expr->result, cand->env, need, have, open, symtab );
    1120                                 Cost thisCost =
    1121                                         (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast)
    1122                             ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env )
    1123                             : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env );
    1124 
    1125                                 PRINT(
    1126                                         std::cerr << "working on cast with result: " << toType << std::endl;
    1127                                         std::cerr << "and expr type: " << cand->expr->result << std::endl;
    1128                                         std::cerr << "env: " << cand->env << std::endl;
    1129                                 )
    1130                                 if ( thisCost != Cost::infinity ) {
    1131                                         PRINT(
    1132                                                 std::cerr << "has finite cost." << std::endl;
    1133                                         )
    1134                                         // count one safe conversion for each value that is thrown away
    1135                                         thisCost.incSafe( discardedValues );
    1136                                         CandidateRef newCand = std::make_shared<Candidate>(
    1137                                                 restructureCast( cand->expr, toType, castExpr->isGenerated ),
    1138                                                 copy( cand->env ), std::move( open ), std::move( need ), cand->cost,
    1139                                                 cand->cost + thisCost );
    1140                                         inferParameters( newCand, matches );
    1141                                 }
    1142                         }
    1143 
    1144                         // select first on argument cost, then conversion cost
    1145                         CandidateList minArgCost = findMinCost( matches );
    1146                         promoteCvtCost( minArgCost );
    1147                         candidates = findMinCost( minArgCost );
    1148                 }
    1149 
    1150                 void postvisit( const ast::VirtualCastExpr * castExpr ) {
    1151                         assertf( castExpr->result, "Implicit virtual cast targets not yet supported." );
    1152                         CandidateFinder finder( context, tenv );
    1153                         // don't prune here, all alternatives guaranteed to have same type
    1154                         finder.find( castExpr->arg, ResolvMode::withoutPrune() );
    1155                         for ( CandidateRef & r : finder.candidates ) {
    1156                                 addCandidate(
    1157                                         *r,
    1158                                         new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );
    1159                         }
    1160                 }
    1161 
    1162                 void postvisit( const ast::KeywordCastExpr * castExpr ) {
    1163                         const auto & loc = castExpr->location;
    1164                         assertf( castExpr->result, "Cast target should have been set in Validate." );
    1165                         auto ref = castExpr->result.strict_as<ast::ReferenceType>();
    1166                         auto inst = ref->base.strict_as<ast::StructInstType>();
    1167                         auto target = inst->base.get();
    1168 
    1169                         CandidateFinder finder( context, tenv );
    1170 
    1171                         auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) {
    1172                                 for(auto & cand : found) {
    1173                                         const ast::Type * expr = cand->expr->result.get();
    1174                                         if(expect_ref) {
    1175                                                 auto res = dynamic_cast<const ast::ReferenceType*>(expr);
    1176                                                 if(!res) { continue; }
    1177                                                 expr = res->base.get();
    1178                                         }
    1179 
    1180                                         if(auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) {
    1181                                                 auto td = cand->env.lookup(*insttype);
    1182                                                 if(!td) { continue; }
    1183                                                 expr = td->bound.get();
    1184                                         }
    1185 
    1186                                         if(auto base = dynamic_cast<const ast::StructInstType*>(expr)) {
    1187                                                 if(base->base == target) {
    1188                                                         candidates.push_back( std::move(cand) );
    1189                                                         reason.code = NoReason;
    1190                                                 }
    1191                                         }
    1192                                 }
    1193                         };
    1194 
    1195                         try {
    1196                                 // Attempt 1 : turn (thread&)X into (thread$&)X.__thrd
    1197                                 // Clone is purely for memory management
    1198                                 std::unique_ptr<const ast::Expr> tech1 { new ast::UntypedMemberExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.field), castExpr->arg) };
    1199 
    1200                                 // don't prune here, since it's guaranteed all alternatives will have the same type
    1201                                 finder.find( tech1.get(), ResolvMode::withoutPrune() );
    1202                                 pick_alternatives(finder.candidates, false);
    1203 
    1204                                 return;
    1205                         } catch(SemanticErrorException & ) {}
    1206 
    1207                         // Fallback : turn (thread&)X into (thread$&)get_thread(X)
    1208                         std::unique_ptr<const ast::Expr> fallback { ast::UntypedExpr::createDeref(loc,  new ast::UntypedExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.getter), { castExpr->arg })) };
    1209                         // don't prune here, since it's guaranteed all alternatives will have the same type
    1210                         finder.find( fallback.get(), ResolvMode::withoutPrune() );
    1211 
    1212                         pick_alternatives(finder.candidates, true);
    1213 
    1214                         // Whatever happens here, we have no more fallbacks
    1215                 }
    1216 
    1217                 void postvisit( const ast::UntypedMemberExpr * memberExpr ) {
    1218                         CandidateFinder aggFinder( context, tenv );
    1219                         aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    1220                         for ( CandidateRef & agg : aggFinder.candidates ) {
    1221                                 // it's okay for the aggregate expression to have reference type -- cast it to the
    1222                                 // base type to treat the aggregate as the referenced value
    1223                                 Cost addedCost = Cost::zero;
    1224                                 agg->expr = referenceToRvalueConversion( agg->expr, addedCost );
    1225 
    1226                                 // find member of the given type
    1227                                 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {
    1228                                         addAggMembers(
    1229                                                 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    1230                                 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {
    1231                                         addAggMembers(
    1232                                                 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );
    1233                                 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {
    1234                                         addTupleMembers( tupleType, agg->expr, *agg, addedCost, memberExpr->member );
    1235                                 }
    1236                         }
    1237                 }
    1238 
    1239                 void postvisit( const ast::MemberExpr * memberExpr ) {
    1240                         addCandidate( memberExpr, tenv );
    1241                 }
    1242 
    1243                 void postvisit( const ast::NameExpr * nameExpr ) {
    1244                         std::vector< ast::SymbolTable::IdData > declList;
    1245                         if (!selfFinder.otypeKeys.empty()) {
    1246                                 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);
    1247                                 assertf(kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS, "special lookup with non-special target: %s", nameExpr->name.c_str());
    1248 
    1249                                 for (auto & otypeKey: selfFinder.otypeKeys) {
    1250                                         auto result = symtab.specialLookupId(kind, otypeKey);
    1251                                         declList.insert(declList.end(), std::make_move_iterator(result.begin()), std::make_move_iterator(result.end()));
    1252                                 }
    1253                         }
    1254                         else {
    1255                                 declList = symtab.lookupId( nameExpr->name );
    1256                         }
    1257                         PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )
    1258 
    1259                         if( declList.empty() ) return;
    1260 
    1261                         reason.code = NoMatch;
    1262 
    1263                         for ( auto & data : declList ) {
    1264                                 Cost cost = Cost::zero;
    1265                                 ast::Expr * newExpr = data.combine( nameExpr->location, cost );
    1266 
    1267                                 CandidateRef newCand = std::make_shared<Candidate>(
    1268                                         newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,
    1269                                         cost );
    1270 
    1271                                 if (newCand->expr->env) {
    1272                                         newCand->env.add(*newCand->expr->env);
    1273                                         auto mutExpr = newCand->expr.get_and_mutate();
    1274                                         mutExpr->env  = nullptr;
    1275                                         newCand->expr = mutExpr;
    1276                                 }
    1277 
    1278                                 PRINT(
    1279                                         std::cerr << "decl is ";
    1280                                         ast::print( std::cerr, data.id );
    1281                                         std::cerr << std::endl;
    1282                                         std::cerr << "newExpr is ";
    1283                                         ast::print( std::cerr, newExpr );
    1284                                         std::cerr << std::endl;
    1285                                 )
    1286                                 newCand->expr = ast::mutate_field(
    1287                                         newCand->expr.get(), &ast::Expr::result,
    1288                                         renameTyVars( newCand->expr->result ) );
    1289                                 // add anonymous member interpretations whenever an aggregate value type is seen
    1290                                 // as a name expression
    1291                                 addAnonConversions( newCand );
    1292                                 candidates.emplace_back( std::move( newCand ) );
    1293                         }
    1294                 }
    1295 
    1296                 void postvisit( const ast::VariableExpr * variableExpr ) {
    1297                         // not sufficient to just pass `variableExpr` here, type might have changed since
    1298                         // creation
    1299                         addCandidate(
    1300                                 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );
    1301                 }
    1302 
    1303                 void postvisit( const ast::ConstantExpr * constantExpr ) {
    1304                         addCandidate( constantExpr, tenv );
    1305                 }
    1306 
    1307                 void postvisit( const ast::SizeofExpr * sizeofExpr ) {
    1308                         if ( sizeofExpr->type ) {
    1309                                 addCandidate(
    1310                                         new ast::SizeofExpr{
    1311                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) },
    1312                                         tenv );
    1313                         } else {
    1314                                 // find all candidates for the argument to sizeof
    1315                                 CandidateFinder finder( context, tenv );
    1316                                 finder.find( sizeofExpr->expr );
    1317                                 // find the lowest-cost candidate, otherwise ambiguous
    1318                                 CandidateList winners = findMinCost( finder.candidates );
    1319                                 if ( winners.size() != 1 ) {
    1320                                         SemanticError(
    1321                                                 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );
    1322                                 }
    1323                                 // return the lowest-cost candidate
    1324                                 CandidateRef & choice = winners.front();
    1325                                 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    1326                                 choice->cost = Cost::zero;
    1327                                 addCandidate( *choice, new ast::SizeofExpr{ sizeofExpr->location, choice->expr } );
    1328                         }
    1329                 }
    1330 
    1331                 void postvisit( const ast::AlignofExpr * alignofExpr ) {
    1332                         if ( alignofExpr->type ) {
    1333                                 addCandidate(
    1334                                         new ast::AlignofExpr{
    1335                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, context ) },
    1336                                         tenv );
    1337                         } else {
    1338                                 // find all candidates for the argument to alignof
    1339                                 CandidateFinder finder( context, tenv );
    1340                                 finder.find( alignofExpr->expr );
    1341                                 // find the lowest-cost candidate, otherwise ambiguous
    1342                                 CandidateList winners = findMinCost( finder.candidates );
    1343                                 if ( winners.size() != 1 ) {
    1344                                         SemanticError(
    1345                                                 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );
    1346                                 }
    1347                                 // return the lowest-cost candidate
    1348                                 CandidateRef & choice = winners.front();
    1349                                 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
    1350                                 choice->cost = Cost::zero;
    1351                                 addCandidate(
    1352                                         *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );
    1353                         }
    1354                 }
    1355 
    1356                 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {
    1357                         const ast::BaseInstType * aggInst;
    1358                         if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ;
    1359                         else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ;
    1360                         else return;
    1361 
    1362                         for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {
    1363                                 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );
    1364                                 addCandidate(
    1365                                         new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );
    1366                         }
    1367                 }
    1368 
    1369                 void postvisit( const ast::OffsetofExpr * offsetofExpr ) {
    1370                         addCandidate( offsetofExpr, tenv );
    1371                 }
    1372 
    1373                 void postvisit( const ast::OffsetPackExpr * offsetPackExpr ) {
    1374                         addCandidate( offsetPackExpr, tenv );
    1375                 }
    1376 
    1377                 void postvisit( const ast::LogicalExpr * logicalExpr ) {
    1378                         CandidateFinder finder1( context, tenv );
    1379                         finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() );
    1380                         if ( finder1.candidates.empty() ) return;
    1381 
    1382                         CandidateFinder finder2( context, tenv );
    1383                         finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
    1384                         if ( finder2.candidates.empty() ) return;
    1385 
    1386                         reason.code = NoMatch;
    1387 
    1388                         for ( const CandidateRef & r1 : finder1.candidates ) {
    1389                                 for ( const CandidateRef & r2 : finder2.candidates ) {
    1390                                         ast::TypeEnvironment env{ r1->env };
    1391                                         env.simpleCombine( r2->env );
    1392                                         ast::OpenVarSet open{ r1->open };
    1393                                         mergeOpenVars( open, r2->open );
    1394                                         ast::AssertionSet need;
    1395                                         mergeAssertionSet( need, r1->need );
    1396                                         mergeAssertionSet( need, r2->need );
    1397 
    1398                                         addCandidate(
    1399                                                 new ast::LogicalExpr{
    1400                                                         logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },
    1401                                                 std::move( env ), std::move( open ), std::move( need ), r1->cost + r2->cost );
    1402                                 }
    1403                         }
    1404                 }
    1405 
    1406                 void postvisit( const ast::ConditionalExpr * conditionalExpr ) {
    1407                         // candidates for condition
    1408                         CandidateFinder finder1( context, tenv );
    1409                         finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );
    1410                         if ( finder1.candidates.empty() ) return;
    1411 
    1412                         // candidates for true result
    1413                         CandidateFinder finder2( context, tenv );
    1414                         finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );
    1415                         if ( finder2.candidates.empty() ) return;
    1416 
    1417                         // candidates for false result
    1418                         CandidateFinder finder3( context, tenv );
    1419                         finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    1420                         if ( finder3.candidates.empty() ) return;
    1421 
    1422                         reason.code = NoMatch;
    1423 
    1424                         for ( const CandidateRef & r1 : finder1.candidates ) {
    1425                                 for ( const CandidateRef & r2 : finder2.candidates ) {
    1426                                         for ( const CandidateRef & r3 : finder3.candidates ) {
    1427                                                 ast::TypeEnvironment env{ r1->env };
    1428                                                 env.simpleCombine( r2->env );
    1429                                                 env.simpleCombine( r3->env );
    1430                                                 ast::OpenVarSet open{ r1->open };
    1431                                                 mergeOpenVars( open, r2->open );
    1432                                                 mergeOpenVars( open, r3->open );
    1433                                                 ast::AssertionSet need;
    1434                                                 mergeAssertionSet( need, r1->need );
    1435                                                 mergeAssertionSet( need, r2->need );
    1436                                                 mergeAssertionSet( need, r3->need );
    1437                                                 ast::AssertionSet have;
    1438 
    1439                                                 // unify true and false results, then infer parameters to produce new
    1440                                                 // candidates
    1441                                                 ast::ptr< ast::Type > common;
    1442                                                 if (
    1443                                                         unify(
    1444                                                                 r2->expr->result, r3->expr->result, env, need, have, open, symtab,
    1445                                                                 common )
    1446                                                 ) {
    1447                                                         // generate typed expression
    1448                                                         ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{
    1449                                                                 conditionalExpr->location, r1->expr, r2->expr, r3->expr };
    1450                                                         newExpr->result = common ? common : r2->expr->result;
    1451                                                         // convert both options to result type
    1452                                                         Cost cost = r1->cost + r2->cost + r3->cost;
    1453                                                         newExpr->arg2 = computeExpressionConversionCost(
    1454                                                                 newExpr->arg2, newExpr->result, symtab, env, cost );
    1455                                                         newExpr->arg3 = computeExpressionConversionCost(
    1456                                                                 newExpr->arg3, newExpr->result, symtab, env, cost );
    1457                                                         // output candidate
    1458                                                         CandidateRef newCand = std::make_shared<Candidate>(
    1459                                                                 newExpr, std::move( env ), std::move( open ), std::move( need ), cost );
    1460                                                         inferParameters( newCand, candidates );
    1461                                                 }
    1462                                         }
    1463                                 }
    1464                         }
    1465                 }
    1466 
    1467                 void postvisit( const ast::CommaExpr * commaExpr ) {
    1468                         ast::TypeEnvironment env{ tenv };
    1469                         ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env );
    1470 
    1471                         CandidateFinder finder2( context, env );
    1472                         finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
    1473 
    1474                         for ( const CandidateRef & r2 : finder2.candidates ) {
    1475                                 addCandidate( *r2, new ast::CommaExpr{ commaExpr->location, arg1, r2->expr } );
    1476                         }
    1477                 }
    1478 
    1479                 void postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ) {
    1480                         addCandidate( ctorExpr, tenv );
    1481                 }
    1482 
    1483                 void postvisit( const ast::ConstructorExpr * ctorExpr ) {
    1484                         CandidateFinder finder( context, tenv );
    1485                         finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() );
    1486                         for ( CandidateRef & r : finder.candidates ) {
    1487                                 addCandidate( *r, new ast::ConstructorExpr{ ctorExpr->location, r->expr } );
    1488                         }
    1489                 }
    1490 
    1491                 void postvisit( const ast::RangeExpr * rangeExpr ) {
    1492                         // resolve low and high, accept candidates where low and high types unify
    1493                         CandidateFinder finder1( context, tenv );
    1494                         finder1.find( rangeExpr->low, ResolvMode::withAdjustment() );
    1495                         if ( finder1.candidates.empty() ) return;
    1496 
    1497                         CandidateFinder finder2( context, tenv );
    1498                         finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
    1499                         if ( finder2.candidates.empty() ) return;
    1500 
    1501                         reason.code = NoMatch;
    1502 
    1503                         for ( const CandidateRef & r1 : finder1.candidates ) {
    1504                                 for ( const CandidateRef & r2 : finder2.candidates ) {
    1505                                         ast::TypeEnvironment env{ r1->env };
    1506                                         env.simpleCombine( r2->env );
    1507                                         ast::OpenVarSet open{ r1->open };
    1508                                         mergeOpenVars( open, r2->open );
    1509                                         ast::AssertionSet need;
    1510                                         mergeAssertionSet( need, r1->need );
    1511                                         mergeAssertionSet( need, r2->need );
    1512                                         ast::AssertionSet have;
    1513 
    1514                                         ast::ptr< ast::Type > common;
    1515                                         if (
    1516                                                 unify(
    1517                                                         r1->expr->result, r2->expr->result, env, need, have, open, symtab,
    1518                                                         common )
    1519                                         ) {
    1520                                                 // generate new expression
    1521                                                 ast::RangeExpr * newExpr =
    1522                                                         new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };
    1523                                                 newExpr->result = common ? common : r1->expr->result;
    1524                                                 // add candidate
    1525                                                 CandidateRef newCand = std::make_shared<Candidate>(
    1526                                                         newExpr, std::move( env ), std::move( open ), std::move( need ),
    1527                                                         r1->cost + r2->cost );
    1528                                                 inferParameters( newCand, candidates );
    1529                                         }
    1530                                 }
    1531                         }
    1532                 }
    1533 
    1534                 void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {
    1535                         std::vector< CandidateFinder > subCandidates =
    1536                                 selfFinder.findSubExprs( tupleExpr->exprs );
    1537                         std::vector< CandidateList > possibilities;
    1538                         combos( subCandidates.begin(), subCandidates.end(), back_inserter( possibilities ) );
    1539 
    1540                         for ( const CandidateList & subs : possibilities ) {
    1541                                 std::vector< ast::ptr< ast::Expr > > exprs;
    1542                                 exprs.reserve( subs.size() );
    1543                                 for ( const CandidateRef & sub : subs ) { exprs.emplace_back( sub->expr ); }
    1544 
    1545                                 ast::TypeEnvironment env;
    1546                                 ast::OpenVarSet open;
    1547                                 ast::AssertionSet need;
    1548                                 for ( const CandidateRef & sub : subs ) {
    1549                                         env.simpleCombine( sub->env );
    1550                                         mergeOpenVars( open, sub->open );
    1551                                         mergeAssertionSet( need, sub->need );
    1552                                 }
    1553 
    1554                                 addCandidate(
    1555                                         new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) },
    1556                                         std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) );
    1557                         }
    1558                 }
    1559 
    1560                 void postvisit( const ast::TupleExpr * tupleExpr ) {
    1561                         addCandidate( tupleExpr, tenv );
    1562                 }
    1563 
    1564                 void postvisit( const ast::TupleIndexExpr * tupleExpr ) {
    1565                         addCandidate( tupleExpr, tenv );
    1566                 }
    1567 
    1568                 void postvisit( const ast::TupleAssignExpr * tupleExpr ) {
    1569                         addCandidate( tupleExpr, tenv );
    1570                 }
    1571 
    1572                 void postvisit( const ast::UniqueExpr * unqExpr ) {
    1573                         CandidateFinder finder( context, tenv );
    1574                         finder.find( unqExpr->expr, ResolvMode::withAdjustment() );
    1575                         for ( CandidateRef & r : finder.candidates ) {
    1576                                 // ensure that the the id is passed on so that the expressions are "linked"
    1577                                 addCandidate( *r, new ast::UniqueExpr{ unqExpr->location, r->expr, unqExpr->id } );
    1578                         }
    1579                 }
    1580 
    1581                 void postvisit( const ast::StmtExpr * stmtExpr ) {
    1582                         addCandidate( resolveStmtExpr( stmtExpr, context ), tenv );
    1583                 }
    1584 
    1585                 void postvisit( const ast::UntypedInitExpr * initExpr ) {
    1586                         // handle each option like a cast
    1587                         CandidateList matches;
    1588                         PRINT(
    1589                                 std::cerr << "untyped init expr: " << initExpr << std::endl;
    1590                         )
    1591                         // O(n^2) checks of d-types with e-types
    1592                         for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) {
    1593                                 // calculate target type
    1594                                 const ast::Type * toType = resolveTypeof( initAlt.type, context );
    1595                                 toType = adjustExprType( toType, tenv, symtab );
    1596                                 // The call to find must occur inside this loop, otherwise polymorphic return
    1597                                 // types are not bound to the initialization type, since return type variables are
    1598                                 // only open for the duration of resolving the UntypedExpr.
    1599                                 CandidateFinder finder( context, tenv, toType );
    1600                                 finder.find( initExpr->expr, ResolvMode::withAdjustment() );
    1601                                 for ( CandidateRef & cand : finder.candidates ) {
    1602                                         if(reason.code == NotFound) reason.code = NoMatch;
    1603 
    1604                                         ast::TypeEnvironment env{ cand->env };
    1605                                         ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
    1606                                         ast::OpenVarSet open{ cand->open };
    1607 
    1608                                         PRINT(
    1609                                                 std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
    1610                                         )
    1611 
    1612                                         // It is possible that a cast can throw away some values in a multiply-valued
    1613                                         // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of
    1614                                         // the subexpression results that are cast directly. The candidate is invalid
    1615                                         // if it has fewer results than there are types to cast to.
    1616                                         int discardedValues = cand->expr->result->size() - toType->size();
    1617                                         if ( discardedValues < 0 ) continue;
    1618 
    1619                                         // unification run for side-effects
    1620                                         bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab );
    1621                                         (void) canUnify;
    1622                                         Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),
    1623                                                 symtab, env );
    1624                                         PRINT(
    1625                                                 Cost legacyCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),
    1626                                                         symtab, env );
    1627                                                 std::cerr << "Considering initialization:";
    1628                                                 std::cerr << std::endl << "  FROM: " << cand->expr->result << std::endl;
    1629                                                 std::cerr << std::endl << "  TO: "   << toType             << std::endl;
    1630                                                 std::cerr << std::endl << "  Unification " << (canUnify ? "succeeded" : "failed");
    1631                                                 std::cerr << std::endl << "  Legacy cost " << legacyCost;
    1632                                                 std::cerr << std::endl << "  New cost " << thisCost;
    1633                                                 std::cerr << std::endl;
    1634                                         )
    1635                                         if ( thisCost != Cost::infinity ) {
    1636                                                 // count one safe conversion for each value that is thrown away
    1637                                                 thisCost.incSafe( discardedValues );
    1638                                                 CandidateRef newCand = std::make_shared<Candidate>(
    1639                                                         new ast::InitExpr{
    1640                                                                 initExpr->location, restructureCast( cand->expr, toType ),
    1641                                                                 initAlt.designation },
    1642                                                         std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost );
    1643                                                 inferParameters( newCand, matches );
    1644                                         }
    1645                                 }
    1646 
    1647                         }
    1648 
    1649                         // select first on argument cost, then conversion cost
    1650                         CandidateList minArgCost = findMinCost( matches );
    1651                         promoteCvtCost( minArgCost );
    1652                         candidates = findMinCost( minArgCost );
    1653                 }
    1654 
    1655                 void postvisit( const ast::InitExpr * ) {
    1656                         assertf( false, "CandidateFinder should never see a resolved InitExpr." );
    1657                 }
    1658 
    1659                 void postvisit( const ast::DeletedExpr * ) {
    1660                         assertf( false, "CandidateFinder should never see a DeletedExpr." );
    1661                 }
    1662 
    1663                 void postvisit( const ast::GenericExpr * ) {
    1664                         assertf( false, "_Generic is not yet supported." );
    1665                 }
    1666         };
    1667 
    1668         // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder");
    1669         /// Prunes a list of candidates down to those that have the minimum conversion cost for a given
    1670         /// return type. Skips ambiguous candidates.
    1671 
    1672 } // anonymous namespace
    1673 
    1674 bool CandidateFinder::pruneCandidates( CandidateList & candidates, CandidateList & out, std::vector<std::string> & errors ) {
    1675         struct PruneStruct {
    1676                 CandidateRef candidate;
    1677                 bool ambiguous;
    1678 
    1679                 PruneStruct() = default;
    1680                 PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}
    1681         };
    1682 
    1683         // find lowest-cost candidate for each type
    1684         std::unordered_map< std::string, PruneStruct > selected;
    1685         // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found
    1686         std::sort(candidates.begin(), candidates.end(), [](const CandidateRef & x, const CandidateRef & y){return x->cost < y->cost;});
    1687         for ( CandidateRef & candidate : candidates ) {
    1688                 std::string mangleName;
    1689                 {
    1690                         ast::ptr< ast::Type > newType = candidate->expr->result;
    1691                         assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());
    1692                         candidate->env.apply( newType );
    1693                         mangleName = Mangle::mangle( newType );
    1694                 }
    1695 
    1696                 auto found = selected.find( mangleName );
    1697                 if (found != selected.end() && found->second.candidate->cost < candidate->cost) {
    1698                         PRINT(
    1699                                 std::cerr << "cost " << candidate->cost << " loses to "
    1700                                         << found->second.candidate->cost << std::endl;
    1701                         )
    1702                         continue;
    1703                 }
    1704 
    1705                 // xxx - when do satisfyAssertions produce more than 1 result?
    1706                 // this should only happen when initial result type contains
    1707                 // unbound type parameters, then it should never be pruned by
    1708                 // the previous step, since renameTyVars guarantees the mangled name
    1709                 // is unique.
    1710                 CandidateList satisfied;
    1711                 bool needRecomputeKey = false;
    1712                 if (candidate->need.empty()) {
    1713                         satisfied.emplace_back(candidate);
    1714                 }
    1715                 else {
    1716                         satisfyAssertions(candidate, context.symtab, satisfied, errors);
    1717                         needRecomputeKey = true;
    1718                 }
    1719 
    1720                 for (auto & newCand : satisfied) {
    1721                         // recomputes type key, if satisfyAssertions changed it
    1722                         if (needRecomputeKey)
    1723                         {
    1724                                 ast::ptr< ast::Type > newType = newCand->expr->result;
    1725                                 assertf(newCand->expr->result, "Result of expression %p for candidate is null", newCand->expr.get());
    1726                                 newCand->env.apply( newType );
    1727                                 mangleName = Mangle::mangle( newType );
    1728                         }
    1729                         auto found = selected.find( mangleName );
    1730                         if ( found != selected.end() ) {
    1731                                 if ( newCand->cost < found->second.candidate->cost ) {
    1732                                         PRINT(
    1733                                                 std::cerr << "cost " << newCand->cost << " beats "
    1734                                                         << found->second.candidate->cost << std::endl;
    1735                                         )
    1736 
    1737                                         found->second = PruneStruct{ newCand };
    1738                                 } else if ( newCand->cost == found->second.candidate->cost ) {
    1739                                         // if one of the candidates contains a deleted identifier, can pick the other,
    1740                                         // since deleted expressions should not be ambiguous if there is another option
    1741                                         // that is at least as good
    1742                                         if ( findDeletedExpr( newCand->expr ) ) {
    1743                                                 // do nothing
    1744                                                 PRINT( std::cerr << "candidate is deleted" << std::endl; )
    1745                                         } else if ( findDeletedExpr( found->second.candidate->expr ) ) {
    1746                                                 PRINT( std::cerr << "current is deleted" << std::endl; )
    1747                                                 found->second = PruneStruct{ newCand };
    1748                                         } else {
    1749                                                 PRINT( std::cerr << "marking ambiguous" << std::endl; )
    1750                                                 found->second.ambiguous = true;
    1751                                         }
    1752                                 } else {
    1753                                         // xxx - can satisfyAssertions increase the cost?
    1754                                         PRINT(
    1755                                                 std::cerr << "cost " << newCand->cost << " loses to "
    1756                                                         << found->second.candidate->cost << std::endl;
    1757                                         )
    1758                                 }
    1759                         } else {
    1760                                 selected.emplace_hint( found, mangleName, newCand );
    1761                         }
    1762                 }
    1763         }
    1764 
    1765         // report unambiguous min-cost candidates
    1766         // CandidateList out;
    1767         for ( auto & target : selected ) {
    1768                 if ( target.second.ambiguous ) continue;
    1769 
    1770                 CandidateRef cand = target.second.candidate;
    1771 
    1772                 ast::ptr< ast::Type > newResult = cand->expr->result;
    1773                 cand->env.applyFree( newResult );
    1774                 cand->expr = ast::mutate_field(
    1775                         cand->expr.get(), &ast::Expr::result, std::move( newResult ) );
    1776 
    1777                 out.emplace_back( cand );
    1778         }
    1779         // if everything is lost in satisfyAssertions, report the error
    1780         return !selected.empty();
    1781 }
    1782 
    1783 void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) {
    1784         // Find alternatives for expression
    1785         ast::Pass<Finder> finder{ *this };
    1786         expr->accept( finder );
    1787 
    1788         if ( mode.failFast && candidates.empty() ) {
    1789                 switch(finder.core.reason.code) {
    1790                 case Finder::NotFound:
    1791                         { SemanticError( expr, "No alternatives for expression " ); break; }
    1792                 case Finder::NoMatch:
    1793                         { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; }
    1794                 case Finder::ArgsToFew:
    1795                 case Finder::ArgsToMany:
    1796                 case Finder::RetsToFew:
    1797                 case Finder::RetsToMany:
    1798                 case Finder::NoReason:
    1799                 default:
    1800                         { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); }
    1801                 }
    1802         }
    1803 
    1804         /*
    1805         if ( mode.satisfyAssns || mode.prune ) {
    1806                 // trim candidates to just those where the assertions are satisfiable
    1807                 // - necessary pre-requisite to pruning
    1808                 CandidateList satisfied;
    1809                 std::vector< std::string > errors;
    1810                 for ( CandidateRef & candidate : candidates ) {
    1811                         satisfyAssertions( candidate, localSyms, satisfied, errors );
    1812                 }
    1813 
    1814                 // fail early if none such
    1815                 if ( mode.failFast && satisfied.empty() ) {
    1816                         std::ostringstream stream;
    1817                         stream << "No alternatives with satisfiable assertions for " << expr << "\n";
    1818                         for ( const auto& err : errors ) {
    1819                                 stream << err;
    1820                         }
    1821                         SemanticError( expr->location, stream.str() );
    1822                 }
    1823 
    1824                 // reset candidates
    1825                 candidates = move( satisfied );
    1826         }
    1827         */
    1828 
    1829         if ( mode.prune ) {
    1830                 // trim candidates to single best one
    1831                 PRINT(
    1832                         std::cerr << "alternatives before prune:" << std::endl;
    1833                         print( std::cerr, candidates );
    1834                 )
    1835 
    1836                 CandidateList pruned;
    1837                 std::vector<std::string> errors;
    1838                 bool found = pruneCandidates( candidates, pruned, errors );
    1839 
    1840                 if ( mode.failFast && pruned.empty() ) {
    1841                         std::ostringstream stream;
    1842                         if (found) {
    1843                                 CandidateList winners = findMinCost( candidates );
    1844                                 stream << "Cannot choose between " << winners.size() << " alternatives for "
    1845                                         "expression\n";
    1846                                 ast::print( stream, expr );
    1847                                 stream << " Alternatives are:\n";
    1848                                 print( stream, winners, 1 );
    1849                                 SemanticError( expr->location, stream.str() );
    1850                         }
    1851                         else {
    1852                                 stream << "No alternatives with satisfiable assertions for " << expr << "\n";
    1853                                 for ( const auto& err : errors ) {
    1854                                         stream << err;
    1855                                 }
    1856                                 SemanticError( expr->location, stream.str() );
    1857                         }
    1858                 }
    1859 
    1860                 auto oldsize = candidates.size();
    1861                 candidates = std::move( pruned );
    1862 
    1863                 PRINT(
    1864                         std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl;
    1865                 )
    1866                 PRINT(
    1867                         std::cerr << "there are " << candidates.size() << " alternatives after elimination"
    1868                                 << std::endl;
    1869                 )
    1870         }
    1871 
    1872         // adjust types after pruning so that types substituted by pruneAlternatives are correctly
    1873         // adjusted
    1874         if ( mode.adjust ) {
    1875                 for ( CandidateRef & r : candidates ) {
    1876                         r->expr = ast::mutate_field(
    1877                                 r->expr.get(), &ast::Expr::result,
    1878                                 adjustExprType( r->expr->result, r->env, context.symtab ) );
    1879                 }
    1880         }
    1881 
    1882         // Central location to handle gcc extension keyword, etc. for all expressions
    1883         for ( CandidateRef & r : candidates ) {
    1884                 if ( r->expr->extension != expr->extension ) {
    1885                         r->expr.get_and_mutate()->extension = expr->extension;
    1886                 }
    1887         }
    1888 }
    1889 
    1890 std::vector< CandidateFinder > CandidateFinder::findSubExprs(
    1891         const std::vector< ast::ptr< ast::Expr > > & xs
    1892 ) {
    1893         std::vector< CandidateFinder > out;
    1894 
    1895         for ( const auto & x : xs ) {
    1896                 out.emplace_back( context, env );
    1897                 out.back().find( x, ResolvMode::withAdjustment() );
    1898 
    1899                 PRINT(
    1900                         std::cerr << "findSubExprs" << std::endl;
    1901                         print( std::cerr, out.back().candidates );
    1902                 )
    1903         }
    1904 
    1905         return out;
    1906 }
    1907 
    19081970} // namespace ResolvExpr
    19091971
  • src/ResolvExpr/CurrentObject.cc

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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/ResolveAssertions.cc

    r2ed94a9 rb110bcc  
    3030#include "Common/FilterCombos.h"    // for filterCombos
    3131#include "Common/Indenter.h"        // for Indenter
    32 #include "Common/utility.h"         // for sort_mins
    3332#include "GenPoly/GenPoly.h"        // for getFunctionType
    3433#include "ResolvExpr/AlternativeFinder.h"  // for computeConversionCost
  • src/ResolvExpr/Resolver.cc

    r2ed94a9 rb110bcc  
    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
  • src/ResolvExpr/Resolver.h

    r2ed94a9 rb110bcc  
    3434        class Decl;
    3535        class DeletedExpr;
     36        class Expr;
    3637        class Init;
    3738        class StmtExpr;
  • src/SymTab/Autogen.cc

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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
     
    4545        /// returns true if obj's name is the empty string and it has a bitfield width
    4646        bool isUnnamedBitfield( ObjectDecl * obj );
    47         bool isUnnamedBitfield( const ast::ObjectDecl * obj );
    4847
    4948        /// generate the type of an assignment function for paramType.
     
    5554        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
    5655
    57         ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true);
    58 
    5956        /// generate the type of a copy constructor for paramType.
    6057        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
     
    6764        template< typename OutputIterator >
    6865        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 );
    7566
    7667        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
     
    121112
    122113                *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 };
    180114
    181115                srcParam.clearArrayIndices();
     
    248182        }
    249183
    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 
    320184        template< typename OutputIterator >
    321185        Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
     
    325189                } else {
    326190                        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 );
    344191                }
    345192        }
     
    379226        }
    380227
    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         }
    414228} // namespace SymTab
    415229
  • src/SymTab/FixFunction.cc

    r2ed94a9 rb110bcc  
    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/Mangler.cc

    r2ed94a9 rb110bcc  
    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...
  • src/SymTab/Validate.cc

    r2ed94a9 rb110bcc  
    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
  • src/SymTab/ValidateType.cc

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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/FunctionDecl.cc

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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 ); }
     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 ); }
    272272        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    273273        bool isInteger() const;
     
    279279
    280280        // In C99, pointer types can be qualified in many ways e.g., int f( int a[ static 3 ] )
    281         Expression *dimension;
     281        Expression * dimension;
    282282        bool isVarLen;
    283283        bool isStatic;
    284284
    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 * >() );
     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 * >() );
    287287        PointerType( const PointerType& );
    288288        virtual ~PointerType();
    289289
    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; }
     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; }
    294294        bool get_isVarLen() { return isVarLen; }
    295295        void set_isVarLen( bool newValue ) { isVarLen = newValue; }
     
    301301        virtual bool isComplete() const override { return ! isVarLen; }
    302302
    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 ); }
     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 ); }
    307307        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    308308};
     
    310310class ArrayType : public Type {
    311311  public:
    312         Type *base;
    313         Expression *dimension;
     312        Type * base;
     313        Expression * dimension;
    314314        bool isVarLen;
    315315        bool isStatic;
    316316
    317         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 * >() );
    318318        ArrayType( const ArrayType& );
    319319        virtual ~ArrayType();
    320320
    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; }
     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; }
    325325        bool get_isVarLen() { return isVarLen; }
    326326        void set_isVarLen( bool newValue ) { isVarLen = newValue; }
     
    333333        virtual bool isComplete() const override { return dimension || isVarLen; }
    334334
    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 ); }
     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 ); }
    339339        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    340340};
     
    348348        virtual ~QualifiedType();
    349349
    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 ); }
     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 ); }
    354354        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    355355};
     
    357357class ReferenceType : public Type {
    358358public:
    359         Type *base;
    360 
    361         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 * >() );
    362362        ReferenceType( const ReferenceType & );
    363363        virtual ~ReferenceType();
    364364
    365         Type *get_base() { return base; }
    366         void set_base( Type *newValue ) { base = newValue; }
     365        Type * get_base() { return base; }
     366        void set_base( Type * newValue ) { base = newValue; }
    367367
    368368        virtual int referenceDepth() const override;
     
    375375        virtual TypeSubstitution genericSubstitution() const override;
    376376
    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 ); }
     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 ); }
    381381        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    382382};
     
    405405        bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; }
    406406
    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 ); }
     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 ); }
    411411        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    412412};
     
    414414class ReferenceToType : public Type {
    415415  public:
    416         std::list< Expression* > parameters;
     416        std::list< Expression * > parameters;
    417417        std::string name;
    418418        bool hoistType;
     
    428428        void set_hoistType( bool newValue ) { hoistType = newValue; }
    429429
    430         virtual ReferenceToType *clone() const override = 0;
     430        virtual ReferenceToType * clone() const override = 0;
    431431        virtual void accept( Visitor & v ) override = 0;
    432         virtual Type *acceptMutator( Mutator & m ) override = 0;
     432        virtual Type * acceptMutator( Mutator & m ) override = 0;
    433433        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    434434
     
    443443        // this decl is not "owned" by the struct inst; it is merely a pointer to elsewhere in the tree,
    444444        // where the structure used in this type is actually defined
    445         StructDecl *baseStruct;
     445        StructDecl * baseStruct;
    446446
    447447        StructInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ), baseStruct( 0 ) {}
     
    449449        StructInstType( const StructInstType & other ) : Parent( other ), baseStruct( other.baseStruct ) {}
    450450
    451         StructDecl *get_baseStruct() const { return baseStruct; }
    452         void set_baseStruct( StructDecl *newValue ) { baseStruct = newValue; }
     451        StructDecl * get_baseStruct() const { return baseStruct; }
     452        void set_baseStruct( StructDecl * newValue ) { baseStruct = newValue; }
    453453
    454454        /// Accesses generic parameters of base struct (NULL if none such)
     
    466466        void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override;
    467467
    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 ); }
     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 ); }
    472472
    473473        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    481481        // this decl is not "owned" by the union inst; it is merely a pointer to elsewhere in the tree,
    482482        // where the union used in this type is actually defined
    483         UnionDecl *baseUnion;
     483        UnionDecl * baseUnion;
    484484
    485485        UnionInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ), baseUnion( 0 ) {}
     
    487487        UnionInstType( const UnionInstType & other ) : Parent( other ), baseUnion( other.baseUnion ) {}
    488488
    489         UnionDecl *get_baseUnion() const { return baseUnion; }
     489        UnionDecl * get_baseUnion() const { return baseUnion; }
    490490        void set_baseUnion( UnionDecl * newValue ) { baseUnion = newValue; }
    491491
     
    504504        void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override;
    505505
    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 ); }
     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 ); }
    510510
    511511        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    519519        // this decl is not "owned" by the enum inst; it is merely a pointer to elsewhere in the tree,
    520520        // where the enum used in this type is actually defined
    521         EnumDecl *baseEnum = nullptr;
     521        EnumDecl * baseEnum = nullptr;
    522522
    523523        EnumInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ) {}
     
    525525        EnumInstType( const EnumInstType & other ) : Parent( other ), baseEnum( other.baseEnum ) {}
    526526
    527         EnumDecl *get_baseEnum() const { return baseEnum; }
    528         void set_baseEnum( EnumDecl *newValue ) { baseEnum = newValue; }
     527        EnumDecl * get_baseEnum() const { return baseEnum; }
     528        void set_baseEnum( EnumDecl * newValue ) { baseEnum = newValue; }
    529529
    530530        virtual bool isComplete() const override;
     
    532532        virtual AggregateDecl * getAggr() const override;
    533533
    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 ); }
     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 ); }
    538538
    539539        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    556556        virtual bool isComplete() const override;
    557557
    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 ); }
     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 ); }
    562562  private:
    563563        virtual std::string typeString() const override;
     
    569569        // this decl is not "owned" by the type inst; it is merely a pointer to elsewhere in the tree,
    570570        // where the type used here is actually defined
    571         TypeDecl *baseType;
     571        TypeDecl * baseType;
    572572        bool isFtype;
    573573
    574         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 * >()  );
    575575        TypeInstType( const Type::Qualifiers & tq, const std::string & name, bool isFtype, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    576576        TypeInstType( const TypeInstType & other );
    577577        ~TypeInstType();
    578578
    579         TypeDecl *get_baseType() const { return baseType; }
    580         void set_baseType( TypeDecl *newValue );
     579        TypeDecl * get_baseType() const { return baseType; }
     580        void set_baseType( TypeDecl * newValue );
    581581        bool get_isFtype() const { return isFtype; }
    582582        void set_isFtype( bool newValue ) { isFtype = newValue; }
     
    584584        virtual bool isComplete() const override;
    585585
    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 ); }
     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 ); }
    590590        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    591591  private:
     
    622622        // virtual bool isComplete() const override { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness
    623623
    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 ); }
     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 ); }
    628628        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    629629};
     
    631631class TypeofType : public Type {
    632632  public:
    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,
     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,
    638638                const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    639639        TypeofType( const TypeofType& );
    640640        virtual ~TypeofType();
    641641
    642         Expression *get_expr() const { return expr; }
    643         void set_expr( Expression *newValue ) { expr = newValue; }
     642        Expression * get_expr() const { return expr; }
     643        void set_expr( Expression * newValue ) { expr = newValue; }
    644644
    645645        virtual bool isComplete() const override { assert( false ); return false; }
    646646
    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 ); }
     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 ); }
    651651        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    652652};
     
    654654class VTableType : public Type {
    655655public:
    656         Type *base;
    657 
    658         VTableType( const Type::Qualifiers & tq, Type *base,
     656        Type * base;
     657
     658        VTableType( const Type::Qualifiers & tq, Type * base,
    659659                const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    660660        VTableType( const VTableType & );
    661661        virtual ~VTableType();
    662662
    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 ); }
     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 ); }
    670670        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    671671};
     
    674674  public:
    675675        std::string name;
    676         Expression *expr;
    677         Type *type;
     676        Expression * expr;
     677        Type * type;
    678678        bool isType;
    679679
    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 * >()  );
     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 * >()  );
    682682        AttrType( const AttrType& );
    683683        virtual ~AttrType();
     
    685685        const std::string & get_name() const { return name; }
    686686        void set_name( const std::string & newValue ) { name = 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; }
     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; }
    691691        bool get_isType() const { return isType; }
    692692        void set_isType( bool newValue ) { isType = newValue; }
     
    694694        virtual bool isComplete() const override { assert( false ); } // xxx - not sure what to do here
    695695
    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 ); }
     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 ); }
    700700        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    701701};
     
    709709        virtual bool isComplete() const override{ return true; } // xxx - is this right?
    710710
    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 ); }
     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 ); }
    715715        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    716716};
     
    722722        ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    723723
    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 ); }
     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 ); }
    728728        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    729729};
     
    735735        OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    736736
    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 ); }
     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 ); }
    741741        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    742742};
     
    746746        GlobalScopeType();
    747747
    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 ); }
     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 ); }
    752752        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    753753};
  • src/Validate/Autogen.cpp

    r2ed94a9 rb110bcc  
    3939#include "InitTweak/GenInit.h"     // for fixReturnStatements
    4040#include "InitTweak/InitTweak.h"   // for isAssignment, isCopyConstructor
     41#include "SymTab/GenImplicitCall.hpp"  // for genImplicitCall
    4142#include "SymTab/Mangler.h"        // for Mangler
    4243#include "CompilationState.h"
     
    423424        for ( unsigned int index = 0 ; index < fields ; ++index ) {
    424425                auto member = aggr->members[index].strict_as<ast::DeclWithType>();
    425                 if ( SymTab::isUnnamedBitfield(
     426                if ( ast::isUnnamedBitfield(
    426427                                dynamic_cast<const ast::ObjectDecl *>( member ) ) ) {
    427428                        if ( index == fields - 1 ) {
     
    599600                // Not sure why it could be null.
    600601                // Don't make a function for a parameter that is an unnamed bitfield.
    601                 if ( nullptr == field || SymTab::isUnnamedBitfield( field ) ) {
     602                if ( nullptr == field || ast::isUnnamedBitfield( field ) ) {
    602603                        continue;
    603604                // Matching Parameter: Initialize the field by copy.
  • src/Validate/FixQualifiedTypes.cpp

    r2ed94a9 rb110bcc  
    1616#include "Validate/FixQualifiedTypes.hpp"
    1717
     18#include "AST/LinkageSpec.hpp"             // for Linkage
    1819#include "AST/Pass.hpp"
    1920#include "AST/TranslationUnit.hpp"
     21#include "Common/ToString.hpp"             // for toString
     22#include "SymTab/Mangler.h"                // for Mangler
    2023#include "Validate/NoIdSymbolTable.hpp"
    21 #include "SymTab/Mangler.h"            // for Mangler
    22 #include "AST/LinkageSpec.hpp"                     // for Linkage
    2324
    2425namespace Validate {
  • src/Validate/ForallPointerDecay.cpp

    r2ed94a9 rb110bcc  
    2222#include "CodeGen/OperatorTable.h"
    2323#include "Common/CodeLocation.h"
     24#include "Common/ToString.hpp"
    2425#include "SymTab/FixFunction.h"
    2526
  • src/Validate/HandleAttributes.cc

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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/Virtual/module.mk

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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

    r2ed94a9 rb110bcc  
    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/Util.hpp"                     // for checkInvariants
    3435#include "CompilationState.h"
    3536#include "../config.h"                      // for CFA_LIBDIR
     
    4041#include "CodeTools/TrackLoc.h"             // for fillLocations
    4142#include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
    42 #include "Common/CompilerError.h"           // for CompilerError
    4343#include "Common/DeclStats.hpp"             // for printDeclStats
    4444#include "Common/ResolvProtoDump.hpp"       // for dumpAsResolverProto
    4545#include "Common/Stats.h"                   // for Stats
    46 #include "Common/UnimplementedError.h"      // for UnimplementedError
    4746#include "Common/utility.h"                 // for deleteAll, filter, printAll
    4847#include "Concurrency/Actors.hpp"           // for implementActors
     
    8483#include "Validate/VerifyCtorDtorAssign.hpp" // for verifyCtorDtorAssign
    8584#include "Virtual/ExpandCasts.h"            // for expandCasts
     85#include "Virtual/VirtualDtor.hpp"           // for implementVirtDtors
    8686
    8787static void NewPass( const char * const name ) {
     
    102102}
    103103
    104 #define PASS( name, pass )                  \
     104// Helpers for checkInvariant:
     105void checkInvariants( std::list< Declaration * > & ) {}
     106using ast::checkInvariants;
     107
     108#define PASS( name, pass, unit, ... )       \
    105109        if ( errorp ) { cerr << name << endl; } \
    106110        NewPass(name);                          \
    107111        Stats::Time::StartBlock(name);          \
    108         pass;                                   \
    109         Stats::Time::StopBlock();
     112        pass(unit,##__VA_ARGS__);               \
     113        Stats::Time::StopBlock();               \
     114        if ( invariant ) {                      \
     115                checkInvariants(unit);              \
     116        }
     117
     118#define DUMP( cond, unit )                  \
     119        if ( cond ) {                           \
     120                dump(unit);                         \
     121                return EXIT_SUCCESS;                \
     122        }
    110123
    111124static bool waiting_for_gdb = false;                                    // flag to set cfa-cpp to wait for gdb on start
     
    274287                        FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" );
    275288                        assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" );
    276                         parse( gcc_builtins, LinkageSpec::Compiler );
     289                        parse( gcc_builtins, ast::Linkage::Compiler );
    277290
    278291                        // read the extra prelude in, if not generating the cfa library
    279292                        FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" );
    280293                        assertf( extras, "cannot open extras.cf\n" );
    281                         parse( extras, LinkageSpec::BuiltinC );
     294                        parse( extras, ast::Linkage::BuiltinC );
    282295
    283296                        if ( ! libcfap ) {
     
    285298                                FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" );
    286299                                assertf( prelude, "cannot open prelude.cfa\n" );
    287                                 parse( prelude, LinkageSpec::Intrinsic );
     300                                parse( prelude, ast::Linkage::Intrinsic );
    288301
    289302                                // Read to cfa builtins, if not generating the cfa library
    290303                                FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" );
    291304                                assertf( builtins, "cannot open builtins.cf\n" );
    292                                 parse( builtins, LinkageSpec::BuiltinCFA );
    293                         } // if
    294                 } // if
    295 
    296                 parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, yydebug );
     305                                parse( builtins, ast::Linkage::BuiltinCFA );
     306                        } // if
     307                } // if
     308
     309                parse( input, libcfap ? ast::Linkage::Intrinsic : ast::Linkage::Cforall, yydebug );
    297310
    298311                transUnit = buildUnit();
    299312
    300                 if ( astp ) {
    301                         dump( std::move( transUnit ) );
    302                         return EXIT_SUCCESS;
    303                 } // if
     313                DUMP( astp, std::move( transUnit ) );
    304314
    305315                Stats::Time::StopBlock();
     
    310320                }
    311321
    312                 PASS( "Hoist Type Decls", Validate::hoistTypeDecls( transUnit ) );
    313                 // Hoist Type Decls pulls some declarations out of contexts where
    314                 // locations are not tracked. Perhaps they should be, but for now
    315                 // the full fill solves it.
    316                 forceFillCodeLocations( transUnit );
    317 
    318                 PASS( "Translate Exception Declarations", ControlStruct::translateExcept( transUnit ) );
    319                 if ( exdeclp ) {
    320                         dump( std::move( transUnit ) );
    321                         return EXIT_SUCCESS;
    322                 }
    323 
    324                 PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign( transUnit ) );
    325                 PASS( "Replace Typedefs", Validate::replaceTypedef( transUnit ) );
    326                 PASS( "Fix Return Types", Validate::fixReturnTypes( transUnit ) );
    327                 PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers( transUnit ) );
    328 
    329                 PASS( "Link Reference To Types", Validate::linkReferenceToTypes( transUnit ) );
    330 
    331                 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes( transUnit ) );
    332                 PASS( "Hoist Struct", Validate::hoistStruct( transUnit ) );
    333                 PASS( "Eliminate Typedef", Validate::eliminateTypedef( transUnit ) );
    334                 PASS( "Validate Generic Parameters", Validate::fillGenericParameters( transUnit ) );
    335                 PASS( "Translate Dimensions", Validate::translateDimensionParameters( transUnit ) );
    336                 PASS( "Check Function Returns", Validate::checkReturnStatements( transUnit ) );
    337                 PASS( "Fix Return Statements", InitTweak::fixReturnStatements( transUnit ) );
    338                 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) );
    339                 PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) );
    340                 PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls( transUnit ) );
    341 
    342                 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) );
    343 
    344         PASS( "Implement Actors", Concurrency::implementActors( transUnit ) );
    345 
    346                 PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) );
    347                 PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) );
    348                 PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) );
    349                 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) );
    350                 PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) );
    351                 PASS( "Fix Label Address", Validate::fixLabelAddresses( transUnit ) );
     322                PASS( "Hoist Type Decls", Validate::hoistTypeDecls, transUnit );
     323
     324                PASS( "Translate Exception Declarations", ControlStruct::translateExcept, transUnit );
     325                DUMP( exdeclp, std::move( transUnit ) );
     326                PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign, transUnit );
     327                PASS( "Replace Typedefs", Validate::replaceTypedef, transUnit );
     328                PASS( "Fix Return Types", Validate::fixReturnTypes, transUnit );
     329                PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers, transUnit );
     330
     331                PASS( "Link Reference To Types", Validate::linkReferenceToTypes, transUnit );
     332
     333                PASS( "Fix Qualified Types", Validate::fixQualifiedTypes, transUnit );
     334                PASS( "Hoist Struct", Validate::hoistStruct, transUnit );
     335                PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit );
     336                PASS( "Validate Generic Parameters", Validate::fillGenericParameters, transUnit );
     337                PASS( "Translate Dimensions", Validate::translateDimensionParameters, transUnit );
     338                PASS( "Check Function Returns", Validate::checkReturnStatements, transUnit );
     339                PASS( "Fix Return Statements", InitTweak::fixReturnStatements, transUnit );
     340                PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords, transUnit );
     341                PASS( "Forall Pointer Decay", Validate::decayForallPointers, transUnit );
     342                PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls, transUnit );
     343
     344                PASS( "Generate Autogen Routines", Validate::autogenerateRoutines, transUnit );
     345
     346                PASS( "Implement Actors", Concurrency::implementActors, transUnit );
     347                PASS( "Implement Virtual Destructors", Virtual::implementVirtDtors, transUnit );
     348                PASS( "Implement Mutex", Concurrency::implementMutex, transUnit );
     349                PASS( "Implement Thread Start", Concurrency::implementThreadStarter, transUnit );
     350                PASS( "Compound Literal", Validate::handleCompoundLiterals, transUnit );
     351                PASS( "Set Length From Initializer", Validate::setLengthFromInitializer, transUnit );
     352                PASS( "Find Global Decls", Validate::findGlobalDecls, transUnit );
     353                PASS( "Fix Label Address", Validate::fixLabelAddresses, transUnit );
    352354
    353355                if ( symtabp ) {
     
    360362                } // if
    361363
    362                 if ( validp ) {
    363                         dump( std::move( transUnit ) );
    364                         return EXIT_SUCCESS;
    365                 } // if
    366 
    367                 PASS( "Translate Throws", ControlStruct::translateThrows( transUnit ) );
    368                 PASS( "Fix Labels", ControlStruct::fixLabels( transUnit ) );
    369                 PASS( "Fix Names", CodeGen::fixNames( transUnit ) );
    370                 PASS( "Gen Init", InitTweak::genInit( transUnit ) );
    371                 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) );
     364                DUMP( validp, std::move( transUnit ) );
     365
     366                PASS( "Translate Throws", ControlStruct::translateThrows, transUnit );
     367                PASS( "Fix Labels", ControlStruct::fixLabels, transUnit );
     368                PASS( "Fix Names", CodeGen::fixNames, transUnit );
     369                PASS( "Gen Init", InitTweak::genInit, transUnit );
     370                PASS( "Expand Member Tuples" , Tuples::expandMemberTuples, transUnit );
    372371
    373372                if ( libcfap ) {
     
    381380                } // if
    382381
    383                 if ( bresolvep ) {
    384                         dump( std::move( transUnit ) );
    385                         return EXIT_SUCCESS;
    386                 } // if
     382                DUMP( bresolvep, std::move( transUnit ) );
    387383
    388384                if ( resolvprotop ) {
     
    391387                } // if
    392388
    393                 PASS( "Resolve", ResolvExpr::resolve( transUnit ) );
    394                 if ( exprp ) {
    395                         dump( std::move( transUnit ) );
    396                         return EXIT_SUCCESS;
    397                 } // if
    398 
    399                 forceFillCodeLocations( transUnit );
    400 
    401                 PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));
     389                PASS( "Resolve", ResolvExpr::resolve, transUnit );
     390                DUMP( exprp, std::move( transUnit ) );
     391
     392                PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() );
    402393
    403394                // fix ObjectDecl - replaces ConstructorInit nodes
    404                 if ( ctorinitp ) {
    405                         dump( std::move( transUnit ) );
    406                         return EXIT_SUCCESS;
    407                 } // if
     395                DUMP( ctorinitp, std::move( transUnit ) );
    408396
    409397                // Currently not working due to unresolved issues with UniqueExpr
    410                 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
    411 
    412                 PASS( "Translate Tries", ControlStruct::translateTries( transUnit ) );
    413                 PASS( "Gen Waitfor", Concurrency::generateWaitFor( transUnit ) );
     398                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
     399
     400                PASS( "Translate Tries", ControlStruct::translateTries, transUnit );
     401                PASS( "Gen Waitfor", Concurrency::generateWaitFor, transUnit );
    414402
    415403                // Needs to happen before tuple types are expanded.
    416                 PASS( "Convert Specializations",  GenPoly::convertSpecializations( transUnit ) );
    417 
    418                 PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) );
    419 
    420                 if ( tuplep ) {
    421                         dump( std::move( transUnit ) );
    422                         return EXIT_SUCCESS;
    423                 } // if
     404                PASS( "Convert Specializations",  GenPoly::convertSpecializations, transUnit );
     405
     406                PASS( "Expand Tuples", Tuples::expandTuples, transUnit );
     407                DUMP( tuplep, std::move( transUnit ) );
    424408
    425409                // Must come after Translate Tries.
    426                 PASS( "Virtual Expand Casts", Virtual::expandCasts( transUnit ) );
    427 
    428                 PASS( "Instantiate Generics", GenPoly::instantiateGeneric( transUnit ) );
    429                 if ( genericsp ) {
    430                         dump( std::move( transUnit ) );
    431                         return EXIT_SUCCESS;
    432                 } // if
    433 
    434                 PASS( "Convert L-Value", GenPoly::convertLvalue( transUnit ) );
     410                PASS( "Virtual Expand Casts", Virtual::expandCasts, transUnit );
     411
     412                PASS( "Instantiate Generics", GenPoly::instantiateGeneric, transUnit );
     413                DUMP( genericsp, std::move( transUnit ) );
     414
     415                PASS( "Convert L-Value", GenPoly::convertLvalue, transUnit );
    435416
    436417                translationUnit = convert( std::move( transUnit ) );
    437418
    438                 if ( bboxp ) {
    439                         dump( translationUnit );
    440                         return EXIT_SUCCESS;
    441                 } // if
    442                 PASS( "Box", GenPoly::box( translationUnit ) );
    443 
    444                 PASS( "Link-Once", CodeGen::translateLinkOnce( translationUnit ) );
     419                DUMP( bboxp, translationUnit );
     420                PASS( "Box", GenPoly::box, translationUnit );
     421
     422                PASS( "Link-Once", CodeGen::translateLinkOnce, translationUnit );
    445423
    446424                // Code has been lowered to C, now we can start generation.
    447425
    448                 if ( bcodegenp ) {
    449                         dump( translationUnit );
    450                         return EXIT_SUCCESS;
    451                 } // if
     426                DUMP( bcodegenp, translationUnit );
    452427
    453428                if ( optind < argc ) {                                                  // any commands after the flags and input file ? => output file name
     
    456431
    457432                CodeTools::fillLocations( translationUnit );
    458                 PASS( "Code Gen", CodeGen::generate( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ) );
     433                PASS( "Code Gen", CodeGen::generate, translationUnit, *output, ! genproto, prettycodegenp, true, linemarks );
    459434
    460435                CodeGen::FixMain::fix( translationUnit, *output,
     
    476451                } // if
    477452                e.print();
    478                 if ( output != &cout ) {
    479                         delete output;
    480                 } // if
    481                 return EXIT_FAILURE;
    482         } catch ( UnimplementedError & e ) {
    483                 cout << "Sorry, " << e.get_what() << " is not currently implemented" << endl;
    484                 if ( output != &cout ) {
    485                         delete output;
    486                 } // if
    487                 return EXIT_FAILURE;
    488         } catch ( CompilerError & e ) {
    489                 cerr << "Compiler Error: " << e.get_what() << endl;
    490                 cerr << "(please report bugs to [REDACTED])" << endl;
    491453                if ( output != &cout ) {
    492454                        delete output;
     
    517479
    518480
    519 static const char optstring[] = ":c:ghlLmNnpdP:S:twW:D:";
     481static const char optstring[] = ":c:ghilLmNnpdP:S:twW:D:";
    520482
    521483enum { PreludeDir = 128 };
     
    524486        { "gdb", no_argument, nullptr, 'g' },
    525487        { "help", no_argument, nullptr, 'h' },
     488        { "invariant", no_argument, nullptr, 'i' },
    526489        { "libcfa", no_argument, nullptr, 'l' },
    527490        { "linemarks", no_argument, nullptr, 'L' },
    528         { "no-main", no_argument, 0, 'm' },
     491        { "no-main", no_argument, nullptr, 'm' },
    529492        { "no-linemarks", no_argument, nullptr, 'N' },
    530493        { "no-prelude", no_argument, nullptr, 'n' },
     
    545508        "wait for gdb to attach",                                                       // -g
    546509        "print translator help message",                                        // -h
     510        "invariant checking during AST passes",                         // -i
    547511        "generate libcfa.c",                                                            // -l
    548512        "generate line marks",                                                          // -L
     
    638602                        usage( argv );                                                          // no return
    639603                        break;
     604                  case 'i':                                                                             // invariant checking
     605                        invariant = true;
     606                        break;
    640607                  case 'l':                                                                             // generate libcfa.c
    641608                        libcfap = true;
Note: See TracChangeset for help on using the changeset viewer.