Changeset 640b3df for src


Ignore:
Timestamp:
Feb 21, 2023, 4:24:34 PM (3 years ago)
Author:
caparson <caparson@…>
Branches:
ADT, ast-experimental, master
Children:
257a8f5, ce44c5f
Parents:
1180175 (diff), 9a533ba (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:
2 added
2 deleted
30 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Create.cpp

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

    r1180175 r640b3df  
    2020#include <unordered_map>
    2121
    22 #include "Common/utility.h"
     22#include "Common/Eval.h"       // for eval
    2323
    2424#include "Fwd.hpp"             // for UniqueId
  • src/AST/Pass.impl.hpp

    r1180175 r640b3df  
    2222#include "AST/TranslationUnit.hpp"
    2323#include "AST/TypeSubstitution.hpp"
     24#include "Common/Iterate.hpp"
    2425
    2526#define VISIT_START( node ) \
  • src/AST/Pass.proto.hpp

    r1180175 r640b3df  
    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/porting.md

    r1180175 r640b3df  
    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/Common/Eval.cc

    r1180175 r640b3df  
    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/module.mk

    r1180175 r640b3df  
    2020        Common/CodeLocationTools.hpp \
    2121        Common/CodeLocationTools.cpp \
    22         Common/CompilerError.h \
    2322        Common/Debug.h \
    2423        Common/DeclStats.hpp \
     
    2625        Common/ErrorObjects.h \
    2726        Common/Eval.cc \
     27        Common/Eval.h \
    2828        Common/Examine.cc \
    2929        Common/Examine.h \
     
    3131        Common/Indenter.h \
    3232        Common/Indenter.cc \
     33        Common/Iterate.hpp \
    3334        Common/PassVisitor.cc \
    3435        Common/PassVisitor.h \
     
    5253        Common/Stats/Time.cc \
    5354        Common/Stats/Time.h \
    54         Common/UnimplementedError.h \
    5555        Common/UniqueName.cc \
    5656        Common/UniqueName.h \
  • src/Common/utility.h

    r1180175 r640b3df  
    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>
     
    2725#include <string>
    2826#include <type_traits>
    29 #include <utility>
    3027#include <vector>
    3128#include <cstring>                                                                              // memcmp
     
    4946                return 0;
    5047        } // 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;
    7448}
    7549
     
    189163
    190164#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 );
    210 }
    211165
    212166template< typename... Args >
     
    236190}
    237191
    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 
    267192template< typename... Params >
    268193void warn( const Params & ... params ) {
    269194        std::cerr << "Warning: ";
    270         warn_single( params... );
     195        toString_single( std::cerr, params... );
     196        std::cerr << std::endl;
    271197}
    272198
     
    274200static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int start = 0 ) {
    275201        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;
     202        return pref == str.substr(start, pref.size());
     203}
    302204
    303205// -----------------------------------------------------------------------------
     
    356258        ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } }
    357259};
    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 }
    564260
    565261// -----------------------------------------------------------------------------
     
    583279} // ilog2
    584280
    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 
    629281// Local Variables: //
    630282// tab-width: 4 //
  • src/GenPoly/Box.cc

    r1180175 r640b3df  
    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

    r1180175 r640b3df  
    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

    r1180175 r640b3df  
    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

    r1180175 r640b3df  
    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

    r1180175 r640b3df  
    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/Parser/DeclarationNode.cc

    r1180175 r640b3df  
    1010// Created On       : Sat May 16 12:34:05 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Aug  8 17:07:00 2022
    13 // Update Count     : 1185
     12// Last Modified On : Thu Feb 16 14:12:03 2023
     13// Update Count     : 1388
    1414//
    1515
     
    6161        variable.initializer = nullptr;
    6262
    63 //      attr.name = nullptr;
    64         attr.expr = nullptr;
    65         attr.type = nullptr;
    66 
    6763        assert.condition = nullptr;
    6864        assert.message = nullptr;
     
    7066
    7167DeclarationNode::~DeclarationNode() {
    72 //      delete attr.name;
    73         delete attr.expr;
    74         delete attr.type;
    75 
    7668//      delete variable.name;
    7769        delete variable.assertions;
     
    115107        newnode->variable.initializer = maybeClone( variable.initializer );
    116108
    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 
    121109        newnode->assert.condition = maybeClone( assert.condition );
    122110        newnode->assert.message = maybeClone( assert.message );
     
    154142        } // if
    155143
    156         for ( Attribute * attr: reverseIterate( attributes ) ) {
    157                 os << string( indent + 2, ' ' ) << "attr " << attr->name.c_str();
    158         } // for
     144        if ( ! attributes.empty() ) {
     145                os << string( indent + 2, ' ' ) << "with attributes " << endl;
     146                for ( Attribute * attr: reverseIterate( attributes ) ) {
     147                        os << string( indent + 4, ' ' ) << attr->name.c_str() << endl;
     148                } // for
     149        } // if
    159150
    160151        os << endl;
     
    244235        newnode->type = new TypeData( TypeData::Aggregate );
    245236        newnode->type->aggregate.kind = kind;
    246         newnode->type->aggregate.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
     237        newnode->type->aggregate.anon = name == nullptr;
     238        newnode->type->aggregate.name = newnode->type->aggregate.anon ? new string( DeclarationNode::anonymous.newName() ) : name;
    247239        newnode->type->aggregate.actuals = actuals;
    248240        newnode->type->aggregate.fields = fields;
     
    250242        newnode->type->aggregate.tagged = false;
    251243        newnode->type->aggregate.parent = nullptr;
    252         newnode->type->aggregate.anon = name == nullptr;
    253244        return newnode;
    254245} // DeclarationNode::newAggregate
     
    257248        DeclarationNode * newnode = new DeclarationNode;
    258249        newnode->type = new TypeData( TypeData::Enum );
    259         newnode->type->enumeration.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name;
     250        newnode->type->enumeration.anon = name == nullptr;
     251        newnode->type->enumeration.name = newnode->type->enumeration.anon ? new string( DeclarationNode::anonymous.newName() ) : name;
    260252        newnode->type->enumeration.constants = constants;
    261253        newnode->type->enumeration.body = body;
    262         newnode->type->enumeration.anon = name == nullptr;
    263254        newnode->type->enumeration.typed = typed;
    264255        newnode->type->enumeration.hiding = hiding;
     
    989980        for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) {
    990981                try {
    991                         bool extracted = false;
    992                         bool anon = false;
     982                        bool extracted = false, anon = false;
     983                        AggregateDecl * unionDecl = nullptr;
     984
    993985                        if ( DeclarationNode * extr = cur->extractAggregate() ) {
    994986                                // handle the case where a structure declaration is contained within an object or type declaration
     987
    995988                                Declaration * decl = extr->build();
    996989                                if ( decl ) {
    997                                         // hoist the structure declaration
     990                                        // Remember the declaration if it is a union aggregate ?
     991                                        unionDecl = dynamic_cast<UnionDecl *>( decl );
     992
    998993                                        decl->location = cur->location;
    999                                         * out++ = decl;
     994                                        *out++ = decl;
    1000995
    1001996                                        // need to remember the cases where a declaration contains an anonymous aggregate definition
     
    1003998                                        assert( extr->type );
    1004999                                        if ( extr->type->kind == TypeData::Aggregate ) {
     1000                                                // typedef struct { int A } B is the only case?
    10051001                                                anon = extr->type->aggregate.anon;
    10061002                                        } else if ( extr->type->kind == TypeData::Enum ) {
    1007                                                 // xxx - is it useful to have an implicit anonymous enum member?
     1003                                                // typedef enum { A } B is the only case?
    10081004                                                anon = extr->type->enumeration.anon;
    10091005                                        }
     
    10141010                        Declaration * decl = cur->build();
    10151011                        if ( decl ) {
     1012                                if ( TypedefDecl * typedefDecl = dynamic_cast<TypedefDecl *>( decl ) ) {
     1013                                        if ( unionDecl ) {                                      // is the typedef alias a union aggregate ?
     1014                                                // This code handles a special issue with the attribute transparent_union.
     1015                                                //
     1016                                                //    typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union ))
     1017                                                //
     1018                                                // Here the attribute aligned goes with the typedef_name, so variables declared of this type are
     1019                                                // aligned.  However, the attribute transparent_union must be moved from the typedef_name to
     1020                                                // alias union U.  Currently, this is the only know attribute that must be moved from typedef to
     1021                                                // alias.
     1022
     1023                                                // If typedef is an alias for a union, then its alias type was hoisted above and remembered.
     1024                                                if ( UnionInstType * unionInstType = dynamic_cast<UnionInstType *>( typedefDecl->base ) ) {
     1025                                                        // Remove all transparent_union attributes from typedef and move to alias union.
     1026                                                        list<Attribute *>::iterator attr;
     1027                                                        for ( attr = unionInstType->attributes.begin(); attr != unionInstType->attributes.end(); ) { // forward order
     1028                                                                if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) {
     1029                                                                        list<Attribute *>::iterator cur = attr; // remember current node
     1030                                                                        attr++;                         // advance iterator
     1031                                                                        unionDecl->attributes.emplace_back( *cur ); // move current
     1032                                                                        unionInstType->attributes.erase( cur ); // remove current
     1033                                                                } else {
     1034                                                                        attr++;                         // advance iterator
     1035                                                                } // if
     1036                                                        } // for
     1037                                                } // if
     1038                                        } // if
     1039                                } // if
     1040
    10161041                                // don't include anonymous declaration for named aggregates, but do include them for anonymous aggregates, e.g.:
    10171042                                // struct S {
     
    11761201        assert( type );
    11771202
    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 
    11841203        switch ( type->kind ) {
    11851204          case TypeData::Enum:
  • src/Parser/ExpressionNode.cc

    r1180175 r640b3df  
    1010// Created On       : Sat May 16 13:17:07 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug  7 09:18:56 2021
    13 // Update Count     : 1077
     12// Last Modified On : Sat Feb 11 14:49:00 2023
     13// Update Count     : 1079
    1414//
    1515
     
    173173                if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; }
    174174
    175                 posn = str.rfind( "hh" );                                               // char
     175                posn = str.rfind( "hh" );                                               // signed char
    176176                if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
    177177
    178                 posn = str.rfind( "HH" );                                               // char
     178                posn = str.rfind( "HH" );                                               // signed char
    179179                if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; }
    180180
     
    592592Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) {
    593593        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.
     594        args.push_back( maybeMoveBuild< Expression >(expr_node) ); // xxx -- this is exactly the same as the val case now, refactor this code.
    595595        return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );
    596596} // build_unary_ptr
  • src/Parser/ParseNode.h

    r1180175 r640b3df  
    1010// Created On       : Sat May 16 13:28:16 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Nov  2 21:27:07 2022
    13 // Update Count     : 939
     12// Last Modified On : Sun Feb 19 09:02:37 2023
     13// Update Count     : 940
    1414//
    1515
     
    2727#include "Common/SemanticError.h"  // for SemanticError
    2828#include "Common/UniqueName.h"     // for UniqueName
    29 #include "Common/utility.h"        // for maybeClone, maybeBuild
     29#include "Common/utility.h"        // for maybeClone
     30#include "Parser/parserutility.h"  // for maybeBuild
    3031#include "SynTree/LinkageSpec.h"   // for Spec
    3132#include "SynTree/Declaration.h"   // for Aggregate
     
    324325        Variable_t variable;
    325326
    326         struct Attr_t {
    327 //              const std::string * name;
    328                 ExpressionNode * expr;
    329                 DeclarationNode * type;
    330         };
    331         Attr_t attr;
    332 
    333327        struct StaticAssert_t {
    334328                ExpressionNode * condition;
     
    342336
    343337        bool inLine = false;
    344         bool enumInLine = false; 
     338        bool enumInLine = false;
    345339        Type::FuncSpecifiers funcSpecs;
    346340        Type::StorageClasses storageClasses;
  • src/Parser/RunParser.cpp

    r1180175 r640b3df  
    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 : Thr Feb 16 10:08:00 2023
     13// Update Count     : 2
    1414//
    1515
     
    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;
  • src/Parser/RunParser.hpp

    r1180175 r640b3df  
    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/TypeData.cc

    r1180175 r640b3df  
    1010// Created On       : Sat May 16 15:12:51 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 10 22:36:52 2022
    13 // Update Count     : 677
     12// Last Modified On : Sun Feb 19 11:00:46 2023
     13// Update Count     : 679
    1414//
    1515
     
    375375                break;
    376376          case Enum:
    377                 os << "enumeration ";
     377                os << "enumeration " << *enumeration.name << endl;;
    378378                if ( enumeration.constants ) {
    379379                        os << "with constants" << endl;
  • src/Parser/TypeData.h

    r1180175 r640b3df  
    1010// Created On       : Sat May 16 15:18:36 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 10 22:18:49 2022
    13 // Update Count     : 203
     12// Last Modified On : Sun Feb 19 09:09:39 2023
     13// Update Count     : 204
    1414//
    1515
     
    3737                bool body;
    3838                bool anon;
    39 
    4039                bool tagged;
    4140                const std::string * parent = nullptr;
  • src/Parser/parser.yy

    r1180175 r640b3df  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  2 21:36:16 2023
    13 // Update Count     : 5865
     12// Last Modified On : Mon Feb 20 11:31:26 2023
     13// Update Count     : 5896
    1414//
    1515
     
    5555#include "Common/utility.h"                                                             // for maybeMoveBuild, maybeBuild, CodeLo...
    5656
    57 #include "SynTree/Attribute.h"     // for Attribute
     57#include "SynTree/Attribute.h"                                                  // for Attribute
    5858
    5959// lex uses __null in a boolean context, it's fine.
     
    19511951                {
    19521952                        typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "6" );
    1953                         $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef();
     1953                        $$ = $4->addQualifiers( $1 )->addType( $3 )->addTypedef();
    19541954                }
    19551955        | type_specifier TYPEDEF declarator
     
    19611961                {
    19621962                        typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "8" );
    1963                         $$ = $4->addQualifiers( $1 )->addTypedef()->addType( $1 );
     1963                        $$ = $4->addQualifiers( $1 )->addType( $1 )->addTypedef();
    19641964                }
    19651965        ;
     
    19831983        | typedef_expression                                                            // deprecated GCC, naming expression type
    19841984        | sue_declaration_specifier
     1985                {
     1986                        assert( $1->type );
     1987                        if ( $1->type->qualifiers.val != 0 ) {
     1988                                SemanticError( yylloc, "Useless type qualifier in empty declaration." ); $$ = nullptr;
     1989                        }
     1990                }
    19851991        ;
    19861992
  • src/Parser/parserutility.h

    r1180175 r640b3df  
    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 : Thr Feb 16 12:34:00 2023
     13// Update Count     : 5
    1414//
    1515
     
    2020Expression *notZeroExpr( Expression *orig );
    2121
     22template< typename T, typename U >
     23struct maybeBuild_t {
     24        static T * doit( const U *orig ) {
     25                if ( orig ) {
     26                        return orig->build();
     27                } else {
     28                        return 0;
     29                }
     30        }
     31};
     32
     33template< typename T, typename U >
     34static inline T * maybeBuild( const U *orig ) {
     35        return maybeBuild_t<T,U>::doit(orig);
     36}
     37
     38template< typename T, typename U >
     39static inline T * maybeMoveBuild( const U *orig ) {
     40        T* ret = maybeBuild<T>(orig);
     41        delete orig;
     42        return ret;
     43}
     44
    2245// Local Variables: //
    2346// tab-width: 4 //
  • src/ResolvExpr/CurrentObject.cc

    r1180175 r640b3df  
    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
  • src/ResolvExpr/ResolveAssertions.cc

    r1180175 r640b3df  
    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

    r1180175 r640b3df  
    3838#include "AST/SymbolTable.hpp"
    3939#include "AST/Type.hpp"
     40#include "Common/Eval.h"                 // for eval
    4041#include "Common/PassVisitor.h"          // for PassVisitor
    4142#include "Common/SemanticError.h"        // for SemanticError
  • src/ResolvExpr/Resolver.h

    r1180175 r640b3df  
    3434        class Decl;
    3535        class DeletedExpr;
     36        class Expr;
    3637        class Init;
    3738        class StmtExpr;
  • src/SynTree/AggregateDecl.cc

    r1180175 r640b3df  
    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/Type.h

    r1180175 r640b3df  
    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+
     26#include "Common/utility.h"  // for toCString
    2627#include "Mutator.h"         // for Mutator
    2728#include "SynTree.h"         // for AST nodes
     
    124125                bool operator!=( Qualifiers other ) const { return (val & Mask) != (other.val & Mask); }
    125126                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
     127                        return is_const    <= other.is_const        // Any non-const converts to const without cost
     128                                && is_volatile <= other.is_volatile             // Any non-volatile converts to volatile without cost
     129                                && is_mutex    >= other.is_mutex                // Any mutex converts to non-mutex without cost
     130                                && is_atomic   == other.is_atomic;              // No conversion from atomic to non atomic is free
    130131                }
    131132                bool operator<( Qualifiers other ) const { return *this != other && *this <= other; }
     
    189190        virtual TypeSubstitution genericSubstitution() const;
    190191
    191         virtual Type *clone() const = 0;
     192        virtual Type * clone() const = 0;
    192193        virtual void accept( Visitor & v ) = 0;
    193194        virtual void accept( Visitor & v ) const = 0;
    194         virtual Type *acceptMutator( Mutator & m ) = 0;
     195        virtual Type * acceptMutator( Mutator & m ) = 0;
    195196        virtual void print( std::ostream & os, Indenter indent = {} ) const;
    196197};
     
    207208        virtual bool isComplete() const override { return false; }
    208209
    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 ); }
     210        virtual VoidType * clone() const override { return new VoidType( *this ); }
     211        virtual void accept( Visitor & v ) override { v.visit( this ); }
     212        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     213        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    213214        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    214215};
     
    259260        // GENERATED END
    260261
    261         static const char *typeNames[];                                         // string names for basic types, MUST MATCH with Kind
     262        static const char * typeNames[];                                        // string names for basic types, MUST MATCH with Kind
    262263
    263264        BasicType( const Type::Qualifiers & tq, Kind bt, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     
    266267        void set_kind( Kind newValue ) { kind = newValue; }
    267268
    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 ); }
     269        virtual BasicType * clone() const override { return new BasicType( *this ); }
     270        virtual void accept( Visitor & v ) override { v.visit( this ); }
     271        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     272        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    272273        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    273274        bool isInteger() const;
     
    279280
    280281        // In C99, pointer types can be qualified in many ways e.g., int f( int a[ static 3 ] )
    281         Expression *dimension;
     282        Expression * dimension;
    282283        bool isVarLen;
    283284        bool isStatic;
    284285
    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 * >() );
     286        PointerType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     287        PointerType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    287288        PointerType( const PointerType& );
    288289        virtual ~PointerType();
    289290
    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; }
     291        Type * get_base() { return base; }
     292        void set_base( Type * newValue ) { base = newValue; }
     293        Expression * get_dimension() { return dimension; }
     294        void set_dimension( Expression * newValue ) { dimension = newValue; }
    294295        bool get_isVarLen() { return isVarLen; }
    295296        void set_isVarLen( bool newValue ) { isVarLen = newValue; }
     
    301302        virtual bool isComplete() const override { return ! isVarLen; }
    302303
    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 ); }
     304        virtual PointerType * clone() const override { return new PointerType( * this ); }
     305        virtual void accept( Visitor & v ) override { v.visit( this ); }
     306        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     307        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    307308        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    308309};
     
    310311class ArrayType : public Type {
    311312  public:
    312         Type *base;
    313         Expression *dimension;
     313        Type * base;
     314        Expression * dimension;
    314315        bool isVarLen;
    315316        bool isStatic;
    316317
    317         ArrayType( const Type::Qualifiers & tq, Type *base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     318        ArrayType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    318319        ArrayType( const ArrayType& );
    319320        virtual ~ArrayType();
    320321
    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; }
     322        Type * get_base() { return base; }
     323        void set_base( Type * newValue ) { base = newValue; }
     324        Expression * get_dimension() { return dimension; }
     325        void set_dimension( Expression * newValue ) { dimension = newValue; }
    325326        bool get_isVarLen() { return isVarLen; }
    326327        void set_isVarLen( bool newValue ) { isVarLen = newValue; }
     
    333334        virtual bool isComplete() const override { return dimension || isVarLen; }
    334335
    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 ); }
     336        virtual ArrayType * clone() const override { return new ArrayType( *this ); }
     337        virtual void accept( Visitor & v ) override { v.visit( this ); }
     338        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     339        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    339340        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    340341};
     
    348349        virtual ~QualifiedType();
    349350
    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 ); }
     351        virtual QualifiedType * clone() const override { return new QualifiedType( *this ); }
     352        virtual void accept( Visitor & v ) override { v.visit( this ); }
     353        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     354        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    354355        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    355356};
     
    357358class ReferenceType : public Type {
    358359public:
    359         Type *base;
    360 
    361         ReferenceType( const Type::Qualifiers & tq, Type *base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     360        Type * base;
     361
     362        ReferenceType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    362363        ReferenceType( const ReferenceType & );
    363364        virtual ~ReferenceType();
    364365
    365         Type *get_base() { return base; }
    366         void set_base( Type *newValue ) { base = newValue; }
     366        Type * get_base() { return base; }
     367        void set_base( Type * newValue ) { base = newValue; }
    367368
    368369        virtual int referenceDepth() const override;
     
    375376        virtual TypeSubstitution genericSubstitution() const override;
    376377
    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 ); }
     378        virtual ReferenceType * clone() const override { return new ReferenceType( *this ); }
     379        virtual void accept( Visitor & v ) override { v.visit( this ); }
     380        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     381        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    381382        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    382383};
     
    405406        bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; }
    406407
    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 ); }
     408        virtual FunctionType * clone() const override { return new FunctionType( *this ); }
     409        virtual void accept( Visitor & v ) override { v.visit( this ); }
     410        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     411        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    411412        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    412413};
     
    414415class ReferenceToType : public Type {
    415416  public:
    416         std::list< Expression* > parameters;
     417        std::list< Expression * > parameters;
    417418        std::string name;
    418419        bool hoistType;
     
    428429        void set_hoistType( bool newValue ) { hoistType = newValue; }
    429430
    430         virtual ReferenceToType *clone() const override = 0;
     431        virtual ReferenceToType * clone() const override = 0;
    431432        virtual void accept( Visitor & v ) override = 0;
    432         virtual Type *acceptMutator( Mutator & m ) override = 0;
     433        virtual Type * acceptMutator( Mutator & m ) override = 0;
    433434        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    434435
     
    443444        // this decl is not "owned" by the struct inst; it is merely a pointer to elsewhere in the tree,
    444445        // where the structure used in this type is actually defined
    445         StructDecl *baseStruct;
     446        StructDecl * baseStruct;
    446447
    447448        StructInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ), baseStruct( 0 ) {}
     
    449450        StructInstType( const StructInstType & other ) : Parent( other ), baseStruct( other.baseStruct ) {}
    450451
    451         StructDecl *get_baseStruct() const { return baseStruct; }
    452         void set_baseStruct( StructDecl *newValue ) { baseStruct = newValue; }
     452        StructDecl * get_baseStruct() const { return baseStruct; }
     453        void set_baseStruct( StructDecl * newValue ) { baseStruct = newValue; }
    453454
    454455        /// Accesses generic parameters of base struct (NULL if none such)
     
    466467        void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override;
    467468
    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 ); }
     469        virtual StructInstType * clone() const override { return new StructInstType( *this ); }
     470        virtual void accept( Visitor & v ) override { v.visit( this ); }
     471        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     472        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    472473
    473474        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    481482        // this decl is not "owned" by the union inst; it is merely a pointer to elsewhere in the tree,
    482483        // where the union used in this type is actually defined
    483         UnionDecl *baseUnion;
     484        UnionDecl * baseUnion;
    484485
    485486        UnionInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ), baseUnion( 0 ) {}
     
    487488        UnionInstType( const UnionInstType & other ) : Parent( other ), baseUnion( other.baseUnion ) {}
    488489
    489         UnionDecl *get_baseUnion() const { return baseUnion; }
     490        UnionDecl * get_baseUnion() const { return baseUnion; }
    490491        void set_baseUnion( UnionDecl * newValue ) { baseUnion = newValue; }
    491492
     
    504505        void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override;
    505506
    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 ); }
     507        virtual UnionInstType * clone() const override { return new UnionInstType( *this ); }
     508        virtual void accept( Visitor & v ) override { v.visit( this ); }
     509        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     510        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    510511
    511512        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    519520        // this decl is not "owned" by the enum inst; it is merely a pointer to elsewhere in the tree,
    520521        // where the enum used in this type is actually defined
    521         EnumDecl *baseEnum = nullptr;
     522        EnumDecl * baseEnum = nullptr;
    522523
    523524        EnumInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >()  ) : Parent( tq, name, attributes ) {}
     
    525526        EnumInstType( const EnumInstType & other ) : Parent( other ), baseEnum( other.baseEnum ) {}
    526527
    527         EnumDecl *get_baseEnum() const { return baseEnum; }
    528         void set_baseEnum( EnumDecl *newValue ) { baseEnum = newValue; }
     528        EnumDecl * get_baseEnum() const { return baseEnum; }
     529        void set_baseEnum( EnumDecl * newValue ) { baseEnum = newValue; }
    529530
    530531        virtual bool isComplete() const override;
     
    532533        virtual AggregateDecl * getAggr() const override;
    533534
    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 ); }
     535        virtual EnumInstType * clone() const override { return new EnumInstType( *this ); }
     536        virtual void accept( Visitor & v ) override { v.visit( this ); }
     537        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     538        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    538539
    539540        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
     
    556557        virtual bool isComplete() const override;
    557558
    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 ); }
     559        virtual TraitInstType * clone() const override { return new TraitInstType( *this ); }
     560        virtual void accept( Visitor & v ) override { v.visit( this ); }
     561        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     562        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    562563  private:
    563564        virtual std::string typeString() const override;
     
    569570        // this decl is not "owned" by the type inst; it is merely a pointer to elsewhere in the tree,
    570571        // where the type used here is actually defined
    571         TypeDecl *baseType;
     572        TypeDecl * baseType;
    572573        bool isFtype;
    573574
    574         TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl *baseType, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
     575        TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl * baseType, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    575576        TypeInstType( const Type::Qualifiers & tq, const std::string & name, bool isFtype, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    576577        TypeInstType( const TypeInstType & other );
    577578        ~TypeInstType();
    578579
    579         TypeDecl *get_baseType() const { return baseType; }
    580         void set_baseType( TypeDecl *newValue );
     580        TypeDecl * get_baseType() const { return baseType; }
     581        void set_baseType( TypeDecl * newValue );
    581582        bool get_isFtype() const { return isFtype; }
    582583        void set_isFtype( bool newValue ) { isFtype = newValue; }
     
    584585        virtual bool isComplete() const override;
    585586
    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 ); }
     587        virtual TypeInstType * clone() const override { return new TypeInstType( *this ); }
     588        virtual void accept( Visitor & v ) override { v.visit( this ); }
     589        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     590        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    590591        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    591592  private:
     
    622623        // virtual bool isComplete() const override { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness
    623624
    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 ); }
     625        virtual TupleType * clone() const override { return new TupleType( *this ); }
     626        virtual void accept( Visitor & v ) override { v.visit( this ); }
     627        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     628        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    628629        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    629630};
     
    631632class TypeofType : public Type {
    632633  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,
     634        Expression * expr;              ///< expression to take the type of
     635        bool is_basetypeof;             ///< true iff is basetypeof type
     636
     637        TypeofType( const Type::Qualifiers & tq, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     638        TypeofType( const Type::Qualifiers & tq, Expression * expr, bool is_basetypeof,
    638639                const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    639640        TypeofType( const TypeofType& );
    640641        virtual ~TypeofType();
    641642
    642         Expression *get_expr() const { return expr; }
    643         void set_expr( Expression *newValue ) { expr = newValue; }
     643        Expression * get_expr() const { return expr; }
     644        void set_expr( Expression * newValue ) { expr = newValue; }
    644645
    645646        virtual bool isComplete() const override { assert( false ); return false; }
    646647
    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 ); }
     648        virtual TypeofType * clone() const override { return new TypeofType( *this ); }
     649        virtual void accept( Visitor & v ) override { v.visit( this ); }
     650        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     651        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    651652        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    652653};
     
    654655class VTableType : public Type {
    655656public:
    656         Type *base;
    657 
    658         VTableType( const Type::Qualifiers & tq, Type *base,
     657        Type * base;
     658
     659        VTableType( const Type::Qualifiers & tq, Type * base,
    659660                const std::list< Attribute * > & attributes = std::list< Attribute * >() );
    660661        VTableType( const VTableType & );
    661662        virtual ~VTableType();
    662663
    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 ); }
     664        Type * get_base() { return base; }
     665        void set_base( Type * newValue ) { base = newValue; }
     666
     667        virtual VTableType * clone() const override { return new VTableType( *this ); }
     668        virtual void accept( Visitor & v ) override { v.visit( this ); }
     669        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     670        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    670671        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    671672};
     
    674675  public:
    675676        std::string name;
    676         Expression *expr;
    677         Type *type;
     677        Expression * expr;
     678        Type * type;
    678679        bool isType;
    679680
    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 * >()  );
     681        AttrType( const Type::Qualifiers & tq, const std::string & name, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
     682        AttrType( const Type::Qualifiers & tq, const std::string & name, Type * type, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    682683        AttrType( const AttrType& );
    683684        virtual ~AttrType();
     
    685686        const std::string & get_name() const { return name; }
    686687        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; }
     688        Expression * get_expr() const { return expr; }
     689        void set_expr( Expression * newValue ) { expr = newValue; }
     690        Type * get_type() const { return type; }
     691        void set_type( Type * newValue ) { type = newValue; }
    691692        bool get_isType() const { return isType; }
    692693        void set_isType( bool newValue ) { isType = newValue; }
     
    694695        virtual bool isComplete() const override { assert( false ); } // xxx - not sure what to do here
    695696
    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 ); }
     697        virtual AttrType * clone() const override { return new AttrType( *this ); }
     698        virtual void accept( Visitor & v ) override { v.visit( this ); }
     699        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     700        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    700701        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    701702};
     
    709710        virtual bool isComplete() const override{ return true; } // xxx - is this right?
    710711
    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 ); }
     712        virtual VarArgsType * clone() const override { return new VarArgsType( *this ); }
     713        virtual void accept( Visitor & v ) override { v.visit( this ); }
     714        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     715        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    715716        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    716717};
     
    722723        ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    723724
    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 ); }
     725        virtual ZeroType * clone() const override { return new ZeroType( *this ); }
     726        virtual void accept( Visitor & v ) override { v.visit( this ); }
     727        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     728        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    728729        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    729730};
     
    735736        OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >()  );
    736737
    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 ); }
     738        virtual OneType * clone() const override { return new OneType( *this ); }
     739        virtual void accept( Visitor & v ) override { v.visit( this ); }
     740        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     741        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    741742        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    742743};
     
    746747        GlobalScopeType();
    747748
    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 ); }
     749        virtual GlobalScopeType * clone() const override { return new GlobalScopeType( *this ); }
     750        virtual void accept( Visitor & v ) override { v.visit( this ); }
     751        virtual void accept( Visitor & v ) const override { v.visit( this ); }
     752        virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
    752753        virtual void print( std::ostream & os, Indenter indent = {} ) const override;
    753754};
  • src/Validate/HandleAttributes.cc

    r1180175 r640b3df  
    1717
    1818#include "CompilationState.h"
     19#include "Common/Eval.h"
    1920#include "Common/PassVisitor.h"
    2021#include "Common/SemanticError.h"
  • src/main.cc

    r1180175 r640b3df  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Oct  5 12:06:00 2022
    13 // Update Count     : 679
     12// Last Modified On : Thr Feb 16 10:08:00 2023
     13// Update Count     : 680
    1414//
    1515
     
    4040#include "CodeTools/TrackLoc.h"             // for fillLocations
    4141#include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
    42 #include "Common/CompilerError.h"           // for CompilerError
    4342#include "Common/DeclStats.hpp"             // for printDeclStats
    4443#include "Common/ResolvProtoDump.hpp"       // for dumpAsResolverProto
    4544#include "Common/Stats.h"                   // for Stats
    46 #include "Common/UnimplementedError.h"      // for UnimplementedError
    4745#include "Common/utility.h"                 // for deleteAll, filter, printAll
    4846#include "Concurrency/Actors.hpp"           // for implementActors
     
    274272                        FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" );
    275273                        assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" );
    276                         parse( gcc_builtins, LinkageSpec::Compiler );
     274                        parse( gcc_builtins, ast::Linkage::Compiler );
    277275
    278276                        // read the extra prelude in, if not generating the cfa library
    279277                        FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" );
    280278                        assertf( extras, "cannot open extras.cf\n" );
    281                         parse( extras, LinkageSpec::BuiltinC );
     279                        parse( extras, ast::Linkage::BuiltinC );
    282280
    283281                        if ( ! libcfap ) {
     
    285283                                FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" );
    286284                                assertf( prelude, "cannot open prelude.cfa\n" );
    287                                 parse( prelude, LinkageSpec::Intrinsic );
     285                                parse( prelude, ast::Linkage::Intrinsic );
    288286
    289287                                // Read to cfa builtins, if not generating the cfa library
    290288                                FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" );
    291289                                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 );
     290                                parse( builtins, ast::Linkage::BuiltinCFA );
     291                        } // if
     292                } // if
     293
     294                parse( input, libcfap ? ast::Linkage::Intrinsic : ast::Linkage::Cforall, yydebug );
    297295
    298296                transUnit = buildUnit();
     
    342340                PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) );
    343341
    344         PASS( "Implement Actors", Concurrency::implementActors( transUnit ) );
    345 
     342                PASS( "Implement Actors", Concurrency::implementActors( transUnit ) );
    346343                PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) );
    347344                PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) );
     
    476473                } // if
    477474                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;
    491475                if ( output != &cout ) {
    492476                        delete output;
Note: See TracChangeset for help on using the changeset viewer.