- Timestamp:
- Aug 13, 2022, 1:30:37 PM (3 years ago)
- Branches:
- ADT, ast-experimental, master, pthread-emulation
- Children:
- 3f1059e
- Parents:
- 62c5a55 (diff), 082af5b (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:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Common/Eval.cc
r62c5a55 r181036c 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 1 08:41:03202213 // Update Count : 11 712 // Last Modified On : Sat Aug 6 12:11:59 2022 13 // Update Count : 119 14 14 // 15 15 … … 217 217 value = arg1.first * arg2.first; 218 218 } else if (fname == "?/?") { 219 value = arg1.first / arg2.first;219 if ( arg2.first ) value = arg1.first / arg2.first; 220 220 } else if (fname == "?%?") { 221 value = arg1.first % arg2.first;221 if ( arg2.first ) value = arg1.first % arg2.first; 222 222 } else if (fname == "?<<?") { 223 223 value = arg1.first << arg2.first; -
src/Common/ScopedMap.h
r62c5a55 r181036c 10 10 // Created On : Wed Dec 2 11:37:00 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon May 21 15:22:40 201813 // Update Count : 312 // Last Modified On : Tue Feb 15 08:41:28 2022 13 // Update Count : 5 14 14 // 15 15 … … 36 36 37 37 template<typename N> 38 Scope(N && n) : map(), note(std::forward<N>(n)) {}38 Scope(N && n) : map(), note(std::forward<N>(n)) {} 39 39 40 40 Scope() = default; 41 Scope(const Scope &) = default;42 Scope(Scope &&) = default;43 Scope & operator= (const Scope&) = default;44 Scope & operator= (Scope&&) = default;41 Scope(const Scope &) = default; 42 Scope(Scope &&) = default; 43 Scope & operator= (const Scope &) = default; 44 Scope & operator= (Scope &&) = default; 45 45 }; 46 46 typedef std::vector< Scope > ScopeList; … … 58 58 typedef typename MapType::const_pointer const_pointer; 59 59 60 class iterator : public std::iterator< std::bidirectional_iterator_tag, 61 value_type > { 60 class iterator : public std::iterator< std::bidirectional_iterator_tag, value_type > { 62 61 friend class ScopedMap; 63 62 friend class const_iterator; … … 72 71 73 72 /// Increments on invalid 74 iterator & next_valid() {73 iterator & next_valid() { 75 74 if ( ! is_valid() ) { ++(*this); } 76 75 return *this; … … 78 77 79 78 /// Decrements on invalid 80 iterator & prev_valid() {79 iterator & prev_valid() { 81 80 if ( ! is_valid() ) { --(*this); } 82 81 return *this; 83 82 } 84 83 85 iterator(scope_list & _scopes, const wrapped_iterator &_it, size_type inLevel)84 iterator(scope_list & _scopes, const wrapped_iterator & _it, size_type inLevel) 86 85 : scopes(&_scopes), it(_it), level(inLevel) {} 87 86 public: 88 iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}89 iterator & operator= (const iterator &that) {87 iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {} 88 iterator & operator= (const iterator & that) { 90 89 scopes = that.scopes; level = that.level; it = that.it; 91 90 return *this; … … 95 94 pointer operator-> () const { return it.operator->(); } 96 95 97 iterator & operator++ () {96 iterator & operator++ () { 98 97 if ( it == (*scopes)[level].map.end() ) { 99 98 if ( level == 0 ) return *this; … … 107 106 iterator operator++ (int) { iterator tmp = *this; ++(*this); return tmp; } 108 107 109 iterator & operator-- () {108 iterator & operator-- () { 110 109 // may fail if this is the begin iterator; allowed by STL spec 111 110 if ( it == (*scopes)[level].map.begin() ) { … … 118 117 iterator operator-- (int) { iterator tmp = *this; --(*this); return tmp; } 119 118 120 bool operator== (const iterator & that) const {119 bool operator== (const iterator & that) const { 121 120 return scopes == that.scopes && level == that.level && it == that.it; 122 121 } 123 bool operator!= (const iterator & that) const { return !( *this == that ); }122 bool operator!= (const iterator & that) const { return !( *this == that ); } 124 123 125 124 size_type get_level() const { return level; } 126 125 127 Note & get_note() { return (*scopes)[level].note; }128 const Note & get_note() const { return (*scopes)[level].note; }126 Note & get_note() { return (*scopes)[level].note; } 127 const Note & get_note() const { return (*scopes)[level].note; } 129 128 130 129 private: … … 148 147 149 148 /// Increments on invalid 150 const_iterator & next_valid() {149 const_iterator & next_valid() { 151 150 if ( ! is_valid() ) { ++(*this); } 152 151 return *this; … … 154 153 155 154 /// Decrements on invalid 156 const_iterator & prev_valid() {155 const_iterator & prev_valid() { 157 156 if ( ! is_valid() ) { --(*this); } 158 157 return *this; 159 158 } 160 159 161 const_iterator(scope_list const & _scopes, const wrapped_const_iterator &_it, size_type inLevel)160 const_iterator(scope_list const & _scopes, const wrapped_const_iterator & _it, size_type inLevel) 162 161 : scopes(&_scopes), it(_it), level(inLevel) {} 163 162 public: 164 const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}165 const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {}166 const_iterator & operator= (const iterator &that) {163 const_iterator(const iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {} 164 const_iterator(const const_iterator & that) : scopes(that.scopes), it(that.it), level(that.level) {} 165 const_iterator & operator= (const iterator & that) { 167 166 scopes = that.scopes; level = that.level; it = that.it; 168 167 return *this; 169 168 } 170 const_iterator & operator= (const const_iterator &that) {169 const_iterator & operator= (const const_iterator & that) { 171 170 scopes = that.scopes; level = that.level; it = that.it; 172 171 return *this; … … 176 175 const_pointer operator-> () { return it.operator->(); } 177 176 178 const_iterator & operator++ () {177 const_iterator & operator++ () { 179 178 if ( it == (*scopes)[level].map.end() ) { 180 179 if ( level == 0 ) return *this; … … 188 187 const_iterator operator++ (int) { const_iterator tmp = *this; ++(*this); return tmp; } 189 188 190 const_iterator & operator-- () {189 const_iterator & operator-- () { 191 190 // may fail if this is the begin iterator; allowed by STL spec 192 191 if ( it == (*scopes)[level].map.begin() ) { … … 199 198 const_iterator operator-- (int) { const_iterator tmp = *this; --(*this); return tmp; } 200 199 201 bool operator== (const const_iterator & that) const {200 bool operator== (const const_iterator & that) const { 202 201 return scopes == that.scopes && level == that.level && it == that.it; 203 202 } 204 bool operator!= (const const_iterator & that) const { return !( *this == that ); }203 bool operator!= (const const_iterator & that) const { return !( *this == that ); } 205 204 206 205 size_type get_level() const { return level; } 207 206 208 const Note & get_note() const { return (*scopes)[level].note; }207 const Note & get_note() const { return (*scopes)[level].note; } 209 208 210 209 private: … … 221 220 // Starts a new scope with the given note 222 221 template<typename N> 223 void beginScope( N && n ) {222 void beginScope( N && n ) { 224 223 scopes.emplace_back( std::forward<N>(n) ); 225 224 } … … 236 235 /// Constructs with a given note on the outermost scope 237 236 template<typename N> 238 ScopedMap( N && n ) : scopes() { beginScope(std::forward<N>(n)); }237 ScopedMap( N && n ) : scopes() { beginScope(std::forward<N>(n)); } 239 238 240 239 iterator begin() { return iterator(scopes, scopes.back().map.begin(), currentScope()).next_valid(); } … … 249 248 250 249 /// Gets the note at the given scope 251 Note & getNote() { return scopes.back().note; }252 const Note & getNote() const { return scopes.back().note; }253 Note & getNote( size_type i ) { return scopes[i].note; }254 const Note & getNote( size_type i ) const { return scopes[i].note; }250 Note & getNote() { return scopes.back().note; } 251 const Note & getNote() const { return scopes.back().note; } 252 Note & getNote( size_type i ) { return scopes[i].note; } 253 const Note & getNote( size_type i ) const { return scopes[i].note; } 255 254 256 255 /// Finds the given key in the outermost scope it occurs; returns end() for none such 257 iterator find( const Key & key ) {256 iterator find( const Key & key ) { 258 257 for ( size_type i = scopes.size() - 1; ; --i ) { 259 258 typename MapType::iterator val = scopes[i].map.find( key ); … … 263 262 return end(); 264 263 } 265 const_iterator find( const Key & key ) const {264 const_iterator find( const Key & key ) const { 266 265 return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->find( key ) ); 267 266 } 268 267 269 268 /// Finds the given key in the provided scope; returns end() for none such 270 iterator findAt( size_type scope, const Key & key ) {269 iterator findAt( size_type scope, const Key & key ) { 271 270 typename MapType::iterator val = scopes[scope].map.find( key ); 272 271 if ( val != scopes[scope].map.end() ) return iterator( scopes, val, scope ); 273 272 return end(); 274 273 } 275 const_iterator findAt( size_type scope, const Key & key ) const {274 const_iterator findAt( size_type scope, const Key & key ) const { 276 275 return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findAt( scope, key ) ); 277 276 } 278 277 279 278 /// Finds the given key in the outermost scope inside the given scope where it occurs 280 iterator findNext( const_iterator & it, const Key &key ) {279 iterator findNext( const_iterator & it, const Key & key ) { 281 280 if ( it.level == 0 ) return end(); 282 281 for ( size_type i = it.level - 1; ; --i ) { … … 287 286 return end(); 288 287 } 289 const_iterator findNext( const_iterator & it, const Key &key ) const {288 const_iterator findNext( const_iterator & it, const Key & key ) const { 290 289 return const_iterator( const_cast< ScopedMap< Key, Value, Note >* >(this)->findNext( it, key ) ); 291 290 } … … 293 292 /// Inserts the given key-value pair into the outermost scope 294 293 template< typename value_type_t > 295 std::pair< iterator, bool > insert( value_type_t && value ) {294 std::pair< iterator, bool > insert( value_type_t && value ) { 296 295 std::pair< typename MapType::iterator, bool > res = scopes.back().map.insert( std::forward<value_type_t>( value ) ); 297 296 return std::make_pair( iterator(scopes, std::move( res.first ), scopes.size()-1), std::move( res.second ) ); … … 299 298 300 299 template< typename value_type_t > 301 std::pair< iterator, bool > insert( iterator at, value_type_t && value ) {302 MapType & scope = (*at.scopes)[ at.level ].map;300 std::pair< iterator, bool > insert( iterator at, value_type_t && value ) { 301 MapType & scope = (*at.scopes)[ at.level ].map; 303 302 std::pair< typename MapType::iterator, bool > res = scope.insert( std::forward<value_type_t>( value ) ); 304 303 return std::make_pair( iterator(scopes, std::move( res.first ), at.level), std::move( res.second ) ); … … 306 305 307 306 template< typename value_t > 308 std::pair< iterator, bool > insert( const Key & key, value_t&& value ) { return insert( std::make_pair( key, std::forward<value_t>( value ) ) ); }307 std::pair< iterator, bool > insert( const Key & key, value_t && value ) { return insert( std::make_pair( key, std::forward<value_t>( value ) ) ); } 309 308 310 309 template< typename value_type_t > 311 std::pair< iterator, bool > insertAt( size_type scope, value_type_t && value ) {310 std::pair< iterator, bool > insertAt( size_type scope, value_type_t && value ) { 312 311 std::pair< typename MapType::iterator, bool > res = scopes.at(scope).map.insert( std::forward<value_type_t>( value ) ); 313 312 return std::make_pair( iterator(scopes, std::move( res.first ), scope), std::move( res.second ) ); … … 315 314 316 315 template< typename value_t > 317 std::pair< iterator, bool > insertAt( size_type scope, const Key & key, value_t&& value ) {316 std::pair< iterator, bool > insertAt( size_type scope, const Key & key, value_t && value ) { 318 317 return insertAt( scope, std::make_pair( key, std::forward<value_t>( value ) ) ); 319 318 } 320 319 321 Value & operator[] ( const Key &key ) {320 Value & operator[] ( const Key & key ) { 322 321 iterator slot = find( key ); 323 322 if ( slot != end() ) return slot->second; … … 326 325 327 326 iterator erase( iterator pos ) { 328 MapType & scope = (*pos.scopes)[ pos.level ].map;329 const typename iterator::wrapped_iterator & new_it = scope.erase( pos.it );327 MapType & scope = (*pos.scopes)[ pos.level ].map; 328 const typename iterator::wrapped_iterator & new_it = scope.erase( pos.it ); 330 329 iterator it( *pos.scopes, new_it, pos.level ); 331 330 return it.next_valid(); 332 331 } 333 332 334 size_type count( const Key & key ) const {333 size_type count( const Key & key ) const { 335 334 size_type c = 0; 336 335 auto it = find( key ); … … 344 343 return c; 345 344 } 346 347 345 }; 348 346 -
src/Parser/DeclarationNode.cc
r62c5a55 r181036c 10 10 // Created On : Sat May 16 12:34:05 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 14 17:36:57 202113 // Update Count : 11 5412 // Last Modified On : Mon Aug 8 17:07:00 2022 13 // Update Count : 1185 14 14 // 15 15 … … 128 128 if ( name ) { 129 129 os << *name << ": "; 130 } else {131 os << "unnamed: ";132 130 } // if 133 131 … … 154 152 initializer->printOneLine( os ); 155 153 os << " maybe constructed? " << initializer->get_maybeConstructed(); 156 157 } // if 154 } // if 155 156 for ( Attribute * attr: reverseIterate( attributes ) ) { 157 os << string( indent + 2, ' ' ) << "attr " << attr->name.c_str(); 158 } // for 158 159 159 160 os << endl; … … 243 244 newnode->type = new TypeData( TypeData::Aggregate ); 244 245 newnode->type->aggregate.kind = kind; 245 newnode->type->aggregate.name = 246 newnode->type->aggregate.name = name == nullptr ? new string( DeclarationNode::anonymous.newName() ) : name; 246 247 newnode->type->aggregate.actuals = actuals; 247 248 newnode->type->aggregate.fields = fields; … … 518 519 storageClasses |= q->storageClasses; 519 520 520 for ( Attribute * attr: reverseIterate( q->attributes ) ) {521 for ( Attribute * attr: reverseIterate( q->attributes ) ) { 521 522 attributes.push_front( attr->clone() ); 522 523 } // for … … 683 684 } // if 684 685 delete o; 686 685 687 return this; 686 688 } -
src/Parser/TypeData.cc
r62c5a55 r181036c 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 15:12:51 2015 11 // Last Modified By : Henry Xue12 // Last Modified On : Tue Jul 20 04:10:50 202113 // Update Count : 67 311 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue May 10 22:36:52 2022 13 // Update Count : 677 14 14 // 15 15 … … 283 283 if ( signedness != DeclarationNode::NoSignedness ) os << DeclarationNode::signednessNames[ signedness ] << " "; 284 284 if ( length != DeclarationNode::NoLength ) os << DeclarationNode::lengthNames[ length ] << " "; 285 if ( complextype == DeclarationNode::NoComplexType ) { // basic type 286 assert( basictype != DeclarationNode::NoBasicType ); 287 os << DeclarationNode::basicTypeNames[ basictype ] << " "; 288 } else { // complex type 289 // handle double _Complex 290 if ( basictype != DeclarationNode::NoBasicType ) os << DeclarationNode::basicTypeNames[ basictype ] << " "; 291 os << DeclarationNode::complexTypeNames[ complextype ] << " "; 292 } // if 285 if ( complextype != DeclarationNode::NoComplexType ) os << DeclarationNode::complexTypeNames[ complextype ] << " "; 286 if ( basictype != DeclarationNode::NoBasicType ) os << DeclarationNode::basicTypeNames[ basictype ] << " "; 293 287 break; 294 288 case Pointer: … … 437 431 __attribute__((fallthrough)); 438 432 #endif 433 // FALL THROUGH 439 434 case Typeof: 440 435 os << "type-of expression "; … … 442 437 typeexpr->print( os, indent + 2 ); 443 438 } // if 439 break; 440 case Vtable: 441 os << "vtable"; 444 442 break; 445 443 case Builtin: -
src/Parser/TypeData.h
r62c5a55 r181036c 10 10 // Created On : Sat May 16 15:18:36 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 14 17:44:05 202113 // Update Count : 20 212 // Last Modified On : Tue May 10 22:18:49 2022 13 // Update Count : 203 14 14 // 15 15 … … 27 27 struct TypeData { 28 28 enum Kind { Basic, Pointer, Reference, Array, Function, Aggregate, AggregateInst, Enum, EnumConstant, Symbolic, 29 SymbolicInst, Tuple, Typeof, Basetypeof, Vtable, Builtin, GlobalScope, Qualified, Unknown };29 SymbolicInst, Tuple, Basetypeof, Typeof, Vtable, Builtin, GlobalScope, Qualified, Unknown }; 30 30 31 31 struct Aggregate_t { -
src/Parser/TypedefTable.cc
r62c5a55 r181036c 10 10 // Created On : Sat May 16 15:20:13 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed May 19 08:30:14 202113 // Update Count : 2 6212 // Last Modified On : Tue Feb 15 08:27:24 2022 13 // Update Count : 275 14 14 // 15 15 … … 18 18 #include <cassert> // for assert 19 19 #include <iostream> 20 using namespace std; 20 21 21 22 #if 0 … … 28 29 29 30 debugPrint( 30 static const char *kindName( int kind ) {31 switch ( kind ) {32 case IDENTIFIER: return "identifier";33 case TYPEDIMname: return "typedim";34 case TYPEDEFname: return "typedef";35 case TYPEGENname: return "typegen";36 default:37 cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl;38 abort();39 } // switch40 } // kindName41 ) 31 static const char *kindName( int kind ) { 32 switch ( kind ) { 33 case IDENTIFIER: return "identifier"; 34 case TYPEDIMname: return "typedim"; 35 case TYPEDEFname: return "typedef"; 36 case TYPEGENname: return "typegen"; 37 default: 38 cerr << "Error: cfa-cpp internal error, invalid kind of identifier" << endl; 39 abort(); 40 } // switch 41 } // kindName 42 ); 42 43 43 44 TypedefTable::~TypedefTable() { … … 80 81 81 82 void TypedefTable::addToScope( const string & identifier, int kind, const char * locn __attribute__((unused)) ) { 82 autoscope = kindTable.currentScope();83 KindTable::size_type scope = kindTable.currentScope(); 83 84 debugPrint( cerr << "Adding current at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << endl ); 84 85 kindTable.insertAt( scope, identifier, kind ); … … 86 87 87 88 void TypedefTable::addToEnclosingScope( const string & identifier, int kind, const char * locn __attribute__((unused)) ) { 88 autoscope = kindTable.currentScope() - 1 - kindTable.getNote( kindTable.currentScope() - 1 ).level;89 // autoscope = level - kindTable.getNote( kindTable.currentScope() - 1 ).level;89 KindTable::size_type scope = kindTable.currentScope() - 1 - kindTable.getNote( kindTable.currentScope() - 1 ).level; 90 // size_type scope = level - kindTable.getNote( kindTable.currentScope() - 1 ).level; 90 91 debugPrint( cerr << "Adding enclosing at " << locn << " " << identifier << " as " << kindName( kind ) << " scope " << scope << " level " << level << " note " << kindTable.getNote( kindTable.currentScope() - 1 ).level << endl ); 91 autoret = kindTable.insertAt( scope, identifier, kind );92 pair< KindTable::iterator, bool > ret = kindTable.insertAt( scope, identifier, kind ); 92 93 if ( ! ret.second ) ret.first->second = kind; // exists => update 93 94 } // TypedefTable::addToEnclosingScope -
src/Parser/parser.yy
r62c5a55 r181036c 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Fri Jul 1 15:35:08 202213 // Update Count : 5 40512 // Last Modified On : Fri Aug 12 07:59:58 2022 13 // Update Count : 5649 14 14 // 15 15 … … 58 58 59 59 // lex uses __null in a boolean context, it's fine. 60 #pragma GCC diagnostic ignored "-Wparentheses-equality"60 //#pragma GCC diagnostic ignored "-Wparentheses-equality" 61 61 62 62 extern DeclarationNode * parseTree; … … 197 197 } // fieldDecl 198 198 199 #define NEW_ZERO new ExpressionNode( build_constantInteger( *new string( "0" ) ) ) 200 #define NEW_ONE new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) 201 #define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right) 202 203 ForCtrl * forCtrl( DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 204 if ( index->initializer ) { 205 SemanticError( yylloc, "Direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." ); 206 } // if 207 if ( index->next ) { 208 SemanticError( yylloc, "Multiple loop indexes disallowed in for-loop declaration." ); 209 } // if 210 return new ForCtrl( index->addInitializer( new InitializerNode( start ) ), 211 // NULL comp/inc => leave blank 212 comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index->name ) ) ), comp ) ) : nullptr, 213 inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto 214 OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index->name ) ) ), inc ) ) : nullptr ); 215 } // forCtrl 216 199 217 ForCtrl * forCtrl( ExpressionNode * type, string * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 200 218 ConstantExpr * constant = dynamic_cast<ConstantExpr *>(type->expr.get()); … … 206 224 distAttr( DeclarationNode::newTypeof( type, true ), DeclarationNode::newName( index )->addInitializer( new InitializerNode( start ) ) ), 207 225 // NULL comp/inc => leave blank 208 comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index ) ) ), comp ) ) : 0,226 comp ? new ExpressionNode( build_binary_val( compop, new ExpressionNode( build_varref( new string( *index ) ) ), comp ) ) : nullptr, 209 227 inc ? new ExpressionNode( build_binary_val( compop == OperKinds::LThan || compop == OperKinds::LEThan ? // choose += or -= for upto/downto 210 OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index ) ) ), inc ) ) : 0);228 OperKinds::PlusAssn : OperKinds::MinusAssn, new ExpressionNode( build_varref( new string( *index ) ) ), inc ) ) : nullptr ); 211 229 } // forCtrl 212 230 … … 346 364 %type<ifctl> conditional_declaration 347 365 %type<fctl> for_control_expression for_control_expression_list 348 %type<compop> inclexcl366 %type<compop> updown updowneq downupdowneq 349 367 %type<en> subrange 350 368 %type<decl> asm_name_opt … … 1239 1257 iteration_statement: 1240 1258 WHILE '(' ')' statement %prec THEN // CFA => while ( 1 ) 1241 { $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) )), maybe_build_compound( $4 ) ) ); }1259 { $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) ); } 1242 1260 | WHILE '(' ')' statement ELSE statement // CFA 1243 1261 { 1244 $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) )), maybe_build_compound( $4 ) ) );1262 $$ = new StatementNode( build_while( new CondCtl( nullptr, NEW_ONE ), maybe_build_compound( $4 ) ) ); 1245 1263 SemanticWarning( yylloc, Warning::SuperfluousElse, "" ); 1246 1264 } … … 1250 1268 { $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); } 1251 1269 | DO statement WHILE '(' ')' ';' // CFA => do while( 1 ) 1252 { $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); }1270 { $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) ); } 1253 1271 | DO statement WHILE '(' ')' ELSE statement // CFA 1254 1272 { 1255 $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) );1273 $$ = new StatementNode( build_do_while( NEW_ONE, maybe_build_compound( $2 ) ) ); 1256 1274 SemanticWarning( yylloc, Warning::SuperfluousElse, "" ); 1257 1275 } … … 1305 1323 1306 1324 | comma_expression // CFA 1307 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), 1308 OperKinds::LThan, $1->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } 1309 | '=' comma_expression // CFA 1310 { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), 1311 OperKinds::LEThan, $2->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } 1312 | comma_expression inclexcl comma_expression // CFA 1313 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } 1314 | comma_expression inclexcl comma_expression '~' comma_expression // CFA 1315 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), $1->clone(), $2, $3, $5 ); } 1316 | comma_expression ';' // CFA 1317 { $$ = forCtrl( new ExpressionNode( build_constantInteger( *new string( "0u" ) ) ), $1, nullptr, OperKinds::LThan, nullptr, nullptr ); } 1325 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), NEW_ZERO, OperKinds::LThan, $1->clone(), NEW_ONE ); } 1326 | downupdowneq comma_expression // CFA 1327 { $$ = forCtrl( $2, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $1, NEW_ZERO, $2->clone() ), $1, UPDOWN( $1, $2->clone(), NEW_ZERO ), NEW_ONE ); } 1328 1329 | comma_expression updowneq comma_expression // CFA 1330 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), NEW_ONE ); } 1331 | '@' updowneq comma_expression // CFA 1332 { 1333 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1334 else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, NEW_ONE ); 1335 } 1336 | comma_expression updowneq '@' // CFA 1337 { 1338 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, "Missing comparison ('@') with an anonymous loop index is meaningless." ); $$ = nullptr; } 1339 else { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1340 } 1341 | comma_expression updowneq comma_expression '~' comma_expression // CFA 1342 { $$ = forCtrl( $1, new string( DeclarationNode::anonymous.newName() ), UPDOWN( $2, $1->clone(), $3 ), $2, UPDOWN( $2, $3->clone(), $1->clone() ), $5 ); } 1343 | '@' updowneq comma_expression '~' comma_expression // CFA 1344 { 1345 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1346 else $$ = forCtrl( $3, new string( DeclarationNode::anonymous.newName() ), $3->clone(), $2, nullptr, $5 ); 1347 } 1348 | comma_expression updowneq '@' '~' comma_expression // CFA 1349 { 1350 if ( $2 == OperKinds::LThan || $2 == OperKinds::LEThan ) { SemanticError( yylloc, "Missing comparison ('@') with an anonymous loop index is meaningless." ); $$ = nullptr; } 1351 else { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1352 } 1353 | comma_expression updowneq comma_expression '~' '@' // CFA, error 1354 { SemanticError( yylloc, "Missing increment ('@') with an anonymous loop index is meaningless." ); $$ = nullptr; } 1355 | '@' updowneq comma_expression '~' '@' // CFA, error 1356 { SemanticError( yylloc, "Missing loop fields ('@') with an anonymous loop index is meaningless." ); $$ = nullptr; } 1357 | comma_expression updowneq '@' '~' '@' // CFA, error 1358 { SemanticError( yylloc, "Missing loop fields ('@') with an anonymous loop index is meaningless." ); $$ = nullptr; } 1359 | '@' updowneq '@' '~' '@' // CFA, error 1360 { SemanticError( yylloc, "Missing loop fields ('@') with an anonymous loop index is meaningless." ); $$ = nullptr; } 1361 1318 1362 | comma_expression ';' comma_expression // CFA 1319 { $$ = forCtrl( $3, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), 1320 OperKinds::LThan, $3->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } 1321 | comma_expression ';' '=' comma_expression // CFA 1322 { $$ = forCtrl( $4, $1, new ExpressionNode( build_constantInteger( *new string( "0" ) ) ), 1323 OperKinds::LEThan, $4->clone(), new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } 1324 | comma_expression ';' comma_expression inclexcl comma_expression // CFA 1325 { $$ = forCtrl( $3, $1, $3->clone(), $4, $5, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } 1326 | comma_expression ';' comma_expression inclexcl comma_expression '~' comma_expression // CFA 1327 { $$ = forCtrl( $3, $1, $3->clone(), $4, $5, $7 ); } 1363 { $$ = forCtrl( $3, $1, NEW_ZERO, OperKinds::LThan, $3->clone(), NEW_ONE ); } 1364 | comma_expression ';' downupdowneq comma_expression // CFA 1365 { $$ = forCtrl( $4, $1, UPDOWN( $3, NEW_ZERO, $4->clone() ), $3, UPDOWN( $3, $4->clone(), NEW_ZERO ), NEW_ONE ); } 1366 1367 | comma_expression ';' comma_expression updowneq comma_expression // CFA 1368 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), NEW_ONE ); } 1369 | comma_expression ';' '@' updowneq comma_expression // CFA 1370 { 1371 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1372 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, NEW_ONE ); 1373 } 1374 | comma_expression ';' comma_expression updowneq '@' // CFA 1375 { 1376 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1377 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing comparison is meaningless. Use \"~\"." ); $$ = nullptr; } 1378 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, NEW_ONE ); 1379 } 1380 | comma_expression ';' '@' updowneq '@' // CFA, error 1381 { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1382 1383 | comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA 1384 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); } 1385 | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, error 1386 { 1387 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1388 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, $7 ); 1389 } 1390 | comma_expression ';' comma_expression updowneq '@' '~' comma_expression // CFA 1391 { 1392 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1393 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing comparison is meaningless. Use \"~\"." ); $$ = nullptr; } 1394 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, $7 ); 1395 } 1396 | comma_expression ';' comma_expression updowneq comma_expression '~' '@' // CFA 1397 { $$ = forCtrl( $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); } 1398 | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, error 1399 { 1400 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1401 else $$ = forCtrl( $5, $1, $5->clone(), $4, nullptr, nullptr ); 1402 } 1403 | comma_expression ';' comma_expression updowneq '@' '~' '@' // CFA 1404 { 1405 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1406 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing comparison is meaningless. Use \"~\"." ); $$ = nullptr; } 1407 else $$ = forCtrl( $3, $1, $3->clone(), $4, nullptr, nullptr ); 1408 } 1409 | comma_expression ';' '@' updowneq '@' '~' '@' // CFA 1410 { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1411 1412 | declaration comma_expression // CFA 1413 { $$ = forCtrl( $1, NEW_ZERO, OperKinds::LThan, $2, NEW_ONE ); } 1414 | declaration downupdowneq comma_expression // CFA 1415 { $$ = forCtrl( $1, UPDOWN( $2, NEW_ZERO, $3 ), $2, UPDOWN( $2, $3->clone(), NEW_ZERO ), NEW_ONE ); } 1416 1417 | declaration comma_expression updowneq comma_expression // CFA 1418 { $$ = forCtrl( $1, UPDOWN( $3, $2->clone(), $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), NEW_ONE ); } 1419 | declaration '@' updowneq comma_expression // CFA 1420 { 1421 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1422 else $$ = forCtrl( $1, $4, $3, nullptr, NEW_ONE ); 1423 } 1424 | declaration comma_expression updowneq '@' // CFA 1425 { 1426 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1427 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing comparison is meaningless. Use \"~\"." ); $$ = nullptr; } 1428 else $$ = forCtrl( $1, $2, $3, nullptr, NEW_ONE ); 1429 } 1430 1431 | declaration comma_expression updowneq comma_expression '~' comma_expression // CFA 1432 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), $6 ); } 1433 | declaration '@' updowneq comma_expression '~' comma_expression // CFA 1434 { 1435 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1436 else $$ = forCtrl( $1, $4, $3, nullptr, $6 ); 1437 } 1438 | declaration comma_expression updowneq '@' '~' comma_expression // CFA 1439 { 1440 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1441 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing comparison is meaningless. Use \"~\"." ); $$ = nullptr; } 1442 else $$ = forCtrl( $1, $2, $3, nullptr, $6 ); 1443 } 1444 | declaration comma_expression updowneq comma_expression '~' '@' // CFA 1445 { $$ = forCtrl( $1, UPDOWN( $3, $2, $4 ), $3, UPDOWN( $3, $4->clone(), $2->clone() ), nullptr ); } 1446 | declaration '@' updowneq comma_expression '~' '@' // CFA 1447 { 1448 if ( $3 == OperKinds::LThan || $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1449 else $$ = forCtrl( $1, $4, $3, nullptr, nullptr ); 1450 } 1451 | declaration comma_expression updowneq '@' '~' '@' // CFA 1452 { 1453 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1454 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "Equality with missing comparison is meaningless. Use \"~\"." ); $$ = nullptr; } 1455 else $$ = forCtrl( $1, $2, $3, nullptr, nullptr ); 1456 } 1457 | declaration '@' updowneq '@' '~' '@' // CFA, error 1458 { SemanticError( yylloc, "Missing start value so cannot compare." ); $$ = nullptr; } 1328 1459 1329 1460 | comma_expression ';' TYPEDEFname // CFA, array type 1330 1461 { 1331 SemanticError( yylloc, "Array interator is currently unimplemented." ); $$ = nullptr; 1332 $$ = forCtrl( new ExpressionNode( build_varref( $3 ) ), $1, nullptr, OperKinds::Range, nullptr, nullptr ); 1333 } 1334 1335 // There is a S/R conflicit if ~ and -~ are factored out. 1336 | comma_expression ';' comma_expression '~' '@' // CFA 1337 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::LThan, nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } 1338 | comma_expression ';' comma_expression ErangeDown '@' // CFA 1339 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::GThan, nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ); } 1340 | comma_expression ';' comma_expression '~' '@' '~' comma_expression // CFA 1341 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::LThan, nullptr, $7 ); } 1342 | comma_expression ';' comma_expression ErangeDown '@' '~' comma_expression // CFA 1343 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::GThan, nullptr, $7 ); } 1344 | comma_expression ';' comma_expression '~' '@' '~' '@' // CFA 1345 { $$ = forCtrl( $3, $1, $3->clone(), OperKinds::LThan, nullptr, nullptr ); } 1462 SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr; 1463 //$$ = forCtrl( new ExpressionNode( build_varref( $3 ) ), $1, nullptr, OperKinds::Range, nullptr, nullptr ); 1464 } 1465 | comma_expression ';' downupdowneq TYPEDEFname // CFA, array type 1466 { 1467 if ( $3 == OperKinds::LEThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, "All enumation ranges are equal (all values). Remove \"=~\"." ); $$ = nullptr; } 1468 SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr; 1469 } 1346 1470 ; 1347 1471 1348 inclexcl: 1472 downupdowneq: 1473 ErangeDown 1474 { $$ = OperKinds::GThan; } 1475 | ErangeUpEq 1476 { $$ = OperKinds::LEThan; } 1477 | ErangeDownEq 1478 { $$ = OperKinds::GEThan; } 1479 ; 1480 1481 updown: 1349 1482 '~' 1350 1483 { $$ = OperKinds::LThan; } 1484 | ErangeDown 1485 { $$ = OperKinds::GThan; } 1486 ; 1487 1488 updowneq: 1489 updown 1351 1490 | ErangeUpEq 1352 1491 { $$ = OperKinds::LEThan; } 1353 | ErangeDown1354 { $$ = OperKinds::GThan; }1355 1492 | ErangeDownEq 1356 1493 { $$ = OperKinds::GEThan; } … … 2395 2532 '{' enumerator_list comma_opt '}' 2396 2533 { $$ = DeclarationNode::newEnum( $3->name, $5, true )->addQualifiers( $2 ); } 2534 | ENUM '(' ')' attribute_list_opt '{' enumerator_list comma_opt '}' 2535 { SemanticError( yylloc, "Unvalued enumerated type is currently unimplemented." ); $$ = nullptr; } 2397 2536 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}' 2398 2537 { -
src/Virtual/ExpandCasts.cc
r62c5a55 r181036c 10 10 // Created On : Mon Jul 24 13:59:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jul 31 10:29:00 202013 // Update Count : 412 // Last Modified On : Thu Aug 11 12:06:00 2022 13 // Update Count : 5 14 14 // 15 15 … … 20 20 #include <string> // for string, allocator, operator==, ope... 21 21 22 #include "AST/Decl.hpp" 23 #include "AST/Expr.hpp" 24 #include "AST/Pass.hpp" 22 25 #include "Common/PassVisitor.h" // for PassVisitor 23 26 #include "Common/ScopedMap.h" // for ScopedMap … … 32 35 namespace Virtual { 33 36 34 static bool is_prefix( const std::string & prefix, const std::string& entire ) { 37 namespace { 38 39 bool is_prefix( const std::string & prefix, const std::string& entire ) { 35 40 size_t const p_size = prefix.size(); 36 41 return (p_size < entire.size() && prefix == entire.substr(0, p_size)); 37 42 } 38 43 39 staticbool is_type_id_object( const ObjectDecl * objectDecl ) {44 bool is_type_id_object( const ObjectDecl * objectDecl ) { 40 45 const std::string & objectName = objectDecl->name; 41 46 return is_prefix( "__cfatid_", objectName ); 47 } 48 49 bool is_type_id_object( const ast::ObjectDecl * decl ) { 50 return is_prefix( "__cfatid_", decl->name ); 42 51 } 43 52 … … 124 133 } 125 134 } 126 127 namespace {128 135 129 136 /// Better error locations for generated casts. … … 229 236 } 230 237 231 } // namespace232 233 238 Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) { 234 239 assertf( castExpr->result, "Virtual Cast target not found before expansion." ); … … 265 270 } 266 271 267 void expandCasts( std::list< Declaration * > & translationUnit ) { 268 PassVisitor<VirtualCastCore> translator; 269 mutateAll( translationUnit, translator ); 270 } 271 } 272 /// Better error locations for generated casts. 273 // TODO: Does the improved distribution of code locations make this unneeded? 274 CodeLocation castLocation( const ast::VirtualCastExpr * castExpr ) { 275 if ( castExpr->location.isSet() ) { 276 return castExpr->location; 277 } else if ( castExpr->arg->location.isSet() ) { 278 return castExpr->arg->location; 279 } else { 280 return CodeLocation(); 281 } 282 } 283 284 [[noreturn]] void castError( ast::VirtualCastExpr const * castExpr, std::string const & message ) { 285 SemanticError( castLocation( castExpr ), message ); 286 } 287 288 class TypeIdTable final { 289 ScopedMap<std::string, ast::ObjectDecl const *> instances; 290 public: 291 void enterScope() { instances.beginScope(); } 292 void leaveScope() { instances.endScope(); } 293 294 // Attempt to insert an instance into the map. If there is a conflict, 295 // returns the previous declaration for error messages. 296 ast::ObjectDecl const * insert( ast::ObjectDecl const * typeIdDecl ) { 297 std::string const & mangledName = 298 Mangle::mangle( typeIdDecl->type, Mangle::typeMode() ); 299 ast::ObjectDecl const *& value = instances[ mangledName ]; 300 if ( value ) { 301 if ( typeIdDecl->storage.is_extern ) { 302 return nullptr; 303 } else if ( !value->storage.is_extern ) { 304 return value; 305 } 306 } 307 value = typeIdDecl; 308 return nullptr; 309 } 310 311 ast::ObjectDecl const * lookup( ast::Type const * typeIdType ) { 312 std::string const & mangledName = 313 Mangle::mangle( typeIdType, Mangle::typeMode() ); 314 auto const it = instances.find( mangledName ); 315 return ( instances.end() == it ) ? nullptr : it->second; 316 } 317 }; 318 319 struct ExpandCastsCore { 320 void previsit( ast::FunctionDecl const * decl ); 321 void previsit( ast::StructDecl const * decl ); 322 void previsit( ast::ObjectDecl const * decl ); 323 ast::Expr const * postvisit( ast::VirtualCastExpr const * expr ); 324 325 ast::CastExpr const * cast_to_type_id( 326 ast::Expr const * expr, unsigned int level_of_indirection ); 327 328 ast::FunctionDecl const * vcast_decl = nullptr; 329 ast::StructDecl const * info_decl = nullptr; 330 331 TypeIdTable symtab; 332 }; 333 334 void ExpandCastsCore::previsit( ast::FunctionDecl const * decl ) { 335 if ( !vcast_decl && "__cfavir_virtual_cast" == decl->name ) { 336 vcast_decl = decl; 337 } 338 } 339 340 void ExpandCastsCore::previsit( ast::StructDecl const * decl ) { 341 if ( !info_decl && decl->body && "__cfavir_type_info" == decl->name ) { 342 info_decl = decl; 343 } 344 } 345 346 void ExpandCastsCore::previsit( ast::ObjectDecl const * decl ) { 347 if ( is_type_id_object( decl ) ) { 348 // Multiple definitions should be fine because of linkonce. 349 symtab.insert( decl ); 350 } 351 } 352 353 /// Get the base type from a pointer or reference. 354 ast::Type const * getBaseType( ast::ptr<ast::Type> const & type ) { 355 if ( auto target = type.as<ast::PointerType>() ) { 356 return target->base.get(); 357 } else if ( auto target = type.as<ast::ReferenceType>() ) { 358 return target->base.get(); 359 } else { 360 return nullptr; 361 } 362 } 363 364 ast::StructInstType * polyCopy( 365 ast::StructInstType const * oldType, 366 ast::StructInstType const * newType ) { 367 assert( oldType->params.size() == newType->params.size() ); 368 ast::StructInstType * retType = ast::deepCopy( newType ); 369 if ( ! oldType->params.empty() ) { 370 retType->params.clear(); 371 for ( auto oldParams : oldType->params ) { 372 retType->params.push_back( ast::deepCopy( oldParams ) ); 373 } 374 } 375 return retType; 376 } 377 378 /// Follow the "head" field of the structure to get the type that is pointed 379 /// to by that field. 380 ast::StructInstType const * followHeadPointerType( 381 CodeLocation const & errorLocation, 382 ast::StructInstType const * oldType, 383 std::string const & fieldName ) { 384 ast::StructDecl const * oldDecl = oldType->base; 385 assert( oldDecl ); 386 387 // Helper function for throwing semantic errors. 388 auto throwError = [&fieldName, &errorLocation, &oldDecl]( 389 std::string const & message ) { 390 std::string const & context = "While following head pointer of " + 391 oldDecl->name + " named '" + fieldName + "': "; 392 SemanticError( errorLocation, context + message ); 393 }; 394 395 if ( oldDecl->members.empty() ) { 396 throwError( "Type has no fields." ); 397 } 398 ast::ptr<ast::Decl> const & memberDecl = oldDecl->members.front(); 399 assert( memberDecl ); 400 ast::ObjectDecl const * fieldDecl = memberDecl.as<ast::ObjectDecl>(); 401 assert( fieldDecl ); 402 if ( fieldName != fieldDecl->name ) { 403 throwError( "Head field did not have expected name." ); 404 } 405 406 ast::ptr<ast::Type> const & fieldType = fieldDecl->type; 407 if ( nullptr == fieldType ) { 408 throwError( "Could not get head field." ); 409 } 410 auto ptrType = fieldType.as<ast::PointerType>(); 411 if ( nullptr == ptrType ) { 412 throwError( "First field is not a pointer type." ); 413 } 414 assert( ptrType->base ); 415 auto newType = ptrType->base.as<ast::StructInstType>(); 416 if ( nullptr == newType ) { 417 throwError( "First field does not point to a structure type." ); 418 } 419 420 return polyCopy( oldType, newType ); 421 } 422 423 /// Get the type-id type from a virtual type. 424 ast::StructInstType const * getTypeIdType( 425 CodeLocation const & errorLocation, 426 ast::Type const * type ) { 427 auto typeInst = dynamic_cast<ast::StructInstType const *>( type ); 428 if ( nullptr == typeInst ) { 429 return nullptr; 430 } 431 ast::ptr<ast::StructInstType> tableInst = 432 followHeadPointerType( errorLocation, typeInst, "virtual_table" ); 433 if ( nullptr == tableInst ) { 434 return nullptr; 435 } 436 ast::StructInstType const * typeIdInst = 437 followHeadPointerType( errorLocation, tableInst, "__cfavir_typeid" ); 438 return typeIdInst; 439 } 440 441 ast::Expr const * ExpandCastsCore::postvisit( 442 ast::VirtualCastExpr const * expr ) { 443 assertf( expr->result, "Virtual cast target not found before expansion." ); 444 445 assert( vcast_decl ); 446 assert( info_decl ); 447 448 ast::Type const * base_type = getBaseType( expr->result ); 449 if ( nullptr == base_type ) { 450 castError( expr, "Virtual cast target must be a pointer or reference type." ); 451 } 452 ast::StructInstType const * type_id_type = 453 getTypeIdType( castLocation( expr ), base_type ); 454 if ( nullptr == type_id_type ) { 455 castError( expr, "Ill formed virtual cast target type." ); 456 } 457 ast::ObjectDecl const * type_id = symtab.lookup( type_id_type ); 458 if ( nullptr == type_id ) { 459 // I'm trying to give a different error for polymorpic types as 460 // different things can go wrong there. 461 if ( type_id_type->params.empty() ) { 462 castError( expr, "Virtual cast does not target a virtual type." ); 463 } else { 464 castError( expr, "Virtual cast does not target a type with a " 465 "type id (possible missing virtual table)." ); 466 } 467 } 468 469 return new ast::CastExpr( expr->location, 470 new ast::ApplicationExpr( expr->location, 471 ast::VariableExpr::functionPointer( expr->location, vcast_decl ), 472 { 473 cast_to_type_id( 474 new ast::AddressExpr( expr->location, 475 new ast::VariableExpr( expr->location, type_id ) ), 476 1 ), 477 cast_to_type_id( expr->arg, 2 ), 478 } 479 ), 480 ast::deepCopy( expr->result ) 481 ); 482 } 483 484 ast::CastExpr const * ExpandCastsCore::cast_to_type_id( 485 ast::Expr const * expr, unsigned int level_of_indirection ) { 486 assert( info_decl ); 487 ast::Type * type = new ast::StructInstType( info_decl, ast::CV::Const ); 488 for ( unsigned int i = 0 ; i < level_of_indirection ; ++i ) { 489 type = new ast::PointerType( type ); 490 } 491 return new ast::CastExpr( expr->location, expr, type ); 492 } 493 494 } // namespace 495 496 void expandCasts( std::list< Declaration * > & translationUnit ) { 497 PassVisitor<VirtualCastCore> translator; 498 mutateAll( translationUnit, translator ); 499 } 500 501 void expandCasts( ast::TranslationUnit & translationUnit ) { 502 ast::Pass<ExpandCastsCore>::run( translationUnit ); 503 } 504 505 } // namespace Virtual -
src/Virtual/ExpandCasts.h
r62c5a55 r181036c 10 10 // Created On : Mon Jul 24 13:54:00 2017 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tus Jul 25 14:51:00 201713 // Update Count : 012 // Last Modified On : Fri Jul 29 14:40:00 2022 13 // Update Count : 1 14 14 // 15 15 … … 19 19 20 20 class Declaration; 21 namespace ast { 22 class TranslationUnit; 23 } 21 24 22 25 namespace Virtual { 23 void expandCasts( std::list< Declaration * > & translationUnit ); 24 // Breaks all virtual cast nodes up into translatable nodes. 26 void expandCasts( std::list< Declaration * > & translationUnit ); 27 void expandCasts( ast::TranslationUnit & translationUnit ); 28 // Breaks all virtual cast nodes up into translatable nodes. 25 29 26 30 // Later this might just set some information so it can happen at CodeGen. 27 31 28 32 } -
src/main.cc
r62c5a55 r181036c 10 10 // Created On : Fri May 15 23:12:02 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Jul 18 11:08:00 202213 // Update Count : 67 612 // Last Modified On : Thu 11 12:18:00 2022 13 // Update Count : 677 14 14 // 15 15 … … 445 445 PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) ); 446 446 447 if ( tuplep ) { 448 dump( move( transUnit ) ); 449 return EXIT_SUCCESS; 450 } // if 451 452 // Must come after Translate Tries. 453 PASS( "Virtual Expand Casts", Virtual::expandCasts( transUnit ) ); 454 447 455 translationUnit = convert( move( transUnit ) ); 448 456 } else { … … 520 528 PASS( "Convert Specializations", GenPoly::convertSpecializations( translationUnit ) ); // needs to happen before tuple types are expanded 521 529 PASS( "Expand Tuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this? 530 531 if ( tuplep ) { 532 dump( translationUnit ); 533 return EXIT_SUCCESS; 534 } // if 535 536 PASS( "Virtual Expand Casts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM 522 537 } 523 524 if ( tuplep ) {525 dump( translationUnit );526 return EXIT_SUCCESS;527 } // if528 529 PASS( "Virtual Expand Casts", Virtual::expandCasts( translationUnit ) ); // Must come after translateEHM530 538 531 539 PASS( "Instantiate Generics", GenPoly::instantiateGeneric( translationUnit ) );
Note:
See TracChangeset
for help on using the changeset viewer.