Changeset b9fe89b
- Timestamp:
- Jun 5, 2023, 1:29:55 PM (4 months ago)
- Branches:
- ast-experimental, master
- Children:
- 134e6d9
- Parents:
- 84334d0
- Location:
- src
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Pass.hpp
r84334d0 rb9fe89b 414 414 }; 415 415 416 /// Use when the templated visitor should update the symbol table 416 /// Use when the templated visitor should update the symbol table, 417 /// that is, when your pass core needs to query the symbol table. 418 /// Expected setups: 419 /// - For master passes that kick off at the compilation unit 420 /// - before resolver: extend WithSymbolTableX<IgnoreErrors> 421 /// - after resolver: extend WithSymbolTable and use defaults 422 /// - (FYI, for completeness, the resolver's main pass uses ValidateOnAdd when it kicks off) 423 /// - For helper passes that kick off at arbitrary points in the AST: 424 /// - take an existing symbol table as a parameter, extend WithSymbolTable, 425 /// and construct with WithSymbolTable(const SymbolTable &) 417 426 struct WithSymbolTable { 418 SymbolTable symtab; 427 WithSymbolTable(const ast::SymbolTable & from) : symtab(from) {} 428 WithSymbolTable(ast::SymbolTable::ErrorDetection errorMode = ast::SymbolTable::ErrorDetection::AssertClean) : symtab(errorMode) {} 429 ast::SymbolTable symtab; 430 }; 431 template <ast::SymbolTable::ErrorDetection errorMode> 432 struct WithSymbolTableX : WithSymbolTable { 433 WithSymbolTableX() : WithSymbolTable(errorMode) {} 419 434 }; 420 435 -
src/AST/SymbolTable.cpp
r84334d0 rb9fe89b 88 88 } 89 89 90 SymbolTable::SymbolTable( )90 SymbolTable::SymbolTable( ErrorDetection errorMode ) 91 91 : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(), 92 prevScope(), scope( 0 ), repScope( 0 ) { ++*stats().count; }92 prevScope(), scope( 0 ), repScope( 0 ), errorMode(errorMode) { ++*stats().count; } 93 93 94 94 SymbolTable::~SymbolTable() { stats().size->push( idTable ? idTable->size() : 0 ); } 95 96 void SymbolTable::OnFindError( CodeLocation location, std::string error ) const { 97 assertf( errorMode != AssertClean, "Name collision/redefinition, found during a compilation phase where none should be possible. Detail: %s", error.c_str() ); 98 if (errorMode == ValidateOnAdd) { 99 SemanticError(location, error); 100 } 101 assertf( errorMode == IgnoreErrors, "Unrecognized symbol-table error mode %d", errorMode ); 102 } 95 103 96 104 void SymbolTable::enterScope() { … … 269 277 } 270 278 271 namespace { 272 /// true if redeclaration conflict between two types 273 bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) { 274 if ( existing->base == nullptr ) { 275 return false; 276 } else if ( added->base == nullptr ) { 277 return true; 278 } else { 279 // typedef redeclarations are errors only if types are different 280 if ( ! ResolvExpr::typesCompatible( existing->base, added->base ) ) { 281 SemanticError( added->location, "redeclaration of " + added->name ); 282 } 283 } 284 // does not need to be added to the table if both existing and added have a base that are 285 // the same 279 bool SymbolTable::addedTypeConflicts( 280 const NamedTypeDecl * existing, const NamedTypeDecl * added ) const { 281 if ( existing->base == nullptr ) { 282 return false; 283 } else if ( added->base == nullptr ) { 286 284 return true; 287 } 288 289 /// true if redeclaration conflict between two aggregate declarations 290 bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) { 291 if ( ! existing->body ) { 292 return false; 293 } else if ( added->body ) { 294 SemanticError( added, "redeclaration of " ); 295 } 296 return true; 297 } 285 } else { 286 // typedef redeclarations are errors only if types are different 287 if ( ! ResolvExpr::typesCompatible( existing->base, added->base ) ) { 288 OnFindError( added->location, "redeclaration of " + added->name ); 289 } 290 } 291 // does not need to be added to the table if both existing and added have a base that are 292 // the same 293 return true; 294 } 295 296 bool SymbolTable::addedDeclConflicts( 297 const AggregateDecl * existing, const AggregateDecl * added ) const { 298 if ( ! existing->body ) { 299 return false; 300 } else if ( added->body ) { 301 OnFindError( added, "redeclaration of " ); 302 } 303 return true; 298 304 } 299 305 … … 648 654 if ( deleter && ! existing.deleter ) { 649 655 if ( handleConflicts.mode == OnConflict::Error ) { 650 SemanticError( added, "deletion of defined identifier " );656 OnFindError( added, "deletion of defined identifier " ); 651 657 } 652 658 return true; 653 659 } else if ( ! deleter && existing.deleter ) { 654 660 if ( handleConflicts.mode == OnConflict::Error ) { 655 SemanticError( added, "definition of deleted identifier " );661 OnFindError( added, "definition of deleted identifier " ); 656 662 } 657 663 return true; … … 661 667 if ( isDefinition( added ) && isDefinition( existing.id ) ) { 662 668 if ( handleConflicts.mode == OnConflict::Error ) { 663 SemanticError( added,669 OnFindError( added, 664 670 isFunction( added ) ? 665 671 "duplicate function definition for " : … … 670 676 } else { 671 677 if ( handleConflicts.mode == OnConflict::Error ) { 672 SemanticError( added, "duplicate definition for " );678 OnFindError( added, "duplicate definition for " ); 673 679 } 674 680 return true; … … 722 728 // Check that a Cforall declaration doesn't override any C declaration 723 729 if ( hasCompatibleCDecl( name, mangleName ) ) { 724 SemanticError( decl, "Cforall declaration hides C function " );730 OnFindError( decl, "Cforall declaration hides C function " ); 725 731 } 726 732 } else { … … 728 734 // type-compatibility, which it may not be. 729 735 if ( hasIncompatibleCDecl( name, mangleName ) ) { 730 SemanticError( decl, "conflicting overload of C function " );736 OnFindError( decl, "conflicting overload of C function " ); 731 737 } 732 738 } -
src/AST/SymbolTable.hpp
r84334d0 rb9fe89b 93 93 94 94 public: 95 SymbolTable(); 95 96 /// Mode to control when (during which pass) user-caused name-declaration errors get reported. 97 /// The default setting `AssertClean` supports, "I expect all user-caused errors to have been 98 /// reported by now," or, "I wouldn't know what to do with an error; are there even any here?" 99 enum ErrorDetection { 100 AssertClean, ///< invalid user decls => assert fails during addFoo (default) 101 ValidateOnAdd, ///< invalid user decls => calls SemanticError during addFoo 102 IgnoreErrors ///< acts as if unspecified decls were removed, forcing validity 103 }; 104 105 explicit SymbolTable( 106 ErrorDetection ///< mode for the lifetime of the symbol table (whole pass) 107 ); 108 SymbolTable() : SymbolTable(AssertClean) {} 96 109 ~SymbolTable(); 110 111 ErrorDetection getErrorMode() const { 112 return errorMode; 113 } 97 114 98 115 // when using an indexer manually (e.g., within a mutator traversal), it is necessary to … … 158 175 159 176 private: 177 void OnFindError( CodeLocation location, std::string error ) const; 178 179 template< typename T > 180 void OnFindError( const T * obj, const std::string & error ) const { 181 OnFindError( obj->location, toString( error, obj ) ); 182 } 183 184 template< typename T > 185 void OnFindError( CodeLocation location, const T * obj, const std::string & error ) const { 186 OnFindError( location, toString( error, obj ) ); 187 } 188 160 189 /// Ensures that a proper backtracking scope exists before a mutation 161 190 void lazyInitScope(); … … 168 197 bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr & mangleTable ); 169 198 170 /// Options for handling identifier conflicts 199 /// Error detection mode given at construction (pass-specific). 200 /// Logically const, except that the symbol table's push-pop is achieved by autogenerated 201 /// assignment onto self. The feield is left motuable to keep this code-gen simple. 202 /// Conceptual constness is preserved by all SymbolTable in a stack sharing the same mode. 203 ErrorDetection errorMode; 204 205 /// Options for handling identifier conflicts. 206 /// Varies according to AST location during traversal: captures semantics of the construct 207 /// being visited as "would shadow" vs "must not collide." 208 /// At a given AST location, is the same for every pass. 171 209 struct OnConflict { 172 210 enum { 173 Error, ///< Throw a semantic error211 Error, ///< Follow the current pass's ErrorDetection mode (may throw a semantic error) 174 212 Delete ///< Delete the earlier version with the delete statement 175 213 } mode; … … 191 229 const Decl * deleter ); 192 230 231 /// true if redeclaration conflict between two types 232 bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) const; 233 234 /// true if redeclaration conflict between two aggregate declarations 235 bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) const; 236 193 237 /// common code for addId, addDeletedId, etc. 194 238 void addIdCommon( … … 213 257 } 214 258 259 215 260 // Local Variables: // 216 261 // tab-width: 4 // -
src/ResolvExpr/Resolver.cc
r84334d0 rb9fe89b 1261 1261 static size_t traceId; 1262 1262 Resolver_new( const ast::TranslationGlobal & global ) : 1263 ast::WithSymbolTable(ast::SymbolTable::ErrorDetection::ValidateOnAdd), 1263 1264 context{ symtab, global } {} 1264 1265 Resolver_new( const ResolveContext & context ) :
Note: See TracChangeset
for help on using the changeset viewer.