- Timestamp:
- Feb 21, 2023, 4:24:34 PM (3 years ago)
- 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. - Location:
- src
- Files:
-
- 2 added
- 2 deleted
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Create.cpp
r1180175 r640b3df 20 20 #include "AST/Decl.hpp" 21 21 #include "AST/Type.hpp" 22 #include "Common/Iterate.hpp" 22 23 23 24 namespace ast { -
src/AST/Decl.cpp
r1180175 r640b3df 20 20 #include <unordered_map> 21 21 22 #include "Common/ utility.h"22 #include "Common/Eval.h" // for eval 23 23 24 24 #include "Fwd.hpp" // for UniqueId -
src/AST/Pass.impl.hpp
r1180175 r640b3df 22 22 #include "AST/TranslationUnit.hpp" 23 23 #include "AST/TypeSubstitution.hpp" 24 #include "Common/Iterate.hpp" 24 25 25 26 #define VISIT_START( node ) \ -
src/AST/Pass.proto.hpp
r1180175 r640b3df 18 18 19 19 #include "Common/Stats/Heap.h" 20 21 20 namespace 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 27 namespace ast::__pass { 28 29 typedef std::function<void( void * )> cleanup_func_t; 30 typedef 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 34 class bool_ref { 35 public: 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 42 private: 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 57 class guard_value { 58 public: 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 80 private: 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) {} 58 86 }; 59 87 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 92 class visit_children_guard { 93 public: 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 109 private: 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 117 template<typename core_t, typename node_t> 118 struct 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. 126 template< typename node_t > 127 struct 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. 136 template< template<class...> class container_t > 137 struct 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) {} 94 146 }; 95 147 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. 162 template< template<class...> class container_t, typename node_t > 163 struct 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 174 template<bool is_void> 175 struct __assign; 176 177 template<> 178 struct __assign<true> { 122 179 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 185 template<> 186 struct __assign<false> { 237 187 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 197 template<bool is_void> 198 struct __return; 199 200 template<> 201 struct __return<true> { 251 202 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 209 template<> 210 struct __return<false> { 255 211 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 232 template<typename core_t, typename node_t> 233 static 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 246 template<typename core_t, typename node_t> 247 static inline auto previsit( core_t &, const node_t *, long ) {} 248 249 // PostVisit : never mutates the passed pointer but may return a different node 250 template<typename core_t, typename node_t> 251 static 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 261 template<typename core_t, typename node_t> 262 static 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 ) \ 277 template< typename core_t > \ 278 static inline auto name( core_t & core, int ) -> decltype( &core.name ) { return &core.name; } \ 279 \ 280 template< typename core_t > \ 281 static inline default_type * name( core_t &, long ) { return nullptr; } 282 283 // List of fields and their expected types 284 FIELD_PTR( typeSubs, const ast::TypeSubstitution * ) 285 FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > ) 286 FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > ) 287 FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > ) 288 FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > ) 289 FIELD_PTR( visit_children, __pass::bool_ref ) 290 FIELD_PTR( at_cleanup, __pass::at_cleanup_t ) 291 FIELD_PTR( visitor, ast::Pass<core_t> * const ) 292 293 // Remove the macro to make sure we don't clash 294 #undef FIELD_PTR 295 296 template< typename core_t > 297 static inline auto beginTrace(core_t &, int) -> decltype( core_t::traceId, void() ) { 298 // Stats::Heap::stacktrace_push(core_t::traceId); 299 } 300 301 template< typename core_t > 302 static inline auto endTrace(core_t &, int) -> decltype( core_t::traceId, void() ) { 303 // Stats::Heap::stacktrace_pop(); 304 } 305 306 template< typename core_t > 307 static void beginTrace(core_t &, long) {} 308 309 template< typename core_t > 310 static 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 315 template< typename core_t > 316 static bool on_error (core_t &, ptr<Decl> &, long) { return true; } 317 318 template< typename core_t > 319 static auto on_error (core_t & core, ptr<Decl> & decl, int) -> decltype(core.on_error(decl)) { 320 return core.on_error(decl); 321 } 322 323 template< typename core_t, typename node_t > 324 static 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 331 template< typename core_t, typename node_t > 332 static 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 339 namespace 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 359 namespace 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 } \ 284 384 \ 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 456 namespace 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` 489 namespace 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. 503 namespace 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 213 213 * `get_statement()` exclusively used for code location, replaced with `CodeLocation` field 214 214 215 `CaseStmt` 215 `CaseStmt` => `CaseClause` 216 216 * `_isDefault` has been removed 217 217 * `isDefault` calculates value from `cond` … … 227 227 * `block` -> `body` and `finallyBlock` -> `finally` 228 228 229 `ThrowStmt` `CatchStmt`229 `ThrowStmt` and `CatchStmt` => `CatchClause` 230 230 * moved `Kind` enums to shared `ast::ExceptionKind` enum 231 231 232 `FinallyStmt` 232 `FinallyStmt` => `FinallyClause` 233 233 * `block` -> `body` 234 234 … … 280 280 * Template class, with specializations and using to implement some other types: 281 281 * `StructInstType`, `UnionInstType` & `EnumInstType` 282 * `baseStruct`, `baseUnion` & `baseEnum` => `base` 282 283 283 284 `TypeInstType` -
src/Common/Eval.cc
r1180175 r640b3df 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // utility.h --7 // Eval.cc -- Evaluate parts of the ast at compile time. 8 8 // 9 9 // Author : Richard C. Bilson … … 13 13 // Update Count : 119 14 14 // 15 16 #include "Eval.h" 15 17 16 18 #include <utility> // for pair -
src/Common/module.mk
r1180175 r640b3df 20 20 Common/CodeLocationTools.hpp \ 21 21 Common/CodeLocationTools.cpp \ 22 Common/CompilerError.h \23 22 Common/Debug.h \ 24 23 Common/DeclStats.hpp \ … … 26 25 Common/ErrorObjects.h \ 27 26 Common/Eval.cc \ 27 Common/Eval.h \ 28 28 Common/Examine.cc \ 29 29 Common/Examine.h \ … … 31 31 Common/Indenter.h \ 32 32 Common/Indenter.cc \ 33 Common/Iterate.hpp \ 33 34 Common/PassVisitor.cc \ 34 35 Common/PassVisitor.h \ … … 52 53 Common/Stats/Time.cc \ 53 54 Common/Stats/Time.h \ 54 Common/UnimplementedError.h \55 55 Common/UniqueName.cc \ 56 56 Common/UniqueName.h \ -
src/Common/utility.h
r1180175 r640b3df 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // utility.h -- 7 // utility.h -- General utilities used across the compiler. 8 8 // 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Apr 25 14:26:00 202213 // Update Count : 5 112 // Last Modified On : Fri Feb 17 15:25:00 2023 13 // Update Count : 53 14 14 // 15 15 … … 19 19 #include <cctype> 20 20 #include <algorithm> 21 #include <functional>22 21 #include <iostream> 23 #include <iterator>24 22 #include <list> 25 23 #include <memory> … … 27 25 #include <string> 28 26 #include <type_traits> 29 #include <utility>30 27 #include <vector> 31 28 #include <cstring> // memcmp … … 49 46 return 0; 50 47 } // 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 } // if61 }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;74 48 } 75 49 … … 189 163 190 164 #define toCString( ... ) toString( __VA_ARGS__ ).c_str() 191 192 // replace element of list with all elements of another list193 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 element206 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 }211 165 212 166 template< typename... Args > … … 236 190 } 237 191 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 amount250 template< class InputIt, class Distance >251 InputIt operator+( InputIt it, Distance n ) {252 advance(it, n);253 return it;254 }255 256 template< typename T >257 void warn_single( const T & arg ) {258 std::cerr << arg << std::endl;259 }260 261 template< typename T, typename... Params >262 void warn_single(const T & arg, const Params & ... params ) {263 std::cerr << arg;264 warn_single( params... );265 }266 267 192 template< typename... Params > 268 193 void warn( const Params & ... params ) { 269 194 std::cerr << "Warning: "; 270 warn_single( params... ); 195 toString_single( std::cerr, params... ); 196 std::cerr << std::endl; 271 197 } 272 198 … … 274 200 static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int start = 0 ) { 275 201 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 } 302 204 303 205 // ----------------------------------------------------------------------------- … … 356 258 ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } } 357 259 }; 358 359 // -----------------------------------------------------------------------------360 // Helper struct and function to support361 // for ( val : reverseIterate( container ) ) {}362 // syntax to have a for each that iterates backwards363 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 can470 // 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 support535 // for ( val : lazy_map( container1, f ) ) {}536 // syntax to have a for each that iterates a container, mapping each element by applying f537 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 }564 260 565 261 // ----------------------------------------------------------------------------- … … 583 279 } // ilog2 584 280 585 // -----------------------------------------------------------------------------586 /// evaluates expr as a long long int. If second is false, expr could not be evaluated587 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 the597 /// 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 position607 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 position611 ++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::less624 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 629 281 // Local Variables: // 630 282 // tab-width: 4 // -
src/GenPoly/Box.cc
r1180175 r640b3df 80 80 CallAdapter(); 81 81 82 void premutate( Declaration * declaration ); 82 83 void premutate( FunctionDecl * functionDecl ); 83 84 void premutate( TypeDecl * typeDecl ); … … 454 455 455 456 CallAdapter::CallAdapter() : tempNamer( "_temp" ) {} 457 458 void CallAdapter::premutate( Declaration * ) { 459 // Prevent type declaration information from leaking out. 460 GuardScope( scopeTyVars ); 461 } 456 462 457 463 void CallAdapter::premutate( FunctionDecl *functionDecl ) { -
src/GenPoly/FindFunction.cc
r1180175 r640b3df 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Rob Schluntz12 // Last Modified On : Fri Feb 05 12:22:20 201613 // Update Count : 611 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Oct 7 17:05:20 2022 13 // Update Count : 7 14 14 // 15 15 … … 18 18 #include <utility> // for pair 19 19 20 #include "AST/Pass.hpp" // for Pass 21 #include "AST/Type.hpp" 20 22 #include "Common/PassVisitor.h" // for PassVisitor 21 23 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::iterator … … 89 91 handleForall( pointerType->get_forall() ); 90 92 } 93 94 namespace { 95 96 struct 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 ); 108 private: 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 117 FindFunctionCore::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 124 void 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 133 void 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 142 ast::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 154 void FindFunctionCore::previsit( ast::PointerType const * /*type*/ ) { 155 GuardScope( typeVars ); 156 //handleForall( type->forall ); 157 } 158 159 } // namespace 160 161 void 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 172 const 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 91 183 } // namespace GenPoly 92 184 -
src/GenPoly/FindFunction.h
r1180175 r640b3df 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:23:36 201713 // Update Count : 211 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Oct 7 10:30:00 2022 13 // Update Count : 3 14 14 // 15 15 … … 30 30 /// like `findFunction`, but also replaces the function type with void ()(void) 31 31 void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ); 32 33 typedef bool (*FindFunctionPred)( const ast::FunctionType *, const TypeVarMap & ); 34 35 /// Recursively walks `type`, placing all functions that match `predicate` 36 /// under `typeVars` into `functions`. 37 void 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)`. 41 const ast::Type * findAndReplaceFunction( const ast::Type * type, 42 std::vector<ast::ptr<ast::FunctionType>> & functions, 43 const TypeVarMap & typeVars, FindFunctionPred predicate ); 44 32 45 } // namespace GenPoly 33 46 -
src/GenPoly/GenPoly.cc
r1180175 r640b3df 275 275 } 276 276 277 const 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 277 285 bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) { 278 286 // if ( ! adaptee->get_returnVals().empty() && isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) { … … 319 327 return 0; 320 328 } 329 330 const 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 } 321 340 322 341 Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) { … … 796 815 } 797 816 817 void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) { 818 typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) ); 819 } 820 798 821 void 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 ) ); 800 823 } 801 824 … … 822 845 } 823 846 847 void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ) { 848 for ( auto & typeDecl : decl->type_params ) { 849 addToTypeVarMap( typeDecl, typeVars ); 850 } 851 } 852 824 853 void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) { 825 854 for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) { -
src/GenPoly/GenPoly.h
r1180175 r640b3df 111 111 void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ); 112 112 void addToTypeVarMap( const ast::TypeDecl * type, TypeVarMap & typeVars ); 113 void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ); 113 114 114 115 /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap` 115 116 void makeTyVarMap( Type *type, TyVarMap &tyVarMap ); 116 117 void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars ); 118 void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ); 117 119 118 120 /// Prints type variable map -
src/Parser/DeclarationNode.cc
r1180175 r640b3df 10 10 // Created On : Sat May 16 12:34:05 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Aug 8 17:07:00 202213 // Update Count : 1 18512 // Last Modified On : Thu Feb 16 14:12:03 2023 13 // Update Count : 1388 14 14 // 15 15 … … 61 61 variable.initializer = nullptr; 62 62 63 // attr.name = nullptr;64 attr.expr = nullptr;65 attr.type = nullptr;66 67 63 assert.condition = nullptr; 68 64 assert.message = nullptr; … … 70 66 71 67 DeclarationNode::~DeclarationNode() { 72 // delete attr.name;73 delete attr.expr;74 delete attr.type;75 76 68 // delete variable.name; 77 69 delete variable.assertions; … … 115 107 newnode->variable.initializer = maybeClone( variable.initializer ); 116 108 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 121 109 newnode->assert.condition = maybeClone( assert.condition ); 122 110 newnode->assert.message = maybeClone( assert.message ); … … 154 142 } // if 155 143 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 159 150 160 151 os << endl; … … 244 235 newnode->type = new TypeData( TypeData::Aggregate ); 245 236 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; 247 239 newnode->type->aggregate.actuals = actuals; 248 240 newnode->type->aggregate.fields = fields; … … 250 242 newnode->type->aggregate.tagged = false; 251 243 newnode->type->aggregate.parent = nullptr; 252 newnode->type->aggregate.anon = name == nullptr;253 244 return newnode; 254 245 } // DeclarationNode::newAggregate … … 257 248 DeclarationNode * newnode = new DeclarationNode; 258 249 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; 260 252 newnode->type->enumeration.constants = constants; 261 253 newnode->type->enumeration.body = body; 262 newnode->type->enumeration.anon = name == nullptr;263 254 newnode->type->enumeration.typed = typed; 264 255 newnode->type->enumeration.hiding = hiding; … … 989 980 for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ) ) { 990 981 try { 991 bool extracted = false; 992 bool anon = false; 982 bool extracted = false, anon = false; 983 AggregateDecl * unionDecl = nullptr; 984 993 985 if ( DeclarationNode * extr = cur->extractAggregate() ) { 994 986 // handle the case where a structure declaration is contained within an object or type declaration 987 995 988 Declaration * decl = extr->build(); 996 989 if ( decl ) { 997 // hoist the structure declaration 990 // Remember the declaration if it is a union aggregate ? 991 unionDecl = dynamic_cast<UnionDecl *>( decl ); 992 998 993 decl->location = cur->location; 999 * 994 *out++ = decl; 1000 995 1001 996 // need to remember the cases where a declaration contains an anonymous aggregate definition … … 1003 998 assert( extr->type ); 1004 999 if ( extr->type->kind == TypeData::Aggregate ) { 1000 // typedef struct { int A } B is the only case? 1005 1001 anon = extr->type->aggregate.anon; 1006 1002 } 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? 1008 1004 anon = extr->type->enumeration.anon; 1009 1005 } … … 1014 1010 Declaration * decl = cur->build(); 1015 1011 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 1016 1041 // don't include anonymous declaration for named aggregates, but do include them for anonymous aggregates, e.g.: 1017 1042 // struct S { … … 1176 1201 assert( type ); 1177 1202 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 } // if1183 1184 1203 switch ( type->kind ) { 1185 1204 case TypeData::Enum: -
src/Parser/ExpressionNode.cc
r1180175 r640b3df 10 10 // Created On : Sat May 16 13:17:07 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Aug 7 09:18:56 202113 // Update Count : 107 712 // Last Modified On : Sat Feb 11 14:49:00 2023 13 // Update Count : 1079 14 14 // 15 15 … … 173 173 if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; } 174 174 175 posn = str.rfind( "hh" ); // char175 posn = str.rfind( "hh" ); // signed char 176 176 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; } 177 177 178 posn = str.rfind( "HH" ); // char178 posn = str.rfind( "HH" ); // signed char 179 179 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; } 180 180 … … 592 592 Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) { 593 593 list< Expression * > args; 594 args.push_back( 594 args.push_back( maybeMoveBuild< Expression >(expr_node) ); // xxx -- this is exactly the same as the val case now, refactor this code. 595 595 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); 596 596 } // build_unary_ptr -
src/Parser/ParseNode.h
r1180175 r640b3df 10 10 // Created On : Sat May 16 13:28:16 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Nov 2 21:27:07 202213 // Update Count : 9 3912 // Last Modified On : Sun Feb 19 09:02:37 2023 13 // Update Count : 940 14 14 // 15 15 … … 27 27 #include "Common/SemanticError.h" // for SemanticError 28 28 #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 30 31 #include "SynTree/LinkageSpec.h" // for Spec 31 32 #include "SynTree/Declaration.h" // for Aggregate … … 324 325 Variable_t variable; 325 326 326 struct Attr_t {327 // const std::string * name;328 ExpressionNode * expr;329 DeclarationNode * type;330 };331 Attr_t attr;332 333 327 struct StaticAssert_t { 334 328 ExpressionNode * condition; … … 342 336 343 337 bool inLine = false; 344 bool enumInLine = false; 338 bool enumInLine = false; 345 339 Type::FuncSpecifiers funcSpecs; 346 340 Type::StorageClasses storageClasses; -
src/Parser/RunParser.cpp
r1180175 r640b3df 10 10 // Created On : Mon Dec 19 11:00:00 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Dec 22 10:18:00 202213 // Update Count : 112 // Last Modified On : Thr Feb 16 10:08:00 2023 13 // Update Count : 2 14 14 // 15 15 … … 24 24 25 25 // Variables global to the parsing code. 26 LinkageSpec::Spec linkage = LinkageSpec::Cforall;26 ast::Linkage::Spec linkage = ast::Linkage::Cforall; 27 27 TypedefTable typedefTable; 28 28 DeclarationNode * parseTree = nullptr; 29 29 30 void parse( FILE * input, LinkageSpec::Spec linkage, bool alwaysExit ) {30 void parse( FILE * input, ast::Linkage::Spec linkage, bool alwaysExit ) { 31 31 extern int yyparse( void ); 32 32 extern FILE * yyin; -
src/Parser/RunParser.hpp
r1180175 r640b3df 10 10 // Created On : Mon Dec 19 10:42:00 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Dec 22 10:23:00 202213 // Update Count : 112 // Last Modified On : Thr Feb 16 10:08:00 2023 13 // Update Count : 2 14 14 // 15 15 … … 18 18 #include <iosfwd> // for ostream 19 19 20 #include " SynTree/LinkageSpec.h"// for Spec20 #include "AST/LinkageSpec.hpp" // for Spec 21 21 namespace ast { 22 22 class TranslationUnit; … … 29 29 /// The input file is closed when complete. Exits instead of returning on 30 30 /// error or if alwaysExit is true. 31 void parse( FILE * input, LinkageSpec::Spec linkage, bool alwaysExit = false );31 void parse( FILE * input, ast::Linkage::Spec linkage, bool alwaysExit = false ); 32 32 33 33 /// Drain the internal accumulator of parsed code and build a translation -
src/Parser/TypeData.cc
r1180175 r640b3df 10 10 // Created On : Sat May 16 15:12:51 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue May 10 22:36:52 202213 // Update Count : 67 712 // Last Modified On : Sun Feb 19 11:00:46 2023 13 // Update Count : 679 14 14 // 15 15 … … 375 375 break; 376 376 case Enum: 377 os << "enumeration " ;377 os << "enumeration " << *enumeration.name << endl;; 378 378 if ( enumeration.constants ) { 379 379 os << "with constants" << endl; -
src/Parser/TypeData.h
r1180175 r640b3df 10 10 // Created On : Sat May 16 15:18:36 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue May 10 22:18:49 202213 // Update Count : 20 312 // Last Modified On : Sun Feb 19 09:09:39 2023 13 // Update Count : 204 14 14 // 15 15 … … 37 37 bool body; 38 38 bool anon; 39 40 39 bool tagged; 41 40 const std::string * parent = nullptr; -
src/Parser/parser.yy
r1180175 r640b3df 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 2 21:36:16 202313 // Update Count : 58 6512 // Last Modified On : Mon Feb 20 11:31:26 2023 13 // Update Count : 5896 14 14 // 15 15 … … 55 55 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... 56 56 57 #include "SynTree/Attribute.h" 57 #include "SynTree/Attribute.h" // for Attribute 58 58 59 59 // lex uses __null in a boolean context, it's fine. … … 1951 1951 { 1952 1952 typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "6" ); 1953 $$ = $4->add Type( $3 )->addQualifiers( $1)->addTypedef();1953 $$ = $4->addQualifiers( $1 )->addType( $3 )->addTypedef(); 1954 1954 } 1955 1955 | type_specifier TYPEDEF declarator … … 1961 1961 { 1962 1962 typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "8" ); 1963 $$ = $4->addQualifiers( $1 )->addType def()->addType( $1);1963 $$ = $4->addQualifiers( $1 )->addType( $1 )->addTypedef(); 1964 1964 } 1965 1965 ; … … 1983 1983 | typedef_expression // deprecated GCC, naming expression type 1984 1984 | 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 } 1985 1991 ; 1986 1992 -
src/Parser/parserutility.h
r1180175 r640b3df 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // parserutility.h -- 7 // parserutility.h -- Collected utilities for the parser. 8 8 // 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 15:31:46 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:32:58 201713 // Update Count : 411 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Feb 16 12:34:00 2023 13 // Update Count : 5 14 14 // 15 15 … … 20 20 Expression *notZeroExpr( Expression *orig ); 21 21 22 template< typename T, typename U > 23 struct 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 33 template< typename T, typename U > 34 static inline T * maybeBuild( const U *orig ) { 35 return maybeBuild_t<T,U>::doit(orig); 36 } 37 38 template< typename T, typename U > 39 static inline T * maybeMoveBuild( const U *orig ) { 40 T* ret = maybeBuild<T>(orig); 41 delete orig; 42 return ret; 43 } 44 22 45 // Local Variables: // 23 46 // tab-width: 4 // -
src/ResolvExpr/CurrentObject.cc
r1180175 r640b3df 26 26 #include "AST/Init.hpp" // for Designation 27 27 #include "AST/Node.hpp" // for readonly 28 #include "AST/Print.hpp" 28 #include "AST/Print.hpp" // for readonly 29 29 #include "AST/Type.hpp" 30 #include "Common/Eval.h" // for eval 30 31 #include "Common/Indenter.h" // for Indenter, operator<< 31 32 #include "Common/SemanticError.h" // for SemanticError -
src/ResolvExpr/ResolveAssertions.cc
r1180175 r640b3df 30 30 #include "Common/FilterCombos.h" // for filterCombos 31 31 #include "Common/Indenter.h" // for Indenter 32 #include "Common/utility.h" // for sort_mins33 32 #include "GenPoly/GenPoly.h" // for getFunctionType 34 33 #include "ResolvExpr/AlternativeFinder.h" // for computeConversionCost -
src/ResolvExpr/Resolver.cc
r1180175 r640b3df 38 38 #include "AST/SymbolTable.hpp" 39 39 #include "AST/Type.hpp" 40 #include "Common/Eval.h" // for eval 40 41 #include "Common/PassVisitor.h" // for PassVisitor 41 42 #include "Common/SemanticError.h" // for SemanticError -
src/ResolvExpr/Resolver.h
r1180175 r640b3df 34 34 class Decl; 35 35 class DeletedExpr; 36 class Expr; 36 37 class Init; 37 38 class StmtExpr; -
src/SynTree/AggregateDecl.cc
r1180175 r640b3df 19 19 20 20 #include "Attribute.h" // for Attribute 21 #include "Common/Eval.h" // for eval 21 22 #include "Common/utility.h" // for printAll, cloneAll, deleteAll 22 23 #include "Declaration.h" // for AggregateDecl, TypeDecl, Declaration -
src/SynTree/Type.h
r1180175 r640b3df 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Wed Jul 14 15:40:00 202113 // Update Count : 17 111 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Feb 19 22:37:10 2023 13 // Update Count : 176 14 14 // 15 15 … … 23 23 24 24 #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 26 27 #include "Mutator.h" // for Mutator 27 28 #include "SynTree.h" // for AST nodes … … 124 125 bool operator!=( Qualifiers other ) const { return (val & Mask) != (other.val & Mask); } 125 126 bool operator<=( Qualifiers other ) const { 126 return is_const <= other.is_const // Any non-const converts to const without cost127 && is_volatile <= other.is_volatile //Any non-volatile converts to volatile without cost128 && is_mutex >= other.is_mutex //Any mutex converts to non-mutex without cost129 && is_atomic == other.is_atomic; //No conversion from atomic to non atomic is free127 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 130 131 } 131 132 bool operator<( Qualifiers other ) const { return *this != other && *this <= other; } … … 189 190 virtual TypeSubstitution genericSubstitution() const; 190 191 191 virtual Type * clone() const = 0;192 virtual Type * clone() const = 0; 192 193 virtual void accept( Visitor & v ) = 0; 193 194 virtual void accept( Visitor & v ) const = 0; 194 virtual Type * acceptMutator( Mutator & m ) = 0;195 virtual Type * acceptMutator( Mutator & m ) = 0; 195 196 virtual void print( std::ostream & os, Indenter indent = {} ) const; 196 197 }; … … 207 208 virtual bool isComplete() const override { return false; } 208 209 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 ); } 213 214 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 214 215 }; … … 259 260 // GENERATED END 260 261 261 static const char * typeNames[];// string names for basic types, MUST MATCH with Kind262 static const char * typeNames[]; // string names for basic types, MUST MATCH with Kind 262 263 263 264 BasicType( const Type::Qualifiers & tq, Kind bt, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); … … 266 267 void set_kind( Kind newValue ) { kind = newValue; } 267 268 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 ); } 272 273 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 273 274 bool isInteger() const; … … 279 280 280 281 // In C99, pointer types can be qualified in many ways e.g., int f( int a[ static 3 ] ) 281 Expression * dimension;282 Expression * dimension; 282 283 bool isVarLen; 283 284 bool isStatic; 284 285 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 * >() ); 287 288 PointerType( const PointerType& ); 288 289 virtual ~PointerType(); 289 290 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; } 294 295 bool get_isVarLen() { return isVarLen; } 295 296 void set_isVarLen( bool newValue ) { isVarLen = newValue; } … … 301 302 virtual bool isComplete() const override { return ! isVarLen; } 302 303 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 ); } 307 308 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 308 309 }; … … 310 311 class ArrayType : public Type { 311 312 public: 312 Type * base;313 Expression * dimension;313 Type * base; 314 Expression * dimension; 314 315 bool isVarLen; 315 316 bool isStatic; 316 317 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 * >() ); 318 319 ArrayType( const ArrayType& ); 319 320 virtual ~ArrayType(); 320 321 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; } 325 326 bool get_isVarLen() { return isVarLen; } 326 327 void set_isVarLen( bool newValue ) { isVarLen = newValue; } … … 333 334 virtual bool isComplete() const override { return dimension || isVarLen; } 334 335 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 ); } 339 340 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 340 341 }; … … 348 349 virtual ~QualifiedType(); 349 350 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 ); } 354 355 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 355 356 }; … … 357 358 class ReferenceType : public Type { 358 359 public: 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 * >() ); 362 363 ReferenceType( const ReferenceType & ); 363 364 virtual ~ReferenceType(); 364 365 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; } 367 368 368 369 virtual int referenceDepth() const override; … … 375 376 virtual TypeSubstitution genericSubstitution() const override; 376 377 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 ); } 381 382 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 382 383 }; … … 405 406 bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; } 406 407 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 ); } 411 412 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 412 413 }; … … 414 415 class ReferenceToType : public Type { 415 416 public: 416 std::list< Expression * > parameters;417 std::list< Expression * > parameters; 417 418 std::string name; 418 419 bool hoistType; … … 428 429 void set_hoistType( bool newValue ) { hoistType = newValue; } 429 430 430 virtual ReferenceToType * clone() const override = 0;431 virtual ReferenceToType * clone() const override = 0; 431 432 virtual void accept( Visitor & v ) override = 0; 432 virtual Type * acceptMutator( Mutator & m ) override = 0;433 virtual Type * acceptMutator( Mutator & m ) override = 0; 433 434 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 434 435 … … 443 444 // this decl is not "owned" by the struct inst; it is merely a pointer to elsewhere in the tree, 444 445 // where the structure used in this type is actually defined 445 StructDecl * baseStruct;446 StructDecl * baseStruct; 446 447 447 448 StructInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ), baseStruct( 0 ) {} … … 449 450 StructInstType( const StructInstType & other ) : Parent( other ), baseStruct( other.baseStruct ) {} 450 451 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; } 453 454 454 455 /// Accesses generic parameters of base struct (NULL if none such) … … 466 467 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; 467 468 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 ); } 472 473 473 474 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 481 482 // this decl is not "owned" by the union inst; it is merely a pointer to elsewhere in the tree, 482 483 // where the union used in this type is actually defined 483 UnionDecl * baseUnion;484 UnionDecl * baseUnion; 484 485 485 486 UnionInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ), baseUnion( 0 ) {} … … 487 488 UnionInstType( const UnionInstType & other ) : Parent( other ), baseUnion( other.baseUnion ) {} 488 489 489 UnionDecl * get_baseUnion() const { return baseUnion; }490 UnionDecl * get_baseUnion() const { return baseUnion; } 490 491 void set_baseUnion( UnionDecl * newValue ) { baseUnion = newValue; } 491 492 … … 504 505 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; 505 506 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 ); } 510 511 511 512 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 519 520 // this decl is not "owned" by the enum inst; it is merely a pointer to elsewhere in the tree, 520 521 // where the enum used in this type is actually defined 521 EnumDecl * baseEnum = nullptr;522 EnumDecl * baseEnum = nullptr; 522 523 523 524 EnumInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ) {} … … 525 526 EnumInstType( const EnumInstType & other ) : Parent( other ), baseEnum( other.baseEnum ) {} 526 527 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; } 529 530 530 531 virtual bool isComplete() const override; … … 532 533 virtual AggregateDecl * getAggr() const override; 533 534 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 ); } 538 539 539 540 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 556 557 virtual bool isComplete() const override; 557 558 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 ); } 562 563 private: 563 564 virtual std::string typeString() const override; … … 569 570 // this decl is not "owned" by the type inst; it is merely a pointer to elsewhere in the tree, 570 571 // where the type used here is actually defined 571 TypeDecl * baseType;572 TypeDecl * baseType; 572 573 bool isFtype; 573 574 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 * >() ); 575 576 TypeInstType( const Type::Qualifiers & tq, const std::string & name, bool isFtype, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 576 577 TypeInstType( const TypeInstType & other ); 577 578 ~TypeInstType(); 578 579 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 ); 581 582 bool get_isFtype() const { return isFtype; } 582 583 void set_isFtype( bool newValue ) { isFtype = newValue; } … … 584 585 virtual bool isComplete() const override; 585 586 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 ); } 590 591 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 591 592 private: … … 622 623 // virtual bool isComplete() const override { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness 623 624 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 ); } 628 629 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 629 630 }; … … 631 632 class TypeofType : public Type { 632 633 public: 633 Expression * expr;///< expression to take the type of634 bool is_basetypeof; 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, 638 639 const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 639 640 TypeofType( const TypeofType& ); 640 641 virtual ~TypeofType(); 641 642 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; } 644 645 645 646 virtual bool isComplete() const override { assert( false ); return false; } 646 647 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 ); } 651 652 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 652 653 }; … … 654 655 class VTableType : public Type { 655 656 public: 656 Type * base;657 658 VTableType( const Type::Qualifiers & tq, Type * base,657 Type * base; 658 659 VTableType( const Type::Qualifiers & tq, Type * base, 659 660 const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 660 661 VTableType( const VTableType & ); 661 662 virtual ~VTableType(); 662 663 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 ); } 670 671 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 671 672 }; … … 674 675 public: 675 676 std::string name; 676 Expression * expr;677 Type * type;677 Expression * expr; 678 Type * type; 678 679 bool isType; 679 680 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 * >() ); 682 683 AttrType( const AttrType& ); 683 684 virtual ~AttrType(); … … 685 686 const std::string & get_name() const { return name; } 686 687 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; } 691 692 bool get_isType() const { return isType; } 692 693 void set_isType( bool newValue ) { isType = newValue; } … … 694 695 virtual bool isComplete() const override { assert( false ); } // xxx - not sure what to do here 695 696 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 ); } 700 701 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 701 702 }; … … 709 710 virtual bool isComplete() const override{ return true; } // xxx - is this right? 710 711 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 ); } 715 716 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 716 717 }; … … 722 723 ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 723 724 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 ); } 728 729 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 729 730 }; … … 735 736 OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 736 737 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 ); } 741 742 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 742 743 }; … … 746 747 GlobalScopeType(); 747 748 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 ); } 752 753 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 753 754 }; -
src/Validate/HandleAttributes.cc
r1180175 r640b3df 17 17 18 18 #include "CompilationState.h" 19 #include "Common/Eval.h" 19 20 #include "Common/PassVisitor.h" 20 21 #include "Common/SemanticError.h" -
src/main.cc
r1180175 r640b3df 10 10 // Created On : Fri May 15 23:12:02 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Oct 5 12:06:00 202213 // Update Count : 6 7912 // Last Modified On : Thr Feb 16 10:08:00 2023 13 // Update Count : 680 14 14 // 15 15 … … 40 40 #include "CodeTools/TrackLoc.h" // for fillLocations 41 41 #include "Common/CodeLocationTools.hpp" // for forceFillCodeLocations 42 #include "Common/CompilerError.h" // for CompilerError43 42 #include "Common/DeclStats.hpp" // for printDeclStats 44 43 #include "Common/ResolvProtoDump.hpp" // for dumpAsResolverProto 45 44 #include "Common/Stats.h" // for Stats 46 #include "Common/UnimplementedError.h" // for UnimplementedError47 45 #include "Common/utility.h" // for deleteAll, filter, printAll 48 46 #include "Concurrency/Actors.hpp" // for implementActors … … 274 272 FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" ); 275 273 assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" ); 276 parse( gcc_builtins, LinkageSpec::Compiler );274 parse( gcc_builtins, ast::Linkage::Compiler ); 277 275 278 276 // read the extra prelude in, if not generating the cfa library 279 277 FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" ); 280 278 assertf( extras, "cannot open extras.cf\n" ); 281 parse( extras, LinkageSpec::BuiltinC );279 parse( extras, ast::Linkage::BuiltinC ); 282 280 283 281 if ( ! libcfap ) { … … 285 283 FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" ); 286 284 assertf( prelude, "cannot open prelude.cfa\n" ); 287 parse( prelude, LinkageSpec::Intrinsic );285 parse( prelude, ast::Linkage::Intrinsic ); 288 286 289 287 // Read to cfa builtins, if not generating the cfa library 290 288 FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" ); 291 289 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 ); 297 295 298 296 transUnit = buildUnit(); … … 342 340 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) ); 343 341 344 PASS( "Implement Actors", Concurrency::implementActors( transUnit ) ); 345 342 PASS( "Implement Actors", Concurrency::implementActors( transUnit ) ); 346 343 PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) ); 347 344 PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) ); … … 476 473 } // if 477 474 e.print(); 478 if ( output != &cout ) {479 delete output;480 } // if481 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 } // if487 return EXIT_FAILURE;488 } catch ( CompilerError & e ) {489 cerr << "Compiler Error: " << e.get_what() << endl;490 cerr << "(please report bugs to [REDACTED])" << endl;491 475 if ( output != &cout ) { 492 476 delete output;
Note:
See TracChangeset
for help on using the changeset viewer.