- Timestamp:
- Apr 21, 2023, 5:36:12 PM (2 years ago)
- Branches:
- ADT, master
- Children:
- 28f8f15, 6e4c44d
- Parents:
- 2ed94a9 (diff), 699a97d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src
- Files:
-
- 11 added
- 3 deleted
- 92 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Attribute.hpp
r2ed94a9 rb110bcc 27 27 class Expr; 28 28 29 /// An entry in an attribute list: `__attribute__(( ... ))` 29 30 class Attribute final : public Node { 30 31 public: -
src/AST/Convert.cpp
r2ed94a9 rb110bcc 559 559 auto stmt = new SuspendStmt(); 560 560 stmt->then = get<CompoundStmt>().accept1( node->then ); 561 switch (node->type) {561 switch (node->kind) { 562 562 case ast::SuspendStmt::None : stmt->type = SuspendStmt::None ; break; 563 563 case ast::SuspendStmt::Coroutine: stmt->type = SuspendStmt::Coroutine; break; … … 1683 1683 GET_ACCEPT_V(attributes, Attribute), 1684 1684 { old->get_funcSpec().val }, 1685 old->type->isVarArgs1685 (old->type->isVarArgs) ? ast::VariableArgs : ast::FixedArgs 1686 1686 }; 1687 1687 … … 1989 1989 GET_ACCEPT_1(else_, Stmt), 1990 1990 GET_ACCEPT_V(initialization, Stmt), 1991 old->isDoWhile,1991 (old->isDoWhile) ? ast::DoWhile : ast::While, 1992 1992 GET_LABELS_V(old->labels) 1993 1993 ); … … 2131 2131 virtual void visit( const SuspendStmt * old ) override final { 2132 2132 if ( inCache( old ) ) return; 2133 ast::SuspendStmt:: Typetype;2133 ast::SuspendStmt::Kind type; 2134 2134 switch (old->type) { 2135 2135 case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break; -
src/AST/Create.cpp
r2ed94a9 rb110bcc 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
r2ed94a9 rb110bcc 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 … … 57 57 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 58 58 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage, 59 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)59 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs ) 60 60 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), 61 61 type_params(std::move(forall)), assertions(), 62 62 params(std::move(params)), returns(std::move(returns)), stmts( stmts ) { 63 FunctionType * ftype = new FunctionType( static_cast<ArgumentFlag>(isVarArgs));63 FunctionType * ftype = new FunctionType( isVarArgs ); 64 64 for (auto & param : this->params) { 65 65 ftype->params.emplace_back(param->get_type()); … … 81 81 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 82 82 CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage, 83 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)83 std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, ArgumentFlag isVarArgs ) 84 84 : DeclWithType( location, name, storage, linkage, std::move(attrs), fs ), 85 85 type_params( std::move( forall) ), assertions( std::move( assertions ) ), 86 86 params( std::move(params) ), returns( std::move(returns) ), 87 87 type( nullptr ), stmts( stmts ) { 88 FunctionType * type = new FunctionType( (isVarArgs) ? VariableArgs : FixedArgs );88 FunctionType * type = new FunctionType( isVarArgs ); 89 89 for ( auto & param : this->params ) { 90 90 type->params.emplace_back( param->get_type() ); -
src/AST/Decl.hpp
r2ed94a9 rb110bcc 10 10 // Created On : Thu May 9 10:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Nov 24 9:44:00 202213 // Update Count : 3 412 // Last Modified On : Wed Apr 5 10:42:00 2023 13 // Update Count : 35 14 14 // 15 15 … … 122 122 }; 123 123 124 /// Function variable arguments flag 125 enum ArgumentFlag { FixedArgs, VariableArgs }; 126 124 127 /// Object declaration `int foo()` 125 128 class FunctionDecl : public DeclWithType { … … 144 147 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 145 148 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall, 146 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);149 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs ); 147 150 148 151 FunctionDecl( const CodeLocation & location, const std::string & name, … … 150 153 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns, 151 154 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall, 152 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);155 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs ); 153 156 154 157 const Type * get_type() const override; … … 313 316 public: 314 317 bool isTyped; // isTyped indicated if the enum has a declaration like: 315 // enum (type_optional) Name {...} 318 // enum (type_optional) Name {...} 316 319 ptr<Type> base; // if isTyped == true && base.get() == nullptr, it is a "void" type enum 317 320 enum class EnumHiding { Visible, Hide } hide; … … 371 374 }; 372 375 376 /// Assembly declaration: `asm ... ( "..." : ... )` 373 377 class AsmDecl : public Decl { 374 378 public: -
src/AST/Expr.hpp
r2ed94a9 rb110bcc 254 254 }; 255 255 256 /// A name qualified by a namespace or type. 256 257 class QualifiedNameExpr final : public Expr { 257 258 public: … … 259 260 std::string name; 260 261 261 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 262 QualifiedNameExpr( const CodeLocation & loc, const Decl * d, const std::string & n ) 262 263 : Expr( loc ), type_decl( d ), name( n ) {} 263 264 … … 621 622 }; 622 623 624 /// A name that refers to a generic dimension parameter. 623 625 class DimensionExpr final : public Expr { 624 626 public: … … 910 912 }; 911 913 912 913 914 } 914 915 -
src/AST/Fwd.hpp
r2ed94a9 rb110bcc 15 15 16 16 #pragma once 17 18 template<typename> struct bitfield; 17 19 18 20 #include "AST/Node.hpp" … … 147 149 class TranslationGlobal; 148 150 151 // For the following types, only use the using type. 152 namespace CV { 153 struct qualifier_flags; 154 using Qualifiers = bitfield<qualifier_flags>; 149 155 } 156 namespace Function { 157 struct spec_flags; 158 using Specs = bitfield<spec_flags>; 159 } 160 namespace Storage { 161 struct class_flags; 162 using Classes = bitfield<class_flags>; 163 } 164 namespace Linkage { 165 struct spec_flags; 166 using Spec = bitfield<spec_flags>; 167 } 168 169 } -
src/AST/Init.hpp
r2ed94a9 rb110bcc 117 117 ptr<Init> init; 118 118 119 ConstructorInit( 119 ConstructorInit( 120 120 const CodeLocation & loc, const Stmt * ctor, const Stmt * dtor, const Init * init ) 121 121 : Init( loc, MaybeConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {} -
src/AST/Inspect.cpp
r2ed94a9 rb110bcc 10 10 // Created On : Fri Jun 24 13:16:31 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Oct 3 11:04:00 202213 // Update Count : 312 // Last Modified On : Fri Apr 14 15:09:00 2023 13 // Update Count : 4 14 14 // 15 15 … … 168 168 } 169 169 170 bool isUnnamedBitfield( const ast::ObjectDecl * obj ) { 171 return obj && obj->name.empty() && obj->bitfieldWidth; 172 } 173 170 174 } // namespace ast -
src/AST/Inspect.hpp
r2ed94a9 rb110bcc 10 10 // Created On : Fri Jun 24 13:16:31 2022 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Sep 22 13:44:00 202213 // Update Count : 212 // Last Modified On : Fri Apr 14 15:09:00 2023 13 // Update Count : 3 14 14 // 15 15 … … 38 38 const ApplicationExpr * isIntrinsicCallExpr( const Expr * expr ); 39 39 40 /// Returns true if obj's name is the empty string and it has a bitfield width. 41 bool isUnnamedBitfield( const ObjectDecl * obj ); 42 40 43 } -
src/AST/ParseNode.hpp
r2ed94a9 rb110bcc 40 40 template<typename node_t> 41 41 friend node_t * mutate(const node_t * node); 42 template<typename node_t> 43 friend node_t * shallowCopy(const node_t * node); 42 44 }; 43 45 -
src/AST/Pass.impl.hpp
r2ed94a9 rb110bcc 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 ) \ … … 2041 2042 if ( __visit_children() ) { 2042 2043 maybe_accept( node, &TupleType::types ); 2043 maybe_accept( node, &TupleType::members );2044 2044 } 2045 2045 -
src/AST/Pass.proto.hpp
r2ed94a9 rb110bcc 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/Print.cpp
r2ed94a9 rb110bcc 29 29 namespace ast { 30 30 31 template <typename C, typename... T> 32 constexpr array<C,sizeof...(T)> make_array(T&&... values) 33 { 34 return array<C,sizeof...(T)>{ 35 std::forward<T>(values)... 36 }; 31 namespace { 32 33 template<typename C, typename... T> 34 constexpr array<C, sizeof...(T)> make_array( T&&... values ) { 35 return array<C, sizeof...(T)>{ std::forward<T>( values )... }; 36 } 37 38 namespace Names { 39 static constexpr auto FuncSpecifiers = make_array<const char*>( 40 "inline", "_Noreturn", "fortran" 41 ); 42 43 static constexpr auto StorageClasses = make_array<const char*>( 44 "extern", "static", "auto", "register", "__thread", "_Thread_local" 45 ); 46 47 static constexpr auto Qualifiers = make_array<const char*>( 48 "const", "restrict", "volatile", "mutex", "_Atomic" 49 ); 50 } 51 52 template<typename bits_t, size_t N> 53 void print( ostream & os, const bits_t & bits, 54 const array<const char *, N> & names ) { 55 if ( !bits.any() ) return; 56 for ( size_t i = 0 ; i < N ; i += 1 ) { 57 if ( bits[i] ) { 58 os << names[i] << ' '; 59 } 60 } 37 61 } 38 62 … … 80 104 static const char* Names[]; 81 105 82 struct Names {83 static constexpr auto FuncSpecifiers = make_array<const char*>(84 "inline", "_Noreturn", "fortran"85 );86 87 static constexpr auto StorageClasses = make_array<const char*>(88 "extern", "static", "auto", "register", "__thread", "_Thread_local"89 );90 91 static constexpr auto Qualifiers = make_array<const char*>(92 "const", "restrict", "volatile", "mutex", "_Atomic"93 );94 };95 96 template<typename storage_t, size_t N>97 void print(const storage_t & storage, const array<const char *, N> & Names ) {98 if ( storage.any() ) {99 for ( size_t i = 0; i < Names.size(); i += 1 ) {100 if ( storage[i] ) {101 os << Names[i] << ' ';102 }103 }104 }105 }106 107 void print( const ast::Function::Specs & specs ) {108 print(specs, Names::FuncSpecifiers);109 }110 111 void print( const ast::Storage::Classes & storage ) {112 print(storage, Names::StorageClasses);113 }114 115 void print( const ast::CV::Qualifiers & qualifiers ) {116 print(qualifiers, Names::Qualifiers);117 }118 119 106 void print( const std::vector<ast::Label> & labels ) { 120 107 if ( labels.empty() ) return; … … 230 217 } 231 218 232 print(node->storage );219 ast::print( os, node->storage ); 233 220 os << node->typeString(); 234 221 … … 272 259 273 260 void preprint( const ast::Type * node ) { 274 print(node->qualifiers );261 ast::print( os, node->qualifiers ); 275 262 } 276 263 … … 278 265 print( node->forall ); 279 266 print( node->assertions ); 280 print(node->qualifiers );267 ast::print( os, node->qualifiers ); 281 268 } 282 269 283 270 void preprint( const ast::BaseInstType * node ) { 284 271 print( node->attributes ); 285 print(node->qualifiers );272 ast::print( os, node->qualifiers ); 286 273 } 287 274 … … 294 281 } 295 282 296 print(node->storage );283 ast::print( os, node->storage ); 297 284 298 285 if ( node->type ) { … … 338 325 if ( ! short_mode ) printAll( node->attributes ); 339 326 340 print( node->storage ); 341 print( node->funcSpec ); 342 343 327 ast::print( os, node->storage ); 328 ast::print( os, node->funcSpec ); 344 329 345 330 if ( node->type && node->isTypeFixed ) { … … 384 369 --indent; 385 370 } 371 } 372 373 if ( ! node->withExprs.empty() ) { 374 // Not with a clause, but the 'with clause'. 375 ++indent; 376 os << " with clause" << endl << indent; 377 printAll( node->withExprs ); 378 --indent; 386 379 } 387 380 … … 746 739 virtual const ast::Stmt * visit( const ast::SuspendStmt * node ) override final { 747 740 os << "Suspend Statement"; 748 switch (node-> type) {749 750 751 741 switch (node->kind) { 742 case ast::SuspendStmt::None : os << " with implicit target"; break; 743 case ast::SuspendStmt::Generator: os << " for generator"; break; 744 case ast::SuspendStmt::Coroutine: os << " for coroutine"; break; 752 745 } 753 746 os << endl; … … 1627 1620 }; 1628 1621 1622 } // namespace 1623 1629 1624 void print( ostream & os, const ast::Node * node, Indenter indent ) { 1630 1625 Printer printer { os, indent, false }; … … 1637 1632 } 1638 1633 1639 // Annoyingly these needed to be defined out of line to avoid undefined references. 1640 // The size here needs to be explicit but at least the compiler will produce an error 1641 // if the wrong size is specified 1642 constexpr array<const char*, 3> Printer::Names::FuncSpecifiers; 1643 constexpr array<const char*, 6> Printer::Names::StorageClasses; 1644 constexpr array<const char*, 5> Printer::Names::Qualifiers; 1634 void print( ostream & os, Function::Specs specs ) { 1635 print( os, specs, Names::FuncSpecifiers ); 1645 1636 } 1637 1638 void print( ostream & os, Storage::Classes storage ) { 1639 print( os, storage, Names::StorageClasses ); 1640 } 1641 1642 void print( ostream & os, CV::Qualifiers qualifiers ) { 1643 print( os, qualifiers, Names::Qualifiers ); 1644 } 1645 1646 } // namespace ast -
src/AST/Print.hpp
r2ed94a9 rb110bcc 16 16 #pragma once 17 17 18 #include <iostream> 19 #include <utility> // for forward 18 #include <iosfwd> 20 19 21 #include "AST/ Node.hpp"20 #include "AST/Fwd.hpp" 22 21 #include "Common/Indenter.h" 23 22 24 23 namespace ast { 25 26 class Decl;27 24 28 25 /// Print a node with the given indenter … … 44 41 } 45 42 43 /// Print each cv-qualifier used in the set, followed by a space. 44 void print( std::ostream & os, CV::Qualifiers ); 45 /// Print each function specifier used in the set, followed by a space. 46 void print( std::ostream & os, Function::Specs ); 47 /// Print each storage class used in the set, followed by a space. 48 void print( std::ostream & os, Storage::Classes ); 49 46 50 } -
src/AST/Stmt.hpp
r2ed94a9 rb110bcc 10 10 // Created On : Wed May 8 13:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Apr 20 14:34:00 202213 // Update Count : 3 612 // Last Modified On : Wed Apr 5 10:34:00 2023 13 // Update Count : 37 14 14 // 15 15 … … 205 205 }; 206 206 207 // A while loop or a do-while loop: 208 enum WhileDoKind { While, DoWhile }; 209 207 210 // While loop: while (...) ... else ... or do ... while (...) else ...; 208 211 class WhileDoStmt final : public Stmt { … … 212 215 ptr<Stmt> else_; 213 216 std::vector<ptr<Stmt>> inits; 214 boolisDoWhile;217 WhileDoKind isDoWhile; 215 218 216 219 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, 217 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )220 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} ) 218 221 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {} 219 222 220 223 WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_, 221 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )224 const std::vector<ptr<Stmt>> && inits, WhileDoKind isDoWhile = While, const std::vector<Label> && labels = {} ) 222 225 : Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {} 223 226 … … 364 367 public: 365 368 ptr<CompoundStmt> then; 366 enum Type { None, Coroutine, Generator } type= None;367 368 SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, const std::vector<Label> && labels = {} )369 : Stmt(loc, std::move(labels)), then(then), type(type) {}369 enum Kind { None, Coroutine, Generator } kind = None; 370 371 SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Kind kind, const std::vector<Label> && labels = {} ) 372 : Stmt(loc, std::move(labels)), then(then), kind(kind) {} 370 373 371 374 const Stmt * accept( Visitor & v ) const override { return v.visit( this ); } … … 394 397 }; 395 398 399 // Clause in a waitfor statement: waitfor (..., ...) ... 396 400 class WaitForClause final : public StmtClause { 397 401 public: … … 454 458 MUTATE_FRIEND 455 459 }; 460 456 461 } // namespace ast 457 462 -
src/AST/SymbolTable.cpp
r2ed94a9 rb110bcc 70 70 if ( baseExpr ) { 71 71 if (baseExpr->env) { 72 Expr * base = shallowCopy(baseExpr);72 Expr * base = deepCopy(baseExpr); 73 73 const TypeSubstitution * subs = baseExpr->env; 74 74 base->env = nullptr; … … 260 260 void SymbolTable::addId( const DeclWithType * decl, const Expr * baseExpr ) { 261 261 // default handling of conflicts is to raise an error 262 addId ( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );262 addIdCommon( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr ); 263 263 } 264 264 265 265 void SymbolTable::addDeletedId( const DeclWithType * decl, const Decl * deleter ) { 266 266 // default handling of conflicts is to raise an error 267 addId ( decl, OnConflict::error(), nullptr, deleter );267 addIdCommon( decl, OnConflict::error(), nullptr, deleter ); 268 268 } 269 269 … … 677 677 } 678 678 679 void SymbolTable::addId (680 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr,681 const Decl * deleter ) {679 void SymbolTable::addIdCommon( 680 const DeclWithType * decl, SymbolTable::OnConflict handleConflicts, 681 const Expr * baseExpr, const Decl * deleter ) { 682 682 SpecialFunctionKind kind = getSpecialFunctionKind(decl->name); 683 683 if (kind == NUMBER_OF_KINDS) { // not a special decl 684 addId (decl, decl->name, idTable, handleConflicts, baseExpr, deleter);684 addIdToTable(decl, decl->name, idTable, handleConflicts, baseExpr, deleter); 685 685 } 686 686 else { … … 695 695 assertf(false, "special decl with non-function type"); 696 696 } 697 addId(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter); 698 } 699 } 700 701 void SymbolTable::addId( 702 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, const Expr * baseExpr, 703 const Decl * deleter ) { 697 addIdToTable(decl, key, specialFunctionTable[kind], handleConflicts, baseExpr, deleter); 698 } 699 } 700 701 void SymbolTable::addIdToTable( 702 const DeclWithType * decl, const std::string & lookupKey, 703 IdTable::Ptr & table, SymbolTable::OnConflict handleConflicts, 704 const Expr * baseExpr, const Decl * deleter ) { 704 705 ++*stats().add_calls; 705 706 const std::string &name = decl->name; … … 778 779 void SymbolTable::addMembers( 779 780 const AggregateDecl * aggr, const Expr * expr, SymbolTable::OnConflict handleConflicts ) { 780 for ( const Decl *decl : aggr->members ) {781 if ( auto dwt = dynamic_cast< const DeclWithType * >( decl ) ) {782 addId( dwt, handleConflicts, expr );783 if ( dwt->name == "" ) {784 const Type * t = dwt->get_type()->stripReferences();785 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) {786 if ( ! dynamic_cast<const StructInstType *>(rty)787 && ! dynamic_cast<const UnionInstType *>(rty) ) continue;788 ResolvExpr::Cost cost = ResolvExpr::Cost::zero;789 ast::ptr<ast::TypeSubstitution> tmp = expr->env;790 expr = mutate_field(expr, &Expr::env, nullptr);791 const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost );792 base = mutate_field(base, &Expr::env, tmp);793 794 addMembers(795 rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts ); 796 }797 }781 for ( const ptr<Decl> & decl : aggr->members ) { 782 auto dwt = decl.as<DeclWithType>(); 783 if ( nullptr == dwt ) continue; 784 addIdCommon( dwt, handleConflicts, expr ); 785 // Inline through unnamed struct/union members. 786 if ( "" != dwt->name ) continue; 787 const Type * t = dwt->get_type()->stripReferences(); 788 if ( auto rty = dynamic_cast<const BaseInstType *>( t ) ) { 789 if ( ! dynamic_cast<const StructInstType *>(rty) 790 && ! dynamic_cast<const UnionInstType *>(rty) ) continue; 791 ResolvExpr::Cost cost = ResolvExpr::Cost::zero; 792 ast::ptr<ast::TypeSubstitution> tmp = expr->env; 793 expr = mutate_field(expr, &Expr::env, nullptr); 794 const Expr * base = ResolvExpr::referenceToRvalueConversion( expr, cost ); 795 base = mutate_field(base, &Expr::env, tmp); 796 797 addMembers( 798 rty->aggr(), new MemberExpr{ base->location, dwt, base }, handleConflicts ); 798 799 } 799 800 } -
src/AST/SymbolTable.hpp
r2ed94a9 rb110bcc 192 192 193 193 /// common code for addId, addDeletedId, etc. 194 void addId (195 const DeclWithType * decl, OnConflict handleConflicts, const Expr * baseExpr = nullptr,196 const Decl * deleter = nullptr );194 void addIdCommon( 195 const DeclWithType * decl, OnConflict handleConflicts, 196 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr ); 197 197 198 198 /// common code for addId when special decls are placed into separate tables 199 void addId( 200 const DeclWithType * decl, const std::string & lookupKey, IdTable::Ptr & idTable, OnConflict handleConflicts, 199 void addIdToTable( 200 const DeclWithType * decl, const std::string & lookupKey, 201 IdTable::Ptr & idTable, OnConflict handleConflicts, 201 202 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr); 202 203 203 204 /// adds all of the members of the Aggregate (addWith helper) 204 205 void addMembers( const AggregateDecl * aggr, const Expr * expr, OnConflict handleConflicts ); -
src/AST/TranslationUnit.hpp
r2ed94a9 rb110bcc 10 10 // Created On : Tue Jun 11 15:30:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : T ue Mar 11 11:19:00 202213 // Update Count : 112 // Last Modified On : Thr Mar 9 16:41:00 2023 13 // Update Count : 2 14 14 // 15 15 … … 17 17 18 18 #include <map> 19 #include < vector>19 #include <list> 20 20 21 21 #include "Fwd.hpp" … … 28 28 29 29 ptr<Type> sizeType; 30 const FunctionDecl * dereference ;31 const StructDecl * dtorStruct ;32 const FunctionDecl * dtorDestroy ;30 const FunctionDecl * dereference = nullptr; 31 const StructDecl * dtorStruct = nullptr; 32 const FunctionDecl * dtorDestroy = nullptr; 33 33 }; 34 34 -
src/AST/Type.cpp
r2ed94a9 rb110bcc 10 10 // Created On : Mon May 13 15:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Nov 24 9:49:00 202213 // Update Count : 612 // Last Modified On : Thu Apr 6 15:59:00 2023 13 // Update Count : 7 14 14 // 15 15 … … 199 199 200 200 TupleType::TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q ) 201 : Type( q ), types( std::move(ts) ), members() { 202 // This constructor is awkward. `TupleType` needs to contain objects so that members can be 203 // named, but members without initializer nodes end up getting constructors, which breaks 204 // things. This happens because the object decls have to be visited so that their types are 205 // kept in sync with the types listed here. Ultimately, the types listed here should perhaps 206 // be eliminated and replaced with a list-view over members. The temporary solution is to 207 // make a `ListInit` with `maybeConstructed = false`, so when the object is visited it is not 208 // constructed. Potential better solutions include: 209 // a) Separate `TupleType` from its declarations, into `TupleDecl` and `Tuple{Inst?}Type`, 210 // similar to the aggregate types. 211 // b) Separate initializer nodes better, e.g. add a `MaybeConstructed` node that is replaced 212 // by `genInit`, rather than the current boolean flag. 213 members.reserve( types.size() ); 214 for ( const Type * ty : types ) { 215 members.emplace_back( new ObjectDecl{ 216 CodeLocation(), "", ty, new ListInit( CodeLocation(), {}, {}, NoConstruct ), 217 Storage::Classes{}, Linkage::Cforall } ); 218 } 219 } 201 : Type( q ), types( std::move(ts) ) {} 220 202 221 203 bool isUnboundType(const Type * type) { -
src/AST/Type.hpp
r2ed94a9 rb110bcc 10 10 // Created On : Thu May 9 10:00:00 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Nov 24 9:47:00 202213 // Update Count : 812 // Last Modified On : Thu Apr 6 15:58:00 2023 13 // Update Count : 9 14 14 // 15 15 … … 265 265 }; 266 266 267 /// Function variable arguments flag268 enum ArgumentFlag { FixedArgs, VariableArgs };269 270 267 /// Type of a function `[R1, R2](*)(P1, P2, P3)` 271 268 class FunctionType final : public Type { … … 460 457 public: 461 458 std::vector<ptr<Type>> types; 462 std::vector<ptr<Decl>> members;463 459 464 460 TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} ); -
src/AST/porting.md
r2ed94a9 rb110bcc 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/CodeGen/CodeGenerator.cc
r2ed94a9 rb110bcc 17 17 #include <cassert> // for assert, assertf 18 18 #include <list> // for _List_iterator, list, list<>::it... 19 #include <sstream> // for stringstream 19 20 20 21 #include "AST/Decl.hpp" // for DeclWithType 21 22 #include "Common/UniqueName.h" // for UniqueName 22 #include "Common/utility.h" // for CodeLocation, toString23 23 #include "GenType.h" // for genType 24 24 #include "InitTweak/InitTweak.h" // for getPointerBase -
src/Common/CodeLocationTools.cpp
r2ed94a9 rb110bcc 208 208 209 209 struct LeafKindVisitor : public ast::Visitor { 210 LeafKind kind;210 LeafKind result; 211 211 212 212 #define VISIT(node_type, return_type) \ 213 213 const ast::return_type * visit( const ast::node_type * ) final { \ 214 kind= LeafKind::node_type; \214 result = LeafKind::node_type; \ 215 215 return nullptr; \ 216 216 } … … 222 222 223 223 LeafKind get_leaf_kind( ast::Node const * node ) { 224 LeafKindVisitor visitor; 225 node->accept( visitor ); 226 return visitor.kind; 224 return ast::Pass<LeafKindVisitor>::read( node ); 227 225 } 228 226 -
src/Common/DeclStats.cpp
r2ed94a9 rb110bcc 23 23 #include <iostream> 24 24 #include <map> 25 #include <sstream> 25 26 #include <unordered_map> 26 27 #include <unordered_set> -
src/Common/Eval.cc
r2ed94a9 rb110bcc 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/ResolvProtoDump.cpp
r2ed94a9 rb110bcc 19 19 #include <iostream> 20 20 #include <set> 21 #include <sstream> 21 22 #include <unordered_set> 22 23 … … 26 27 #include "AST/Type.hpp" 27 28 #include "CodeGen/OperatorTable.h" 28 #include "Common/utility.h"29 29 30 30 namespace { -
src/Common/SemanticError.h
r2ed94a9 rb110bcc 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Feb 2 10:59:10202313 // Update Count : 3 612 // Last Modified On : Sat Feb 25 12:01:31 2023 13 // Update Count : 37 14 14 // 15 15 … … 56 56 {"self-assign" , Severity::Warn , "self assignment of expression: %s" }, 57 57 {"reference-conversion" , Severity::Warn , "rvalue to reference conversion of rvalue: %s" }, 58 {"qualifiers-zero_t-one_t" , Severity::Warn , "questionable use of type qualifier %swith %s" },58 {"qualifiers-zero_t-one_t" , Severity::Warn , "questionable use of type qualifier(s) with %s" }, 59 59 {"aggregate-forward-decl" , Severity::Warn , "forward declaration of nested aggregate: %s" }, 60 60 {"superfluous-decl" , Severity::Warn , "declaration does not allocate storage: %s" }, -
src/Common/module.mk
r2ed94a9 rb110bcc 20 20 Common/CodeLocationTools.hpp \ 21 21 Common/CodeLocationTools.cpp \ 22 Common/CompilerError.h \23 Common/Debug.h \24 22 Common/DeclStats.hpp \ 25 23 Common/DeclStats.cpp \ 26 24 Common/ErrorObjects.h \ 27 25 Common/Eval.cc \ 26 Common/Eval.h \ 28 27 Common/Examine.cc \ 29 28 Common/Examine.h \ … … 31 30 Common/Indenter.h \ 32 31 Common/Indenter.cc \ 32 Common/Iterate.hpp \ 33 33 Common/PassVisitor.cc \ 34 34 Common/PassVisitor.h \ … … 52 52 Common/Stats/Time.cc \ 53 53 Common/Stats/Time.h \ 54 Common/ UnimplementedError.h\54 Common/ToString.hpp \ 55 55 Common/UniqueName.cc \ 56 56 Common/UniqueName.h \ -
src/Common/utility.h
r2ed94a9 rb110bcc 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> 26 #include <sstream>27 24 #include <string> 28 25 #include <type_traits> 29 #include <utility>30 26 #include <vector> 31 27 #include <cstring> // memcmp … … 49 45 return 0; 50 46 } // 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 47 } 75 48 … … 168 141 splice( src, dst ); 169 142 dst.swap( src ); 170 }171 172 template < typename T >173 void toString_single( std::ostream & os, const T & value ) {174 os << value;175 }176 177 template < typename T, typename... Params >178 void toString_single( std::ostream & os, const T & value, const Params & ... params ) {179 os << value;180 toString_single( os, params ... );181 }182 183 template < typename ... Params >184 std::string toString( const Params & ... params ) {185 std::ostringstream os;186 toString_single( os, params... );187 return os.str();188 }189 190 #define toCString( ... ) toString( __VA_ARGS__ ).c_str()191 192 // replace element of list with all elements of another 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 143 } 211 144 … … 236 169 } 237 170 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 template< typename... Params >268 void warn( const Params & ... params ) {269 std::cerr << "Warning: ";270 warn_single( params... );271 }272 273 171 // determines if pref is a prefix of str 274 172 static inline bool isPrefix( const std::string & str, const std::string & pref, unsigned int start = 0 ) { 275 173 if ( pref.size() > str.size() ) return false; 276 return 0 == memcmp( str.c_str() + start, pref.c_str(), pref.size() ); 277 // return prefix == full.substr(0, prefix.size()); // for future, requires c++17 278 } 279 280 // ----------------------------------------------------------------------------- 281 // Ref Counted Singleton class 282 // Objects that inherit from this class will have at most one reference to it 283 // but if all references die, the object will be deleted. 284 285 template< typename ThisType > 286 class RefCountSingleton { 287 public: 288 static std::shared_ptr<ThisType> get() { 289 if( global_instance.expired() ) { 290 std::shared_ptr<ThisType> new_instance = std::make_shared<ThisType>(); 291 global_instance = new_instance; 292 return std::move(new_instance); 293 } 294 return global_instance.lock(); 295 } 296 private: 297 static std::weak_ptr<ThisType> global_instance; 298 }; 299 300 template< typename ThisType > 301 std::weak_ptr<ThisType> RefCountSingleton<ThisType>::global_instance; 174 return pref == str.substr(start, pref.size()); 175 } 302 176 303 177 // ----------------------------------------------------------------------------- … … 356 230 ~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } } 357 231 }; 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 232 565 233 // ----------------------------------------------------------------------------- … … 583 251 } // ilog2 584 252 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 253 // Local Variables: // 630 254 // tab-width: 4 // -
src/CompilationState.cc
r2ed94a9 rb110bcc 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Henry Xue12 // Last Modified On : Tue Jul 20 04:27:35 202113 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 19:12:50 2023 13 // Update Count : 6 14 14 // 15 15 … … 27 27 expraltp = false, 28 28 genericsp = false, 29 invariant = false, 29 30 libcfap = false, 30 31 nopreludep = false, -
src/CompilationState.h
r2ed94a9 rb110bcc 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon Ju1 30 10:47:01 2018 11 // Last Modified By : Henry Xue12 // Last Modified On : Tue Jul 20 04:27:35 202113 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 19:12:53 2023 13 // Update Count : 6 14 14 // 15 15 … … 26 26 expraltp, 27 27 genericsp, 28 invariant, 28 29 libcfap, 29 30 nopreludep, -
src/Concurrency/Actors.cpp
r2ed94a9 rb110bcc 45 45 // finds and sets a ptr to the actor, message, and request structs, which are needed in the next pass 46 46 void previsit( const StructDecl * decl ) { 47 GuardValue(insideStruct); 48 insideStruct = true; 49 parentDecl = mutate( decl ); 50 if( decl->name == "actor" ) *actorDecl = decl; 51 if( decl->name == "message" ) *msgDecl = decl; 52 if( decl->name == "request" ) *requestDecl = decl; 47 if ( !decl->body ) return; 48 if ( decl->name == "actor" ) { 49 actorStructDecls.insert( decl ); // skip inserting fwd decl 50 *actorDecl = decl; 51 } else if( decl->name == "message" ) { 52 messageStructDecls.insert( decl ); // skip inserting fwd decl 53 *msgDecl = decl; 54 } else if( decl->name == "request" ) *requestDecl = decl; 55 else { 56 GuardValue(insideStruct); 57 insideStruct = true; 58 parentDecl = mutate( decl ); 59 } 53 60 } 54 61 … … 64 71 } 65 72 66 // this collects the valid actor and message struct decl pts73 // this collects the derived actor and message struct decl ptrs 67 74 void postvisit( const StructInstType * node ) { 68 75 if ( ! *actorDecl || ! *msgDecl ) return; 69 76 if ( insideStruct && !namedDecl ) { 70 if ( node->aggr() == *actorDecl ) { 77 auto actorIter = actorStructDecls.find( node->aggr() ); 78 if ( actorIter != actorStructDecls.end() ) { 71 79 actorStructDecls.insert( parentDecl ); 72 } else if ( node->aggr() == *msgDecl ) { 80 return; 81 } 82 auto messageIter = messageStructDecls.find( node->aggr() ); 83 if ( messageIter != messageStructDecls.end() ) { 73 84 messageStructDecls.insert( parentDecl ); 74 85 } … … 180 191 }; 181 192 182 #define __ALLOC 0 // C_TODO: complete swap to no-alloc version 183 184 struct GenReceiveDecls : public ast::WithDeclsToAdd<> { 193 // generates the definitions of send operators for actors 194 // collects data needed for next pass that does the circular defn resolution 195 // for message send operators (via table above) 196 struct GenFuncsCreateTables : public ast::WithDeclsToAdd<> { 185 197 unordered_set<const StructDecl *> & actorStructDecls; 186 198 unordered_set<const StructDecl *> & messageStructDecls; … … 191 203 FwdDeclTable & forwardDecls; 192 204 205 // generates the operator for actor message sends 193 206 void postvisit( const FunctionDecl * decl ) { 194 207 // return if not of the form receive( param1, param2 ) or if it is a forward decl … … 209 222 auto messageIter = messageStructDecls.find( arg2InstType->aggr() ); 210 223 if ( actorIter != actorStructDecls.end() && messageIter != messageStructDecls.end() ) { 211 212 // check that we have found all the decls we need from <actor.hfa>213 if ( !*allocationDecl || !*requestDecl )214 SemanticError( decl->location, "using actors requires a header, add #include <actor.hfa>\n" );215 216 224 ////////////////////////////////////////////////////////////////////// 217 225 // The following generates this send message operator routine for all receive(derived_actor &, derived_msg &) functions 218 226 /* 219 227 static inline derived_actor & ?|?( derived_actor & receiver, derived_msg & msg ) { 220 request * new_req = alloc();228 request new_req; 221 229 Allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive; 222 230 __receive_fn fn = (__receive_fn)my_work_fn; 223 (*new_req){ &receiver, &msg, fn };224 send( receiver, *new_req );231 new_req{ &receiver, &msg, fn }; 232 send( receiver, new_req ); 225 233 return receiver; 226 234 } 227 */ // C_TODO: update this with new no alloc version235 */ 228 236 CompoundStmt * sendBody = new CompoundStmt( decl->location ); 229 237 230 #if __ALLOC231 // Generates: request * new_req = alloc();232 sendBody->push_back( new DeclStmt(233 decl->location,234 new ObjectDecl(235 decl->location,236 "new_req",237 new PointerType( new StructInstType( *requestDecl ) ),238 new SingleInit( decl->location, new UntypedExpr( decl->location, new NameExpr( decl->location, "alloc" ), {} ) )239 )240 ));241 #else242 238 // Generates: request new_req; 243 239 sendBody->push_back( new DeclStmt( … … 249 245 ) 250 246 )); 251 #endif252 247 253 248 // Function type is: Allocation (*)( derived_actor &, derived_msg & ) … … 268 263 )); 269 264 270 // Function type is: Allocation (*)( actor &, mess sage & )265 // Function type is: Allocation (*)( actor &, message & ) 271 266 FunctionType * genericReceive = new FunctionType(); 272 267 genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) ); … … 274 269 genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) ); 275 270 276 // Generates: Allocation (*fn)( actor &, mess sage & ) = (Allocation (*)( actor &, messsage & ))my_work_fn;271 // Generates: Allocation (*fn)( actor &, message & ) = (Allocation (*)( actor &, message & ))my_work_fn; 277 272 // More readable synonymous code: 278 273 // typedef Allocation (*__receive_fn)(actor &, message &); … … 290 285 )); 291 286 292 #if __ALLOC293 // Generates: (*new_req){ &receiver, &msg, fn };294 sendBody->push_back( new ExprStmt(295 decl->location,296 new UntypedExpr (297 decl->location,298 new NameExpr( decl->location, "?{}" ),299 {300 new UntypedExpr( decl->location, new NameExpr( decl->location, "*?" ), { new NameExpr( decl->location, "new_req" ) } ),301 new AddressExpr( new NameExpr( decl->location, "receiver" ) ),302 new AddressExpr( new NameExpr( decl->location, "msg" ) ),303 new NameExpr( decl->location, "fn" )304 }305 )306 ));307 308 // Generates: send( receiver, *new_req );309 sendBody->push_back( new ExprStmt(310 decl->location,311 new UntypedExpr (312 decl->location,313 new NameExpr( decl->location, "send" ),314 {315 {316 new NameExpr( decl->location, "receiver" ),317 new UntypedExpr( decl->location, new NameExpr( decl->location, "*?" ), { new NameExpr( decl->location, "new_req" ) } )318 }319 }320 )321 ));322 #else323 287 // Generates: new_req{ &receiver, &msg, fn }; 324 288 sendBody->push_back( new ExprStmt( … … 350 314 ) 351 315 )); 352 #endif353 316 354 317 // Generates: return receiver; … … 358 321 FunctionDecl * sendOperatorFunction = new FunctionDecl( 359 322 decl->location, 360 "? |?",323 "?<<?", 361 324 {}, // forall 362 325 { … … 388 351 // forward decls to resolve use before decl problem for '|' routines 389 352 forwardDecls.insertDecl( *actorIter, *messageIter , ast::deepCopy( sendOperatorFunction ) ); 390 // forwardDecls.push_back( ast::deepCopy( sendOperatorFunction ) );391 353 392 354 sendOperatorFunction->stmts = sendBody; … … 396 358 397 359 public: 398 Gen ReceiveDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls,360 GenFuncsCreateTables( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls, 399 361 const StructDecl ** requestDecl, const EnumDecl ** allocationDecl, const StructDecl ** actorDecl, const StructDecl ** msgDecl, 400 362 FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), … … 402 364 }; 403 365 404 struct GenFwdDecls : public ast::WithDeclsToAdd<> { 366 367 // separate pass is needed since this pass resolves circular defn issues 368 // generates the forward declarations of the send operator for actor routines 369 struct FwdDeclOperator : public ast::WithDeclsToAdd<> { 405 370 unordered_set<const StructDecl *> & actorStructDecls; 406 371 unordered_set<const StructDecl *> & messageStructDecls; 407 372 FwdDeclTable & forwardDecls; 408 373 374 // handles forward declaring the message operator 409 375 void postvisit( const StructDecl * decl ) { 410 376 list<FunctionDecl *> toAddAfter; … … 433 399 434 400 public: 435 GenFwdDecls( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls, 436 FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), 437 forwardDecls(forwardDecls) {} 401 FwdDeclOperator( unordered_set<const StructDecl *> & actorStructDecls, unordered_set<const StructDecl *> & messageStructDecls, 402 FwdDeclTable & forwardDecls ) : actorStructDecls(actorStructDecls), messageStructDecls(messageStructDecls), forwardDecls(forwardDecls) {} 438 403 }; 439 404 … … 461 426 Pass<CollectactorStructDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl, 462 427 allocationDecl, actorDecl, msgDecl ); 463 428 429 // check that we have found all the decls we need from <actor.hfa>, if not no need to run the rest of this pass 430 if ( !allocationDeclPtr || !requestDeclPtr || !actorDeclPtr || !msgDeclPtr ) 431 return; 432 464 433 // second pass locates all receive() routines that overload the generic receive fn 465 434 // it then generates the appropriate operator '|' send routines for the receive routines 466 Pass<Gen ReceiveDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl,435 Pass<GenFuncsCreateTables>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl, 467 436 allocationDecl, actorDecl, msgDecl, forwardDecls ); 468 437 469 438 // The third pass forward declares operator '|' send routines 470 Pass< GenFwdDecls>::run( translationUnit, actorStructDecls, messageStructDecls, forwardDecls );439 Pass<FwdDeclOperator>::run( translationUnit, actorStructDecls, messageStructDecls, forwardDecls ); 471 440 } 472 441 -
src/Concurrency/Actors.hpp
r2ed94a9 rb110bcc 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Keywords.h-- Implement concurrency constructs from their keywords.7 // Actors.hpp -- Implement concurrency constructs from their keywords. 8 8 // 9 9 // Author : Colby Parsons -
src/Concurrency/KeywordsNew.cpp
r2ed94a9 rb110bcc 779 779 780 780 const ast::Stmt * SuspendKeyword::postvisit( const ast::SuspendStmt * stmt ) { 781 switch ( stmt-> type) {781 switch ( stmt->kind ) { 782 782 case ast::SuspendStmt::None: 783 783 // Use the context to determain the implicit target. -
src/ControlStruct/ExceptDeclNew.cpp
r2ed94a9 rb110bcc 15 15 16 16 #include "ExceptDecl.h" 17 18 #include <sstream> 17 19 18 20 #include "AST/Decl.hpp" -
src/ControlStruct/ExceptTranslateNew.cpp
r2ed94a9 rb110bcc 314 314 nullptr, 315 315 ast::Storage::Classes{}, 316 ast::Linkage::Cforall 316 ast::Linkage::Cforall, 317 {}, 318 { ast::Function::Inline } 317 319 ); 318 320 } -
src/ControlStruct/MLEMutator.cc
r2ed94a9 rb110bcc 25 25 #include <memory> // for allocator_traits<>::value_... 26 26 27 #include "Common/ utility.h" // for toString, operator+27 #include "Common/ToString.hpp" // for toString 28 28 #include "ControlStruct/LabelGenerator.h" // for LabelGenerator 29 29 #include "MLEMutator.h" -
src/GenPoly/Box.cc
r2ed94a9 rb110bcc 31 31 #include "Common/SemanticError.h" // for SemanticError 32 32 #include "Common/UniqueName.h" // for UniqueName 33 #include "Common/ utility.h" // for toString33 #include "Common/ToString.hpp" // for toCString 34 34 #include "FindFunction.h" // for findFunction, findAndReplace... 35 35 #include "GenPoly/ErasableScopedMap.h" // for ErasableScopedMap<>::const_i... … … 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
r2ed94a9 rb110bcc 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
r2ed94a9 rb110bcc 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
r2ed94a9 rb110bcc 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
r2ed94a9 rb110bcc 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/GenPoly/Lvalue.cc
r2ed94a9 rb110bcc 17 17 #include <string> // for string 18 18 19 #include "Common/ToString.hpp" // for toCString 19 20 #include "Common/UniqueName.h" 20 21 #include "Common/PassVisitor.h" -
src/GenPoly/LvalueNew.cpp
r2ed94a9 rb110bcc 25 25 #include "AST/Pass.hpp" 26 26 #include "Common/SemanticError.h" // for SemanticWarning 27 #include "Common/ToString.hpp" // for toCString 27 28 #include "Common/UniqueName.h" // for UniqueName 28 29 #include "GenPoly/GenPoly.h" // for genFunctionType -
src/InitTweak/FixInit.cc
r2ed94a9 rb110bcc 32 32 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 33 33 #include "Common/SemanticError.h" // for SemanticError 34 #include "Common/ToString.hpp" // for toCString 34 35 #include "Common/UniqueName.h" // for UniqueName 35 #include "Common/utility.h" // for CodeLocation, ValueGuard, toSt...36 36 #include "FixGlobalInit.h" // for fixGlobalInit 37 37 #include "GenInit.h" // for genCtorDtor … … 1233 1233 } 1234 1234 1235 template< typename Visitor, typename... Params >1236 void error( Visitor & v, CodeLocation loc, const Params &... params ) {1237 SemanticErrorException err( loc, toString( params... ) );1238 v.errors.append( err );1239 }1240 1241 1235 template< typename... Params > 1242 1236 void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) { 1243 // toggle warnings vs. errors here. 1244 // warn( params... ); 1245 error( *this, loc, params... ); 1237 SemanticErrorException err( loc, toString( params... ) ); 1238 errors.append( err ); 1246 1239 } 1247 1240 -
src/InitTweak/FixInitNew.cpp
r2ed94a9 rb110bcc 14 14 #include <utility> // for pair 15 15 16 #include "AST/DeclReplacer.hpp" 17 #include "AST/Expr.hpp" 16 18 #include "AST/Inspect.hpp" // for getFunction, getPointerBase, g... 19 #include "AST/Node.hpp" 20 #include "AST/Pass.hpp" 21 #include "AST/Print.hpp" 22 #include "AST/SymbolTable.hpp" 23 #include "AST/Type.hpp" 17 24 #include "CodeGen/GenType.h" // for genPrettyType 18 25 #include "CodeGen/OperatorTable.h" 19 #include "Common/CodeLocationTools.hpp"20 26 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 21 27 #include "Common/SemanticError.h" // for SemanticError 28 #include "Common/ToString.hpp" // for toCString 22 29 #include "Common/UniqueName.h" // for UniqueName 23 #include "Common/utility.h" // for CodeLocation, ValueGuard, toSt...24 30 #include "FixGlobalInit.h" // for fixGlobalInit 25 31 #include "GenInit.h" // for genCtorDtor … … 28 34 #include "ResolvExpr/Unify.h" // for typesCompatible 29 35 #include "SymTab/Autogen.h" // for genImplicitCall 36 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall 30 37 #include "SymTab/Indexer.h" // for Indexer 31 38 #include "SymTab/Mangler.h" // for Mangler … … 45 52 #include "Validate/FindSpecialDecls.h" // for dtorStmt, dtorStructDestroy 46 53 47 #include "AST/Expr.hpp"48 #include "AST/Node.hpp"49 #include "AST/Pass.hpp"50 #include "AST/Print.hpp"51 #include "AST/SymbolTable.hpp"52 #include "AST/Type.hpp"53 #include "AST/DeclReplacer.hpp"54 55 54 extern bool ctordtorp; // print all debug 56 55 extern bool ctorp; // print ctor debug … … 63 62 namespace InitTweak { 64 63 namespace { 64 65 // Shallow copy the pointer list for return. 66 std::vector<ast::ptr<ast::TypeDecl>> getGenericParams( const ast::Type * t ) { 67 if ( auto inst = dynamic_cast<const ast::StructInstType *>( t ) ) { 68 return inst->base->params; 69 } 70 if ( auto inst = dynamic_cast<const ast::UnionInstType *>( t ) ) { 71 return inst->base->params; 72 } 73 return {}; 74 } 75 76 /// Given type T, generate type of default ctor/dtor, i.e. function type void (*) (T &). 77 ast::FunctionDecl * genDefaultFunc( 78 const CodeLocation loc, 79 const std::string fname, 80 const ast::Type * paramType, 81 bool maybePolymorphic = true) { 82 std::vector<ast::ptr<ast::TypeDecl>> typeParams; 83 if ( maybePolymorphic ) typeParams = getGenericParams( paramType ); 84 auto dstParam = new ast::ObjectDecl( loc, 85 "_dst", 86 new ast::ReferenceType( paramType ), 87 nullptr, 88 {}, 89 ast::Linkage::Cforall 90 ); 91 return new ast::FunctionDecl( loc, 92 fname, 93 std::move(typeParams), 94 {dstParam}, 95 {}, 96 new ast::CompoundStmt(loc), 97 {}, 98 ast::Linkage::Cforall 99 ); 100 } 101 65 102 struct SelfAssignChecker { 66 103 void previsit( const ast::ApplicationExpr * appExpr ); … … 107 144 private: 108 145 /// hack to implement WithTypeSubstitution while conforming to mutation safety. 109 ast::TypeSubstitution * env ;110 bool envModified ;146 ast::TypeSubstitution * env = nullptr; 147 bool envModified = false; 111 148 }; 112 149 … … 121 158 void previsit( const ast::FunctionDecl * ) { visit_children = false; } 122 159 123 160 protected: 124 161 ObjectSet curVars; 125 162 }; … … 202 239 203 240 SemanticErrorException errors; 204 241 private: 205 242 template< typename... Params > 206 243 void emit( CodeLocation, const Params &... params ); … … 288 325 static UniqueName dtorNamer( "__cleanup_dtor" ); 289 326 std::string name = dtorNamer.newName(); 290 ast::FunctionDecl * dtorFunc = SymTab::genDefaultFunc( loc, name, objDecl->type->stripReferences(), false );327 ast::FunctionDecl * dtorFunc = genDefaultFunc( loc, name, objDecl->type->stripReferences(), false ); 291 328 stmtsToAdd.push_back( new ast::DeclStmt(loc, dtorFunc ) ); 292 329 … … 522 559 { 523 560 static UniqueName tempNamer("_tmp_cp"); 524 assert( env );525 561 const CodeLocation loc = impCpCtorExpr->location; 526 562 // CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; ) … … 534 570 535 571 // xxx - this originally mutates arg->result in place. is it correct? 572 assert( env ); 536 573 result = env->applyFree( result.get() ).node; 537 574 auto mutResult = result.get_and_mutate(); … … 1080 1117 void InsertDtors::previsit( const ast::BranchStmt * stmt ) { 1081 1118 switch( stmt->kind ) { 1082 1083 1119 case ast::BranchStmt::Continue: 1120 case ast::BranchStmt::Break: 1084 1121 // could optimize the break/continue case, because the S_L-S_G check is unnecessary (this set should 1085 1122 // always be empty), but it serves as a small sanity check. 1086 1123 case ast::BranchStmt::Goto: 1087 1124 handleGoto( stmt ); 1088 1125 break; 1089 1126 default: 1090 1127 assert( false ); 1091 1128 } // switch … … 1303 1340 } 1304 1341 1305 template< typename Visitor, typename... Params >1306 void error( Visitor & v, CodeLocation loc, const Params &... params ) {1307 SemanticErrorException err( loc, toString( params... ) );1308 v.errors.append( err );1309 }1310 1311 1342 template< typename... Params > 1312 1343 void GenStructMemberCalls::emit( CodeLocation loc, const Params &... params ) { 1313 // toggle warnings vs. errors here. 1314 // warn( params... ); 1315 error( *this, loc, params... ); 1344 SemanticErrorException err( loc, toString( params... ) ); 1345 errors.append( err ); 1316 1346 } 1317 1347 … … 1319 1349 // xxx - functions returning ast::ptr seems wrong... 1320 1350 auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } ); 1321 // Fix CodeLocation (at least until resolver is fixed). 1322 auto fix = localFillCodeLocations( untypedExpr->location, res.release() ); 1323 return strict_dynamic_cast<const ast::Expr *>( fix ); 1351 return res.release(); 1324 1352 } 1325 1353 -
src/InitTweak/GenInit.cc
r2ed94a9 rb110bcc 31 31 #include "Common/PassVisitor.h" // for PassVisitor, WithGuards, WithShort... 32 32 #include "Common/SemanticError.h" // for SemanticError 33 #include "Common/ToString.hpp" // for toCString 33 34 #include "Common/UniqueName.h" // for UniqueName 34 35 #include "Common/utility.h" // for ValueGuard, maybeClone … … 38 39 #include "ResolvExpr/Resolver.h" 39 40 #include "SymTab/Autogen.h" // for genImplicitCall 41 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall 40 42 #include "SymTab/Mangler.h" // for Mangler 41 43 #include "SynTree/LinkageSpec.h" // for isOverridable, C -
src/Parser/DeclarationNode.cc
r2ed94a9 rb110bcc 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 12:34:05 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Mon Aug 8 17:07:00 202213 // Update Count : 1 18511 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr Apr 20 11:46:00 2023 13 // Update Count : 1393 14 14 // 15 16 #include "DeclarationNode.h" 15 17 16 18 #include <cassert> // for assert, assertf, strict_dynamic_cast … … 21 23 #include <string> // for string, operator+, allocator, char... 22 24 25 #include "AST/Attribute.hpp" // for Attribute 26 #include "AST/Copy.hpp" // for shallowCopy 27 #include "AST/Decl.hpp" // for Decl 28 #include "AST/Expr.hpp" // for Expr 29 #include "AST/Print.hpp" // for print 30 #include "AST/Stmt.hpp" // for AsmStmt, DirectiveStmt 31 #include "AST/StorageClasses.hpp" // for Storage::Class 32 #include "AST/Type.hpp" // for Type 33 #include "Common/CodeLocation.h" // for CodeLocation 34 #include "Common/Iterate.hpp" // for reverseIterate 23 35 #include "Common/SemanticError.h" // for SemanticError 24 36 #include "Common/UniqueName.h" // for UniqueName 25 #include "Common/utility.h" // for maybeClone, maybeBuild, CodeLocation 26 #include "Parser/ParseNode.h" // for DeclarationNode, ExpressionNode 27 #include "SynTree/LinkageSpec.h" // for Spec, linkageName, Cforall 28 #include "SynTree/Attribute.h" // for Attribute 29 #include "SynTree/Declaration.h" // for TypeDecl, ObjectDecl, InlineMemberDecl, Declaration 30 #include "SynTree/Expression.h" // for Expression, ConstantExpr 31 #include "SynTree/Statement.h" // for AsmStmt 32 #include "SynTree/Type.h" // for Type, Type::StorageClasses, Type::... 37 #include "Common/utility.h" // for maybeClone 38 #include "Parser/ExpressionNode.h" // for ExpressionNode 39 #include "Parser/InitializerNode.h"// for InitializerNode 40 #include "Parser/StatementNode.h" // for StatementNode 33 41 #include "TypeData.h" // for TypeData, TypeData::Aggregate_t 34 42 #include "TypedefTable.h" // for TypedefTable … … 41 49 42 50 // These must harmonize with the corresponding DeclarationNode enumerations. 43 const char * DeclarationNode::basicTypeNames[] = { "void", "_Bool", "char", "int", "int128", 44 "float", "double", "long double", "float80", "float128", 45 "_float16", "_float32", "_float32x", "_float64", "_float64x", "_float128", "_float128x", "NoBasicTypeNames" }; 46 const char * DeclarationNode::complexTypeNames[] = { "_Complex", "NoComplexTypeNames", "_Imaginary" }; // Imaginary unsupported => parse, but make invisible and print error message 47 const char * DeclarationNode::signednessNames[] = { "signed", "unsigned", "NoSignednessNames" }; 48 const char * DeclarationNode::lengthNames[] = { "short", "long", "long long", "NoLengthNames" }; 49 const char * DeclarationNode::builtinTypeNames[] = { "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames" }; 51 const char * DeclarationNode::basicTypeNames[] = { 52 "void", "_Bool", "char", "int", "int128", 53 "float", "double", "long double", "float80", "float128", 54 "_float16", "_float32", "_float32x", "_float64", "_float64x", "_float128", "_float128x", "NoBasicTypeNames" 55 }; 56 const char * DeclarationNode::complexTypeNames[] = { 57 "_Complex", "NoComplexTypeNames", "_Imaginary" 58 }; // Imaginary unsupported => parse, but make invisible and print error message 59 const char * DeclarationNode::signednessNames[] = { 60 "signed", "unsigned", "NoSignednessNames" 61 }; 62 const char * DeclarationNode::lengthNames[] = { 63 "short", "long", "long long", "NoLengthNames" 64 }; 65 const char * DeclarationNode::builtinTypeNames[] = { 66 "__builtin_va_list", "__auto_type", "zero_t", "one_t", "NoBuiltinTypeNames" 67 }; 50 68 51 69 UniqueName DeclarationNode::anonymous( "__anonymous" ); 52 70 53 extern LinkageSpec::Spec linkage; // defined in parser.yy71 extern ast::Linkage::Spec linkage; // defined in parser.yy 54 72 55 73 DeclarationNode::DeclarationNode() : … … 57 75 58 76 // variable.name = nullptr; 59 variable.tyClass = TypeDecl::NUMBER_OF_KINDS;77 variable.tyClass = ast::TypeDecl::NUMBER_OF_KINDS; 60 78 variable.assertions = nullptr; 61 79 variable.initializer = nullptr; 62 80 63 // attr.name = nullptr;64 attr.expr = nullptr;65 attr.type = nullptr;66 67 81 assert.condition = nullptr; 68 82 assert.message = nullptr; … … 70 84 71 85 DeclarationNode::~DeclarationNode() { 72 // delete attr.name;73 delete attr.expr;74 delete attr.type;75 76 86 // delete variable.name; 77 87 delete variable.assertions; 78 88 delete variable.initializer; 79 89 80 // 90 // delete type; 81 91 delete bitfieldWidth; 82 92 … … 103 113 newnode->hasEllipsis = hasEllipsis; 104 114 newnode->linkage = linkage; 105 newnode->asmName = maybeC lone( asmName );106 cloneAll( attributes, newnode->attributes );115 newnode->asmName = maybeCopy( asmName ); 116 newnode->attributes = attributes; 107 117 newnode->initializer = maybeClone( initializer ); 108 118 newnode->extension = extension; … … 115 125 newnode->variable.initializer = maybeClone( variable.initializer ); 116 126 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 127 newnode->assert.condition = maybeClone( assert.condition ); 122 newnode->assert.message = maybeC lone( assert.message );128 newnode->assert.message = maybeCopy( assert.message ); 123 129 return newnode; 124 130 } // DeclarationNode::clone … … 130 136 } // if 131 137 132 if ( linkage != LinkageSpec::Cforall ) {133 os << LinkageSpec::name( linkage ) << " ";134 } // if 135 136 storageClasses.print( os );137 funcSpecs.print( os );138 if ( linkage != ast::Linkage::Cforall ) { 139 os << ast::Linkage::name( linkage ) << " "; 140 } // if 141 142 ast::print( os, storageClasses ); 143 ast::print( os, funcSpecs ); 138 144 139 145 if ( type ) { … … 154 160 } // if 155 161 156 for ( Attribute * attr: reverseIterate( attributes ) ) { 157 os << string( indent + 2, ' ' ) << "attr " << attr->name.c_str(); 158 } // for 162 if ( ! attributes.empty() ) { 163 os << string( indent + 2, ' ' ) << "with attributes " << endl; 164 for ( ast::ptr<ast::Attribute> const & attr : reverseIterate( attributes ) ) { 165 os << string( indent + 4, ' ' ) << attr->name.c_str() << endl; 166 } // for 167 } // if 159 168 160 169 os << endl; … … 168 177 } 169 178 170 DeclarationNode * DeclarationNode::newStorageClass( Type::StorageClasses sc ) {179 DeclarationNode * DeclarationNode::newStorageClass( ast::Storage::Classes sc ) { 171 180 DeclarationNode * newnode = new DeclarationNode; 172 181 newnode->storageClasses = sc; … … 174 183 } // DeclarationNode::newStorageClass 175 184 176 DeclarationNode * DeclarationNode::newFuncSpecifier( Type::FuncSpecifiers fs ) {185 DeclarationNode * DeclarationNode::newFuncSpecifier( ast::Function::Specs fs ) { 177 186 DeclarationNode * newnode = new DeclarationNode; 178 187 newnode->funcSpecs = fs; … … 180 189 } // DeclarationNode::newFuncSpecifier 181 190 182 DeclarationNode * DeclarationNode::newTypeQualifier( Type::Qualifiers tq ) {191 DeclarationNode * DeclarationNode::newTypeQualifier( ast::CV::Qualifiers tq ) { 183 192 DeclarationNode * newnode = new DeclarationNode; 184 193 newnode->type = new TypeData(); … … 240 249 } 241 250 242 DeclarationNode * DeclarationNode::newAggregate( AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) {251 DeclarationNode * DeclarationNode::newAggregate( ast::AggregateDecl::Aggregate kind, const string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body ) { 243 252 DeclarationNode * newnode = new DeclarationNode; 244 253 newnode->type = new TypeData( TypeData::Aggregate ); 245 254 newnode->type->aggregate.kind = kind; 246 newnode->type->aggregate.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name; 255 newnode->type->aggregate.anon = name == nullptr; 256 newnode->type->aggregate.name = newnode->type->aggregate.anon ? new string( DeclarationNode::anonymous.newName() ) : name; 247 257 newnode->type->aggregate.actuals = actuals; 248 258 newnode->type->aggregate.fields = fields; … … 250 260 newnode->type->aggregate.tagged = false; 251 261 newnode->type->aggregate.parent = nullptr; 252 newnode->type->aggregate.anon = name == nullptr;253 262 return newnode; 254 263 } // DeclarationNode::newAggregate … … 257 266 DeclarationNode * newnode = new DeclarationNode; 258 267 newnode->type = new TypeData( TypeData::Enum ); 259 newnode->type->enumeration.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name; 268 newnode->type->enumeration.anon = name == nullptr; 269 newnode->type->enumeration.name = newnode->type->enumeration.anon ? new string( DeclarationNode::anonymous.newName() ) : name; 260 270 newnode->type->enumeration.constants = constants; 261 271 newnode->type->enumeration.body = body; 262 newnode->type->enumeration.anon = name == nullptr;263 272 newnode->type->enumeration.typed = typed; 264 273 newnode->type->enumeration.hiding = hiding; 265 if ( base && base->type ) {274 if ( base && base->type ) { 266 275 newnode->type->base = base->type; 267 276 } // if … … 269 278 return newnode; 270 279 } // DeclarationNode::newEnum 271 272 273 280 274 281 DeclarationNode * DeclarationNode::newName( const string * name ) { … … 323 330 } // DeclarationNode::newFromTypeGen 324 331 325 DeclarationNode * DeclarationNode::newTypeParam( TypeDecl::Kind tc, const string * name ) {332 DeclarationNode * DeclarationNode::newTypeParam( ast::TypeDecl::Kind tc, const string * name ) { 326 333 DeclarationNode * newnode = newName( name ); 327 334 newnode->type = nullptr; … … 335 342 newnode->type = new TypeData( TypeData::Aggregate ); 336 343 newnode->type->aggregate.name = name; 337 newnode->type->aggregate.kind = AggregateDecl::Trait;344 newnode->type->aggregate.kind = ast::AggregateDecl::Trait; 338 345 newnode->type->aggregate.params = params; 339 346 newnode->type->aggregate.fields = asserts; … … 345 352 newnode->type = new TypeData( TypeData::AggregateInst ); 346 353 newnode->type->aggInst.aggregate = new TypeData( TypeData::Aggregate ); 347 newnode->type->aggInst.aggregate->aggregate.kind = AggregateDecl::Trait;354 newnode->type->aggInst.aggregate->aggregate.kind = ast::AggregateDecl::Trait; 348 355 newnode->type->aggInst.aggregate->aggregate.name = name; 349 356 newnode->type->aggInst.params = params; … … 380 387 newnode->type->array.dimension = size; 381 388 newnode->type->array.isStatic = isStatic; 382 if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType< ConstantExpr *>() ) {389 if ( newnode->type->array.dimension == nullptr || newnode->type->array.dimension->isExpressionType<ast::ConstantExpr *>() ) { 383 390 newnode->type->array.isVarLen = false; 384 391 } else { … … 450 457 DeclarationNode * newnode = new DeclarationNode; 451 458 newnode->type = nullptr; 452 std:: list< Expression *> exprs;459 std::vector<ast::ptr<ast::Expr>> exprs; 453 460 buildList( expr, exprs ); 454 newnode->attributes.push_back( new Attribute( *name, exprs ) ); 461 newnode->attributes.push_back( 462 new ast::Attribute( *name, std::move( exprs ) ) ); 455 463 delete name; 456 464 return newnode; … … 469 477 } 470 478 471 DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, Expression* message ) {479 DeclarationNode * DeclarationNode::newStaticAssert( ExpressionNode * condition, ast::Expr * message ) { 472 480 DeclarationNode * newnode = new DeclarationNode; 473 481 newnode->assert.condition = condition; … … 476 484 } 477 485 478 479 void appendError( string & dst, const string & src ) { 486 static void appendError( string & dst, const string & src ) { 480 487 if ( src.empty() ) return; 481 488 if ( dst.empty() ) { dst = src; return; } … … 484 491 485 492 void DeclarationNode::checkQualifiers( const TypeData * src, const TypeData * dst ) { 486 const Type::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization 487 488 if ( (qsrc & qdst).any() ) { // duplicates ? 489 for ( unsigned int i = 0; i < Type::NumTypeQualifier; i += 1 ) { // find duplicates 490 if ( qsrc[i] && qdst[i] ) { 491 appendError( error, string( "duplicate " ) + Type::QualifiersNames[i] ); 492 } // if 493 } // for 493 const ast::CV::Qualifiers qsrc = src->qualifiers, qdst = dst->qualifiers; // optimization 494 const ast::CV::Qualifiers duplicates = qsrc & qdst; 495 496 if ( duplicates.any() ) { 497 std::stringstream str; 498 str << "duplicate "; 499 ast::print( str, duplicates ); 500 str << "qualifier(s)"; 501 appendError( error, str.str() ); 494 502 } // for 495 503 } // DeclarationNode::checkQualifiers 496 504 497 505 void DeclarationNode::checkSpecifiers( DeclarationNode * src ) { 498 if ( (funcSpecs & src->funcSpecs).any() ) { // duplicates ? 499 for ( unsigned int i = 0; i < Type::NumFuncSpecifier; i += 1 ) { // find duplicates 500 if ( funcSpecs[i] && src->funcSpecs[i] ) { 501 appendError( error, string( "duplicate " ) + Type::FuncSpecifiersNames[i] ); 502 } // if 503 } // for 504 } // if 505 506 if ( storageClasses.any() && src->storageClasses.any() ) { // any reason to check ? 507 if ( (storageClasses & src->storageClasses ).any() ) { // duplicates ? 508 for ( unsigned int i = 0; i < Type::NumStorageClass; i += 1 ) { // find duplicates 509 if ( storageClasses[i] && src->storageClasses[i] ) { 510 appendError( error, string( "duplicate " ) + Type::StorageClassesNames[i] ); 511 } // if 512 } // for 513 // src is the new item being added and has a single bit 514 } else if ( ! src->storageClasses.is_threadlocal_any() ) { // conflict ? 515 appendError( error, string( "conflicting " ) + Type::StorageClassesNames[storageClasses.ffs()] + 516 " & " + Type::StorageClassesNames[src->storageClasses.ffs()] ); 517 src->storageClasses.reset(); // FIX to preserve invariant of one basic storage specifier 518 } // if 506 ast::Function::Specs fsDups = funcSpecs & src->funcSpecs; 507 if ( fsDups.any() ) { 508 std::stringstream str; 509 str << "duplicate "; 510 ast::print( str, fsDups ); 511 str << "function specifier(s)"; 512 appendError( error, str.str() ); 513 } // if 514 515 // Skip if everything is unset. 516 if ( storageClasses.any() && src->storageClasses.any() ) { 517 ast::Storage::Classes dups = storageClasses & src->storageClasses; 518 // Check for duplicates. 519 if ( dups.any() ) { 520 std::stringstream str; 521 str << "duplicate "; 522 ast::print( str, dups ); 523 str << "storage class(es)"; 524 appendError( error, str.str() ); 525 // Check for conflicts. 526 } else if ( !src->storageClasses.is_threadlocal_any() ) { 527 std::stringstream str; 528 str << "conflicting "; 529 ast::print( str, ast::Storage::Classes( 1 << storageClasses.ffs() ) ); 530 str << "& "; 531 ast::print( str, ast::Storage::Classes( 1 << src->storageClasses.ffs() ) ); 532 str << "storage classes"; 533 appendError( error, str.str() ); 534 // FIX to preserve invariant of one basic storage specifier 535 src->storageClasses.reset(); 536 } 519 537 } // if 520 538 … … 526 544 storageClasses |= q->storageClasses; 527 545 528 for ( Attribute * attr: reverseIterate( q->attributes ) ) { 529 attributes.push_front( attr->clone() ); 530 } // for 546 std::vector<ast::ptr<ast::Attribute>> tmp; 547 tmp.reserve( q->attributes.size() ); 548 for ( auto const & attr : q->attributes ) { 549 tmp.emplace_back( ast::shallowCopy( attr.get() ) ); 550 } 551 spliceBegin( attributes, tmp ); 552 531 553 return this; 532 554 } // DeclarationNode::copySpecifiers … … 576 598 577 599 checkQualifiers( type, q->type ); 578 if ( (builtin == Zero || builtin == One) && q->type->qualifiers. val != 0&& error.length() == 0 ) {579 SemanticWarning( yylloc, Warning::BadQualifiersZeroOne, Type::QualifiersNames[ilog2( q->type->qualifiers.val )],builtinTypeNames[builtin] );600 if ( (builtin == Zero || builtin == One) && q->type->qualifiers.any() && error.length() == 0 ) { 601 SemanticWarning( yylloc, Warning::BadQualifiersZeroOne, builtinTypeNames[builtin] ); 580 602 } // if 581 603 addQualifiersToType( q->type, type ); … … 598 620 } else { 599 621 switch ( dst->kind ) { 600 622 case TypeData::Unknown: 601 623 src->qualifiers |= dst->qualifiers; 602 624 dst = src; 603 625 src = nullptr; 604 626 break; 605 627 case TypeData::Basic: 606 628 dst->qualifiers |= src->qualifiers; 607 629 if ( src->kind != TypeData::Unknown ) { … … 631 653 } // if 632 654 break; 633 655 default: 634 656 switch ( src->kind ) { 635 636 657 case TypeData::Aggregate: 658 case TypeData::Enum: 637 659 dst->base = new TypeData( TypeData::AggregateInst ); 638 660 dst->base->aggInst.aggregate = src; … … 643 665 src = nullptr; 644 666 break; 645 667 default: 646 668 if ( dst->forall ) { 647 669 dst->forall->appendList( src->forall ); … … 714 736 715 737 DeclarationNode * DeclarationNode::addAssertions( DeclarationNode * assertions ) { 716 if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) {717 718 719 720 721 722 738 if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) { 739 if ( variable.assertions ) { 740 variable.assertions->appendList( assertions ); 741 } else { 742 variable.assertions = assertions; 743 } // if 744 return this; 723 745 } // if 724 746 725 747 assert( type ); 726 748 switch ( type->kind ) { 727 749 case TypeData::Symbolic: 728 750 if ( type->symbolic.assertions ) { 729 751 type->symbolic.assertions->appendList( assertions ); … … 732 754 } // if 733 755 break; 734 756 default: 735 757 assert( false ); 736 758 } // switch … … 796 818 DeclarationNode * DeclarationNode::copyAttribute( DeclarationNode * a ) { 797 819 if ( a ) { 798 for ( Attribute *attr: reverseIterate( a->attributes ) ) { 799 attributes.push_front( attr ); 800 } // for 820 spliceBegin( attributes, a->attributes ); 801 821 a->attributes.clear(); 802 822 } // if … … 831 851 if ( type ) { 832 852 switch ( type->kind ) { 833 834 853 case TypeData::Aggregate: 854 case TypeData::Enum: 835 855 p->type->base = new TypeData( TypeData::AggregateInst ); 836 856 p->type->base->aggInst.aggregate = type; … … 841 861 break; 842 862 843 863 default: 844 864 p->type->base = type; 845 865 } // switch … … 863 883 864 884 DeclarationNode * DeclarationNode::addNewArray( DeclarationNode * a ) { 865 885 if ( ! a ) return this; 866 886 assert( a->type->kind == TypeData::Array ); 867 887 TypeData * lastArray = findLast( a->type ); 868 888 if ( type ) { 869 889 switch ( type->kind ) { 870 871 890 case TypeData::Aggregate: 891 case TypeData::Enum: 872 892 lastArray->base = new TypeData( TypeData::AggregateInst ); 873 893 lastArray->base->aggInst.aggregate = type; … … 877 897 lastArray->base->qualifiers |= type->qualifiers; 878 898 break; 879 899 default: 880 900 lastArray->base = type; 881 901 } // switch … … 919 939 920 940 DeclarationNode * DeclarationNode::addTypeInitializer( DeclarationNode * init ) { 921 assertf( variable.tyClass != TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." );941 assertf( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS, "Called addTypeInitializer on something that isn't a type variable." ); 922 942 variable.initializer = init; 923 943 return this; … … 983 1003 } 984 1004 985 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList ) { 1005 // If a typedef wraps an anonymous declaration, name the inner declaration 1006 // so it has a consistent name across translation units. 1007 static void nameTypedefedDecl( 1008 DeclarationNode * innerDecl, 1009 const DeclarationNode * outerDecl ) { 1010 TypeData * outer = outerDecl->type; 1011 assert( outer ); 1012 // First make sure this is a typedef: 1013 if ( outer->kind != TypeData::Symbolic || !outer->symbolic.isTypedef ) { 1014 return; 1015 } 1016 TypeData * inner = innerDecl->type; 1017 assert( inner ); 1018 // Always clear any CVs associated with the aggregate: 1019 inner->qualifiers.reset(); 1020 // Handle anonymous aggregates: typedef struct { int i; } foo 1021 if ( inner->kind == TypeData::Aggregate && inner->aggregate.anon ) { 1022 delete inner->aggregate.name; 1023 inner->aggregate.name = new string( "__anonymous_" + *outerDecl->name ); 1024 inner->aggregate.anon = false; 1025 assert( outer->base ); 1026 delete outer->base->aggInst.aggregate->aggregate.name; 1027 outer->base->aggInst.aggregate->aggregate.name = new string( "__anonymous_" + *outerDecl->name ); 1028 outer->base->aggInst.aggregate->aggregate.anon = false; 1029 outer->base->aggInst.aggregate->qualifiers.reset(); 1030 // Handle anonymous enumeration: typedef enum { A, B, C } foo 1031 } else if ( inner->kind == TypeData::Enum && inner->enumeration.anon ) { 1032 delete inner->enumeration.name; 1033 inner->enumeration.name = new string( "__anonymous_" + *outerDecl->name ); 1034 inner->enumeration.anon = false; 1035 assert( outer->base ); 1036 delete outer->base->aggInst.aggregate->enumeration.name; 1037 outer->base->aggInst.aggregate->enumeration.name = new string( "__anonymous_" + *outerDecl->name ); 1038 outer->base->aggInst.aggregate->enumeration.anon = false; 1039 // No qualifiers.reset() here. 1040 } 1041 } 1042 1043 // This code handles a special issue with the attribute transparent_union. 1044 // 1045 // typedef union U { int i; } typedef_name __attribute__(( aligned(16) )) __attribute__(( transparent_union )) 1046 // 1047 // Here the attribute aligned goes with the typedef_name, so variables declared of this type are 1048 // aligned. However, the attribute transparent_union must be moved from the typedef_name to 1049 // alias union U. Currently, this is the only know attribute that must be moved from typedef to 1050 // alias. 1051 static void moveUnionAttribute( ast::Decl * decl, ast::UnionDecl * unionDecl ) { 1052 if ( auto typedefDecl = dynamic_cast<ast::TypedefDecl *>( decl ) ) { 1053 // Is the typedef alias a union aggregate? 1054 if ( nullptr == unionDecl ) return; 1055 1056 // If typedef is an alias for a union, then its alias type was hoisted above and remembered. 1057 if ( auto unionInstType = typedefDecl->base.as<ast::UnionInstType>() ) { 1058 auto instType = ast::mutate( unionInstType ); 1059 // Remove all transparent_union attributes from typedef and move to alias union. 1060 for ( auto attr = instType->attributes.begin() ; attr != instType->attributes.end() ; ) { 1061 assert( *attr ); 1062 if ( (*attr)->name == "transparent_union" || (*attr)->name == "__transparent_union__" ) { 1063 unionDecl->attributes.emplace_back( attr->release() ); 1064 attr = instType->attributes.erase( attr ); 1065 } else { 1066 attr++; 1067 } 1068 } 1069 typedefDecl->base = instType; 1070 } 1071 } 1072 } 1073 1074 // Get the non-anonymous name of the instance type of the declaration, 1075 // if one exists. 1076 static const std::string * getInstTypeOfName( ast::Decl * decl ) { 1077 if ( auto dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1078 if ( auto aggr = dynamic_cast<ast::BaseInstType const *>( dwt->get_type() ) ) { 1079 if ( aggr->name.find("anonymous") == std::string::npos ) { 1080 return &aggr->name; 1081 } 1082 } 1083 } 1084 return nullptr; 1085 } 1086 1087 void buildList( DeclarationNode * firstNode, 1088 std::vector<ast::ptr<ast::Decl>> & outputList ) { 986 1089 SemanticErrorException errors; 987 std::back_insert_iterator< std::list< Declaration * >> out( outputList );988 989 for ( const DeclarationNode * cur = firstNode ; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next()) ) {1090 std::back_insert_iterator<std::vector<ast::ptr<ast::Decl>>> out( outputList ); 1091 1092 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) { 990 1093 try { 991 bool extracted = false; 992 bool anon = false; 1094 bool extracted_named = false; 1095 ast::UnionDecl * unionDecl = nullptr; 1096 993 1097 if ( DeclarationNode * extr = cur->extractAggregate() ) { 994 // handle the case where a structure declaration is contained within an object or type declaration 995 Declaration * decl = extr->build(); 996 if ( decl ) { 997 // hoist the structure declaration 998 decl->location = cur->location; 999 * out++ = decl; 1098 assert( cur->type ); 1099 nameTypedefedDecl( extr, cur ); 1100 1101 if ( ast::Decl * decl = extr->build() ) { 1102 // Remember the declaration if it is a union aggregate ? 1103 unionDecl = dynamic_cast<ast::UnionDecl *>( decl ); 1104 1105 *out++ = decl; 1000 1106 1001 1107 // need to remember the cases where a declaration contains an anonymous aggregate definition 1002 extracted = true;1003 1108 assert( extr->type ); 1004 1109 if ( extr->type->kind == TypeData::Aggregate ) { 1005 anon = extr->type->aggregate.anon; 1110 // typedef struct { int A } B is the only case? 1111 extracted_named = !extr->type->aggregate.anon; 1006 1112 } else if ( extr->type->kind == TypeData::Enum ) { 1007 // xxx - is it useful to have an implicit anonymous enum member? 1008 anon = extr->type->enumeration.anon; 1113 // typedef enum { A } B is the only case? 1114 extracted_named = !extr->type->enumeration.anon; 1115 } else { 1116 extracted_named = true; 1009 1117 } 1010 1118 } // if … … 1012 1120 } // if 1013 1121 1014 Declaration * decl = cur->build(); 1015 if ( decl ) { 1016 // don't include anonymous declaration for named aggregates, but do include them for anonymous aggregates, e.g.: 1017 // struct S { 1018 // struct T { int x; }; // no anonymous member 1019 // struct { int y; }; // anonymous member 1020 // struct T; // anonymous member 1021 // }; 1022 if ( ! (extracted && decl->name == "" && ! anon && ! cur->get_inLine()) ) { 1023 if ( decl->name == "" ) { 1024 if ( DeclarationWithType * dwt = dynamic_cast<DeclarationWithType *>( decl ) ) { 1025 if ( ReferenceToType * aggr = dynamic_cast<ReferenceToType *>( dwt->get_type() ) ) { 1026 if ( aggr->name.find("anonymous") == std::string::npos ) { 1027 if ( ! cur->get_inLine() ) { 1028 // temporary: warn about anonymous member declarations of named types, since 1029 // this conflicts with the syntax for the forward declaration of an anonymous type 1030 SemanticWarning( cur->location, Warning::AggrForwardDecl, aggr->name.c_str() ); 1031 } // if 1032 } // if 1033 } // if 1034 } // if 1035 } // if 1036 decl->location = cur->location; 1037 *out++ = decl; 1122 if ( ast::Decl * decl = cur->build() ) { 1123 moveUnionAttribute( decl, unionDecl ); 1124 1125 if ( "" == decl->name && !cur->get_inLine() ) { 1126 // Don't include anonymous declaration for named aggregates, 1127 // but do include them for anonymous aggregates, e.g.: 1128 // struct S { 1129 // struct T { int x; }; // no anonymous member 1130 // struct { int y; }; // anonymous member 1131 // struct T; // anonymous member 1132 // }; 1133 if ( extracted_named ) { 1134 continue; 1135 } 1136 1137 if ( auto name = getInstTypeOfName( decl ) ) { 1138 // Temporary: warn about anonymous member declarations of named types, since 1139 // this conflicts with the syntax for the forward declaration of an anonymous type. 1140 SemanticWarning( cur->location, Warning::AggrForwardDecl, name->c_str() ); 1141 } 1038 1142 } // if 1143 *out++ = decl; 1039 1144 } // if 1040 } catch ( SemanticErrorException & e ) {1145 } catch ( SemanticErrorException & e ) { 1041 1146 errors.append( e ); 1042 1147 } // try … … 1049 1154 1050 1155 // currently only builds assertions, function parameters, and return values 1051 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType *> & outputList ) {1156 void buildList( DeclarationNode * firstNode, std::vector<ast::ptr<ast::DeclWithType>> & outputList ) { 1052 1157 SemanticErrorException errors; 1053 std::back_insert_iterator< std::list< DeclarationWithType * >> out( outputList );1054 1055 for ( const DeclarationNode * cur = firstNode; cur; cur = dynamic_cast< DeclarationNode * >( cur->get_next()) ) {1158 std::back_insert_iterator<std::vector<ast::ptr<ast::DeclWithType>>> out( outputList ); 1159 1160 for ( const DeclarationNode * cur = firstNode; cur; cur = strict_next( cur ) ) { 1056 1161 try { 1057 Declaration* decl = cur->build();1058 assert ( decl);1059 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType *>( decl ) ) {1162 ast::Decl * decl = cur->build(); 1163 assertf( decl, "buildList: build for ast::DeclWithType." ); 1164 if ( ast::DeclWithType * dwt = dynamic_cast<ast::DeclWithType *>( decl ) ) { 1060 1165 dwt->location = cur->location; 1061 1166 *out++ = dwt; 1062 } else if ( StructDecl * agg = dynamic_cast< StructDecl *>( decl ) ) {1167 } else if ( ast::StructDecl * agg = dynamic_cast<ast::StructDecl *>( decl ) ) { 1063 1168 // e.g., int foo(struct S) {} 1064 StructInstType * inst = new StructInstType( Type::Qualifiers(),agg->name );1065 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr);1066 obj->l ocation = cur->location;1169 auto inst = new ast::StructInstType( agg->name ); 1170 auto obj = new ast::ObjectDecl( cur->location, "", inst ); 1171 obj->linkage = linkage; 1067 1172 *out++ = obj; 1068 1173 delete agg; 1069 } else if ( UnionDecl * agg = dynamic_cast< UnionDecl *>( decl ) ) {1174 } else if ( ast::UnionDecl * agg = dynamic_cast<ast::UnionDecl *>( decl ) ) { 1070 1175 // e.g., int foo(union U) {} 1071 UnionInstType * inst = new UnionInstType( Type::Qualifiers(), agg->name ); 1072 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr ); 1073 obj->location = cur->location; 1176 auto inst = new ast::UnionInstType( agg->name ); 1177 auto obj = new ast::ObjectDecl( cur->location, 1178 "", inst, nullptr, ast::Storage::Classes(), 1179 linkage ); 1074 1180 *out++ = obj; 1075 } else if ( EnumDecl * agg = dynamic_cast< EnumDecl *>( decl ) ) {1181 } else if ( ast::EnumDecl * agg = dynamic_cast<ast::EnumDecl *>( decl ) ) { 1076 1182 // e.g., int foo(enum E) {} 1077 EnumInstType * inst = new EnumInstType( Type::Qualifiers(), agg->name ); 1078 auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr ); 1079 obj->location = cur->location; 1183 auto inst = new ast::EnumInstType( agg->name ); 1184 auto obj = new ast::ObjectDecl( cur->location, 1185 "", 1186 inst, 1187 nullptr, 1188 ast::Storage::Classes(), 1189 linkage 1190 ); 1080 1191 *out++ = obj; 1192 } else { 1193 assertf( false, "buildList: Could not convert to ast::DeclWithType." ); 1081 1194 } // if 1082 } catch ( SemanticErrorException & e ) {1195 } catch ( SemanticErrorException & e ) { 1083 1196 errors.append( e ); 1084 1197 } // try … … 1090 1203 } // buildList 1091 1204 1092 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList ) { 1205 void buildTypeList( const DeclarationNode * firstNode, 1206 std::vector<ast::ptr<ast::Type>> & outputList ) { 1093 1207 SemanticErrorException errors; 1094 std::back_insert_iterator< std::list< Type * > > out( outputList ); 1095 const DeclarationNode * cur = firstNode; 1096 1097 while ( cur ) { 1208 std::back_insert_iterator<std::vector<ast::ptr<ast::Type>>> out( outputList ); 1209 1210 for ( const DeclarationNode * cur = firstNode ; cur ; cur = strict_next( cur ) ) { 1098 1211 try { 1099 1212 * out++ = cur->buildType(); 1100 } catch ( SemanticErrorException & e ) {1213 } catch ( SemanticErrorException & e ) { 1101 1214 errors.append( e ); 1102 1215 } // try 1103 cur = dynamic_cast< DeclarationNode * >( cur->get_next() ); 1104 } // while 1216 } // for 1105 1217 1106 1218 if ( ! errors.isEmpty() ) { … … 1109 1221 } // buildTypeList 1110 1222 1111 Declaration* DeclarationNode::build() const {1223 ast::Decl * DeclarationNode::build() const { 1112 1224 if ( ! error.empty() ) SemanticError( this, error + " in declaration of " ); 1113 1225 1114 1226 if ( asmStmt ) { 1115 return new AsmDecl( strict_dynamic_cast<AsmStmt *>( asmStmt->build() ) ); 1227 auto stmt = strict_dynamic_cast<ast::AsmStmt *>( asmStmt->build() ); 1228 return new ast::AsmDecl( stmt->location, stmt ); 1116 1229 } // if 1117 1230 if ( directiveStmt ) { 1118 return new DirectiveDecl( strict_dynamic_cast<DirectiveStmt *>( directiveStmt->build() ) ); 1119 } // if 1120 1121 if ( variable.tyClass != TypeDecl::NUMBER_OF_KINDS ) { 1231 auto stmt = strict_dynamic_cast<ast::DirectiveStmt *>( directiveStmt->build() ); 1232 return new ast::DirectiveDecl( stmt->location, stmt ); 1233 } // if 1234 1235 if ( variable.tyClass != ast::TypeDecl::NUMBER_OF_KINDS ) { 1122 1236 // otype is internally converted to dtype + otype parameters 1123 static const TypeDecl::Kind kindMap[] = { TypeDecl::Dtype, TypeDecl::Dtype, TypeDecl::Dtype, TypeDecl::Ftype, TypeDecl::Ttype,TypeDecl::Dimension };1124 static_assert( sizeof(kindMap) / sizeof(kindMap[0]) == TypeDecl::NUMBER_OF_KINDS, "DeclarationNode::build: kindMap is out of sync." );1237 static const ast::TypeDecl::Kind kindMap[] = { ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Dtype, ast::TypeDecl::Ftype, ast::TypeDecl::Ttype, ast::TypeDecl::Dimension }; 1238 static_assert( sizeof(kindMap) / sizeof(kindMap[0]) == ast::TypeDecl::NUMBER_OF_KINDS, "DeclarationNode::build: kindMap is out of sync." ); 1125 1239 assertf( variable.tyClass < sizeof(kindMap)/sizeof(kindMap[0]), "Variable's tyClass is out of bounds." ); 1126 TypeDecl * ret = new TypeDecl( *name, Type::StorageClasses(), nullptr, kindMap[ variable.tyClass ], variable.tyClass == TypeDecl::Otype || variable.tyClass == TypeDecl::DStype, variable.initializer ? variable.initializer->buildType() : nullptr ); 1127 buildList( variable.assertions, ret->get_assertions() ); 1240 ast::TypeDecl * ret = new ast::TypeDecl( location, 1241 *name, 1242 ast::Storage::Classes(), 1243 (ast::Type *)nullptr, 1244 kindMap[ variable.tyClass ], 1245 variable.tyClass == ast::TypeDecl::Otype || variable.tyClass == ast::TypeDecl::DStype, 1246 variable.initializer ? variable.initializer->buildType() : nullptr 1247 ); 1248 buildList( variable.assertions, ret->assertions ); 1128 1249 return ret; 1129 1250 } // if … … 1147 1268 } // if 1148 1269 bool isDelete = initializer && initializer->get_isDelete(); 1149 Declaration * decl = buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, isDelete ? nullptr : maybeBuild< Initializer >(initializer), attributes )->set_extension( extension ); 1270 ast::Decl * decl = buildDecl( 1271 type, 1272 name ? *name : string( "" ), 1273 storageClasses, 1274 maybeBuild( bitfieldWidth ), 1275 funcSpecs, 1276 linkage, 1277 asmName, 1278 isDelete ? nullptr : maybeBuild( initializer ), 1279 copy( attributes ) 1280 )->set_extension( extension ); 1150 1281 if ( isDelete ) { 1151 DeclarationWithType * dwt = strict_dynamic_cast<DeclarationWithType *>( decl );1282 auto dwt = strict_dynamic_cast<ast::DeclWithType *>( decl ); 1152 1283 dwt->isDeleted = true; 1153 1284 } … … 1156 1287 1157 1288 if ( assert.condition ) { 1158 return new StaticAssertDecl( maybeBuild< Expression >( assert.condition ), strict_dynamic_cast< ConstantExpr * >( maybeClone( assert.message ) ) ); 1289 auto cond = maybeBuild( assert.condition ); 1290 auto msg = strict_dynamic_cast<ast::ConstantExpr *>( maybeCopy( assert.message ) ); 1291 return new ast::StaticAssertDecl( location, cond, msg ); 1159 1292 } 1160 1293 … … 1167 1300 } // if 1168 1301 if ( enumInLine ) { 1169 return new InlineMemberDecl( *name, storageClasses, linkage, nullptr ); 1302 return new ast::InlineMemberDecl( location, 1303 *name, (ast::Type*)nullptr, storageClasses, linkage ); 1170 1304 } // if 1171 1305 assertf( name, "ObjectDecl must a have name\n" ); 1172 return (new ObjectDecl( *name, storageClasses, linkage, maybeBuild< Expression >( bitfieldWidth ), nullptr, maybeBuild< Initializer >( initializer ) ))->set_asmName( asmName )->set_extension( extension ); 1173 } 1174 1175 Type * DeclarationNode::buildType() const { 1306 auto ret = new ast::ObjectDecl( location, 1307 *name, 1308 (ast::Type*)nullptr, 1309 maybeBuild( initializer ), 1310 storageClasses, 1311 linkage, 1312 maybeBuild( bitfieldWidth ) 1313 ); 1314 ret->asmName = asmName; 1315 ret->extension = extension; 1316 return ret; 1317 } 1318 1319 ast::Type * DeclarationNode::buildType() const { 1176 1320 assert( type ); 1177 1321 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 1322 switch ( type->kind ) { 1185 case TypeData::Enum: 1186 case TypeData::Aggregate: { 1187 ReferenceToType * ret = buildComAggInst( type, attributes, linkage ); 1188 buildList( type->aggregate.actuals, ret->get_parameters() ); 1189 return ret; 1190 } 1191 case TypeData::Symbolic: { 1192 TypeInstType * ret = new TypeInstType( buildQualifiers( type ), *type->symbolic.name, false, attributes ); 1193 buildList( type->symbolic.actuals, ret->get_parameters() ); 1194 return ret; 1195 } 1196 default: 1197 Type * simpletypes = typebuild( type ); 1198 simpletypes->get_attributes() = attributes; // copy because member is const 1323 case TypeData::Enum: 1324 case TypeData::Aggregate: { 1325 ast::BaseInstType * ret = 1326 buildComAggInst( type, copy( attributes ), linkage ); 1327 buildList( type->aggregate.actuals, ret->params ); 1328 return ret; 1329 } 1330 case TypeData::Symbolic: { 1331 ast::TypeInstType * ret = new ast::TypeInstType( 1332 *type->symbolic.name, 1333 // This is just a default, the true value is not known yet. 1334 ast::TypeDecl::Dtype, 1335 buildQualifiers( type ), 1336 copy( attributes ) ); 1337 buildList( type->symbolic.actuals, ret->params ); 1338 return ret; 1339 } 1340 default: 1341 ast::Type * simpletypes = typebuild( type ); 1342 // copy because member is const 1343 simpletypes->attributes = attributes; 1199 1344 return simpletypes; 1200 1345 } // switch -
src/Parser/ExpressionNode.cc
r2ed94a9 rb110bcc 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat May 16 13:17:07 2015 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Aug 7 09:18:56 2021 13 // Update Count : 1077 14 // 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Apr 4 11:07:00 2023 13 // Update Count : 1083 14 // 15 16 #include "ExpressionNode.h" 15 17 16 18 #include <cassert> // for assert … … 21 23 #include <string> // for string, operator+, operator== 22 24 25 #include "AST/Expr.hpp" // for NameExpr 26 #include "AST/Type.hpp" // for BaseType, SueInstType 23 27 #include "Common/SemanticError.h" // for SemanticError 24 28 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... 25 #include "ParseNode.h" // for ExpressionNode, maybeMoveBuildType 26 #include "SynTree/Constant.h" // for Constant 27 #include "SynTree/Declaration.h" // for EnumDecl, StructDecl, UnionDecl 28 #include "SynTree/Expression.h" // for Expression, ConstantExpr, NameExpr 29 #include "SynTree/Statement.h" // for CompoundStmt, Statement 30 #include "SynTree/Type.h" // for BasicType, Type, Type::Qualifiers 29 #include "DeclarationNode.h" // for DeclarationNode 30 #include "InitializerNode.h" // for InitializerNode 31 31 #include "parserutility.h" // for notZeroExpr 32 33 class Initializer;34 32 35 33 using namespace std; … … 48 46 // because the CONT rule is NOT triggered if the pattern is empty. Hence, constants are reparsed here to determine their 49 47 // type. 50 51 extern const Type::Qualifiers noQualifiers; // no qualifiers on constants52 48 53 49 // static inline bool checkH( char c ) { return c == 'h' || c == 'H'; } … … 71 67 size_t end = str.length() - 1; 72 68 if ( posn == end ) { type = 3; return; } // no length after 'l' => long 73 69 74 70 string::size_type next = posn + 1; // advance to length 75 71 if ( str[next] == '3' ) { // 32 … … 122 118 if ( str[i] == '1' ) v |= 1; 123 119 i += 1; 124 120 if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break; 125 121 v <<= 1; 126 122 } // for 127 123 } // scanbin 128 124 129 Expression * build_constantInteger( string & str ) { 130 static const BasicType::Kind kind[2][6] = { 125 ast::Expr * build_constantInteger( 126 const CodeLocation & location, string & str ) { 127 static const ast::BasicType::Kind kind[2][6] = { 131 128 // short (h) must be before char (hh) because shorter type has the longer suffix 132 { BasicType::ShortSignedInt, BasicType::SignedChar, BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */BasicType::LongLongSignedInt, },133 { BasicType::ShortUnsignedInt, BasicType::UnsignedChar, BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */BasicType::LongLongUnsignedInt, },129 { ast::BasicType::ShortSignedInt, ast::BasicType::SignedChar, ast::BasicType::SignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, /* BasicType::SignedInt128 */ ast::BasicType::LongLongSignedInt, }, 130 { ast::BasicType::ShortUnsignedInt, ast::BasicType::UnsignedChar, ast::BasicType::UnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, /* BasicType::UnsignedInt128 */ ast::BasicType::LongLongUnsignedInt, }, 134 131 }; 135 132 … … 141 138 string str2( "0x0" ); 142 139 unsigned long long int v, v2 = 0; // converted integral value 143 Expression* ret, * ret2;140 ast::Expr * ret, * ret2; 144 141 145 142 int type = -1; // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128 … … 149 146 // special constants 150 147 if ( str == "0" ) { 151 ret = new ConstantExpr( Constant( (Type *)new ZeroType( noQualifiers ), str, (unsigned long long int)0 ));148 ret = new ast::ConstantExpr( location, new ast::ZeroType(), str, 0 ); 152 149 goto CLEANUP; 153 150 } // if 154 151 if ( str == "1" ) { 155 ret = new ConstantExpr( Constant( (Type *)new OneType( noQualifiers ), str, (unsigned long long int)1 ));152 ret = new ast::ConstantExpr( location, new ast::OneType(), str, 1 ); 156 153 goto CLEANUP; 157 154 } // if 158 159 string::size_type posn;160 155 161 156 // 'u' can appear before or after length suffix … … 166 161 } else { 167 162 // At least one digit in integer constant, so safe to backup while looking for suffix. 168 169 posn = str.find_last_of( "pP" ); // pointer value 170 if ( posn != string::npos ) { ltype = 5; str.erase( posn, 1 ); goto FINI; } 171 172 posn = str.find_last_of( "zZ" ); // size_t 173 if ( posn != string::npos ) { Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); goto FINI; } 174 175 posn = str.rfind( "hh" ); // char 176 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; } 177 178 posn = str.rfind( "HH" ); // char 179 if ( posn != string::npos ) { type = 1; str.erase( posn, 2 ); goto FINI; } 180 181 posn = str.find_last_of( "hH" ); // short 182 if ( posn != string::npos ) { type = 0; str.erase( posn, 1 ); goto FINI; } 183 184 posn = str.find_last_of( "nN" ); // int (natural number) 185 if ( posn != string::npos ) { type = 2; str.erase( posn, 1 ); goto FINI; } 186 187 if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { type = 4; goto FINI; } 188 189 lnthSuffix( str, type, ltype ); // must be after check for "ll" 190 FINI: ; 163 // This declaration and the comma expressions in the conditions mimic 164 // the declare and check pattern allowed in later compiler versions. 165 // (Only some early compilers/C++ standards do not support it.) 166 string::size_type posn; 167 // pointer value 168 if ( posn = str.find_last_of( "pP" ), posn != string::npos ) { 169 ltype = 5; str.erase( posn, 1 ); 170 // size_t 171 } else if ( posn = str.find_last_of( "zZ" ), posn != string::npos ) { 172 Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 ); 173 // signed char 174 } else if ( posn = str.rfind( "hh" ), posn != string::npos ) { 175 type = 1; str.erase( posn, 2 ); 176 // signed char 177 } else if ( posn = str.rfind( "HH" ), posn != string::npos ) { 178 type = 1; str.erase( posn, 2 ); 179 // short 180 } else if ( posn = str.find_last_of( "hH" ), posn != string::npos ) { 181 type = 0; str.erase( posn, 1 ); 182 // int (natural number) 183 } else if ( posn = str.find_last_of( "nN" ), posn != string::npos ) { 184 type = 2; str.erase( posn, 1 ); 185 } else if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) { 186 type = 4; 187 } else { 188 lnthSuffix( str, type, ltype ); 189 } // if 191 190 } // if 192 191 … … 196 195 if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target " + str ); 197 196 #endif // ! __SIZEOF_INT128__ 198 197 199 198 if ( str[0] == '0' ) { // radix character ? 200 199 dec = false; … … 206 205 unsigned int len = str.length(); 207 206 if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large " + str ); 208 if ( len <= (2 + 16) ) goto FHEX1; // hex digits < 2^64 209 str2 = "0x" + str.substr( len - 16 ); 210 sscanf( (char *)str2.c_str(), "%llx", &v2 ); 211 str = str.substr( 0, len - 16 ); 212 FHEX1: ; 207 // hex digits < 2^64 208 if ( len > (2 + 16) ) { 209 str2 = "0x" + str.substr( len - 16 ); 210 sscanf( (char *)str2.c_str(), "%llx", &v2 ); 211 str = str.substr( 0, len - 16 ); 212 } // if 213 213 sscanf( (char *)str.c_str(), "%llx", &v ); 214 214 #endif // __SIZEOF_INT128__ … … 301 301 302 302 // Constant type is correct for overload resolving. 303 ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][type] ), str, v ) ); 303 ret = new ast::ConstantExpr( location, 304 new ast::BasicType( kind[Unsigned][type] ), str, v ); 304 305 if ( Unsigned && type < 2 ) { // hh or h, less than int ? 305 306 // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values. 306 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false ); 307 ret = new ast::CastExpr( location, 308 ret, 309 new ast::BasicType( kind[Unsigned][type] ), 310 ast::ExplicitCast ); 307 311 } else if ( ltype != -1 ) { // explicit length ? 308 312 if ( ltype == 6 ) { // int128, (int128)constant 309 // ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[Unsigned][type] ), false ); 310 ret2 = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::LongLongSignedInt ), str2, v2 ) ); 311 ret = build_compoundLiteral( DeclarationNode::newBasicType( DeclarationNode::Int128 )->addType( DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ), 312 new InitializerNode( (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true ) ); 313 ret2 = new ast::ConstantExpr( location, 314 new ast::BasicType( ast::BasicType::LongLongSignedInt ), 315 str2, 316 v2 ); 317 ret = build_compoundLiteral( location, 318 DeclarationNode::newBasicType( 319 DeclarationNode::Int128 320 )->addType( 321 DeclarationNode::newSignedNess( DeclarationNode::Unsigned ) ), 322 new InitializerNode( 323 (InitializerNode *)(new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true ) 324 ); 313 325 } else { // explicit length, (length_type)constant 314 ret = new CastExpr( ret, new TypeInstType( Type::Qualifiers(), lnthsInt[Unsigned][ltype], false ), false ); 326 ret = new ast::CastExpr( location, 327 ret, 328 new ast::TypeInstType( lnthsInt[Unsigned][ltype], ast::TypeDecl::Dtype ), 329 ast::ExplicitCast ); 315 330 if ( ltype == 5 ) { // pointer, intptr( (uintptr_t)constant ) 316 ret = build_func( new ExpressionNode( build_varref( new string( "intptr" ) ) ), new ExpressionNode( ret ) ); 331 ret = build_func( location, 332 new ExpressionNode( 333 build_varref( location, new string( "intptr" ) ) ), 334 new ExpressionNode( ret ) ); 317 335 } // if 318 336 } // if … … 358 376 359 377 360 Expression * build_constantFloat( string & str ) { 361 static const BasicType::Kind kind[2][12] = { 362 { BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128, BasicType::uFloat128x }, 363 { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, BasicType::NUMBER_OF_BASIC_TYPES, BasicType::NUMBER_OF_BASIC_TYPES, BasicType::uFloat16Complex, BasicType::uFloat32Complex, BasicType::uFloat32xComplex, BasicType::uFloat64Complex, BasicType::uFloat64xComplex, BasicType::uFloat128Complex, BasicType::uFloat128xComplex }, 378 ast::Expr * build_constantFloat( 379 const CodeLocation & location, string & str ) { 380 static const ast::BasicType::Kind kind[2][12] = { 381 { ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x }, 382 { ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, ast::BasicType::NUMBER_OF_BASIC_TYPES, ast::BasicType::NUMBER_OF_BASIC_TYPES, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex }, 364 383 }; 365 384 … … 398 417 399 418 assert( 0 <= type && type < 12 ); 400 Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[complx][type] ), str, v ) ); 401 if ( explnth ) { // explicit length ? 402 ret = new CastExpr( ret, new BasicType( Type::Qualifiers(), kind[complx][type] ), false ); 419 ast::Expr * ret = new ast::ConstantExpr( location, 420 new ast::BasicType( kind[complx][type] ), 421 str, 422 v ); 423 // explicit length ? 424 if ( explnth ) { 425 ret = new ast::CastExpr( location, 426 ret, 427 new ast::BasicType( kind[complx][type] ), 428 ast::ExplicitCast ); 403 429 } // if 404 430 … … 415 441 } // sepString 416 442 417 Expression * build_constantChar(string & str ) {443 ast::Expr * build_constantChar( const CodeLocation & location, string & str ) { 418 444 string units; // units 419 445 sepString( str, units, '\'' ); // separate constant from units 420 446 421 Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::Char ), str, (unsigned long long int)(unsigned char)str[1] ) ); 447 ast::Expr * ret = new ast::ConstantExpr( location, 448 new ast::BasicType( ast::BasicType::Char ), 449 str, 450 (unsigned long long int)(unsigned char)str[1] ); 422 451 if ( units.length() != 0 ) { 423 ret = new UntypedExpr( new NameExpr( units ), { ret } ); 452 ret = new ast::UntypedExpr( location, 453 new ast::NameExpr( location, units ), 454 { ret } ); 424 455 } // if 425 456 … … 428 459 } // build_constantChar 429 460 430 Expression * build_constantStr( string & str ) { 461 ast::Expr * build_constantStr( 462 const CodeLocation & location, 463 string & str ) { 431 464 assert( str.length() > 0 ); 432 465 string units; // units 433 466 sepString( str, units, '"' ); // separate constant from units 434 467 435 Type * strtype;468 ast::Type * strtype; 436 469 switch ( str[0] ) { // str has >= 2 characters, i.e, null string "" => safe to look at subscripts 0/1 437 470 case 'u': 438 471 if ( str[1] == '8' ) goto Default; // utf-8 characters => array of char 439 472 // lookup type of associated typedef 440 strtype = new TypeInstType( Type::Qualifiers( ), "char16_t", false );473 strtype = new ast::TypeInstType( "char16_t", ast::TypeDecl::Dtype ); 441 474 break; 442 443 strtype = new TypeInstType( Type::Qualifiers( ), "char32_t", false );475 case 'U': 476 strtype = new ast::TypeInstType( "char32_t", ast::TypeDecl::Dtype ); 444 477 break; 445 446 strtype = new TypeInstType( Type::Qualifiers( ), "wchar_t", false );478 case 'L': 479 strtype = new ast::TypeInstType( "wchar_t", ast::TypeDecl::Dtype ); 447 480 break; 448 449 450 strtype = new BasicType( Type::Qualifiers( ),BasicType::Char );481 Default: // char default string type 482 default: 483 strtype = new ast::BasicType( ast::BasicType::Char ); 451 484 } // switch 452 ArrayType * at = new ArrayType( noQualifiers, strtype, 453 new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"' 454 false, false ); 455 Expression * ret = new ConstantExpr( Constant( at, str, std::nullopt ) ); 485 ast::ArrayType * at = new ast::ArrayType( 486 strtype, 487 // Length is adjusted: +1 for '\0' and -2 for '"' 488 ast::ConstantExpr::from_ulong( location, str.size() + 1 - 2 ), 489 ast::FixedLen, 490 ast::DynamicDim ); 491 ast::Expr * ret = new ast::ConstantExpr( location, at, str, std::nullopt ); 456 492 if ( units.length() != 0 ) { 457 ret = new UntypedExpr( new NameExpr( units ), { ret } ); 493 ret = new ast::UntypedExpr( location, 494 new ast::NameExpr( location, units ), 495 { ret } ); 458 496 } // if 459 497 … … 462 500 } // build_constantStr 463 501 464 Expression * build_field_name_FLOATING_FRACTIONconstant( const string & str ) { 502 ast::Expr * build_field_name_FLOATING_FRACTIONconstant( 503 const CodeLocation & location, const string & str ) { 465 504 if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) SemanticError( yylloc, "invalid tuple index " + str ); 466 Expression * ret = build_constantInteger( *new string( str.substr(1) ) ); 505 ast::Expr * ret = build_constantInteger( location, 506 *new string( str.substr(1) ) ); 467 507 delete &str; 468 508 return ret; 469 509 } // build_field_name_FLOATING_FRACTIONconstant 470 510 471 Expression * build_field_name_FLOATING_DECIMALconstant( const string & str ) { 511 ast::Expr * build_field_name_FLOATING_DECIMALconstant( 512 const CodeLocation & location, const string & str ) { 472 513 if ( str[str.size() - 1] != '.' ) SemanticError( yylloc, "invalid tuple index " + str ); 473 Expression * ret = build_constantInteger( *new string( str.substr( 0, str.size()-1 ) ) ); 514 ast::Expr * ret = build_constantInteger( 515 location, *new string( str.substr( 0, str.size()-1 ) ) ); 474 516 delete &str; 475 517 return ret; 476 518 } // build_field_name_FLOATING_DECIMALconstant 477 519 478 Expression * build_field_name_FLOATINGconstant( const string & str ) { 520 ast::Expr * build_field_name_FLOATINGconstant( const CodeLocation & location, 521 const string & str ) { 479 522 // str is of the form A.B -> separate at the . and return member expression 480 523 int a, b; … … 482 525 stringstream ss( str ); 483 526 ss >> a >> dot >> b; 484 UntypedMemberExpr * ret = new UntypedMemberExpr( new ConstantExpr( Constant::from_int( b ) ), new ConstantExpr( Constant::from_int( a ) ) ); 527 auto ret = new ast::UntypedMemberExpr( location, 528 ast::ConstantExpr::from_int( location, b ), 529 ast::ConstantExpr::from_int( location, a ) 530 ); 485 531 delete &str; 486 532 return ret; 487 533 } // build_field_name_FLOATINGconstant 488 534 489 Expression * make_field_name_fraction_constants( Expression * fieldName, Expression * fracts ) { 490 if ( fracts ) { 491 if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( fracts ) ) { 492 memberExpr->set_member( make_field_name_fraction_constants( fieldName, memberExpr->get_aggregate() ) ); 493 return memberExpr; 494 } else { 495 return new UntypedMemberExpr( fracts, fieldName ); 496 } // if 497 } // if 498 return fieldName; 535 ast::Expr * make_field_name_fraction_constants( const CodeLocation & location, 536 ast::Expr * fieldName, 537 ast::Expr * fracts ) { 538 if ( nullptr == fracts ) { 539 return fieldName; 540 } else if ( auto memberExpr = dynamic_cast<ast::UntypedMemberExpr *>( fracts ) ) { 541 memberExpr->member = make_field_name_fraction_constants( location, 542 fieldName, 543 ast::mutate( memberExpr->aggregate.get() ) ); 544 return memberExpr; 545 } else { 546 return new ast::UntypedMemberExpr( location, fracts, fieldName ); 547 } // if 499 548 } // make_field_name_fraction_constants 500 549 501 Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts ) { 502 return make_field_name_fraction_constants( fieldName, maybeMoveBuild< Expression >( fracts ) ); 550 ast::Expr * build_field_name_fraction_constants( const CodeLocation & location, 551 ast::Expr * fieldName, 552 ExpressionNode * fracts ) { 553 return make_field_name_fraction_constants( location, fieldName, maybeMoveBuild( fracts ) ); 503 554 } // build_field_name_fraction_constants 504 555 505 NameExpr * build_varref( const string * name ) { 506 NameExpr * expr = new NameExpr( *name ); 556 ast::NameExpr * build_varref( const CodeLocation & location, 557 const string * name ) { 558 ast::NameExpr * expr = new ast::NameExpr( location, *name ); 507 559 delete name; 508 560 return expr; 509 561 } // build_varref 510 562 511 QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name ) { 512 Declaration * newDecl = maybeBuild< Declaration >(decl_node); 513 if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) { 514 const Type * t = newDeclWithType->get_type(); 515 if ( t ) { 516 if ( const TypeInstType * typeInst = dynamic_cast<const TypeInstType *>( t ) ) { 517 newDecl= new EnumDecl( typeInst->name ); 563 ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location, 564 const DeclarationNode * decl_node, 565 const ast::NameExpr * name ) { 566 ast::Decl * newDecl = maybeBuild( decl_node ); 567 if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) { 568 if ( const ast::Type * t = newDeclWithType->get_type() ) { 569 if ( auto typeInst = dynamic_cast<const ast::TypeInstType *>( t ) ) { 570 newDecl = new ast::EnumDecl( location, typeInst->name ); 518 571 } 519 572 } 520 573 } 521 return new QualifiedNameExpr(newDecl, name->name );574 return new ast::QualifiedNameExpr( location, newDecl, name->name ); 522 575 } 523 576 524 QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl_node, const NameExpr * name ) { 525 EnumDecl * newDecl = const_cast< EnumDecl * >( decl_node ); 526 return new QualifiedNameExpr( newDecl, name->name ); 577 ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location, 578 const ast::EnumDecl * decl, 579 const ast::NameExpr * name ) { 580 return new ast::QualifiedNameExpr( location, decl, name->name ); 527 581 } 528 582 529 DimensionExpr * build_dimensionref( const string * name ) { 530 DimensionExpr * expr = new DimensionExpr( *name ); 583 ast::DimensionExpr * build_dimensionref( const CodeLocation & location, 584 const string * name ) { 585 ast::DimensionExpr * expr = new ast::DimensionExpr( location, *name ); 531 586 delete name; 532 587 return expr; … … 544 599 }; // OperName 545 600 546 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) { 547 Type * targetType = maybeMoveBuildType( decl_node ); 548 if ( dynamic_cast< VoidType * >( targetType ) ) { 601 ast::Expr * build_cast( const CodeLocation & location, 602 DeclarationNode * decl_node, 603 ExpressionNode * expr_node ) { 604 ast::Type * targetType = maybeMoveBuildType( decl_node ); 605 if ( dynamic_cast<ast::VoidType *>( targetType ) ) { 549 606 delete targetType; 550 return new CastExpr( maybeMoveBuild< Expression >(expr_node), false ); 607 return new ast::CastExpr( location, 608 maybeMoveBuild( expr_node ), 609 ast::ExplicitCast ); 551 610 } else { 552 return new CastExpr( maybeMoveBuild< Expression >(expr_node), targetType, false ); 611 return new ast::CastExpr( location, 612 maybeMoveBuild( expr_node ), 613 targetType, 614 ast::ExplicitCast ); 553 615 } // if 554 616 } // build_cast 555 617 556 Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node ) { 557 return new KeywordCastExpr( maybeMoveBuild< Expression >(expr_node), target ); 618 ast::Expr * build_keyword_cast( const CodeLocation & location, 619 ast::AggregateDecl::Aggregate target, 620 ExpressionNode * expr_node ) { 621 return new ast::KeywordCastExpr( location, 622 maybeMoveBuild( expr_node ), 623 target 624 ); 558 625 } 559 626 560 Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) { 561 return new VirtualCastExpr( maybeMoveBuild< Expression >( expr_node ), maybeMoveBuildType( decl_node ) ); 627 ast::Expr * build_virtual_cast( const CodeLocation & location, 628 DeclarationNode * decl_node, 629 ExpressionNode * expr_node ) { 630 return new ast::VirtualCastExpr( location, 631 maybeMoveBuild( expr_node ), 632 maybeMoveBuildType( decl_node ) 633 ); 562 634 } // build_virtual_cast 563 635 564 Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member ) { 565 return new UntypedMemberExpr( member, maybeMoveBuild< Expression >(expr_node) ); 636 ast::Expr * build_fieldSel( const CodeLocation & location, 637 ExpressionNode * expr_node, 638 ast::Expr * member ) { 639 return new ast::UntypedMemberExpr( location, 640 member, 641 maybeMoveBuild( expr_node ) 642 ); 566 643 } // build_fieldSel 567 644 568 Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member ) { 569 UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) ); 645 ast::Expr * build_pfieldSel( const CodeLocation & location, 646 ExpressionNode * expr_node, 647 ast::Expr * member ) { 648 auto deref = new ast::UntypedExpr( location, 649 new ast::NameExpr( location, "*?" ) 650 ); 570 651 deref->location = expr_node->location; 571 deref-> get_args().push_back( maybeMoveBuild< Expression >(expr_node) );572 UntypedMemberExpr * ret = new UntypedMemberExpr(member, deref );652 deref->args.push_back( maybeMoveBuild( expr_node ) ); 653 auto ret = new ast::UntypedMemberExpr( location, member, deref ); 573 654 return ret; 574 655 } // build_pfieldSel 575 656 576 Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member ) { 577 Expression * ret = new UntypedOffsetofExpr( maybeMoveBuildType( decl_node ), member->get_name() ); 657 ast::Expr * build_offsetOf( const CodeLocation & location, 658 DeclarationNode * decl_node, 659 ast::NameExpr * member ) { 660 ast::Expr * ret = new ast::UntypedOffsetofExpr( location, 661 maybeMoveBuildType( decl_node ), 662 member->name 663 ); 664 ret->result = new ast::BasicType( ast::BasicType::LongUnsignedInt ); 578 665 delete member; 579 666 return ret; 580 667 } // build_offsetOf 581 668 582 Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind ) { 583 return new LogicalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), notZeroExpr( maybeMoveBuild< Expression >(expr_node2) ), kind ); 669 ast::Expr * build_and_or( const CodeLocation & location, 670 ExpressionNode * expr_node1, 671 ExpressionNode * expr_node2, 672 ast::LogicalFlag flag ) { 673 return new ast::LogicalExpr( location, 674 notZeroExpr( maybeMoveBuild( expr_node1 ) ), 675 notZeroExpr( maybeMoveBuild( expr_node2 ) ), 676 flag 677 ); 584 678 } // build_and_or 585 679 586 Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node ) { 587 list< Expression * > args; 588 args.push_back( maybeMoveBuild< Expression >(expr_node) ); 589 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); 680 ast::Expr * build_unary_val( const CodeLocation & location, 681 OperKinds op, 682 ExpressionNode * expr_node ) { 683 std::vector<ast::ptr<ast::Expr>> args; 684 args.push_back( maybeMoveBuild( expr_node ) ); 685 return new ast::UntypedExpr( location, 686 new ast::NameExpr( location, OperName[ (int)op ] ), 687 std::move( args ) 688 ); 590 689 } // build_unary_val 591 690 592 Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) { 593 list< Expression * > args;594 args.push_back( maybeMoveBuild< Expression >(expr_node) ); // xxx -- this is exactly the same as the val case now, refactor this code.595 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );596 } // build_unary_ptr 597 598 Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) { 599 list< Expression * > args;600 args.push_back( maybeMoveBuild< Expression >(expr_node1) );601 args.push_back( maybeMoveBuild< Expression >(expr_node2) );602 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args);691 ast::Expr * build_binary_val( const CodeLocation & location, 692 OperKinds op, 693 ExpressionNode * expr_node1, 694 ExpressionNode * expr_node2 ) { 695 std::vector<ast::ptr<ast::Expr>> args; 696 args.push_back( maybeMoveBuild( expr_node1 ) ); 697 args.push_back( maybeMoveBuild( expr_node2 ) ); 698 return new ast::UntypedExpr( location, 699 new ast::NameExpr( location, OperName[ (int)op ] ), 700 std::move( args ) 701 ); 603 702 } // build_binary_val 604 703 605 Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) { 606 list< Expression * > args;607 args.push_back( maybeMoveBuild< Expression >(expr_node1) );608 args.push_back( maybeMoveBuild< Expression >(expr_node2) );609 return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args );610 } // build_binary_ptr 611 612 Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 ) { 613 return new ConditionalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), maybeMoveBuild< Expression >(expr_node2), maybeMoveBuild< Expression >(expr_node3));704 ast::Expr * build_cond( const CodeLocation & location, 705 ExpressionNode * expr_node1, 706 ExpressionNode * expr_node2, 707 ExpressionNode * expr_node3 ) { 708 return new ast::ConditionalExpr( location, 709 notZeroExpr( maybeMoveBuild( expr_node1 ) ), 710 maybeMoveBuild( expr_node2 ), 711 maybeMoveBuild( expr_node3 ) 712 ); 614 713 } // build_cond 615 714 616 Expression * build_tuple( ExpressionNode * expr_node ) { 617 list< Expression * > exprs; 715 ast::Expr * build_tuple( const CodeLocation & location, 716 ExpressionNode * expr_node ) { 717 std::vector<ast::ptr<ast::Expr>> exprs; 618 718 buildMoveList( expr_node, exprs ); 619 return new UntypedTupleExpr( exprs );;719 return new ast::UntypedTupleExpr( location, std::move( exprs ) ); 620 720 } // build_tuple 621 721 622 Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node ) { 623 list< Expression * > args; 722 ast::Expr * build_func( const CodeLocation & location, 723 ExpressionNode * function, 724 ExpressionNode * expr_node ) { 725 std::vector<ast::ptr<ast::Expr>> args; 624 726 buildMoveList( expr_node, args ); 625 return new UntypedExpr( maybeMoveBuild< Expression >(function), args ); 727 return new ast::UntypedExpr( location, 728 maybeMoveBuild( function ), 729 std::move( args ) 730 ); 626 731 } // build_func 627 732 628 Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids ) { 629 Declaration * newDecl = maybeBuild< Declaration >(decl_node); // compound literal type 630 if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) { // non-sue compound-literal type 631 return new CompoundLiteralExpr( newDeclWithType->get_type(), maybeMoveBuild< Initializer >(kids) ); 733 ast::Expr * build_compoundLiteral( const CodeLocation & location, 734 DeclarationNode * decl_node, 735 InitializerNode * kids ) { 736 // compound literal type 737 ast::Decl * newDecl = maybeBuild( decl_node ); 738 // non-sue compound-literal type 739 if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) { 740 return new ast::CompoundLiteralExpr( location, 741 newDeclWithType->get_type(), 742 maybeMoveBuild( kids ) ); 632 743 // these types do not have associated type information 633 } else if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( newDecl ) ) { 634 if ( newDeclStructDecl->has_body() ) { 635 return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl ), maybeMoveBuild< Initializer >(kids) ); 744 } else if ( auto newDeclStructDecl = dynamic_cast<ast::StructDecl *>( newDecl ) ) { 745 if ( newDeclStructDecl->body ) { 746 return new ast::CompoundLiteralExpr( location, 747 new ast::StructInstType( newDeclStructDecl ), 748 maybeMoveBuild( kids ) ); 636 749 } else { 637 return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 638 } // if 639 } else if ( UnionDecl * newDeclUnionDecl = dynamic_cast< UnionDecl * >( newDecl ) ) { 640 if ( newDeclUnionDecl->has_body() ) { 641 return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl ), maybeMoveBuild< Initializer >(kids) ); 750 return new ast::CompoundLiteralExpr( location, 751 new ast::StructInstType( newDeclStructDecl->name ), 752 maybeMoveBuild( kids ) ); 753 } // if 754 } else if ( auto newDeclUnionDecl = dynamic_cast<ast::UnionDecl *>( newDecl ) ) { 755 if ( newDeclUnionDecl->body ) { 756 return new ast::CompoundLiteralExpr( location, 757 new ast::UnionInstType( newDeclUnionDecl ), 758 maybeMoveBuild( kids ) ); 642 759 } else { 643 return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 644 } // if 645 } else if ( EnumDecl * newDeclEnumDecl = dynamic_cast< EnumDecl * >( newDecl ) ) { 646 if ( newDeclEnumDecl->has_body() ) { 647 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl ), maybeMoveBuild< Initializer >(kids) ); 760 return new ast::CompoundLiteralExpr( location, 761 new ast::UnionInstType( newDeclUnionDecl->name ), 762 maybeMoveBuild( kids ) ); 763 } // if 764 } else if ( auto newDeclEnumDecl = dynamic_cast<ast::EnumDecl *>( newDecl ) ) { 765 if ( newDeclEnumDecl->body ) { 766 return new ast::CompoundLiteralExpr( location, 767 new ast::EnumInstType( newDeclEnumDecl ), 768 maybeMoveBuild( kids ) ); 648 769 } else { 649 return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); 770 return new ast::CompoundLiteralExpr( location, 771 new ast::EnumInstType( newDeclEnumDecl->name ), 772 maybeMoveBuild( kids ) ); 650 773 } // if 651 774 } else { … … 656 779 // Local Variables: // 657 780 // tab-width: 4 // 658 // mode: c++ //659 // compile-command: "make install" //660 781 // End: // -
src/Parser/InitializerNode.cc
r2ed94a9 rb110bcc 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 13:20:24 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Jul 28 23:27:20 201713 // Update Count : 2 611 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Apr 4 11:18:00 2023 13 // Update Count : 27 14 14 // 15 16 #include "InitializerNode.h" 15 17 16 18 #include <iostream> // for operator<<, ostream, basic_ostream … … 18 20 #include <string> // for operator<<, string 19 21 22 #include "AST/Expr.hpp" // for Expr 23 #include "AST/Init.hpp" // for Designator, Init, ListInit, Sing... 24 #include "Common/SemanticError.h" // for SemanticError 25 #include "Common/utility.h" // for maybeBuild 26 #include "ExpressionNode.h" // for ExpressionNode 27 #include "DeclarationNode.h" // for buildList 28 20 29 using namespace std; 21 30 22 #include "Common/SemanticError.h" // for SemanticError 23 #include "Common/utility.h" // for maybeBuild 24 #include "ParseNode.h" // for InitializerNode, ExpressionNode 25 #include "SynTree/Expression.h" // for Expression 26 #include "SynTree/Initializer.h" // for Initializer, ListInit, SingleInit 31 static ast::ConstructFlag toConstructFlag( bool maybeConstructed ) { 32 return maybeConstructed ? ast::MaybeConstruct : ast::NoConstruct; 33 } 27 34 28 35 InitializerNode::InitializerNode( ExpressionNode * _expr, bool aggrp, ExpressionNode * des ) … … 33 40 if ( kids ) 34 41 set_last( nullptr ); 35 } // InitializerNode::InitializerNode 42 } // InitializerNode::InitializerNode 36 43 37 44 InitializerNode::InitializerNode( InitializerNode * init, bool aggrp, ExpressionNode * des ) … … 85 92 } // InitializerNode::printOneLine 86 93 87 Initializer* InitializerNode::build() const {94 ast::Init * InitializerNode::build() const { 88 95 assertf( ! isDelete, "Should not build delete stmt InitializerNode" ); 89 96 if ( aggregate ) { 90 97 // steal designators from children 91 std:: list< Designation *> designlist;98 std::vector<ast::ptr<ast::Designation>> designlist; 92 99 InitializerNode * child = next_init(); 93 for ( ; child != nullptr; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) { 94 std::list< Expression * > desList; 95 buildList< Expression, ExpressionNode >( child->designator, desList ); 96 designlist.push_back( new Designation( desList ) ); 100 for ( ; child != nullptr ; child = dynamic_cast< InitializerNode * >( child->get_next() ) ) { 101 std::deque<ast::ptr<ast::Expr>> desList; 102 buildList( child->designator, desList ); 103 designlist.push_back( 104 new ast::Designation( location, std::move( desList ) ) ); 97 105 } // for 98 std::list< Initializer * > initlist; 99 buildList< Initializer, InitializerNode >( next_init(), initlist ); 100 return new ListInit( initlist, designlist, maybeConstructed ); 101 } else { 102 if ( get_expression() ) { 103 assertf( get_expression()->expr, "The expression of initializer must have value" ); 104 return new SingleInit( maybeBuild< Expression >( get_expression() ), maybeConstructed ); 105 } // if 106 std::vector<ast::ptr<ast::Init>> initlist; 107 buildList( next_init(), initlist ); 108 return new ast::ListInit( location, 109 std::move( initlist ), 110 std::move( designlist ), 111 toConstructFlag( maybeConstructed ) 112 ); 113 } else if ( get_expression() ) { 114 assertf( get_expression()->expr, "The expression of initializer must have value" ); 115 return new ast::SingleInit( location, 116 maybeBuild( get_expression() ), 117 toConstructFlag( maybeConstructed ) 118 ); 106 119 } // if 107 120 return nullptr; -
src/Parser/ParseNode.h
r2ed94a9 rb110bcc 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 13:28:16 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Nov 2 21:27:07 202213 // Update Count : 9 3911 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Apr 3 17:55:00 2023 13 // Update Count : 942 14 14 // 15 15 … … 24 24 #include <string> // for string 25 25 26 #include "AST/Expr.hpp" // for Expr, NameExpr LogicalFlag 27 #include "AST/Fwd.hpp" // for ptr, Decl, DeclWithType, 28 #include "AST/Stmt.hpp" // for Stmt 26 29 #include "Common/CodeLocation.h" // for CodeLocation 27 30 #include "Common/SemanticError.h" // for SemanticError 28 31 #include "Common/UniqueName.h" // for UniqueName 29 #include "Common/utility.h" // for maybeClone, maybeBuild 30 #include "SynTree/LinkageSpec.h" // for Spec 31 #include "SynTree/Declaration.h" // for Aggregate 32 #include "SynTree/Expression.h" // for Expression, ConstantExpr (ptr only) 33 #include "SynTree/Label.h" // for Label 34 #include "SynTree/Statement.h" // for Statement, BranchStmt, BranchStmt:... 35 #include "SynTree/Type.h" // for Type, Type::FuncSpecifiers, Type::... 32 #include "Common/utility.h" // for maybeClone 33 #include "Parser/parserutility.h" // for maybeBuild, maybeCopy 36 34 37 35 class Attribute; … … 40 38 class DeclarationWithType; 41 39 class Initializer; 40 class InitializerNode; 42 41 class ExpressionNode; 43 42 struct StatementNode; … … 82 81 }; // ParseNode 83 82 84 //##############################################################################85 86 class InitializerNode : public ParseNode {87 public:88 InitializerNode( ExpressionNode *, bool aggrp = false, ExpressionNode * des = nullptr );89 InitializerNode( InitializerNode *, bool aggrp = false, ExpressionNode * des = nullptr );90 InitializerNode( bool isDelete );91 ~InitializerNode();92 virtual InitializerNode * clone() const { assert( false ); return nullptr; }93 94 ExpressionNode * get_expression() const { return expr; }95 96 InitializerNode * set_designators( ExpressionNode * des ) { designator = des; return this; }97 ExpressionNode * get_designators() const { return designator; }98 99 InitializerNode * set_maybeConstructed( bool value ) { maybeConstructed = value; return this; }100 bool get_maybeConstructed() const { return maybeConstructed; }101 102 bool get_isDelete() const { return isDelete; }103 104 InitializerNode * next_init() const { return kids; }105 106 void print( std::ostream & os, int indent = 0 ) const;107 void printOneLine( std::ostream & ) const;108 109 virtual Initializer * build() const;110 private:111 ExpressionNode * expr;112 bool aggregate;113 ExpressionNode * designator; // may be list114 InitializerNode * kids;115 bool maybeConstructed;116 bool isDelete;117 }; // InitializerNode118 119 //##############################################################################120 121 class ExpressionNode final : public ParseNode {122 public:123 ExpressionNode( Expression * expr = nullptr ) : expr( expr ) {}124 virtual ~ExpressionNode() {}125 virtual ExpressionNode * clone() const override { return expr ? static_cast<ExpressionNode*>((new ExpressionNode( expr->clone() ))->set_next( maybeClone( get_next() ) )) : nullptr; }126 127 bool get_extension() const { return extension; }128 ExpressionNode * set_extension( bool exten ) { extension = exten; return this; }129 130 virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {131 os << expr.get();132 }133 void printOneLine( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const {}134 135 template<typename T>136 bool isExpressionType() const { return nullptr != dynamic_cast<T>(expr.get()); }137 138 Expression * build() const { return const_cast<ExpressionNode *>(this)->expr.release(); }139 140 std::unique_ptr<Expression> expr; // public because of lifetime implications141 private:142 bool extension = false;143 }; // ExpressionNode144 145 template< typename T >146 struct maybeBuild_t< Expression, T > {147 static inline Expression * doit( const T * orig ) {148 if ( orig ) {149 Expression * p = orig->build();150 p->set_extension( orig->get_extension() );151 p->location = orig->location;152 return p;153 } else {154 return nullptr;155 } // if156 }157 };158 159 83 // Must harmonize with OperName. 160 84 enum class OperKinds { … … 172 96 173 97 struct LabelNode { 174 std:: list< Label> labels;98 std::vector<ast::Label> labels; 175 99 }; 176 100 177 Expression * build_constantInteger( std::string & str ); // these 4 routines modify the string178 Expression * build_constantFloat( std::string & str );179 Expression * build_constantChar( std::string & str );180 Expression * build_constantStr( std::string & str );181 Expression * build_field_name_FLOATING_FRACTIONconstant( const std::string & str );182 Expression * build_field_name_FLOATING_DECIMALconstant( const std::string & str );183 Expression * build_field_name_FLOATINGconstant( const std::string & str );184 Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts );185 186 NameExpr * build_varref( const std::string * name );187 QualifiedNameExpr * build_qualified_expr( const DeclarationNode * decl_node, const NameExpr * name );188 QualifiedNameExpr * build_qualified_expr( const EnumDecl * decl, const NameExpr * name );189 DimensionExpr * build_dimensionref( const std::string * name );190 191 Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node );192 Expression * build_keyword_cast( AggregateDecl::Aggregate target, ExpressionNode * expr_node );193 Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node );194 Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member );195 Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member );196 Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member );197 Expression * build_and( ExpressionNode * expr_node1, ExpressionNode * expr_node2 );198 Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind );199 Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node );200 Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node );201 Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );202 Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 );203 Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 );204 Expression * build_tuple( ExpressionNode * expr_node = nullptr );205 Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node );206 Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids );207 208 //##############################################################################209 210 struct TypeData;211 212 struct DeclarationNode : public ParseNode {213 // These enumerations must harmonize with their names in DeclarationNode.cc.214 enum BasicType { Void, Bool, Char, Int, Int128,215 Float, Double, LongDouble, uuFloat80, uuFloat128,216 uFloat16, uFloat32, uFloat32x, uFloat64, uFloat64x, uFloat128, uFloat128x, NoBasicType };217 static const char * basicTypeNames[];218 enum ComplexType { Complex, NoComplexType, Imaginary }; // Imaginary unsupported => parse, but make invisible and print error message219 static const char * complexTypeNames[];220 enum Signedness { Signed, Unsigned, NoSignedness };221 static const char * signednessNames[];222 enum Length { Short, Long, LongLong, NoLength };223 static const char * lengthNames[];224 enum BuiltinType { Valist, AutoType, Zero, One, NoBuiltinType };225 static const char * builtinTypeNames[];226 227 static DeclarationNode * newStorageClass( Type::StorageClasses );228 static DeclarationNode * newFuncSpecifier( Type::FuncSpecifiers );229 static DeclarationNode * newTypeQualifier( Type::Qualifiers );230 static DeclarationNode * newBasicType( BasicType );231 static DeclarationNode * newComplexType( ComplexType );232 static DeclarationNode * newSignedNess( Signedness );233 static DeclarationNode * newLength( Length );234 static DeclarationNode * newBuiltinType( BuiltinType );235 static DeclarationNode * newForall( DeclarationNode * );236 static DeclarationNode * newFromTypedef( const std::string * );237 static DeclarationNode * newFromGlobalScope();238 static DeclarationNode * newQualifiedType( DeclarationNode *, DeclarationNode * );239 static DeclarationNode * newFunction( const std::string * name, DeclarationNode * ret, DeclarationNode * param, StatementNode * body );240 static DeclarationNode * newAggregate( AggregateDecl::Aggregate kind, const std::string * name, ExpressionNode * actuals, DeclarationNode * fields, bool body );241 static DeclarationNode * newEnum( const std::string * name, DeclarationNode * constants, bool body, bool typed, DeclarationNode * base = nullptr, EnumHiding hiding = EnumHiding::Visible );242 static DeclarationNode * newEnumConstant( const std::string * name, ExpressionNode * constant );243 static DeclarationNode * newEnumValueGeneric( const std::string * name, InitializerNode * init );244 static DeclarationNode * newEnumInLine( const std::string name );245 static DeclarationNode * newName( const std::string * );246 static DeclarationNode * newFromTypeGen( const std::string *, ExpressionNode * params );247 static DeclarationNode * newTypeParam( TypeDecl::Kind, const std::string * );248 static DeclarationNode * newTrait( const std::string * name, DeclarationNode * params, DeclarationNode * asserts );249 static DeclarationNode * newTraitUse( const std::string * name, ExpressionNode * params );250 static DeclarationNode * newTypeDecl( const std::string * name, DeclarationNode * typeParams );251 static DeclarationNode * newPointer( DeclarationNode * qualifiers, OperKinds kind );252 static DeclarationNode * newArray( ExpressionNode * size, DeclarationNode * qualifiers, bool isStatic );253 static DeclarationNode * newVarArray( DeclarationNode * qualifiers );254 static DeclarationNode * newBitfield( ExpressionNode * size );255 static DeclarationNode * newTuple( DeclarationNode * members );256 static DeclarationNode * newTypeof( ExpressionNode * expr, bool basetypeof = false );257 static DeclarationNode * newVtableType( DeclarationNode * expr );258 static DeclarationNode * newAttribute( const std::string *, ExpressionNode * expr = nullptr ); // gcc attributes259 static DeclarationNode * newDirectiveStmt( StatementNode * stmt ); // gcc external directive statement260 static DeclarationNode * newAsmStmt( StatementNode * stmt ); // gcc external asm statement261 static DeclarationNode * newStaticAssert( ExpressionNode * condition, Expression * message );262 263 DeclarationNode();264 ~DeclarationNode();265 DeclarationNode * clone() const override;266 267 DeclarationNode * addQualifiers( DeclarationNode * );268 void checkQualifiers( const TypeData *, const TypeData * );269 void checkSpecifiers( DeclarationNode * );270 DeclarationNode * copySpecifiers( DeclarationNode * );271 DeclarationNode * addType( DeclarationNode * );272 DeclarationNode * addTypedef();273 DeclarationNode * addEnumBase( DeclarationNode * );274 DeclarationNode * addAssertions( DeclarationNode * );275 DeclarationNode * addName( std::string * );276 DeclarationNode * addAsmName( DeclarationNode * );277 DeclarationNode * addBitfield( ExpressionNode * size );278 DeclarationNode * addVarArgs();279 DeclarationNode * addFunctionBody( StatementNode * body, ExpressionNode * with = nullptr );280 DeclarationNode * addOldDeclList( DeclarationNode * list );281 DeclarationNode * setBase( TypeData * newType );282 DeclarationNode * copyAttribute( DeclarationNode * attr );283 DeclarationNode * addPointer( DeclarationNode * qualifiers );284 DeclarationNode * addArray( DeclarationNode * array );285 DeclarationNode * addNewPointer( DeclarationNode * pointer );286 DeclarationNode * addNewArray( DeclarationNode * array );287 DeclarationNode * addParamList( DeclarationNode * list );288 DeclarationNode * addIdList( DeclarationNode * list ); // old-style functions289 DeclarationNode * addInitializer( InitializerNode * init );290 DeclarationNode * addTypeInitializer( DeclarationNode * init );291 292 DeclarationNode * cloneType( std::string * newName );293 DeclarationNode * cloneBaseType( DeclarationNode * newdecl );294 295 DeclarationNode * appendList( DeclarationNode * node ) {296 return (DeclarationNode *)set_last( node );297 }298 299 virtual void print( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;300 virtual void printList( __attribute__((unused)) std::ostream & os, __attribute__((unused)) int indent = 0 ) const override;301 302 Declaration * build() const;303 Type * buildType() const;304 305 LinkageSpec::Spec get_linkage() const { return linkage; }306 DeclarationNode * extractAggregate() const;307 bool has_enumeratorValue() const { return (bool)enumeratorValue; }308 ExpressionNode * consume_enumeratorValue() const { return const_cast<DeclarationNode *>(this)->enumeratorValue.release(); }309 310 bool get_extension() const { return extension; }311 DeclarationNode * set_extension( bool exten ) { extension = exten; return this; }312 313 bool get_inLine() const { return inLine; }314 DeclarationNode * set_inLine( bool inL ) { inLine = inL; return this; }315 316 DeclarationNode * get_last() { return (DeclarationNode *)ParseNode::get_last(); }317 318 struct Variable_t {319 // const std::string * name;320 TypeDecl::Kind tyClass;321 DeclarationNode * assertions;322 DeclarationNode * initializer;323 };324 Variable_t variable;325 326 struct Attr_t {327 // const std::string * name;328 ExpressionNode * expr;329 DeclarationNode * type;330 };331 Attr_t attr;332 333 struct StaticAssert_t {334 ExpressionNode * condition;335 Expression * message;336 };337 StaticAssert_t assert;338 339 BuiltinType builtin = NoBuiltinType;340 341 TypeData * type = nullptr;342 343 bool inLine = false;344 bool enumInLine = false;345 Type::FuncSpecifiers funcSpecs;346 Type::StorageClasses storageClasses;347 348 ExpressionNode * bitfieldWidth = nullptr;349 std::unique_ptr<ExpressionNode> enumeratorValue;350 bool hasEllipsis = false;351 LinkageSpec::Spec linkage;352 Expression * asmName = nullptr;353 std::list< Attribute * > attributes;354 InitializerNode * initializer = nullptr;355 bool extension = false;356 std::string error;357 StatementNode * asmStmt = nullptr;358 StatementNode * directiveStmt = nullptr;359 360 static UniqueName anonymous;361 }; // DeclarationNode362 363 Type * buildType( TypeData * type );364 365 static inline Type * maybeMoveBuildType( const DeclarationNode * orig ) {366 Type * ret = orig ? orig->buildType() : nullptr;367 delete orig;368 return ret;369 }370 371 //##############################################################################372 373 struct StatementNode final : public ParseNode {374 StatementNode() { stmt = nullptr; }375 StatementNode( Statement * stmt ) : stmt( stmt ) {}376 StatementNode( DeclarationNode * decl );377 virtual ~StatementNode() {}378 379 virtual StatementNode * clone() const final { assert( false ); return nullptr; }380 Statement * build() const { return const_cast<StatementNode *>(this)->stmt.release(); }381 382 virtual StatementNode * add_label( const std::string * name, DeclarationNode * attr = nullptr ) {383 stmt->get_labels().emplace_back( * name, nullptr, attr ? std::move( attr->attributes ) : std::list< Attribute * > {} );384 delete attr;385 delete name;386 return this;387 }388 389 virtual StatementNode * append_last_case( StatementNode * );390 391 virtual void print( std::ostream & os, __attribute__((unused)) int indent = 0 ) const override {392 os << stmt.get() << std::endl;393 }394 395 std::unique_ptr<Statement> stmt;396 }; // StatementNode397 398 Statement * build_expr( ExpressionNode * ctl );399 400 struct CondCtl {401 CondCtl( DeclarationNode * decl, ExpressionNode * condition ) :402 init( decl ? new StatementNode( decl ) : nullptr ), condition( condition ) {}403 404 StatementNode * init;405 ExpressionNode * condition;406 };407 408 struct ForCtrl {409 ForCtrl( ExpressionNode * expr, ExpressionNode * condition, ExpressionNode * change ) :410 init( new StatementNode( build_expr( expr ) ) ), condition( condition ), change( change ) {}411 ForCtrl( DeclarationNode * decl, ExpressionNode * condition, ExpressionNode * change ) :412 init( new StatementNode( decl ) ), condition( condition ), change( change ) {}413 414 StatementNode * init;415 ExpressionNode * condition;416 ExpressionNode * change;417 };418 419 Expression * build_if_control( CondCtl * ctl, std::list< Statement * > & init );420 Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ );421 Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );422 Statement * build_case( ExpressionNode * ctl );423 Statement * build_default();424 Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );425 Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );426 Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ = nullptr );427 Statement * build_branch( BranchStmt::Type kind );428 Statement * build_branch( std::string * identifier, BranchStmt::Type kind );429 Statement * build_computedgoto( ExpressionNode * ctl );430 Statement * build_return( ExpressionNode * ctl );431 Statement * build_throw( ExpressionNode * ctl );432 Statement * build_resume( ExpressionNode * ctl );433 Statement * build_resume_at( ExpressionNode * ctl , ExpressionNode * target );434 Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ );435 Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body );436 Statement * build_finally( StatementNode * stmt );437 Statement * build_compound( StatementNode * first );438 StatementNode * maybe_build_compound( StatementNode * first );439 Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output = nullptr, ExpressionNode * input = nullptr, ExpressionNode * clobber = nullptr, LabelNode * gotolabels = nullptr );440 Statement * build_directive( std::string * directive );441 SuspendStmt * build_suspend( StatementNode *, SuspendStmt::Type = SuspendStmt::None);442 WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when );443 WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when, WaitForStmt * existing );444 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when );445 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_stmt, ExpressionNode * else_when );446 Statement * build_with( ExpressionNode * exprs, StatementNode * stmt );447 Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt );448 449 //##############################################################################450 451 template< typename SynTreeType, typename NodeType, template< typename, typename...> class Container, typename... Args >452 void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > & outputList ) {453 SemanticErrorException errors;454 std::back_insert_iterator< Container< SynTreeType *, Args... > > out( outputList );455 const NodeType * cur = firstNode;456 457 while ( cur ) {458 try {459 SynTreeType * result = dynamic_cast< SynTreeType * >( maybeBuild< typename std::pointer_traits< decltype(cur->build())>::element_type >( cur ) );460 if ( result ) {461 result->location = cur->location;462 * out++ = result;463 } else {464 SemanticError( cur->location, "type specifier declaration in forall clause is currently unimplemented." );465 } // if466 } catch( SemanticErrorException & e ) {467 errors.append( e );468 } // try469 const ParseNode * temp = (cur->get_next());470 cur = dynamic_cast< const NodeType * >( temp ); // should not return nullptr471 if ( ! cur && temp ) { // non-homogeneous nodes ?472 SemanticError( temp->location, "internal error, non-homogeneous nodes founds in buildList processing." );473 } // if474 } // while475 if ( ! errors.isEmpty() ) {476 throw errors;477 } // if478 }479 480 // in DeclarationNode.cc481 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > & outputList );482 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > & outputList );483 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > & outputList );484 485 template< typename SynTreeType, typename NodeType >486 void buildMoveList( const NodeType * firstNode, std::list< SynTreeType * > & outputList ) {487 buildList( firstNode, outputList );488 delete firstNode;489 }490 491 // in ParseNode.cc492 101 std::ostream & operator<<( std::ostream & out, const ParseNode * node ); 493 102 -
src/Parser/ParserTypes.h
r2ed94a9 rb110bcc 4 4 // The contents of this file are covered under the licence agreement in the 5 5 // file "LICENCE" distributed with Cforall. 6 // 7 // parser.hh -- 8 // 6 // 7 // parser.hh -- 8 // 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat Sep 22 08:58:10 2001 -
src/Parser/RunParser.cpp
r2ed94a9 rb110bcc 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 : Mon Mar 6 9:42:00 2023 13 // Update Count : 3 14 14 // 15 15 … … 20 20 #include "CodeTools/TrackLoc.h" // for fillLocations 21 21 #include "Common/CodeLocationTools.hpp" // for forceFillCodeLocations 22 #include "Parser/ ParseNode.h"// for DeclarationNode, buildList22 #include "Parser/DeclarationNode.h" // for DeclarationNode, buildList 23 23 #include "Parser/TypedefTable.h" // for TypedefTable 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; … … 46 46 47 47 ast::TranslationUnit buildUnit(void) { 48 std::list<Declaration *> translationUnit; 49 buildList( parseTree, translationUnit ); 50 48 std::vector<ast::ptr<ast::Decl>> decls; 49 buildList( parseTree, decls ); 51 50 delete parseTree; 52 51 parseTree = nullptr; 53 52 54 // When the parse/buildList code is translated to the new ast, these 55 // fill passes (and the one after 'Hoist Type Decls') should be redundent 56 // because the code locations should already be filled. 57 CodeTools::fillLocations( translationUnit ); 58 ast::TranslationUnit transUnit = convert( std::move( translationUnit ) ); 59 forceFillCodeLocations( transUnit ); 53 ast::TranslationUnit transUnit; 54 for ( auto decl : decls ) { 55 transUnit.decls.emplace_back( std::move( decl ) ); 56 } 60 57 return transUnit; 61 58 } -
src/Parser/RunParser.hpp
r2ed94a9 rb110bcc 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/StatementNode.cc
r2ed94a9 rb110bcc 10 10 // Author : Rodolfo G. Esteves 11 11 // Created On : Sat May 16 14:59:41 2015 12 // Last Modified By : Peter A. Buhr13 // Last Modified On : Wed Feb 2 20:29:30 202214 // Update Count : 42 512 // Last Modified By : Andrew Beach 13 // Last Modified On : Tue Apr 11 10:16:00 2023 14 // Update Count : 428 15 15 // 16 16 17 #include "StatementNode.h" 18 17 19 #include <cassert> // for assert, strict_dynamic_cast, assertf 18 #include <list> // for list19 20 #include <memory> // for unique_ptr 20 21 #include <string> // for string 21 22 23 #include "AST/Label.hpp" // for Label 24 #include "AST/Stmt.hpp" // for Stmt, AsmStmt, BranchStmt, CaseCla... 22 25 #include "Common/SemanticError.h" // for SemanticError 23 26 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild 24 #include "ParseNode.h" // for StatementNode, ExpressionNode, bui... 25 #include "SynTree/Expression.h" // for Expression, ConstantExpr 26 #include "SynTree/Label.h" // for Label, noLabels 27 #include "SynTree/Declaration.h" 28 #include "SynTree/Statement.h" // for Statement, BranchStmt, CaseStmt 27 #include "DeclarationNode.h" // for DeclarationNode 28 #include "ExpressionNode.h" // for ExpressionNode 29 29 #include "parserutility.h" // for notZeroExpr 30 30 … … 33 33 using namespace std; 34 34 35 // Some helpers for cases that really want a single node but check for lists. 36 static const ast::Stmt * buildMoveSingle( StatementNode * node ) { 37 std::vector<ast::ptr<ast::Stmt>> list; 38 buildMoveList( node, list ); 39 assertf( list.size() == 1, "CFA Internal Error: Extra/Missing Nodes" ); 40 return list.front().release(); 41 } 42 43 static const ast::Stmt * buildMoveOptional( StatementNode * node ) { 44 std::vector<ast::ptr<ast::Stmt>> list; 45 buildMoveList( node, list ); 46 assertf( list.size() <= 1, "CFA Internal Error: Extra Nodes" ); 47 return list.empty() ? nullptr : list.front().release(); 48 } 35 49 36 50 StatementNode::StatementNode( DeclarationNode * decl ) { … … 38 52 DeclarationNode * agg = decl->extractAggregate(); 39 53 if ( agg ) { 40 StatementNode * nextStmt = new StatementNode( new DeclStmt( maybeBuild< Declaration >( decl ) ) ); 54 StatementNode * nextStmt = new StatementNode( 55 new ast::DeclStmt( decl->location, maybeBuild( decl ) ) ); 41 56 set_next( nextStmt ); 42 57 if ( decl->get_next() ) { … … 51 66 agg = decl; 52 67 } // if 53 stmt.reset( new DeclStmt( maybeMoveBuild< Declaration >(agg) ) ); 68 // Local copy to avoid accessing the pointer after it is moved from. 69 CodeLocation declLocation = agg->location; 70 stmt.reset( new ast::DeclStmt( declLocation, maybeMoveBuild( agg ) ) ); 54 71 } // StatementNode::StatementNode 55 72 56 StatementNode * StatementNode::append_last_case( StatementNode * stmt ) { 57 StatementNode * prev = this; 73 StatementNode * StatementNode::add_label( 74 const CodeLocation & location, 75 const std::string * name, 76 DeclarationNode * attr ) { 77 stmt->labels.emplace_back( location, 78 *name, 79 attr ? std::move( attr->attributes ) 80 : std::vector<ast::ptr<ast::Attribute>>{} ); 81 delete attr; 82 delete name; 83 return this; 84 } 85 86 ClauseNode * ClauseNode::append_last_case( StatementNode * stmt ) { 87 ClauseNode * prev = this; 58 88 // find end of list and maintain previous pointer 59 for ( StatementNode * curr = prev; curr != nullptr; curr = (StatementNode *)curr->get_next() ) {60 StatementNode * node = strict_dynamic_cast< StatementNode * >(curr);61 assert( dynamic_cast< CaseStmt * >(node->stmt.get()) );89 for ( ClauseNode * curr = prev; curr != nullptr; curr = (ClauseNode *)curr->get_next() ) { 90 ClauseNode * node = strict_dynamic_cast< ClauseNode * >(curr); 91 assert( dynamic_cast<ast::CaseClause *>( node->clause.get() ) ); 62 92 prev = curr; 63 93 } // for 94 ClauseNode * node = dynamic_cast< ClauseNode * >(prev); 64 95 // convert from StatementNode list to Statement list 65 StatementNode * node = dynamic_cast< StatementNode * >(prev); 66 list< Statement * > stmts; 96 std::vector<ast::ptr<ast::Stmt>> stmts; 67 97 buildMoveList( stmt, stmts ); 68 98 // splice any new Statements to end of current Statements 69 CaseStmt * caseStmt = dynamic_cast< CaseStmt * >(node->stmt.get()); 70 caseStmt->get_statements().splice( caseStmt->get_statements().end(), stmts ); 99 auto caseStmt = strict_dynamic_cast<ast::CaseClause *>( node->clause.get() ); 100 for ( auto const & newStmt : stmts ) { 101 caseStmt->stmts.emplace_back( newStmt ); 102 } 103 stmts.clear(); 71 104 return this; 72 } // StatementNode::append_last_case 73 74 Statement * build_expr( ExpressionNode * ctl ) { 75 Expression * e = maybeMoveBuild< Expression >( ctl ); 76 77 if ( e ) return new ExprStmt( e ); 78 else return new NullStmt(); 105 } // ClauseNode::append_last_case 106 107 ast::Stmt * build_expr( CodeLocation const & location, ExpressionNode * ctl ) { 108 if ( ast::Expr * e = maybeMoveBuild( ctl ) ) { 109 return new ast::ExprStmt( location, e ); 110 } else { 111 return new ast::NullStmt( location ); 112 } 79 113 } // build_expr 80 114 81 Expression * build_if_control( CondCtl * ctl, list< Statement * > & init ) { 82 if ( ctl->init != 0 ) { 83 buildMoveList( ctl->init, init ); 115 static ast::Expr * build_if_control( CondCtl * ctl, 116 std::vector<ast::ptr<ast::Stmt>> & inits ) { 117 assert( inits.empty() ); 118 if ( nullptr != ctl->init ) { 119 buildMoveList( ctl->init, inits ); 84 120 } // if 85 121 86 Expression* cond = nullptr;122 ast::Expr * cond = nullptr; 87 123 if ( ctl->condition ) { 88 124 // compare the provided condition against 0 89 cond = notZeroExpr( maybeMoveBuild < Expression >(ctl->condition) );125 cond = notZeroExpr( maybeMoveBuild( ctl->condition ) ); 90 126 } else { 91 for ( Statement * stmt : init) {127 for ( ast::ptr<ast::Stmt> & stmt : inits ) { 92 128 // build the && of all of the declared variables compared against 0 93 DeclStmt * declStmt = strict_dynamic_cast< DeclStmt * >( stmt);94 DeclarationWithType * dwt = strict_dynamic_cast< DeclarationWithType * >( declStmt->decl);95 Expression * nze = notZeroExpr( new VariableExpr(dwt ) );96 cond = cond ? new LogicalExpr( cond, nze, true) : nze;129 auto declStmt = stmt.strict_as<ast::DeclStmt>(); 130 auto dwt = declStmt->decl.strict_as<ast::DeclWithType>(); 131 ast::Expr * nze = notZeroExpr( new ast::VariableExpr( dwt->location, dwt ) ); 132 cond = cond ? new ast::LogicalExpr( dwt->location, cond, nze, ast::AndExpr ) : nze; 97 133 } 98 134 } … … 101 137 } // build_if_control 102 138 103 Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ ) { 104 list< Statement * > astinit; // maybe empty 105 Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 106 107 Statement * astthen, * astelse = nullptr; 108 list< Statement * > aststmt; 109 buildMoveList< Statement, StatementNode >( then, aststmt ); 110 assert( aststmt.size() == 1 ); 111 astthen = aststmt.front(); 112 113 if ( else_ ) { 114 list< Statement * > aststmt; 115 buildMoveList< Statement, StatementNode >( else_, aststmt ); 116 assert( aststmt.size() == 1 ); 117 astelse = aststmt.front(); 118 } // if 119 120 return new IfStmt( astcond, astthen, astelse, astinit ); 139 ast::Stmt * build_if( const CodeLocation & location, CondCtl * ctl, StatementNode * then, StatementNode * else_ ) { 140 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty 141 ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 142 143 ast::Stmt const * astthen = buildMoveSingle( then ); 144 ast::Stmt const * astelse = buildMoveOptional( else_ ); 145 146 return new ast::IfStmt( location, astcond, astthen, astelse, 147 std::move( astinit ) 148 ); 121 149 } // build_if 122 150 123 Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) { 124 list< Statement * > aststmt; 125 buildMoveList< Statement, StatementNode >( stmt, aststmt ); 126 if ( ! isSwitch ) { // choose statement 127 for ( Statement * stmt : aststmt ) { 128 CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt ); 129 if ( ! caseStmt->stmts.empty() ) { // code after "case" => end of case list 130 CompoundStmt * block = strict_dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() ); 131 block->kids.push_back( new BranchStmt( "", BranchStmt::Break ) ); 151 ast::Stmt * build_switch( const CodeLocation & location, bool isSwitch, ExpressionNode * ctl, ClauseNode * stmt ) { 152 std::vector<ast::ptr<ast::CaseClause>> aststmt; 153 buildMoveList( stmt, aststmt ); 154 // If it is not a switch it is a choose statement. 155 if ( ! isSwitch ) { 156 for ( ast::ptr<ast::CaseClause> & stmt : aststmt ) { 157 // Code after "case" is the end of case list. 158 if ( !stmt->stmts.empty() ) { 159 auto mutStmt = ast::mutate( stmt.get() ); 160 // I believe the stmts are actually always one block. 161 auto stmts = mutStmt->stmts.front().get_and_mutate(); 162 auto block = strict_dynamic_cast<ast::CompoundStmt *>( stmts ); 163 block->kids.push_back( new ast::BranchStmt( block->location, 164 ast::BranchStmt::Break, 165 ast::Label( block->location ) ) ); 166 stmt = mutStmt; 132 167 } // if 133 168 } // for 134 169 } // if 135 170 // aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements 136 return new SwitchStmt( maybeMoveBuild< Expression >(ctl), aststmt ); 171 return new ast::SwitchStmt( location, 172 maybeMoveBuild( ctl ), std::move( aststmt ) ); 137 173 } // build_switch 138 174 139 Statement * build_case( ExpressionNode * ctl ) { 140 return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to 175 ast::CaseClause * build_case( const CodeLocation & location, ExpressionNode * ctl ) { 176 // stmt starts empty and then added to 177 auto expr = maybeMoveBuild( ctl ); 178 return new ast::CaseClause( location, expr, {} ); 141 179 } // build_case 142 180 143 Statement * build_default() { 144 return new CaseStmt( nullptr, {}, true ); // stmt starts empty and then added to 181 ast::CaseClause * build_default( const CodeLocation & location ) { 182 // stmt starts empty and then added to 183 return new ast::CaseClause( location, nullptr, {} ); 145 184 } // build_default 146 185 147 Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) { 148 list< Statement * > astinit; // maybe empty 149 Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 150 151 list< Statement * > aststmt; // loop body, compound created if empty 152 buildMoveList< Statement, StatementNode >( stmt, aststmt ); 153 assert( aststmt.size() == 1 ); 154 155 list< Statement * > astelse; // else clause, maybe empty 156 buildMoveList< Statement, StatementNode >( else_, astelse ); 157 158 return new WhileDoStmt( astcond, aststmt.front(), astelse.front(), astinit, false ); 186 ast::Stmt * build_while( const CodeLocation & location, CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) { 187 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty 188 ast::Expr * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set 189 190 return new ast::WhileDoStmt( location, 191 astcond, 192 buildMoveSingle( stmt ), 193 buildMoveOptional( else_ ), 194 std::move( astinit ), 195 ast::While 196 ); 159 197 } // build_while 160 198 161 Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) { 162 list< Statement * > aststmt; // loop body, compound created if empty 163 buildMoveList< Statement, StatementNode >( stmt, aststmt ); 164 assert( aststmt.size() == 1 ); // compound created if empty 165 166 list< Statement * > astelse; // else clause, maybe empty 167 buildMoveList< Statement, StatementNode >( else_, astelse ); 168 199 ast::Stmt * build_do_while( const CodeLocation & location, ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) { 169 200 // do-while cannot have declarations in the contitional, so init is always empty 170 return new WhileDoStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), aststmt.front(), astelse.front(), {}, true ); 201 return new ast::WhileDoStmt( location, 202 notZeroExpr( maybeMoveBuild( ctl ) ), 203 buildMoveSingle( stmt ), 204 buildMoveOptional( else_ ), 205 {}, 206 ast::DoWhile 207 ); 171 208 } // build_do_while 172 209 173 Statement * build_for(ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {174 list< Statement *> astinit; // maybe empty210 ast::Stmt * build_for( const CodeLocation & location, ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) { 211 std::vector<ast::ptr<ast::Stmt>> astinit; // maybe empty 175 212 buildMoveList( forctl->init, astinit ); 176 213 177 Expression* astcond = nullptr; // maybe empty178 astcond = notZeroExpr( maybeMoveBuild < Expression >(forctl->condition) );179 180 Expression* astincr = nullptr; // maybe empty181 astincr = maybeMoveBuild < Expression >(forctl->change);214 ast::Expr * astcond = nullptr; // maybe empty 215 astcond = notZeroExpr( maybeMoveBuild( forctl->condition ) ); 216 217 ast::Expr * astincr = nullptr; // maybe empty 218 astincr = maybeMoveBuild( forctl->change ); 182 219 delete forctl; 183 220 184 list< Statement * > aststmt; // loop body, compound created if empty 185 buildMoveList< Statement, StatementNode >( stmt, aststmt ); 186 assert( aststmt.size() == 1 ); 187 188 list< Statement * > astelse; // else clause, maybe empty 189 buildMoveList< Statement, StatementNode >( else_, astelse ); 190 191 return new ForStmt( astinit, astcond, astincr, aststmt.front(), astelse.front() ); 221 return new ast::ForStmt( location, 222 std::move( astinit ), 223 astcond, 224 astincr, 225 buildMoveSingle( stmt ), 226 buildMoveOptional( else_ ) 227 ); 192 228 } // build_for 193 229 194 Statement * build_branch( BranchStmt::Type kind ) { 195 Statement * ret = new BranchStmt( "", kind ); 196 return ret; 230 ast::Stmt * build_branch( const CodeLocation & location, ast::BranchStmt::Kind kind ) { 231 return new ast::BranchStmt( location, 232 kind, 233 ast::Label( location ) 234 ); 197 235 } // build_branch 198 236 199 Statement * build_branch( string * identifier, BranchStmt::Type kind ) { 200 Statement * ret = new BranchStmt( * identifier, kind ); 237 ast::Stmt * build_branch( const CodeLocation & location, string * identifier, ast::BranchStmt::Kind kind ) { 238 ast::Stmt * ret = new ast::BranchStmt( location, 239 kind, 240 ast::Label( location, *identifier ) 241 ); 201 242 delete identifier; // allocated by lexer 202 243 return ret; 203 244 } // build_branch 204 245 205 Statement * build_computedgoto( ExpressionNode * ctl ) { 206 return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto ); 246 ast::Stmt * build_computedgoto( ExpressionNode * ctl ) { 247 ast::Expr * expr = maybeMoveBuild( ctl ); 248 return new ast::BranchStmt( expr->location, expr ); 207 249 } // build_computedgoto 208 250 209 Statement * build_return(ExpressionNode * ctl ) {210 list< Expression *> exps;251 ast::Stmt * build_return( const CodeLocation & location, ExpressionNode * ctl ) { 252 std::vector<ast::ptr<ast::Expr>> exps; 211 253 buildMoveList( ctl, exps ); 212 return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr ); 254 return new ast::ReturnStmt( location, 255 exps.size() > 0 ? exps.back().release() : nullptr 256 ); 213 257 } // build_return 214 258 215 Statement * build_throw( ExpressionNode * ctl ) { 216 list< Expression * > exps; 259 static ast::Stmt * build_throw_stmt( 260 const CodeLocation & location, 261 ExpressionNode * ctl, 262 ast::ExceptionKind kind ) { 263 std::vector<ast::ptr<ast::Expr>> exps; 217 264 buildMoveList( ctl, exps ); 218 265 assertf( exps.size() < 2, "CFA internal error: leaking memory" ); 219 return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr ); 266 return new ast::ThrowStmt( location, 267 kind, 268 !exps.empty() ? exps.back().release() : nullptr, 269 (ast::Expr *)nullptr 270 ); 271 } 272 273 ast::Stmt * build_throw( const CodeLocation & loc, ExpressionNode * ctl ) { 274 return build_throw_stmt( loc, ctl, ast::Terminate ); 220 275 } // build_throw 221 276 222 Statement * build_resume( ExpressionNode * ctl ) { 223 list< Expression * > exps; 224 buildMoveList( ctl, exps ); 225 assertf( exps.size() < 2, "CFA internal error: leaking memory" ); 226 return new ThrowStmt( ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr ); 277 ast::Stmt * build_resume( const CodeLocation & loc, ExpressionNode * ctl ) { 278 return build_throw_stmt( loc, ctl, ast::Resume ); 227 279 } // build_resume 228 280 229 Statement * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) {281 ast::Stmt * build_resume_at( ExpressionNode * ctl, ExpressionNode * target ) { 230 282 (void)ctl; 231 283 (void)target; … … 233 285 } // build_resume_at 234 286 235 Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) { 236 list< CatchStmt * > aststmt; 237 buildMoveList< CatchStmt, StatementNode >( catch_, aststmt ); 238 CompoundStmt * tryBlock = strict_dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >(try_)); 239 FinallyStmt * finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_) ); 240 return new TryStmt( tryBlock, aststmt, finallyBlock ); 287 ast::Stmt * build_try( const CodeLocation & location, StatementNode * try_, ClauseNode * catch_, ClauseNode * finally_ ) { 288 std::vector<ast::ptr<ast::CatchClause>> aststmt; 289 buildMoveList( catch_, aststmt ); 290 ast::CompoundStmt * tryBlock = strict_dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( try_ ) ); 291 ast::FinallyClause * finallyBlock = nullptr; 292 if ( finally_ ) { 293 finallyBlock = dynamic_cast<ast::FinallyClause *>( finally_->clause.release() ); 294 } 295 return new ast::TryStmt( location, 296 tryBlock, 297 std::move( aststmt ), 298 finallyBlock 299 ); 241 300 } // build_try 242 301 243 Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) { 244 list< Statement * > aststmt; 245 buildMoveList< Statement, StatementNode >( body, aststmt ); 246 assert( aststmt.size() == 1 ); 247 return new CatchStmt( kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), aststmt.front() ); 302 ast::CatchClause * build_catch( const CodeLocation & location, ast::ExceptionKind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) { 303 return new ast::CatchClause( location, 304 kind, 305 maybeMoveBuild( decl ), 306 maybeMoveBuild( cond ), 307 buildMoveSingle( body ) 308 ); 248 309 } // build_catch 249 310 250 Statement * build_finally( StatementNode * stmt ) { 251 list< Statement * > aststmt; 252 buildMoveList< Statement, StatementNode >( stmt, aststmt ); 253 assert( aststmt.size() == 1 ); 254 return new FinallyStmt( dynamic_cast< CompoundStmt * >( aststmt.front() ) ); 311 ast::FinallyClause * build_finally( const CodeLocation & location, StatementNode * stmt ) { 312 return new ast::FinallyClause( location, 313 strict_dynamic_cast<const ast::CompoundStmt *>( 314 buildMoveSingle( stmt ) 315 ) 316 ); 255 317 } // build_finally 256 318 257 SuspendStmt * build_suspend( StatementNode * then, SuspendStmt::Type type ) { 258 auto node = new SuspendStmt(); 259 260 node->type = type; 261 262 list< Statement * > stmts; 263 buildMoveList< Statement, StatementNode >( then, stmts ); 264 if(!stmts.empty()) { 265 assert( stmts.size() == 1 ); 266 node->then = dynamic_cast< CompoundStmt * >( stmts.front() ); 267 } 268 269 return node; 270 } 271 272 WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when ) { 273 auto node = new WaitForStmt(); 274 275 WaitForStmt::Target target; 276 target.function = maybeBuild<Expression>( targetExpr ); 319 ast::SuspendStmt * build_suspend( const CodeLocation & location, StatementNode * then, ast::SuspendStmt::Kind kind ) { 320 return new ast::SuspendStmt( location, 321 strict_dynamic_cast<const ast::CompoundStmt *, nullptr>( 322 buildMoveOptional( then ) 323 ), 324 kind 325 ); 326 } // build_suspend 327 328 ast::WaitForStmt * build_waitfor( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) { 329 auto clause = new ast::WaitForClause( location ); 330 clause->target_func = maybeBuild( targetExpr ); 331 clause->stmt = maybeMoveBuild( stmt ); 332 clause->cond = notZeroExpr( maybeMoveBuild( when ) ); 277 333 278 334 ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() ); 279 335 targetExpr->set_next( nullptr ); 280 buildMoveList < Expression >( next, target.arguments );336 buildMoveList( next, clause->target_args ); 281 337 282 338 delete targetExpr; 283 339 284 node->clauses.push_back( WaitForStmt::Clause{ 285 target, 286 maybeMoveBuild<Statement >( stmt ), 287 notZeroExpr( maybeMoveBuild<Expression>( when ) ) 288 }); 289 290 return node; 340 existing->clauses.insert( existing->clauses.begin(), clause ); 341 342 return existing; 291 343 } // build_waitfor 292 344 293 WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when, WaitForStmt * node ) { 294 WaitForStmt::Target target; 295 target.function = maybeBuild<Expression>( targetExpr ); 296 297 ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() ); 298 targetExpr->set_next( nullptr ); 299 buildMoveList< Expression >( next, target.arguments ); 300 301 delete targetExpr; 302 303 node->clauses.insert( node->clauses.begin(), WaitForStmt::Clause{ 304 std::move( target ), 305 maybeMoveBuild<Statement >( stmt ), 306 notZeroExpr( maybeMoveBuild<Expression>( when ) ) 307 }); 308 309 return node; 310 } // build_waitfor 311 312 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when ) { 313 auto node = new WaitForStmt(); 314 315 if( timeout ) { 316 node->timeout.time = maybeMoveBuild<Expression>( timeout ); 317 node->timeout.statement = maybeMoveBuild<Statement >( stmt ); 318 node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) ); 319 } else { 320 node->orelse.statement = maybeMoveBuild<Statement >( stmt ); 321 node->orelse.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) ); 322 } // if 323 324 return node; 345 ast::WaitForStmt * build_waitfor_else( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) { 346 existing->else_stmt = maybeMoveBuild( stmt ); 347 existing->else_cond = notZeroExpr( maybeMoveBuild( when ) ); 348 349 (void)location; 350 return existing; 351 } // build_waitfor_else 352 353 ast::WaitForStmt * build_waitfor_timeout( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) { 354 existing->timeout_time = maybeMoveBuild( timeout ); 355 existing->timeout_stmt = maybeMoveBuild( stmt ); 356 existing->timeout_cond = notZeroExpr( maybeMoveBuild( when ) ); 357 358 (void)location; 359 return existing; 325 360 } // build_waitfor_timeout 326 361 327 WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_, ExpressionNode * else_when ) { 328 auto node = new WaitForStmt(); 329 330 node->timeout.time = maybeMoveBuild<Expression>( timeout ); 331 node->timeout.statement = maybeMoveBuild<Statement >( stmt ); 332 node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) ); 333 334 node->orelse.statement = maybeMoveBuild<Statement >( else_ ); 335 node->orelse.condition = notZeroExpr( maybeMoveBuild<Expression>( else_when ) ); 336 337 return node; 338 } // build_waitfor_timeout 339 340 Statement * build_with( ExpressionNode * exprs, StatementNode * stmt ) { 341 list< Expression * > e; 362 ast::Stmt * build_with( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) { 363 std::vector<ast::ptr<ast::Expr>> e; 342 364 buildMoveList( exprs, e ); 343 Statement * s = maybeMoveBuild<Statement>( stmt );344 return new DeclStmt( new WithStmt( e, s ) );365 ast::Stmt * s = maybeMoveBuild( stmt ); 366 return new ast::DeclStmt( location, new ast::WithStmt( location, std::move( e ), s ) ); 345 367 } // build_with 346 368 347 Statement * build_compound(StatementNode * first ) {348 CompoundStmt * cs = new CompoundStmt();349 buildMoveList( first, cs-> get_kids());369 ast::Stmt * build_compound( const CodeLocation & location, StatementNode * first ) { 370 auto cs = new ast::CompoundStmt( location ); 371 buildMoveList( first, cs->kids ); 350 372 return cs; 351 373 } // build_compound … … 355 377 // statement and wrap it into a compound statement to insert additional code. Hence, all control structures have a 356 378 // conical form for code generation. 357 StatementNode * maybe_build_compound( StatementNode * first ) {379 StatementNode * maybe_build_compound( const CodeLocation & location, StatementNode * first ) { 358 380 // Optimization: if the control-structure statement is a compound statement, do not wrap it. 359 381 // e.g., if (...) {...} do not wrap the existing compound statement. 360 if ( ! dynamic_cast<CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr 361 CompoundStmt * cs = new CompoundStmt(); 362 buildMoveList( first, cs->get_kids() ); 363 return new StatementNode( cs ); 382 if ( !dynamic_cast<ast::CompoundStmt *>( first->stmt.get() ) ) { // unique_ptr 383 return new StatementNode( build_compound( location, first ) ); 364 384 } // if 365 385 return first; … … 367 387 368 388 // Question 369 Statement * build_asm( bool voltile, Expression* instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {370 list< Expression *> out, in;371 list< ConstantExpr *> clob;389 ast::Stmt * build_asm( const CodeLocation & location, bool is_volatile, ExpressionNode * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) { 390 std::vector<ast::ptr<ast::Expr>> out, in; 391 std::vector<ast::ptr<ast::ConstantExpr>> clob; 372 392 373 393 buildMoveList( output, out ); 374 394 buildMoveList( input, in ); 375 395 buildMoveList( clobber, clob ); 376 return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels ); 396 return new ast::AsmStmt( location, 397 is_volatile, 398 maybeMoveBuild( instruction ), 399 std::move( out ), 400 std::move( in ), 401 std::move( clob ), 402 gotolabels ? gotolabels->labels : std::vector<ast::Label>() 403 ); 377 404 } // build_asm 378 405 379 Statement * build_directive( string * directive ) { 380 return new DirectiveStmt( *directive ); 406 ast::Stmt * build_directive( const CodeLocation & location, string * directive ) { 407 auto stmt = new ast::DirectiveStmt( location, *directive ); 408 delete directive; 409 return stmt; 381 410 } // build_directive 382 411 383 Statement * build_mutex(ExpressionNode * exprs, StatementNode * stmt ) {384 list< Expression *> expList;412 ast::Stmt * build_mutex( const CodeLocation & location, ExpressionNode * exprs, StatementNode * stmt ) { 413 std::vector<ast::ptr<ast::Expr>> expList; 385 414 buildMoveList( exprs, expList ); 386 Statement * body = maybeMoveBuild<Statement>( stmt );387 return new MutexStmt( body, expList);415 ast::Stmt * body = maybeMoveBuild( stmt ); 416 return new ast::MutexStmt( location, body, std::move( expList ) ); 388 417 } // build_mutex 389 418 -
src/Parser/TypeData.cc
r2ed94a9 rb110bcc 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 15:12:51 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue May 10 22:36:52 202213 // Update Count : 6 7711 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Apr 4 13:39:00 2023 13 // Update Count : 680 14 14 // 15 16 #include "TypeData.h" 15 17 16 18 #include <cassert> // for assert 17 19 #include <ostream> // for operator<<, ostream, basic_ostream 18 20 21 #include "AST/Decl.hpp" // for AggregateDecl, ObjectDecl, TypeDe... 22 #include "AST/Init.hpp" // for SingleInit, ListInit 23 #include "AST/Print.hpp" // for print 19 24 #include "Common/SemanticError.h" // for SemanticError 20 #include "Common/utility.h" // for maybeClone, maybeBuild, maybeMoveB... 21 #include "Parser/ParseNode.h" // for DeclarationNode, ExpressionNode 22 #include "SynTree/Declaration.h" // for TypeDecl, ObjectDecl, FunctionDecl 23 #include "SynTree/Expression.h" // for Expression, ConstantExpr (ptr only) 24 #include "SynTree/Initializer.h" // for SingleInit, Initializer (ptr only) 25 #include "SynTree/Statement.h" // for CompoundStmt, Statement 26 #include "SynTree/Type.h" // for BasicType, Type, Type::ForallList 27 #include "TypeData.h" 25 #include "Common/utility.h" // for splice, spliceBegin 26 #include "Parser/ExpressionNode.h" // for ExpressionNode 27 #include "Parser/StatementNode.h" // for StatementNode 28 28 29 29 class Attribute; … … 33 33 TypeData::TypeData( Kind k ) : location( yylloc ), kind( k ), base( nullptr ), forall( nullptr ) /*, PTR1( (void*)(0xdeadbeefdeadbeef)), PTR2( (void*)(0xdeadbeefdeadbeef) ) */ { 34 34 switch ( kind ) { 35 case Unknown: 36 case Pointer: 37 case Reference: 38 case EnumConstant: 39 case GlobalScope: 40 // nothing else to initialize 41 break; 42 case Basic: 43 // basic = new Basic_t; 44 break; 45 case Array: 46 // array = new Array_t; 35 case Unknown: 36 case Pointer: 37 case Reference: 38 case EnumConstant: 39 case GlobalScope: 40 case Basic: 41 // No unique data to initialize. 42 break; 43 case Array: 47 44 array.dimension = nullptr; 48 45 array.isVarLen = false; 49 46 array.isStatic = false; 50 47 break; 51 case Function: 52 // function = new Function_t; 48 case Function: 53 49 function.params = nullptr; 54 50 function.idList = nullptr; … … 57 53 function.withExprs = nullptr; 58 54 break; 59 // Enum is an Aggregate, so both structures are initialized together. 60 case Enum: 61 // enumeration = new Enumeration_t; 55 case Enum: 62 56 enumeration.name = nullptr; 63 57 enumeration.constants = nullptr; … … 65 59 enumeration.anon = false; 66 60 break; 67 case Aggregate: 68 // aggregate = new Aggregate_t; 69 aggregate.kind = AggregateDecl::NoAggregate; 61 case Aggregate: 62 aggregate.kind = ast::AggregateDecl::NoAggregate; 70 63 aggregate.name = nullptr; 71 64 aggregate.params = nullptr; … … 77 70 aggregate.anon = false; 78 71 break; 79 case AggregateInst: 80 // aggInst = new AggInst_t; 72 case AggregateInst: 81 73 aggInst.aggregate = nullptr; 82 74 aggInst.params = nullptr; 83 75 aggInst.hoistType = false; 84 76 break; 85 case Symbolic: 86 case SymbolicInst: 87 // symbolic = new Symbolic_t; 77 case Symbolic: 78 case SymbolicInst: 88 79 symbolic.name = nullptr; 89 80 symbolic.params = nullptr; … … 91 82 symbolic.assertions = nullptr; 92 83 break; 93 case Tuple: 94 // tuple = new Tuple_t; 84 case Tuple: 95 85 tuple = nullptr; 96 86 break; 97 case Typeof: 98 case Basetypeof: 99 // typeexpr = new Typeof_t; 87 case Typeof: 88 case Basetypeof: 100 89 typeexpr = nullptr; 101 90 break; 102 103 break;104 case Builtin:105 // builtin = new Builtin_t;106 91 case Vtable: 92 case Builtin: 93 // No unique data to initialize. 94 break; 95 case Qualified: 107 96 qualified.parent = nullptr; 108 97 qualified.child = nullptr; … … 117 106 118 107 switch ( kind ) { 119 case Unknown: 120 case Pointer: 121 case Reference: 122 case EnumConstant: 123 case GlobalScope: 124 // nothing to destroy 125 break; 126 case Basic: 127 // delete basic; 128 break; 129 case Array: 108 case Unknown: 109 case Pointer: 110 case Reference: 111 case EnumConstant: 112 case GlobalScope: 113 case Basic: 114 // No unique data to deconstruct. 115 break; 116 case Array: 130 117 delete array.dimension; 131 // delete array; 132 break; 133 case Function: 118 break; 119 case Function: 134 120 delete function.params; 135 121 delete function.idList; … … 137 123 delete function.body; 138 124 delete function.withExprs; 139 // delete function; 140 break; 141 case Aggregate: 125 break; 126 case Aggregate: 142 127 delete aggregate.name; 143 128 delete aggregate.params; 144 129 delete aggregate.actuals; 145 130 delete aggregate.fields; 146 // delete aggregate; 147 break; 148 case AggregateInst: 131 break; 132 case AggregateInst: 149 133 delete aggInst.aggregate; 150 134 delete aggInst.params; 151 // delete aggInst; 152 break; 153 case Enum: 135 break; 136 case Enum: 154 137 delete enumeration.name; 155 138 delete enumeration.constants; 156 // delete enumeration; 157 break; 158 case Symbolic: 159 case SymbolicInst: 139 break; 140 case Symbolic: 141 case SymbolicInst: 160 142 delete symbolic.name; 161 143 delete symbolic.params; 162 144 delete symbolic.actuals; 163 145 delete symbolic.assertions; 164 // delete symbolic; 165 break; 166 case Tuple: 167 // delete tuple->members; 146 break; 147 case Tuple: 168 148 delete tuple; 169 149 break; 170 case Typeof: 171 case Basetypeof: 172 // delete typeexpr->expr; 150 case Typeof: 151 case Basetypeof: 173 152 delete typeexpr; 174 153 break; 175 case Vtable: 176 break; 177 case Builtin: 178 // delete builtin; 179 break; 180 case Qualified: 154 case Vtable: 155 case Builtin: 156 // No unique data to deconstruct. 157 break; 158 case Qualified: 181 159 delete qualified.parent; 182 160 delete qualified.child; 161 break; 183 162 } // switch 184 163 } // TypeData::~TypeData … … 192 171 193 172 switch ( kind ) { 194 195 196 197 198 173 case Unknown: 174 case EnumConstant: 175 case Pointer: 176 case Reference: 177 case GlobalScope: 199 178 // nothing else to copy 200 179 break; 201 180 case Basic: 202 181 newtype->basictype = basictype; 203 182 newtype->complextype = complextype; … … 205 184 newtype->length = length; 206 185 break; 207 186 case Array: 208 187 newtype->array.dimension = maybeClone( array.dimension ); 209 188 newtype->array.isVarLen = array.isVarLen; 210 189 newtype->array.isStatic = array.isStatic; 211 190 break; 212 191 case Function: 213 192 newtype->function.params = maybeClone( function.params ); 214 193 newtype->function.idList = maybeClone( function.idList ); … … 217 196 newtype->function.withExprs = maybeClone( function.withExprs ); 218 197 break; 219 198 case Aggregate: 220 199 newtype->aggregate.kind = aggregate.kind; 221 200 newtype->aggregate.name = aggregate.name ? new string( *aggregate.name ) : nullptr; … … 228 207 newtype->aggregate.parent = aggregate.parent ? new string( *aggregate.parent ) : nullptr; 229 208 break; 230 209 case AggregateInst: 231 210 newtype->aggInst.aggregate = maybeClone( aggInst.aggregate ); 232 211 newtype->aggInst.params = maybeClone( aggInst.params ); 233 212 newtype->aggInst.hoistType = aggInst.hoistType; 234 213 break; 235 214 case Enum: 236 215 newtype->enumeration.name = enumeration.name ? new string( *enumeration.name ) : nullptr; 237 216 newtype->enumeration.constants = maybeClone( enumeration.constants ); … … 239 218 newtype->enumeration.anon = enumeration.anon; 240 219 break; 241 242 220 case Symbolic: 221 case SymbolicInst: 243 222 newtype->symbolic.name = symbolic.name ? new string( *symbolic.name ) : nullptr; 244 223 newtype->symbolic.params = maybeClone( symbolic.params ); … … 247 226 newtype->symbolic.isTypedef = symbolic.isTypedef; 248 227 break; 249 228 case Tuple: 250 229 newtype->tuple = maybeClone( tuple ); 251 230 break; 252 253 231 case Typeof: 232 case Basetypeof: 254 233 newtype->typeexpr = maybeClone( typeexpr ); 255 234 break; 256 257 break; 258 235 case Vtable: 236 break; 237 case Builtin: 259 238 assert( builtintype == DeclarationNode::Zero || builtintype == DeclarationNode::One ); 260 239 newtype->builtintype = builtintype; 261 240 break; 262 241 case Qualified: 263 242 newtype->qualified.parent = maybeClone( qualified.parent ); 264 243 newtype->qualified.child = maybeClone( qualified.child ); … … 270 249 271 250 void TypeData::print( ostream &os, int indent ) const { 272 for ( int i = 0; i < Type::NumTypeQualifier; i += 1 ) { 273 if ( qualifiers[i] ) os << Type::QualifiersNames[ i ] << ' '; 274 } // for 251 ast::print( os, qualifiers ); 275 252 276 253 if ( forall ) { … … 280 257 281 258 switch ( kind ) { 282 259 case Basic: 283 260 if ( signedness != DeclarationNode::NoSignedness ) os << DeclarationNode::signednessNames[ signedness ] << " "; 284 261 if ( length != DeclarationNode::NoLength ) os << DeclarationNode::lengthNames[ length ] << " "; … … 286 263 if ( basictype != DeclarationNode::NoBasicType ) os << DeclarationNode::basicTypeNames[ basictype ] << " "; 287 264 break; 288 265 case Pointer: 289 266 os << "pointer "; 290 267 if ( base ) { … … 293 270 } // if 294 271 break; 295 272 case Reference: 296 273 os << "reference "; 297 274 if ( base ) { … … 300 277 } // if 301 278 break; 302 279 case Array: 303 280 if ( array.isStatic ) { 304 281 os << "static "; … … 316 293 } // if 317 294 break; 318 295 case Function: 319 296 os << "function" << endl; 320 297 if ( function.params ) { … … 344 321 } // if 345 322 break; 346 347 os << AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl;323 case Aggregate: 324 os << ast::AggregateDecl::aggrString( aggregate.kind ) << ' ' << *aggregate.name << endl; 348 325 if ( aggregate.params ) { 349 326 os << string( indent + 2, ' ' ) << "with type parameters" << endl; … … 362 339 } // if 363 340 break; 364 341 case AggregateInst: 365 342 if ( aggInst.aggregate ) { 366 343 os << "instance of " ; … … 374 351 } // if 375 352 break; 376 377 os << "enumeration " ;353 case Enum: 354 os << "enumeration " << *enumeration.name << endl;; 378 355 if ( enumeration.constants ) { 379 356 os << "with constants" << endl; … … 388 365 } // if 389 366 break; 390 367 case EnumConstant: 391 368 os << "enumeration constant "; 392 369 break; 393 370 case Symbolic: 394 371 if ( symbolic.isTypedef ) { 395 372 os << "typedef definition "; … … 411 388 } // if 412 389 break; 413 390 case SymbolicInst: 414 391 os << *symbolic.name; 415 392 if ( symbolic.actuals ) { … … 419 396 } // if 420 397 break; 421 398 case Tuple: 422 399 os << "tuple "; 423 400 if ( tuple ) { … … 426 403 } // if 427 404 break; 428 405 case Basetypeof: 429 406 os << "base-"; 430 407 #if defined(__GNUC__) && __GNUC__ >= 7 … … 432 409 #endif 433 410 // FALL THROUGH 434 411 case Typeof: 435 412 os << "type-of expression "; 436 413 if ( typeexpr ) { … … 438 415 } // if 439 416 break; 440 417 case Vtable: 441 418 os << "vtable"; 442 419 break; 443 420 case Builtin: 444 421 os << DeclarationNode::builtinTypeNames[builtintype]; 445 422 break; 446 447 break; 448 423 case GlobalScope: 424 break; 425 case Qualified: 449 426 qualified.parent->print( os ); 450 427 os << "."; 451 428 qualified.child->print( os ); 452 429 break; 453 430 case Unknown: 454 431 os << "entity of unknown type "; 455 432 break; 456 433 default: 457 434 os << "internal error: TypeData::print " << kind << endl; 458 435 assert( false ); … … 462 439 const std::string * TypeData::leafName() const { 463 440 switch ( kind ) { 464 465 466 467 468 469 470 471 472 473 474 475 476 477 441 case Unknown: 442 case Pointer: 443 case Reference: 444 case EnumConstant: 445 case GlobalScope: 446 case Array: 447 case Basic: 448 case Function: 449 case AggregateInst: 450 case Tuple: 451 case Typeof: 452 case Basetypeof: 453 case Builtin: 454 case Vtable: 478 455 assertf(false, "Tried to get leaf name from kind without a name: %d", kind); 479 456 break; 480 457 case Aggregate: 481 458 return aggregate.name; 482 459 case Enum: 483 460 return enumeration.name; 484 485 461 case Symbolic: 462 case SymbolicInst: 486 463 return symbolic.name; 487 464 case Qualified: 488 465 return qualified.child->leafName(); 489 466 } // switch … … 492 469 493 470 494 template< typename ForallList > 495 void buildForall( const DeclarationNode * firstNode, ForallList &outputList ) { 496 buildList( firstNode, outputList ); 471 void buildForall( 472 const DeclarationNode * firstNode, 473 std::vector<ast::ptr<ast::TypeInstType>> &outputList ) { 474 { 475 std::vector<ast::ptr<ast::Type>> tmpList; 476 buildTypeList( firstNode, tmpList ); 477 for ( auto tmp : tmpList ) { 478 outputList.emplace_back( 479 strict_dynamic_cast<const ast::TypeInstType *>( 480 tmp.release() ) ); 481 } 482 } 497 483 auto n = firstNode; 498 for ( typename ForallList::iterator i = outputList.begin(); i != outputList.end(); ++i, n = (DeclarationNode*)n->get_next() ) { 499 TypeDecl * td = static_cast<TypeDecl *>(*i); 500 if ( n->variable.tyClass == TypeDecl::Otype ) { 501 // add assertion parameters to `type' tyvars in reverse order 502 // add dtor: void ^?{}(T *) 503 FunctionType * dtorType = new FunctionType( Type::Qualifiers(), false ); 504 dtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 505 td->get_assertions().push_front( new FunctionDecl( "^?{}", Type::StorageClasses(), LinkageSpec::Cforall, dtorType, nullptr ) ); 506 507 // add copy ctor: void ?{}(T *, T) 508 FunctionType * copyCtorType = new FunctionType( Type::Qualifiers(), false ); 509 copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 510 copyCtorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); 511 td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, copyCtorType, nullptr ) ); 512 513 // add default ctor: void ?{}(T *) 514 FunctionType * ctorType = new FunctionType( Type::Qualifiers(), false ); 515 ctorType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 516 td->get_assertions().push_front( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, ctorType, nullptr ) ); 517 518 // add assignment operator: T * ?=?(T *, T) 519 FunctionType * assignType = new FunctionType( Type::Qualifiers(), false ); 520 assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), new TypeInstType( Type::Qualifiers(), td->get_name(), *i ) ), nullptr ) ); 521 assignType->get_parameters().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); 522 assignType->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new TypeInstType( Type::Qualifiers(), td->get_name(), *i ), nullptr ) ); 523 td->get_assertions().push_front( new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Cforall, assignType, nullptr ) ); 524 } // if 484 for ( auto i = outputList.begin() ; 485 i != outputList.end() ; 486 ++i, n = (DeclarationNode*)n->get_next() ) { 487 // Only the object type class adds additional assertions. 488 if ( n->variable.tyClass != ast::TypeDecl::Otype ) { 489 continue; 490 } 491 492 ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>(); 493 std::vector<ast::ptr<ast::DeclWithType>> newAssertions; 494 auto mutTypeDecl = ast::mutate( td ); 495 const CodeLocation & location = mutTypeDecl->location; 496 *i = mutTypeDecl; 497 498 // add assertion parameters to `type' tyvars in reverse order 499 // add assignment operator: T * ?=?(T *, T) 500 newAssertions.push_back( new ast::FunctionDecl( 501 location, 502 "?=?", 503 {}, // forall 504 {}, // assertions 505 { 506 new ast::ObjectDecl( 507 location, 508 "", 509 new ast::ReferenceType( i->get() ), 510 (ast::Init *)nullptr, 511 ast::Storage::Classes(), 512 ast::Linkage::Cforall, 513 (ast::Expr *)nullptr 514 ), 515 new ast::ObjectDecl( 516 location, 517 "", 518 i->get(), 519 (ast::Init *)nullptr, 520 ast::Storage::Classes(), 521 ast::Linkage::Cforall, 522 (ast::Expr *)nullptr 523 ), 524 }, // params 525 { 526 new ast::ObjectDecl( 527 location, 528 "", 529 i->get(), 530 (ast::Init *)nullptr, 531 ast::Storage::Classes(), 532 ast::Linkage::Cforall, 533 (ast::Expr *)nullptr 534 ), 535 }, // returns 536 (ast::CompoundStmt *)nullptr, 537 ast::Storage::Classes(), 538 ast::Linkage::Cforall 539 ) ); 540 541 // add default ctor: void ?{}(T *) 542 newAssertions.push_back( new ast::FunctionDecl( 543 location, 544 "?{}", 545 {}, // forall 546 {}, // assertions 547 { 548 new ast::ObjectDecl( 549 location, 550 "", 551 new ast::ReferenceType( i->get() ), 552 (ast::Init *)nullptr, 553 ast::Storage::Classes(), 554 ast::Linkage::Cforall, 555 (ast::Expr *)nullptr 556 ), 557 }, // params 558 {}, // returns 559 (ast::CompoundStmt *)nullptr, 560 ast::Storage::Classes(), 561 ast::Linkage::Cforall 562 ) ); 563 564 // add copy ctor: void ?{}(T *, T) 565 newAssertions.push_back( new ast::FunctionDecl( 566 location, 567 "?{}", 568 {}, // forall 569 {}, // assertions 570 { 571 new ast::ObjectDecl( 572 location, 573 "", 574 new ast::ReferenceType( i->get() ), 575 (ast::Init *)nullptr, 576 ast::Storage::Classes(), 577 ast::Linkage::Cforall, 578 (ast::Expr *)nullptr 579 ), 580 new ast::ObjectDecl( 581 location, 582 "", 583 i->get(), 584 (ast::Init *)nullptr, 585 ast::Storage::Classes(), 586 ast::Linkage::Cforall, 587 (ast::Expr *)nullptr 588 ), 589 }, // params 590 {}, // returns 591 (ast::CompoundStmt *)nullptr, 592 ast::Storage::Classes(), 593 ast::Linkage::Cforall 594 ) ); 595 596 // add dtor: void ^?{}(T *) 597 newAssertions.push_back( new ast::FunctionDecl( 598 location, 599 "^?{}", 600 {}, // forall 601 {}, // assertions 602 { 603 new ast::ObjectDecl( 604 location, 605 "", 606 new ast::ReferenceType( i->get() ), 607 (ast::Init *)nullptr, 608 ast::Storage::Classes(), 609 ast::Linkage::Cforall, 610 (ast::Expr *)nullptr 611 ), 612 }, // params 613 {}, // returns 614 (ast::CompoundStmt *)nullptr, 615 ast::Storage::Classes(), 616 ast::Linkage::Cforall 617 ) ); 618 619 spliceBegin( mutTypeDecl->assertions, newAssertions ); 620 } // for 621 } 622 623 624 void buildForall( 625 const DeclarationNode * firstNode, 626 std::vector<ast::ptr<ast::TypeDecl>> &outputForall ) { 627 buildList( firstNode, outputForall ); 628 auto n = firstNode; 629 for ( auto i = outputForall.begin() ; 630 i != outputForall.end() ; 631 ++i, n = (DeclarationNode*)n->get_next() ) { 632 // Only the object type class adds additional assertions. 633 if ( n->variable.tyClass != ast::TypeDecl::Otype ) { 634 continue; 635 } 636 637 ast::TypeDecl const * td = i->strict_as<ast::TypeDecl>(); 638 std::vector<ast::ptr<ast::DeclWithType>> newAssertions; 639 auto mutTypeDecl = ast::mutate( td ); 640 const CodeLocation & location = mutTypeDecl->location; 641 *i = mutTypeDecl; 642 643 // add assertion parameters to `type' tyvars in reverse order 644 // add assignment operator: T * ?=?(T *, T) 645 newAssertions.push_back( new ast::FunctionDecl( 646 location, 647 "?=?", 648 {}, // forall 649 {}, // assertions 650 { 651 new ast::ObjectDecl( 652 location, 653 "", 654 new ast::ReferenceType( new ast::TypeInstType( td->name, *i ) ), 655 (ast::Init *)nullptr, 656 ast::Storage::Classes(), 657 ast::Linkage::Cforall, 658 (ast::Expr *)nullptr 659 ), 660 new ast::ObjectDecl( 661 location, 662 "", 663 new ast::TypeInstType( td->name, *i ), 664 (ast::Init *)nullptr, 665 ast::Storage::Classes(), 666 ast::Linkage::Cforall, 667 (ast::Expr *)nullptr 668 ), 669 }, // params 670 { 671 new ast::ObjectDecl( 672 location, 673 "", 674 new ast::TypeInstType( td->name, *i ), 675 (ast::Init *)nullptr, 676 ast::Storage::Classes(), 677 ast::Linkage::Cforall, 678 (ast::Expr *)nullptr 679 ), 680 }, // returns 681 (ast::CompoundStmt *)nullptr, 682 ast::Storage::Classes(), 683 ast::Linkage::Cforall 684 ) ); 685 686 // add default ctor: void ?{}(T *) 687 newAssertions.push_back( new ast::FunctionDecl( 688 location, 689 "?{}", 690 {}, // forall 691 {}, // assertions 692 { 693 new ast::ObjectDecl( 694 location, 695 "", 696 new ast::ReferenceType( 697 new ast::TypeInstType( td->name, i->get() ) ), 698 (ast::Init *)nullptr, 699 ast::Storage::Classes(), 700 ast::Linkage::Cforall, 701 (ast::Expr *)nullptr 702 ), 703 }, // params 704 {}, // returns 705 (ast::CompoundStmt *)nullptr, 706 ast::Storage::Classes(), 707 ast::Linkage::Cforall 708 ) ); 709 710 // add copy ctor: void ?{}(T *, T) 711 newAssertions.push_back( new ast::FunctionDecl( 712 location, 713 "?{}", 714 {}, // forall 715 {}, // assertions 716 { 717 new ast::ObjectDecl( 718 location, 719 "", 720 new ast::ReferenceType( 721 new ast::TypeInstType( td->name, *i ) ), 722 (ast::Init *)nullptr, 723 ast::Storage::Classes(), 724 ast::Linkage::Cforall, 725 (ast::Expr *)nullptr 726 ), 727 new ast::ObjectDecl( 728 location, 729 "", 730 new ast::TypeInstType( td->name, *i ), 731 (ast::Init *)nullptr, 732 ast::Storage::Classes(), 733 ast::Linkage::Cforall, 734 (ast::Expr *)nullptr 735 ), 736 }, // params 737 {}, // returns 738 (ast::CompoundStmt *)nullptr, 739 ast::Storage::Classes(), 740 ast::Linkage::Cforall 741 ) ); 742 743 // add dtor: void ^?{}(T *) 744 newAssertions.push_back( new ast::FunctionDecl( 745 location, 746 "^?{}", 747 {}, // forall 748 {}, // assertions 749 { 750 new ast::ObjectDecl( 751 location, 752 "", 753 new ast::ReferenceType( 754 new ast::TypeInstType( i->get() ) 755 ), 756 (ast::Init *)nullptr, 757 ast::Storage::Classes(), 758 ast::Linkage::Cforall, 759 (ast::Expr *)nullptr 760 ), 761 }, // params 762 {}, // returns 763 (ast::CompoundStmt *)nullptr, 764 ast::Storage::Classes(), 765 ast::Linkage::Cforall 766 ) ); 767 768 spliceBegin( mutTypeDecl->assertions, newAssertions ); 525 769 } // for 526 770 } // buildForall 527 771 528 772 529 Type * typebuild( const TypeData * td ) {773 ast::Type * typebuild( const TypeData * td ) { 530 774 assert( td ); 531 775 switch ( td->kind ) { 532 776 case TypeData::Unknown: 533 777 // fill in implicit int 534 return new BasicType( buildQualifiers( td ), BasicType::SignedInt ); 535 case TypeData::Basic: 778 return new ast::BasicType( 779 ast::BasicType::SignedInt, 780 buildQualifiers( td ) 781 ); 782 case TypeData::Basic: 536 783 return buildBasicType( td ); 537 784 case TypeData::Pointer: 538 785 return buildPointer( td ); 539 786 case TypeData::Array: 540 787 return buildArray( td ); 541 788 case TypeData::Reference: 542 789 return buildReference( td ); 543 544 return buildFunction ( td );545 790 case TypeData::Function: 791 return buildFunctionType( td ); 792 case TypeData::AggregateInst: 546 793 return buildAggInst( td ); 547 548 return new EnumInstType( buildQualifiers( td ), "");549 794 case TypeData::EnumConstant: 795 return new ast::EnumInstType( "", buildQualifiers( td ) ); 796 case TypeData::SymbolicInst: 550 797 return buildSymbolicInst( td ); 551 798 case TypeData::Tuple: 552 799 return buildTuple( td ); 553 554 800 case TypeData::Typeof: 801 case TypeData::Basetypeof: 555 802 return buildTypeof( td ); 556 803 case TypeData::Vtable: 557 804 return buildVtable( td ); 558 805 case TypeData::Builtin: 559 806 switch ( td->builtintype ) { 560 561 return new ZeroType( noQualifiers);562 563 return new OneType( noQualifiers);564 565 return new VarArgsType( buildQualifiers( td ) );807 case DeclarationNode::Zero: 808 return new ast::ZeroType(); 809 case DeclarationNode::One: 810 return new ast::OneType(); 811 default: 812 return new ast::VarArgsType( buildQualifiers( td ) ); 566 813 } // switch 567 case TypeData::GlobalScope: 568 return new GlobalScopeType(); 569 case TypeData::Qualified: 570 return new QualifiedType( buildQualifiers( td ), typebuild( td->qualified.parent ), typebuild( td->qualified.child ) ); 571 case TypeData::Symbolic: 572 case TypeData::Enum: 573 case TypeData::Aggregate: 814 case TypeData::GlobalScope: 815 return new ast::GlobalScopeType(); 816 case TypeData::Qualified: 817 return new ast::QualifiedType( 818 typebuild( td->qualified.parent ), 819 typebuild( td->qualified.child ), 820 buildQualifiers( td ) 821 ); 822 case TypeData::Symbolic: 823 case TypeData::Enum: 824 case TypeData::Aggregate: 574 825 assert( false ); 575 826 } // switch … … 583 834 584 835 switch ( td->kind ) { 585 836 case TypeData::Aggregate: 586 837 if ( ! toplevel && td->aggregate.body ) { 587 838 ret = td->clone(); 588 839 } // if 589 840 break; 590 841 case TypeData::Enum: 591 842 if ( ! toplevel && td->enumeration.body ) { 592 843 ret = td->clone(); 593 844 } // if 594 845 break; 595 846 case TypeData::AggregateInst: 596 847 if ( td->aggInst.aggregate ) { 597 848 ret = typeextractAggregate( td->aggInst.aggregate, false ); 598 849 } // if 599 850 break; 600 851 default: 601 852 if ( td->base ) { 602 853 ret = typeextractAggregate( td->base, false ); … … 607 858 608 859 609 Type::Qualifiers buildQualifiers( const TypeData * td ) {860 ast::CV::Qualifiers buildQualifiers( const TypeData * td ) { 610 861 return td->qualifiers; 611 862 } // buildQualifiers … … 616 867 } // genTSError 617 868 618 Type * buildBasicType( const TypeData * td ) {619 BasicType::Kind ret;869 ast::Type * buildBasicType( const TypeData * td ) { 870 ast::BasicType::Kind ret; 620 871 621 872 switch ( td->basictype ) { 622 873 case DeclarationNode::Void: 623 874 if ( td->signedness != DeclarationNode::NoSignedness ) { 624 875 genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype ); … … 627 878 genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype ); 628 879 } // if 629 return new VoidType( buildQualifiers( td ) );630 break; 631 632 880 return new ast::VoidType( buildQualifiers( td ) ); 881 break; 882 883 case DeclarationNode::Bool: 633 884 if ( td->signedness != DeclarationNode::NoSignedness ) { 634 885 genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype ); … … 638 889 } // if 639 890 640 ret = BasicType::Bool;641 break; 642 643 891 ret = ast::BasicType::Bool; 892 break; 893 894 case DeclarationNode::Char: 644 895 // C11 Standard 6.2.5.15: The three types char, signed char, and unsigned char are collectively called the 645 896 // character types. The implementation shall define char to have the same range, representation, and behavior as 646 897 // either signed char or unsigned char. 647 static BasicType::Kind chartype[] = { BasicType::SignedChar, BasicType::UnsignedChar,BasicType::Char };898 static ast::BasicType::Kind chartype[] = { ast::BasicType::SignedChar, ast::BasicType::UnsignedChar, ast::BasicType::Char }; 648 899 649 900 if ( td->length != DeclarationNode::NoLength ) { … … 654 905 break; 655 906 656 657 static BasicType::Kind inttype[2][4] = {658 { BasicType::ShortSignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt,BasicType::SignedInt },659 { BasicType::ShortUnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt,BasicType::UnsignedInt },907 case DeclarationNode::Int: 908 static ast::BasicType::Kind inttype[2][4] = { 909 { ast::BasicType::ShortSignedInt, ast::BasicType::LongSignedInt, ast::BasicType::LongLongSignedInt, ast::BasicType::SignedInt }, 910 { ast::BasicType::ShortUnsignedInt, ast::BasicType::LongUnsignedInt, ast::BasicType::LongLongUnsignedInt, ast::BasicType::UnsignedInt }, 660 911 }; 661 912 662 913 Integral: ; 663 914 if ( td->signedness == DeclarationNode::NoSignedness ) { 664 915 const_cast<TypeData *>(td)->signedness = DeclarationNode::Signed; … … 667 918 break; 668 919 669 670 ret = td->signedness == DeclarationNode::Unsigned ? BasicType::UnsignedInt128 :BasicType::SignedInt128;920 case DeclarationNode::Int128: 921 ret = td->signedness == DeclarationNode::Unsigned ? ast::BasicType::UnsignedInt128 : ast::BasicType::SignedInt128; 671 922 if ( td->length != DeclarationNode::NoLength ) { 672 923 genTSError( DeclarationNode::lengthNames[ td->length ], td->basictype ); … … 674 925 break; 675 926 676 677 678 679 680 681 682 683 684 685 686 687 688 static BasicType::Kind floattype[2][12] = {689 { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex, (BasicType::Kind)-1, (BasicType::Kind)-1, BasicType::uFloat16Complex, BasicType::uFloat32Complex, BasicType::uFloat32xComplex, BasicType::uFloat64Complex, BasicType::uFloat64xComplex, BasicType::uFloat128Complex,BasicType::uFloat128xComplex, },690 { BasicType::Float, BasicType::Double, BasicType::LongDouble, BasicType::uuFloat80, BasicType::uuFloat128, BasicType::uFloat16, BasicType::uFloat32, BasicType::uFloat32x, BasicType::uFloat64, BasicType::uFloat64x, BasicType::uFloat128,BasicType::uFloat128x, },927 case DeclarationNode::Float: 928 case DeclarationNode::Double: 929 case DeclarationNode::LongDouble: // not set until below 930 case DeclarationNode::uuFloat80: 931 case DeclarationNode::uuFloat128: 932 case DeclarationNode::uFloat16: 933 case DeclarationNode::uFloat32: 934 case DeclarationNode::uFloat32x: 935 case DeclarationNode::uFloat64: 936 case DeclarationNode::uFloat64x: 937 case DeclarationNode::uFloat128: 938 case DeclarationNode::uFloat128x: 939 static ast::BasicType::Kind floattype[2][12] = { 940 { ast::BasicType::FloatComplex, ast::BasicType::DoubleComplex, ast::BasicType::LongDoubleComplex, (ast::BasicType::Kind)-1, (ast::BasicType::Kind)-1, ast::BasicType::uFloat16Complex, ast::BasicType::uFloat32Complex, ast::BasicType::uFloat32xComplex, ast::BasicType::uFloat64Complex, ast::BasicType::uFloat64xComplex, ast::BasicType::uFloat128Complex, ast::BasicType::uFloat128xComplex, }, 941 { ast::BasicType::Float, ast::BasicType::Double, ast::BasicType::LongDouble, ast::BasicType::uuFloat80, ast::BasicType::uuFloat128, ast::BasicType::uFloat16, ast::BasicType::uFloat32, ast::BasicType::uFloat32x, ast::BasicType::uFloat64, ast::BasicType::uFloat64x, ast::BasicType::uFloat128, ast::BasicType::uFloat128x, }, 691 942 }; 692 943 693 944 FloatingPoint: ; 694 945 if ( td->signedness != DeclarationNode::NoSignedness ) { 695 946 genTSError( DeclarationNode::signednessNames[ td->signedness ], td->basictype ); … … 715 966 break; 716 967 717 968 case DeclarationNode::NoBasicType: 718 969 // No basic type in declaration => default double for Complex/Imaginary and int type for integral types 719 970 if ( td->complextype == DeclarationNode::Complex || td->complextype == DeclarationNode::Imaginary ) { … … 724 975 const_cast<TypeData *>(td)->basictype = DeclarationNode::Int; 725 976 goto Integral; 726 727 977 default: 978 assertf( false, "unknown basic type" ); 728 979 return nullptr; 729 980 } // switch 730 981 731 BasicType * bt = new BasicType( buildQualifiers( td ), ret ); 732 buildForall( td->forall, bt->get_forall() ); 982 ast::BasicType * bt = new ast::BasicType( ret, buildQualifiers( td ) ); 733 983 return bt; 734 984 } // buildBasicType 735 985 736 986 737 PointerType * buildPointer( const TypeData * td ) {738 PointerType * pt;987 ast::PointerType * buildPointer( const TypeData * td ) { 988 ast::PointerType * pt; 739 989 if ( td->base ) { 740 pt = new PointerType( buildQualifiers( td ), typebuild( td->base ) ); 990 pt = new ast::PointerType( 991 typebuild( td->base ), 992 buildQualifiers( td ) 993 ); 741 994 } else { 742 pt = new PointerType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 995 pt = new ast::PointerType( 996 new ast::BasicType( ast::BasicType::SignedInt ), 997 buildQualifiers( td ) 998 ); 743 999 } // if 744 buildForall( td->forall, pt->get_forall() );745 1000 return pt; 746 1001 } // buildPointer 747 1002 748 1003 749 ArrayType * buildArray( const TypeData * td ) {750 ArrayType * at;1004 ast::ArrayType * buildArray( const TypeData * td ) { 1005 ast::ArrayType * at; 751 1006 if ( td->base ) { 752 at = new ArrayType( buildQualifiers( td ), typebuild( td->base ), maybeBuild< Expression >( td->array.dimension ), 753 td->array.isVarLen, td->array.isStatic ); 1007 at = new ast::ArrayType( 1008 typebuild( td->base ), 1009 maybeBuild( td->array.dimension ), 1010 td->array.isVarLen ? ast::VariableLen : ast::FixedLen, 1011 td->array.isStatic ? ast::StaticDim : ast::DynamicDim, 1012 buildQualifiers( td ) 1013 ); 754 1014 } else { 755 at = new ArrayType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ), 756 maybeBuild< Expression >( td->array.dimension ), td->array.isVarLen, td->array.isStatic ); 1015 at = new ast::ArrayType( 1016 new ast::BasicType( ast::BasicType::SignedInt ), 1017 maybeBuild( td->array.dimension ), 1018 td->array.isVarLen ? ast::VariableLen : ast::FixedLen, 1019 td->array.isStatic ? ast::StaticDim : ast::DynamicDim, 1020 buildQualifiers( td ) 1021 ); 757 1022 } // if 758 buildForall( td->forall, at->get_forall() );759 1023 return at; 760 1024 } // buildArray 761 1025 762 1026 763 ReferenceType * buildReference( const TypeData * td ) {764 ReferenceType * rt;1027 ast::ReferenceType * buildReference( const TypeData * td ) { 1028 ast::ReferenceType * rt; 765 1029 if ( td->base ) { 766 rt = new ReferenceType( buildQualifiers( td ), typebuild( td->base ) ); 1030 rt = new ast::ReferenceType( 1031 typebuild( td->base ), 1032 buildQualifiers( td ) 1033 ); 767 1034 } else { 768 rt = new ReferenceType( buildQualifiers( td ), new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 1035 rt = new ast::ReferenceType( 1036 new ast::BasicType( ast::BasicType::SignedInt ), 1037 buildQualifiers( td ) 1038 ); 769 1039 } // if 770 buildForall( td->forall, rt->get_forall() );771 1040 return rt; 772 1041 } // buildReference 773 1042 774 1043 775 AggregateDecl * buildAggregate( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) {1044 ast::AggregateDecl * buildAggregate( const TypeData * td, std::vector<ast::ptr<ast::Attribute>> attributes, ast::Linkage::Spec linkage ) { 776 1045 assert( td->kind == TypeData::Aggregate ); 777 AggregateDecl * at;1046 ast::AggregateDecl * at; 778 1047 switch ( td->aggregate.kind ) { 779 case AggregateDecl::Struct: 780 case AggregateDecl::Coroutine: 781 case AggregateDecl::Exception: 782 case AggregateDecl::Generator: 783 case AggregateDecl::Monitor: 784 case AggregateDecl::Thread: 785 at = new StructDecl( *td->aggregate.name, td->aggregate.kind, attributes, linkage ); 786 buildForall( td->aggregate.params, at->get_parameters() ); 787 break; 788 case AggregateDecl::Union: 789 at = new UnionDecl( *td->aggregate.name, attributes, linkage ); 790 buildForall( td->aggregate.params, at->get_parameters() ); 791 break; 792 case AggregateDecl::Trait: 793 at = new TraitDecl( *td->aggregate.name, attributes, linkage ); 794 buildList( td->aggregate.params, at->get_parameters() ); 795 break; 796 default: 1048 case ast::AggregateDecl::Struct: 1049 case ast::AggregateDecl::Coroutine: 1050 case ast::AggregateDecl::Exception: 1051 case ast::AggregateDecl::Generator: 1052 case ast::AggregateDecl::Monitor: 1053 case ast::AggregateDecl::Thread: 1054 at = new ast::StructDecl( td->location, 1055 *td->aggregate.name, 1056 td->aggregate.kind, 1057 std::move( attributes ), 1058 linkage 1059 ); 1060 buildForall( td->aggregate.params, at->params ); 1061 break; 1062 case ast::AggregateDecl::Union: 1063 at = new ast::UnionDecl( td->location, 1064 *td->aggregate.name, 1065 std::move( attributes ), 1066 linkage 1067 ); 1068 buildForall( td->aggregate.params, at->params ); 1069 break; 1070 case ast::AggregateDecl::Trait: 1071 at = new ast::TraitDecl( td->location, 1072 *td->aggregate.name, 1073 std::move( attributes ), 1074 linkage 1075 ); 1076 buildList( td->aggregate.params, at->params ); 1077 break; 1078 default: 797 1079 assert( false ); 798 1080 } // switch 799 1081 800 buildList( td->aggregate.fields, at-> get_members());1082 buildList( td->aggregate.fields, at->members ); 801 1083 at->set_body( td->aggregate.body ); 802 1084 … … 805 1087 806 1088 807 ReferenceToType * buildComAggInst( const TypeData * type, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) { 1089 ast::BaseInstType * buildComAggInst( 1090 const TypeData * type, 1091 std::vector<ast::ptr<ast::Attribute>> && attributes, 1092 ast::Linkage::Spec linkage ) { 808 1093 switch ( type->kind ) { 809 case TypeData::Enum: { 810 if ( type->enumeration.body ) { 811 EnumDecl * typedecl = buildEnum( type, attributes, linkage ); 812 return new EnumInstType( buildQualifiers( type ), typedecl ); 813 } else { 814 return new EnumInstType( buildQualifiers( type ), *type->enumeration.name ); 815 } // if 816 } 817 case TypeData::Aggregate: { 818 ReferenceToType * ret; 819 if ( type->aggregate.body ) { 820 AggregateDecl * typedecl = buildAggregate( type, attributes, linkage ); 821 switch ( type->aggregate.kind ) { 822 case AggregateDecl::Struct: 823 case AggregateDecl::Coroutine: 824 case AggregateDecl::Monitor: 825 case AggregateDecl::Thread: 826 ret = new StructInstType( buildQualifiers( type ), (StructDecl *)typedecl ); 827 break; 828 case AggregateDecl::Union: 829 ret = new UnionInstType( buildQualifiers( type ), (UnionDecl *)typedecl ); 830 break; 831 case AggregateDecl::Trait: 832 assert( false ); 833 //ret = new TraitInstType( buildQualifiers( type ), (TraitDecl *)typedecl ); 834 break; 835 default: 836 assert( false ); 837 } // switch 838 } else { 839 switch ( type->aggregate.kind ) { 840 case AggregateDecl::Struct: 841 case AggregateDecl::Coroutine: 842 case AggregateDecl::Monitor: 843 case AggregateDecl::Thread: 844 ret = new StructInstType( buildQualifiers( type ), *type->aggregate.name ); 845 break; 846 case AggregateDecl::Union: 847 ret = new UnionInstType( buildQualifiers( type ), *type->aggregate.name ); 848 break; 849 case AggregateDecl::Trait: 850 ret = new TraitInstType( buildQualifiers( type ), *type->aggregate.name ); 851 break; 852 default: 853 assert( false ); 854 } // switch 855 } // if 856 return ret; 857 } 858 default: 1094 case TypeData::Enum: 1095 if ( type->enumeration.body ) { 1096 ast::EnumDecl * typedecl = 1097 buildEnum( type, std::move( attributes ), linkage ); 1098 return new ast::EnumInstType( 1099 typedecl, 1100 buildQualifiers( type ) 1101 ); 1102 } else { 1103 return new ast::EnumInstType( 1104 *type->enumeration.name, 1105 buildQualifiers( type ) 1106 ); 1107 } // if 1108 break; 1109 case TypeData::Aggregate: 1110 if ( type->aggregate.body ) { 1111 ast::AggregateDecl * typedecl = 1112 buildAggregate( type, std::move( attributes ), linkage ); 1113 switch ( type->aggregate.kind ) { 1114 case ast::AggregateDecl::Struct: 1115 case ast::AggregateDecl::Coroutine: 1116 case ast::AggregateDecl::Monitor: 1117 case ast::AggregateDecl::Thread: 1118 return new ast::StructInstType( 1119 strict_dynamic_cast<ast::StructDecl *>( typedecl ), 1120 buildQualifiers( type ) 1121 ); 1122 case ast::AggregateDecl::Union: 1123 return new ast::UnionInstType( 1124 strict_dynamic_cast<ast::UnionDecl *>( typedecl ), 1125 buildQualifiers( type ) 1126 ); 1127 case ast::AggregateDecl::Trait: 1128 assert( false ); 1129 break; 1130 default: 1131 assert( false ); 1132 } // switch 1133 } else { 1134 switch ( type->aggregate.kind ) { 1135 case ast::AggregateDecl::Struct: 1136 case ast::AggregateDecl::Coroutine: 1137 case ast::AggregateDecl::Monitor: 1138 case ast::AggregateDecl::Thread: 1139 return new ast::StructInstType( 1140 *type->aggregate.name, 1141 buildQualifiers( type ) 1142 ); 1143 case ast::AggregateDecl::Union: 1144 return new ast::UnionInstType( 1145 *type->aggregate.name, 1146 buildQualifiers( type ) 1147 ); 1148 case ast::AggregateDecl::Trait: 1149 return new ast::TraitInstType( 1150 *type->aggregate.name, 1151 buildQualifiers( type ) 1152 ); 1153 default: 1154 assert( false ); 1155 } // switch 1156 break; 1157 } // if 1158 break; 1159 default: 859 1160 assert( false ); 860 1161 } // switch 1162 assert( false ); 861 1163 } // buildAggInst 862 1164 863 1165 864 ReferenceToType * buildAggInst( const TypeData * td ) {1166 ast::BaseInstType * buildAggInst( const TypeData * td ) { 865 1167 assert( td->kind == TypeData::AggregateInst ); 866 1168 867 // ReferenceToType * ret = buildComAggInst( td->aggInst.aggregate, std::list< Attribute * >() ); 868 ReferenceToType * ret = nullptr; 1169 ast::BaseInstType * ret = nullptr; 869 1170 TypeData * type = td->aggInst.aggregate; 870 1171 switch ( type->kind ) { 871 case TypeData::Enum: { 872 return new EnumInstType( buildQualifiers( type ), *type->enumeration.name ); 873 } 874 case TypeData::Aggregate: { 875 switch ( type->aggregate.kind ) { 876 case AggregateDecl::Struct: 877 case AggregateDecl::Coroutine: 878 case AggregateDecl::Monitor: 879 case AggregateDecl::Thread: 880 ret = new StructInstType( buildQualifiers( type ), *type->aggregate.name ); 881 break; 882 case AggregateDecl::Union: 883 ret = new UnionInstType( buildQualifiers( type ), *type->aggregate.name ); 884 break; 885 case AggregateDecl::Trait: 886 ret = new TraitInstType( buildQualifiers( type ), *type->aggregate.name ); 887 break; 888 default: 889 assert( false ); 890 } // switch 891 } 892 break; 893 default: 1172 case TypeData::Enum: 1173 return new ast::EnumInstType( 1174 *type->enumeration.name, 1175 buildQualifiers( type ) 1176 ); 1177 case TypeData::Aggregate: 1178 switch ( type->aggregate.kind ) { 1179 case ast::AggregateDecl::Struct: 1180 case ast::AggregateDecl::Coroutine: 1181 case ast::AggregateDecl::Monitor: 1182 case ast::AggregateDecl::Thread: 1183 ret = new ast::StructInstType( 1184 *type->aggregate.name, 1185 buildQualifiers( type ) 1186 ); 1187 break; 1188 case ast::AggregateDecl::Union: 1189 ret = new ast::UnionInstType( 1190 *type->aggregate.name, 1191 buildQualifiers( type ) 1192 ); 1193 break; 1194 case ast::AggregateDecl::Trait: 1195 ret = new ast::TraitInstType( 1196 *type->aggregate.name, 1197 buildQualifiers( type ) 1198 ); 1199 break; 1200 default: 1201 assert( false ); 1202 } // switch 1203 break; 1204 default: 894 1205 assert( false ); 895 1206 } // switch 896 1207 897 ret->set_hoistType( td->aggInst.hoistType ); 898 buildList( td->aggInst.params, ret->get_parameters() ); 899 buildForall( td->forall, ret->get_forall() ); 1208 ret->hoistType = td->aggInst.hoistType; 1209 buildList( td->aggInst.params, ret->params ); 900 1210 return ret; 901 1211 } // buildAggInst 902 1212 903 1213 904 NamedTypeDecl * buildSymbolic( const TypeData * td, std::list< Attribute * > attributes, const string & name, Type::StorageClasses scs, LinkageSpec::Spec linkage ) { 1214 ast::NamedTypeDecl * buildSymbolic( 1215 const TypeData * td, 1216 std::vector<ast::ptr<ast::Attribute>> attributes, 1217 const std::string & name, 1218 ast::Storage::Classes scs, 1219 ast::Linkage::Spec linkage ) { 905 1220 assert( td->kind == TypeData::Symbolic ); 906 NamedTypeDecl * ret;1221 ast::NamedTypeDecl * ret; 907 1222 assert( td->base ); 908 1223 if ( td->symbolic.isTypedef ) { 909 ret = new TypedefDecl( name, td->location, scs, typebuild( td->base ), linkage ); 1224 ret = new ast::TypedefDecl( 1225 td->location, 1226 name, 1227 scs, 1228 typebuild( td->base ), 1229 linkage 1230 ); 910 1231 } else { 911 ret = new TypeDecl( name, scs, typebuild( td->base ), TypeDecl::Dtype, true ); 1232 ret = new ast::TypeDecl( 1233 td->location, 1234 name, 1235 scs, 1236 typebuild( td->base ), 1237 ast::TypeDecl::Dtype, 1238 true 1239 ); 912 1240 } // if 913 buildList( td->symbolic.assertions, ret-> get_assertions());914 ret->base->attributes.splice( ret->base->attributes.end(), attributes );1241 buildList( td->symbolic.assertions, ret->assertions ); 1242 splice( ret->base.get_and_mutate()->attributes, attributes ); 915 1243 return ret; 916 1244 } // buildSymbolic 917 1245 918 1246 919 EnumDecl * buildEnum( const TypeData * td, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ) { 1247 ast::EnumDecl * buildEnum( 1248 const TypeData * td, 1249 std::vector<ast::ptr<ast::Attribute>> && attributes, 1250 ast::Linkage::Spec linkage ) { 920 1251 assert( td->kind == TypeData::Enum ); 921 Type * baseType = td->base ? typebuild(td->base) : nullptr; 922 EnumDecl * ret = new EnumDecl( *td->enumeration.name, attributes, td->enumeration.typed, linkage, baseType ); 923 buildList( td->enumeration.constants, ret->get_members() ); 924 list< Declaration * >::iterator members = ret->get_members().begin(); 925 ret->hide = td->enumeration.hiding == EnumHiding::Hide ? EnumDecl::EnumHiding::Hide : EnumDecl::EnumHiding::Visible; 1252 ast::Type * baseType = td->base ? typebuild(td->base) : nullptr; 1253 ast::EnumDecl * ret = new ast::EnumDecl( 1254 td->location, 1255 *td->enumeration.name, 1256 td->enumeration.typed, 1257 std::move( attributes ), 1258 linkage, 1259 baseType 1260 ); 1261 buildList( td->enumeration.constants, ret->members ); 1262 auto members = ret->members.begin(); 1263 ret->hide = td->enumeration.hiding == EnumHiding::Hide ? ast::EnumDecl::EnumHiding::Hide : ast::EnumDecl::EnumHiding::Visible; 926 1264 for ( const DeclarationNode * cur = td->enumeration.constants; cur != nullptr; cur = dynamic_cast< DeclarationNode * >( cur->get_next() ), ++members ) { 927 1265 if ( cur->enumInLine ) { … … 930 1268 SemanticError( td->location, "Enumerator of enum(void) cannot have an explicit initializer value." ); 931 1269 } else if ( cur->has_enumeratorValue() ) { 932 ObjectDecl * member = dynamic_cast< ObjectDecl * >(* members); 933 member->set_init( new SingleInit( maybeMoveBuild< Expression >( cur->consume_enumeratorValue() ) ) ); 1270 ast::Decl * member = members->get_and_mutate(); 1271 ast::ObjectDecl * object = strict_dynamic_cast<ast::ObjectDecl *>( member ); 1272 object->init = new ast::SingleInit( 1273 td->location, 1274 maybeMoveBuild( cur->consume_enumeratorValue() ), 1275 ast::NoConstruct 1276 ); 934 1277 } else if ( !cur->initializer ) { 935 if ( baseType && (!dynamic_cast< BasicType *>(baseType) || !dynamic_cast<BasicType *>(baseType)->isInteger())) {1278 if ( baseType && (!dynamic_cast<ast::BasicType *>(baseType) || !dynamic_cast<ast::BasicType *>(baseType)->isInteger())) { 936 1279 SemanticError( td->location, "Enumerators of an non-integer typed enum must be explicitly initialized." ); 937 1280 } … … 940 1283 // if 941 1284 } // for 942 ret-> set_body( td->enumeration.body );1285 ret->body = td->enumeration.body; 943 1286 return ret; 944 1287 } // buildEnum 945 1288 946 1289 947 TypeInstType * buildSymbolicInst( const TypeData * td ) {1290 ast::TypeInstType * buildSymbolicInst( const TypeData * td ) { 948 1291 assert( td->kind == TypeData::SymbolicInst ); 949 TypeInstType * ret = new TypeInstType( buildQualifiers( td ), *td->symbolic.name, false ); 950 buildList( td->symbolic.actuals, ret->get_parameters() ); 951 buildForall( td->forall, ret->get_forall() ); 1292 ast::TypeInstType * ret = new ast::TypeInstType( 1293 *td->symbolic.name, 1294 ast::TypeDecl::Dtype, 1295 buildQualifiers( td ) 1296 ); 1297 buildList( td->symbolic.actuals, ret->params ); 952 1298 return ret; 953 1299 } // buildSymbolicInst 954 1300 955 1301 956 TupleType * buildTuple( const TypeData * td ) {1302 ast::TupleType * buildTuple( const TypeData * td ) { 957 1303 assert( td->kind == TypeData::Tuple ); 958 std:: list< Type *> types;1304 std::vector<ast::ptr<ast::Type>> types; 959 1305 buildTypeList( td->tuple, types ); 960 TupleType * ret = new TupleType( buildQualifiers( td ), types ); 961 buildForall( td->forall, ret->get_forall() ); 1306 ast::TupleType * ret = new ast::TupleType( 1307 std::move( types ), 1308 buildQualifiers( td ) 1309 ); 962 1310 return ret; 963 1311 } // buildTuple 964 1312 965 1313 966 TypeofType * buildTypeof( const TypeData * td ) {1314 ast::TypeofType * buildTypeof( const TypeData * td ) { 967 1315 assert( td->kind == TypeData::Typeof || td->kind == TypeData::Basetypeof ); 968 1316 assert( td->typeexpr ); 969 // assert( td->typeexpr->expr ); 970 return new TypeofType{ buildQualifiers( td ), td->typeexpr->build(), td->kind == TypeData::Basetypeof }; 1317 return new ast::TypeofType( 1318 td->typeexpr->build(), 1319 td->kind == TypeData::Typeof 1320 ? ast::TypeofType::Typeof : ast::TypeofType::Basetypeof, 1321 buildQualifiers( td ) 1322 ); 971 1323 } // buildTypeof 972 1324 973 1325 974 VTableType * buildVtable( const TypeData * td ) {1326 ast::VTableType * buildVtable( const TypeData * td ) { 975 1327 assert( td->base ); 976 return new VTableType{ buildQualifiers( td ), typebuild( td->base ) }; 1328 return new ast::VTableType( 1329 typebuild( td->base ), 1330 buildQualifiers( td ) 1331 ); 977 1332 } // buildVtable 978 1333 979 1334 980 Declaration * buildDecl( const TypeData * td, const string &name, Type::StorageClasses scs, Expression * bitfieldWidth, Type::FuncSpecifiers funcSpec, LinkageSpec::Spec linkage, Expression *asmName, Initializer * init, std::list< Attribute * > attributes ) { 1335 ast::FunctionDecl * buildFunctionDecl( 1336 const TypeData * td, 1337 const string &name, 1338 ast::Storage::Classes scs, 1339 ast::Function::Specs funcSpec, 1340 ast::Linkage::Spec linkage, 1341 ast::Expr * asmName, 1342 std::vector<ast::ptr<ast::Attribute>> && attributes ) { 1343 assert( td->kind == TypeData::Function ); 1344 // For some reason FunctionDecl takes a bool instead of an ArgumentFlag. 1345 bool isVarArgs = !td->function.params || td->function.params->hasEllipsis; 1346 ast::CV::Qualifiers cvq = buildQualifiers( td ); 1347 std::vector<ast::ptr<ast::TypeDecl>> forall; 1348 std::vector<ast::ptr<ast::DeclWithType>> assertions; 1349 std::vector<ast::ptr<ast::DeclWithType>> params; 1350 std::vector<ast::ptr<ast::DeclWithType>> returns; 1351 buildList( td->function.params, params ); 1352 buildForall( td->forall, forall ); 1353 // Functions do not store their assertions there anymore. 1354 for ( ast::ptr<ast::TypeDecl> & type_param : forall ) { 1355 auto mut = type_param.get_and_mutate(); 1356 splice( assertions, mut->assertions ); 1357 } 1358 if ( td->base ) { 1359 switch ( td->base->kind ) { 1360 case TypeData::Tuple: 1361 buildList( td->base->tuple, returns ); 1362 break; 1363 default: 1364 returns.push_back( dynamic_cast<ast::DeclWithType *>( 1365 buildDecl( 1366 td->base, 1367 "", 1368 ast::Storage::Classes(), 1369 (ast::Expr *)nullptr, // bitfieldWidth 1370 ast::Function::Specs(), 1371 ast::Linkage::Cforall, 1372 (ast::Expr *)nullptr // asmName 1373 ) 1374 ) ); 1375 } // switch 1376 } else { 1377 returns.push_back( new ast::ObjectDecl( 1378 td->location, 1379 "", 1380 new ast::BasicType( ast::BasicType::SignedInt ), 1381 (ast::Init *)nullptr, 1382 ast::Storage::Classes(), 1383 ast::Linkage::Cforall 1384 ) ); 1385 } // if 1386 ast::Stmt * stmt = maybeBuild( td->function.body ); 1387 ast::CompoundStmt * body = dynamic_cast<ast::CompoundStmt *>( stmt ); 1388 ast::FunctionDecl * decl = new ast::FunctionDecl( td->location, 1389 name, 1390 std::move( forall ), 1391 std::move( assertions ), 1392 std::move( params ), 1393 std::move( returns ), 1394 body, 1395 scs, 1396 linkage, 1397 std::move( attributes ), 1398 funcSpec, 1399 (isVarArgs) ? ast::VariableArgs : ast::FixedArgs 1400 ); 1401 buildList( td->function.withExprs, decl->withExprs ); 1402 decl->asmName = asmName; 1403 // This may be redundant on a declaration. 1404 decl->type.get_and_mutate()->qualifiers = cvq; 1405 return decl; 1406 } // buildFunctionDecl 1407 1408 1409 ast::Decl * buildDecl( 1410 const TypeData * td, 1411 const string &name, 1412 ast::Storage::Classes scs, 1413 ast::Expr * bitfieldWidth, 1414 ast::Function::Specs funcSpec, 1415 ast::Linkage::Spec linkage, 1416 ast::Expr * asmName, 1417 ast::Init * init, 1418 std::vector<ast::ptr<ast::Attribute>> && attributes ) { 981 1419 if ( td->kind == TypeData::Function ) { 982 1420 if ( td->function.idList ) { // KR function ? … … 984 1422 } // if 985 1423 986 FunctionDecl * decl; 987 Statement * stmt = maybeBuild<Statement>( td->function.body ); 988 CompoundStmt * body = dynamic_cast< CompoundStmt * >( stmt ); 989 decl = new FunctionDecl( name, scs, linkage, buildFunction( td ), body, attributes, funcSpec ); 990 buildList( td->function.withExprs, decl->withExprs ); 991 return decl->set_asmName( asmName ); 1424 return buildFunctionDecl( 1425 td, name, scs, funcSpec, linkage, 1426 asmName, std::move( attributes ) ); 992 1427 } else if ( td->kind == TypeData::Aggregate ) { 993 return buildAggregate( td, attributes, linkage );1428 return buildAggregate( td, std::move( attributes ), linkage ); 994 1429 } else if ( td->kind == TypeData::Enum ) { 995 return buildEnum( td, attributes, linkage );1430 return buildEnum( td, std::move( attributes ), linkage ); 996 1431 } else if ( td->kind == TypeData::Symbolic ) { 997 return buildSymbolic( td, attributes, name, scs, linkage );1432 return buildSymbolic( td, std::move( attributes ), name, scs, linkage ); 998 1433 } else { 999 return (new ObjectDecl( name, scs, linkage, bitfieldWidth, typebuild( td ), init, attributes ))->set_asmName( asmName ); 1434 auto ret = new ast::ObjectDecl( td->location, 1435 name, 1436 typebuild( td ), 1437 init, 1438 scs, 1439 linkage, 1440 bitfieldWidth, 1441 std::move( attributes ) 1442 ); 1443 ret->asmName = asmName; 1444 return ret; 1000 1445 } // if 1001 1446 return nullptr; … … 1003 1448 1004 1449 1005 FunctionType * buildFunction( const TypeData * td ) {1450 ast::FunctionType * buildFunctionType( const TypeData * td ) { 1006 1451 assert( td->kind == TypeData::Function ); 1007 FunctionType * ft = new FunctionType( buildQualifiers( td ), ! td->function.params || td->function.params->hasEllipsis ); 1008 buildList( td->function.params, ft->parameters ); 1452 ast::FunctionType * ft = new ast::FunctionType( 1453 ( !td->function.params || td->function.params->hasEllipsis ) 1454 ? ast::VariableArgs : ast::FixedArgs, 1455 buildQualifiers( td ) 1456 ); 1457 buildTypeList( td->function.params, ft->params ); 1009 1458 buildForall( td->forall, ft->forall ); 1010 1459 if ( td->base ) { 1011 1460 switch ( td->base->kind ) { 1012 1013 build List( td->base->tuple, ft->returnVals );1461 case TypeData::Tuple: 1462 buildTypeList( td->base->tuple, ft->returns ); 1014 1463 break; 1015 default: 1016 ft->get_returnVals().push_back( dynamic_cast< DeclarationWithType * >( buildDecl( td->base, "", Type::StorageClasses(), nullptr, Type::FuncSpecifiers(), LinkageSpec::Cforall, nullptr ) ) ); 1464 default: 1465 ft->returns.push_back( typebuild( td->base ) ); 1466 break; 1017 1467 } // switch 1018 1468 } else { 1019 ft->get_returnVals().push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ) ); 1469 ft->returns.push_back( 1470 new ast::BasicType( ast::BasicType::SignedInt ) ); 1020 1471 } // if 1021 1472 return ft; 1022 } // buildFunction 1473 } // buildFunctionType 1023 1474 1024 1475 … … 1051 1502 param->type = decl->type; // set copy declaration type to parameter type 1052 1503 decl->type = nullptr; // reset declaration type 1053 param->attributes.splice( param->attributes.end(), decl->attributes ); // copy and reset attributes from declaration to parameter 1504 // Copy and reset attributes from declaration to parameter: 1505 splice( param->attributes, decl->attributes ); 1054 1506 } // if 1055 1507 } // for -
src/Parser/TypeData.h
r2ed94a9 rb110bcc 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat May 16 15:18:36 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue May 10 22:18:49 202213 // Update Count : 20 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Wed Mar 1 10:44:00 2023 13 // Update Count : 206 14 14 // 15 15 16 16 #pragma once 17 17 18 #include <iosfwd> 19 #include <list> 20 #include <string> 18 #include <iosfwd> // for ostream 19 #include <list> // for list 20 #include <string> // for string 21 21 22 #include "ParseNode.h" // for DeclarationNode, DeclarationNode::Ag... 23 #include "SynTree/LinkageSpec.h" // for Spec 24 #include "SynTree/Type.h" // for Type, ReferenceToType (ptr only) 25 #include "SynTree/SynTree.h" // for Visitor Nodes 22 #include "AST/Type.hpp" // for Type 23 #include "DeclarationNode.h" // for DeclarationNode 26 24 27 25 struct TypeData { … … 30 28 31 29 struct Aggregate_t { 32 AggregateDecl::Aggregate kind;30 ast::AggregateDecl::Aggregate kind; 33 31 const std::string * name = nullptr; 34 32 DeclarationNode * params = nullptr; … … 37 35 bool body; 38 36 bool anon; 39 40 37 bool tagged; 41 38 const std::string * parent = nullptr; … … 94 91 DeclarationNode::BuiltinType builtintype = DeclarationNode::NoBuiltinType; 95 92 96 Type::Qualifiers qualifiers;93 ast::CV::Qualifiers qualifiers; 97 94 DeclarationNode * forall = nullptr; 98 95 … … 115 112 }; 116 113 117 Type * typebuild( const TypeData * );114 ast::Type * typebuild( const TypeData * ); 118 115 TypeData * typeextractAggregate( const TypeData * td, bool toplevel = true ); 119 Type::Qualifiers buildQualifiers( const TypeData * td ); 120 Type * buildBasicType( const TypeData * ); 121 PointerType * buildPointer( const TypeData * ); 122 ArrayType * buildArray( const TypeData * ); 123 ReferenceType * buildReference( const TypeData * ); 124 AggregateDecl * buildAggregate( const TypeData *, std::list< Attribute * > ); 125 ReferenceToType * buildComAggInst( const TypeData *, std::list< Attribute * > attributes, LinkageSpec::Spec linkage ); 126 ReferenceToType * buildAggInst( const TypeData * ); 127 TypeDecl * buildVariable( const TypeData * ); 128 EnumDecl * buildEnum( const TypeData *, std::list< Attribute * >, LinkageSpec::Spec ); 129 TypeInstType * buildSymbolicInst( const TypeData * ); 130 TupleType * buildTuple( const TypeData * ); 131 TypeofType * buildTypeof( const TypeData * ); 132 VTableType * buildVtable( const TypeData * ); 133 Declaration * buildDecl( const TypeData *, const std::string &, Type::StorageClasses, Expression *, Type::FuncSpecifiers funcSpec, LinkageSpec::Spec, Expression * asmName, 134 Initializer * init = nullptr, std::list< class Attribute * > attributes = std::list< class Attribute * >() ); 135 FunctionType * buildFunction( const TypeData * ); 136 Declaration * addEnumBase( Declaration *, const TypeData * ); 116 ast::CV::Qualifiers buildQualifiers( const TypeData * td ); 117 ast::Type * buildBasicType( const TypeData * ); 118 ast::PointerType * buildPointer( const TypeData * ); 119 ast::ArrayType * buildArray( const TypeData * ); 120 ast::ReferenceType * buildReference( const TypeData * ); 121 ast::AggregateDecl * buildAggregate( const TypeData *, std::vector<ast::ptr<ast::Attribute>> ); 122 ast::BaseInstType * buildComAggInst( const TypeData *, std::vector<ast::ptr<ast::Attribute>> && attributes, ast::Linkage::Spec linkage ); 123 ast::BaseInstType * buildAggInst( const TypeData * ); 124 ast::TypeDecl * buildVariable( const TypeData * ); 125 ast::EnumDecl * buildEnum( const TypeData *, std::vector<ast::ptr<ast::Attribute>> &&, ast::Linkage::Spec ); 126 ast::TypeInstType * buildSymbolicInst( const TypeData * ); 127 ast::TupleType * buildTuple( const TypeData * ); 128 ast::TypeofType * buildTypeof( const TypeData * ); 129 ast::VTableType * buildVtable( const TypeData * ); 130 ast::Decl * buildDecl( 131 const TypeData *, const std::string &, ast::Storage::Classes, ast::Expr *, 132 ast::Function::Specs funcSpec, ast::Linkage::Spec, ast::Expr * asmName, 133 ast::Init * init = nullptr, std::vector<ast::ptr<ast::Attribute>> && attributes = std::vector<ast::ptr<ast::Attribute>>() ); 134 ast::FunctionType * buildFunctionType( const TypeData * ); 135 ast::Decl * addEnumBase( Declaration *, const TypeData * ); 137 136 void buildKRFunction( const TypeData::Function_t & function ); 138 137 -
src/Parser/TypedefTable.cc
r2ed94a9 rb110bcc 16 16 17 17 #include "TypedefTable.h" 18 #include <cassert> // for assert 19 #include <iostream> 18 19 #include <cassert> // for assert 20 #include <string> // for string 21 #include <iostream> // for iostream 22 23 #include "ExpressionNode.h" // for LabelNode 24 #include "ParserTypes.h" // for Token 25 #include "StatementNode.h" // for CondCtl, ForCtrl 26 // This (generated) header must come late as it is missing includes. 27 #include "parser.hh" // for IDENTIFIER, TYPEDEFname, TYPEGENname 28 20 29 using namespace std; 21 30 22 31 #if 0 23 32 #define debugPrint( code ) code 33 34 static const char *kindName( int kind ) { 35 switch ( kind ) { 36 case IDENTIFIER: return "identifier"; 37 case TYPEDIMname: return "typedim"; 38 case TYPEDEFname: return "typedef"; 39 case TYPEGENname: return "typegen"; 40 default: 41 cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl; 42 abort(); 43 } // switch 44 } // kindName 24 45 #else 25 46 #define debugPrint( code ) 26 47 #endif 27 28 using namespace std; // string, iostream29 30 debugPrint(31 static const char *kindName( int kind ) {32 switch ( kind ) {33 case IDENTIFIER: return "identifier";34 case TYPEDIMname: return "typedim";35 case TYPEDEFname: return "typedef";36 case TYPEGENname: return "typegen";37 default:38 cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;39 abort();40 } // switch41 } // kindName42 );43 48 44 49 TypedefTable::~TypedefTable() { … … 78 83 typedefTable.addToEnclosingScope( name, kind, "MTD" ); 79 84 } // if 85 } // TypedefTable::makeTypedef 86 87 void TypedefTable::makeTypedef( const string & name ) { 88 return makeTypedef( name, TYPEDEFname ); 80 89 } // TypedefTable::makeTypedef 81 90 -
src/Parser/TypedefTable.h
r2ed94a9 rb110bcc 19 19 20 20 #include "Common/ScopedMap.h" // for ScopedMap 21 #include "ParserTypes.h"22 #include "parser.hh" // for IDENTIFIER, TYPEDEFname, TYPEGENname23 21 24 22 class TypedefTable { 25 23 struct Note { size_t level; bool forall; }; 26 24 typedef ScopedMap< std::string, int, Note > KindTable; 27 KindTable kindTable; 25 KindTable kindTable; 28 26 unsigned int level = 0; 29 27 public: … … 33 31 bool existsCurr( const std::string & identifier ) const; 34 32 int isKind( const std::string & identifier ) const; 35 void makeTypedef( const std::string & name, int kind = TYPEDEFname ); 33 void makeTypedef( const std::string & name, int kind ); 34 void makeTypedef( const std::string & name ); 36 35 void addToScope( const std::string & identifier, int kind, const char * ); 37 36 void addToEnclosingScope( const std::string & identifier, int kind, const char * ); -
src/Parser/lex.ll
r2ed94a9 rb110bcc 10 10 * Created On : Sat Sep 22 08:58:10 2001 11 11 * Last Modified By : Peter A. Buhr 12 * Last Modified On : Mon Jan 30 19:03:34202313 * Update Count : 76 712 * Last Modified On : Sat Mar 25 08:09:03 2023 13 * Update Count : 768 14 14 */ 15 15 … … 23 23 // line-number directives) and C/C++ style comments, which are ignored. 24 24 25 // **************************** Includes and Defines ****************************25 // *************************** Includes and Defines **************************** 26 26 27 27 #ifdef __clang__ … … 44 44 45 45 #include "config.h" // configure info 46 #include "DeclarationNode.h" // for DeclarationNode 47 #include "ExpressionNode.h" // for LabelNode 48 #include "InitializerNode.h" // for InitializerNode 46 49 #include "ParseNode.h" 50 #include "ParserTypes.h" // for Token 51 #include "StatementNode.h" // for CondCtl, ForCtrl 47 52 #include "TypedefTable.h" 53 // This (generated) header must come late as it is missing includes. 54 #include "parser.hh" // generated info 48 55 49 56 string * build_postfix_name( string * name ); … … 214 221 __alignof { KEYWORD_RETURN(ALIGNOF); } // GCC 215 222 __alignof__ { KEYWORD_RETURN(ALIGNOF); } // GCC 223 and { QKEYWORD_RETURN(WAND); } // CFA 216 224 asm { KEYWORD_RETURN(ASM); } 217 225 __asm { KEYWORD_RETURN(ASM); } // GCC -
src/Parser/module.mk
r2ed94a9 rb110bcc 21 21 SRC += \ 22 22 Parser/DeclarationNode.cc \ 23 Parser/DeclarationNode.h \ 23 24 Parser/ExpressionNode.cc \ 25 Parser/ExpressionNode.h \ 24 26 Parser/InitializerNode.cc \ 27 Parser/InitializerNode.h \ 25 28 Parser/lex.ll \ 26 29 Parser/ParseNode.cc \ … … 33 36 Parser/RunParser.hpp \ 34 37 Parser/StatementNode.cc \ 38 Parser/StatementNode.h \ 35 39 Parser/TypeData.cc \ 36 40 Parser/TypeData.h \ -
src/Parser/parser.yy
r2ed94a9 rb110bcc 9 9 // Author : Peter A. Buhr 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : T hu Feb 2 21:36:16202313 // Update Count : 586511 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Apr 4 14:02:00 2023 13 // Update Count : 6329 14 14 // 15 15 … … 44 44 45 45 #include <cstdio> 46 #include <sstream> 46 47 #include <stack> 47 48 using namespace std; 48 49 49 #include "SynTree/Declaration.h" 50 #include "ParseNode.h" 50 #include "SynTree/Type.h" // for Type 51 #include "DeclarationNode.h" // for DeclarationNode, ... 52 #include "ExpressionNode.h" // for ExpressionNode, ... 53 #include "InitializerNode.h" // for InitializerNode, ... 54 #include "ParserTypes.h" 55 #include "StatementNode.h" // for build_... 51 56 #include "TypedefTable.h" 52 57 #include "TypeData.h" 53 #include "SynTree/LinkageSpec.h"54 58 #include "Common/SemanticError.h" // error_str 55 59 #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... 56 60 57 #include "SynTree/Attribute.h" 61 #include "SynTree/Attribute.h" // for Attribute 58 62 59 63 // lex uses __null in a boolean context, it's fine. … … 63 67 64 68 extern DeclarationNode * parseTree; 65 extern LinkageSpec::Spec linkage;69 extern ast::Linkage::Spec linkage; 66 70 extern TypedefTable typedefTable; 67 71 68 stack< LinkageSpec::Spec> linkageStack;72 stack<ast::Linkage::Spec> linkageStack; 69 73 70 74 bool appendStr( string & to, string & from ) { … … 199 203 } // fieldDecl 200 204 201 #define NEW_ZERO new ExpressionNode( build_constantInteger( *new string( "0" ) ) )202 #define NEW_ONE new ExpressionNode( build_constantInteger( *new string( "1" ) ) )205 #define NEW_ZERO new ExpressionNode( build_constantInteger( yylloc, *new string( "0" ) ) ) 206 #define NEW_ONE new ExpressionNode( build_constantInteger( yylloc, *new string( "1" ) ) ) 203 207 #define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right) 204 208 #define MISSING_ANON_FIELD "Missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body." … … 206 210 #define MISSING_HIGH "Missing high value for down-to range so index is uninitialized." 207 211 208 ForCtrl * forCtrl( DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 212 static ForCtrl * makeForCtrl( 213 const CodeLocation & location, 214 DeclarationNode * init, 215 enum OperKinds compop, 216 ExpressionNode * comp, 217 ExpressionNode * inc ) { 218 // Wrap both comp/inc if they are non-null. 219 if ( comp ) comp = new ExpressionNode( build_binary_val( location, 220 compop, 221 new ExpressionNode( build_varref( location, new string( *init->name ) ) ), 222 comp ) ); 223 if ( inc ) inc = new ExpressionNode( build_binary_val( location, 224 // choose += or -= for upto/downto 225 compop == OperKinds::LThan || compop == OperKinds::LEThan ? OperKinds::PlusAssn : OperKinds::MinusAssn, 226 new ExpressionNode( build_varref( location, new string( *init->name ) ) ), 227 inc ) ); 228 // The StatementNode call frees init->name, it must happen later. 229 return new ForCtrl( new StatementNode( init ), comp, inc ); 230 } 231 232 ForCtrl * forCtrl( const CodeLocation & location, DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 209 233 if ( index->initializer ) { 210 234 SemanticError( yylloc, "Direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." ); … … 213 237 SemanticError( yylloc, "Multiple loop indexes disallowed in for-loop declaration." ); 214 238 } // if 215 return new ForCtrl( index->addInitializer( new InitializerNode( start ) ), 216 // NULL comp/inc => leave blank 217 comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index->name ) ) ), comp ) ) : nullptr, 218 inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto 219 OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index->name ) ) ), inc ) ) : nullptr ); 239 DeclarationNode * initDecl = index->addInitializer( new InitializerNode( start ) ); 240 return makeForCtrl( location, initDecl, compop, comp, inc ); 220 241 } // forCtrl 221 242 222 ForCtrl * forCtrl( ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {223 ConstantExpr * constant = dynamic_cast<ConstantExpr *>(type->expr.get());224 if ( constant && (constant-> get_constant()->get_value() == "0" || constant->get_constant()->get_value()== "1") ) {225 type = new ExpressionNode( new CastExpr( maybeMoveBuild<Expression>(type), new BasicType( Type::Qualifiers(),BasicType::SignedInt ) ) );243 ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 244 ast::ConstantExpr * constant = dynamic_cast<ast::ConstantExpr *>(type->expr.get()); 245 if ( constant && (constant->rep == "0" || constant->rep == "1") ) { 246 type = new ExpressionNode( new ast::CastExpr( location, maybeMoveBuild(type), new ast::BasicType( ast::BasicType::SignedInt ) ) ); 226 247 } // if 227 // type = new ExpressionNode( build_func( new ExpressionNode( build_varref( new string( "__for_control_index_constraints__" ) ) ), type ) ); 228 return new ForCtrl( 229 distAttr( DeclarationNode::newTypeof( type, true ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ), 230 // NULL comp/inc => leave blank 231 comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index ) ) ), comp ) ) : nullptr, 232 inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto 233 OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index ) ) ), inc ) ) : nullptr ); 248 DeclarationNode * initDecl = distAttr( 249 DeclarationNode::newTypeof( type, true ), 250 DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) 251 ); 252 return makeForCtrl( location, initDecl, compop, comp, inc ); 234 253 } // forCtrl 235 254 236 ForCtrl * forCtrl( ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) {237 if ( NameExpr * identifier = dynamic_cast<NameExpr *>(index->expr.get()) ) {238 return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );239 } else if ( CommaExpr * commaExpr = dynamic_cast<CommaExpr *>(index->expr.get()) ) {240 if ( NameExpr * identifier = dynamic_cast<NameExpr *>(commaExpr->arg1) ) {241 return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );255 ForCtrl * forCtrl( const CodeLocation & location, ExpressionNode * type, ExpressionNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 256 if ( auto identifier = dynamic_cast<ast::NameExpr *>(index->expr.get()) ) { 257 return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc ); 258 } else if ( auto commaExpr = dynamic_cast<ast::CommaExpr *>( index->expr.get() ) ) { 259 if ( auto identifier = commaExpr->arg1.as<ast::NameExpr>() ) { 260 return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc ); 242 261 } else { 243 262 SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr; … … 281 300 %union { 282 301 Token tok; 283 ParseNode * pn; 284 ExpressionNode * en; 302 ExpressionNode * expr; 285 303 DeclarationNode * decl; 286 AggregateDecl::Aggregate aggKey;287 TypeDecl::Kind tclass;288 StatementNode * s n;289 WaitForStmt * wfs;290 Expression * constant;304 ast::AggregateDecl::Aggregate aggKey; 305 ast::TypeDecl::Kind tclass; 306 StatementNode * stmt; 307 ClauseNode * clause; 308 ast::WaitForStmt * wfs; 291 309 CondCtl * ifctl; 292 ForCtrl * fctl; 293 OperKinds compop; 294 LabelNode * label; 295 InitializerNode * in; 296 OperKinds op; 310 ForCtrl * forctl; 311 LabelNode * labels; 312 InitializerNode * init; 313 OperKinds oper; 297 314 std::string * str; 298 bool flag;299 EnumHiding hide;300 CatchStmt::Kind catch_kind;301 GenericExpr * genexpr;315 bool is_volatile; 316 EnumHiding enum_hiding; 317 ast::ExceptionKind except_kind; 318 ast::GenericExpr * genexpr; 302 319 } 303 320 304 // ************************* TERMINAL TOKENS ********************************321 // ************************ TERMINAL TOKENS ******************************** 305 322 306 323 // keywords … … 337 354 338 355 // names and constants: lexer differentiates between identifier and typedef names 339 %token<tok> IDENTIFIER QUOTED_IDENTIFIERTYPEDIMname TYPEDEFname TYPEGENname340 %token<tok> TIMEOUT W ORCATCH RECOVER CATCHRESUME FIXUP FINALLY // CFA356 %token<tok> IDENTIFIER TYPEDIMname TYPEDEFname TYPEGENname 357 %token<tok> TIMEOUT WAND WOR CATCH RECOVER CATCHRESUME FIXUP FINALLY // CFA 341 358 %token<tok> INTEGERconstant CHARACTERconstant STRINGliteral 342 359 %token<tok> DIRECTIVE … … 364 381 %type<tok> identifier identifier_at identifier_or_type_name attr_name 365 382 %type<tok> quasi_keyword 366 %type< constant> string_literal383 %type<expr> string_literal 367 384 %type<str> string_literal_list 368 385 369 %type< hide> hide_opt visible_hide_opt386 %type<enum_hiding> hide_opt visible_hide_opt 370 387 371 388 // expressions 372 %type<e n> constant373 %type<e n> tuple tuple_expression_list374 %type<op > ptrref_operator unary_operator assignment_operator simple_assignment_operator compound_assignment_operator375 %type<e n> primary_expression postfix_expression unary_expression376 %type<e n> cast_expression_list cast_expression exponential_expression multiplicative_expression additive_expression377 %type<e n> shift_expression relational_expression equality_expression378 %type<e n> AND_expression exclusive_OR_expression inclusive_OR_expression379 %type<e n> logical_AND_expression logical_OR_expression380 %type<e n> conditional_expression constant_expression assignment_expression assignment_expression_opt381 %type<e n> comma_expression comma_expression_opt382 %type<e n> argument_expression_list_opt argument_expression_list argument_expression default_initializer_opt389 %type<expr> constant 390 %type<expr> tuple tuple_expression_list 391 %type<oper> ptrref_operator unary_operator assignment_operator simple_assignment_operator compound_assignment_operator 392 %type<expr> primary_expression postfix_expression unary_expression 393 %type<expr> cast_expression_list cast_expression exponential_expression multiplicative_expression additive_expression 394 %type<expr> shift_expression relational_expression equality_expression 395 %type<expr> AND_expression exclusive_OR_expression inclusive_OR_expression 396 %type<expr> logical_AND_expression logical_OR_expression 397 %type<expr> conditional_expression constant_expression assignment_expression assignment_expression_opt 398 %type<expr> comma_expression comma_expression_opt 399 %type<expr> argument_expression_list_opt argument_expression_list argument_expression default_initializer_opt 383 400 %type<ifctl> conditional_declaration 384 %type<f ctl> for_control_expression for_control_expression_list385 %type< compop> upupeq updown updowneq downupdowneq386 %type<e n> subrange401 %type<forctl> for_control_expression for_control_expression_list 402 %type<oper> upupeq updown updowneq downupdowneq 403 %type<expr> subrange 387 404 %type<decl> asm_name_opt 388 %type<e n> asm_operands_opt asm_operands_list asm_operand389 %type<label > label_list390 %type<e n> asm_clobbers_list_opt391 %type< flag> asm_volatile_opt392 %type<e n> handler_predicate_opt405 %type<expr> asm_operands_opt asm_operands_list asm_operand 406 %type<labels> label_list 407 %type<expr> asm_clobbers_list_opt 408 %type<is_volatile> asm_volatile_opt 409 %type<expr> handler_predicate_opt 393 410 %type<genexpr> generic_association generic_assoc_list 394 411 395 412 // statements 396 %type<sn> statement labeled_statement compound_statement 397 %type<sn> statement_decl statement_decl_list statement_list_nodecl 398 %type<sn> selection_statement if_statement 399 %type<sn> switch_clause_list_opt switch_clause_list 400 %type<en> case_value 401 %type<sn> case_clause case_value_list case_label case_label_list 402 %type<sn> iteration_statement jump_statement 403 %type<sn> expression_statement asm_statement 404 %type<sn> with_statement 405 %type<en> with_clause_opt 406 %type<sn> exception_statement handler_clause finally_clause 407 %type<catch_kind> handler_key 408 %type<sn> mutex_statement 409 %type<en> when_clause when_clause_opt waitfor timeout 410 %type<sn> waitfor_statement 411 %type<wfs> waitfor_clause 413 %type<stmt> statement labeled_statement compound_statement 414 %type<stmt> statement_decl statement_decl_list statement_list_nodecl 415 %type<stmt> selection_statement if_statement 416 %type<clause> switch_clause_list_opt switch_clause_list 417 %type<expr> case_value 418 %type<clause> case_clause case_value_list case_label case_label_list 419 %type<stmt> iteration_statement jump_statement 420 %type<stmt> expression_statement asm_statement 421 %type<stmt> with_statement 422 %type<expr> with_clause_opt 423 %type<stmt> exception_statement 424 %type<clause> handler_clause finally_clause 425 %type<except_kind> handler_key 426 %type<stmt> mutex_statement 427 %type<expr> when_clause when_clause_opt waitfor waituntil timeout 428 %type<stmt> waitfor_statement waituntil_statement 429 %type<wfs> wor_waitfor_clause waituntil_clause wand_waituntil_clause wor_waituntil_clause 412 430 413 431 // declarations … … 421 439 %type<decl> assertion assertion_list assertion_list_opt 422 440 423 %type<e n> bit_subrange_size_opt bit_subrange_size441 %type<expr> bit_subrange_size_opt bit_subrange_size 424 442 425 443 %type<decl> basic_declaration_specifier basic_type_name basic_type_specifier direct_type indirect_type … … 434 452 435 453 %type<decl> enumerator_list enum_type enum_type_nobody 436 %type<in > enumerator_value_opt454 %type<init> enumerator_value_opt 437 455 438 456 %type<decl> external_definition external_definition_list external_definition_list_opt … … 441 459 442 460 %type<decl> field_declaration_list_opt field_declaration field_declaring_list_opt field_declarator field_abstract_list_opt field_abstract 443 %type<e n> field field_name_list field_name fraction_constants_opt461 %type<expr> field field_name_list field_name fraction_constants_opt 444 462 445 463 %type<decl> external_function_definition function_definition function_array function_declarator function_no_ptr function_ptr … … 482 500 %type<decl> typedef_name typedef_declaration typedef_expression 483 501 484 %type<decl> variable_type_redeclarator type_ptr type_array type_function 502 %type<decl> variable_type_redeclarator variable_type_ptr variable_type_array variable_type_function 503 %type<decl> general_function_declarator function_type_redeclarator function_type_array function_type_no_ptr function_type_ptr 485 504 486 505 %type<decl> type_parameter_redeclarator type_parameter_ptr type_parameter_array type_parameter_function … … 489 508 %type<decl> type_parameter type_parameter_list type_initializer_opt 490 509 491 %type<e n> type_parameters_opt type_list array_type_list510 %type<expr> type_parameters_opt type_list array_type_list 492 511 493 512 %type<decl> type_qualifier type_qualifier_name forall type_qualifier_list_opt type_qualifier_list … … 500 519 501 520 // initializers 502 %type<in > initializer initializer_list_opt initializer_opt521 %type<init> initializer initializer_list_opt initializer_opt 503 522 504 523 // designators 505 %type<e n> designator designator_list designation524 %type<expr> designator designator_list designation 506 525 507 526 … … 512 531 // Similar issues exit with the waitfor statement. 513 532 514 // Order of these lines matters (low-to-high precedence). THEN is left associative over W OR/TIMEOUT/ELSE, WOR is left515 // associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.533 // Order of these lines matters (low-to-high precedence). THEN is left associative over WAND/WOR/TIMEOUT/ELSE, WAND/WOR 534 // is left associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE. 516 535 %precedence THEN // rule precedence for IF/WAITFOR statement 536 %precedence ANDAND // token precedence for start of WAND in WAITFOR statement 537 %precedence WAND // token precedence for start of WAND in WAITFOR statement 538 %precedence OROR // token precedence for start of WOR in WAITFOR statement 517 539 %precedence WOR // token precedence for start of WOR in WAITFOR statement 518 540 %precedence TIMEOUT // token precedence for start of TIMEOUT in WAITFOR statement … … 592 614 constant: 593 615 // ENUMERATIONconstant is not included here; it is treated as a variable with type "enumeration constant". 594 INTEGERconstant { $$ = new ExpressionNode( build_constantInteger( *$1 ) ); }595 | FLOATING_DECIMALconstant { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }596 | FLOATING_FRACTIONconstant { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }597 | FLOATINGconstant { $$ = new ExpressionNode( build_constantFloat( *$1 ) ); }598 | CHARACTERconstant { $$ = new ExpressionNode( build_constantChar( *$1 ) ); }616 INTEGERconstant { $$ = new ExpressionNode( build_constantInteger( yylloc, *$1 ) ); } 617 | FLOATING_DECIMALconstant { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); } 618 | FLOATING_FRACTIONconstant { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); } 619 | FLOATINGconstant { $$ = new ExpressionNode( build_constantFloat( yylloc, *$1 ) ); } 620 | CHARACTERconstant { $$ = new ExpressionNode( build_constantChar( yylloc, *$1 ) ); } 599 621 ; 600 622 601 623 quasi_keyword: // CFA 602 624 TIMEOUT 625 | WAND 603 626 | WOR 604 627 | CATCH … … 621 644 622 645 string_literal: 623 string_literal_list { $$ = build_constantStr( *$1); }646 string_literal_list { $$ = new ExpressionNode( build_constantStr( yylloc, *$1 ) ); } 624 647 ; 625 648 … … 638 661 primary_expression: 639 662 IDENTIFIER // typedef name cannot be used as a variable name 640 { $$ = new ExpressionNode( build_varref( $1 ) ); }663 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); } 641 664 | quasi_keyword 642 { $$ = new ExpressionNode( build_varref( $1 ) ); }665 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); } 643 666 | TYPEDIMname // CFA, generic length argument 644 667 // { $$ = new ExpressionNode( new TypeExpr( maybeMoveBuildType( DeclarationNode::newFromTypedef( $1 ) ) ) ); } 645 668 // { $$ = new ExpressionNode( build_varref( $1 ) ); } 646 { $$ = new ExpressionNode( build_dimensionref( $1 ) ); }669 { $$ = new ExpressionNode( build_dimensionref( yylloc, $1 ) ); } 647 670 | tuple 648 671 | '(' comma_expression ')' 649 672 { $$ = $2; } 650 673 | '(' compound_statement ')' // GCC, lambda expression 651 { $$ = new ExpressionNode( new StmtExpr( dynamic_cast<CompoundStmt *>(maybeMoveBuild<Statement>($2) ) ) ); }674 { $$ = new ExpressionNode( new ast::StmtExpr( yylloc, dynamic_cast<ast::CompoundStmt *>( maybeMoveBuild( $2 ) ) ) ); } 652 675 | type_name '.' identifier // CFA, nested type 653 { $$ = new ExpressionNode( build_qualified_expr( $1, build_varref($3 ) ) ); }676 { $$ = new ExpressionNode( build_qualified_expr( yylloc, $1, build_varref( yylloc, $3 ) ) ); } 654 677 | type_name '.' '[' field_name_list ']' // CFA, nested type / tuple field selector 655 678 { SemanticError( yylloc, "Qualified name is currently unimplemented." ); $$ = nullptr; } … … 657 680 { 658 681 // add the missing control expression to the GenericExpr and return it 659 $5->control = maybeMoveBuild <Expression>( $3 );682 $5->control = maybeMoveBuild( $3 ); 660 683 $$ = new ExpressionNode( $5 ); 661 684 } … … 683 706 { 684 707 // steal the association node from the singleton and delete the wrapper 685 $1->associations.splice($1->associations.end(), $3->associations); 708 assert( 1 == $3->associations.size() ); 709 $1->associations.push_back( $3->associations.front() ); 686 710 delete $3; 687 711 $$ = $1; … … 693 717 { 694 718 // create a GenericExpr wrapper with one association pair 695 $$ = new GenericExpr( nullptr, { { maybeMoveBuildType($1), maybeMoveBuild<Expression>( $3 ) } } );719 $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuildType( $1 ), maybeMoveBuild( $3 ) } } ); 696 720 } 697 721 | DEFAULT ':' assignment_expression 698 { $$ = new GenericExpr( nullptr, { { maybeMoveBuild<Expression>( $3 ) } } ); }722 { $$ = new ast::GenericExpr( yylloc, nullptr, { { maybeMoveBuild( $3 ) } } ); } 699 723 ; 700 724 … … 705 729 // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts. 706 730 // Current: Commas in subscripts make tuples. 707 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, new ExpressionNode( build_tuple((ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }731 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); } 708 732 | postfix_expression '[' assignment_expression ']' 709 733 // CFA, comma_expression disallowed in this context because it results in a common user error: subscripting a … … 711 735 // little advantage to this feature and many disadvantages. It is possible to write x[(i,j)] in CFA, which is 712 736 // equivalent to the old x[i,j]. 713 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }737 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); } 714 738 | constant '[' assignment_expression ']' // 3[a], 'a'[a], 3.5[a] 715 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }739 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); } 716 740 | string_literal '[' assignment_expression ']' // "abc"[3], 3["abc"] 717 { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); }741 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Index, $1, $3 ) ); } 718 742 | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call 719 743 { 720 744 Token fn; 721 745 fn.str = new std::string( "?{}" ); // location undefined - use location of '{'? 722 $$ = new ExpressionNode( new ConstructorExpr( build_func( new ExpressionNode( build_varref(fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) );746 $$ = new ExpressionNode( new ast::ConstructorExpr( yylloc, build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $1 )->set_last( $3 ) ) ) ); 723 747 } 724 748 | postfix_expression '(' argument_expression_list_opt ')' 725 { $$ = new ExpressionNode( build_func( $1, $3 ) ); }749 { $$ = new ExpressionNode( build_func( yylloc, $1, $3 ) ); } 726 750 | VA_ARG '(' primary_expression ',' declaration_specifier_nobody abstract_parameter_declarator_opt ')' 727 751 // { SemanticError( yylloc, "va_arg is currently unimplemented." ); $$ = nullptr; } 728 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref(new string( "__builtin_va_arg") ) ),752 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, new string( "__builtin_va_arg") ) ), 729 753 (ExpressionNode *)($3->set_last( (ExpressionNode *)($6 ? $6->addType( $5 ) : $5) )) ) ); } 730 754 | postfix_expression '`' identifier // CFA, postfix call 731 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref(build_postfix_name( $3 ) ) ), $1 ) ); }755 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); } 732 756 | constant '`' identifier // CFA, postfix call 733 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref(build_postfix_name( $3 ) ) ), $1 ) ); }757 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); } 734 758 | string_literal '`' identifier // CFA, postfix call 735 { $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref( build_postfix_name( $3 ) ) ), new ExpressionNode( $1 )) ); }759 { $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, build_postfix_name( $3 ) ) ), $1 ) ); } 736 760 | postfix_expression '.' identifier 737 { $$ = new ExpressionNode( build_fieldSel( $1, build_varref($3 ) ) ); }761 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); } 738 762 | postfix_expression '.' INTEGERconstant // CFA, tuple index 739 { $$ = new ExpressionNode( build_fieldSel( $1, build_constantInteger(*$3 ) ) ); }763 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); } 740 764 | postfix_expression FLOATING_FRACTIONconstant // CFA, tuple index 741 { $$ = new ExpressionNode( build_fieldSel( $1, build_field_name_FLOATING_FRACTIONconstant(*$2 ) ) ); }765 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 ) ) ); } 742 766 | postfix_expression '.' '[' field_name_list ']' // CFA, tuple field selector 743 { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple($4 ) ) ); }767 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); } 744 768 | postfix_expression '.' aggregate_control 745 { $$ = new ExpressionNode( build_keyword_cast( $3, $1 ) ); }769 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $3, $1 ) ); } 746 770 | postfix_expression ARROW identifier 747 { $$ = new ExpressionNode( build_pfieldSel( $1, build_varref($3 ) ) ); }771 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_varref( yylloc, $3 ) ) ); } 748 772 | postfix_expression ARROW INTEGERconstant // CFA, tuple index 749 { $$ = new ExpressionNode( build_pfieldSel( $1, build_constantInteger(*$3 ) ) ); }773 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_constantInteger( yylloc, *$3 ) ) ); } 750 774 | postfix_expression ARROW '[' field_name_list ']' // CFA, tuple field selector 751 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple($4 ) ) ); }775 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); } 752 776 | postfix_expression ICR 753 { $$ = new ExpressionNode( build_unary_ptr(OperKinds::IncrPost, $1 ) ); }777 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::IncrPost, $1 ) ); } 754 778 | postfix_expression DECR 755 { $$ = new ExpressionNode( build_unary_ptr(OperKinds::DecrPost, $1 ) ); }779 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::DecrPost, $1 ) ); } 756 780 | '(' type_no_function ')' '{' initializer_list_opt comma_opt '}' // C99, compound-literal 757 { $$ = new ExpressionNode( build_compoundLiteral( $2, new InitializerNode( $5, true ) ) ); }781 { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, new InitializerNode( $5, true ) ) ); } 758 782 | '(' type_no_function ')' '@' '{' initializer_list_opt comma_opt '}' // CFA, explicit C compound-literal 759 { $$ = new ExpressionNode( build_compoundLiteral( $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); }783 { $$ = new ExpressionNode( build_compoundLiteral( yylloc, $2, (new InitializerNode( $6, true ))->set_maybeConstructed( false ) ) ); } 760 784 | '^' primary_expression '{' argument_expression_list_opt '}' // CFA, destructor call 761 785 { 762 786 Token fn; 763 787 fn.str = new string( "^?{}" ); // location undefined 764 $$ = new ExpressionNode( build_func( new ExpressionNode( build_varref(fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) );788 $$ = new ExpressionNode( build_func( yylloc, new ExpressionNode( build_varref( yylloc, fn ) ), (ExpressionNode *)( $2 )->set_last( $4 ) ) ); 765 789 } 766 790 ; … … 781 805 '@' // CFA, default parameter 782 806 { SemanticError( yylloc, "Default parameter for argument is currently unimplemented." ); $$ = nullptr; } 783 807 // { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); } 784 808 | assignment_expression 785 809 ; … … 793 817 field_name 794 818 | FLOATING_DECIMALconstant field 795 { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), maybeMoveBuild<Expression>( $2 ) ) ); }819 { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), maybeMoveBuild( $2 ) ) ); } 796 820 | FLOATING_DECIMALconstant '[' field_name_list ']' 797 { $$ = new ExpressionNode( build_fieldSel( new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( *$1 ) ), build_tuple($3 ) ) ); }821 { $$ = new ExpressionNode( build_fieldSel( yylloc, new ExpressionNode( build_field_name_FLOATING_DECIMALconstant( yylloc, *$1 ) ), build_tuple( yylloc, $3 ) ) ); } 798 822 | field_name '.' field 799 { $$ = new ExpressionNode( build_fieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }823 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); } 800 824 | field_name '.' '[' field_name_list ']' 801 { $$ = new ExpressionNode( build_fieldSel( $1, build_tuple($4 ) ) ); }825 { $$ = new ExpressionNode( build_fieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); } 802 826 | field_name ARROW field 803 { $$ = new ExpressionNode( build_pfieldSel( $1, maybeMoveBuild<Expression>( $3 ) ) ); }827 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, maybeMoveBuild( $3 ) ) ); } 804 828 | field_name ARROW '[' field_name_list ']' 805 { $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple($4 ) ) ); }829 { $$ = new ExpressionNode( build_pfieldSel( yylloc, $1, build_tuple( yylloc, $4 ) ) ); } 806 830 ; 807 831 808 832 field_name: 809 833 INTEGERconstant fraction_constants_opt 810 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_constantInteger(*$1 ), $2 ) ); }834 { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_constantInteger( yylloc, *$1 ), $2 ) ); } 811 835 | FLOATINGconstant fraction_constants_opt 812 { $$ = new ExpressionNode( build_field_name_fraction_constants( build_field_name_FLOATINGconstant(*$1 ), $2 ) ); }836 { $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_field_name_FLOATINGconstant( yylloc, *$1 ), $2 ) ); } 813 837 | identifier_at fraction_constants_opt // CFA, allow anonymous fields 814 838 { 815 $$ = new ExpressionNode( build_field_name_fraction_constants( build_varref($1 ), $2 ) );839 $$ = new ExpressionNode( build_field_name_fraction_constants( yylloc, build_varref( yylloc, $1 ), $2 ) ); 816 840 } 817 841 ; … … 822 846 | fraction_constants_opt FLOATING_FRACTIONconstant 823 847 { 824 Expression * constant = build_field_name_FLOATING_FRACTIONconstant(*$2 );825 $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( $1,constant ) ) : new ExpressionNode( constant );848 ast::Expr * constant = build_field_name_FLOATING_FRACTIONconstant( yylloc, *$2 ); 849 $$ = $1 != nullptr ? new ExpressionNode( build_fieldSel( yylloc, $1, constant ) ) : new ExpressionNode( constant ); 826 850 } 827 851 ; … … 833 857 | constant 834 858 | string_literal 835 { $$ = new ExpressionNode( $1 ); }859 { $$ = $1; } 836 860 | EXTENSION cast_expression // GCC 837 861 { $$ = $2->set_extension( true ); } … … 842 866 { 843 867 switch ( $1 ) { 844 845 $$ = new ExpressionNode( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) );868 case OperKinds::AddressOf: 869 $$ = new ExpressionNode( new ast::AddressExpr( maybeMoveBuild( $2 ) ) ); 846 870 break; 847 848 $$ = new ExpressionNode( build_unary_val( $1, $2 ) );871 case OperKinds::PointTo: 872 $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) ); 849 873 break; 850 851 $$ = new ExpressionNode( new AddressExpr( new AddressExpr( maybeMoveBuild<Expression>( $2 ) ) ) );874 case OperKinds::And: 875 $$ = new ExpressionNode( new ast::AddressExpr( new ast::AddressExpr( maybeMoveBuild( $2 ) ) ) ); 852 876 break; 853 877 default: 854 878 assert( false ); 855 879 } 856 880 } 857 881 | unary_operator cast_expression 858 { $$ = new ExpressionNode( build_unary_val($1, $2 ) ); }882 { $$ = new ExpressionNode( build_unary_val( yylloc, $1, $2 ) ); } 859 883 | ICR unary_expression 860 { $$ = new ExpressionNode( build_unary_ptr(OperKinds::Incr, $2 ) ); }884 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Incr, $2 ) ); } 861 885 | DECR unary_expression 862 { $$ = new ExpressionNode( build_unary_ptr(OperKinds::Decr, $2 ) ); }886 { $$ = new ExpressionNode( build_unary_val( yylloc, OperKinds::Decr, $2 ) ); } 863 887 | SIZEOF unary_expression 864 { $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuild<Expression>( $2 ) ) ); }888 { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuild( $2 ) ) ); } 865 889 | SIZEOF '(' type_no_function ')' 866 { $$ = new ExpressionNode( new SizeofExpr(maybeMoveBuildType( $3 ) ) ); }890 { $$ = new ExpressionNode( new ast::SizeofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); } 867 891 | ALIGNOF unary_expression // GCC, variable alignment 868 { $$ = new ExpressionNode( new AlignofExpr( maybeMoveBuild<Expression>( $2 ) ) ); }892 { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuild( $2 ) ) ); } 869 893 | ALIGNOF '(' type_no_function ')' // GCC, type alignment 870 { $$ = new ExpressionNode( new AlignofExpr(maybeMoveBuildType( $3 ) ) ); }894 { $$ = new ExpressionNode( new ast::AlignofExpr( yylloc, maybeMoveBuildType( $3 ) ) ); } 871 895 | OFFSETOF '(' type_no_function ',' identifier ')' 872 { $$ = new ExpressionNode( build_offsetOf( $3, build_varref($5 ) ) ); }896 { $$ = new ExpressionNode( build_offsetOf( yylloc, $3, build_varref( yylloc, $5 ) ) ); } 873 897 | TYPEID '(' type_no_function ')' 874 898 { … … 895 919 unary_expression 896 920 | '(' type_no_function ')' cast_expression 897 { $$ = new ExpressionNode( build_cast( $2, $4 ) ); }921 { $$ = new ExpressionNode( build_cast( yylloc, $2, $4 ) ); } 898 922 | '(' aggregate_control '&' ')' cast_expression // CFA 899 { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }923 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); } 900 924 | '(' aggregate_control '*' ')' cast_expression // CFA 901 { $$ = new ExpressionNode( build_keyword_cast( $2, $5 ) ); }925 { $$ = new ExpressionNode( build_keyword_cast( yylloc, $2, $5 ) ); } 902 926 | '(' VIRTUAL ')' cast_expression // CFA 903 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $4 ), maybeMoveBuildType( nullptr ) ) ); }927 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $4 ), maybeMoveBuildType( nullptr ) ) ); } 904 928 | '(' VIRTUAL type_no_function ')' cast_expression // CFA 905 { $$ = new ExpressionNode( new VirtualCastExpr( maybeMoveBuild<Expression>( $5 ), maybeMoveBuildType( $3 ) ) ); }929 { $$ = new ExpressionNode( new ast::VirtualCastExpr( yylloc, maybeMoveBuild( $5 ), maybeMoveBuildType( $3 ) ) ); } 906 930 | '(' RETURN type_no_function ')' cast_expression // CFA 907 931 { SemanticError( yylloc, "Return cast is currently unimplemented." ); $$ = nullptr; } … … 911 935 { SemanticError( yylloc, "Qualifier cast is currently unimplemented." ); $$ = nullptr; } 912 936 // | '(' type_no_function ')' tuple 913 // { $$ = new ExpressionNode( build_cast($2, $4 ) ); }937 // { $$ = new ast::ExpressionNode( build_cast( yylloc, $2, $4 ) ); } 914 938 ; 915 939 … … 929 953 cast_expression 930 954 | exponential_expression '\\' cast_expression 931 { $$ = new ExpressionNode( build_binary_val( OperKinds::Exp, $1, $3 ) ); }955 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Exp, $1, $3 ) ); } 932 956 ; 933 957 … … 935 959 exponential_expression 936 960 | multiplicative_expression '*' exponential_expression 937 { $$ = new ExpressionNode( build_binary_val( OperKinds::Mul, $1, $3 ) ); }961 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mul, $1, $3 ) ); } 938 962 | multiplicative_expression '/' exponential_expression 939 { $$ = new ExpressionNode( build_binary_val( OperKinds::Div, $1, $3 ) ); }963 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Div, $1, $3 ) ); } 940 964 | multiplicative_expression '%' exponential_expression 941 { $$ = new ExpressionNode( build_binary_val( OperKinds::Mod, $1, $3 ) ); }965 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Mod, $1, $3 ) ); } 942 966 ; 943 967 … … 945 969 multiplicative_expression 946 970 | additive_expression '+' multiplicative_expression 947 { $$ = new ExpressionNode( build_binary_val( OperKinds::Plus, $1, $3 ) ); }971 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Plus, $1, $3 ) ); } 948 972 | additive_expression '-' multiplicative_expression 949 { $$ = new ExpressionNode( build_binary_val( OperKinds::Minus, $1, $3 ) ); }973 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Minus, $1, $3 ) ); } 950 974 ; 951 975 … … 953 977 additive_expression 954 978 | shift_expression LS additive_expression 955 { $$ = new ExpressionNode( build_binary_val( OperKinds::LShift, $1, $3 ) ); }979 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LShift, $1, $3 ) ); } 956 980 | shift_expression RS additive_expression 957 { $$ = new ExpressionNode( build_binary_val( OperKinds::RShift, $1, $3 ) ); }981 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::RShift, $1, $3 ) ); } 958 982 ; 959 983 … … 961 985 shift_expression 962 986 | relational_expression '<' shift_expression 963 { $$ = new ExpressionNode( build_binary_val( OperKinds::LThan, $1, $3 ) ); }987 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LThan, $1, $3 ) ); } 964 988 | relational_expression '>' shift_expression 965 { $$ = new ExpressionNode( build_binary_val( OperKinds::GThan, $1, $3 ) ); }989 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GThan, $1, $3 ) ); } 966 990 | relational_expression LE shift_expression 967 { $$ = new ExpressionNode( build_binary_val( OperKinds::LEThan, $1, $3 ) ); }991 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::LEThan, $1, $3 ) ); } 968 992 | relational_expression GE shift_expression 969 { $$ = new ExpressionNode( build_binary_val( OperKinds::GEThan, $1, $3 ) ); }993 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::GEThan, $1, $3 ) ); } 970 994 ; 971 995 … … 973 997 relational_expression 974 998 | equality_expression EQ relational_expression 975 { $$ = new ExpressionNode( build_binary_val( OperKinds::Eq, $1, $3 ) ); }999 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Eq, $1, $3 ) ); } 976 1000 | equality_expression NE relational_expression 977 { $$ = new ExpressionNode( build_binary_val( OperKinds::Neq, $1, $3 ) ); }1001 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Neq, $1, $3 ) ); } 978 1002 ; 979 1003 … … 981 1005 equality_expression 982 1006 | AND_expression '&' equality_expression 983 { $$ = new ExpressionNode( build_binary_val( OperKinds::BitAnd, $1, $3 ) ); }1007 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitAnd, $1, $3 ) ); } 984 1008 ; 985 1009 … … 987 1011 AND_expression 988 1012 | exclusive_OR_expression '^' AND_expression 989 { $$ = new ExpressionNode( build_binary_val( OperKinds::Xor, $1, $3 ) ); }1013 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::Xor, $1, $3 ) ); } 990 1014 ; 991 1015 … … 993 1017 exclusive_OR_expression 994 1018 | inclusive_OR_expression '|' exclusive_OR_expression 995 { $$ = new ExpressionNode( build_binary_val( OperKinds::BitOr, $1, $3 ) ); }1019 { $$ = new ExpressionNode( build_binary_val( yylloc, OperKinds::BitOr, $1, $3 ) ); } 996 1020 ; 997 1021 … … 999 1023 inclusive_OR_expression 1000 1024 | logical_AND_expression ANDAND inclusive_OR_expression 1001 { $$ = new ExpressionNode( build_and_or( $1, $3, true) ); }1025 { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::AndExpr ) ); } 1002 1026 ; 1003 1027 … … 1005 1029 logical_AND_expression 1006 1030 | logical_OR_expression OROR logical_AND_expression 1007 { $$ = new ExpressionNode( build_and_or( $1, $3, false) ); }1031 { $$ = new ExpressionNode( build_and_or( yylloc, $1, $3, ast::OrExpr ) ); } 1008 1032 ; 1009 1033 … … 1011 1035 logical_OR_expression 1012 1036 | logical_OR_expression '?' comma_expression ':' conditional_expression 1013 { $$ = new ExpressionNode( build_cond( $1, $3, $5 ) ); }1037 { $$ = new ExpressionNode( build_cond( yylloc, $1, $3, $5 ) ); } 1014 1038 // FIX ME: computes $1 twice 1015 1039 | logical_OR_expression '?' /* empty */ ':' conditional_expression // GCC, omitted first operand 1016 { $$ = new ExpressionNode( build_cond( $1, $1, $4 ) ); }1040 { $$ = new ExpressionNode( build_cond( yylloc, $1, $1, $4 ) ); } 1017 1041 ; 1018 1042 … … 1029 1053 // SemanticError( yylloc, "C @= assignment is currently unimplemented." ); $$ = nullptr; 1030 1054 // } else { 1031 $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) );1055 $$ = new ExpressionNode( build_binary_val( yylloc, $2, $1, $3 ) ); 1032 1056 // } // if 1033 1057 } … … 1074 1098 // { $$ = new ExpressionNode( build_tuple( $3 ) ); } 1075 1099 '[' ',' tuple_expression_list ']' 1076 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); }1100 { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)(new ExpressionNode( nullptr ) )->set_last( $3 ) ) ); } 1077 1101 | '[' push assignment_expression pop ',' tuple_expression_list ']' 1078 { $$ = new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $6 ) ) )); }1102 { $$ = new ExpressionNode( build_tuple( yylloc, (ExpressionNode *)($3->set_last( $6 ) ) )); } 1079 1103 ; 1080 1104 … … 1092 1116 assignment_expression 1093 1117 | comma_expression ',' assignment_expression 1094 { $$ = new ExpressionNode( new CommaExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }1118 { $$ = new ExpressionNode( new ast::CommaExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); } 1095 1119 ; 1096 1120 … … 1113 1137 | mutex_statement 1114 1138 | waitfor_statement 1139 | waituntil_statement 1115 1140 | exception_statement 1116 1141 | enable_disable_statement … … 1118 1143 | asm_statement 1119 1144 | DIRECTIVE 1120 { $$ = new StatementNode( build_directive( $1 ) ); }1145 { $$ = new StatementNode( build_directive( yylloc, $1 ) ); } 1121 1146 ; 1122 1147 … … 1124 1149 // labels cannot be identifiers 0 or 1 1125 1150 identifier_or_type_name ':' attribute_list_opt statement 1126 { $$ = $4->add_label( $1, $3 ); }1151 { $$ = $4->add_label( yylloc, $1, $3 ); } 1127 1152 | identifier_or_type_name ':' attribute_list_opt error // syntax error 1128 1153 { … … 1136 1161 compound_statement: 1137 1162 '{' '}' 1138 { $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); }1163 { $$ = new StatementNode( build_compound( yylloc, (StatementNode *)0 ) ); } 1139 1164 | '{' push 1140 1165 local_label_declaration_opt // GCC, local labels appear at start of block 1141 1166 statement_decl_list // C99, intermix declarations and statements 1142 1167 pop '}' 1143 { $$ = new StatementNode( build_compound( $4 ) ); }1168 { $$ = new StatementNode( build_compound( yylloc, $4 ) ); } 1144 1169 ; 1145 1170 … … 1172 1197 expression_statement: 1173 1198 comma_expression_opt ';' 1174 { $$ = new StatementNode( build_expr( $1 ) ); } 1175 | MUTEX '(' ')' comma_expression ';' 1176 { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); } 1199 { $$ = new StatementNode( build_expr( yylloc, $1 ) ); } 1177 1200 ; 1178 1201 … … 1183 1206 { $$ = $2; } 1184 1207 | SWITCH '(' comma_expression ')' case_clause 1185 { $$ = new StatementNode( build_switch( true, $3, $5 ) ); }1208 { $$ = new StatementNode( build_switch( yylloc, true, $3, $5 ) ); } 1186 1209 | SWITCH '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA 1187 1210 { 1188 StatementNode *sw = new StatementNode( build_switch( true, $3, $8 ) );1211 StatementNode *sw = new StatementNode( build_switch( yylloc, true, $3, $8 ) ); 1189 1212 // The semantics of the declaration list is changed to include associated initialization, which is performed 1190 1213 // *before* the transfer to the appropriate case clause by hoisting the declarations into a compound … … 1192 1215 // therefore, are removed from the grammar even though C allows it. The change also applies to choose 1193 1216 // statement. 1194 $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;1217 $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw; 1195 1218 } 1196 1219 | SWITCH '(' comma_expression ')' '{' error '}' // CFA, syntax error 1197 1220 { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; } 1198 1221 | CHOOSE '(' comma_expression ')' case_clause // CFA 1199 { $$ = new StatementNode( build_switch( false, $3, $5 ) ); }1222 { $$ = new StatementNode( build_switch( yylloc, false, $3, $5 ) ); } 1200 1223 | CHOOSE '(' comma_expression ')' '{' push declaration_list_opt switch_clause_list_opt pop '}' // CFA 1201 1224 { 1202 StatementNode *sw = new StatementNode( build_switch( false, $3, $8 ) );1203 $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;1225 StatementNode *sw = new StatementNode( build_switch( yylloc, false, $3, $8 ) ); 1226 $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw; 1204 1227 } 1205 1228 | CHOOSE '(' comma_expression ')' '{' error '}' // CFA, syntax error … … 1210 1233 IF '(' conditional_declaration ')' statement %prec THEN 1211 1234 // explicitly deal with the shift/reduce conflict on if/else 1212 { $$ = new StatementNode( build_if( $3, maybe_build_compound($5 ), nullptr ) ); }1235 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), nullptr ) ); } 1213 1236 | IF '(' conditional_declaration ')' statement ELSE statement 1214 { $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), maybe_build_compound($7 ) ) ); }1237 { $$ = new StatementNode( build_if( yylloc, $3, maybe_build_compound( yylloc, $5 ), maybe_build_compound( yylloc, $7 ) ) ); } 1215 1238 ; 1216 1239 … … 1224 1247 | declaration comma_expression // semi-colon separated 1225 1248 { $$ = new CondCtl( $1, $2 ); } 1226 1249 ; 1227 1250 1228 1251 // CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a case … … 1232 1255 constant_expression { $$ = $1; } 1233 1256 | constant_expression ELLIPSIS constant_expression // GCC, subrange 1234 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }1257 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); } 1235 1258 | subrange // CFA, subrange 1236 1259 ; 1237 1260 1238 1261 case_value_list: // CFA 1239 case_value { $$ = new StatementNode( build_case($1 ) ); }1262 case_value { $$ = new ClauseNode( build_case( yylloc, $1 ) ); } 1240 1263 // convert case list, e.g., "case 1, 3, 5:" into "case 1: case 3: case 5" 1241 | case_value_list ',' case_value { $$ = (StatementNode *)($1->set_last( new StatementNode( build_case( $3 )) ) ); }1264 | case_value_list ',' case_value { $$ = $1->set_last( new ClauseNode( build_case( yylloc, $3 ) ) ); } 1242 1265 ; 1243 1266 … … 1248 1271 | CASE case_value_list error // syntax error 1249 1272 { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; } 1250 | DEFAULT ':' { $$ = new StatementNode( build_default() ); }1273 | DEFAULT ':' { $$ = new ClauseNode( build_default( yylloc ) ); } 1251 1274 // A semantic check is required to ensure only one default clause per switch/choose statement. 1252 1275 | DEFAULT error // syntax error … … 1256 1279 case_label_list: // CFA 1257 1280 case_label 1258 | case_label_list case_label { $$ = (StatementNode *)( $1->set_last( $2 )); }1281 | case_label_list case_label { $$ = $1->set_last( $2 ); } 1259 1282 ; 1260 1283 1261 1284 case_clause: // CFA 1262 case_label_list statement { $$ = $1->append_last_case( maybe_build_compound( $2 ) ); }1285 case_label_list statement { $$ = $1->append_last_case( maybe_build_compound( yylloc, $2 ) ); } 1263 1286 ; 1264 1287 … … 1271 1294 switch_clause_list: // CFA 1272 1295 case_label_list statement_list_nodecl 1273 { $$ = $1->append_last_case( new StatementNode( build_compound( $2 ) ) ); }1296 { $$ = $1->append_last_case( new StatementNode( build_compound( yylloc, $2 ) ) ); } 1274 1297 | switch_clause_list case_label_list statement_list_nodecl 1275 { $$ = (StatementNode *)( $1->set_last( $2->append_last_case( new StatementNode( build_compound( $3 )) ) ) ); }1298 { $$ = $1->set_last( $2->append_last_case( new StatementNode( build_compound( yylloc, $3 ) ) ) ); } 1276 1299 ; 1277 1300 1278 1301 iteration_statement: 1279 1302 WHILE '(' ')' statement %prec THEN // CFA => while ( 1 ) 1280 { $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound($4 ) ) ); }1303 { $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) ); } 1281 1304 | WHILE '(' ')' statement ELSE statement // CFA 1282 1305 { 1283 $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound($4 ) ) );1284 SemanticWarning( yylloc, Warning::SuperfluousElse , "");1306 $$ = new StatementNode( build_while( yylloc, new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( yylloc, $4 ) ) ); 1307 SemanticWarning( yylloc, Warning::SuperfluousElse ); 1285 1308 } 1286 1309 | WHILE '(' conditional_declaration ')' statement %prec THEN 1287 { $$ = new StatementNode( build_while( $3, maybe_build_compound($5 ) ) ); }1310 { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); } 1288 1311 | WHILE '(' conditional_declaration ')' statement ELSE statement // CFA 1289 { $$ = new StatementNode( build_while( $3, maybe_build_compound($5 ), $7 ) ); }1312 { $$ = new StatementNode( build_while( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); } 1290 1313 | DO statement WHILE '(' ')' ';' // CFA => do while( 1 ) 1291 { $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound($2 ) ) ); }1314 { $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) ); } 1292 1315 | DO statement WHILE '(' ')' ELSE statement // CFA 1293 1316 { 1294 $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound($2 ) ) );1295 SemanticWarning( yylloc, Warning::SuperfluousElse , "");1317 $$ = new StatementNode( build_do_while( yylloc, NEW_ONE, maybe_build_compound( yylloc, $2 ) ) ); 1318 SemanticWarning( yylloc, Warning::SuperfluousElse ); 1296 1319 } 1297 1320 | DO statement WHILE '(' comma_expression ')' ';' 1298 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound($2 ) ) ); }1321 { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ) ) ); } 1299 1322 | DO statement WHILE '(' comma_expression ')' ELSE statement // CFA 1300 { $$ = new StatementNode( build_do_while( $5, maybe_build_compound($2 ), $8 ) ); }1323 { $$ = new StatementNode( build_do_while( yylloc, $5, maybe_build_compound( yylloc, $2 ), $8 ) ); } 1301 1324 | FOR '(' ')' statement %prec THEN // CFA => for ( ;; ) 1302 { $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound($4 ) ) ); }1325 { $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) ); } 1303 1326 | FOR '(' ')' statement ELSE statement // CFA 1304 1327 { 1305 $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound($4 ) ) );1306 SemanticWarning( yylloc, Warning::SuperfluousElse , "");1328 $$ = new StatementNode( build_for( yylloc, new ForCtrl( nullptr, nullptr, nullptr ), maybe_build_compound( yylloc, $4 ) ) ); 1329 SemanticWarning( yylloc, Warning::SuperfluousElse ); 1307 1330 } 1308 1331 | FOR '(' for_control_expression_list ')' statement %prec THEN 1309 { $$ = new StatementNode( build_for( $3, maybe_build_compound($5 ) ) ); }1332 { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ) ) ); } 1310 1333 | FOR '(' for_control_expression_list ')' statement ELSE statement // CFA 1311 { $$ = new StatementNode( build_for( $3, maybe_build_compound($5 ), $7 ) ); }1334 { $$ = new StatementNode( build_for( yylloc, $3, maybe_build_compound( yylloc, $5 ), $7 ) ); } 1312 1335 ; 1313 1336 … … 1323 1346 if ( $1->condition ) { 1324 1347 if ( $3->condition ) { 1325 $1->condition->expr.reset( new LogicalExpr( $1->condition->expr.release(), $3->condition->expr.release(), true) );1348 $1->condition->expr.reset( new ast::LogicalExpr( yylloc, $1->condition->expr.release(), $3->condition->expr.release(), ast::AndExpr ) ); 1326 1349 } // if 1327 1350 } else $1->condition = $3->condition; 1328 1351 if ( $1->change ) { 1329 1352 if ( $3->change ) { 1330 $1->change->expr.reset( new CommaExpr($1->change->expr.release(), $3->change->expr.release() ) );1353 $1->change->expr.reset( new ast::CommaExpr( yylloc, $1->change->expr.release(), $3->change->expr.release() ) ); 1331 1354 } // if 1332 1355 } else $1->change = $3->change; … … 1337 1360 for_control_expression: 1338 1361 ';' comma_expression_opt ';' comma_expression_opt 1339 { $$ = new ForCtrl( (ExpressionNode * )nullptr, $2, $4 ); }1362 { $$ = new ForCtrl( nullptr, $2, $4 ); } 1340 1363 | comma_expression ';' comma_expression_opt ';' comma_expression_opt 1341 { $$ = new ForCtrl( $1, $3, $5 ); } 1364 { 1365 StatementNode * init = $1 ? new StatementNode( new ast::ExprStmt( yylloc, maybeMoveBuild( $1 ) ) ) : nullptr; 1366 $$ = new ForCtrl( init, $3, $5 ); 1367 } 1342 1368 | declaration comma_expression_opt ';' comma_expression_opt // C99, declaration has ';' 1343 { $$ = new ForCtrl( $1, $2, $4 ); }1369 { $$ = new ForCtrl( new StatementNode( $1 ), $2, $4 ); } 1344 1370 1345 1371 | '@' ';' comma_expression // CFA, empty loop-index 1346 { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, nullptr ); }1372 { $$ = new ForCtrl( nullptr, $3, nullptr ); } 1347 1373 | '@' ';' comma_expression ';' comma_expression // CFA, empty loop-index 1348 { $$ = new ForCtrl( (ExpressionNode *)nullptr, $3, $5 ); }1374 { $$ = new ForCtrl( nullptr, $3, $5 ); } 1349 1375 1350 1376 | comma_expression // CFA, anonymous loop-index 1351 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); }1377 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); } 1352 1378 | downupdowneq comma_expression // CFA, anonymous loop-index 1353 { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); }1379 { $$ = forCtrl( yylloc, $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); } 1354 1380 1355 1381 | comma_expression updowneq comma_expression // CFA, anonymous loop-index 1356 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); }1382 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); } 1357 1383 | '@' updowneq comma_expression // CFA, anonymous loop-index 1358 1384 { 1359 1385 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1360 else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE );1386 else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE ); 1361 1387 } 1362 1388 | comma_expression updowneq '@' // CFA, anonymous loop-index … … 1366 1392 } 1367 1393 | comma_expression updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index 1368 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); }1394 { $$ = forCtrl( yylloc, $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); } 1369 1395 | '@' updowneq comma_expression '~' comma_expression // CFA, anonymous loop-index 1370 1396 { 1371 1397 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1372 else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 );1398 else $$ = forCtrl( yylloc, $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 ); 1373 1399 } 1374 1400 | comma_expression updowneq '@' '~' comma_expression // CFA, anonymous loop-index … … 1389 1415 1390 1416 | comma_expression ';' comma_expression // CFA 1391 { $$ = forCtrl( $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); }1417 { $$ = forCtrl( yylloc, $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); } 1392 1418 | comma_expression ';' downupdowneq comma_expression // CFA 1393 { $$ = forCtrl( $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); }1419 { $$ = forCtrl( yylloc, $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); } 1394 1420 1395 1421 | comma_expression ';' comma_expression updowneq comma_expression // CFA 1396 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); }1422 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); } 1397 1423 | comma_expression ';' '@' updowneq comma_expression // CFA 1398 1424 { 1399 1425 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1400 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, NEW_ONE );1426 else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, NEW_ONE ); 1401 1427 } 1402 1428 | comma_expression ';' comma_expression updowneq '@' // CFA … … 1404 1430 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1405 1431 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1406 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, NEW_ONE );1432 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, NEW_ONE ); 1407 1433 } 1408 1434 | comma_expression ';' '@' updowneq '@' // CFA, error … … 1410 1436 1411 1437 | comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA 1412 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); }1438 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); } 1413 1439 | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, error 1414 1440 { 1415 1441 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1416 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, $7 );1442 else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, $7 ); 1417 1443 } 1418 1444 | comma_expression ';' comma_expression updowneq '@' '~' comma_expression // CFA … … 1420 1446 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1421 1447 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1422 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, $7 );1448 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, $7 ); 1423 1449 } 1424 1450 | comma_expression ';' comma_expression updowneq comma_expression '~' '@' // CFA 1425 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); }1451 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); } 1426 1452 | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, error 1427 1453 { 1428 1454 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1429 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, nullptr );1455 else $$ = forCtrl( yylloc, $5, $1, $5->clone(), $4, nullptr, nullptr ); 1430 1456 } 1431 1457 | comma_expression ';' comma_expression updowneq '@' '~' '@' // CFA … … 1433 1459 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1434 1460 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1435 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, nullptr );1461 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, nullptr ); 1436 1462 } 1437 1463 | comma_expression ';' '@' updowneq '@' '~' '@' // CFA … … 1439 1465 1440 1466 | declaration comma_expression // CFA 1441 { $$ = forCtrl( $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); }1467 { $$ = forCtrl( yylloc, $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); } 1442 1468 | declaration downupdowneq comma_expression // CFA 1443 { $$ = forCtrl( $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); }1469 { $$ = forCtrl( yylloc, $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); } 1444 1470 1445 1471 | declaration comma_expression updowneq comma_expression // CFA 1446 { $$ = forCtrl( $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); }1472 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); } 1447 1473 | declaration '@' updowneq comma_expression // CFA 1448 1474 { 1449 1475 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1450 else $$ = forCtrl( $1, $4, $3, nullptr, NEW_ONE );1476 else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, NEW_ONE ); 1451 1477 } 1452 1478 | declaration comma_expression updowneq '@' // CFA … … 1454 1480 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1455 1481 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1456 else $$ = forCtrl( $1, $2, $3, nullptr, NEW_ONE );1482 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, NEW_ONE ); 1457 1483 } 1458 1484 1459 1485 | declaration comma_expression updowneq comma_expression '~' comma_expression // CFA 1460 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); }1486 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); } 1461 1487 | declaration '@' updowneq comma_expression '~' comma_expression // CFA 1462 1488 { 1463 1489 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1464 else $$ = forCtrl( $1, $4, $3, nullptr, $6 );1490 else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, $6 ); 1465 1491 } 1466 1492 | declaration comma_expression updowneq '@' '~' comma_expression // CFA … … 1468 1494 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1469 1495 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1470 else $$ = forCtrl( $1, $2, $3, nullptr, $6 );1496 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, $6 ); 1471 1497 } 1472 1498 | declaration comma_expression updowneq comma_expression '~' '@' // CFA 1473 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); }1499 { $$ = forCtrl( yylloc, $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); } 1474 1500 | declaration '@' updowneq comma_expression '~' '@' // CFA 1475 1501 { 1476 1502 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } 1477 else $$ = forCtrl( $1, $4, $3, nullptr, nullptr );1503 else $$ = forCtrl( yylloc, $1, $4, $3, nullptr, nullptr ); 1478 1504 } 1479 1505 | declaration comma_expression updowneq '@' '~' '@' // CFA … … 1481 1507 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1482 1508 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1483 else $$ = forCtrl( $1, $2, $3, nullptr, nullptr );1509 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, nullptr ); 1484 1510 } 1485 1511 | declaration '@' updowneq '@' '~' '@' // CFA, error … … 1496 1522 SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr; 1497 1523 } 1498 1524 ; 1499 1525 1500 1526 downupdowneq: … … 1505 1531 | ErangeDownEq 1506 1532 { $$ = OperKinds::GEThan; } 1507 1533 ; 1508 1534 1509 1535 updown: … … 1512 1538 | ErangeDown 1513 1539 { $$ = OperKinds::GThan; } 1514 1540 ; 1515 1541 1516 1542 updowneq: … … 1520 1546 | ErangeDownEq 1521 1547 { $$ = OperKinds::GEThan; } 1522 1548 ; 1523 1549 1524 1550 jump_statement: 1525 1551 GOTO identifier_or_type_name ';' 1526 { $$ = new StatementNode( build_branch( $2,BranchStmt::Goto ) ); }1552 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Goto ) ); } 1527 1553 | GOTO '*' comma_expression ';' // GCC, computed goto 1528 1554 // The syntax for the GCC computed goto violates normal expression precedence, e.g., goto *i+3; => goto *(i+3); … … 1531 1557 // A semantic check is required to ensure fallthru appears only in the body of a choose statement. 1532 1558 | fall_through_name ';' // CFA 1533 { $$ = new StatementNode( build_branch( BranchStmt::FallThrough ) ); }1559 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThrough ) ); } 1534 1560 | fall_through_name identifier_or_type_name ';' // CFA 1535 { $$ = new StatementNode( build_branch( $2,BranchStmt::FallThrough ) ); }1561 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::FallThrough ) ); } 1536 1562 | fall_through_name DEFAULT ';' // CFA 1537 { $$ = new StatementNode( build_branch( BranchStmt::FallThroughDefault ) ); }1563 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::FallThroughDefault ) ); } 1538 1564 | CONTINUE ';' 1539 1565 // A semantic check is required to ensure this statement appears only in the body of an iteration statement. 1540 { $$ = new StatementNode( build_branch( BranchStmt::Continue ) ); }1566 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Continue ) ); } 1541 1567 | CONTINUE identifier_or_type_name ';' // CFA, multi-level continue 1542 1568 // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and 1543 1569 // the target of the transfer appears only at the start of an iteration statement. 1544 { $$ = new StatementNode( build_branch( $2,BranchStmt::Continue ) ); }1570 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Continue ) ); } 1545 1571 | BREAK ';' 1546 1572 // A semantic check is required to ensure this statement appears only in the body of an iteration statement. 1547 { $$ = new StatementNode( build_branch( BranchStmt::Break ) ); }1573 { $$ = new StatementNode( build_branch( yylloc, ast::BranchStmt::Break ) ); } 1548 1574 | BREAK identifier_or_type_name ';' // CFA, multi-level exit 1549 1575 // A semantic check is required to ensure this statement appears only in the body of an iteration statement, and 1550 1576 // the target of the transfer appears only at the start of an iteration statement. 1551 { $$ = new StatementNode( build_branch( $2,BranchStmt::Break ) ); }1577 { $$ = new StatementNode( build_branch( yylloc, $2, ast::BranchStmt::Break ) ); } 1552 1578 | RETURN comma_expression_opt ';' 1553 { $$ = new StatementNode( build_return( $2 ) ); }1579 { $$ = new StatementNode( build_return( yylloc, $2 ) ); } 1554 1580 | RETURN '{' initializer_list_opt comma_opt '}' ';' 1555 1581 { SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; } 1556 1582 | SUSPEND ';' 1557 { $$ = new StatementNode( build_suspend( nullptr) ); }1583 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::None ) ); } 1558 1584 | SUSPEND compound_statement 1559 { $$ = new StatementNode( build_suspend( $2) ); }1585 { $$ = new StatementNode( build_suspend( yylloc, $2, ast::SuspendStmt::None ) ); } 1560 1586 | SUSPEND COROUTINE ';' 1561 { $$ = new StatementNode( build_suspend( nullptr,SuspendStmt::Coroutine ) ); }1587 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Coroutine ) ); } 1562 1588 | SUSPEND COROUTINE compound_statement 1563 { $$ = new StatementNode( build_suspend( $3,SuspendStmt::Coroutine ) ); }1589 { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Coroutine ) ); } 1564 1590 | SUSPEND GENERATOR ';' 1565 { $$ = new StatementNode( build_suspend( nullptr,SuspendStmt::Generator ) ); }1591 { $$ = new StatementNode( build_suspend( yylloc, nullptr, ast::SuspendStmt::Generator ) ); } 1566 1592 | SUSPEND GENERATOR compound_statement 1567 { $$ = new StatementNode( build_suspend( $3,SuspendStmt::Generator ) ); }1593 { $$ = new StatementNode( build_suspend( yylloc, $3, ast::SuspendStmt::Generator ) ); } 1568 1594 | THROW assignment_expression_opt ';' // handles rethrow 1569 { $$ = new StatementNode( build_throw( $2 ) ); }1595 { $$ = new StatementNode( build_throw( yylloc, $2 ) ); } 1570 1596 | THROWRESUME assignment_expression_opt ';' // handles reresume 1571 { $$ = new StatementNode( build_resume( $2 ) ); }1597 { $$ = new StatementNode( build_resume( yylloc, $2 ) ); } 1572 1598 | THROWRESUME assignment_expression_opt AT assignment_expression ';' // handles reresume 1573 1599 { $$ = new StatementNode( build_resume_at( $2, $4 ) ); } … … 1581 1607 with_statement: 1582 1608 WITH '(' tuple_expression_list ')' statement 1583 { $$ = new StatementNode( build_with( $3, $5 ) ); }1584 ; 1585 1586 // If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so change syntax to "with mutex".1609 { $$ = new StatementNode( build_with( yylloc, $3, $5 ) ); } 1610 ; 1611 1612 // If MUTEX becomes a general qualifier, there are shift/reduce conflicts, so possibly change syntax to "with mutex". 1587 1613 mutex_statement: 1588 MUTEX '(' argument_expression_list ')' statement 1589 { $$ = new StatementNode( build_mutex( $3, $5 ) ); } 1614 MUTEX '(' argument_expression_list_opt ')' statement 1615 { 1616 if ( ! $3 ) { SemanticError( yylloc, "mutex argument list cannot be empty." ); $$ = nullptr; } 1617 $$ = new StatementNode( build_mutex( yylloc, $3, $5 ) ); 1618 } 1590 1619 ; 1591 1620 … … 1598 1627 { $$ = nullptr; } 1599 1628 | when_clause 1600 ;1601 1602 waitfor:1603 WAITFOR '(' cast_expression ')'1604 { $$ = $3; }1605 // | WAITFOR '(' cast_expression ',' argument_expression_list_opt ')'1606 // { $$ = (ExpressionNode *)$3->set_last( $5 ); }1607 | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'1608 { $$ = (ExpressionNode *)($3->set_last( $5 )); }1609 1629 ; 1610 1630 … … 1617 1637 1618 1638 timeout: 1619 TIMEOUT '(' comma_expression ')' { $$ = $3; } 1620 ; 1621 1622 waitfor_clause: 1639 TIMEOUT '(' comma_expression ')' { $$ = $3; } 1640 ; 1641 1642 wor: 1643 OROR 1644 | WOR 1645 1646 waitfor: 1647 WAITFOR '(' cast_expression ')' 1648 { $$ = $3; } 1649 | WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')' 1650 { $$ = (ExpressionNode *)($3->set_last( $5 )); } 1651 ; 1652 1653 wor_waitfor_clause: 1623 1654 when_clause_opt waitfor statement %prec THEN 1624 { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1 ); } 1625 | when_clause_opt waitfor statement WOR waitfor_clause 1626 { $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1, $5 ); } 1627 | when_clause_opt timeout statement %prec THEN 1628 { $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1 ); } 1629 | when_clause_opt ELSE statement 1630 { $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); } 1655 // Called first: create header for WaitForStmt. 1656 { $$ = build_waitfor( yylloc, new ast::WaitForStmt( yylloc ), $1, $2, maybe_build_compound( yylloc, $3 ) ); } 1657 | wor_waitfor_clause wor when_clause_opt waitfor statement 1658 { $$ = build_waitfor( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); } 1659 | wor_waitfor_clause wor when_clause_opt ELSE statement 1660 { $$ = build_waitfor_else( yylloc, $1, $3, maybe_build_compound( yylloc, $5 ) ); } 1661 | wor_waitfor_clause wor when_clause_opt timeout statement %prec THEN 1662 { $$ = build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); } 1631 1663 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless) 1632 | w hen_clause_opt timeout statement WORELSE statement // syntax error1664 | wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error 1633 1665 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; } 1634 | w hen_clause_opt timeout statement WORwhen_clause ELSE statement1635 { $$ = build_waitfor_ timeout( $2, maybe_build_compound( $3 ), $1, maybe_build_compound( $7 ), $5); }1666 | wor_waitfor_clause wor when_clause_opt timeout statement wor when_clause ELSE statement 1667 { $$ = build_waitfor_else( yylloc, build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ), $7, maybe_build_compound( yylloc, $9 ) ); } 1636 1668 ; 1637 1669 1638 1670 waitfor_statement: 1639 when_clause_opt waitfor statement %prec THEN 1640 { $$ = new StatementNode( build_waitfor( $2, $3, $1 ) ); } 1641 | when_clause_opt waitfor statement WOR waitfor_clause 1642 { $$ = new StatementNode( build_waitfor( $2, $3, $1, $5 ) ); } 1671 wor_waitfor_clause %prec THEN 1672 { $$ = new StatementNode( $1 ); } 1673 ; 1674 1675 wand: 1676 ANDAND 1677 | WAND 1678 ; 1679 1680 waituntil: 1681 WAITUNTIL '(' cast_expression ')' 1682 { $$ = $3; } 1683 ; 1684 1685 waituntil_clause: 1686 when_clause_opt waituntil statement 1687 { printf( "waituntil_clause 1\n" ); $$ = nullptr; } 1688 | '(' wor_waituntil_clause ')' 1689 { printf( "waituntil_clause 2\n" ); $$ = nullptr; } 1690 ; 1691 1692 wand_waituntil_clause: 1693 waituntil_clause %prec THEN 1694 { printf( "wand_waituntil_clause 1\n" ); $$ = nullptr; } 1695 | waituntil_clause wand wand_waituntil_clause 1696 { printf( "wand_waituntil_clause 2\n" ); $$ = nullptr; } 1697 ; 1698 1699 wor_waituntil_clause: 1700 wand_waituntil_clause 1701 { printf( "wor_waituntil_clause 1\n" ); $$ = nullptr; } 1702 | wor_waituntil_clause wor wand_waituntil_clause 1703 { printf( "wor_waituntil_clause 2\n" ); $$ = nullptr; } 1704 | wor_waituntil_clause wor when_clause_opt ELSE statement 1705 { printf( "wor_waituntil_clause 3\n" ); $$ = nullptr; } 1706 | wor_waituntil_clause wor when_clause_opt timeout statement %prec THEN 1707 { printf( "wor_waituntil_clause 4\n" ); $$ = nullptr; } 1708 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless) 1709 | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error 1710 { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; } 1711 | wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement 1712 { printf( "wor_waituntil_clause 6\n" ); $$ = nullptr; } 1713 ; 1714 1715 waituntil_statement: 1716 wor_waituntil_clause %prec THEN 1717 // SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement. 1718 { $$ = new StatementNode( build_compound( yylloc, nullptr ) ); } 1643 1719 ; 1644 1720 1645 1721 exception_statement: 1646 TRY compound_statement handler_clause 1647 { $$ = new StatementNode( build_try( $2, $3, nullptr ) ); }1722 TRY compound_statement handler_clause %prec THEN 1723 { $$ = new StatementNode( build_try( yylloc, $2, $3, nullptr ) ); } 1648 1724 | TRY compound_statement finally_clause 1649 { $$ = new StatementNode( build_try( $2, nullptr, $3 ) ); }1725 { $$ = new StatementNode( build_try( yylloc, $2, nullptr, $3 ) ); } 1650 1726 | TRY compound_statement handler_clause finally_clause 1651 { $$ = new StatementNode( build_try( $2, $3, $4 ) ); }1727 { $$ = new StatementNode( build_try( yylloc, $2, $3, $4 ) ); } 1652 1728 ; 1653 1729 1654 1730 handler_clause: 1655 1731 handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement 1656 { $$ = new StatementNode( build_catch($1, $4, $6, $8 ) ); }1732 { $$ = new ClauseNode( build_catch( yylloc, $1, $4, $6, $8 ) ); } 1657 1733 | handler_clause handler_key '(' push exception_declaration pop handler_predicate_opt ')' compound_statement 1658 { $$ = (StatementNode *)$1->set_last( new StatementNode( build_catch($2, $5, $7, $9 ) ) ); }1734 { $$ = $1->set_last( new ClauseNode( build_catch( yylloc, $2, $5, $7, $9 ) ) ); } 1659 1735 ; 1660 1736 … … 1666 1742 1667 1743 handler_key: 1668 CATCH { $$ = CatchStmt::Terminate; }1669 | RECOVER { $$ = CatchStmt::Terminate; }1670 | CATCHRESUME { $$ = CatchStmt::Resume; }1671 | FIXUP { $$ = CatchStmt::Resume; }1744 CATCH { $$ = ast::Terminate; } 1745 | RECOVER { $$ = ast::Terminate; } 1746 | CATCHRESUME { $$ = ast::Resume; } 1747 | FIXUP { $$ = ast::Resume; } 1672 1748 ; 1673 1749 1674 1750 finally_clause: 1675 FINALLY compound_statement { $$ = new StatementNode( build_finally($2 ) ); }1751 FINALLY compound_statement { $$ = new ClauseNode( build_finally( yylloc, $2 ) ); } 1676 1752 ; 1677 1753 … … 1699 1775 asm_statement: 1700 1776 ASM asm_volatile_opt '(' string_literal ')' ';' 1701 { $$ = new StatementNode( build_asm( $2, $4, nullptr ) ); }1777 { $$ = new StatementNode( build_asm( yylloc, $2, $4, nullptr ) ); } 1702 1778 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ')' ';' // remaining GCC 1703 { $$ = new StatementNode( build_asm( $2, $4, $6 ) ); }1779 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6 ) ); } 1704 1780 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ')' ';' 1705 { $$ = new StatementNode( build_asm( $2, $4, $6, $8 ) ); }1781 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8 ) ); } 1706 1782 | ASM asm_volatile_opt '(' string_literal ':' asm_operands_opt ':' asm_operands_opt ':' asm_clobbers_list_opt ')' ';' 1707 { $$ = new StatementNode( build_asm( $2, $4, $6, $8, $10 ) ); }1783 { $$ = new StatementNode( build_asm( yylloc, $2, $4, $6, $8, $10 ) ); } 1708 1784 | ASM asm_volatile_opt GOTO '(' string_literal ':' ':' asm_operands_opt ':' asm_clobbers_list_opt ':' label_list ')' ';' 1709 { $$ = new StatementNode( build_asm( $2, $5, nullptr, $8, $10, $12 ) ); }1785 { $$ = new StatementNode( build_asm( yylloc, $2, $5, nullptr, $8, $10, $12 ) ); } 1710 1786 ; 1711 1787 … … 1731 1807 asm_operand: // GCC 1732 1808 string_literal '(' constant_expression ')' 1733 { $$ = new ExpressionNode( new AsmExpr( nullptr, $1, maybeMoveBuild<Expression>( $3 ) ) ); }1809 { $$ = new ExpressionNode( new ast::AsmExpr( yylloc, "", maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); } 1734 1810 | '[' IDENTIFIER ']' string_literal '(' constant_expression ')' 1735 { $$ = new ExpressionNode( new AsmExpr( $2, $4, maybeMoveBuild<Expression>( $6 ) ) ); } 1811 { 1812 $$ = new ExpressionNode( new ast::AsmExpr( yylloc, *$2.str, maybeMoveBuild( $4 ), maybeMoveBuild( $6 ) ) ); 1813 delete $2.str; 1814 } 1736 1815 ; 1737 1816 … … 1740 1819 { $$ = nullptr; } // use default argument 1741 1820 | string_literal 1742 { $$ = new ExpressionNode( $1 ); }1821 { $$ = $1; } 1743 1822 | asm_clobbers_list_opt ',' string_literal 1744 { $$ = (ExpressionNode *)( $1->set_last( new ExpressionNode( $3 ) )); }1823 { $$ = (ExpressionNode *)( $1->set_last( $3 ) ); } 1745 1824 ; 1746 1825 … … 1748 1827 identifier 1749 1828 { 1750 $$ = new LabelNode(); $$->labels. push_back(*$1 );1829 $$ = new LabelNode(); $$->labels.emplace_back( yylloc, *$1 ); 1751 1830 delete $1; // allocated by lexer 1752 1831 } 1753 1832 | label_list ',' identifier 1754 1833 { 1755 $$ = $1; $1->labels. push_back(*$3 );1834 $$ = $1; $1->labels.emplace_back( yylloc, *$3 ); 1756 1835 delete $3; // allocated by lexer 1757 1836 } … … 1804 1883 { 1805 1884 // printf( "C_DECLARATION1 %p %s\n", $$, $$->name ? $$->name->c_str() : "(nil)" ); 1806 1885 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 1807 1886 // printf( "\tattr %s\n", attr->name.c_str() ); 1808 1887 // } // for … … 1814 1893 static_assert: 1815 1894 STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11 1816 { $$ = DeclarationNode::newStaticAssert( $3, $5); }1895 { $$ = DeclarationNode::newStaticAssert( $3, maybeMoveBuild( $5 ) ); } 1817 1896 | STATICASSERT '(' constant_expression ')' ';' // CFA 1818 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( *new string( "\"\"" ) ) ); }1897 { $$ = DeclarationNode::newStaticAssert( $3, build_constantStr( yylloc, *new string( "\"\"" ) ) ); } 1819 1898 1820 1899 // C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function … … 1939 2018 TYPEDEF type_specifier declarator 1940 2019 { 1941 // if type_specifier is an anon aggregate => name1942 2020 typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "4" ); 1943 $$ = $3->addType( $2 )->addTypedef(); 2021 if ( $2->type->forall || ($2->type->kind == TypeData::Aggregate && $2->type->aggregate.params) ) { 2022 SemanticError( yylloc, "forall qualifier in typedef is currently unimplemented." ); $$ = nullptr; 2023 } else $$ = $3->addType( $2 )->addTypedef(); // watchout frees $2 and $3 1944 2024 } 1945 2025 | typedef_declaration pop ',' push declarator … … 1949 2029 } 1950 2030 | type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 ) 1951 { 1952 typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "6" ); 1953 $$ = $4->addType( $3 )->addQualifiers( $1 )->addTypedef(); 1954 } 2031 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; } 1955 2032 | type_specifier TYPEDEF declarator 1956 { 1957 typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "7" ); 1958 $$ = $3->addType( $1 )->addTypedef(); 1959 } 2033 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; } 1960 2034 | type_specifier TYPEDEF type_qualifier_list declarator 1961 { 1962 typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "8" ); 1963 $$ = $4->addQualifiers( $1 )->addTypedef()->addType( $1 ); 1964 } 2035 { SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; } 1965 2036 ; 1966 2037 … … 1969 2040 TYPEDEF identifier '=' assignment_expression 1970 2041 { 1971 SemanticError( yylloc, "T ypedefexpression is deprecated, use typeof(...) instead." ); $$ = nullptr;2042 SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr; 1972 2043 } 1973 2044 | typedef_expression pop ',' push identifier '=' assignment_expression 1974 2045 { 1975 SemanticError( yylloc, "T ypedefexpression is deprecated, use typeof(...) instead." ); $$ = nullptr;2046 SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr; 1976 2047 } 1977 2048 ; … … 1983 2054 | typedef_expression // deprecated GCC, naming expression type 1984 2055 | sue_declaration_specifier 2056 { 2057 assert( $1->type ); 2058 if ( $1->type->qualifiers.any() ) { // CV qualifiers ? 2059 SemanticError( yylloc, "Useless type qualifier(s) in empty declaration." ); $$ = nullptr; 2060 } 2061 // enums are never empty declarations because there must have at least one enumeration. 2062 if ( $1->type->kind == TypeData::AggregateInst && $1->storageClasses.any() ) { // storage class ? 2063 SemanticError( yylloc, "Useless storage qualifier(s) in empty aggregate declaration." ); $$ = nullptr; 2064 } 2065 } 1985 2066 ; 1986 2067 … … 1988 2069 // A semantic check is required to ensure asm_name only appears on declarations with implicit or explicit static 1989 2070 // storage-class 1990 declarator asm_name_opt initializer_opt2071 variable_declarator asm_name_opt initializer_opt 1991 2072 { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); } 2073 | variable_type_redeclarator asm_name_opt initializer_opt 2074 { $$ = $1->addAsmName( $2 )->addInitializer( $3 ); } 2075 2076 | general_function_declarator asm_name_opt 2077 { $$ = $1->addAsmName( $2 )->addInitializer( nullptr ); } 2078 | general_function_declarator asm_name_opt '=' VOID 2079 { $$ = $1->addAsmName( $2 )->addInitializer( new InitializerNode( true ) ); } 2080 1992 2081 | declaring_list ',' attribute_list_opt declarator asm_name_opt initializer_opt 1993 2082 { $$ = $1->appendList( $4->addQualifiers( $3 )->addAsmName( $5 )->addInitializer( $6 ) ); } 2083 ; 2084 2085 general_function_declarator: 2086 function_type_redeclarator 2087 | function_declarator 1994 2088 ; 1995 2089 … … 2000 2094 | sue_declaration_specifier invalid_types 2001 2095 { 2002 SemanticError( yylloc, 2003 ::toString( "Missing ';' after end of ", 2004 $1->type->enumeration.name ? "enum" : AggregateDecl::aggrString( $1->type->aggregate.kind ), 2005 " declaration" ) ); 2096 SemanticError( yylloc, ::toString( "Missing ';' after end of ", 2097 $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ), 2098 " declaration" ) ); 2006 2099 $$ = nullptr; 2007 2100 } … … 2028 2121 basic_type_specifier 2029 2122 | sue_type_specifier 2030 {2031 // printf( "sue_type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );2032 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2033 // printf( "\tattr %s\n", attr->name.c_str() );2034 // } // for2035 }2036 2123 | type_type_specifier 2037 2124 ; … … 2242 2329 { $$ = DeclarationNode::newTypeof( $3 ); } 2243 2330 | BASETYPEOF '(' type ')' // CFA: basetypeof( x ) y; 2244 { $$ = DeclarationNode::newTypeof( new ExpressionNode( new TypeExpr(maybeMoveBuildType( $3 ) ) ), true ); }2331 { $$ = DeclarationNode::newTypeof( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ), true ); } 2245 2332 | BASETYPEOF '(' comma_expression ')' // CFA: basetypeof( a+b ) y; 2246 2333 { $$ = DeclarationNode::newTypeof( $3, true ); } … … 2255 2342 { 2256 2343 // printf( "sue_declaration_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2257 2344 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2258 2345 // printf( "\tattr %s\n", attr->name.c_str() ); 2259 2346 // } // for … … 2271 2358 { 2272 2359 // printf( "sue_type_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2273 2360 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2274 2361 // printf( "\tattr %s\n", attr->name.c_str() ); 2275 2362 // } // for … … 2349 2436 { 2350 2437 // printf( "elaborated_type %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2351 2438 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2352 2439 // printf( "\tattr %s\n", attr->name.c_str() ); 2353 2440 // } // for … … 2373 2460 '{' field_declaration_list_opt '}' type_parameters_opt 2374 2461 { 2375 // printf( "aggregate_type1 %s\n", $3.str->c_str() );2376 // if ( $2 )2377 // for ( Attribute * attr: reverseIterate( $2->attributes ) ) {2378 // printf( "copySpecifiers12 %s\n", attr->name.c_str() );2379 // } // for2380 2462 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 ); 2381 // printf( "aggregate_type2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );2382 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) {2383 // printf( "aggregate_type3 %s\n", attr->name.c_str() );2384 // } // for2385 2463 } 2386 2464 | aggregate_key attribute_list_opt TYPEDEFname // unqualified type name … … 2391 2469 '{' field_declaration_list_opt '}' type_parameters_opt 2392 2470 { 2393 // printf( "AGG3\n" );2394 2471 DeclarationNode::newFromTypedef( $3 ); 2395 2472 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 ); … … 2402 2479 '{' field_declaration_list_opt '}' type_parameters_opt 2403 2480 { 2404 // printf( "AGG4\n" );2405 2481 DeclarationNode::newFromTypeGen( $3, nullptr ); 2406 2482 $$ = DeclarationNode::newAggregate( $1, $3, $8, $6, true )->addQualifiers( $2 ); … … 2429 2505 // switched to a TYPEGENname. Link any generic arguments from typegen_name to new generic declaration and 2430 2506 // delete newFromTypeGen. 2431 $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 ); 2432 $3->type->symbolic.name = nullptr; 2433 $3->type->symbolic.actuals = nullptr; 2434 delete $3; 2507 if ( $3->type->kind == TypeData::SymbolicInst && ! $3->type->symbolic.isTypedef ) { 2508 $$ = $3->addQualifiers( $2 ); 2509 } else { 2510 $$ = DeclarationNode::newAggregate( $1, $3->type->symbolic.name, $3->type->symbolic.actuals, nullptr, false )->addQualifiers( $2 ); 2511 $3->type->symbolic.name = nullptr; // copied to $$ 2512 $3->type->symbolic.actuals = nullptr; 2513 delete $3; 2514 } 2435 2515 } 2436 2516 ; … … 2443 2523 aggregate_data: 2444 2524 STRUCT vtable_opt 2445 { $$ = AggregateDecl::Struct; }2525 { $$ = ast::AggregateDecl::Struct; } 2446 2526 | UNION 2447 { $$ = AggregateDecl::Union; }2527 { $$ = ast::AggregateDecl::Union; } 2448 2528 | EXCEPTION // CFA 2449 { $$ = AggregateDecl::Exception; }2450 // { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; }2529 { $$ = ast::AggregateDecl::Exception; } 2530 // { SemanticError( yylloc, "exception aggregate is currently unimplemented." ); $$ = ast::AggregateDecl::NoAggregate; } 2451 2531 ; 2452 2532 2453 2533 aggregate_control: // CFA 2454 2534 MONITOR 2455 { $$ = AggregateDecl::Monitor; }2535 { $$ = ast::AggregateDecl::Monitor; } 2456 2536 | MUTEX STRUCT 2457 { $$ = AggregateDecl::Monitor; }2537 { $$ = ast::AggregateDecl::Monitor; } 2458 2538 | GENERATOR 2459 { $$ = AggregateDecl::Generator; }2539 { $$ = ast::AggregateDecl::Generator; } 2460 2540 | MUTEX GENERATOR 2461 { SemanticError( yylloc, "monitor generator is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2541 { 2542 SemanticError( yylloc, "monitor generator is currently unimplemented." ); 2543 $$ = ast::AggregateDecl::NoAggregate; 2544 } 2462 2545 | COROUTINE 2463 { $$ = AggregateDecl::Coroutine; }2546 { $$ = ast::AggregateDecl::Coroutine; } 2464 2547 | MUTEX COROUTINE 2465 { SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2548 { 2549 SemanticError( yylloc, "monitor coroutine is currently unimplemented." ); 2550 $$ = ast::AggregateDecl::NoAggregate; 2551 } 2466 2552 | THREAD 2467 { $$ = AggregateDecl::Thread; }2553 { $$ = ast::AggregateDecl::Thread; } 2468 2554 | MUTEX THREAD 2469 { SemanticError( yylloc, "monitor thread is currently unimplemented." ); $$ = AggregateDecl::NoAggregate; } 2555 { 2556 SemanticError( yylloc, "monitor thread is currently unimplemented." ); 2557 $$ = ast::AggregateDecl::NoAggregate; 2558 } 2470 2559 ; 2471 2560 … … 2483 2572 $$ = fieldDecl( $1, $2 ); 2484 2573 // printf( "type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" ); 2485 2574 // for ( Attribute * attr: reverseIterate( $$->attributes ) ) { 2486 2575 // printf( "\tattr %s\n", attr->name.c_str() ); 2487 2576 // } // for … … 2490 2579 { $$ = fieldDecl( $2, $3 ); distExt( $$ ); } 2491 2580 | STATIC type_specifier field_declaring_list_opt ';' // CFA 2492 2581 { SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; } 2493 2582 | INLINE type_specifier field_abstract_list_opt ';' // CFA 2494 2583 { … … 2501 2590 } 2502 2591 | INLINE aggregate_control ';' // CFA 2503 2592 { SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; } 2504 2593 | typedef_declaration ';' // CFA 2505 2594 | cfa_field_declaring_list ';' // CFA, new style field declaration … … 2527 2616 { $$ = $1->addBitfield( $2 ); } 2528 2617 | variable_type_redeclarator bit_subrange_size_opt 2618 // A semantic check is required to ensure bit_subrange only appears on integral types. 2619 { $$ = $1->addBitfield( $2 ); } 2620 | function_type_redeclarator bit_subrange_size_opt 2529 2621 // A semantic check is required to ensure bit_subrange only appears on integral types. 2530 2622 { $$ = $1->addBitfield( $2 ); } … … 2581 2673 { $$ = DeclarationNode::newEnum( $3->name, $6, true, false, nullptr, $4 )->addQualifiers( $2 ); } 2582 2674 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}' 2583 2584 if ( $3->storageClasses.val != 0 || $3->type->qualifiers. val != 0)2675 { 2676 if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() ) 2585 2677 { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); } 2586 2678 … … 2589 2681 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt 2590 2682 { 2591 if ( $3->storageClasses. val != 0|| $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }2683 if ( $3->storageClasses.any() || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); } 2592 2684 typedefTable.makeTypedef( *$6 ); 2593 2685 } … … 2757 2849 type_no_function: // sizeof, alignof, cast (constructor) 2758 2850 cfa_abstract_declarator_tuple // CFA 2759 | type_specifier 2851 | type_specifier // cannot be type_specifier_nobody, e.g., (struct S {}){} is a thing 2760 2852 | type_specifier abstract_declarator 2761 2853 { $$ = $2->addType( $1 ); } … … 2802 2894 designator_list ':' // C99, CFA uses ":" instead of "=" 2803 2895 | identifier_at ':' // GCC, field name 2804 { $$ = new ExpressionNode( build_varref( $1 ) ); }2896 { $$ = new ExpressionNode( build_varref( yylloc, $1 ) ); } 2805 2897 ; 2806 2898 … … 2814 2906 designator: 2815 2907 '.' identifier_at // C99, field name 2816 { $$ = new ExpressionNode( build_varref( $2 ) ); }2908 { $$ = new ExpressionNode( build_varref( yylloc, $2 ) ); } 2817 2909 | '[' push assignment_expression pop ']' // C99, single array element 2818 2910 // assignment_expression used instead of constant_expression because of shift/reduce conflicts with tuple. … … 2821 2913 { $$ = $3; } 2822 2914 | '[' push constant_expression ELLIPSIS constant_expression pop ']' // GCC, multiple array elements 2823 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $3 ), maybeMoveBuild<Expression>( $5 ) ) ); }2915 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $3 ), maybeMoveBuild( $5 ) ) ); } 2824 2916 | '.' '[' push field_name_list pop ']' // CFA, tuple field selector 2825 2917 { $$ = $4; } … … 2861 2953 { 2862 2954 typedefTable.addToScope( *$2, TYPEDEFname, "9" ); 2863 if ( $1 == TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); }2864 if ( $1 == TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); }2865 if ( $1 == TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); }2955 if ( $1 == ast::TypeDecl::Otype ) { SemanticError( yylloc, "otype keyword is deprecated, use T " ); } 2956 if ( $1 == ast::TypeDecl::Dtype ) { SemanticError( yylloc, "dtype keyword is deprecated, use T &" ); } 2957 if ( $1 == ast::TypeDecl::Ttype ) { SemanticError( yylloc, "ttype keyword is deprecated, use T ..." ); } 2866 2958 } 2867 2959 type_initializer_opt assertion_list_opt … … 2874 2966 { 2875 2967 typedefTable.addToScope( *$2, TYPEDIMname, "9" ); 2876 $$ = DeclarationNode::newTypeParam( TypeDecl::Dimension, $2 );2968 $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dimension, $2 ); 2877 2969 } 2878 2970 // | type_specifier identifier_parameter_declarator 2879 2971 | assertion_list 2880 { $$ = DeclarationNode::newTypeParam( TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }2972 { $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); } 2881 2973 ; 2882 2974 2883 2975 new_type_class: // CFA 2884 2976 // empty 2885 { $$ = TypeDecl::Otype; }2977 { $$ = ast::TypeDecl::Otype; } 2886 2978 | '&' 2887 { $$ = TypeDecl::Dtype; }2979 { $$ = ast::TypeDecl::Dtype; } 2888 2980 | '*' 2889 { $$ = TypeDecl::DStype; } // dtype + sized2981 { $$ = ast::TypeDecl::DStype; } // dtype + sized 2890 2982 // | '(' '*' ')' 2891 // { $$ = TypeDecl::Ftype; }2983 // { $$ = ast::TypeDecl::Ftype; } 2892 2984 | ELLIPSIS 2893 { $$ = TypeDecl::Ttype; }2985 { $$ = ast::TypeDecl::Ttype; } 2894 2986 ; 2895 2987 2896 2988 type_class: // CFA 2897 2989 OTYPE 2898 { $$ = TypeDecl::Otype; }2990 { $$ = ast::TypeDecl::Otype; } 2899 2991 | DTYPE 2900 { $$ = TypeDecl::Dtype; }2992 { $$ = ast::TypeDecl::Dtype; } 2901 2993 | FTYPE 2902 { $$ = TypeDecl::Ftype; }2994 { $$ = ast::TypeDecl::Ftype; } 2903 2995 | TTYPE 2904 { $$ = TypeDecl::Ttype; }2996 { $$ = ast::TypeDecl::Ttype; } 2905 2997 ; 2906 2998 … … 2928 3020 type_list: // CFA 2929 3021 type 2930 { $$ = new ExpressionNode( new TypeExpr(maybeMoveBuildType( $1 ) ) ); }3022 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); } 2931 3023 | assignment_expression 2932 3024 | type_list ',' type 2933 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr(maybeMoveBuildType( $3 ) ) ) )); }3025 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); } 2934 3026 | type_list ',' assignment_expression 2935 3027 { $$ = (ExpressionNode *)( $1->set_last( $3 )); } … … 2968 3060 TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' '}' 2969 3061 { 2970 SemanticWarning( yylloc, Warning::DeprecTraitSyntax , "");3062 SemanticWarning( yylloc, Warning::DeprecTraitSyntax ); 2971 3063 $$ = DeclarationNode::newTrait( $2, $4, nullptr ); 2972 3064 } … … 2975 3067 | TRAIT identifier_or_type_name '(' type_parameter_list ')' '{' push trait_declaration_list pop '}' 2976 3068 { 2977 SemanticWarning( yylloc, Warning::DeprecTraitSyntax , "");3069 SemanticWarning( yylloc, Warning::DeprecTraitSyntax ); 2978 3070 $$ = DeclarationNode::newTrait( $2, $4, $8 ); 2979 3071 } … … 3038 3130 external_definition: 3039 3131 DIRECTIVE 3040 { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( $1 ) ) ); }3132 { $$ = DeclarationNode::newDirectiveStmt( new StatementNode( build_directive( yylloc, $1 ) ) ); } 3041 3133 | declaration 3134 { 3135 // Variable declarations of anonymous types requires creating a unique type-name across multiple translation 3136 // unit, which is a dubious task, especially because C uses name rather than structural typing; hence it is 3137 // disallowed at the moment. 3138 if ( $1->linkage == ast::Linkage::Cforall && ! $1->storageClasses.is_static && $1->type && $1->type->kind == TypeData::AggregateInst ) { 3139 if ( $1->type->aggInst.aggregate->kind == TypeData::Enum && $1->type->aggInst.aggregate->enumeration.anon ) { 3140 SemanticError( yylloc, "extern anonymous enumeration is currently unimplemented." ); $$ = nullptr; 3141 } else if ( $1->type->aggInst.aggregate->aggregate.anon ) { // handles struct or union 3142 SemanticError( yylloc, "extern anonymous struct/union is currently unimplemented." ); $$ = nullptr; 3143 } 3144 } 3145 } 3042 3146 | IDENTIFIER IDENTIFIER 3043 3147 { IdentifierBeforeIdentifier( *$1.str, *$2.str, " declaration" ); $$ = nullptr; } … … 3059 3163 } 3060 3164 | ASM '(' string_literal ')' ';' // GCC, global assembler statement 3061 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( false, $3, nullptr ) ) ); }3165 { $$ = DeclarationNode::newAsmStmt( new StatementNode( build_asm( yylloc, false, $3, nullptr ) ) ); } 3062 3166 | EXTERN STRINGliteral 3063 3167 { 3064 3168 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall" 3065 linkage = LinkageSpec::update( yylloc, linkage, $2 );3169 linkage = ast::Linkage::update( yylloc, linkage, $2 ); 3066 3170 } 3067 3171 up external_definition down … … 3074 3178 { 3075 3179 linkageStack.push( linkage ); // handle nested extern "C"/"Cforall" 3076 linkage = LinkageSpec::update( yylloc, linkage, $2 );3180 linkage = ast::Linkage::update( yylloc, linkage, $2 ); 3077 3181 } 3078 3182 '{' up external_definition_list_opt down '}' … … 3085 3189 | type_qualifier_list 3086 3190 { 3087 if ( $1->type->qualifiers. val) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }3191 if ( $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); } 3088 3192 if ( $1->type->forall ) forall = true; // remember generic type 3089 3193 } … … 3091 3195 { 3092 3196 distQual( $5, $1 ); 3093 3197 forall = false; 3094 3198 $$ = $5; 3095 3199 } 3096 3200 | declaration_qualifier_list 3097 3201 { 3098 if ( $1->type && $1->type->qualifiers. val) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }3202 if ( $1->type && $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); } 3099 3203 if ( $1->type && $1->type->forall ) forall = true; // remember generic type 3100 3204 } … … 3102 3206 { 3103 3207 distQual( $5, $1 ); 3104 3208 forall = false; 3105 3209 $$ = $5; 3106 3210 } 3107 3211 | declaration_qualifier_list type_qualifier_list 3108 3212 { 3109 if ( ($1->type && $1->type->qualifiers. val) || ($2->type && $2->type->qualifiers.val) ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); }3213 if ( ($1->type && $1->type->qualifiers.any()) || ($2->type && $2->type->qualifiers.any()) ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); } 3110 3214 if ( ($1->type && $1->type->forall) || ($2->type && $2->type->forall) ) forall = true; // remember generic type 3111 3215 } … … 3113 3217 { 3114 3218 distQual( $6, $1->addQualifiers( $2 ) ); 3115 3219 forall = false; 3116 3220 $$ = $6; 3117 3221 } … … 3157 3261 $$ = $2->addFunctionBody( $4, $3 )->addType( $1 ); 3158 3262 } 3159 | declaration_specifier variable_type_redeclarator with_clause_opt compound_statement3263 | declaration_specifier function_type_redeclarator with_clause_opt compound_statement 3160 3264 { 3161 3265 rebindForall( $1, $2 ); … … 3193 3297 | variable_type_redeclarator 3194 3298 | function_declarator 3299 | function_type_redeclarator 3195 3300 ; 3196 3301 3197 3302 subrange: 3198 3303 constant_expression '~' constant_expression // CFA, integer subrange 3199 { $$ = new ExpressionNode( new RangeExpr( maybeMoveBuild<Expression>( $1 ), maybeMoveBuild<Expression>( $3 ) ) ); }3304 { $$ = new ExpressionNode( new ast::RangeExpr( yylloc, maybeMoveBuild( $1 ), maybeMoveBuild( $3 ) ) ); } 3200 3305 ; 3201 3306 … … 3206 3311 { 3207 3312 DeclarationNode * name = new DeclarationNode(); 3208 name->asmName = $3;3313 name->asmName = maybeMoveBuild( $3 ); 3209 3314 $$ = name->addQualifiers( $5 ); 3210 3315 } … … 3319 3424 | '(' attribute_list variable_ptr ')' array_dimension 3320 3425 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3321 | '(' variable_array ')' multi_array_dimension 3426 | '(' variable_array ')' multi_array_dimension // redundant parenthesis 3322 3427 { $$ = $2->addArray( $4 ); } 3323 3428 | '(' attribute_list variable_array ')' multi_array_dimension // redundant parenthesis … … 3443 3548 ; 3444 3549 3445 // This pattern parses a declaration for a variable or function prototypethat redefines a type name, e.g.:3550 // This pattern parses a declaration for a variable that redefines a type name, e.g.: 3446 3551 // 3447 3552 // typedef int foo; … … 3449 3554 // int foo; // redefine typedef name in new scope 3450 3555 // } 3451 //3452 // The pattern precludes declaring an array of functions versus a pointer to an array of functions, and returning arrays3453 // and functions versus pointers to arrays and functions.3454 3556 3455 3557 paren_type: … … 3466 3568 paren_type attribute_list_opt 3467 3569 { $$ = $1->addQualifiers( $2 ); } 3468 | type_ptr3469 | type_array attribute_list_opt3570 | variable_type_ptr 3571 | variable_type_array attribute_list_opt 3470 3572 { $$ = $1->addQualifiers( $2 ); } 3471 | type_function attribute_list_opt3573 | variable_type_function attribute_list_opt 3472 3574 { $$ = $1->addQualifiers( $2 ); } 3473 3575 ; 3474 3576 3475 type_ptr:3577 variable_type_ptr: 3476 3578 ptrref_operator variable_type_redeclarator 3477 3579 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3478 3580 | ptrref_operator type_qualifier_list variable_type_redeclarator 3479 3581 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 3480 | '(' type_ptr ')' attribute_list_opt// redundant parenthesis3582 | '(' variable_type_ptr ')' attribute_list_opt // redundant parenthesis 3481 3583 { $$ = $2->addQualifiers( $4 ); } 3482 | '(' attribute_list type_ptr ')' attribute_list_opt // redundant parenthesis3584 | '(' attribute_list variable_type_ptr ')' attribute_list_opt // redundant parenthesis 3483 3585 { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); } 3484 3586 ; 3485 3587 3486 type_array:3588 variable_type_array: 3487 3589 paren_type array_dimension 3488 3590 { $$ = $1->addArray( $2 ); } 3489 | '(' type_ptr ')' array_dimension3591 | '(' variable_type_ptr ')' array_dimension 3490 3592 { $$ = $2->addArray( $4 ); } 3491 | '(' attribute_list type_ptr ')' array_dimension3593 | '(' attribute_list variable_type_ptr ')' array_dimension 3492 3594 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3493 | '(' type_array ')' multi_array_dimension// redundant parenthesis3595 | '(' variable_type_array ')' multi_array_dimension // redundant parenthesis 3494 3596 { $$ = $2->addArray( $4 ); } 3495 | '(' attribute_list type_array ')' multi_array_dimension // redundant parenthesis3597 | '(' attribute_list variable_type_array ')' multi_array_dimension // redundant parenthesis 3496 3598 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3497 | '(' type_array ')'// redundant parenthesis3599 | '(' variable_type_array ')' // redundant parenthesis 3498 3600 { $$ = $2; } 3499 | '(' attribute_list type_array ')'// redundant parenthesis3601 | '(' attribute_list variable_type_array ')' // redundant parenthesis 3500 3602 { $$ = $3->addQualifiers( $2 ); } 3501 3603 ; 3502 3604 3503 type_function: 3605 variable_type_function: 3606 '(' variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3607 { $$ = $2->addParamList( $6 ); } 3608 | '(' attribute_list variable_type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3609 { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); } 3610 | '(' variable_type_function ')' // redundant parenthesis 3611 { $$ = $2; } 3612 | '(' attribute_list variable_type_function ')' // redundant parenthesis 3613 { $$ = $3->addQualifiers( $2 ); } 3614 ; 3615 3616 // This pattern parses a declaration for a function prototype that redefines a type name. It precludes declaring an 3617 // array of functions versus a pointer to an array of functions, and returning arrays and functions versus pointers to 3618 // arrays and functions. 3619 3620 function_type_redeclarator: 3621 function_type_no_ptr attribute_list_opt 3622 { $$ = $1->addQualifiers( $2 ); } 3623 | function_type_ptr 3624 | function_type_array attribute_list_opt 3625 { $$ = $1->addQualifiers( $2 ); } 3626 ; 3627 3628 function_type_no_ptr: 3504 3629 paren_type '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3) 3505 3630 { $$ = $1->addParamList( $4 ); } 3506 | '(' type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)3631 | '(' function_type_ptr ')' '(' push parameter_type_list_opt pop ')' 3507 3632 { $$ = $2->addParamList( $6 ); } 3508 | '(' attribute_list type_ptr ')' '(' push parameter_type_list_opt pop ')' // empty parameter list OBSOLESCENT (see 3)3633 | '(' attribute_list function_type_ptr ')' '(' push parameter_type_list_opt pop ')' 3509 3634 { $$ = $3->addQualifiers( $2 )->addParamList( $7 ); } 3510 | '(' type_function ')'// redundant parenthesis3635 | '(' function_type_no_ptr ')' // redundant parenthesis 3511 3636 { $$ = $2; } 3512 | '(' attribute_list type_function ')' // redundant parenthesis 3637 | '(' attribute_list function_type_no_ptr ')' // redundant parenthesis 3638 { $$ = $3->addQualifiers( $2 ); } 3639 ; 3640 3641 function_type_ptr: 3642 ptrref_operator function_type_redeclarator 3643 { $$ = $2->addPointer( DeclarationNode::newPointer( nullptr, $1 ) ); } 3644 | ptrref_operator type_qualifier_list function_type_redeclarator 3645 { $$ = $3->addPointer( DeclarationNode::newPointer( $2, $1 ) ); } 3646 | '(' function_type_ptr ')' attribute_list_opt 3647 { $$ = $2->addQualifiers( $4 ); } 3648 | '(' attribute_list function_type_ptr ')' attribute_list_opt 3649 { $$ = $3->addQualifiers( $2 )->addQualifiers( $5 ); } 3650 ; 3651 3652 function_type_array: 3653 '(' function_type_ptr ')' array_dimension 3654 { $$ = $2->addArray( $4 ); } 3655 | '(' attribute_list function_type_ptr ')' array_dimension 3656 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3657 | '(' function_type_array ')' multi_array_dimension // redundant parenthesis 3658 { $$ = $2->addArray( $4 ); } 3659 | '(' attribute_list function_type_array ')' multi_array_dimension // redundant parenthesis 3660 { $$ = $3->addQualifiers( $2 )->addArray( $5 ); } 3661 | '(' function_type_array ')' // redundant parenthesis 3662 { $$ = $2; } 3663 | '(' attribute_list function_type_array ')' // redundant parenthesis 3513 3664 { $$ = $3->addQualifiers( $2 ); } 3514 3665 ; … … 3680 3831 array_type_list: 3681 3832 basic_type_name 3682 { $$ = new ExpressionNode( new TypeExpr(maybeMoveBuildType( $1 ) ) ); }3833 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); } 3683 3834 | type_name 3684 { $$ = new ExpressionNode( new TypeExpr(maybeMoveBuildType( $1 ) ) ); }3835 { $$ = new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $1 ) ) ); } 3685 3836 | assignment_expression upupeq assignment_expression 3686 3837 | array_type_list ',' basic_type_name 3687 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr(maybeMoveBuildType( $3 ) ) ) )); }3688 | array_type_list ',' type_name 3689 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new TypeExpr(maybeMoveBuildType( $3 ) ) ) )); }3838 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); } 3839 | array_type_list ',' type_name 3840 { $$ = (ExpressionNode *)($1->set_last( new ExpressionNode( new ast::TypeExpr( yylloc, maybeMoveBuildType( $3 ) ) ) )); } 3690 3841 | array_type_list ',' assignment_expression upupeq assignment_expression 3691 3842 ; … … 3696 3847 | ErangeUpEq 3697 3848 { $$ = OperKinds::LEThan; } 3698 3849 ; 3699 3850 3700 3851 multi_array_dimension: -
src/Parser/parserutility.cc
r2ed94a9 rb110bcc 10 10 // Created On : Sat May 16 15:30:39 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tus Jul 18 10:12:00 201713 // Update Count : 812 // Last Modified On : Wed Mar 1 10:42:00 2023 13 // Update Count : 9 14 14 // 15 15 … … 19 19 #include <string> // for string 20 20 21 #include "SynTree/Constant.h" // for Constant 22 #include "SynTree/Expression.h" // for UntypedExpr, CastExpr, ConstantExpr 23 #include "SynTree/Type.h" // for BasicType, ZeroType, BasicType::Kind... 21 #include "AST/Expr.hpp" // for UntypedExpr, CastExpr, ConstantExpr 22 #include "AST/Type.hpp" // for BasicType, ZeroType, BasicType::Kind... 24 23 25 24 // rewrite … … 28 27 // if ( (int)(x != 0) ) ... 29 28 30 Expression *notZeroExpr( Expression *orig ) { 31 if( !orig ) return nullptr; 32 UntypedExpr *comparison = new UntypedExpr( new NameExpr( "?!=?" ) ); 33 comparison->get_args().push_back( orig ); 34 comparison->get_args().push_back( new ConstantExpr( Constant( new ZeroType( noQualifiers ), "0", (unsigned long long int)0 ) ) ); 35 return new CastExpr( comparison, new BasicType( Type::Qualifiers(), BasicType::SignedInt ) ); 29 ast::Expr * notZeroExpr( ast::Expr * orig ) { 30 return ( !orig ) ? nullptr : new ast::CastExpr( orig->location, 31 ast::UntypedExpr::createCall( orig->location, 32 "?!=?", 33 { 34 orig, 35 new ast::ConstantExpr( orig->location, 36 new ast::ZeroType(), 37 "0", 38 std::optional<unsigned long long>( 0 ) 39 ), 40 } 41 ), 42 new ast::BasicType( ast::BasicType::SignedInt ) 43 ); 36 44 } 37 45 -
src/Parser/parserutility.h
r2ed94a9 rb110bcc 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 : Tue Apr 4 14:03:00 2023 13 // Update Count : 7 14 14 // 15 15 16 16 #pragma once 17 17 18 class Expression; 18 #include "AST/Copy.hpp" // for shallowCopy 19 namespace ast { 20 class Expr; 21 } 19 22 20 Expression *notZeroExpr( Expression *orig ); 23 ast::Expr * notZeroExpr( ast::Expr *orig ); 24 25 template< typename T > 26 static inline auto maybeBuild( T * orig ) -> decltype(orig->build()) { 27 return (orig) ? orig->build() : nullptr; 28 } 29 30 template< typename T > 31 static inline auto maybeMoveBuild( T * orig ) -> decltype(orig->build()) { 32 auto ret = maybeBuild<T>(orig); 33 delete orig; 34 return ret; 35 } 36 37 template<typename node_t> 38 node_t * maybeCopy( node_t const * node ) { 39 return node ? ast::shallowCopy( node ) : nullptr; 40 } 21 41 22 42 // Local Variables: // -
src/ResolvExpr/Candidate.cpp
r2ed94a9 rb110bcc 17 17 18 18 #include <iostream> 19 #include <sstream> 19 20 20 21 #include "AST/Print.hpp" … … 44 45 sorted.reserve(cands.size()); 45 46 for(const auto & c : cands) { 46 std:: stringstream ss;47 std::ostringstream ss; 47 48 print( ss, *c, indent ); 48 49 sorted.push_back(ss.str()); -
src/ResolvExpr/CandidateFinder.cpp
r2ed94a9 rb110bcc 55 55 namespace ResolvExpr { 56 56 57 /// Unique identifier for matching expression resolutions to their requesting expression 58 UniqueId globalResnSlot = 0; 59 60 namespace { 61 /// First index is which argument, second is which alternative, third is which exploded element 62 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >; 63 64 /// Returns a list of alternatives with the minimum cost in the given list 65 CandidateList findMinCost( const CandidateList & candidates ) { 66 CandidateList out; 67 Cost minCost = Cost::infinity; 68 for ( const CandidateRef & r : candidates ) { 69 if ( r->cost < minCost ) { 70 minCost = r->cost; 71 out.clear(); 72 out.emplace_back( r ); 73 } else if ( r->cost == minCost ) { 74 out.emplace_back( r ); 75 } 76 } 77 return out; 78 } 79 80 /// Computes conversion cost for a given expression to a given type 81 const ast::Expr * computeExpressionConversionCost( 82 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost 83 ) { 84 Cost convCost = computeConversionCost( 85 arg->result, paramType, arg->get_lvalue(), symtab, env ); 86 outCost += convCost; 87 88 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires 89 // conversion. Ignore poly cost for now, since this requires resolution of the cast to 90 // infer parameters and this does not currently work for the reason stated below 91 Cost tmpCost = convCost; 92 tmpCost.incPoly( -tmpCost.get_polyCost() ); 93 if ( tmpCost != Cost::zero ) { 94 ast::ptr< ast::Type > newType = paramType; 95 env.apply( newType ); 96 return new ast::CastExpr{ arg, newType }; 97 98 // xxx - *should* be able to resolve this cast, but at the moment pointers are not 99 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent, 100 // once this is fixed it should be possible to resolve the cast. 101 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable, 102 // but it shouldn't be because this makes the conversion from DT* to DT* since 103 // commontype(zero_t, DT*) is DT*, rather than nothing 104 105 // CandidateFinder finder{ symtab, env }; 106 // finder.find( arg, ResolvMode::withAdjustment() ); 107 // assertf( finder.candidates.size() > 0, 108 // "Somehow castable expression failed to find alternatives." ); 109 // assertf( finder.candidates.size() == 1, 110 // "Somehow got multiple alternatives for known cast expression." ); 111 // return finder.candidates.front()->expr; 112 } 113 114 return arg; 115 } 116 117 /// Computes conversion cost for a given candidate 118 Cost computeApplicationConversionCost( 119 CandidateRef cand, const ast::SymbolTable & symtab 120 ) { 121 auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >(); 122 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 123 auto function = pointer->base.strict_as< ast::FunctionType >(); 124 125 Cost convCost = Cost::zero; 126 const auto & params = function->params; 127 auto param = params.begin(); 128 auto & args = appExpr->args; 129 130 for ( unsigned i = 0; i < args.size(); ++i ) { 131 const ast::Type * argType = args[i]->result; 132 PRINT( 133 std::cerr << "arg expression:" << std::endl; 134 ast::print( std::cerr, args[i], 2 ); 135 std::cerr << "--- results are" << std::endl; 136 ast::print( std::cerr, argType, 2 ); 137 ) 138 139 if ( param == params.end() ) { 140 if ( function->isVarArgs ) { 141 convCost.incUnsafe(); 142 PRINT( std::cerr << "end of params with varargs function: inc unsafe: " 143 << convCost << std::endl; ; ) 144 // convert reference-typed expressions into value-typed expressions 145 cand->expr = ast::mutate_field_index( 146 appExpr, &ast::ApplicationExpr::args, i, 147 referenceToRvalueConversion( args[i], convCost ) ); 148 continue; 149 } else return Cost::infinity; 150 } 151 152 if ( auto def = args[i].as< ast::DefaultArgExpr >() ) { 153 // Default arguments should be free - don't include conversion cost. 154 // Unwrap them here because they are not relevant to the rest of the system 155 cand->expr = ast::mutate_field_index( 156 appExpr, &ast::ApplicationExpr::args, i, def->expr ); 157 ++param; 158 continue; 159 } 160 161 // mark conversion cost and also specialization cost of param type 162 // const ast::Type * paramType = (*param)->get_type(); 163 cand->expr = ast::mutate_field_index( 164 appExpr, &ast::ApplicationExpr::args, i, 165 computeExpressionConversionCost( 166 args[i], *param, symtab, cand->env, convCost ) ); 167 convCost.decSpec( specCost( *param ) ); 168 ++param; // can't be in for-loop update because of the continue 169 } 170 171 if ( param != params.end() ) return Cost::infinity; 172 173 // specialization cost of return types can't be accounted for directly, it disables 174 // otherwise-identical calls, like this example based on auto-newline in the I/O lib: 175 // 176 // forall(otype OS) { 177 // void ?|?(OS&, int); // with newline 178 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization 179 // } 180 181 // mark type variable and specialization cost of forall clause 182 convCost.incVar( function->forall.size() ); 183 convCost.decSpec( function->assertions.size() ); 184 185 return convCost; 186 } 187 188 void makeUnifiableVars( 189 const ast::FunctionType * type, ast::OpenVarSet & unifiableVars, 190 ast::AssertionSet & need 191 ) { 192 for ( auto & tyvar : type->forall ) { 193 unifiableVars[ *tyvar ] = ast::TypeData{ tyvar->base }; 194 } 195 for ( auto & assn : type->assertions ) { 196 need[ assn ].isUsed = true; 197 } 198 } 199 200 /// Gets a default value from an initializer, nullptr if not present 201 const ast::ConstantExpr * getDefaultValue( const ast::Init * init ) { 202 if ( auto si = dynamic_cast< const ast::SingleInit * >( init ) ) { 203 if ( auto ce = si->value.as< ast::CastExpr >() ) { 204 return ce->arg.as< ast::ConstantExpr >(); 205 } else { 206 return si->value.as< ast::ConstantExpr >(); 207 } 208 } 209 return nullptr; 210 } 211 212 /// State to iteratively build a match of parameter expressions to arguments 213 struct ArgPack { 214 std::size_t parent; ///< Index of parent pack 215 ast::ptr< ast::Expr > expr; ///< The argument stored here 216 Cost cost; ///< The cost of this argument 217 ast::TypeEnvironment env; ///< Environment for this pack 218 ast::AssertionSet need; ///< Assertions outstanding for this pack 219 ast::AssertionSet have; ///< Assertions found for this pack 220 ast::OpenVarSet open; ///< Open variables for this pack 221 unsigned nextArg; ///< Index of next argument in arguments list 222 unsigned tupleStart; ///< Number of tuples that start at this index 223 unsigned nextExpl; ///< Index of next exploded element 224 unsigned explAlt; ///< Index of alternative for nextExpl > 0 225 226 ArgPack() 227 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ), 228 tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 229 230 ArgPack( 231 const ast::TypeEnvironment & env, const ast::AssertionSet & need, 232 const ast::AssertionSet & have, const ast::OpenVarSet & open ) 233 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ), 234 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {} 235 236 ArgPack( 237 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env, 238 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open, 239 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero, 240 unsigned nextExpl = 0, unsigned explAlt = 0 ) 241 : parent(parent), expr( expr ), cost( cost ), env( std::move( env ) ), need( std::move( need ) ), 242 have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ), 243 nextExpl( nextExpl ), explAlt( explAlt ) {} 244 245 ArgPack( 246 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need, 247 ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added ) 248 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( std::move( env ) ), 249 need( std::move( need ) ), have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), 250 tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {} 251 252 /// true if this pack is in the middle of an exploded argument 253 bool hasExpl() const { return nextExpl > 0; } 254 255 /// Gets the list of exploded candidates for this pack 256 const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const { 257 return args[ nextArg-1 ][ explAlt ]; 258 } 259 260 /// Ends a tuple expression, consolidating the appropriate args 261 void endTuple( const std::vector< ArgPack > & packs ) { 262 // add all expressions in tuple to list, summing cost 263 std::deque< const ast::Expr * > exprs; 264 const ArgPack * pack = this; 265 if ( expr ) { exprs.emplace_front( expr ); } 266 while ( pack->tupleStart == 0 ) { 267 pack = &packs[pack->parent]; 268 exprs.emplace_front( pack->expr ); 269 cost += pack->cost; 270 } 271 // reset pack to appropriate tuple 272 std::vector< ast::ptr< ast::Expr > > exprv( exprs.begin(), exprs.end() ); 273 expr = new ast::TupleExpr{ expr->location, std::move( exprv ) }; 274 tupleStart = pack->tupleStart - 1; 275 parent = pack->parent; 276 } 277 }; 278 279 /// Instantiates an argument to match a parameter, returns false if no matching results left 280 bool instantiateArgument( 281 const CodeLocation & location, 282 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args, 283 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab, 284 unsigned nTuples = 0 285 ) { 286 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) { 287 // paramType is a TupleType -- group args into a TupleExpr 288 ++nTuples; 289 for ( const ast::Type * type : *tupleType ) { 290 // xxx - dropping initializer changes behaviour from previous, but seems correct 291 // ^^^ need to handle the case where a tuple has a default argument 292 if ( ! instantiateArgument( location, 293 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false; 294 nTuples = 0; 295 } 296 // re-constitute tuples for final generation 297 for ( auto i = genStart; i < results.size(); ++i ) { 298 results[i].endTuple( results ); 299 } 300 return true; 301 } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) { 302 // paramType is a ttype, consumes all remaining arguments 303 304 // completed tuples; will be spliced to end of results to finish 305 std::vector< ArgPack > finalResults{}; 306 307 // iterate until all results completed 308 std::size_t genEnd; 309 ++nTuples; 310 do { 311 genEnd = results.size(); 312 313 // add another argument to results 314 for ( std::size_t i = genStart; i < genEnd; ++i ) { 315 unsigned nextArg = results[i].nextArg; 316 317 // use next element of exploded tuple if present 318 if ( results[i].hasExpl() ) { 319 const ExplodedArg & expl = results[i].getExpl( args ); 320 321 unsigned nextExpl = results[i].nextExpl + 1; 322 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 323 324 results.emplace_back( 325 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ), 326 copy( results[i].need ), copy( results[i].have ), 327 copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl, 328 results[i].explAlt ); 329 330 continue; 331 } 332 333 // finish result when out of arguments 334 if ( nextArg >= args.size() ) { 335 ArgPack newResult{ 336 results[i].env, results[i].need, results[i].have, results[i].open }; 337 newResult.nextArg = nextArg; 338 const ast::Type * argType = nullptr; 339 340 if ( nTuples > 0 || ! results[i].expr ) { 341 // first iteration or no expression to clone, 342 // push empty tuple expression 343 newResult.parent = i; 344 newResult.expr = new ast::TupleExpr( location, {} ); 345 argType = newResult.expr->result; 346 } else { 347 // clone result to collect tuple 348 newResult.parent = results[i].parent; 349 newResult.cost = results[i].cost; 350 newResult.tupleStart = results[i].tupleStart; 351 newResult.expr = results[i].expr; 352 argType = newResult.expr->result; 353 354 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) { 355 // the case where a ttype value is passed directly is special, 356 // e.g. for argument forwarding purposes 357 // xxx - what if passing multiple arguments, last of which is 358 // ttype? 359 // xxx - what would happen if unify was changed so that unifying 360 // tuple 361 // types flattened both before unifying lists? then pass in 362 // TupleType (ttype) below. 363 --newResult.tupleStart; 364 } else { 365 // collapse leftover arguments into tuple 366 newResult.endTuple( results ); 367 argType = newResult.expr->result; 368 } 369 } 370 371 // check unification for ttype before adding to final 372 if ( 373 unify( 374 ttype, argType, newResult.env, newResult.need, newResult.have, 375 newResult.open, symtab ) 376 ) { 377 finalResults.emplace_back( std::move( newResult ) ); 378 } 379 380 continue; 381 } 382 383 // add each possible next argument 384 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 385 const ExplodedArg & expl = args[nextArg][j]; 386 387 // fresh copies of parent parameters for this iteration 388 ast::TypeEnvironment env = results[i].env; 389 ast::OpenVarSet open = results[i].open; 390 391 env.addActual( expl.env, open ); 392 393 // skip empty tuple arguments by (nearly) cloning parent into next gen 394 if ( expl.exprs.empty() ) { 395 results.emplace_back( 396 results[i], std::move( env ), copy( results[i].need ), 397 copy( results[i].have ), std::move( open ), nextArg + 1, expl.cost ); 398 399 continue; 400 } 401 402 // add new result 403 results.emplace_back( 404 i, expl.exprs.front(), std::move( env ), copy( results[i].need ), 405 copy( results[i].have ), std::move( open ), nextArg + 1, nTuples, 406 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 407 } 408 } 409 410 // reset for next round 411 genStart = genEnd; 412 nTuples = 0; 413 } while ( genEnd != results.size() ); 414 415 // splice final results onto results 416 for ( std::size_t i = 0; i < finalResults.size(); ++i ) { 417 results.emplace_back( std::move( finalResults[i] ) ); 418 } 419 return ! finalResults.empty(); 420 } 421 422 // iterate each current subresult 423 std::size_t genEnd = results.size(); 424 for ( std::size_t i = genStart; i < genEnd; ++i ) { 425 unsigned nextArg = results[i].nextArg; 426 427 // use remainder of exploded tuple if present 428 if ( results[i].hasExpl() ) { 429 const ExplodedArg & expl = results[i].getExpl( args ); 430 const ast::Expr * expr = expl.exprs[ results[i].nextExpl ]; 431 432 ast::TypeEnvironment env = results[i].env; 433 ast::AssertionSet need = results[i].need, have = results[i].have; 434 ast::OpenVarSet open = results[i].open; 435 436 const ast::Type * argType = expr->result; 437 438 PRINT( 439 std::cerr << "param type is "; 440 ast::print( std::cerr, paramType ); 441 std::cerr << std::endl << "arg type is "; 442 ast::print( std::cerr, argType ); 443 std::cerr << std::endl; 444 ) 445 446 if ( unify( paramType, argType, env, need, have, open, symtab ) ) { 447 unsigned nextExpl = results[i].nextExpl + 1; 448 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 449 450 results.emplace_back( 451 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), nextArg, 452 nTuples, Cost::zero, nextExpl, results[i].explAlt ); 453 } 454 455 continue; 456 } 457 458 // use default initializers if out of arguments 459 if ( nextArg >= args.size() ) { 460 if ( const ast::ConstantExpr * cnst = getDefaultValue( init ) ) { 461 ast::TypeEnvironment env = results[i].env; 462 ast::AssertionSet need = results[i].need, have = results[i].have; 463 ast::OpenVarSet open = results[i].open; 464 465 if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) { 466 results.emplace_back( 467 i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ), 468 std::move( need ), std::move( have ), std::move( open ), nextArg, nTuples ); 469 } 470 } 471 472 continue; 473 } 474 475 // Check each possible next argument 476 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 477 const ExplodedArg & expl = args[nextArg][j]; 478 479 // fresh copies of parent parameters for this iteration 480 ast::TypeEnvironment env = results[i].env; 481 ast::AssertionSet need = results[i].need, have = results[i].have; 482 ast::OpenVarSet open = results[i].open; 483 484 env.addActual( expl.env, open ); 485 486 // skip empty tuple arguments by (nearly) cloning parent into next gen 487 if ( expl.exprs.empty() ) { 488 results.emplace_back( 489 results[i], std::move( env ), std::move( need ), std::move( have ), std::move( open ), 490 nextArg + 1, expl.cost ); 491 492 continue; 493 } 494 495 // consider only first exploded arg 496 const ast::Expr * expr = expl.exprs.front(); 497 const ast::Type * argType = expr->result; 498 499 PRINT( 500 std::cerr << "param type is "; 501 ast::print( std::cerr, paramType ); 502 std::cerr << std::endl << "arg type is "; 503 ast::print( std::cerr, argType ); 504 std::cerr << std::endl; 505 ) 506 507 // attempt to unify types 508 if ( unify( paramType, argType, env, need, have, open, symtab ) ) { 509 // add new result 510 results.emplace_back( 511 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), 512 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j ); 513 } 514 } 515 } 516 517 // reset for next parameter 518 genStart = genEnd; 519 520 return genEnd != results.size(); // were any new results added? 521 } 522 523 /// Generate a cast expression from `arg` to `toType` 524 const ast::Expr * restructureCast( 525 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast 526 ) { 527 if ( 528 arg->result->size() > 1 529 && ! toType->isVoid() 530 && ! dynamic_cast< const ast::ReferenceType * >( toType ) 531 ) { 532 // Argument is a tuple and the target type is neither void nor a reference. Cast each 533 // member of the tuple to its corresponding target type, producing the tuple of those 534 // cast expressions. If there are more components of the tuple than components in the 535 // target type, then excess components do not come out in the result expression (but 536 // UniqueExpr ensures that the side effects will still be produced) 537 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) { 538 // expressions which may contain side effects require a single unique instance of 539 // the expression 540 arg = new ast::UniqueExpr{ arg->location, arg }; 541 } 542 std::vector< ast::ptr< ast::Expr > > components; 543 for ( unsigned i = 0; i < toType->size(); ++i ) { 544 // cast each component 545 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i }; 546 components.emplace_back( 547 restructureCast( idx, toType->getComponent( i ), isGenerated ) ); 548 } 549 return new ast::TupleExpr{ arg->location, std::move( components ) }; 550 } else { 551 // handle normally 552 return new ast::CastExpr{ arg->location, arg, toType, isGenerated }; 553 } 554 } 555 556 /// Gets the name from an untyped member expression (must be NameExpr) 557 const std::string & getMemberName( const ast::UntypedMemberExpr * memberExpr ) { 558 if ( memberExpr->member.as< ast::ConstantExpr >() ) { 559 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " ); 560 } 561 562 return memberExpr->member.strict_as< ast::NameExpr >()->name; 563 } 564 565 /// Actually visits expressions to find their candidate interpretations 566 class Finder final : public ast::WithShortCircuiting { 567 const ResolveContext & context; 568 const ast::SymbolTable & symtab; 569 public: 570 // static size_t traceId; 571 CandidateFinder & selfFinder; 572 CandidateList & candidates; 573 const ast::TypeEnvironment & tenv; 574 ast::ptr< ast::Type > & targetType; 575 576 enum Errors { 577 NotFound, 578 NoMatch, 579 ArgsToFew, 580 ArgsToMany, 581 RetsToFew, 582 RetsToMany, 583 NoReason 584 }; 585 586 struct { 587 Errors code = NotFound; 588 } reason; 589 590 Finder( CandidateFinder & f ) 591 : context( f.context ), symtab( context.symtab ), selfFinder( f ), 592 candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {} 593 594 void previsit( const ast::Node * ) { visit_children = false; } 595 596 /// Convenience to add candidate to list 597 template<typename... Args> 598 void addCandidate( Args &&... args ) { 599 candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } ); 600 reason.code = NoReason; 601 } 602 603 void postvisit( const ast::ApplicationExpr * applicationExpr ) { 604 addCandidate( applicationExpr, tenv ); 605 } 606 607 /// Set up candidate assertions for inference 608 void inferParameters( CandidateRef & newCand, CandidateList & out ); 609 610 /// Completes a function candidate with arguments located 611 void validateFunctionCandidate( 612 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 613 CandidateList & out ); 614 615 /// Builds a list of candidates for a function, storing them in out 616 void makeFunctionCandidates( 617 const CodeLocation & location, 618 const CandidateRef & func, const ast::FunctionType * funcType, 619 const ExplodedArgs_new & args, CandidateList & out ); 620 621 /// Adds implicit struct-conversions to the alternative list 622 void addAnonConversions( const CandidateRef & cand ); 623 624 /// Adds aggregate member interpretations 625 void addAggMembers( 626 const ast::BaseInstType * aggrInst, const ast::Expr * expr, 627 const Candidate & cand, const Cost & addedCost, const std::string & name 628 ); 629 630 /// Adds tuple member interpretations 631 void addTupleMembers( 632 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 633 const Cost & addedCost, const ast::Expr * member 634 ); 635 636 /// true if expression is an lvalue 637 static bool isLvalue( const ast::Expr * x ) { 638 return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() ); 639 } 640 641 void postvisit( const ast::UntypedExpr * untypedExpr ); 642 void postvisit( const ast::VariableExpr * variableExpr ); 643 void postvisit( const ast::ConstantExpr * constantExpr ); 644 void postvisit( const ast::SizeofExpr * sizeofExpr ); 645 void postvisit( const ast::AlignofExpr * alignofExpr ); 646 void postvisit( const ast::AddressExpr * addressExpr ); 647 void postvisit( const ast::LabelAddressExpr * labelExpr ); 648 void postvisit( const ast::CastExpr * castExpr ); 649 void postvisit( const ast::VirtualCastExpr * castExpr ); 650 void postvisit( const ast::KeywordCastExpr * castExpr ); 651 void postvisit( const ast::UntypedMemberExpr * memberExpr ); 652 void postvisit( const ast::MemberExpr * memberExpr ); 653 void postvisit( const ast::NameExpr * nameExpr ); 654 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ); 655 void postvisit( const ast::OffsetofExpr * offsetofExpr ); 656 void postvisit( const ast::OffsetPackExpr * offsetPackExpr ); 657 void postvisit( const ast::LogicalExpr * logicalExpr ); 658 void postvisit( const ast::ConditionalExpr * conditionalExpr ); 659 void postvisit( const ast::CommaExpr * commaExpr ); 660 void postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ); 661 void postvisit( const ast::ConstructorExpr * ctorExpr ); 662 void postvisit( const ast::RangeExpr * rangeExpr ); 663 void postvisit( const ast::UntypedTupleExpr * tupleExpr ); 664 void postvisit( const ast::TupleExpr * tupleExpr ); 665 void postvisit( const ast::TupleIndexExpr * tupleExpr ); 666 void postvisit( const ast::TupleAssignExpr * tupleExpr ); 667 void postvisit( const ast::UniqueExpr * unqExpr ); 668 void postvisit( const ast::StmtExpr * stmtExpr ); 669 void postvisit( const ast::UntypedInitExpr * initExpr ); 670 671 void postvisit( const ast::InitExpr * ) { 672 assertf( false, "CandidateFinder should never see a resolved InitExpr." ); 673 } 674 675 void postvisit( const ast::DeletedExpr * ) { 676 assertf( false, "CandidateFinder should never see a DeletedExpr." ); 677 } 678 679 void postvisit( const ast::GenericExpr * ) { 680 assertf( false, "_Generic is not yet supported." ); 681 } 682 }; 683 684 /// Set up candidate assertions for inference 685 void Finder::inferParameters( CandidateRef & newCand, CandidateList & out ) { 686 // Set need bindings for any unbound assertions 687 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions 688 for ( auto & assn : newCand->need ) { 689 // skip already-matched assertions 690 if ( assn.second.resnSlot != 0 ) continue; 691 // assign slot for expression if needed 692 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; } 693 // fix slot to assertion 694 assn.second.resnSlot = crntResnSlot; 695 } 696 // pair slot to expression 697 if ( crntResnSlot != 0 ) { 698 newCand->expr.get_and_mutate()->inferred.resnSlots().emplace_back( crntResnSlot ); 699 } 700 701 // add to output list; assertion satisfaction will occur later 702 out.emplace_back( newCand ); 703 } 704 705 /// Completes a function candidate with arguments located 706 void Finder::validateFunctionCandidate( 707 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results, 708 CandidateList & out 709 ) { 710 ast::ApplicationExpr * appExpr = 711 new ast::ApplicationExpr{ func->expr->location, func->expr }; 712 // sum cost and accumulate arguments 713 std::deque< const ast::Expr * > args; 714 Cost cost = func->cost; 715 const ArgPack * pack = &result; 716 while ( pack->expr ) { 717 args.emplace_front( pack->expr ); 718 cost += pack->cost; 719 pack = &results[pack->parent]; 720 } 721 std::vector< ast::ptr< ast::Expr > > vargs( args.begin(), args.end() ); 722 appExpr->args = std::move( vargs ); 723 // build and validate new candidate 724 auto newCand = 725 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost ); 726 PRINT( 727 std::cerr << "instantiate function success: " << appExpr << std::endl; 728 std::cerr << "need assertions:" << std::endl; 729 ast::print( std::cerr, result.need, 2 ); 730 ) 731 inferParameters( newCand, out ); 732 } 733 734 /// Builds a list of candidates for a function, storing them in out 735 void Finder::makeFunctionCandidates( 736 const CodeLocation & location, 737 const CandidateRef & func, const ast::FunctionType * funcType, 738 const ExplodedArgs_new & args, CandidateList & out 739 ) { 740 ast::OpenVarSet funcOpen; 741 ast::AssertionSet funcNeed, funcHave; 742 ast::TypeEnvironment funcEnv{ func->env }; 743 makeUnifiableVars( funcType, funcOpen, funcNeed ); 744 // add all type variables as open variables now so that those not used in the 745 // parameter list are still considered open 746 funcEnv.add( funcType->forall ); 747 748 if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) { 749 // attempt to narrow based on expected target type 750 const ast::Type * returnType = funcType->returns.front(); 751 if ( ! unify( 752 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab ) 753 ) { 754 // unification failed, do not pursue this candidate 755 return; 756 } 757 } 758 759 // iteratively build matches, one parameter at a time 760 std::vector< ArgPack > results; 761 results.emplace_back( funcEnv, funcNeed, funcHave, funcOpen ); 762 std::size_t genStart = 0; 763 764 // xxx - how to handle default arg after change to ftype representation? 765 if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) { 766 if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) { 767 // function may have default args only if directly calling by name 768 // must use types on candidate however, due to RenameVars substitution 769 auto nParams = funcType->params.size(); 770 771 for (size_t i=0; i<nParams; ++i) { 772 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>(); 773 if (!instantiateArgument( location, 774 funcType->params[i], obj->init, args, results, genStart, symtab)) return; 775 } 776 goto endMatch; 777 } 778 } 779 for ( const auto & param : funcType->params ) { 780 // Try adding the arguments corresponding to the current parameter to the existing 781 // matches 782 // no default args for indirect calls 783 if ( ! instantiateArgument( location, 784 param, nullptr, args, results, genStart, symtab ) ) return; 785 } 786 787 endMatch: 788 if ( funcType->isVarArgs ) { 789 // append any unused arguments to vararg pack 790 std::size_t genEnd; 791 do { 792 genEnd = results.size(); 793 794 // iterate results 795 for ( std::size_t i = genStart; i < genEnd; ++i ) { 796 unsigned nextArg = results[i].nextArg; 797 798 // use remainder of exploded tuple if present 799 if ( results[i].hasExpl() ) { 800 const ExplodedArg & expl = results[i].getExpl( args ); 801 802 unsigned nextExpl = results[i].nextExpl + 1; 803 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } 804 805 results.emplace_back( 806 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ), 807 copy( results[i].need ), copy( results[i].have ), 808 copy( results[i].open ), nextArg, 0, Cost::zero, nextExpl, 809 results[i].explAlt ); 810 811 continue; 812 } 813 814 // finish result when out of arguments 815 if ( nextArg >= args.size() ) { 816 validateFunctionCandidate( func, results[i], results, out ); 817 818 continue; 819 } 820 821 // add each possible next argument 822 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) { 823 const ExplodedArg & expl = args[nextArg][j]; 824 825 // fresh copies of parent parameters for this iteration 826 ast::TypeEnvironment env = results[i].env; 827 ast::OpenVarSet open = results[i].open; 828 829 env.addActual( expl.env, open ); 830 831 // skip empty tuple arguments by (nearly) cloning parent into next gen 832 if ( expl.exprs.empty() ) { 833 results.emplace_back( 834 results[i], std::move( env ), copy( results[i].need ), 835 copy( results[i].have ), std::move( open ), nextArg + 1, 836 expl.cost ); 837 838 continue; 839 } 840 841 // add new result 842 results.emplace_back( 843 i, expl.exprs.front(), std::move( env ), copy( results[i].need ), 844 copy( results[i].have ), std::move( open ), nextArg + 1, 0, expl.cost, 845 expl.exprs.size() == 1 ? 0 : 1, j ); 846 } 847 } 848 849 genStart = genEnd; 850 } while( genEnd != results.size() ); 851 } else { 852 // filter out the results that don't use all the arguments 853 for ( std::size_t i = genStart; i < results.size(); ++i ) { 854 ArgPack & result = results[i]; 855 if ( ! result.hasExpl() && result.nextArg >= args.size() ) { 856 validateFunctionCandidate( func, result, results, out ); 857 } 858 } 859 } 860 } 861 862 /// Adds implicit struct-conversions to the alternative list 863 void Finder::addAnonConversions( const CandidateRef & cand ) { 864 // adds anonymous member interpretations whenever an aggregate value type is seen. 865 // it's okay for the aggregate expression to have reference type -- cast it to the 866 // base type to treat the aggregate as the referenced value 867 ast::ptr< ast::Expr > aggrExpr( cand->expr ); 868 ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result; 869 cand->env.apply( aggrType ); 870 871 if ( aggrType.as< ast::ReferenceType >() ) { 872 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() }; 873 } 874 875 if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) { 876 addAggMembers( structInst, aggrExpr, *cand, Cost::safe, "" ); 877 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) { 878 addAggMembers( unionInst, aggrExpr, *cand, Cost::safe, "" ); 879 } 880 } 881 882 /// Adds aggregate member interpretations 883 void Finder::addAggMembers( 884 const ast::BaseInstType * aggrInst, const ast::Expr * expr, 885 const Candidate & cand, const Cost & addedCost, const std::string & name 886 ) { 887 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) { 888 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl ); 889 CandidateRef newCand = std::make_shared<Candidate>( 890 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost ); 891 // add anonymous member interpretations whenever an aggregate value type is seen 892 // as a member expression 893 addAnonConversions( newCand ); 894 candidates.emplace_back( std::move( newCand ) ); 895 } 896 } 897 898 /// Adds tuple member interpretations 899 void Finder::addTupleMembers( 900 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand, 901 const Cost & addedCost, const ast::Expr * member 902 ) { 903 if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) { 904 // get the value of the constant expression as an int, must be between 0 and the 905 // length of the tuple to have meaning 906 long long val = constantExpr->intValue(); 907 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) { 908 addCandidate( 909 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val }, 910 addedCost ); 911 } 912 } 913 } 914 915 void Finder::postvisit( const ast::UntypedExpr * untypedExpr ) { 916 std::vector< CandidateFinder > argCandidates = 917 selfFinder.findSubExprs( untypedExpr->args ); 918 919 // take care of possible tuple assignments 920 // if not tuple assignment, handled as normal function call 921 Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates ); 922 923 CandidateFinder funcFinder( context, tenv ); 924 if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) { 925 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name); 926 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) { 927 assertf(!argCandidates.empty(), "special function call without argument"); 928 for (auto & firstArgCand: argCandidates[0]) { 929 ast::ptr<ast::Type> argType = firstArgCand->expr->result; 930 firstArgCand->env.apply(argType); 931 // strip references 932 // xxx - is this correct? 933 while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base; 934 935 // convert 1-tuple to plain type 936 if (auto tuple = argType.as<ast::TupleType>()) { 937 if (tuple->size() == 1) { 938 argType = tuple->types[0]; 939 } 940 } 941 942 // if argType is an unbound type parameter, all special functions need to be searched. 943 if (isUnboundType(argType)) { 944 funcFinder.otypeKeys.clear(); 945 break; 946 } 947 948 if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer); 949 // else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) { 950 // const ast::EnumDecl * enumDecl = enumInst->base; // Here 951 // if ( const ast::Type* enumType = enumDecl->base ) { 952 // // instance of enum (T) is a instance of type (T) 953 // funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type)); 954 // } else { 955 // // instance of an untyped enum is techically int 956 // funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type)); 957 // } 958 // } 959 else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type)); 960 } 961 } 962 } 963 // if candidates are already produced, do not fail 964 // xxx - is it possible that handleTupleAssignment and main finder both produce candidates? 965 // this means there exists ctor/assign functions with a tuple as first parameter. 966 ResolvMode mode = { 967 true, // adjust 968 !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name 969 selfFinder.candidates.empty() // failfast if other options are not found 970 }; 971 funcFinder.find( untypedExpr->func, mode ); 972 // short-circuit if no candidates 973 // if ( funcFinder.candidates.empty() ) return; 974 975 reason.code = NoMatch; 976 977 // find function operators 978 ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; // ??? why not ?{} 979 CandidateFinder opFinder( context, tenv ); 980 // okay if there aren't any function operations 981 opFinder.find( opExpr, ResolvMode::withoutFailFast() ); 982 PRINT( 983 std::cerr << "known function ops:" << std::endl; 984 print( std::cerr, opFinder.candidates, 1 ); 985 ) 986 987 // pre-explode arguments 988 ExplodedArgs_new argExpansions; 989 for ( const CandidateFinder & args : argCandidates ) { 990 argExpansions.emplace_back(); 991 auto & argE = argExpansions.back(); 992 for ( const CandidateRef & arg : args ) { argE.emplace_back( *arg, symtab ); } 993 } 994 995 // Find function matches 996 CandidateList found; 997 SemanticErrorException errors; 998 for ( CandidateRef & func : funcFinder ) { 999 try { 1000 PRINT( 1001 std::cerr << "working on alternative:" << std::endl; 1002 print( std::cerr, *func, 2 ); 1003 ) 1004 1005 // check if the type is a pointer to function 1006 const ast::Type * funcResult = func->expr->result->stripReferences(); 1007 if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) { 1008 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 1009 CandidateRef newFunc{ new Candidate{ *func } }; 1010 newFunc->expr = 1011 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 1012 makeFunctionCandidates( untypedExpr->location, 1013 newFunc, function, argExpansions, found ); 1014 } 1015 } else if ( 1016 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult ) 1017 ) { 1018 if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) { 1019 if ( auto function = clz->bound.as< ast::FunctionType >() ) { 1020 CandidateRef newFunc{ new Candidate{ *func } }; 1021 newFunc->expr = 1022 referenceToRvalueConversion( newFunc->expr, newFunc->cost ); 1023 makeFunctionCandidates( untypedExpr->location, 1024 newFunc, function, argExpansions, found ); 1025 } 1026 } 1027 } 1028 } catch ( SemanticErrorException & e ) { errors.append( e ); } 1029 } 1030 1031 // Find matches on function operators `?()` 1032 if ( ! opFinder.candidates.empty() ) { 1033 // add exploded function alternatives to front of argument list 1034 std::vector< ExplodedArg > funcE; 1035 funcE.reserve( funcFinder.candidates.size() ); 1036 for ( const CandidateRef & func : funcFinder ) { 1037 funcE.emplace_back( *func, symtab ); 1038 } 1039 argExpansions.emplace_front( std::move( funcE ) ); 1040 1041 for ( const CandidateRef & op : opFinder ) { 1042 try { 1043 // check if type is pointer-to-function 1044 const ast::Type * opResult = op->expr->result->stripReferences(); 1045 if ( auto pointer = dynamic_cast< const ast::PointerType * >( opResult ) ) { 1046 if ( auto function = pointer->base.as< ast::FunctionType >() ) { 1047 CandidateRef newOp{ new Candidate{ *op} }; 1048 newOp->expr = 1049 referenceToRvalueConversion( newOp->expr, newOp->cost ); 1050 makeFunctionCandidates( untypedExpr->location, 1051 newOp, function, argExpansions, found ); 1052 } 1053 } 1054 } catch ( SemanticErrorException & e ) { errors.append( e ); } 1055 } 1056 } 1057 1058 // Implement SFINAE; resolution errors are only errors if there aren't any non-error 1059 // candidates 1060 if ( found.empty() && ! errors.isEmpty() ) { throw errors; } 1061 1062 // Compute conversion costs 1063 for ( CandidateRef & withFunc : found ) { 1064 Cost cvtCost = computeApplicationConversionCost( withFunc, symtab ); 1065 1066 PRINT( 1067 auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >(); 1068 auto pointer = appExpr->func->result.strict_as< ast::PointerType >(); 1069 auto function = pointer->base.strict_as< ast::FunctionType >(); 1070 1071 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl; 1072 std::cerr << "parameters are:" << std::endl; 1073 ast::printAll( std::cerr, function->params, 2 ); 1074 std::cerr << "arguments are:" << std::endl; 1075 ast::printAll( std::cerr, appExpr->args, 2 ); 1076 std::cerr << "bindings are:" << std::endl; 1077 ast::print( std::cerr, withFunc->env, 2 ); 1078 std::cerr << "cost is: " << withFunc->cost << std::endl; 1079 std::cerr << "cost of conversion is:" << cvtCost << std::endl; 1080 ) 1081 1082 if ( cvtCost != Cost::infinity ) { 1083 withFunc->cvtCost = cvtCost; 1084 candidates.emplace_back( std::move( withFunc ) ); 1085 } 1086 } 1087 found = std::move( candidates ); 1088 1089 // use a new list so that candidates are not examined by addAnonConversions twice 1090 CandidateList winners = findMinCost( found ); 1091 promoteCvtCost( winners ); 1092 1093 // function may return a struct/union value, in which case we need to add candidates 1094 // for implicit conversions to each of the anonymous members, which must happen after 1095 // `findMinCost`, since anon conversions are never the cheapest 1096 for ( const CandidateRef & c : winners ) { 1097 addAnonConversions( c ); 1098 } 1099 spliceBegin( candidates, winners ); 1100 1101 if ( candidates.empty() && targetType && ! targetType->isVoid() ) { 1102 // If resolution is unsuccessful with a target type, try again without, since it 1103 // will sometimes succeed when it wouldn't with a target type binding. 1104 // For example: 1105 // forall( otype T ) T & ?[]( T *, ptrdiff_t ); 1106 // const char * x = "hello world"; 1107 // unsigned char ch = x[0]; 1108 // Fails with simple return type binding (xxx -- check this!) as follows: 1109 // * T is bound to unsigned char 1110 // * (x: const char *) is unified with unsigned char *, which fails 1111 // xxx -- fix this better 1112 targetType = nullptr; 1113 postvisit( untypedExpr ); 1114 } 1115 } 1116 1117 void Finder::postvisit( const ast::AddressExpr * addressExpr ) { 1118 CandidateFinder finder( context, tenv ); 1119 finder.find( addressExpr->arg ); 1120 1121 if ( finder.candidates.empty() ) return; 1122 1123 reason.code = NoMatch; 1124 1125 for ( CandidateRef & r : finder.candidates ) { 1126 if ( ! isLvalue( r->expr ) ) continue; 1127 addCandidate( *r, new ast::AddressExpr{ addressExpr->location, r->expr } ); 1128 } 1129 } 1130 1131 void Finder::postvisit( const ast::LabelAddressExpr * labelExpr ) { 1132 addCandidate( labelExpr, tenv ); 1133 } 1134 1135 void Finder::postvisit( const ast::CastExpr * castExpr ) { 1136 ast::ptr< ast::Type > toType = castExpr->result; 1137 assert( toType ); 1138 toType = resolveTypeof( toType, context ); 1139 toType = adjustExprType( toType, tenv, symtab ); 1140 1141 CandidateFinder finder( context, tenv, toType ); 1142 finder.find( castExpr->arg, ResolvMode::withAdjustment() ); 1143 1144 if ( !finder.candidates.empty() ) reason.code = NoMatch; 1145 1146 CandidateList matches; 1147 for ( CandidateRef & cand : finder.candidates ) { 1148 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; 1149 ast::OpenVarSet open( cand->open ); 1150 1151 cand->env.extractOpenVars( open ); 1152 1153 // It is possible that a cast can throw away some values in a multiply-valued 1154 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the 1155 // subexpression results that are cast directly. The candidate is invalid if it 1156 // has fewer results than there are types to cast to. 1157 int discardedValues = cand->expr->result->size() - toType->size(); 1158 if ( discardedValues < 0 ) continue; 1159 1160 // unification run for side-effects 1161 unify( toType, cand->expr->result, cand->env, need, have, open, symtab ); 1162 Cost thisCost = 1163 (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast) 1164 ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ) 1165 : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ); 1166 1167 PRINT( 1168 std::cerr << "working on cast with result: " << toType << std::endl; 1169 std::cerr << "and expr type: " << cand->expr->result << std::endl; 1170 std::cerr << "env: " << cand->env << std::endl; 1171 ) 1172 if ( thisCost != Cost::infinity ) { 1173 PRINT( 1174 std::cerr << "has finite cost." << std::endl; 1175 ) 1176 // count one safe conversion for each value that is thrown away 1177 thisCost.incSafe( discardedValues ); 1178 CandidateRef newCand = std::make_shared<Candidate>( 1179 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1180 copy( cand->env ), std::move( open ), std::move( need ), cand->cost, 1181 cand->cost + thisCost ); 1182 inferParameters( newCand, matches ); 1183 } 1184 } 1185 1186 // select first on argument cost, then conversion cost 1187 CandidateList minArgCost = findMinCost( matches ); 1188 promoteCvtCost( minArgCost ); 1189 candidates = findMinCost( minArgCost ); 1190 } 1191 1192 void Finder::postvisit( const ast::VirtualCastExpr * castExpr ) { 1193 assertf( castExpr->result, "Implicit virtual cast targets not yet supported." ); 1194 CandidateFinder finder( context, tenv ); 1195 // don't prune here, all alternatives guaranteed to have same type 1196 finder.find( castExpr->arg, ResolvMode::withoutPrune() ); 1197 for ( CandidateRef & r : finder.candidates ) { 1198 addCandidate( 1199 *r, 1200 new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } ); 1201 } 1202 } 1203 1204 void Finder::postvisit( const ast::KeywordCastExpr * castExpr ) { 1205 const auto & loc = castExpr->location; 1206 assertf( castExpr->result, "Cast target should have been set in Validate." ); 1207 auto ref = castExpr->result.strict_as<ast::ReferenceType>(); 1208 auto inst = ref->base.strict_as<ast::StructInstType>(); 1209 auto target = inst->base.get(); 1210 1211 CandidateFinder finder( context, tenv ); 1212 1213 auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) { 1214 for (auto & cand : found) { 1215 const ast::Type * expr = cand->expr->result.get(); 1216 if (expect_ref) { 1217 auto res = dynamic_cast<const ast::ReferenceType*>(expr); 1218 if (!res) { continue; } 1219 expr = res->base.get(); 1220 } 1221 1222 if (auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) { 1223 auto td = cand->env.lookup(*insttype); 1224 if (!td) { continue; } 1225 expr = td->bound.get(); 1226 } 1227 1228 if (auto base = dynamic_cast<const ast::StructInstType*>(expr)) { 1229 if (base->base == target) { 1230 candidates.push_back( std::move(cand) ); 1231 reason.code = NoReason; 1232 } 1233 } 1234 } 1235 }; 1236 1237 try { 1238 // Attempt 1 : turn (thread&)X into (thread$&)X.__thrd 1239 // Clone is purely for memory management 1240 std::unique_ptr<const ast::Expr> tech1 { new ast::UntypedMemberExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.field), castExpr->arg) }; 1241 1242 // don't prune here, since it's guaranteed all alternatives will have the same type 1243 finder.find( tech1.get(), ResolvMode::withoutPrune() ); 1244 pick_alternatives(finder.candidates, false); 1245 1246 return; 1247 } catch(SemanticErrorException & ) {} 1248 1249 // Fallback : turn (thread&)X into (thread$&)get_thread(X) 1250 std::unique_ptr<const ast::Expr> fallback { ast::UntypedExpr::createDeref(loc, new ast::UntypedExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.getter), { castExpr->arg })) }; 1251 // don't prune here, since it's guaranteed all alternatives will have the same type 1252 finder.find( fallback.get(), ResolvMode::withoutPrune() ); 1253 1254 pick_alternatives(finder.candidates, true); 1255 1256 // Whatever happens here, we have no more fallbacks 1257 } 1258 1259 void Finder::postvisit( const ast::UntypedMemberExpr * memberExpr ) { 1260 CandidateFinder aggFinder( context, tenv ); 1261 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() ); 1262 for ( CandidateRef & agg : aggFinder.candidates ) { 1263 // it's okay for the aggregate expression to have reference type -- cast it to the 1264 // base type to treat the aggregate as the referenced value 1265 Cost addedCost = Cost::zero; 1266 agg->expr = referenceToRvalueConversion( agg->expr, addedCost ); 1267 1268 // find member of the given type 1269 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) { 1270 addAggMembers( 1271 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1272 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) { 1273 addAggMembers( 1274 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) ); 1275 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) { 1276 addTupleMembers( tupleType, agg->expr, *agg, addedCost, memberExpr->member ); 1277 } 1278 } 1279 } 1280 1281 void Finder::postvisit( const ast::MemberExpr * memberExpr ) { 1282 addCandidate( memberExpr, tenv ); 1283 } 1284 1285 void Finder::postvisit( const ast::NameExpr * nameExpr ) { 1286 std::vector< ast::SymbolTable::IdData > declList; 1287 if (!selfFinder.otypeKeys.empty()) { 1288 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name); 1289 assertf(kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS, "special lookup with non-special target: %s", nameExpr->name.c_str()); 1290 1291 for (auto & otypeKey: selfFinder.otypeKeys) { 1292 auto result = symtab.specialLookupId(kind, otypeKey); 1293 declList.insert(declList.end(), std::make_move_iterator(result.begin()), std::make_move_iterator(result.end())); 1294 } 1295 } else { 1296 declList = symtab.lookupId( nameExpr->name ); 1297 } 1298 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; ) 1299 1300 if ( declList.empty() ) return; 1301 1302 reason.code = NoMatch; 1303 1304 for ( auto & data : declList ) { 1305 Cost cost = Cost::zero; 1306 ast::Expr * newExpr = data.combine( nameExpr->location, cost ); 1307 1308 CandidateRef newCand = std::make_shared<Candidate>( 1309 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero, 1310 cost ); 1311 1312 if (newCand->expr->env) { 1313 newCand->env.add(*newCand->expr->env); 1314 auto mutExpr = newCand->expr.get_and_mutate(); 1315 mutExpr->env = nullptr; 1316 newCand->expr = mutExpr; 1317 } 1318 1319 PRINT( 1320 std::cerr << "decl is "; 1321 ast::print( std::cerr, data.id ); 1322 std::cerr << std::endl; 1323 std::cerr << "newExpr is "; 1324 ast::print( std::cerr, newExpr ); 1325 std::cerr << std::endl; 1326 ) 1327 newCand->expr = ast::mutate_field( 1328 newCand->expr.get(), &ast::Expr::result, 1329 renameTyVars( newCand->expr->result ) ); 1330 // add anonymous member interpretations whenever an aggregate value type is seen 1331 // as a name expression 1332 addAnonConversions( newCand ); 1333 candidates.emplace_back( std::move( newCand ) ); 1334 } 1335 } 1336 1337 void Finder::postvisit( const ast::VariableExpr * variableExpr ) { 1338 // not sufficient to just pass `variableExpr` here, type might have changed since 1339 // creation 1340 addCandidate( 1341 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv ); 1342 } 1343 1344 void Finder::postvisit( const ast::ConstantExpr * constantExpr ) { 1345 addCandidate( constantExpr, tenv ); 1346 } 1347 1348 void Finder::postvisit( const ast::SizeofExpr * sizeofExpr ) { 1349 if ( sizeofExpr->type ) { 1350 addCandidate( 1351 new ast::SizeofExpr{ 1352 sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) }, 1353 tenv ); 1354 } else { 1355 // find all candidates for the argument to sizeof 1356 CandidateFinder finder( context, tenv ); 1357 finder.find( sizeofExpr->expr ); 1358 // find the lowest-cost candidate, otherwise ambiguous 1359 CandidateList winners = findMinCost( finder.candidates ); 1360 if ( winners.size() != 1 ) { 1361 SemanticError( 1362 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " ); 1363 } 1364 // return the lowest-cost candidate 1365 CandidateRef & choice = winners.front(); 1366 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1367 choice->cost = Cost::zero; 1368 addCandidate( *choice, new ast::SizeofExpr{ sizeofExpr->location, choice->expr } ); 1369 } 1370 } 1371 1372 void Finder::postvisit( const ast::AlignofExpr * alignofExpr ) { 1373 if ( alignofExpr->type ) { 1374 addCandidate( 1375 new ast::AlignofExpr{ 1376 alignofExpr->location, resolveTypeof( alignofExpr->type, context ) }, 1377 tenv ); 1378 } else { 1379 // find all candidates for the argument to alignof 1380 CandidateFinder finder( context, tenv ); 1381 finder.find( alignofExpr->expr ); 1382 // find the lowest-cost candidate, otherwise ambiguous 1383 CandidateList winners = findMinCost( finder.candidates ); 1384 if ( winners.size() != 1 ) { 1385 SemanticError( 1386 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " ); 1387 } 1388 // return the lowest-cost candidate 1389 CandidateRef & choice = winners.front(); 1390 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost ); 1391 choice->cost = Cost::zero; 1392 addCandidate( 1393 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } ); 1394 } 1395 } 1396 1397 void Finder::postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) { 1398 const ast::BaseInstType * aggInst; 1399 if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ; 1400 else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ; 1401 else return; 1402 1403 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) { 1404 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member ); 1405 addCandidate( 1406 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv ); 1407 } 1408 } 1409 1410 void Finder::postvisit( const ast::OffsetofExpr * offsetofExpr ) { 1411 addCandidate( offsetofExpr, tenv ); 1412 } 1413 1414 void Finder::postvisit( const ast::OffsetPackExpr * offsetPackExpr ) { 1415 addCandidate( offsetPackExpr, tenv ); 1416 } 1417 1418 void Finder::postvisit( const ast::LogicalExpr * logicalExpr ) { 1419 CandidateFinder finder1( context, tenv ); 1420 finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() ); 1421 if ( finder1.candidates.empty() ) return; 1422 1423 CandidateFinder finder2( context, tenv ); 1424 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() ); 1425 if ( finder2.candidates.empty() ) return; 1426 1427 reason.code = NoMatch; 1428 1429 for ( const CandidateRef & r1 : finder1.candidates ) { 1430 for ( const CandidateRef & r2 : finder2.candidates ) { 1431 ast::TypeEnvironment env{ r1->env }; 1432 env.simpleCombine( r2->env ); 1433 ast::OpenVarSet open{ r1->open }; 1434 mergeOpenVars( open, r2->open ); 1435 ast::AssertionSet need; 1436 mergeAssertionSet( need, r1->need ); 1437 mergeAssertionSet( need, r2->need ); 1438 1439 addCandidate( 1440 new ast::LogicalExpr{ 1441 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd }, 1442 std::move( env ), std::move( open ), std::move( need ), r1->cost + r2->cost ); 1443 } 1444 } 1445 } 1446 1447 void Finder::postvisit( const ast::ConditionalExpr * conditionalExpr ) { 1448 // candidates for condition 1449 CandidateFinder finder1( context, tenv ); 1450 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() ); 1451 if ( finder1.candidates.empty() ) return; 1452 1453 // candidates for true result 1454 CandidateFinder finder2( context, tenv ); 1455 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() ); 1456 if ( finder2.candidates.empty() ) return; 1457 1458 // candidates for false result 1459 CandidateFinder finder3( context, tenv ); 1460 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() ); 1461 if ( finder3.candidates.empty() ) return; 1462 1463 reason.code = NoMatch; 1464 1465 for ( const CandidateRef & r1 : finder1.candidates ) { 1466 for ( const CandidateRef & r2 : finder2.candidates ) { 1467 for ( const CandidateRef & r3 : finder3.candidates ) { 1468 ast::TypeEnvironment env{ r1->env }; 1469 env.simpleCombine( r2->env ); 1470 env.simpleCombine( r3->env ); 1471 ast::OpenVarSet open{ r1->open }; 1472 mergeOpenVars( open, r2->open ); 1473 mergeOpenVars( open, r3->open ); 1474 ast::AssertionSet need; 1475 mergeAssertionSet( need, r1->need ); 1476 mergeAssertionSet( need, r2->need ); 1477 mergeAssertionSet( need, r3->need ); 1478 ast::AssertionSet have; 1479 1480 // unify true and false results, then infer parameters to produce new 1481 // candidates 1482 ast::ptr< ast::Type > common; 1483 if ( 1484 unify( 1485 r2->expr->result, r3->expr->result, env, need, have, open, symtab, 1486 common ) 1487 ) { 1488 // generate typed expression 1489 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{ 1490 conditionalExpr->location, r1->expr, r2->expr, r3->expr }; 1491 newExpr->result = common ? common : r2->expr->result; 1492 // convert both options to result type 1493 Cost cost = r1->cost + r2->cost + r3->cost; 1494 newExpr->arg2 = computeExpressionConversionCost( 1495 newExpr->arg2, newExpr->result, symtab, env, cost ); 1496 newExpr->arg3 = computeExpressionConversionCost( 1497 newExpr->arg3, newExpr->result, symtab, env, cost ); 1498 // output candidate 1499 CandidateRef newCand = std::make_shared<Candidate>( 1500 newExpr, std::move( env ), std::move( open ), std::move( need ), cost ); 1501 inferParameters( newCand, candidates ); 1502 } 1503 } 1504 } 1505 } 1506 } 1507 1508 void Finder::postvisit( const ast::CommaExpr * commaExpr ) { 1509 ast::TypeEnvironment env{ tenv }; 1510 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env ); 1511 1512 CandidateFinder finder2( context, env ); 1513 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() ); 1514 1515 for ( const CandidateRef & r2 : finder2.candidates ) { 1516 addCandidate( *r2, new ast::CommaExpr{ commaExpr->location, arg1, r2->expr } ); 1517 } 1518 } 1519 1520 void Finder::postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ) { 1521 addCandidate( ctorExpr, tenv ); 1522 } 1523 1524 void Finder::postvisit( const ast::ConstructorExpr * ctorExpr ) { 1525 CandidateFinder finder( context, tenv ); 1526 finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() ); 1527 for ( CandidateRef & r : finder.candidates ) { 1528 addCandidate( *r, new ast::ConstructorExpr{ ctorExpr->location, r->expr } ); 1529 } 1530 } 1531 1532 void Finder::postvisit( const ast::RangeExpr * rangeExpr ) { 1533 // resolve low and high, accept candidates where low and high types unify 1534 CandidateFinder finder1( context, tenv ); 1535 finder1.find( rangeExpr->low, ResolvMode::withAdjustment() ); 1536 if ( finder1.candidates.empty() ) return; 1537 1538 CandidateFinder finder2( context, tenv ); 1539 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() ); 1540 if ( finder2.candidates.empty() ) return; 1541 1542 reason.code = NoMatch; 1543 1544 for ( const CandidateRef & r1 : finder1.candidates ) { 1545 for ( const CandidateRef & r2 : finder2.candidates ) { 1546 ast::TypeEnvironment env{ r1->env }; 1547 env.simpleCombine( r2->env ); 1548 ast::OpenVarSet open{ r1->open }; 1549 mergeOpenVars( open, r2->open ); 1550 ast::AssertionSet need; 1551 mergeAssertionSet( need, r1->need ); 1552 mergeAssertionSet( need, r2->need ); 1553 ast::AssertionSet have; 1554 1555 ast::ptr< ast::Type > common; 1556 if ( 1557 unify( 1558 r1->expr->result, r2->expr->result, env, need, have, open, symtab, 1559 common ) 1560 ) { 1561 // generate new expression 1562 ast::RangeExpr * newExpr = 1563 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr }; 1564 newExpr->result = common ? common : r1->expr->result; 1565 // add candidate 1566 CandidateRef newCand = std::make_shared<Candidate>( 1567 newExpr, std::move( env ), std::move( open ), std::move( need ), 1568 r1->cost + r2->cost ); 1569 inferParameters( newCand, candidates ); 1570 } 1571 } 1572 } 1573 } 1574 1575 void Finder::postvisit( const ast::UntypedTupleExpr * tupleExpr ) { 1576 std::vector< CandidateFinder > subCandidates = 1577 selfFinder.findSubExprs( tupleExpr->exprs ); 1578 std::vector< CandidateList > possibilities; 1579 combos( subCandidates.begin(), subCandidates.end(), back_inserter( possibilities ) ); 1580 1581 for ( const CandidateList & subs : possibilities ) { 1582 std::vector< ast::ptr< ast::Expr > > exprs; 1583 exprs.reserve( subs.size() ); 1584 for ( const CandidateRef & sub : subs ) { exprs.emplace_back( sub->expr ); } 1585 1586 ast::TypeEnvironment env; 1587 ast::OpenVarSet open; 1588 ast::AssertionSet need; 1589 for ( const CandidateRef & sub : subs ) { 1590 env.simpleCombine( sub->env ); 1591 mergeOpenVars( open, sub->open ); 1592 mergeAssertionSet( need, sub->need ); 1593 } 1594 1595 addCandidate( 1596 new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) }, 1597 std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) ); 1598 } 1599 } 1600 1601 void Finder::postvisit( const ast::TupleExpr * tupleExpr ) { 1602 addCandidate( tupleExpr, tenv ); 1603 } 1604 1605 void Finder::postvisit( const ast::TupleIndexExpr * tupleExpr ) { 1606 addCandidate( tupleExpr, tenv ); 1607 } 1608 1609 void Finder::postvisit( const ast::TupleAssignExpr * tupleExpr ) { 1610 addCandidate( tupleExpr, tenv ); 1611 } 1612 1613 void Finder::postvisit( const ast::UniqueExpr * unqExpr ) { 1614 CandidateFinder finder( context, tenv ); 1615 finder.find( unqExpr->expr, ResolvMode::withAdjustment() ); 1616 for ( CandidateRef & r : finder.candidates ) { 1617 // ensure that the the id is passed on so that the expressions are "linked" 1618 addCandidate( *r, new ast::UniqueExpr{ unqExpr->location, r->expr, unqExpr->id } ); 1619 } 1620 } 1621 1622 void Finder::postvisit( const ast::StmtExpr * stmtExpr ) { 1623 addCandidate( resolveStmtExpr( stmtExpr, context ), tenv ); 1624 } 1625 1626 void Finder::postvisit( const ast::UntypedInitExpr * initExpr ) { 1627 // handle each option like a cast 1628 CandidateList matches; 1629 PRINT( 1630 std::cerr << "untyped init expr: " << initExpr << std::endl; 1631 ) 1632 // O(n^2) checks of d-types with e-types 1633 for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) { 1634 // calculate target type 1635 const ast::Type * toType = resolveTypeof( initAlt.type, context ); 1636 toType = adjustExprType( toType, tenv, symtab ); 1637 // The call to find must occur inside this loop, otherwise polymorphic return 1638 // types are not bound to the initialization type, since return type variables are 1639 // only open for the duration of resolving the UntypedExpr. 1640 CandidateFinder finder( context, tenv, toType ); 1641 finder.find( initExpr->expr, ResolvMode::withAdjustment() ); 1642 for ( CandidateRef & cand : finder.candidates ) { 1643 if (reason.code == NotFound) reason.code = NoMatch; 1644 1645 ast::TypeEnvironment env{ cand->env }; 1646 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; 1647 ast::OpenVarSet open{ cand->open }; 1648 1649 PRINT( 1650 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl; 1651 ) 1652 1653 // It is possible that a cast can throw away some values in a multiply-valued 1654 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 1655 // the subexpression results that are cast directly. The candidate is invalid 1656 // if it has fewer results than there are types to cast to. 1657 int discardedValues = cand->expr->result->size() - toType->size(); 1658 if ( discardedValues < 0 ) continue; 1659 1660 // unification run for side-effects 1661 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab ); 1662 (void) canUnify; 1663 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1664 symtab, env ); 1665 PRINT( 1666 Cost legacyCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(), 1667 symtab, env ); 1668 std::cerr << "Considering initialization:"; 1669 std::cerr << std::endl << " FROM: " << cand->expr->result << std::endl; 1670 std::cerr << std::endl << " TO: " << toType << std::endl; 1671 std::cerr << std::endl << " Unification " << (canUnify ? "succeeded" : "failed"); 1672 std::cerr << std::endl << " Legacy cost " << legacyCost; 1673 std::cerr << std::endl << " New cost " << thisCost; 1674 std::cerr << std::endl; 1675 ) 1676 if ( thisCost != Cost::infinity ) { 1677 // count one safe conversion for each value that is thrown away 1678 thisCost.incSafe( discardedValues ); 1679 CandidateRef newCand = std::make_shared<Candidate>( 1680 new ast::InitExpr{ 1681 initExpr->location, restructureCast( cand->expr, toType ), 1682 initAlt.designation }, 1683 std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost ); 1684 inferParameters( newCand, matches ); 1685 } 1686 } 1687 } 1688 1689 // select first on argument cost, then conversion cost 1690 CandidateList minArgCost = findMinCost( matches ); 1691 promoteCvtCost( minArgCost ); 1692 candidates = findMinCost( minArgCost ); 1693 } 1694 1695 // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder"); 1696 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given 1697 /// return type. Skips ambiguous candidates. 1698 1699 } // anonymous namespace 1700 1701 bool CandidateFinder::pruneCandidates( CandidateList & candidates, CandidateList & out, std::vector<std::string> & errors ) { 1702 struct PruneStruct { 1703 CandidateRef candidate; 1704 bool ambiguous; 1705 1706 PruneStruct() = default; 1707 PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {} 1708 }; 1709 1710 // find lowest-cost candidate for each type 1711 std::unordered_map< std::string, PruneStruct > selected; 1712 // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found 1713 std::sort(candidates.begin(), candidates.end(), [](const CandidateRef & x, const CandidateRef & y){return x->cost < y->cost;}); 1714 for ( CandidateRef & candidate : candidates ) { 1715 std::string mangleName; 1716 { 1717 ast::ptr< ast::Type > newType = candidate->expr->result; 1718 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get()); 1719 candidate->env.apply( newType ); 1720 mangleName = Mangle::mangle( newType ); 1721 } 1722 1723 auto found = selected.find( mangleName ); 1724 if (found != selected.end() && found->second.candidate->cost < candidate->cost) { 1725 PRINT( 1726 std::cerr << "cost " << candidate->cost << " loses to " 1727 << found->second.candidate->cost << std::endl; 1728 ) 1729 continue; 1730 } 1731 1732 // xxx - when do satisfyAssertions produce more than 1 result? 1733 // this should only happen when initial result type contains 1734 // unbound type parameters, then it should never be pruned by 1735 // the previous step, since renameTyVars guarantees the mangled name 1736 // is unique. 1737 CandidateList satisfied; 1738 bool needRecomputeKey = false; 1739 if (candidate->need.empty()) { 1740 satisfied.emplace_back(candidate); 1741 } 1742 else { 1743 satisfyAssertions(candidate, context.symtab, satisfied, errors); 1744 needRecomputeKey = true; 1745 } 1746 1747 for (auto & newCand : satisfied) { 1748 // recomputes type key, if satisfyAssertions changed it 1749 if (needRecomputeKey) 1750 { 1751 ast::ptr< ast::Type > newType = newCand->expr->result; 1752 assertf(newCand->expr->result, "Result of expression %p for candidate is null", newCand->expr.get()); 1753 newCand->env.apply( newType ); 1754 mangleName = Mangle::mangle( newType ); 1755 } 1756 auto found = selected.find( mangleName ); 1757 if ( found != selected.end() ) { 1758 if ( newCand->cost < found->second.candidate->cost ) { 1759 PRINT( 1760 std::cerr << "cost " << newCand->cost << " beats " 1761 << found->second.candidate->cost << std::endl; 1762 ) 1763 1764 found->second = PruneStruct{ newCand }; 1765 } else if ( newCand->cost == found->second.candidate->cost ) { 1766 // if one of the candidates contains a deleted identifier, can pick the other, 1767 // since deleted expressions should not be ambiguous if there is another option 1768 // that is at least as good 1769 if ( findDeletedExpr( newCand->expr ) ) { 1770 // do nothing 1771 PRINT( std::cerr << "candidate is deleted" << std::endl; ) 1772 } else if ( findDeletedExpr( found->second.candidate->expr ) ) { 1773 PRINT( std::cerr << "current is deleted" << std::endl; ) 1774 found->second = PruneStruct{ newCand }; 1775 } else { 1776 PRINT( std::cerr << "marking ambiguous" << std::endl; ) 1777 found->second.ambiguous = true; 1778 } 1779 } else { 1780 // xxx - can satisfyAssertions increase the cost? 1781 PRINT( 1782 std::cerr << "cost " << newCand->cost << " loses to " 1783 << found->second.candidate->cost << std::endl; 1784 ) 1785 } 1786 } else { 1787 selected.emplace_hint( found, mangleName, newCand ); 1788 } 1789 } 1790 } 1791 1792 // report unambiguous min-cost candidates 1793 // CandidateList out; 1794 for ( auto & target : selected ) { 1795 if ( target.second.ambiguous ) continue; 1796 1797 CandidateRef cand = target.second.candidate; 1798 1799 ast::ptr< ast::Type > newResult = cand->expr->result; 1800 cand->env.applyFree( newResult ); 1801 cand->expr = ast::mutate_field( 1802 cand->expr.get(), &ast::Expr::result, std::move( newResult ) ); 1803 1804 out.emplace_back( cand ); 1805 } 1806 // if everything is lost in satisfyAssertions, report the error 1807 return !selected.empty(); 1808 } 1809 1810 void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) { 1811 // Find alternatives for expression 1812 ast::Pass<Finder> finder{ *this }; 1813 expr->accept( finder ); 1814 1815 if ( mode.failFast && candidates.empty() ) { 1816 switch(finder.core.reason.code) { 1817 case Finder::NotFound: 1818 { SemanticError( expr, "No alternatives for expression " ); break; } 1819 case Finder::NoMatch: 1820 { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; } 1821 case Finder::ArgsToFew: 1822 case Finder::ArgsToMany: 1823 case Finder::RetsToFew: 1824 case Finder::RetsToMany: 1825 case Finder::NoReason: 1826 default: 1827 { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); } 1828 } 1829 } 1830 1831 /* 1832 if ( mode.satisfyAssns || mode.prune ) { 1833 // trim candidates to just those where the assertions are satisfiable 1834 // - necessary pre-requisite to pruning 1835 CandidateList satisfied; 1836 std::vector< std::string > errors; 1837 for ( CandidateRef & candidate : candidates ) { 1838 satisfyAssertions( candidate, localSyms, satisfied, errors ); 1839 } 1840 1841 // fail early if none such 1842 if ( mode.failFast && satisfied.empty() ) { 1843 std::ostringstream stream; 1844 stream << "No alternatives with satisfiable assertions for " << expr << "\n"; 1845 for ( const auto& err : errors ) { 1846 stream << err; 1847 } 1848 SemanticError( expr->location, stream.str() ); 1849 } 1850 1851 // reset candidates 1852 candidates = move( satisfied ); 1853 } 1854 */ 1855 1856 if ( mode.prune ) { 1857 // trim candidates to single best one 1858 PRINT( 1859 std::cerr << "alternatives before prune:" << std::endl; 1860 print( std::cerr, candidates ); 1861 ) 1862 1863 CandidateList pruned; 1864 std::vector<std::string> errors; 1865 bool found = pruneCandidates( candidates, pruned, errors ); 1866 1867 if ( mode.failFast && pruned.empty() ) { 1868 std::ostringstream stream; 1869 if (found) { 1870 CandidateList winners = findMinCost( candidates ); 1871 stream << "Cannot choose between " << winners.size() << " alternatives for " 1872 "expression\n"; 1873 ast::print( stream, expr ); 1874 stream << " Alternatives are:\n"; 1875 print( stream, winners, 1 ); 1876 SemanticError( expr->location, stream.str() ); 1877 } 1878 else { 1879 stream << "No alternatives with satisfiable assertions for " << expr << "\n"; 1880 for ( const auto& err : errors ) { 1881 stream << err; 1882 } 1883 SemanticError( expr->location, stream.str() ); 1884 } 1885 } 1886 1887 auto oldsize = candidates.size(); 1888 candidates = std::move( pruned ); 1889 1890 PRINT( 1891 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl; 1892 ) 1893 PRINT( 1894 std::cerr << "there are " << candidates.size() << " alternatives after elimination" 1895 << std::endl; 1896 ) 1897 } 1898 1899 // adjust types after pruning so that types substituted by pruneAlternatives are correctly 1900 // adjusted 1901 if ( mode.adjust ) { 1902 for ( CandidateRef & r : candidates ) { 1903 r->expr = ast::mutate_field( 1904 r->expr.get(), &ast::Expr::result, 1905 adjustExprType( r->expr->result, r->env, context.symtab ) ); 1906 } 1907 } 1908 1909 // Central location to handle gcc extension keyword, etc. for all expressions 1910 for ( CandidateRef & r : candidates ) { 1911 if ( r->expr->extension != expr->extension ) { 1912 r->expr.get_and_mutate()->extension = expr->extension; 1913 } 1914 } 1915 } 1916 1917 std::vector< CandidateFinder > CandidateFinder::findSubExprs( 1918 const std::vector< ast::ptr< ast::Expr > > & xs 1919 ) { 1920 std::vector< CandidateFinder > out; 1921 1922 for ( const auto & x : xs ) { 1923 out.emplace_back( context, env ); 1924 out.back().find( x, ResolvMode::withAdjustment() ); 1925 1926 PRINT( 1927 std::cerr << "findSubExprs" << std::endl; 1928 print( std::cerr, out.back().candidates ); 1929 ) 1930 } 1931 1932 return out; 1933 } 1934 57 1935 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) { 58 1936 if ( expr->result.as< ast::ReferenceType >() ) { … … 64 1942 return expr; 65 1943 } 66 67 /// Unique identifier for matching expression resolutions to their requesting expression68 UniqueId globalResnSlot = 0;69 1944 70 1945 Cost computeConversionCost( … … 93 1968 } 94 1969 95 namespace {96 /// First index is which argument, second is which alternative, third is which exploded element97 using ExplodedArgs_new = std::deque< std::vector< ExplodedArg > >;98 99 /// Returns a list of alternatives with the minimum cost in the given list100 CandidateList findMinCost( const CandidateList & candidates ) {101 CandidateList out;102 Cost minCost = Cost::infinity;103 for ( const CandidateRef & r : candidates ) {104 if ( r->cost < minCost ) {105 minCost = r->cost;106 out.clear();107 out.emplace_back( r );108 } else if ( r->cost == minCost ) {109 out.emplace_back( r );110 }111 }112 return out;113 }114 115 /// Computes conversion cost for a given expression to a given type116 const ast::Expr * computeExpressionConversionCost(117 const ast::Expr * arg, const ast::Type * paramType, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, Cost & outCost118 ) {119 Cost convCost = computeConversionCost(120 arg->result, paramType, arg->get_lvalue(), symtab, env );121 outCost += convCost;122 123 // If there is a non-zero conversion cost, ignoring poly cost, then the expression requires124 // conversion. Ignore poly cost for now, since this requires resolution of the cast to125 // infer parameters and this does not currently work for the reason stated below126 Cost tmpCost = convCost;127 tmpCost.incPoly( -tmpCost.get_polyCost() );128 if ( tmpCost != Cost::zero ) {129 ast::ptr< ast::Type > newType = paramType;130 env.apply( newType );131 return new ast::CastExpr{ arg, newType };132 133 // xxx - *should* be able to resolve this cast, but at the moment pointers are not134 // castable to zero_t, but are implicitly convertible. This is clearly inconsistent,135 // once this is fixed it should be possible to resolve the cast.136 // xxx - this isn't working, it appears because type1 (parameter) is seen as widenable,137 // but it shouldn't be because this makes the conversion from DT* to DT* since138 // commontype(zero_t, DT*) is DT*, rather than nothing139 140 // CandidateFinder finder{ symtab, env };141 // finder.find( arg, ResolvMode::withAdjustment() );142 // assertf( finder.candidates.size() > 0,143 // "Somehow castable expression failed to find alternatives." );144 // assertf( finder.candidates.size() == 1,145 // "Somehow got multiple alternatives for known cast expression." );146 // return finder.candidates.front()->expr;147 }148 149 return arg;150 }151 152 /// Computes conversion cost for a given candidate153 Cost computeApplicationConversionCost(154 CandidateRef cand, const ast::SymbolTable & symtab155 ) {156 auto appExpr = cand->expr.strict_as< ast::ApplicationExpr >();157 auto pointer = appExpr->func->result.strict_as< ast::PointerType >();158 auto function = pointer->base.strict_as< ast::FunctionType >();159 160 Cost convCost = Cost::zero;161 const auto & params = function->params;162 auto param = params.begin();163 auto & args = appExpr->args;164 165 for ( unsigned i = 0; i < args.size(); ++i ) {166 const ast::Type * argType = args[i]->result;167 PRINT(168 std::cerr << "arg expression:" << std::endl;169 ast::print( std::cerr, args[i], 2 );170 std::cerr << "--- results are" << std::endl;171 ast::print( std::cerr, argType, 2 );172 )173 174 if ( param == params.end() ) {175 if ( function->isVarArgs ) {176 convCost.incUnsafe();177 PRINT( std::cerr << "end of params with varargs function: inc unsafe: "178 << convCost << std::endl; ; )179 // convert reference-typed expressions into value-typed expressions180 cand->expr = ast::mutate_field_index(181 appExpr, &ast::ApplicationExpr::args, i,182 referenceToRvalueConversion( args[i], convCost ) );183 continue;184 } else return Cost::infinity;185 }186 187 if ( auto def = args[i].as< ast::DefaultArgExpr >() ) {188 // Default arguments should be free - don't include conversion cost.189 // Unwrap them here because they are not relevant to the rest of the system190 cand->expr = ast::mutate_field_index(191 appExpr, &ast::ApplicationExpr::args, i, def->expr );192 ++param;193 continue;194 }195 196 // mark conversion cost and also specialization cost of param type197 // const ast::Type * paramType = (*param)->get_type();198 cand->expr = ast::mutate_field_index(199 appExpr, &ast::ApplicationExpr::args, i,200 computeExpressionConversionCost(201 args[i], *param, symtab, cand->env, convCost ) );202 convCost.decSpec( specCost( *param ) );203 ++param; // can't be in for-loop update because of the continue204 }205 206 if ( param != params.end() ) return Cost::infinity;207 208 // specialization cost of return types can't be accounted for directly, it disables209 // otherwise-identical calls, like this example based on auto-newline in the I/O lib:210 //211 // forall(otype OS) {212 // void ?|?(OS&, int); // with newline213 // OS& ?|?(OS&, int); // no newline, always chosen due to more specialization214 // }215 216 // mark type variable and specialization cost of forall clause217 convCost.incVar( function->forall.size() );218 convCost.decSpec( function->assertions.size() );219 220 return convCost;221 }222 223 void makeUnifiableVars(224 const ast::FunctionType * type, ast::OpenVarSet & unifiableVars,225 ast::AssertionSet & need226 ) {227 for ( auto & tyvar : type->forall ) {228 unifiableVars[ *tyvar ] = ast::TypeData{ tyvar->base };229 }230 for ( auto & assn : type->assertions ) {231 need[ assn ].isUsed = true;232 }233 }234 235 /// Gets a default value from an initializer, nullptr if not present236 const ast::ConstantExpr * getDefaultValue( const ast::Init * init ) {237 if ( auto si = dynamic_cast< const ast::SingleInit * >( init ) ) {238 if ( auto ce = si->value.as< ast::CastExpr >() ) {239 return ce->arg.as< ast::ConstantExpr >();240 } else {241 return si->value.as< ast::ConstantExpr >();242 }243 }244 return nullptr;245 }246 247 /// State to iteratively build a match of parameter expressions to arguments248 struct ArgPack {249 std::size_t parent; ///< Index of parent pack250 ast::ptr< ast::Expr > expr; ///< The argument stored here251 Cost cost; ///< The cost of this argument252 ast::TypeEnvironment env; ///< Environment for this pack253 ast::AssertionSet need; ///< Assertions outstanding for this pack254 ast::AssertionSet have; ///< Assertions found for this pack255 ast::OpenVarSet open; ///< Open variables for this pack256 unsigned nextArg; ///< Index of next argument in arguments list257 unsigned tupleStart; ///< Number of tuples that start at this index258 unsigned nextExpl; ///< Index of next exploded element259 unsigned explAlt; ///< Index of alternative for nextExpl > 0260 261 ArgPack()262 : parent( 0 ), expr(), cost( Cost::zero ), env(), need(), have(), open(), nextArg( 0 ),263 tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}264 265 ArgPack(266 const ast::TypeEnvironment & env, const ast::AssertionSet & need,267 const ast::AssertionSet & have, const ast::OpenVarSet & open )268 : parent( 0 ), expr(), cost( Cost::zero ), env( env ), need( need ), have( have ),269 open( open ), nextArg( 0 ), tupleStart( 0 ), nextExpl( 0 ), explAlt( 0 ) {}270 271 ArgPack(272 std::size_t parent, const ast::Expr * expr, ast::TypeEnvironment && env,273 ast::AssertionSet && need, ast::AssertionSet && have, ast::OpenVarSet && open,274 unsigned nextArg, unsigned tupleStart = 0, Cost cost = Cost::zero,275 unsigned nextExpl = 0, unsigned explAlt = 0 )276 : parent(parent), expr( expr ), cost( cost ), env( std::move( env ) ), need( std::move( need ) ),277 have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ), tupleStart( tupleStart ),278 nextExpl( nextExpl ), explAlt( explAlt ) {}279 280 ArgPack(281 const ArgPack & o, ast::TypeEnvironment && env, ast::AssertionSet && need,282 ast::AssertionSet && have, ast::OpenVarSet && open, unsigned nextArg, Cost added )283 : parent( o.parent ), expr( o.expr ), cost( o.cost + added ), env( std::move( env ) ),284 need( std::move( need ) ), have( std::move( have ) ), open( std::move( open ) ), nextArg( nextArg ),285 tupleStart( o.tupleStart ), nextExpl( 0 ), explAlt( 0 ) {}286 287 /// true if this pack is in the middle of an exploded argument288 bool hasExpl() const { return nextExpl > 0; }289 290 /// Gets the list of exploded candidates for this pack291 const ExplodedArg & getExpl( const ExplodedArgs_new & args ) const {292 return args[ nextArg-1 ][ explAlt ];293 }294 295 /// Ends a tuple expression, consolidating the appropriate args296 void endTuple( const std::vector< ArgPack > & packs ) {297 // add all expressions in tuple to list, summing cost298 std::deque< const ast::Expr * > exprs;299 const ArgPack * pack = this;300 if ( expr ) { exprs.emplace_front( expr ); }301 while ( pack->tupleStart == 0 ) {302 pack = &packs[pack->parent];303 exprs.emplace_front( pack->expr );304 cost += pack->cost;305 }306 // reset pack to appropriate tuple307 std::vector< ast::ptr< ast::Expr > > exprv( exprs.begin(), exprs.end() );308 expr = new ast::TupleExpr{ expr->location, std::move( exprv ) };309 tupleStart = pack->tupleStart - 1;310 parent = pack->parent;311 }312 };313 314 /// Instantiates an argument to match a parameter, returns false if no matching results left315 bool instantiateArgument(316 const ast::Type * paramType, const ast::Init * init, const ExplodedArgs_new & args,317 std::vector< ArgPack > & results, std::size_t & genStart, const ast::SymbolTable & symtab,318 unsigned nTuples = 0319 ) {320 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( paramType ) ) {321 // paramType is a TupleType -- group args into a TupleExpr322 ++nTuples;323 for ( const ast::Type * type : *tupleType ) {324 // xxx - dropping initializer changes behaviour from previous, but seems correct325 // ^^^ need to handle the case where a tuple has a default argument326 if ( ! instantiateArgument(327 type, nullptr, args, results, genStart, symtab, nTuples ) ) return false;328 nTuples = 0;329 }330 // re-constitute tuples for final generation331 for ( auto i = genStart; i < results.size(); ++i ) {332 results[i].endTuple( results );333 }334 return true;335 } else if ( const ast::TypeInstType * ttype = Tuples::isTtype( paramType ) ) {336 // paramType is a ttype, consumes all remaining arguments337 338 // completed tuples; will be spliced to end of results to finish339 std::vector< ArgPack > finalResults{};340 341 // iterate until all results completed342 std::size_t genEnd;343 ++nTuples;344 do {345 genEnd = results.size();346 347 // add another argument to results348 for ( std::size_t i = genStart; i < genEnd; ++i ) {349 unsigned nextArg = results[i].nextArg;350 351 // use next element of exploded tuple if present352 if ( results[i].hasExpl() ) {353 const ExplodedArg & expl = results[i].getExpl( args );354 355 unsigned nextExpl = results[i].nextExpl + 1;356 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }357 358 results.emplace_back(359 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),360 copy( results[i].need ), copy( results[i].have ),361 copy( results[i].open ), nextArg, nTuples, Cost::zero, nextExpl,362 results[i].explAlt );363 364 continue;365 }366 367 // finish result when out of arguments368 if ( nextArg >= args.size() ) {369 ArgPack newResult{370 results[i].env, results[i].need, results[i].have, results[i].open };371 newResult.nextArg = nextArg;372 const ast::Type * argType = nullptr;373 374 if ( nTuples > 0 || ! results[i].expr ) {375 // first iteration or no expression to clone,376 // push empty tuple expression377 newResult.parent = i;378 newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };379 argType = newResult.expr->result;380 } else {381 // clone result to collect tuple382 newResult.parent = results[i].parent;383 newResult.cost = results[i].cost;384 newResult.tupleStart = results[i].tupleStart;385 newResult.expr = results[i].expr;386 argType = newResult.expr->result;387 388 if ( results[i].tupleStart > 0 && Tuples::isTtype( argType ) ) {389 // the case where a ttype value is passed directly is special,390 // e.g. for argument forwarding purposes391 // xxx - what if passing multiple arguments, last of which is392 // ttype?393 // xxx - what would happen if unify was changed so that unifying394 // tuple395 // types flattened both before unifying lists? then pass in396 // TupleType (ttype) below.397 --newResult.tupleStart;398 } else {399 // collapse leftover arguments into tuple400 newResult.endTuple( results );401 argType = newResult.expr->result;402 }403 }404 405 // check unification for ttype before adding to final406 if (407 unify(408 ttype, argType, newResult.env, newResult.need, newResult.have,409 newResult.open, symtab )410 ) {411 finalResults.emplace_back( std::move( newResult ) );412 }413 414 continue;415 }416 417 // add each possible next argument418 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {419 const ExplodedArg & expl = args[nextArg][j];420 421 // fresh copies of parent parameters for this iteration422 ast::TypeEnvironment env = results[i].env;423 ast::OpenVarSet open = results[i].open;424 425 env.addActual( expl.env, open );426 427 // skip empty tuple arguments by (nearly) cloning parent into next gen428 if ( expl.exprs.empty() ) {429 results.emplace_back(430 results[i], std::move( env ), copy( results[i].need ),431 copy( results[i].have ), std::move( open ), nextArg + 1, expl.cost );432 433 continue;434 }435 436 // add new result437 results.emplace_back(438 i, expl.exprs.front(), std::move( env ), copy( results[i].need ),439 copy( results[i].have ), std::move( open ), nextArg + 1, nTuples,440 expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );441 }442 }443 444 // reset for next round445 genStart = genEnd;446 nTuples = 0;447 } while ( genEnd != results.size() );448 449 // splice final results onto results450 for ( std::size_t i = 0; i < finalResults.size(); ++i ) {451 results.emplace_back( std::move( finalResults[i] ) );452 }453 return ! finalResults.empty();454 }455 456 // iterate each current subresult457 std::size_t genEnd = results.size();458 for ( std::size_t i = genStart; i < genEnd; ++i ) {459 unsigned nextArg = results[i].nextArg;460 461 // use remainder of exploded tuple if present462 if ( results[i].hasExpl() ) {463 const ExplodedArg & expl = results[i].getExpl( args );464 const ast::Expr * expr = expl.exprs[ results[i].nextExpl ];465 466 ast::TypeEnvironment env = results[i].env;467 ast::AssertionSet need = results[i].need, have = results[i].have;468 ast::OpenVarSet open = results[i].open;469 470 const ast::Type * argType = expr->result;471 472 PRINT(473 std::cerr << "param type is ";474 ast::print( std::cerr, paramType );475 std::cerr << std::endl << "arg type is ";476 ast::print( std::cerr, argType );477 std::cerr << std::endl;478 )479 480 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {481 unsigned nextExpl = results[i].nextExpl + 1;482 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }483 484 results.emplace_back(485 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ), nextArg,486 nTuples, Cost::zero, nextExpl, results[i].explAlt );487 }488 489 continue;490 }491 492 // use default initializers if out of arguments493 if ( nextArg >= args.size() ) {494 if ( const ast::ConstantExpr * cnst = getDefaultValue( init ) ) {495 ast::TypeEnvironment env = results[i].env;496 ast::AssertionSet need = results[i].need, have = results[i].have;497 ast::OpenVarSet open = results[i].open;498 499 if ( unify( paramType, cnst->result, env, need, have, open, symtab ) ) {500 results.emplace_back(501 i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ),502 std::move( need ), std::move( have ), std::move( open ), nextArg, nTuples );503 }504 }505 506 continue;507 }508 509 // Check each possible next argument510 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {511 const ExplodedArg & expl = args[nextArg][j];512 513 // fresh copies of parent parameters for this iteration514 ast::TypeEnvironment env = results[i].env;515 ast::AssertionSet need = results[i].need, have = results[i].have;516 ast::OpenVarSet open = results[i].open;517 518 env.addActual( expl.env, open );519 520 // skip empty tuple arguments by (nearly) cloning parent into next gen521 if ( expl.exprs.empty() ) {522 results.emplace_back(523 results[i], std::move( env ), std::move( need ), std::move( have ), std::move( open ),524 nextArg + 1, expl.cost );525 526 continue;527 }528 529 // consider only first exploded arg530 const ast::Expr * expr = expl.exprs.front();531 const ast::Type * argType = expr->result;532 533 PRINT(534 std::cerr << "param type is ";535 ast::print( std::cerr, paramType );536 std::cerr << std::endl << "arg type is ";537 ast::print( std::cerr, argType );538 std::cerr << std::endl;539 )540 541 // attempt to unify types542 if ( unify( paramType, argType, env, need, have, open, symtab ) ) {543 // add new result544 results.emplace_back(545 i, expr, std::move( env ), std::move( need ), std::move( have ), std::move( open ),546 nextArg + 1, nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );547 }548 }549 }550 551 // reset for next parameter552 genStart = genEnd;553 554 return genEnd != results.size(); // were any new results added?555 }556 557 /// Generate a cast expression from `arg` to `toType`558 const ast::Expr * restructureCast(559 ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast560 ) {561 if (562 arg->result->size() > 1563 && ! toType->isVoid()564 && ! dynamic_cast< const ast::ReferenceType * >( toType )565 ) {566 // Argument is a tuple and the target type is neither void nor a reference. Cast each567 // member of the tuple to its corresponding target type, producing the tuple of those568 // cast expressions. If there are more components of the tuple than components in the569 // target type, then excess components do not come out in the result expression (but570 // UniqueExpr ensures that the side effects will still be produced)571 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {572 // expressions which may contain side effects require a single unique instance of573 // the expression574 arg = new ast::UniqueExpr{ arg->location, arg };575 }576 std::vector< ast::ptr< ast::Expr > > components;577 for ( unsigned i = 0; i < toType->size(); ++i ) {578 // cast each component579 ast::ptr< ast::Expr > idx = new ast::TupleIndexExpr{ arg->location, arg, i };580 components.emplace_back(581 restructureCast( idx, toType->getComponent( i ), isGenerated ) );582 }583 return new ast::TupleExpr{ arg->location, std::move( components ) };584 } else {585 // handle normally586 return new ast::CastExpr{ arg->location, arg, toType, isGenerated };587 }588 }589 590 /// Gets the name from an untyped member expression (must be NameExpr)591 const std::string & getMemberName( const ast::UntypedMemberExpr * memberExpr ) {592 if ( memberExpr->member.as< ast::ConstantExpr >() ) {593 SemanticError( memberExpr, "Indexed access to struct fields unsupported: " );594 }595 596 return memberExpr->member.strict_as< ast::NameExpr >()->name;597 }598 599 /// Actually visits expressions to find their candidate interpretations600 class Finder final : public ast::WithShortCircuiting {601 const ResolveContext & context;602 const ast::SymbolTable & symtab;603 public:604 // static size_t traceId;605 CandidateFinder & selfFinder;606 CandidateList & candidates;607 const ast::TypeEnvironment & tenv;608 ast::ptr< ast::Type > & targetType;609 610 enum Errors {611 NotFound,612 NoMatch,613 ArgsToFew,614 ArgsToMany,615 RetsToFew,616 RetsToMany,617 NoReason618 };619 620 struct {621 Errors code = NotFound;622 } reason;623 624 Finder( CandidateFinder & f )625 : context( f.context ), symtab( context.symtab ), selfFinder( f ),626 candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {}627 628 void previsit( const ast::Node * ) { visit_children = false; }629 630 /// Convenience to add candidate to list631 template<typename... Args>632 void addCandidate( Args &&... args ) {633 candidates.emplace_back( new Candidate{ std::forward<Args>( args )... } );634 reason.code = NoReason;635 }636 637 void postvisit( const ast::ApplicationExpr * applicationExpr ) {638 addCandidate( applicationExpr, tenv );639 }640 641 /// Set up candidate assertions for inference642 void inferParameters( CandidateRef & newCand, CandidateList & out ) {643 // Set need bindings for any unbound assertions644 UniqueId crntResnSlot = 0; // matching ID for this expression's assertions645 for ( auto & assn : newCand->need ) {646 // skip already-matched assertions647 if ( assn.second.resnSlot != 0 ) continue;648 // assign slot for expression if needed649 if ( crntResnSlot == 0 ) { crntResnSlot = ++globalResnSlot; }650 // fix slot to assertion651 assn.second.resnSlot = crntResnSlot;652 }653 // pair slot to expression654 if ( crntResnSlot != 0 ) {655 newCand->expr.get_and_mutate()->inferred.resnSlots().emplace_back( crntResnSlot );656 }657 658 // add to output list; assertion satisfaction will occur later659 out.emplace_back( newCand );660 }661 662 /// Completes a function candidate with arguments located663 void validateFunctionCandidate(664 const CandidateRef & func, ArgPack & result, const std::vector< ArgPack > & results,665 CandidateList & out666 ) {667 ast::ApplicationExpr * appExpr =668 new ast::ApplicationExpr{ func->expr->location, func->expr };669 // sum cost and accumulate arguments670 std::deque< const ast::Expr * > args;671 Cost cost = func->cost;672 const ArgPack * pack = &result;673 while ( pack->expr ) {674 args.emplace_front( pack->expr );675 cost += pack->cost;676 pack = &results[pack->parent];677 }678 std::vector< ast::ptr< ast::Expr > > vargs( args.begin(), args.end() );679 appExpr->args = std::move( vargs );680 // build and validate new candidate681 auto newCand =682 std::make_shared<Candidate>( appExpr, result.env, result.open, result.need, cost );683 PRINT(684 std::cerr << "instantiate function success: " << appExpr << std::endl;685 std::cerr << "need assertions:" << std::endl;686 ast::print( std::cerr, result.need, 2 );687 )688 inferParameters( newCand, out );689 }690 691 /// Builds a list of candidates for a function, storing them in out692 void makeFunctionCandidates(693 const CandidateRef & func, const ast::FunctionType * funcType,694 const ExplodedArgs_new & args, CandidateList & out695 ) {696 ast::OpenVarSet funcOpen;697 ast::AssertionSet funcNeed, funcHave;698 ast::TypeEnvironment funcEnv{ func->env };699 makeUnifiableVars( funcType, funcOpen, funcNeed );700 // add all type variables as open variables now so that those not used in the701 // parameter list are still considered open702 funcEnv.add( funcType->forall );703 704 if ( targetType && ! targetType->isVoid() && ! funcType->returns.empty() ) {705 // attempt to narrow based on expected target type706 const ast::Type * returnType = funcType->returns.front();707 if ( ! unify(708 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen, symtab )709 ) {710 // unification failed, do not pursue this candidate711 return;712 }713 }714 715 // iteratively build matches, one parameter at a time716 std::vector< ArgPack > results;717 results.emplace_back( funcEnv, funcNeed, funcHave, funcOpen );718 std::size_t genStart = 0;719 720 // xxx - how to handle default arg after change to ftype representation?721 if (const ast::VariableExpr * varExpr = func->expr.as<ast::VariableExpr>()) {722 if (const ast::FunctionDecl * funcDecl = varExpr->var.as<ast::FunctionDecl>()) {723 // function may have default args only if directly calling by name724 // must use types on candidate however, due to RenameVars substitution725 auto nParams = funcType->params.size();726 727 for (size_t i=0; i<nParams; ++i) {728 auto obj = funcDecl->params[i].strict_as<ast::ObjectDecl>();729 if (!instantiateArgument(730 funcType->params[i], obj->init, args, results, genStart, symtab)) return;731 }732 goto endMatch;733 }734 }735 for ( const auto & param : funcType->params ) {736 // Try adding the arguments corresponding to the current parameter to the existing737 // matches738 // no default args for indirect calls739 if ( ! instantiateArgument(740 param, nullptr, args, results, genStart, symtab ) ) return;741 }742 743 endMatch:744 if ( funcType->isVarArgs ) {745 // append any unused arguments to vararg pack746 std::size_t genEnd;747 do {748 genEnd = results.size();749 750 // iterate results751 for ( std::size_t i = genStart; i < genEnd; ++i ) {752 unsigned nextArg = results[i].nextArg;753 754 // use remainder of exploded tuple if present755 if ( results[i].hasExpl() ) {756 const ExplodedArg & expl = results[i].getExpl( args );757 758 unsigned nextExpl = results[i].nextExpl + 1;759 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; }760 761 results.emplace_back(762 i, expl.exprs[ results[i].nextExpl ], copy( results[i].env ),763 copy( results[i].need ), copy( results[i].have ),764 copy( results[i].open ), nextArg, 0, Cost::zero, nextExpl,765 results[i].explAlt );766 767 continue;768 }769 770 // finish result when out of arguments771 if ( nextArg >= args.size() ) {772 validateFunctionCandidate( func, results[i], results, out );773 774 continue;775 }776 777 // add each possible next argument778 for ( std::size_t j = 0; j < args[nextArg].size(); ++j ) {779 const ExplodedArg & expl = args[nextArg][j];780 781 // fresh copies of parent parameters for this iteration782 ast::TypeEnvironment env = results[i].env;783 ast::OpenVarSet open = results[i].open;784 785 env.addActual( expl.env, open );786 787 // skip empty tuple arguments by (nearly) cloning parent into next gen788 if ( expl.exprs.empty() ) {789 results.emplace_back(790 results[i], std::move( env ), copy( results[i].need ),791 copy( results[i].have ), std::move( open ), nextArg + 1,792 expl.cost );793 794 continue;795 }796 797 // add new result798 results.emplace_back(799 i, expl.exprs.front(), std::move( env ), copy( results[i].need ),800 copy( results[i].have ), std::move( open ), nextArg + 1, 0, expl.cost,801 expl.exprs.size() == 1 ? 0 : 1, j );802 }803 }804 805 genStart = genEnd;806 } while( genEnd != results.size() );807 } else {808 // filter out the results that don't use all the arguments809 for ( std::size_t i = genStart; i < results.size(); ++i ) {810 ArgPack & result = results[i];811 if ( ! result.hasExpl() && result.nextArg >= args.size() ) {812 validateFunctionCandidate( func, result, results, out );813 }814 }815 }816 }817 818 /// Adds implicit struct-conversions to the alternative list819 void addAnonConversions( const CandidateRef & cand ) {820 // adds anonymous member interpretations whenever an aggregate value type is seen.821 // it's okay for the aggregate expression to have reference type -- cast it to the822 // base type to treat the aggregate as the referenced value823 ast::ptr< ast::Expr > aggrExpr( cand->expr );824 ast::ptr< ast::Type > & aggrType = aggrExpr.get_and_mutate()->result;825 cand->env.apply( aggrType );826 827 if ( aggrType.as< ast::ReferenceType >() ) {828 aggrExpr = new ast::CastExpr{ aggrExpr, aggrType->stripReferences() };829 }830 831 if ( auto structInst = aggrExpr->result.as< ast::StructInstType >() ) {832 addAggMembers( structInst, aggrExpr, *cand, Cost::safe, "" );833 } else if ( auto unionInst = aggrExpr->result.as< ast::UnionInstType >() ) {834 addAggMembers( unionInst, aggrExpr, *cand, Cost::safe, "" );835 }836 }837 838 /// Adds aggregate member interpretations839 void addAggMembers(840 const ast::BaseInstType * aggrInst, const ast::Expr * expr,841 const Candidate & cand, const Cost & addedCost, const std::string & name842 ) {843 for ( const ast::Decl * decl : aggrInst->lookup( name ) ) {844 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( decl );845 CandidateRef newCand = std::make_shared<Candidate>(846 cand, new ast::MemberExpr{ expr->location, dwt, expr }, addedCost );847 // add anonymous member interpretations whenever an aggregate value type is seen848 // as a member expression849 addAnonConversions( newCand );850 candidates.emplace_back( std::move( newCand ) );851 }852 }853 854 /// Adds tuple member interpretations855 void addTupleMembers(856 const ast::TupleType * tupleType, const ast::Expr * expr, const Candidate & cand,857 const Cost & addedCost, const ast::Expr * member858 ) {859 if ( auto constantExpr = dynamic_cast< const ast::ConstantExpr * >( member ) ) {860 // get the value of the constant expression as an int, must be between 0 and the861 // length of the tuple to have meaning862 long long val = constantExpr->intValue();863 if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {864 addCandidate(865 cand, new ast::TupleIndexExpr{ expr->location, expr, (unsigned)val },866 addedCost );867 }868 }869 }870 871 void postvisit( const ast::UntypedExpr * untypedExpr ) {872 std::vector< CandidateFinder > argCandidates =873 selfFinder.findSubExprs( untypedExpr->args );874 875 // take care of possible tuple assignments876 // if not tuple assignment, handled as normal function call877 Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );878 879 CandidateFinder funcFinder( context, tenv );880 if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) {881 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);882 if (kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS) {883 assertf(!argCandidates.empty(), "special function call without argument");884 for (auto & firstArgCand: argCandidates[0]) {885 ast::ptr<ast::Type> argType = firstArgCand->expr->result;886 firstArgCand->env.apply(argType);887 // strip references888 // xxx - is this correct?889 while (argType.as<ast::ReferenceType>()) argType = argType.as<ast::ReferenceType>()->base;890 891 // convert 1-tuple to plain type892 if (auto tuple = argType.as<ast::TupleType>()) {893 if (tuple->size() == 1) {894 argType = tuple->types[0];895 }896 }897 898 // if argType is an unbound type parameter, all special functions need to be searched.899 if (isUnboundType(argType)) {900 funcFinder.otypeKeys.clear();901 break;902 }903 904 if (argType.as<ast::PointerType>()) funcFinder.otypeKeys.insert(Mangle::Encoding::pointer);905 // else if (const ast::EnumInstType * enumInst = argType.as<ast::EnumInstType>()) {906 // const ast::EnumDecl * enumDecl = enumInst->base; // Here907 // if ( const ast::Type* enumType = enumDecl->base ) {908 // // instance of enum (T) is a instance of type (T)909 // funcFinder.otypeKeys.insert(Mangle::mangle(enumType, Mangle::NoGenericParams | Mangle::Type));910 // } else {911 // // instance of an untyped enum is techically int912 // funcFinder.otypeKeys.insert(Mangle::mangle(enumDecl, Mangle::NoGenericParams | Mangle::Type));913 // }914 // }915 else funcFinder.otypeKeys.insert(Mangle::mangle(argType, Mangle::NoGenericParams | Mangle::Type));916 }917 }918 }919 // if candidates are already produced, do not fail920 // xxx - is it possible that handleTupleAssignment and main finder both produce candidates?921 // this means there exists ctor/assign functions with a tuple as first parameter.922 ResolvMode mode = {923 true, // adjust924 !untypedExpr->func.as<ast::NameExpr>(), // prune if not calling by name925 selfFinder.candidates.empty() // failfast if other options are not found926 };927 funcFinder.find( untypedExpr->func, mode );928 // short-circuit if no candidates929 // if ( funcFinder.candidates.empty() ) return;930 931 reason.code = NoMatch;932 933 // find function operators934 ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" }; // ??? why not ?{}935 CandidateFinder opFinder( context, tenv );936 // okay if there aren't any function operations937 opFinder.find( opExpr, ResolvMode::withoutFailFast() );938 PRINT(939 std::cerr << "known function ops:" << std::endl;940 print( std::cerr, opFinder.candidates, 1 );941 )942 943 // pre-explode arguments944 ExplodedArgs_new argExpansions;945 for ( const CandidateFinder & args : argCandidates ) {946 argExpansions.emplace_back();947 auto & argE = argExpansions.back();948 for ( const CandidateRef & arg : args ) { argE.emplace_back( *arg, symtab ); }949 }950 951 // Find function matches952 CandidateList found;953 SemanticErrorException errors;954 for ( CandidateRef & func : funcFinder ) {955 try {956 PRINT(957 std::cerr << "working on alternative:" << std::endl;958 print( std::cerr, *func, 2 );959 )960 961 // check if the type is a pointer to function962 const ast::Type * funcResult = func->expr->result->stripReferences();963 if ( auto pointer = dynamic_cast< const ast::PointerType * >( funcResult ) ) {964 if ( auto function = pointer->base.as< ast::FunctionType >() ) {965 CandidateRef newFunc{ new Candidate{ *func } };966 newFunc->expr =967 referenceToRvalueConversion( newFunc->expr, newFunc->cost );968 makeFunctionCandidates( newFunc, function, argExpansions, found );969 }970 } else if (971 auto inst = dynamic_cast< const ast::TypeInstType * >( funcResult )972 ) {973 if ( const ast::EqvClass * clz = func->env.lookup( *inst ) ) {974 if ( auto function = clz->bound.as< ast::FunctionType >() ) {975 CandidateRef newFunc{ new Candidate{ *func } };976 newFunc->expr =977 referenceToRvalueConversion( newFunc->expr, newFunc->cost );978 makeFunctionCandidates( newFunc, function, argExpansions, found );979 }980 }981 }982 } catch ( SemanticErrorException & e ) { errors.append( e ); }983 }984 985 // Find matches on function operators `?()`986 if ( ! opFinder.candidates.empty() ) {987 // add exploded function alternatives to front of argument list988 std::vector< ExplodedArg > funcE;989 funcE.reserve( funcFinder.candidates.size() );990 for ( const CandidateRef & func : funcFinder ) {991 funcE.emplace_back( *func, symtab );992 }993 argExpansions.emplace_front( std::move( funcE ) );994 995 for ( const CandidateRef & op : opFinder ) {996 try {997 // check if type is pointer-to-function998 const ast::Type * opResult = op->expr->result->stripReferences();999 if ( auto pointer = dynamic_cast< const ast::PointerType * >( opResult ) ) {1000 if ( auto function = pointer->base.as< ast::FunctionType >() ) {1001 CandidateRef newOp{ new Candidate{ *op} };1002 newOp->expr =1003 referenceToRvalueConversion( newOp->expr, newOp->cost );1004 makeFunctionCandidates( newOp, function, argExpansions, found );1005 }1006 }1007 } catch ( SemanticErrorException & e ) { errors.append( e ); }1008 }1009 }1010 1011 // Implement SFINAE; resolution errors are only errors if there aren't any non-error1012 // candidates1013 if ( found.empty() && ! errors.isEmpty() ) { throw errors; }1014 1015 // Compute conversion costs1016 for ( CandidateRef & withFunc : found ) {1017 Cost cvtCost = computeApplicationConversionCost( withFunc, symtab );1018 1019 PRINT(1020 auto appExpr = withFunc->expr.strict_as< ast::ApplicationExpr >();1021 auto pointer = appExpr->func->result.strict_as< ast::PointerType >();1022 auto function = pointer->base.strict_as< ast::FunctionType >();1023 1024 std::cerr << "Case +++++++++++++ " << appExpr->func << std::endl;1025 std::cerr << "parameters are:" << std::endl;1026 ast::printAll( std::cerr, function->params, 2 );1027 std::cerr << "arguments are:" << std::endl;1028 ast::printAll( std::cerr, appExpr->args, 2 );1029 std::cerr << "bindings are:" << std::endl;1030 ast::print( std::cerr, withFunc->env, 2 );1031 std::cerr << "cost is: " << withFunc->cost << std::endl;1032 std::cerr << "cost of conversion is:" << cvtCost << std::endl;1033 )1034 1035 if ( cvtCost != Cost::infinity ) {1036 withFunc->cvtCost = cvtCost;1037 candidates.emplace_back( std::move( withFunc ) );1038 }1039 }1040 found = std::move( candidates );1041 1042 // use a new list so that candidates are not examined by addAnonConversions twice1043 CandidateList winners = findMinCost( found );1044 promoteCvtCost( winners );1045 1046 // function may return a struct/union value, in which case we need to add candidates1047 // for implicit conversions to each of the anonymous members, which must happen after1048 // `findMinCost`, since anon conversions are never the cheapest1049 for ( const CandidateRef & c : winners ) {1050 addAnonConversions( c );1051 }1052 spliceBegin( candidates, winners );1053 1054 if ( candidates.empty() && targetType && ! targetType->isVoid() ) {1055 // If resolution is unsuccessful with a target type, try again without, since it1056 // will sometimes succeed when it wouldn't with a target type binding.1057 // For example:1058 // forall( otype T ) T & ?[]( T *, ptrdiff_t );1059 // const char * x = "hello world";1060 // unsigned char ch = x[0];1061 // Fails with simple return type binding (xxx -- check this!) as follows:1062 // * T is bound to unsigned char1063 // * (x: const char *) is unified with unsigned char *, which fails1064 // xxx -- fix this better1065 targetType = nullptr;1066 postvisit( untypedExpr );1067 }1068 }1069 1070 /// true if expression is an lvalue1071 static bool isLvalue( const ast::Expr * x ) {1072 return x->result && ( x->get_lvalue() || x->result.as< ast::ReferenceType >() );1073 }1074 1075 void postvisit( const ast::AddressExpr * addressExpr ) {1076 CandidateFinder finder( context, tenv );1077 finder.find( addressExpr->arg );1078 1079 if( finder.candidates.empty() ) return;1080 1081 reason.code = NoMatch;1082 1083 for ( CandidateRef & r : finder.candidates ) {1084 if ( ! isLvalue( r->expr ) ) continue;1085 addCandidate( *r, new ast::AddressExpr{ addressExpr->location, r->expr } );1086 }1087 }1088 1089 void postvisit( const ast::LabelAddressExpr * labelExpr ) {1090 addCandidate( labelExpr, tenv );1091 }1092 1093 void postvisit( const ast::CastExpr * castExpr ) {1094 ast::ptr< ast::Type > toType = castExpr->result;1095 assert( toType );1096 toType = resolveTypeof( toType, context );1097 toType = adjustExprType( toType, tenv, symtab );1098 1099 CandidateFinder finder( context, tenv, toType );1100 finder.find( castExpr->arg, ResolvMode::withAdjustment() );1101 1102 if( !finder.candidates.empty() ) reason.code = NoMatch;1103 1104 CandidateList matches;1105 for ( CandidateRef & cand : finder.candidates ) {1106 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;1107 ast::OpenVarSet open( cand->open );1108 1109 cand->env.extractOpenVars( open );1110 1111 // It is possible that a cast can throw away some values in a multiply-valued1112 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of the1113 // subexpression results that are cast directly. The candidate is invalid if it1114 // has fewer results than there are types to cast to.1115 int discardedValues = cand->expr->result->size() - toType->size();1116 if ( discardedValues < 0 ) continue;1117 1118 // unification run for side-effects1119 unify( toType, cand->expr->result, cand->env, need, have, open, symtab );1120 Cost thisCost =1121 (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast)1122 ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env )1123 : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env );1124 1125 PRINT(1126 std::cerr << "working on cast with result: " << toType << std::endl;1127 std::cerr << "and expr type: " << cand->expr->result << std::endl;1128 std::cerr << "env: " << cand->env << std::endl;1129 )1130 if ( thisCost != Cost::infinity ) {1131 PRINT(1132 std::cerr << "has finite cost." << std::endl;1133 )1134 // count one safe conversion for each value that is thrown away1135 thisCost.incSafe( discardedValues );1136 CandidateRef newCand = std::make_shared<Candidate>(1137 restructureCast( cand->expr, toType, castExpr->isGenerated ),1138 copy( cand->env ), std::move( open ), std::move( need ), cand->cost,1139 cand->cost + thisCost );1140 inferParameters( newCand, matches );1141 }1142 }1143 1144 // select first on argument cost, then conversion cost1145 CandidateList minArgCost = findMinCost( matches );1146 promoteCvtCost( minArgCost );1147 candidates = findMinCost( minArgCost );1148 }1149 1150 void postvisit( const ast::VirtualCastExpr * castExpr ) {1151 assertf( castExpr->result, "Implicit virtual cast targets not yet supported." );1152 CandidateFinder finder( context, tenv );1153 // don't prune here, all alternatives guaranteed to have same type1154 finder.find( castExpr->arg, ResolvMode::withoutPrune() );1155 for ( CandidateRef & r : finder.candidates ) {1156 addCandidate(1157 *r,1158 new ast::VirtualCastExpr{ castExpr->location, r->expr, castExpr->result } );1159 }1160 }1161 1162 void postvisit( const ast::KeywordCastExpr * castExpr ) {1163 const auto & loc = castExpr->location;1164 assertf( castExpr->result, "Cast target should have been set in Validate." );1165 auto ref = castExpr->result.strict_as<ast::ReferenceType>();1166 auto inst = ref->base.strict_as<ast::StructInstType>();1167 auto target = inst->base.get();1168 1169 CandidateFinder finder( context, tenv );1170 1171 auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) {1172 for(auto & cand : found) {1173 const ast::Type * expr = cand->expr->result.get();1174 if(expect_ref) {1175 auto res = dynamic_cast<const ast::ReferenceType*>(expr);1176 if(!res) { continue; }1177 expr = res->base.get();1178 }1179 1180 if(auto insttype = dynamic_cast<const ast::TypeInstType*>(expr)) {1181 auto td = cand->env.lookup(*insttype);1182 if(!td) { continue; }1183 expr = td->bound.get();1184 }1185 1186 if(auto base = dynamic_cast<const ast::StructInstType*>(expr)) {1187 if(base->base == target) {1188 candidates.push_back( std::move(cand) );1189 reason.code = NoReason;1190 }1191 }1192 }1193 };1194 1195 try {1196 // Attempt 1 : turn (thread&)X into (thread$&)X.__thrd1197 // Clone is purely for memory management1198 std::unique_ptr<const ast::Expr> tech1 { new ast::UntypedMemberExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.field), castExpr->arg) };1199 1200 // don't prune here, since it's guaranteed all alternatives will have the same type1201 finder.find( tech1.get(), ResolvMode::withoutPrune() );1202 pick_alternatives(finder.candidates, false);1203 1204 return;1205 } catch(SemanticErrorException & ) {}1206 1207 // Fallback : turn (thread&)X into (thread$&)get_thread(X)1208 std::unique_ptr<const ast::Expr> fallback { ast::UntypedExpr::createDeref(loc, new ast::UntypedExpr(loc, new ast::NameExpr(loc, castExpr->concrete_target.getter), { castExpr->arg })) };1209 // don't prune here, since it's guaranteed all alternatives will have the same type1210 finder.find( fallback.get(), ResolvMode::withoutPrune() );1211 1212 pick_alternatives(finder.candidates, true);1213 1214 // Whatever happens here, we have no more fallbacks1215 }1216 1217 void postvisit( const ast::UntypedMemberExpr * memberExpr ) {1218 CandidateFinder aggFinder( context, tenv );1219 aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );1220 for ( CandidateRef & agg : aggFinder.candidates ) {1221 // it's okay for the aggregate expression to have reference type -- cast it to the1222 // base type to treat the aggregate as the referenced value1223 Cost addedCost = Cost::zero;1224 agg->expr = referenceToRvalueConversion( agg->expr, addedCost );1225 1226 // find member of the given type1227 if ( auto structInst = agg->expr->result.as< ast::StructInstType >() ) {1228 addAggMembers(1229 structInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );1230 } else if ( auto unionInst = agg->expr->result.as< ast::UnionInstType >() ) {1231 addAggMembers(1232 unionInst, agg->expr, *agg, addedCost, getMemberName( memberExpr ) );1233 } else if ( auto tupleType = agg->expr->result.as< ast::TupleType >() ) {1234 addTupleMembers( tupleType, agg->expr, *agg, addedCost, memberExpr->member );1235 }1236 }1237 }1238 1239 void postvisit( const ast::MemberExpr * memberExpr ) {1240 addCandidate( memberExpr, tenv );1241 }1242 1243 void postvisit( const ast::NameExpr * nameExpr ) {1244 std::vector< ast::SymbolTable::IdData > declList;1245 if (!selfFinder.otypeKeys.empty()) {1246 auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);1247 assertf(kind != ast::SymbolTable::SpecialFunctionKind::NUMBER_OF_KINDS, "special lookup with non-special target: %s", nameExpr->name.c_str());1248 1249 for (auto & otypeKey: selfFinder.otypeKeys) {1250 auto result = symtab.specialLookupId(kind, otypeKey);1251 declList.insert(declList.end(), std::make_move_iterator(result.begin()), std::make_move_iterator(result.end()));1252 }1253 }1254 else {1255 declList = symtab.lookupId( nameExpr->name );1256 }1257 PRINT( std::cerr << "nameExpr is " << nameExpr->name << std::endl; )1258 1259 if( declList.empty() ) return;1260 1261 reason.code = NoMatch;1262 1263 for ( auto & data : declList ) {1264 Cost cost = Cost::zero;1265 ast::Expr * newExpr = data.combine( nameExpr->location, cost );1266 1267 CandidateRef newCand = std::make_shared<Candidate>(1268 newExpr, copy( tenv ), ast::OpenVarSet{}, ast::AssertionSet{}, Cost::zero,1269 cost );1270 1271 if (newCand->expr->env) {1272 newCand->env.add(*newCand->expr->env);1273 auto mutExpr = newCand->expr.get_and_mutate();1274 mutExpr->env = nullptr;1275 newCand->expr = mutExpr;1276 }1277 1278 PRINT(1279 std::cerr << "decl is ";1280 ast::print( std::cerr, data.id );1281 std::cerr << std::endl;1282 std::cerr << "newExpr is ";1283 ast::print( std::cerr, newExpr );1284 std::cerr << std::endl;1285 )1286 newCand->expr = ast::mutate_field(1287 newCand->expr.get(), &ast::Expr::result,1288 renameTyVars( newCand->expr->result ) );1289 // add anonymous member interpretations whenever an aggregate value type is seen1290 // as a name expression1291 addAnonConversions( newCand );1292 candidates.emplace_back( std::move( newCand ) );1293 }1294 }1295 1296 void postvisit( const ast::VariableExpr * variableExpr ) {1297 // not sufficient to just pass `variableExpr` here, type might have changed since1298 // creation1299 addCandidate(1300 new ast::VariableExpr{ variableExpr->location, variableExpr->var }, tenv );1301 }1302 1303 void postvisit( const ast::ConstantExpr * constantExpr ) {1304 addCandidate( constantExpr, tenv );1305 }1306 1307 void postvisit( const ast::SizeofExpr * sizeofExpr ) {1308 if ( sizeofExpr->type ) {1309 addCandidate(1310 new ast::SizeofExpr{1311 sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) },1312 tenv );1313 } else {1314 // find all candidates for the argument to sizeof1315 CandidateFinder finder( context, tenv );1316 finder.find( sizeofExpr->expr );1317 // find the lowest-cost candidate, otherwise ambiguous1318 CandidateList winners = findMinCost( finder.candidates );1319 if ( winners.size() != 1 ) {1320 SemanticError(1321 sizeofExpr->expr.get(), "Ambiguous expression in sizeof operand: " );1322 }1323 // return the lowest-cost candidate1324 CandidateRef & choice = winners.front();1325 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );1326 choice->cost = Cost::zero;1327 addCandidate( *choice, new ast::SizeofExpr{ sizeofExpr->location, choice->expr } );1328 }1329 }1330 1331 void postvisit( const ast::AlignofExpr * alignofExpr ) {1332 if ( alignofExpr->type ) {1333 addCandidate(1334 new ast::AlignofExpr{1335 alignofExpr->location, resolveTypeof( alignofExpr->type, context ) },1336 tenv );1337 } else {1338 // find all candidates for the argument to alignof1339 CandidateFinder finder( context, tenv );1340 finder.find( alignofExpr->expr );1341 // find the lowest-cost candidate, otherwise ambiguous1342 CandidateList winners = findMinCost( finder.candidates );1343 if ( winners.size() != 1 ) {1344 SemanticError(1345 alignofExpr->expr.get(), "Ambiguous expression in alignof operand: " );1346 }1347 // return the lowest-cost candidate1348 CandidateRef & choice = winners.front();1349 choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );1350 choice->cost = Cost::zero;1351 addCandidate(1352 *choice, new ast::AlignofExpr{ alignofExpr->location, choice->expr } );1353 }1354 }1355 1356 void postvisit( const ast::UntypedOffsetofExpr * offsetofExpr ) {1357 const ast::BaseInstType * aggInst;1358 if (( aggInst = offsetofExpr->type.as< ast::StructInstType >() )) ;1359 else if (( aggInst = offsetofExpr->type.as< ast::UnionInstType >() )) ;1360 else return;1361 1362 for ( const ast::Decl * member : aggInst->lookup( offsetofExpr->member ) ) {1363 auto dwt = strict_dynamic_cast< const ast::DeclWithType * >( member );1364 addCandidate(1365 new ast::OffsetofExpr{ offsetofExpr->location, aggInst, dwt }, tenv );1366 }1367 }1368 1369 void postvisit( const ast::OffsetofExpr * offsetofExpr ) {1370 addCandidate( offsetofExpr, tenv );1371 }1372 1373 void postvisit( const ast::OffsetPackExpr * offsetPackExpr ) {1374 addCandidate( offsetPackExpr, tenv );1375 }1376 1377 void postvisit( const ast::LogicalExpr * logicalExpr ) {1378 CandidateFinder finder1( context, tenv );1379 finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() );1380 if ( finder1.candidates.empty() ) return;1381 1382 CandidateFinder finder2( context, tenv );1383 finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );1384 if ( finder2.candidates.empty() ) return;1385 1386 reason.code = NoMatch;1387 1388 for ( const CandidateRef & r1 : finder1.candidates ) {1389 for ( const CandidateRef & r2 : finder2.candidates ) {1390 ast::TypeEnvironment env{ r1->env };1391 env.simpleCombine( r2->env );1392 ast::OpenVarSet open{ r1->open };1393 mergeOpenVars( open, r2->open );1394 ast::AssertionSet need;1395 mergeAssertionSet( need, r1->need );1396 mergeAssertionSet( need, r2->need );1397 1398 addCandidate(1399 new ast::LogicalExpr{1400 logicalExpr->location, r1->expr, r2->expr, logicalExpr->isAnd },1401 std::move( env ), std::move( open ), std::move( need ), r1->cost + r2->cost );1402 }1403 }1404 }1405 1406 void postvisit( const ast::ConditionalExpr * conditionalExpr ) {1407 // candidates for condition1408 CandidateFinder finder1( context, tenv );1409 finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );1410 if ( finder1.candidates.empty() ) return;1411 1412 // candidates for true result1413 CandidateFinder finder2( context, tenv );1414 finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );1415 if ( finder2.candidates.empty() ) return;1416 1417 // candidates for false result1418 CandidateFinder finder3( context, tenv );1419 finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );1420 if ( finder3.candidates.empty() ) return;1421 1422 reason.code = NoMatch;1423 1424 for ( const CandidateRef & r1 : finder1.candidates ) {1425 for ( const CandidateRef & r2 : finder2.candidates ) {1426 for ( const CandidateRef & r3 : finder3.candidates ) {1427 ast::TypeEnvironment env{ r1->env };1428 env.simpleCombine( r2->env );1429 env.simpleCombine( r3->env );1430 ast::OpenVarSet open{ r1->open };1431 mergeOpenVars( open, r2->open );1432 mergeOpenVars( open, r3->open );1433 ast::AssertionSet need;1434 mergeAssertionSet( need, r1->need );1435 mergeAssertionSet( need, r2->need );1436 mergeAssertionSet( need, r3->need );1437 ast::AssertionSet have;1438 1439 // unify true and false results, then infer parameters to produce new1440 // candidates1441 ast::ptr< ast::Type > common;1442 if (1443 unify(1444 r2->expr->result, r3->expr->result, env, need, have, open, symtab,1445 common )1446 ) {1447 // generate typed expression1448 ast::ConditionalExpr * newExpr = new ast::ConditionalExpr{1449 conditionalExpr->location, r1->expr, r2->expr, r3->expr };1450 newExpr->result = common ? common : r2->expr->result;1451 // convert both options to result type1452 Cost cost = r1->cost + r2->cost + r3->cost;1453 newExpr->arg2 = computeExpressionConversionCost(1454 newExpr->arg2, newExpr->result, symtab, env, cost );1455 newExpr->arg3 = computeExpressionConversionCost(1456 newExpr->arg3, newExpr->result, symtab, env, cost );1457 // output candidate1458 CandidateRef newCand = std::make_shared<Candidate>(1459 newExpr, std::move( env ), std::move( open ), std::move( need ), cost );1460 inferParameters( newCand, candidates );1461 }1462 }1463 }1464 }1465 }1466 1467 void postvisit( const ast::CommaExpr * commaExpr ) {1468 ast::TypeEnvironment env{ tenv };1469 ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env );1470 1471 CandidateFinder finder2( context, env );1472 finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );1473 1474 for ( const CandidateRef & r2 : finder2.candidates ) {1475 addCandidate( *r2, new ast::CommaExpr{ commaExpr->location, arg1, r2->expr } );1476 }1477 }1478 1479 void postvisit( const ast::ImplicitCopyCtorExpr * ctorExpr ) {1480 addCandidate( ctorExpr, tenv );1481 }1482 1483 void postvisit( const ast::ConstructorExpr * ctorExpr ) {1484 CandidateFinder finder( context, tenv );1485 finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() );1486 for ( CandidateRef & r : finder.candidates ) {1487 addCandidate( *r, new ast::ConstructorExpr{ ctorExpr->location, r->expr } );1488 }1489 }1490 1491 void postvisit( const ast::RangeExpr * rangeExpr ) {1492 // resolve low and high, accept candidates where low and high types unify1493 CandidateFinder finder1( context, tenv );1494 finder1.find( rangeExpr->low, ResolvMode::withAdjustment() );1495 if ( finder1.candidates.empty() ) return;1496 1497 CandidateFinder finder2( context, tenv );1498 finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );1499 if ( finder2.candidates.empty() ) return;1500 1501 reason.code = NoMatch;1502 1503 for ( const CandidateRef & r1 : finder1.candidates ) {1504 for ( const CandidateRef & r2 : finder2.candidates ) {1505 ast::TypeEnvironment env{ r1->env };1506 env.simpleCombine( r2->env );1507 ast::OpenVarSet open{ r1->open };1508 mergeOpenVars( open, r2->open );1509 ast::AssertionSet need;1510 mergeAssertionSet( need, r1->need );1511 mergeAssertionSet( need, r2->need );1512 ast::AssertionSet have;1513 1514 ast::ptr< ast::Type > common;1515 if (1516 unify(1517 r1->expr->result, r2->expr->result, env, need, have, open, symtab,1518 common )1519 ) {1520 // generate new expression1521 ast::RangeExpr * newExpr =1522 new ast::RangeExpr{ rangeExpr->location, r1->expr, r2->expr };1523 newExpr->result = common ? common : r1->expr->result;1524 // add candidate1525 CandidateRef newCand = std::make_shared<Candidate>(1526 newExpr, std::move( env ), std::move( open ), std::move( need ),1527 r1->cost + r2->cost );1528 inferParameters( newCand, candidates );1529 }1530 }1531 }1532 }1533 1534 void postvisit( const ast::UntypedTupleExpr * tupleExpr ) {1535 std::vector< CandidateFinder > subCandidates =1536 selfFinder.findSubExprs( tupleExpr->exprs );1537 std::vector< CandidateList > possibilities;1538 combos( subCandidates.begin(), subCandidates.end(), back_inserter( possibilities ) );1539 1540 for ( const CandidateList & subs : possibilities ) {1541 std::vector< ast::ptr< ast::Expr > > exprs;1542 exprs.reserve( subs.size() );1543 for ( const CandidateRef & sub : subs ) { exprs.emplace_back( sub->expr ); }1544 1545 ast::TypeEnvironment env;1546 ast::OpenVarSet open;1547 ast::AssertionSet need;1548 for ( const CandidateRef & sub : subs ) {1549 env.simpleCombine( sub->env );1550 mergeOpenVars( open, sub->open );1551 mergeAssertionSet( need, sub->need );1552 }1553 1554 addCandidate(1555 new ast::TupleExpr{ tupleExpr->location, std::move( exprs ) },1556 std::move( env ), std::move( open ), std::move( need ), sumCost( subs ) );1557 }1558 }1559 1560 void postvisit( const ast::TupleExpr * tupleExpr ) {1561 addCandidate( tupleExpr, tenv );1562 }1563 1564 void postvisit( const ast::TupleIndexExpr * tupleExpr ) {1565 addCandidate( tupleExpr, tenv );1566 }1567 1568 void postvisit( const ast::TupleAssignExpr * tupleExpr ) {1569 addCandidate( tupleExpr, tenv );1570 }1571 1572 void postvisit( const ast::UniqueExpr * unqExpr ) {1573 CandidateFinder finder( context, tenv );1574 finder.find( unqExpr->expr, ResolvMode::withAdjustment() );1575 for ( CandidateRef & r : finder.candidates ) {1576 // ensure that the the id is passed on so that the expressions are "linked"1577 addCandidate( *r, new ast::UniqueExpr{ unqExpr->location, r->expr, unqExpr->id } );1578 }1579 }1580 1581 void postvisit( const ast::StmtExpr * stmtExpr ) {1582 addCandidate( resolveStmtExpr( stmtExpr, context ), tenv );1583 }1584 1585 void postvisit( const ast::UntypedInitExpr * initExpr ) {1586 // handle each option like a cast1587 CandidateList matches;1588 PRINT(1589 std::cerr << "untyped init expr: " << initExpr << std::endl;1590 )1591 // O(n^2) checks of d-types with e-types1592 for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) {1593 // calculate target type1594 const ast::Type * toType = resolveTypeof( initAlt.type, context );1595 toType = adjustExprType( toType, tenv, symtab );1596 // The call to find must occur inside this loop, otherwise polymorphic return1597 // types are not bound to the initialization type, since return type variables are1598 // only open for the duration of resolving the UntypedExpr.1599 CandidateFinder finder( context, tenv, toType );1600 finder.find( initExpr->expr, ResolvMode::withAdjustment() );1601 for ( CandidateRef & cand : finder.candidates ) {1602 if(reason.code == NotFound) reason.code = NoMatch;1603 1604 ast::TypeEnvironment env{ cand->env };1605 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;1606 ast::OpenVarSet open{ cand->open };1607 1608 PRINT(1609 std::cerr << " @ " << toType << " " << initAlt.designation << std::endl;1610 )1611 1612 // It is possible that a cast can throw away some values in a multiply-valued1613 // expression, e.g. cast-to-void, one value to zero. Figure out the prefix of1614 // the subexpression results that are cast directly. The candidate is invalid1615 // if it has fewer results than there are types to cast to.1616 int discardedValues = cand->expr->result->size() - toType->size();1617 if ( discardedValues < 0 ) continue;1618 1619 // unification run for side-effects1620 bool canUnify = unify( toType, cand->expr->result, env, need, have, open, symtab );1621 (void) canUnify;1622 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(),1623 symtab, env );1624 PRINT(1625 Cost legacyCost = castCost( cand->expr->result, toType, cand->expr->get_lvalue(),1626 symtab, env );1627 std::cerr << "Considering initialization:";1628 std::cerr << std::endl << " FROM: " << cand->expr->result << std::endl;1629 std::cerr << std::endl << " TO: " << toType << std::endl;1630 std::cerr << std::endl << " Unification " << (canUnify ? "succeeded" : "failed");1631 std::cerr << std::endl << " Legacy cost " << legacyCost;1632 std::cerr << std::endl << " New cost " << thisCost;1633 std::cerr << std::endl;1634 )1635 if ( thisCost != Cost::infinity ) {1636 // count one safe conversion for each value that is thrown away1637 thisCost.incSafe( discardedValues );1638 CandidateRef newCand = std::make_shared<Candidate>(1639 new ast::InitExpr{1640 initExpr->location, restructureCast( cand->expr, toType ),1641 initAlt.designation },1642 std::move(env), std::move( open ), std::move( need ), cand->cost, thisCost );1643 inferParameters( newCand, matches );1644 }1645 }1646 1647 }1648 1649 // select first on argument cost, then conversion cost1650 CandidateList minArgCost = findMinCost( matches );1651 promoteCvtCost( minArgCost );1652 candidates = findMinCost( minArgCost );1653 }1654 1655 void postvisit( const ast::InitExpr * ) {1656 assertf( false, "CandidateFinder should never see a resolved InitExpr." );1657 }1658 1659 void postvisit( const ast::DeletedExpr * ) {1660 assertf( false, "CandidateFinder should never see a DeletedExpr." );1661 }1662 1663 void postvisit( const ast::GenericExpr * ) {1664 assertf( false, "_Generic is not yet supported." );1665 }1666 };1667 1668 // size_t Finder::traceId = Stats::Heap::new_stacktrace_id("Finder");1669 /// Prunes a list of candidates down to those that have the minimum conversion cost for a given1670 /// return type. Skips ambiguous candidates.1671 1672 } // anonymous namespace1673 1674 bool CandidateFinder::pruneCandidates( CandidateList & candidates, CandidateList & out, std::vector<std::string> & errors ) {1675 struct PruneStruct {1676 CandidateRef candidate;1677 bool ambiguous;1678 1679 PruneStruct() = default;1680 PruneStruct( const CandidateRef & c ) : candidate( c ), ambiguous( false ) {}1681 };1682 1683 // find lowest-cost candidate for each type1684 std::unordered_map< std::string, PruneStruct > selected;1685 // attempt to skip satisfyAssertions on more expensive alternatives if better options have been found1686 std::sort(candidates.begin(), candidates.end(), [](const CandidateRef & x, const CandidateRef & y){return x->cost < y->cost;});1687 for ( CandidateRef & candidate : candidates ) {1688 std::string mangleName;1689 {1690 ast::ptr< ast::Type > newType = candidate->expr->result;1691 assertf(candidate->expr->result, "Result of expression %p for candidate is null", candidate->expr.get());1692 candidate->env.apply( newType );1693 mangleName = Mangle::mangle( newType );1694 }1695 1696 auto found = selected.find( mangleName );1697 if (found != selected.end() && found->second.candidate->cost < candidate->cost) {1698 PRINT(1699 std::cerr << "cost " << candidate->cost << " loses to "1700 << found->second.candidate->cost << std::endl;1701 )1702 continue;1703 }1704 1705 // xxx - when do satisfyAssertions produce more than 1 result?1706 // this should only happen when initial result type contains1707 // unbound type parameters, then it should never be pruned by1708 // the previous step, since renameTyVars guarantees the mangled name1709 // is unique.1710 CandidateList satisfied;1711 bool needRecomputeKey = false;1712 if (candidate->need.empty()) {1713 satisfied.emplace_back(candidate);1714 }1715 else {1716 satisfyAssertions(candidate, context.symtab, satisfied, errors);1717 needRecomputeKey = true;1718 }1719 1720 for (auto & newCand : satisfied) {1721 // recomputes type key, if satisfyAssertions changed it1722 if (needRecomputeKey)1723 {1724 ast::ptr< ast::Type > newType = newCand->expr->result;1725 assertf(newCand->expr->result, "Result of expression %p for candidate is null", newCand->expr.get());1726 newCand->env.apply( newType );1727 mangleName = Mangle::mangle( newType );1728 }1729 auto found = selected.find( mangleName );1730 if ( found != selected.end() ) {1731 if ( newCand->cost < found->second.candidate->cost ) {1732 PRINT(1733 std::cerr << "cost " << newCand->cost << " beats "1734 << found->second.candidate->cost << std::endl;1735 )1736 1737 found->second = PruneStruct{ newCand };1738 } else if ( newCand->cost == found->second.candidate->cost ) {1739 // if one of the candidates contains a deleted identifier, can pick the other,1740 // since deleted expressions should not be ambiguous if there is another option1741 // that is at least as good1742 if ( findDeletedExpr( newCand->expr ) ) {1743 // do nothing1744 PRINT( std::cerr << "candidate is deleted" << std::endl; )1745 } else if ( findDeletedExpr( found->second.candidate->expr ) ) {1746 PRINT( std::cerr << "current is deleted" << std::endl; )1747 found->second = PruneStruct{ newCand };1748 } else {1749 PRINT( std::cerr << "marking ambiguous" << std::endl; )1750 found->second.ambiguous = true;1751 }1752 } else {1753 // xxx - can satisfyAssertions increase the cost?1754 PRINT(1755 std::cerr << "cost " << newCand->cost << " loses to "1756 << found->second.candidate->cost << std::endl;1757 )1758 }1759 } else {1760 selected.emplace_hint( found, mangleName, newCand );1761 }1762 }1763 }1764 1765 // report unambiguous min-cost candidates1766 // CandidateList out;1767 for ( auto & target : selected ) {1768 if ( target.second.ambiguous ) continue;1769 1770 CandidateRef cand = target.second.candidate;1771 1772 ast::ptr< ast::Type > newResult = cand->expr->result;1773 cand->env.applyFree( newResult );1774 cand->expr = ast::mutate_field(1775 cand->expr.get(), &ast::Expr::result, std::move( newResult ) );1776 1777 out.emplace_back( cand );1778 }1779 // if everything is lost in satisfyAssertions, report the error1780 return !selected.empty();1781 }1782 1783 void CandidateFinder::find( const ast::Expr * expr, ResolvMode mode ) {1784 // Find alternatives for expression1785 ast::Pass<Finder> finder{ *this };1786 expr->accept( finder );1787 1788 if ( mode.failFast && candidates.empty() ) {1789 switch(finder.core.reason.code) {1790 case Finder::NotFound:1791 { SemanticError( expr, "No alternatives for expression " ); break; }1792 case Finder::NoMatch:1793 { SemanticError( expr, "Invalid application of existing declaration(s) in expression " ); break; }1794 case Finder::ArgsToFew:1795 case Finder::ArgsToMany:1796 case Finder::RetsToFew:1797 case Finder::RetsToMany:1798 case Finder::NoReason:1799 default:1800 { SemanticError( expr->location, "No reasonable alternatives for expression : reasons unkown" ); }1801 }1802 }1803 1804 /*1805 if ( mode.satisfyAssns || mode.prune ) {1806 // trim candidates to just those where the assertions are satisfiable1807 // - necessary pre-requisite to pruning1808 CandidateList satisfied;1809 std::vector< std::string > errors;1810 for ( CandidateRef & candidate : candidates ) {1811 satisfyAssertions( candidate, localSyms, satisfied, errors );1812 }1813 1814 // fail early if none such1815 if ( mode.failFast && satisfied.empty() ) {1816 std::ostringstream stream;1817 stream << "No alternatives with satisfiable assertions for " << expr << "\n";1818 for ( const auto& err : errors ) {1819 stream << err;1820 }1821 SemanticError( expr->location, stream.str() );1822 }1823 1824 // reset candidates1825 candidates = move( satisfied );1826 }1827 */1828 1829 if ( mode.prune ) {1830 // trim candidates to single best one1831 PRINT(1832 std::cerr << "alternatives before prune:" << std::endl;1833 print( std::cerr, candidates );1834 )1835 1836 CandidateList pruned;1837 std::vector<std::string> errors;1838 bool found = pruneCandidates( candidates, pruned, errors );1839 1840 if ( mode.failFast && pruned.empty() ) {1841 std::ostringstream stream;1842 if (found) {1843 CandidateList winners = findMinCost( candidates );1844 stream << "Cannot choose between " << winners.size() << " alternatives for "1845 "expression\n";1846 ast::print( stream, expr );1847 stream << " Alternatives are:\n";1848 print( stream, winners, 1 );1849 SemanticError( expr->location, stream.str() );1850 }1851 else {1852 stream << "No alternatives with satisfiable assertions for " << expr << "\n";1853 for ( const auto& err : errors ) {1854 stream << err;1855 }1856 SemanticError( expr->location, stream.str() );1857 }1858 }1859 1860 auto oldsize = candidates.size();1861 candidates = std::move( pruned );1862 1863 PRINT(1864 std::cerr << "there are " << oldsize << " alternatives before elimination" << std::endl;1865 )1866 PRINT(1867 std::cerr << "there are " << candidates.size() << " alternatives after elimination"1868 << std::endl;1869 )1870 }1871 1872 // adjust types after pruning so that types substituted by pruneAlternatives are correctly1873 // adjusted1874 if ( mode.adjust ) {1875 for ( CandidateRef & r : candidates ) {1876 r->expr = ast::mutate_field(1877 r->expr.get(), &ast::Expr::result,1878 adjustExprType( r->expr->result, r->env, context.symtab ) );1879 }1880 }1881 1882 // Central location to handle gcc extension keyword, etc. for all expressions1883 for ( CandidateRef & r : candidates ) {1884 if ( r->expr->extension != expr->extension ) {1885 r->expr.get_and_mutate()->extension = expr->extension;1886 }1887 }1888 }1889 1890 std::vector< CandidateFinder > CandidateFinder::findSubExprs(1891 const std::vector< ast::ptr< ast::Expr > > & xs1892 ) {1893 std::vector< CandidateFinder > out;1894 1895 for ( const auto & x : xs ) {1896 out.emplace_back( context, env );1897 out.back().find( x, ResolvMode::withAdjustment() );1898 1899 PRINT(1900 std::cerr << "findSubExprs" << std::endl;1901 print( std::cerr, out.back().candidates );1902 )1903 }1904 1905 return out;1906 }1907 1908 1970 } // namespace ResolvExpr 1909 1971 -
src/ResolvExpr/CurrentObject.cc
r2ed94a9 rb110bcc 9 9 // Author : Rob Schluntz 10 10 // Created On : Tue Jun 13 15:28:32 2017 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Jul 1 09:16:01 202213 // Update Count : 1 511 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Apr 10 9:40:00 2023 13 // Update Count : 18 14 14 // 15 15 … … 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 … … 592 593 593 594 namespace ast { 595 /// Iterates members of a type by initializer. 596 class MemberIterator { 597 public: 598 virtual ~MemberIterator() {} 599 600 /// Internal set position based on iterator ranges. 601 virtual void setPosition( 602 std::deque< ptr< Expr > >::const_iterator it, 603 std::deque< ptr< Expr > >::const_iterator end ) = 0; 604 605 /// Walks the current object using the given designators as a guide. 606 void setPosition( const std::deque< ptr< Expr > > & designators ) { 607 setPosition( designators.begin(), designators.end() ); 608 } 609 610 /// Retrieve the list of possible (Type,Designation) pairs for the 611 /// current position in the current object. 612 virtual std::deque< InitAlternative > operator* () const = 0; 613 614 /// True if the iterator is not currently at the end. 615 virtual operator bool() const = 0; 616 617 /// Moves the iterator by one member in the current object. 618 virtual MemberIterator & bigStep() = 0; 619 620 /// Moves the iterator by one member in the current subobject. 621 virtual MemberIterator & smallStep() = 0; 622 623 /// The type of the current object. 624 virtual const Type * getType() = 0; 625 626 /// The type of the current subobject. 627 virtual const Type * getNext() = 0; 628 629 /// Helper for operator*; aggregates must add designator to each init 630 /// alternative, but adding designators in operator* creates duplicates. 631 virtual std::deque< InitAlternative > first() const = 0; 632 }; 633 594 634 /// create a new MemberIterator that traverses a type correctly 595 635 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ); … … 631 671 }; 632 672 633 /// Iterates array types 634 class ArrayIterator final : public MemberIterator { 673 /// Iterates over an indexed type: 674 class IndexIterator : public MemberIterator { 675 protected: 635 676 CodeLocation location; 636 const ArrayType * array = nullptr;637 const Type * base = nullptr;638 677 size_t index = 0; 639 678 size_t size = 0; 640 std::unique_ptr< MemberIterator > memberIter; 641 642 void setSize( const Expr * expr ) { 643 auto res = eval( expr ); 644 if ( ! res.second ) { 645 SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) ); 646 } 647 size = res.first; 648 } 649 650 public: 651 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) : location( loc ), array( at ), base( at->base ) { 652 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) 653 memberIter.reset( createMemberIterator( loc, base ) ); 654 if ( at->isVarLen ) { 655 SemanticError( location, at, "VLA initialization does not support @=: " ); 656 } 657 setSize( at->dimension ); 658 } 679 std::unique_ptr<MemberIterator> memberIter; 680 public: 681 IndexIterator( const CodeLocation & loc, size_t size ) : 682 location( loc ), size( size ) 683 {} 659 684 660 685 void setPosition( const Expr * expr ) { … … 665 690 auto arg = eval( expr ); 666 691 index = arg.first; 667 return;668 692 669 693 // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) { … … 683 707 684 708 void setPosition( 685 std::deque< ptr< Expr >>::const_iterator begin,686 std::deque< ptr< Expr >>::const_iterator end709 std::deque<ast::ptr<ast::Expr>>::const_iterator begin, 710 std::deque<ast::ptr<ast::Expr>>::const_iterator end 687 711 ) override { 688 712 if ( begin == end ) return; … … 695 719 696 720 operator bool() const override { return index < size; } 721 }; 722 723 /// Iterates over the members of array types: 724 class ArrayIterator final : public IndexIterator { 725 const ArrayType * array = nullptr; 726 const Type * base = nullptr; 727 728 size_t getSize( const Expr * expr ) { 729 auto res = eval( expr ); 730 if ( !res.second ) { 731 SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) ); 732 } 733 return res.first; 734 } 735 736 public: 737 ArrayIterator( const CodeLocation & loc, const ArrayType * at ) : 738 IndexIterator( loc, getSize( at->dimension) ), 739 array( at ), base( at->base ) { 740 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; ) 741 memberIter.reset( createMemberIterator( loc, base ) ); 742 if ( at->isVarLen ) { 743 SemanticError( location, at, "VLA initialization does not support @=: " ); 744 } 745 } 697 746 698 747 ArrayIterator & bigStep() override { … … 833 882 834 883 const Type * getNext() final { 835 return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr; 884 bool hasMember = memberIter && *memberIter; 885 return hasMember ? memberIter->getType() : nullptr; 836 886 } 837 887 … … 897 947 }; 898 948 899 class TupleIterator final : public AggregateIterator { 900 public: 901 TupleIterator( const CodeLocation & loc, const TupleType * inst ) 902 : AggregateIterator( 903 loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members 904 ) {} 905 906 operator bool() const override { 907 return curMember != members.end() || (memberIter && *memberIter); 949 /// Iterates across the positions in a tuple: 950 class TupleIterator final : public IndexIterator { 951 ast::TupleType const * const tuple; 952 953 const ast::Type * typeAtIndex() const { 954 assert( index < size ); 955 return tuple->types[ index ].get(); 956 } 957 958 public: 959 TupleIterator( const CodeLocation & loc, const TupleType * type ) 960 : IndexIterator( loc, type->size() ), tuple( type ) { 961 PRINT( std::cerr << "Creating tuple iterator: " << type << std::endl; ) 962 memberIter.reset( createMemberIterator( loc, typeAtIndex() ) ); 908 963 } 909 964 910 965 TupleIterator & bigStep() override { 911 PRINT( std::cerr << "bigStep in " << kind << std::endl; ) 912 atbegin = false; 913 memberIter = nullptr; 914 curType = nullptr; 915 while ( curMember != members.end() ) { 916 ++curMember; 917 if ( init() ) return *this; 918 } 966 ++index; 967 memberIter.reset( index < size ? 968 createMemberIterator( location, typeAtIndex() ) : nullptr ); 919 969 return *this; 970 } 971 972 TupleIterator & smallStep() override { 973 if ( memberIter ) { 974 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; ) 975 memberIter->smallStep(); 976 if ( !memberIter ) { 977 PRINT( std::cerr << "has valid member iter" << std::endl; ) 978 return *this; 979 } 980 } 981 return bigStep(); 982 } 983 984 const ast::Type * getType() override { 985 return tuple; 986 } 987 988 const ast::Type * getNext() override { 989 bool hasMember = memberIter && *memberIter; 990 return hasMember ? memberIter->getType() : nullptr; 991 } 992 993 std::deque< InitAlternative > first() const override { 994 PRINT( std::cerr << "first in TupleIterator (" << index << "/" << size << ")" << std::endl; ) 995 if ( memberIter && *memberIter ) { 996 std::deque< InitAlternative > ret = memberIter->first(); 997 for ( InitAlternative & alt : ret ) { 998 alt.designation.get_and_mutate()->designators.emplace_front( 999 ConstantExpr::from_ulong( location, index ) ); 1000 } 1001 return ret; 1002 } 1003 return {}; 920 1004 } 921 1005 }; -
src/ResolvExpr/CurrentObject.h
r2ed94a9 rb110bcc 9 9 // Author : Rob Schluntz 10 10 // Created On : Thu Jun 8 11:07:25 2017 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sat Jul 22 09:36:48 201713 // Update Count : 311 // Last Modified By : Andrew Beach 12 // Last Modified On : Thu Apr 6 16:14:00 2023 13 // Update Count : 4 14 14 // 15 15 … … 65 65 66 66 /// Iterates members of a type by initializer 67 class MemberIterator { 68 public: 69 virtual ~MemberIterator() {} 70 71 /// Internal set position based on iterator ranges 72 virtual void setPosition( 73 std::deque< ptr< Expr > >::const_iterator it, 74 std::deque< ptr< Expr > >::const_iterator end ) = 0; 75 76 /// walks the current object using the given designators as a guide 77 void setPosition( const std::deque< ptr< Expr > > & designators ) { 78 setPosition( designators.begin(), designators.end() ); 79 } 80 81 /// retrieve the list of possible (Type,Designation) pairs for the current position in the 82 /// current object 83 virtual std::deque< InitAlternative > operator* () const = 0; 84 85 /// true if the iterator is not currently at the end 86 virtual operator bool() const = 0; 87 88 /// moves the iterator by one member in the current object 89 virtual MemberIterator & bigStep() = 0; 90 91 /// moves the iterator by one member in the current subobject 92 virtual MemberIterator & smallStep() = 0; 93 94 /// the type of the current object 95 virtual const Type * getType() = 0; 96 97 /// the type of the current subobject 98 virtual const Type * getNext() = 0; 99 100 /// helper for operator*; aggregates must add designator to each init alternative, but 101 /// adding designators in operator* creates duplicates 102 virtual std::deque< InitAlternative > first() const = 0; 103 }; 67 class MemberIterator; 104 68 105 69 /// Builds initializer lists in resolution -
src/ResolvExpr/ExplodedArg.hpp
r2ed94a9 rb110bcc 35 35 ExplodedArg() : env(), cost( Cost::zero ), exprs() {} 36 36 ExplodedArg( const Candidate & arg, const ast::SymbolTable & symtab ); 37 37 38 38 ExplodedArg( ExplodedArg && ) = default; 39 39 ExplodedArg & operator= ( ExplodedArg && ) = default; -
src/ResolvExpr/ResolveAssertions.cc
r2ed94a9 rb110bcc 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
r2ed94a9 rb110bcc 38 38 #include "AST/SymbolTable.hpp" 39 39 #include "AST/Type.hpp" 40 #include "Common/Eval.h" // for eval 41 #include "Common/Iterate.hpp" // for group_iterate 40 42 #include "Common/PassVisitor.h" // for PassVisitor 41 43 #include "Common/SemanticError.h" // for SemanticError 42 44 #include "Common/Stats/ResolveTime.h" // for ResolveTime::start(), ResolveTime::stop() 43 #include "Common/ utility.h" // for ValueGuard, group_iterate45 #include "Common/ToString.hpp" // for toCString 44 46 #include "InitTweak/GenInit.h" 45 47 #include "InitTweak/InitTweak.h" // for isIntrinsicSingleArgCallStmt -
src/ResolvExpr/Resolver.h
r2ed94a9 rb110bcc 34 34 class Decl; 35 35 class DeletedExpr; 36 class Expr; 36 37 class Init; 37 38 class StmtExpr; -
src/SymTab/Autogen.cc
r2ed94a9 rb110bcc 10 10 // Created On : Thu Mar 03 15:45:56 2016 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Apr 27 14:39:06 201813 // Update Count : 6 312 // Last Modified On : Fri Apr 14 15:03:00 2023 13 // Update Count : 64 14 14 // 15 15 … … 211 211 } 212 212 213 bool isUnnamedBitfield( const ast::ObjectDecl * obj ) {214 return obj && obj->name.empty() && obj->bitfieldWidth;215 }216 217 213 /// inserts a forward declaration for functionDecl into declsToAdd 218 214 void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) { … … 234 230 } 235 231 236 // shallow copy the pointer list for return237 std::vector<ast::ptr<ast::TypeDecl>> getGenericParams (const ast::Type * t) {238 if (auto structInst = dynamic_cast<const ast::StructInstType*>(t)) {239 return structInst->base->params;240 }241 if (auto unionInst = dynamic_cast<const ast::UnionInstType*>(t)) {242 return unionInst->base->params;243 }244 return {};245 }246 247 232 /// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *) 248 233 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) { … … 256 241 ftype->parameters.push_back( dstParam ); 257 242 return ftype; 258 }259 260 /// Given type T, generate type of default ctor/dtor, i.e. function type void (*) (T &).261 ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic) {262 std::vector<ast::ptr<ast::TypeDecl>> typeParams;263 if (maybePolymorphic) typeParams = getGenericParams(paramType);264 auto dstParam = new ast::ObjectDecl(loc, "_dst", new ast::ReferenceType(paramType), nullptr, {}, ast::Linkage::Cforall);265 return new ast::FunctionDecl(loc, fname, std::move(typeParams), {dstParam}, {}, new ast::CompoundStmt(loc), {}, ast::Linkage::Cforall);266 243 } 267 244 -
src/SymTab/Autogen.h
r2ed94a9 rb110bcc 9 9 // Author : Rob Schluntz 10 10 // Created On : Sun May 17 21:53:34 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Fri Dec 13 16:38:06 201913 // Update Count : 1 611 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Apr 14 15:06:00 2023 13 // Update Count : 17 14 14 // 15 15 … … 45 45 /// returns true if obj's name is the empty string and it has a bitfield width 46 46 bool isUnnamedBitfield( ObjectDecl * obj ); 47 bool isUnnamedBitfield( const ast::ObjectDecl * obj );48 47 49 48 /// generate the type of an assignment function for paramType. … … 55 54 FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true ); 56 55 57 ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true);58 59 56 /// generate the type of a copy constructor for paramType. 60 57 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic … … 67 64 template< typename OutputIterator > 68 65 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true ); 69 70 template< typename OutIter >71 ast::ptr< ast::Stmt > genCall(72 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,73 const CodeLocation & loc, const std::string & fname, OutIter && out,74 const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );75 66 76 67 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types. … … 121 112 122 113 *out++ = new ExprStmt( fExpr ); 123 124 srcParam.clearArrayIndices();125 126 return listInit;127 }128 129 /// inserts into out a generated call expression to function fname with arguments dstParam and130 /// srcParam. Should only be called with non-array types.131 /// optionally returns a statement which must be inserted prior to the containing loop, if132 /// there is one133 template< typename OutIter >134 ast::ptr< ast::Stmt > genScalarCall(135 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,136 const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,137 const ast::Type * addCast = nullptr138 ) {139 bool isReferenceCtorDtor = false;140 if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {141 // reference constructors are essentially application of the rebind operator.142 // apply & to both arguments, do not need a cast143 fname = "?=?";144 dstParam = new ast::AddressExpr{ dstParam };145 addCast = nullptr;146 isReferenceCtorDtor = true;147 }148 149 // want to be able to generate assignment, ctor, and dtor generically, so fname is one of150 // "?=?", "?{}", or "^?{}"151 ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } };152 153 if ( addCast ) {154 // cast to T& with qualifiers removed, so that qualified objects can be constructed and155 // destructed with the same functions as non-qualified objects. Unfortunately, lvalue156 // is considered a qualifier - for AddressExpr to resolve, its argument must have an157 // lvalue-qualified type, so remove all qualifiers except lvalue.158 // xxx -- old code actually removed lvalue too...159 ast::ptr< ast::Type > guard = addCast; // prevent castType from mutating addCast160 ast::ptr< ast::Type > castType = addCast;161 ast::remove_qualifiers(162 castType,163 ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );164 dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };165 }166 fExpr->args.emplace_back( dstParam );167 168 ast::ptr<ast::Stmt> listInit = srcParam.buildListInit( fExpr );169 170 // fetch next set of arguments171 ++srcParam;172 173 // return if adding reference fails -- will happen on default ctor and dtor174 if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;175 176 std::vector< ast::ptr< ast::Expr > > args = *srcParam;177 splice( fExpr->args, args );178 179 *out++ = new ast::ExprStmt{ loc, fExpr };180 114 181 115 srcParam.clearArrayIndices(); … … 248 182 } 249 183 250 /// Store in out a loop which calls fname on each element of the array with srcParam and251 /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0252 template< typename OutIter >253 void genArrayCall(254 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,255 const CodeLocation & loc, const std::string & fname, OutIter && out,256 const ast::ArrayType * array, const ast::Type * addCast = nullptr,257 LoopDirection forward = LoopForward258 ) {259 static UniqueName indexName( "_index" );260 261 // for a flexible array member nothing is done -- user must define own assignment262 if ( ! array->dimension ) return;263 264 if ( addCast ) {265 // peel off array layer from cast266 addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;267 }268 269 ast::ptr< ast::Expr > begin, end;270 std::string cmp, update;271 272 if ( forward ) {273 // generate: for ( int i = 0; i < N; ++i )274 begin = ast::ConstantExpr::from_int( loc, 0 );275 end = array->dimension;276 cmp = "?<?";277 update = "++?";278 } else {279 // generate: for ( int i = N-1; i >= 0; --i )280 begin = ast::UntypedExpr::createCall( loc, "?-?",281 { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } );282 end = ast::ConstantExpr::from_int( loc, 0 );283 cmp = "?>=?";284 update = "--?";285 }286 287 ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{288 loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },289 new ast::SingleInit{ loc, begin } };290 ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };291 292 ast::ptr< ast::Expr > cond = ast::UntypedExpr::createCall(293 loc, cmp, { indexVar, end } );294 295 ast::ptr< ast::Expr > inc = ast::UntypedExpr::createCall(296 loc, update, { indexVar } );297 298 ast::ptr< ast::Expr > dstIndex = ast::UntypedExpr::createCall(299 loc, "?[?]", { dstParam, indexVar } );300 301 // srcParam must keep track of the array indices to build the source parameter and/or302 // array list initializer303 srcParam.addArrayIndex( indexVar, array->dimension );304 305 // for stmt's body, eventually containing call306 ast::CompoundStmt * body = new ast::CompoundStmt{ loc };307 ast::ptr< ast::Stmt > listInit = genCall(308 srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,309 forward );310 311 // block containing the stmt and index variable312 ast::CompoundStmt * block = new ast::CompoundStmt{ loc };313 block->push_back( new ast::DeclStmt{ loc, index } );314 if ( listInit ) { block->push_back( listInit ); }315 block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } );316 317 *out++ = block;318 }319 320 184 template< typename OutputIterator > 321 185 Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) { … … 325 189 } else { 326 190 return genScalarCall( srcParam, dstParam, fname, out, type, addCast ); 327 }328 }329 330 template< typename OutIter >331 ast::ptr< ast::Stmt > genCall(332 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,333 const CodeLocation & loc, const std::string & fname, OutIter && out,334 const ast::Type * type, const ast::Type * addCast, LoopDirection forward335 ) {336 if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {337 genArrayCall(338 srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,339 forward );340 return {};341 } else {342 return genScalarCall(343 srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );344 191 } 345 192 } … … 379 226 } 380 227 381 static inline ast::ptr< ast::Stmt > genImplicitCall(382 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,383 const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,384 LoopDirection forward = LoopForward385 ) {386 // unnamed bit fields are not copied as they cannot be accessed387 if ( isUnnamedBitfield( obj ) ) return {};388 389 ast::ptr< ast::Type > addCast;390 if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {391 assert( dstParam->result );392 addCast = dstParam->result;393 }394 395 std::vector< ast::ptr< ast::Stmt > > stmts;396 genCall(397 srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );398 399 if ( stmts.empty() ) {400 return {};401 } else if ( stmts.size() == 1 ) {402 const ast::Stmt * callStmt = stmts.front();403 if ( addCast ) {404 // implicitly generated ctor/dtor calls should be wrapped so that later passes are405 // aware they were generated.406 callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt };407 }408 return callStmt;409 } else {410 assert( false );411 return {};412 }413 }414 228 } // namespace SymTab 415 229 -
src/SymTab/FixFunction.cc
r2ed94a9 rb110bcc 21 21 #include "AST/Pass.hpp" 22 22 #include "AST/Type.hpp" 23 #include "Common/utility.h" // for maybeClone,copy23 #include "Common/utility.h" // for copy 24 24 #include "SynTree/Declaration.h" // for FunctionDecl, ObjectDecl, Declarati... 25 25 #include "SynTree/Expression.h" // for Expression -
src/SymTab/Mangler.cc
r2ed94a9 rb110bcc 24 24 #include "CodeGen/OperatorTable.h" // for OperatorInfo, operatorLookup 25 25 #include "Common/PassVisitor.h" 26 #include "Common/ToString.hpp" // for toCString 26 27 #include "Common/SemanticError.h" // for SemanticError 27 #include "Common/utility.h" // for toString28 28 #include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment 29 29 #include "SynTree/LinkageSpec.h" // for Spec, isOverridable, AutoGen, Int... -
src/SymTab/Validate.cc
r2ed94a9 rb110bcc 55 55 #include "Common/ScopedMap.h" // for ScopedMap 56 56 #include "Common/SemanticError.h" // for SemanticError 57 #include "Common/ToString.hpp" // for toCString 57 58 #include "Common/UniqueName.h" // for UniqueName 58 #include "Common/utility.h" // for operator+,cloneAll, deleteAll59 #include "Common/utility.h" // for cloneAll, deleteAll 59 60 #include "CompilationState.h" // skip some passes in new-ast build 60 61 #include "Concurrency/Keywords.h" // for applyKeywords -
src/SymTab/ValidateType.cc
r2ed94a9 rb110bcc 18 18 #include "CodeGen/OperatorTable.h" 19 19 #include "Common/PassVisitor.h" 20 #include "Common/ToString.hpp" 20 21 #include "SymTab/FixFunction.h" 21 22 #include "SynTree/Declaration.h" -
src/SymTab/module.mk
r2ed94a9 rb110bcc 20 20 SymTab/FixFunction.cc \ 21 21 SymTab/FixFunction.h \ 22 SymTab/GenImplicitCall.cpp \ 23 SymTab/GenImplicitCall.hpp \ 22 24 SymTab/Indexer.cc \ 23 25 SymTab/Indexer.h \ -
src/SynTree/AggregateDecl.cc
r2ed94a9 rb110bcc 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/FunctionDecl.cc
r2ed94a9 rb110bcc 87 87 } // if 88 88 89 if ( !withExprs.empty() ) { 90 os << indent << "... with clause" << std::endl; 91 os << indent + 1; 92 printAll( withExprs, os, indent + 1 ); 93 } 94 89 95 if ( statements ) { 90 96 os << indent << "... with body" << endl << indent+1; -
src/SynTree/Type.cc
r2ed94a9 rb110bcc 16 16 17 17 #include "Attribute.h" // for Attribute 18 #include "Common/ToString.hpp" // for toCString 18 19 #include "Common/utility.h" // for cloneAll, deleteAll, printAll 19 20 #include "InitTweak/InitTweak.h" // for getPointerBase … … 105 106 int Type::referenceDepth() const { return 0; } 106 107 108 AggregateDecl * Type::getAggr() const { 109 assertf( false, "Non-aggregate type: %s", toCString( this ) ); 110 } 111 107 112 TypeSubstitution Type::genericSubstitution() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); } 108 113 -
src/SynTree/Type.h
r2ed94a9 rb110bcc 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 26 #include "Mutator.h" // for Mutator 27 27 #include "SynTree.h" // for AST nodes … … 124 124 bool operator!=( Qualifiers other ) const { return (val & Mask) != (other.val & Mask); } 125 125 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 free126 return is_const <= other.is_const // Any non-const converts to const without cost 127 && is_volatile <= other.is_volatile // Any non-volatile converts to volatile without cost 128 && is_mutex >= other.is_mutex // Any mutex converts to non-mutex without cost 129 && is_atomic == other.is_atomic; // No conversion from atomic to non atomic is free 130 130 } 131 131 bool operator<( Qualifiers other ) const { return *this != other && *this <= other; } … … 185 185 virtual bool isComplete() const { return true; } 186 186 187 virtual AggregateDecl * getAggr() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }187 virtual AggregateDecl * getAggr() const; 188 188 189 189 virtual TypeSubstitution genericSubstitution() const; 190 190 191 virtual Type * clone() const = 0;191 virtual Type * clone() const = 0; 192 192 virtual void accept( Visitor & v ) = 0; 193 193 virtual void accept( Visitor & v ) const = 0; 194 virtual Type * acceptMutator( Mutator & m ) = 0;194 virtual Type * acceptMutator( Mutator & m ) = 0; 195 195 virtual void print( std::ostream & os, Indenter indent = {} ) const; 196 196 }; … … 207 207 virtual bool isComplete() const override { return false; } 208 208 209 virtual VoidType * clone() const override { return new VoidType( *this ); }210 virtual void accept( Visitor & v ) override { v.visit( this ); } 211 virtual void accept( Visitor & v ) const override { v.visit( this ); } 212 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }209 virtual VoidType * clone() const override { return new VoidType( *this ); } 210 virtual void accept( Visitor & v ) override { v.visit( this ); } 211 virtual void accept( Visitor & v ) const override { v.visit( this ); } 212 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 213 213 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 214 214 }; … … 259 259 // GENERATED END 260 260 261 static const char * typeNames[];// string names for basic types, MUST MATCH with Kind261 static const char * typeNames[]; // string names for basic types, MUST MATCH with Kind 262 262 263 263 BasicType( const Type::Qualifiers & tq, Kind bt, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); … … 266 266 void set_kind( Kind newValue ) { kind = newValue; } 267 267 268 virtual BasicType * clone() const override { return new BasicType( *this ); }269 virtual void accept( Visitor & v ) override { v.visit( this ); } 270 virtual void accept( Visitor & v ) const override { v.visit( this ); } 271 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }268 virtual BasicType * clone() const override { return new BasicType( *this ); } 269 virtual void accept( Visitor & v ) override { v.visit( this ); } 270 virtual void accept( Visitor & v ) const override { v.visit( this ); } 271 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 272 272 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 273 273 bool isInteger() const; … … 279 279 280 280 // In C99, pointer types can be qualified in many ways e.g., int f( int a[ static 3 ] ) 281 Expression * dimension;281 Expression * dimension; 282 282 bool isVarLen; 283 283 bool isStatic; 284 284 285 PointerType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );286 PointerType( const Type::Qualifiers & tq, Type * base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );285 PointerType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 286 PointerType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 287 287 PointerType( const PointerType& ); 288 288 virtual ~PointerType(); 289 289 290 Type * get_base() { return base; }291 void set_base( Type * newValue ) { base = newValue; }292 Expression * get_dimension() { return dimension; }293 void set_dimension( Expression * newValue ) { dimension = newValue; }290 Type * get_base() { return base; } 291 void set_base( Type * newValue ) { base = newValue; } 292 Expression * get_dimension() { return dimension; } 293 void set_dimension( Expression * newValue ) { dimension = newValue; } 294 294 bool get_isVarLen() { return isVarLen; } 295 295 void set_isVarLen( bool newValue ) { isVarLen = newValue; } … … 301 301 virtual bool isComplete() const override { return ! isVarLen; } 302 302 303 virtual PointerType * clone() const override { return new PointerType( *this ); }304 virtual void accept( Visitor & v ) override { v.visit( this ); } 305 virtual void accept( Visitor & v ) const override { v.visit( this ); } 306 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }303 virtual PointerType * clone() const override { return new PointerType( * this ); } 304 virtual void accept( Visitor & v ) override { v.visit( this ); } 305 virtual void accept( Visitor & v ) const override { v.visit( this ); } 306 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 307 307 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 308 308 }; … … 310 310 class ArrayType : public Type { 311 311 public: 312 Type * base;313 Expression * dimension;312 Type * base; 313 Expression * dimension; 314 314 bool isVarLen; 315 315 bool isStatic; 316 316 317 ArrayType( const Type::Qualifiers & tq, Type * base, Expression *dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() );317 ArrayType( const Type::Qualifiers & tq, Type * base, Expression * dimension, bool isVarLen, bool isStatic, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 318 318 ArrayType( const ArrayType& ); 319 319 virtual ~ArrayType(); 320 320 321 Type * get_base() { return base; }322 void set_base( Type * newValue ) { base = newValue; }323 Expression * get_dimension() { return dimension; }324 void set_dimension( Expression * newValue ) { dimension = newValue; }321 Type * get_base() { return base; } 322 void set_base( Type * newValue ) { base = newValue; } 323 Expression * get_dimension() { return dimension; } 324 void set_dimension( Expression * newValue ) { dimension = newValue; } 325 325 bool get_isVarLen() { return isVarLen; } 326 326 void set_isVarLen( bool newValue ) { isVarLen = newValue; } … … 333 333 virtual bool isComplete() const override { return dimension || isVarLen; } 334 334 335 virtual ArrayType * clone() const override { return new ArrayType( *this ); }336 virtual void accept( Visitor & v ) override { v.visit( this ); } 337 virtual void accept( Visitor & v ) const override { v.visit( this ); } 338 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }335 virtual ArrayType * clone() const override { return new ArrayType( *this ); } 336 virtual void accept( Visitor & v ) override { v.visit( this ); } 337 virtual void accept( Visitor & v ) const override { v.visit( this ); } 338 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 339 339 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 340 340 }; … … 348 348 virtual ~QualifiedType(); 349 349 350 virtual QualifiedType * clone() const override { return new QualifiedType( *this ); }351 virtual void accept( Visitor & v ) override { v.visit( this ); } 352 virtual void accept( Visitor & v ) const override { v.visit( this ); } 353 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }350 virtual QualifiedType * clone() const override { return new QualifiedType( *this ); } 351 virtual void accept( Visitor & v ) override { v.visit( this ); } 352 virtual void accept( Visitor & v ) const override { v.visit( this ); } 353 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 354 354 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 355 355 }; … … 357 357 class ReferenceType : public Type { 358 358 public: 359 Type * base;360 361 ReferenceType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() );359 Type * base; 360 361 ReferenceType( const Type::Qualifiers & tq, Type * base, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 362 362 ReferenceType( const ReferenceType & ); 363 363 virtual ~ReferenceType(); 364 364 365 Type * get_base() { return base; }366 void set_base( Type * newValue ) { base = newValue; }365 Type * get_base() { return base; } 366 void set_base( Type * newValue ) { base = newValue; } 367 367 368 368 virtual int referenceDepth() const override; … … 375 375 virtual TypeSubstitution genericSubstitution() const override; 376 376 377 virtual ReferenceType * clone() const override { return new ReferenceType( *this ); }378 virtual void accept( Visitor & v ) override { v.visit( this ); } 379 virtual void accept( Visitor & v ) const override { v.visit( this ); } 380 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }377 virtual ReferenceType * clone() const override { return new ReferenceType( *this ); } 378 virtual void accept( Visitor & v ) override { v.visit( this ); } 379 virtual void accept( Visitor & v ) const override { v.visit( this ); } 380 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 381 381 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 382 382 }; … … 405 405 bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; } 406 406 407 virtual FunctionType * clone() const override { return new FunctionType( *this ); }408 virtual void accept( Visitor & v ) override { v.visit( this ); } 409 virtual void accept( Visitor & v ) const override { v.visit( this ); } 410 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }407 virtual FunctionType * clone() const override { return new FunctionType( *this ); } 408 virtual void accept( Visitor & v ) override { v.visit( this ); } 409 virtual void accept( Visitor & v ) const override { v.visit( this ); } 410 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 411 411 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 412 412 }; … … 414 414 class ReferenceToType : public Type { 415 415 public: 416 std::list< Expression * > parameters;416 std::list< Expression * > parameters; 417 417 std::string name; 418 418 bool hoistType; … … 428 428 void set_hoistType( bool newValue ) { hoistType = newValue; } 429 429 430 virtual ReferenceToType * clone() const override = 0;430 virtual ReferenceToType * clone() const override = 0; 431 431 virtual void accept( Visitor & v ) override = 0; 432 virtual Type * acceptMutator( Mutator & m ) override = 0;432 virtual Type * acceptMutator( Mutator & m ) override = 0; 433 433 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 434 434 … … 443 443 // this decl is not "owned" by the struct inst; it is merely a pointer to elsewhere in the tree, 444 444 // where the structure used in this type is actually defined 445 StructDecl * baseStruct;445 StructDecl * baseStruct; 446 446 447 447 StructInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ), baseStruct( 0 ) {} … … 449 449 StructInstType( const StructInstType & other ) : Parent( other ), baseStruct( other.baseStruct ) {} 450 450 451 StructDecl * get_baseStruct() const { return baseStruct; }452 void set_baseStruct( StructDecl * newValue ) { baseStruct = newValue; }451 StructDecl * get_baseStruct() const { return baseStruct; } 452 void set_baseStruct( StructDecl * newValue ) { baseStruct = newValue; } 453 453 454 454 /// Accesses generic parameters of base struct (NULL if none such) … … 466 466 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; 467 467 468 virtual StructInstType * clone() const override { return new StructInstType( *this ); }469 virtual void accept( Visitor & v ) override { v.visit( this ); } 470 virtual void accept( Visitor & v ) const override { v.visit( this ); } 471 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }468 virtual StructInstType * clone() const override { return new StructInstType( *this ); } 469 virtual void accept( Visitor & v ) override { v.visit( this ); } 470 virtual void accept( Visitor & v ) const override { v.visit( this ); } 471 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 472 472 473 473 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 481 481 // this decl is not "owned" by the union inst; it is merely a pointer to elsewhere in the tree, 482 482 // where the union used in this type is actually defined 483 UnionDecl * baseUnion;483 UnionDecl * baseUnion; 484 484 485 485 UnionInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ), baseUnion( 0 ) {} … … 487 487 UnionInstType( const UnionInstType & other ) : Parent( other ), baseUnion( other.baseUnion ) {} 488 488 489 UnionDecl * get_baseUnion() const { return baseUnion; }489 UnionDecl * get_baseUnion() const { return baseUnion; } 490 490 void set_baseUnion( UnionDecl * newValue ) { baseUnion = newValue; } 491 491 … … 504 504 void lookup( const std::string & name, std::list< Declaration* > & foundDecls ) const override; 505 505 506 virtual UnionInstType * clone() const override { return new UnionInstType( *this ); }507 virtual void accept( Visitor & v ) override { v.visit( this ); } 508 virtual void accept( Visitor & v ) const override { v.visit( this ); } 509 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }506 virtual UnionInstType * clone() const override { return new UnionInstType( *this ); } 507 virtual void accept( Visitor & v ) override { v.visit( this ); } 508 virtual void accept( Visitor & v ) const override { v.visit( this ); } 509 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 510 510 511 511 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 519 519 // this decl is not "owned" by the enum inst; it is merely a pointer to elsewhere in the tree, 520 520 // where the enum used in this type is actually defined 521 EnumDecl * baseEnum = nullptr;521 EnumDecl * baseEnum = nullptr; 522 522 523 523 EnumInstType( const Type::Qualifiers & tq, const std::string & name, const std::list< Attribute * > & attributes = std::list< Attribute * >() ) : Parent( tq, name, attributes ) {} … … 525 525 EnumInstType( const EnumInstType & other ) : Parent( other ), baseEnum( other.baseEnum ) {} 526 526 527 EnumDecl * get_baseEnum() const { return baseEnum; }528 void set_baseEnum( EnumDecl * newValue ) { baseEnum = newValue; }527 EnumDecl * get_baseEnum() const { return baseEnum; } 528 void set_baseEnum( EnumDecl * newValue ) { baseEnum = newValue; } 529 529 530 530 virtual bool isComplete() const override; … … 532 532 virtual AggregateDecl * getAggr() const override; 533 533 534 virtual EnumInstType * clone() const override { return new EnumInstType( *this ); }535 virtual void accept( Visitor & v ) override { v.visit( this ); } 536 virtual void accept( Visitor & v ) const override { v.visit( this ); } 537 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }534 virtual EnumInstType * clone() const override { return new EnumInstType( *this ); } 535 virtual void accept( Visitor & v ) override { v.visit( this ); } 536 virtual void accept( Visitor & v ) const override { v.visit( this ); } 537 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 538 538 539 539 virtual void print( std::ostream & os, Indenter indent = {} ) const override; … … 556 556 virtual bool isComplete() const override; 557 557 558 virtual TraitInstType * clone() const override { return new TraitInstType( *this ); }559 virtual void accept( Visitor & v ) override { v.visit( this ); } 560 virtual void accept( Visitor & v ) const override { v.visit( this ); } 561 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }558 virtual TraitInstType * clone() const override { return new TraitInstType( *this ); } 559 virtual void accept( Visitor & v ) override { v.visit( this ); } 560 virtual void accept( Visitor & v ) const override { v.visit( this ); } 561 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 562 562 private: 563 563 virtual std::string typeString() const override; … … 569 569 // this decl is not "owned" by the type inst; it is merely a pointer to elsewhere in the tree, 570 570 // where the type used here is actually defined 571 TypeDecl * baseType;571 TypeDecl * baseType; 572 572 bool isFtype; 573 573 574 TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl * baseType, const std::list< Attribute * > & attributes = std::list< Attribute * >() );574 TypeInstType( const Type::Qualifiers & tq, const std::string & name, TypeDecl * baseType, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 575 575 TypeInstType( const Type::Qualifiers & tq, const std::string & name, bool isFtype, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 576 576 TypeInstType( const TypeInstType & other ); 577 577 ~TypeInstType(); 578 578 579 TypeDecl * get_baseType() const { return baseType; }580 void set_baseType( TypeDecl * newValue );579 TypeDecl * get_baseType() const { return baseType; } 580 void set_baseType( TypeDecl * newValue ); 581 581 bool get_isFtype() const { return isFtype; } 582 582 void set_isFtype( bool newValue ) { isFtype = newValue; } … … 584 584 virtual bool isComplete() const override; 585 585 586 virtual TypeInstType * clone() const override { return new TypeInstType( *this ); }587 virtual void accept( Visitor & v ) override { v.visit( this ); } 588 virtual void accept( Visitor & v ) const override { v.visit( this ); } 589 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }586 virtual TypeInstType * clone() const override { return new TypeInstType( *this ); } 587 virtual void accept( Visitor & v ) override { v.visit( this ); } 588 virtual void accept( Visitor & v ) const override { v.visit( this ); } 589 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 590 590 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 591 591 private: … … 622 622 // virtual bool isComplete() const override { return true; } // xxx - not sure if this is right, might need to recursively check complete-ness 623 623 624 virtual TupleType * clone() const override { return new TupleType( *this ); }625 virtual void accept( Visitor & v ) override { v.visit( this ); } 626 virtual void accept( Visitor & v ) const override { v.visit( this ); } 627 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }624 virtual TupleType * clone() const override { return new TupleType( *this ); } 625 virtual void accept( Visitor & v ) override { v.visit( this ); } 626 virtual void accept( Visitor & v ) const override { v.visit( this ); } 627 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 628 628 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 629 629 }; … … 631 631 class TypeofType : public Type { 632 632 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,633 Expression * expr; ///< expression to take the type of 634 bool is_basetypeof; ///< true iff is basetypeof type 635 636 TypeofType( const Type::Qualifiers & tq, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 637 TypeofType( const Type::Qualifiers & tq, Expression * expr, bool is_basetypeof, 638 638 const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 639 639 TypeofType( const TypeofType& ); 640 640 virtual ~TypeofType(); 641 641 642 Expression * get_expr() const { return expr; }643 void set_expr( Expression * newValue ) { expr = newValue; }642 Expression * get_expr() const { return expr; } 643 void set_expr( Expression * newValue ) { expr = newValue; } 644 644 645 645 virtual bool isComplete() const override { assert( false ); return false; } 646 646 647 virtual TypeofType * clone() const override { return new TypeofType( *this ); }648 virtual void accept( Visitor & v ) override { v.visit( this ); } 649 virtual void accept( Visitor & v ) const override { v.visit( this ); } 650 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }647 virtual TypeofType * clone() const override { return new TypeofType( *this ); } 648 virtual void accept( Visitor & v ) override { v.visit( this ); } 649 virtual void accept( Visitor & v ) const override { v.visit( this ); } 650 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 651 651 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 652 652 }; … … 654 654 class VTableType : public Type { 655 655 public: 656 Type * base;657 658 VTableType( const Type::Qualifiers & tq, Type * base,656 Type * base; 657 658 VTableType( const Type::Qualifiers & tq, Type * base, 659 659 const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 660 660 VTableType( const VTableType & ); 661 661 virtual ~VTableType(); 662 662 663 Type * get_base() { return base; }664 void set_base( Type * newValue ) { base = newValue; }665 666 virtual VTableType * clone() const override { return new VTableType( *this ); }667 virtual void accept( Visitor & v ) override { v.visit( this ); } 668 virtual void accept( Visitor & v ) const override { v.visit( this ); } 669 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }663 Type * get_base() { return base; } 664 void set_base( Type * newValue ) { base = newValue; } 665 666 virtual VTableType * clone() const override { return new VTableType( *this ); } 667 virtual void accept( Visitor & v ) override { v.visit( this ); } 668 virtual void accept( Visitor & v ) const override { v.visit( this ); } 669 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 670 670 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 671 671 }; … … 674 674 public: 675 675 std::string name; 676 Expression * expr;677 Type * type;676 Expression * expr; 677 Type * type; 678 678 bool isType; 679 679 680 AttrType( const Type::Qualifiers & tq, const std::string & name, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );681 AttrType( const Type::Qualifiers & tq, const std::string & name, Type * type, const std::list< Attribute * > & attributes = std::list< Attribute * >() );680 AttrType( const Type::Qualifiers & tq, const std::string & name, Expression * expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 681 AttrType( const Type::Qualifiers & tq, const std::string & name, Type * type, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 682 682 AttrType( const AttrType& ); 683 683 virtual ~AttrType(); … … 685 685 const std::string & get_name() const { return name; } 686 686 void set_name( const std::string & newValue ) { name = newValue; } 687 Expression * get_expr() const { return expr; }688 void set_expr( Expression * newValue ) { expr = newValue; }689 Type * get_type() const { return type; }690 void set_type( Type * newValue ) { type = newValue; }687 Expression * get_expr() const { return expr; } 688 void set_expr( Expression * newValue ) { expr = newValue; } 689 Type * get_type() const { return type; } 690 void set_type( Type * newValue ) { type = newValue; } 691 691 bool get_isType() const { return isType; } 692 692 void set_isType( bool newValue ) { isType = newValue; } … … 694 694 virtual bool isComplete() const override { assert( false ); } // xxx - not sure what to do here 695 695 696 virtual AttrType * clone() const override { return new AttrType( *this ); }697 virtual void accept( Visitor & v ) override { v.visit( this ); } 698 virtual void accept( Visitor & v ) const override { v.visit( this ); } 699 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }696 virtual AttrType * clone() const override { return new AttrType( *this ); } 697 virtual void accept( Visitor & v ) override { v.visit( this ); } 698 virtual void accept( Visitor & v ) const override { v.visit( this ); } 699 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 700 700 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 701 701 }; … … 709 709 virtual bool isComplete() const override{ return true; } // xxx - is this right? 710 710 711 virtual VarArgsType * clone() const override { return new VarArgsType( *this ); }712 virtual void accept( Visitor & v ) override { v.visit( this ); } 713 virtual void accept( Visitor & v ) const override { v.visit( this ); } 714 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }711 virtual VarArgsType * clone() const override { return new VarArgsType( *this ); } 712 virtual void accept( Visitor & v ) override { v.visit( this ); } 713 virtual void accept( Visitor & v ) const override { v.visit( this ); } 714 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 715 715 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 716 716 }; … … 722 722 ZeroType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 723 723 724 virtual ZeroType * clone() const override { return new ZeroType( *this ); }725 virtual void accept( Visitor & v ) override { v.visit( this ); } 726 virtual void accept( Visitor & v ) const override { v.visit( this ); } 727 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }724 virtual ZeroType * clone() const override { return new ZeroType( *this ); } 725 virtual void accept( Visitor & v ) override { v.visit( this ); } 726 virtual void accept( Visitor & v ) const override { v.visit( this ); } 727 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 728 728 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 729 729 }; … … 735 735 OneType( Type::Qualifiers tq, const std::list< Attribute * > & attributes = std::list< Attribute * >() ); 736 736 737 virtual OneType * clone() const override { return new OneType( *this ); }738 virtual void accept( Visitor & v ) override { v.visit( this ); } 739 virtual void accept( Visitor & v ) const override { v.visit( this ); } 740 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }737 virtual OneType * clone() const override { return new OneType( *this ); } 738 virtual void accept( Visitor & v ) override { v.visit( this ); } 739 virtual void accept( Visitor & v ) const override { v.visit( this ); } 740 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 741 741 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 742 742 }; … … 746 746 GlobalScopeType(); 747 747 748 virtual GlobalScopeType * clone() const override { return new GlobalScopeType( *this ); }749 virtual void accept( Visitor & v ) override { v.visit( this ); } 750 virtual void accept( Visitor & v ) const override { v.visit( this ); } 751 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); }748 virtual GlobalScopeType * clone() const override { return new GlobalScopeType( *this ); } 749 virtual void accept( Visitor & v ) override { v.visit( this ); } 750 virtual void accept( Visitor & v ) const override { v.visit( this ); } 751 virtual Type * acceptMutator( Mutator & m ) override { return m.mutate( this ); } 752 752 virtual void print( std::ostream & os, Indenter indent = {} ) const override; 753 753 }; -
src/Validate/Autogen.cpp
r2ed94a9 rb110bcc 39 39 #include "InitTweak/GenInit.h" // for fixReturnStatements 40 40 #include "InitTweak/InitTweak.h" // for isAssignment, isCopyConstructor 41 #include "SymTab/GenImplicitCall.hpp" // for genImplicitCall 41 42 #include "SymTab/Mangler.h" // for Mangler 42 43 #include "CompilationState.h" … … 423 424 for ( unsigned int index = 0 ; index < fields ; ++index ) { 424 425 auto member = aggr->members[index].strict_as<ast::DeclWithType>(); 425 if ( SymTab::isUnnamedBitfield(426 if ( ast::isUnnamedBitfield( 426 427 dynamic_cast<const ast::ObjectDecl *>( member ) ) ) { 427 428 if ( index == fields - 1 ) { … … 599 600 // Not sure why it could be null. 600 601 // Don't make a function for a parameter that is an unnamed bitfield. 601 if ( nullptr == field || SymTab::isUnnamedBitfield( field ) ) {602 if ( nullptr == field || ast::isUnnamedBitfield( field ) ) { 602 603 continue; 603 604 // Matching Parameter: Initialize the field by copy. -
src/Validate/FixQualifiedTypes.cpp
r2ed94a9 rb110bcc 16 16 #include "Validate/FixQualifiedTypes.hpp" 17 17 18 #include "AST/LinkageSpec.hpp" // for Linkage 18 19 #include "AST/Pass.hpp" 19 20 #include "AST/TranslationUnit.hpp" 21 #include "Common/ToString.hpp" // for toString 22 #include "SymTab/Mangler.h" // for Mangler 20 23 #include "Validate/NoIdSymbolTable.hpp" 21 #include "SymTab/Mangler.h" // for Mangler22 #include "AST/LinkageSpec.hpp" // for Linkage23 24 24 25 namespace Validate { -
src/Validate/ForallPointerDecay.cpp
r2ed94a9 rb110bcc 22 22 #include "CodeGen/OperatorTable.h" 23 23 #include "Common/CodeLocation.h" 24 #include "Common/ToString.hpp" 24 25 #include "SymTab/FixFunction.h" 25 26 -
src/Validate/HandleAttributes.cc
r2ed94a9 rb110bcc 17 17 18 18 #include "CompilationState.h" 19 #include "Common/Eval.h" 19 20 #include "Common/PassVisitor.h" 21 #include "Common/ToString.hpp" 20 22 #include "Common/SemanticError.h" 21 23 #include "ResolvExpr/Resolver.h" -
src/Validate/HoistStruct.cpp
r2ed94a9 rb110bcc 16 16 #include "Validate/HoistStruct.hpp" 17 17 18 #include <sstream> 19 18 20 #include "AST/Pass.hpp" 19 21 #include "AST/TranslationUnit.hpp" 20 #include "Common/utility.h"21 22 22 23 namespace Validate { -
src/Virtual/module.mk
r2ed94a9 rb110bcc 19 19 Virtual/ExpandCasts.h \ 20 20 Virtual/Tables.cc \ 21 Virtual/Tables.h 21 Virtual/Tables.h \ 22 Virtual/VirtualDtor.cpp \ 23 Virtual/VirtualDtor.hpp -
src/include/cassert
r2ed94a9 rb110bcc 20 20 #include_next <cassert> 21 21 22 #include <string> 23 24 template < typename ... Params > 25 std::string toString( const Params & ... params ); 22 #include "Common/ToString.hpp" 26 23 27 24 #ifdef NDEBUG -
src/main.cc
r2ed94a9 rb110bcc 9 9 // Author : Peter Buhr and Rob Schluntz 10 10 // Created On : Fri May 15 23:12:02 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Wed Oct 5 12:06:00 202213 // Update Count : 6 7911 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Apr 10 21:12:17 2023 13 // Update Count : 682 14 14 // 15 15 … … 32 32 33 33 #include "AST/Convert.hpp" 34 #include "AST/Util.hpp" // for checkInvariants 34 35 #include "CompilationState.h" 35 36 #include "../config.h" // for CFA_LIBDIR … … 40 41 #include "CodeTools/TrackLoc.h" // for fillLocations 41 42 #include "Common/CodeLocationTools.hpp" // for forceFillCodeLocations 42 #include "Common/CompilerError.h" // for CompilerError43 43 #include "Common/DeclStats.hpp" // for printDeclStats 44 44 #include "Common/ResolvProtoDump.hpp" // for dumpAsResolverProto 45 45 #include "Common/Stats.h" // for Stats 46 #include "Common/UnimplementedError.h" // for UnimplementedError47 46 #include "Common/utility.h" // for deleteAll, filter, printAll 48 47 #include "Concurrency/Actors.hpp" // for implementActors … … 84 83 #include "Validate/VerifyCtorDtorAssign.hpp" // for verifyCtorDtorAssign 85 84 #include "Virtual/ExpandCasts.h" // for expandCasts 85 #include "Virtual/VirtualDtor.hpp" // for implementVirtDtors 86 86 87 87 static void NewPass( const char * const name ) { … … 102 102 } 103 103 104 #define PASS( name, pass ) \ 104 // Helpers for checkInvariant: 105 void checkInvariants( std::list< Declaration * > & ) {} 106 using ast::checkInvariants; 107 108 #define PASS( name, pass, unit, ... ) \ 105 109 if ( errorp ) { cerr << name << endl; } \ 106 110 NewPass(name); \ 107 111 Stats::Time::StartBlock(name); \ 108 pass; \ 109 Stats::Time::StopBlock(); 112 pass(unit,##__VA_ARGS__); \ 113 Stats::Time::StopBlock(); \ 114 if ( invariant ) { \ 115 checkInvariants(unit); \ 116 } 117 118 #define DUMP( cond, unit ) \ 119 if ( cond ) { \ 120 dump(unit); \ 121 return EXIT_SUCCESS; \ 122 } 110 123 111 124 static bool waiting_for_gdb = false; // flag to set cfa-cpp to wait for gdb on start … … 274 287 FILE * gcc_builtins = fopen( (PreludeDirector + "/gcc-builtins.cf").c_str(), "r" ); 275 288 assertf( gcc_builtins, "cannot open gcc-builtins.cf\n" ); 276 parse( gcc_builtins, LinkageSpec::Compiler );289 parse( gcc_builtins, ast::Linkage::Compiler ); 277 290 278 291 // read the extra prelude in, if not generating the cfa library 279 292 FILE * extras = fopen( (PreludeDirector + "/extras.cf").c_str(), "r" ); 280 293 assertf( extras, "cannot open extras.cf\n" ); 281 parse( extras, LinkageSpec::BuiltinC );294 parse( extras, ast::Linkage::BuiltinC ); 282 295 283 296 if ( ! libcfap ) { … … 285 298 FILE * prelude = fopen( (PreludeDirector + "/prelude.cfa").c_str(), "r" ); 286 299 assertf( prelude, "cannot open prelude.cfa\n" ); 287 parse( prelude, LinkageSpec::Intrinsic );300 parse( prelude, ast::Linkage::Intrinsic ); 288 301 289 302 // Read to cfa builtins, if not generating the cfa library 290 303 FILE * builtins = fopen( (PreludeDirector + "/builtins.cf").c_str(), "r" ); 291 304 assertf( builtins, "cannot open builtins.cf\n" ); 292 parse( builtins, LinkageSpec::BuiltinCFA );293 } // if 294 } // if 295 296 parse( input, libcfap ? LinkageSpec::Intrinsic : LinkageSpec::Cforall, yydebug );305 parse( builtins, ast::Linkage::BuiltinCFA ); 306 } // if 307 } // if 308 309 parse( input, libcfap ? ast::Linkage::Intrinsic : ast::Linkage::Cforall, yydebug ); 297 310 298 311 transUnit = buildUnit(); 299 312 300 if ( astp ) { 301 dump( std::move( transUnit ) ); 302 return EXIT_SUCCESS; 303 } // if 313 DUMP( astp, std::move( transUnit ) ); 304 314 305 315 Stats::Time::StopBlock(); … … 310 320 } 311 321 312 PASS( "Hoist Type Decls", Validate::hoistTypeDecls( transUnit ) ); 313 // Hoist Type Decls pulls some declarations out of contexts where 314 // locations are not tracked. Perhaps they should be, but for now 315 // the full fill solves it. 316 forceFillCodeLocations( transUnit ); 317 318 PASS( "Translate Exception Declarations", ControlStruct::translateExcept( transUnit ) ); 319 if ( exdeclp ) { 320 dump( std::move( transUnit ) ); 321 return EXIT_SUCCESS; 322 } 323 324 PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign( transUnit ) ); 325 PASS( "Replace Typedefs", Validate::replaceTypedef( transUnit ) ); 326 PASS( "Fix Return Types", Validate::fixReturnTypes( transUnit ) ); 327 PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers( transUnit ) ); 328 329 PASS( "Link Reference To Types", Validate::linkReferenceToTypes( transUnit ) ); 330 331 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes( transUnit ) ); 332 PASS( "Hoist Struct", Validate::hoistStruct( transUnit ) ); 333 PASS( "Eliminate Typedef", Validate::eliminateTypedef( transUnit ) ); 334 PASS( "Validate Generic Parameters", Validate::fillGenericParameters( transUnit ) ); 335 PASS( "Translate Dimensions", Validate::translateDimensionParameters( transUnit ) ); 336 PASS( "Check Function Returns", Validate::checkReturnStatements( transUnit ) ); 337 PASS( "Fix Return Statements", InitTweak::fixReturnStatements( transUnit ) ); 338 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) ); 339 PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) ); 340 PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls( transUnit ) ); 341 342 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) ); 343 344 PASS( "Implement Actors", Concurrency::implementActors( transUnit ) ); 345 346 PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) ); 347 PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) ); 348 PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) ); 349 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) ); 350 PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) ); 351 PASS( "Fix Label Address", Validate::fixLabelAddresses( transUnit ) ); 322 PASS( "Hoist Type Decls", Validate::hoistTypeDecls, transUnit ); 323 324 PASS( "Translate Exception Declarations", ControlStruct::translateExcept, transUnit ); 325 DUMP( exdeclp, std::move( transUnit ) ); 326 PASS( "Verify Ctor, Dtor & Assign", Validate::verifyCtorDtorAssign, transUnit ); 327 PASS( "Replace Typedefs", Validate::replaceTypedef, transUnit ); 328 PASS( "Fix Return Types", Validate::fixReturnTypes, transUnit ); 329 PASS( "Enum and Pointer Decay", Validate::decayEnumsAndPointers, transUnit ); 330 331 PASS( "Link Reference To Types", Validate::linkReferenceToTypes, transUnit ); 332 333 PASS( "Fix Qualified Types", Validate::fixQualifiedTypes, transUnit ); 334 PASS( "Hoist Struct", Validate::hoistStruct, transUnit ); 335 PASS( "Eliminate Typedef", Validate::eliminateTypedef, transUnit ); 336 PASS( "Validate Generic Parameters", Validate::fillGenericParameters, transUnit ); 337 PASS( "Translate Dimensions", Validate::translateDimensionParameters, transUnit ); 338 PASS( "Check Function Returns", Validate::checkReturnStatements, transUnit ); 339 PASS( "Fix Return Statements", InitTweak::fixReturnStatements, transUnit ); 340 PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords, transUnit ); 341 PASS( "Forall Pointer Decay", Validate::decayForallPointers, transUnit ); 342 PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls, transUnit ); 343 344 PASS( "Generate Autogen Routines", Validate::autogenerateRoutines, transUnit ); 345 346 PASS( "Implement Actors", Concurrency::implementActors, transUnit ); 347 PASS( "Implement Virtual Destructors", Virtual::implementVirtDtors, transUnit ); 348 PASS( "Implement Mutex", Concurrency::implementMutex, transUnit ); 349 PASS( "Implement Thread Start", Concurrency::implementThreadStarter, transUnit ); 350 PASS( "Compound Literal", Validate::handleCompoundLiterals, transUnit ); 351 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer, transUnit ); 352 PASS( "Find Global Decls", Validate::findGlobalDecls, transUnit ); 353 PASS( "Fix Label Address", Validate::fixLabelAddresses, transUnit ); 352 354 353 355 if ( symtabp ) { … … 360 362 } // if 361 363 362 if ( validp ) { 363 dump( std::move( transUnit ) ); 364 return EXIT_SUCCESS; 365 } // if 366 367 PASS( "Translate Throws", ControlStruct::translateThrows( transUnit ) ); 368 PASS( "Fix Labels", ControlStruct::fixLabels( transUnit ) ); 369 PASS( "Fix Names", CodeGen::fixNames( transUnit ) ); 370 PASS( "Gen Init", InitTweak::genInit( transUnit ) ); 371 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples( transUnit ) ); 364 DUMP( validp, std::move( transUnit ) ); 365 366 PASS( "Translate Throws", ControlStruct::translateThrows, transUnit ); 367 PASS( "Fix Labels", ControlStruct::fixLabels, transUnit ); 368 PASS( "Fix Names", CodeGen::fixNames, transUnit ); 369 PASS( "Gen Init", InitTweak::genInit, transUnit ); 370 PASS( "Expand Member Tuples" , Tuples::expandMemberTuples, transUnit ); 372 371 373 372 if ( libcfap ) { … … 381 380 } // if 382 381 383 if ( bresolvep ) { 384 dump( std::move( transUnit ) ); 385 return EXIT_SUCCESS; 386 } // if 382 DUMP( bresolvep, std::move( transUnit ) ); 387 383 388 384 if ( resolvprotop ) { … … 391 387 } // if 392 388 393 PASS( "Resolve", ResolvExpr::resolve( transUnit ) ); 394 if ( exprp ) { 395 dump( std::move( transUnit ) ); 396 return EXIT_SUCCESS; 397 } // if 398 399 forceFillCodeLocations( transUnit ); 400 401 PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary())); 389 PASS( "Resolve", ResolvExpr::resolve, transUnit ); 390 DUMP( exprp, std::move( transUnit ) ); 391 392 PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() ); 402 393 403 394 // fix ObjectDecl - replaces ConstructorInit nodes 404 if ( ctorinitp ) { 405 dump( std::move( transUnit ) ); 406 return EXIT_SUCCESS; 407 } // if 395 DUMP( ctorinitp, std::move( transUnit ) ); 408 396 409 397 // Currently not working due to unresolved issues with UniqueExpr 410 PASS( "Expand Unique Expr", Tuples::expandUniqueExpr ( transUnit )); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused411 412 PASS( "Translate Tries", ControlStruct::translateTries ( transUnit ));413 PASS( "Gen Waitfor", Concurrency::generateWaitFor ( transUnit ));398 PASS( "Expand Unique Expr", Tuples::expandUniqueExpr, transUnit ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused 399 400 PASS( "Translate Tries", ControlStruct::translateTries, transUnit ); 401 PASS( "Gen Waitfor", Concurrency::generateWaitFor, transUnit ); 414 402 415 403 // Needs to happen before tuple types are expanded. 416 PASS( "Convert Specializations", GenPoly::convertSpecializations( transUnit ) ); 417 418 PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) ); 419 420 if ( tuplep ) { 421 dump( std::move( transUnit ) ); 422 return EXIT_SUCCESS; 423 } // if 404 PASS( "Convert Specializations", GenPoly::convertSpecializations, transUnit ); 405 406 PASS( "Expand Tuples", Tuples::expandTuples, transUnit ); 407 DUMP( tuplep, std::move( transUnit ) ); 424 408 425 409 // Must come after Translate Tries. 426 PASS( "Virtual Expand Casts", Virtual::expandCasts( transUnit ) ); 427 428 PASS( "Instantiate Generics", GenPoly::instantiateGeneric( transUnit ) ); 429 if ( genericsp ) { 430 dump( std::move( transUnit ) ); 431 return EXIT_SUCCESS; 432 } // if 433 434 PASS( "Convert L-Value", GenPoly::convertLvalue( transUnit ) ); 410 PASS( "Virtual Expand Casts", Virtual::expandCasts, transUnit ); 411 412 PASS( "Instantiate Generics", GenPoly::instantiateGeneric, transUnit ); 413 DUMP( genericsp, std::move( transUnit ) ); 414 415 PASS( "Convert L-Value", GenPoly::convertLvalue, transUnit ); 435 416 436 417 translationUnit = convert( std::move( transUnit ) ); 437 418 438 if ( bboxp ) { 439 dump( translationUnit ); 440 return EXIT_SUCCESS; 441 } // if 442 PASS( "Box", GenPoly::box( translationUnit ) ); 443 444 PASS( "Link-Once", CodeGen::translateLinkOnce( translationUnit ) ); 419 DUMP( bboxp, translationUnit ); 420 PASS( "Box", GenPoly::box, translationUnit ); 421 422 PASS( "Link-Once", CodeGen::translateLinkOnce, translationUnit ); 445 423 446 424 // Code has been lowered to C, now we can start generation. 447 425 448 if ( bcodegenp ) { 449 dump( translationUnit ); 450 return EXIT_SUCCESS; 451 } // if 426 DUMP( bcodegenp, translationUnit ); 452 427 453 428 if ( optind < argc ) { // any commands after the flags and input file ? => output file name … … 456 431 457 432 CodeTools::fillLocations( translationUnit ); 458 PASS( "Code Gen", CodeGen::generate ( translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ));433 PASS( "Code Gen", CodeGen::generate, translationUnit, *output, ! genproto, prettycodegenp, true, linemarks ); 459 434 460 435 CodeGen::FixMain::fix( translationUnit, *output, … … 476 451 } // if 477 452 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 453 if ( output != &cout ) { 492 454 delete output; … … 517 479 518 480 519 static const char optstring[] = ":c:gh lLmNnpdP:S:twW:D:";481 static const char optstring[] = ":c:ghilLmNnpdP:S:twW:D:"; 520 482 521 483 enum { PreludeDir = 128 }; … … 524 486 { "gdb", no_argument, nullptr, 'g' }, 525 487 { "help", no_argument, nullptr, 'h' }, 488 { "invariant", no_argument, nullptr, 'i' }, 526 489 { "libcfa", no_argument, nullptr, 'l' }, 527 490 { "linemarks", no_argument, nullptr, 'L' }, 528 { "no-main", no_argument, 0, 'm' },491 { "no-main", no_argument, nullptr, 'm' }, 529 492 { "no-linemarks", no_argument, nullptr, 'N' }, 530 493 { "no-prelude", no_argument, nullptr, 'n' }, … … 545 508 "wait for gdb to attach", // -g 546 509 "print translator help message", // -h 510 "invariant checking during AST passes", // -i 547 511 "generate libcfa.c", // -l 548 512 "generate line marks", // -L … … 638 602 usage( argv ); // no return 639 603 break; 604 case 'i': // invariant checking 605 invariant = true; 606 break; 640 607 case 'l': // generate libcfa.c 641 608 libcfap = true;
Note:
See TracChangeset
for help on using the changeset viewer.