Changeset b067d9b for src/SymTab/Indexer.cc
- Timestamp:
- Oct 29, 2019, 4:01:24 PM (6 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 773db65, 9421f3d8
- Parents:
- 7951100 (diff), 8364209 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/SymTab/Indexer.cc
r7951100 rb067d9b 9 9 // Author : Richard C. Bilson 10 10 // Created On : Sun May 17 21:37:33 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Thu Aug 17 16:08:40 201713 // Update Count : 2 011 // Last Modified By : Aaron B. Moss 12 // Last Modified On : Fri Mar 8 13:55:00 2019 13 // Update Count : 21 14 14 // 15 15 … … 17 17 18 18 #include <cassert> // for assert, strict_dynamic_cast 19 #include <iostream> // for operator<<, basic_ostream, ostream20 19 #include <string> // for string, operator<<, operator!= 20 #include <memory> // for shared_ptr, make_shared 21 21 #include <unordered_map> // for operator!=, unordered_map<>::const... 22 22 #include <unordered_set> // for unordered_set 23 23 #include <utility> // for pair, make_pair, move 24 #include <vector> // for vector 24 25 25 26 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign 26 27 #include "Common/SemanticError.h" // for SemanticError 27 28 #include "Common/utility.h" // for cloneAll 28 #include "GenPoly/GenPoly.h" 29 #include "Common/Stats/Counter.h" // for counters 30 #include "GenPoly/GenPoly.h" // for getFunctionType 29 31 #include "InitTweak/InitTweak.h" // for isConstructor, isCopyFunction, isC... 30 32 #include "Mangler.h" // for Mangler … … 38 40 #include "SynTree/Type.h" // for Type, StructInstType, UnionInstType 39 41 40 #define debugPrint(x) if ( doDebug ) { std::cerr << x; }41 42 42 namespace SymTab { 43 std::ostream & operator<<( std::ostream & out, const Indexer::IdData & data ) { 44 return out << "(" << data.id << "," << data.baseExpr << ")"; 45 } 46 47 typedef std::unordered_map< std::string, Indexer::IdData > MangleTable; 48 typedef std::unordered_map< std::string, MangleTable > IdTable; 49 typedef std::unordered_map< std::string, NamedTypeDecl* > TypeTable; 50 typedef std::unordered_map< std::string, StructDecl* > StructTable; 51 typedef std::unordered_map< std::string, EnumDecl* > EnumTable; 52 typedef std::unordered_map< std::string, UnionDecl* > UnionTable; 53 typedef std::unordered_map< std::string, TraitDecl* > TraitTable; 54 55 void dump( const IdTable &table, std::ostream &os ) { 56 for ( IdTable::const_iterator id = table.begin(); id != table.end(); ++id ) { 57 for ( MangleTable::const_iterator mangle = id->second.begin(); mangle != id->second.end(); ++mangle ) { 58 os << mangle->second << std::endl; 59 } 60 } 61 } 62 63 template< typename Decl > 64 void dump( const std::unordered_map< std::string, Decl* > &table, std::ostream &os ) { 65 for ( typename std::unordered_map< std::string, Decl* >::const_iterator it = table.begin(); it != table.end(); ++it ) { 66 os << it->second << std::endl; 67 } // for 68 } 69 70 struct Indexer::Impl { 71 Impl( unsigned long _scope ) : refCount(1), scope( _scope ), size( 0 ), base(), 72 idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {} 73 Impl( unsigned long _scope, Indexer &&_base ) : refCount(1), scope( _scope ), size( 0 ), base( _base ), 74 idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {} 75 unsigned long refCount; ///< Number of references to these tables 76 unsigned long scope; ///< Scope these tables are associated with 77 unsigned long size; ///< Number of elements stored in this table 78 const Indexer base; ///< Base indexer this extends 79 80 IdTable idTable; ///< Identifier namespace 81 TypeTable typeTable; ///< Type namespace 82 StructTable structTable; ///< Struct namespace 83 EnumTable enumTable; ///< Enum namespace 84 UnionTable unionTable; ///< Union namespace 85 TraitTable traitTable; ///< Trait namespace 86 }; 87 88 Indexer::Impl *Indexer::newRef( Indexer::Impl *toClone ) { 89 if ( ! toClone ) return 0; 90 91 // shorten the search chain by skipping empty links 92 Indexer::Impl *ret = toClone->size == 0 ? toClone->base.tables : toClone; 93 if ( ret ) { ++ret->refCount; } 94 95 return ret; 96 } 97 98 void Indexer::deleteRef( Indexer::Impl *toFree ) { 99 if ( ! toFree ) return; 100 101 if ( --toFree->refCount == 0 ) delete toFree; 102 } 103 104 void Indexer::removeSpecialOverrides( const std::string &id, std::list< IdData > & out ) const { 105 // only need to perform this step for constructors, destructors, and assignment functions 106 if ( ! CodeGen::isCtorDtorAssign( id ) ) return; 107 108 // helpful data structure to organize properties for a type 109 struct ValueType { 110 struct DeclBall { // properties for this particular decl 111 IdData decl; 112 bool isUserDefinedFunc; 113 bool isCopyFunc; 43 44 // Statistics block 45 namespace { 46 static inline auto stats() { 47 using namespace Stats::Counters; 48 static auto group = build<CounterGroup>("Indexers"); 49 static struct { 50 SimpleCounter * count; 51 AverageCounter<double> * size; 52 SimpleCounter * new_scopes; 53 SimpleCounter * lazy_scopes; 54 AverageCounter<double> * avg_scope_depth; 55 MaxCounter<size_t> * max_scope_depth; 56 SimpleCounter * add_calls; 57 SimpleCounter * lookup_calls; 58 SimpleCounter * map_lookups; 59 SimpleCounter * map_mutations; 60 } ret = { 61 .count = build<SimpleCounter>("Count", group), 62 .size = build<AverageCounter<double>>("Average Size", group), 63 .new_scopes = build<SimpleCounter>("Scopes", group), 64 .lazy_scopes = build<SimpleCounter>("Lazy Scopes", group), 65 .avg_scope_depth = build<AverageCounter<double>>("Average Scope", group), 66 .max_scope_depth = build<MaxCounter<size_t>>("Max Scope", group), 67 .add_calls = build<SimpleCounter>("Add Calls", group), 68 .lookup_calls = build<SimpleCounter>("Lookup Calls", group), 69 .map_lookups = build<SimpleCounter>("Map Lookups", group), 70 .map_mutations = build<SimpleCounter>("Map Mutations", group) 114 71 }; 115 // properties for this type 116 bool existsUserDefinedCopyFunc = false; // user-defined copy ctor found 117 BaseSyntaxNode * deleteStmt = nullptr; // non-null if a user-defined function is found 118 std::list< DeclBall > decls; 119 120 // another FunctionDecl for the current type was found - determine 121 // if it has special properties and update data structure accordingly 122 ValueType & operator+=( IdData data ) { 123 DeclarationWithType * function = data.id; 124 bool isUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage ); 125 bool isCopyFunc = InitTweak::isCopyFunction( function, function->name ); 126 decls.push_back( DeclBall{ data, isUserDefinedFunc, isCopyFunc } ); 127 existsUserDefinedCopyFunc = existsUserDefinedCopyFunc || (isUserDefinedFunc && isCopyFunc); 128 if ( isUserDefinedFunc && ! data.deleteStmt ) { 129 // any user-defined function can act as an implicit delete statement for generated constructors. 130 // a delete stmt should not act as an implicit delete statement. 131 deleteStmt = data.id; 132 } 133 return *this; 134 } 135 }; // ValueType 136 137 std::list< IdData > copy; 138 copy.splice( copy.end(), out ); 139 140 // organize discovered declarations by type 141 std::unordered_map< std::string, ValueType > funcMap; 142 for ( auto decl : copy ) { 143 if ( FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl.id ) ) { 144 std::list< DeclarationWithType * > & params = function->type->parameters; 145 assert( ! params.empty() ); 146 // use base type of pointer, so that qualifiers on the pointer type aren't considered. 147 Type * base = InitTweak::getPointerBase( params.front()->get_type() ); 148 assert( base ); 149 funcMap[ Mangler::mangle( base ) ] += decl; 150 } else { 151 out.push_back( decl ); 152 } 153 } 154 155 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which determine 156 // the set of ctor/dtor/assign that can be used by the requester. In particular, if the user defines 157 // a default ctor, then the generated default ctor is unavailable, likewise for copy ctor 158 // and dtor. If the user defines any ctor/dtor, then no generated field ctors are available. 159 // If the user defines any ctor then the generated default ctor is unavailable (intrinsic default 160 // ctor must be overridden exactly). If the user defines anything that looks like a copy constructor, 161 // then the generated copy constructor is unavailable, and likewise for the assignment operator. 162 for ( std::pair< const std::string, ValueType > & pair : funcMap ) { 163 ValueType & val = pair.second; 164 for ( ValueType::DeclBall ball : val.decls ) { 165 bool isNotUserDefinedFunc = ! ball.isUserDefinedFunc && ball.decl.id->linkage != LinkageSpec::Intrinsic; 166 bool isCopyFunc = ball.isCopyFunc; 167 bool existsUserDefinedCopyFunc = val.existsUserDefinedCopyFunc; 168 // only implicitly delete non-user defined functions that are not intrinsic, and are 169 // not copy functions (assignment or copy constructor), unless a user-defined copy function exists. 170 // deleteStmt will be non-null only if a user-defined function is found. 171 if (isNotUserDefinedFunc && (! isCopyFunc || existsUserDefinedCopyFunc)) { 172 ball.decl.deleteStmt = val.deleteStmt; 173 } 174 out.push_back( ball.decl ); 175 } 176 } 177 } 178 179 void Indexer::makeWritable() { 180 if ( ! tables ) { 181 // create indexer if not yet set 182 tables = new Indexer::Impl( scope ); 183 } else if ( tables->refCount > 1 || tables->scope != scope ) { 184 // make this indexer the base of a fresh indexer at the current scope 185 tables = new Indexer::Impl( scope, std::move( *this ) ); 186 } 187 } 188 189 Indexer::Indexer() : tables( 0 ), scope( 0 ) {} 190 191 Indexer::Indexer( const Indexer &that ) : doDebug( that.doDebug ), tables( newRef( that.tables ) ), scope( that.scope ) {} 192 193 Indexer::Indexer( Indexer &&that ) : doDebug( that.doDebug ), tables( that.tables ), scope( that.scope ) { 194 that.tables = 0; 195 } 72 return ret; 73 } 74 } 75 76 Indexer::Indexer() 77 : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(), 78 prevScope(), scope( 0 ), repScope( 0 ) { ++* stats().count; } 196 79 197 80 Indexer::~Indexer() { 198 deleteRef( tables ); 199 } 200 201 Indexer& Indexer::operator= ( const Indexer &that ) { 202 deleteRef( tables ); 203 204 tables = newRef( that.tables ); 205 scope = that.scope; 206 doDebug = that.doDebug; 207 208 return *this; 209 } 210 211 Indexer& Indexer::operator= ( Indexer &&that ) { 212 deleteRef( tables ); 213 214 tables = that.tables; 215 scope = that.scope; 216 doDebug = that.doDebug; 217 218 that.tables = 0; 219 220 return *this; 221 } 222 223 void Indexer::lookupId( const std::string &id, std::list< IdData > &out ) const { 224 std::unordered_set< std::string > foundMangleNames; 225 226 Indexer::Impl *searchTables = tables; 227 while ( searchTables ) { 228 229 IdTable::const_iterator decls = searchTables->idTable.find( id ); 230 if ( decls != searchTables->idTable.end() ) { 231 const MangleTable &mangleTable = decls->second; 232 for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) { 233 // mark the mangled name as found, skipping this insertion if a declaration for that name has already been found 234 if ( foundMangleNames.insert( decl->first ).second == false ) continue; 235 236 out.push_back( decl->second ); 237 } 238 } 239 240 // get declarations from base indexers 241 searchTables = searchTables->base.tables; 242 } 243 244 // some special functions, e.g. constructors and destructors 245 // remove autogenerated functions when they are defined so that 246 // they can never be matched 247 removeSpecialOverrides( id, out ); 248 } 249 250 NamedTypeDecl *Indexer::lookupType( const std::string &id ) const { 251 if ( ! tables ) return 0; 252 253 TypeTable::const_iterator ret = tables->typeTable.find( id ); 254 return ret != tables->typeTable.end() ? ret->second : tables->base.lookupType( id ); 255 } 256 257 StructDecl *Indexer::lookupStruct( const std::string &id ) const { 258 if ( ! tables ) return 0; 259 260 StructTable::const_iterator ret = tables->structTable.find( id ); 261 return ret != tables->structTable.end() ? ret->second : tables->base.lookupStruct( id ); 262 } 263 264 EnumDecl *Indexer::lookupEnum( const std::string &id ) const { 265 if ( ! tables ) return 0; 266 267 EnumTable::const_iterator ret = tables->enumTable.find( id ); 268 return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnum( id ); 269 } 270 271 UnionDecl *Indexer::lookupUnion( const std::string &id ) const { 272 if ( ! tables ) return 0; 273 274 UnionTable::const_iterator ret = tables->unionTable.find( id ); 275 return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnion( id ); 276 } 277 278 TraitDecl *Indexer::lookupTrait( const std::string &id ) const { 279 if ( ! tables ) return 0; 280 281 TraitTable::const_iterator ret = tables->traitTable.find( id ); 282 return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTrait( id ); 283 } 284 285 const Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const { 286 if ( ! tables ) return nullptr; 287 if ( tables->scope < scope ) return nullptr; 288 289 IdTable::const_iterator decls = tables->idTable.find( id ); 290 if ( decls != tables->idTable.end() ) { 291 const MangleTable &mangleTable = decls->second; 292 MangleTable::const_iterator decl = mangleTable.find( mangleName ); 293 if ( decl != mangleTable.end() ) return &decl->second; 294 } 295 296 return tables->base.lookupIdAtScope( id, mangleName, scope ); 297 } 298 299 Indexer::IdData * Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) { 300 return const_cast<IdData *>(const_cast<const Indexer *>(this)->lookupIdAtScope( id, mangleName, scope )); 301 } 302 303 bool Indexer::hasIncompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const { 304 if ( ! tables ) return false; 305 if ( tables->scope < scope ) return false; 306 307 IdTable::const_iterator decls = tables->idTable.find( id ); 308 if ( decls != tables->idTable.end() ) { 309 const MangleTable &mangleTable = decls->second; 310 for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) { 311 // check for C decls with the same name, skipping those with a compatible type (by mangleName) 312 if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first != mangleName ) return true; 313 } 314 } 315 316 return tables->base.hasIncompatibleCDecl( id, mangleName, scope ); 317 } 318 319 bool Indexer::hasCompatibleCDecl( const std::string &id, const std::string &mangleName, unsigned long scope ) const { 320 if ( ! tables ) return false; 321 if ( tables->scope < scope ) return false; 322 323 IdTable::const_iterator decls = tables->idTable.find( id ); 324 if ( decls != tables->idTable.end() ) { 325 const MangleTable &mangleTable = decls->second; 326 for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) { 327 // check for C decls with the same name, skipping 328 // those with an incompatible type (by mangleName) 329 if ( ! LinkageSpec::isMangled( decl->second.id->get_linkage() ) && decl->first == mangleName ) return true; 330 } 331 } 332 333 return tables->base.hasCompatibleCDecl( id, mangleName, scope ); 334 } 335 336 NamedTypeDecl *Indexer::lookupTypeAtScope( const std::string &id, unsigned long scope ) const { 337 if ( ! tables ) return 0; 338 if ( tables->scope < scope ) return 0; 339 340 TypeTable::const_iterator ret = tables->typeTable.find( id ); 341 return ret != tables->typeTable.end() ? ret->second : tables->base.lookupTypeAtScope( id, scope ); 342 } 343 344 StructDecl *Indexer::lookupStructAtScope( const std::string &id, unsigned long scope ) const { 345 if ( ! tables ) return 0; 346 if ( tables->scope < scope ) return 0; 347 348 StructTable::const_iterator ret = tables->structTable.find( id ); 349 return ret != tables->structTable.end() ? ret->second : tables->base.lookupStructAtScope( id, scope ); 350 } 351 352 EnumDecl *Indexer::lookupEnumAtScope( const std::string &id, unsigned long scope ) const { 353 if ( ! tables ) return 0; 354 if ( tables->scope < scope ) return 0; 355 356 EnumTable::const_iterator ret = tables->enumTable.find( id ); 357 return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnumAtScope( id, scope ); 358 } 359 360 UnionDecl *Indexer::lookupUnionAtScope( const std::string &id, unsigned long scope ) const { 361 if ( ! tables ) return 0; 362 if ( tables->scope < scope ) return 0; 363 364 UnionTable::const_iterator ret = tables->unionTable.find( id ); 365 return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnionAtScope( id, scope ); 366 } 367 368 TraitDecl *Indexer::lookupTraitAtScope( const std::string &id, unsigned long scope ) const { 369 if ( ! tables ) return 0; 370 if ( tables->scope < scope ) return 0; 371 372 TraitTable::const_iterator ret = tables->traitTable.find( id ); 373 return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTraitAtScope( id, scope ); 374 } 375 376 bool isFunction( DeclarationWithType * decl ) { 81 stats().size->push( idTable ? idTable->size() : 0 ); 82 } 83 84 void Indexer::lazyInitScope() { 85 if ( repScope < scope ) { 86 ++* stats().lazy_scopes; 87 // create rollback 88 prevScope = std::make_shared<Indexer>( * this ); 89 // update repScope 90 repScope = scope; 91 } 92 } 93 94 void Indexer::enterScope() { 95 ++scope; 96 97 ++* stats().new_scopes; 98 stats().avg_scope_depth->push( scope ); 99 stats().max_scope_depth->push( scope ); 100 } 101 102 void Indexer::leaveScope() { 103 if ( repScope == scope ) { 104 Ptr prev = prevScope; // make sure prevScope stays live 105 * this = std::move(* prevScope); // replace with previous scope 106 } 107 108 --scope; 109 } 110 111 void Indexer::lookupId( const std::string & id, std::list< IdData > &out ) const { 112 ++* stats().lookup_calls; 113 if ( ! idTable ) return; 114 115 ++* stats().map_lookups; 116 auto decls = idTable->find( id ); 117 if ( decls == idTable->end() ) return; 118 119 for ( auto decl : *(decls->second) ) { 120 out.push_back( decl.second ); 121 } 122 } 123 124 const NamedTypeDecl * Indexer::lookupType( const std::string & id ) const { 125 ++* stats().lookup_calls; 126 if ( ! typeTable ) return nullptr; 127 ++* stats().map_lookups; 128 auto it = typeTable->find( id ); 129 return it == typeTable->end() ? nullptr : it->second.decl; 130 } 131 132 const StructDecl * Indexer::lookupStruct( const std::string & id ) const { 133 ++* stats().lookup_calls; 134 if ( ! structTable ) return nullptr; 135 ++* stats().map_lookups; 136 auto it = structTable->find( id ); 137 return it == structTable->end() ? nullptr : it->second.decl; 138 } 139 140 const EnumDecl * Indexer::lookupEnum( const std::string & id ) const { 141 ++* stats().lookup_calls; 142 if ( ! enumTable ) return nullptr; 143 ++* stats().map_lookups; 144 auto it = enumTable->find( id ); 145 return it == enumTable->end() ? nullptr : it->second.decl; 146 } 147 148 const UnionDecl * Indexer::lookupUnion( const std::string & id ) const { 149 ++* stats().lookup_calls; 150 if ( ! unionTable ) return nullptr; 151 ++* stats().map_lookups; 152 auto it = unionTable->find( id ); 153 return it == unionTable->end() ? nullptr : it->second.decl; 154 } 155 156 const TraitDecl * Indexer::lookupTrait( const std::string & id ) const { 157 ++* stats().lookup_calls; 158 if ( ! traitTable ) return nullptr; 159 ++* stats().map_lookups; 160 auto it = traitTable->find( id ); 161 return it == traitTable->end() ? nullptr : it->second.decl; 162 } 163 164 const Indexer * Indexer::atScope( unsigned long target ) const { 165 // by lazy construction, final indexer in list has repScope 0, cannot be > target 166 // otherwise, will find first scope representing the target 167 const Indexer * indexer = this; 168 while ( indexer->repScope > target ) { 169 indexer = indexer->prevScope.get(); 170 } 171 return indexer; 172 } 173 174 const NamedTypeDecl * Indexer::globalLookupType( const std::string & id ) const { 175 return atScope( 0 )->lookupType( id ); 176 } 177 178 const StructDecl * Indexer::globalLookupStruct( const std::string & id ) const { 179 return atScope( 0 )->lookupStruct( id ); 180 } 181 182 const UnionDecl * Indexer::globalLookupUnion( const std::string & id ) const { 183 return atScope( 0 )->lookupUnion( id ); 184 } 185 186 const EnumDecl * Indexer::globalLookupEnum( const std::string & id ) const { 187 return atScope( 0 )->lookupEnum( id ); 188 } 189 190 bool isFunction( const DeclarationWithType * decl ) { 377 191 return GenPoly::getFunctionType( decl->get_type() ); 378 192 } 379 193 380 bool isObject( DeclarationWithType * decl ) {194 bool isObject( const DeclarationWithType * decl ) { 381 195 return ! isFunction( decl ); 382 196 } 383 197 384 bool isDefinition( DeclarationWithType * decl ) {385 if ( FunctionDecl * func = dynamic_cast<FunctionDecl * >( decl ) ) {198 bool isDefinition( const DeclarationWithType * decl ) { 199 if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) { 386 200 // a function is a definition if it has a body 387 201 return func->statements; … … 393 207 } 394 208 395 bool addedIdConflicts( Indexer::IdData & existing, DeclarationWithType *added, BaseSyntaxNode * deleteStmt, Indexer::ConflictFunction handleConflicts ) { 396 // if we're giving the same name mangling to things of different types then there is something wrong 209 210 bool Indexer::addedIdConflicts( 211 const Indexer::IdData & existing, const DeclarationWithType * added, 212 Indexer::OnConflict handleConflicts, const Declaration * deleteStmt ) { 213 // if we're giving the same name mangling to things of different types then there is 214 // something wrong 397 215 assert( (isObject( added ) && isObject( existing.id ) ) 398 216 || ( isFunction( added ) && isFunction( existing.id ) ) ); 399 217 400 if ( LinkageSpec::isOverridable( existing.id-> get_linkage()) ) {218 if ( LinkageSpec::isOverridable( existing.id->linkage ) ) { 401 219 // new definition shadows the autogenerated one, even at the same scope 402 220 return false; 403 } else if ( LinkageSpec::isMangled( added->get_linkage() ) || ResolvExpr::typesCompatible( added->get_type(), existing.id->get_type(), Indexer() ) ) { 221 } else if ( LinkageSpec::isMangled( added->linkage ) 222 || ResolvExpr::typesCompatible( 223 added->get_type(), existing.id->get_type(), Indexer() ) ) { 404 224 405 225 // it is a conflict if one declaration is deleted and the other is not 406 226 if ( deleteStmt && ! existing.deleteStmt ) { 407 return handleConflicts( existing, "deletion of defined identifier " ); 227 if ( handleConflicts.mode == OnConflict::Error ) { 228 SemanticError( added, "deletion of defined identifier " ); 229 } 230 return true; 408 231 } else if ( ! deleteStmt && existing.deleteStmt ) { 409 return handleConflicts( existing, "definition of deleted identifier " ); 232 if ( handleConflicts.mode == OnConflict::Error ) { 233 SemanticError( added, "definition of deleted identifier " ); 234 } 235 return true; 410 236 } 411 237 412 238 if ( isDefinition( added ) && isDefinition( existing.id ) ) { 413 if ( isFunction( added ) ) { 414 return handleConflicts( existing, "duplicate function definition for " ); 239 if ( handleConflicts.mode == OnConflict::Error ) { 240 SemanticError( added, 241 isFunction( added ) ? 242 "duplicate function definition for " : 243 "duplicate object definition for " ); 244 } 245 return true; 246 } // if 247 } else { 248 if ( handleConflicts.mode == OnConflict::Error ) { 249 SemanticError( added, "duplicate definition for " ); 250 } 251 return true; 252 } // if 253 254 return true; 255 } 256 257 bool Indexer::hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const { 258 if ( ! idTable ) return false; 259 260 ++* stats().map_lookups; 261 auto decls = idTable->find( id ); 262 if ( decls == idTable->end() ) return false; 263 264 for ( auto decl : *(decls->second) ) { 265 // skip other scopes (hidden by this decl) 266 if ( decl.second.scope != scope ) continue; 267 // check for C decl with compatible type (by mangleName) 268 if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first == mangleName ) { 269 return true; 270 } 271 } 272 273 return false; 274 } 275 276 bool Indexer::hasIncompatibleCDecl(const std::string & id, const std::string &mangleName ) const { 277 if ( ! idTable ) return false; 278 279 ++* stats().map_lookups; 280 auto decls = idTable->find( id ); 281 if ( decls == idTable->end() ) return false; 282 283 for ( auto decl : *(decls->second) ) { 284 // skip other scopes (hidden by this decl) 285 if ( decl.second.scope != scope ) continue; 286 // check for C decl with incompatible type (by manglename) 287 if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first != mangleName ) { 288 return true; 289 } 290 } 291 292 return false; 293 } 294 295 /// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function 296 std::string getOtypeKey( const FunctionDecl * function ) { 297 auto& params = function->type->parameters; 298 assert( ! params.empty() ); 299 // use base type of pointer, so that qualifiers on the pointer type aren't considered. 300 Type * base = InitTweak::getPointerBase( params.front()->get_type() ); 301 assert( base ); 302 return Mangler::mangle( base ); 303 } 304 305 /// gets the declaration for the function acting on a type specified by otype key, 306 /// nullptr if none such 307 const FunctionDecl * getFunctionForOtype( const DeclarationWithType * decl, const std::string& otypeKey ) { 308 const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ); 309 if ( ! func || otypeKey != getOtypeKey( func ) ) return nullptr; 310 return func; 311 } 312 313 bool Indexer::removeSpecialOverrides(Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) { 314 // if a type contains user defined ctor/dtor/assign, then special rules trigger, which 315 // determinethe set of ctor/dtor/assign that can be used by the requester. In particular, 316 // if the user defines a default ctor, then the generated default ctor is unavailable, 317 // likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated 318 // field ctors are available. If the user defines any ctor then the generated default ctor 319 // is unavailable (intrinsic default ctor must be overridden exactly). If the user defines 320 // anything that looks like a copy constructor, then the generated copy constructor is 321 // unavailable, and likewise for the assignment operator. 322 323 // only relevant on function declarations 324 const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( data.id ); 325 if ( ! function ) return true; 326 // only need to perform this check for constructors, destructors, and assignment functions 327 if ( ! CodeGen::isCtorDtorAssign( data.id->name ) ) return true; 328 329 // set up information for this type 330 bool dataIsUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage ); 331 bool dataIsCopyFunc = InitTweak::isCopyFunction( function, function->name ); 332 std::string dataOtypeKey = getOtypeKey( function ); 333 334 if ( dataIsUserDefinedFunc && dataIsCopyFunc ) { 335 // this is a user-defined copy function 336 // if this is the first such, delete/remove non-user-defined overloads as needed 337 std::vector< std::string > removed; 338 std::vector< MangleTable::value_type > deleted; 339 bool alreadyUserDefinedFunc = false; 340 341 for ( const auto& entry : * mangleTable ) { 342 // skip decls that aren't functions or are for the wrong type 343 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); 344 if ( ! decl ) continue; 345 346 bool isCopyFunc = InitTweak::isCopyFunction( decl, decl->name ); 347 if ( ! LinkageSpec::isOverridable( decl->linkage ) ) { 348 // matching user-defined function 349 if ( isCopyFunc ) { 350 // mutation already performed, return early 351 return true; 352 } else { 353 // note that non-copy deletions already performed 354 alreadyUserDefinedFunc = true; 355 } 415 356 } else { 416 return handleConflicts( existing, "duplicate object definition for " ); 417 } // if 418 } // if 419 } else { 420 return handleConflicts( existing, "duplicate definition for " ); 421 } // if 422 357 // non-user-defined function; mark for deletion/removal as appropriate 358 if ( isCopyFunc ) { 359 removed.push_back( entry.first ); 360 } else if ( ! alreadyUserDefinedFunc ) { 361 deleted.push_back( entry ); 362 } 363 } 364 } 365 366 // perform removals from mangle table, and deletions if necessary 367 for ( const auto& key : removed ) { 368 ++* stats().map_mutations; 369 mangleTable = mangleTable->erase( key ); 370 } 371 if ( ! alreadyUserDefinedFunc ) for ( const auto& entry : deleted ) { 372 ++* stats().map_mutations; 373 mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } ); 374 } 375 } else if ( dataIsUserDefinedFunc ) { 376 // this is a user-defined non-copy function 377 // if this is the first user-defined function, delete non-user-defined overloads 378 std::vector< MangleTable::value_type > deleted; 379 380 for ( const auto& entry : * mangleTable ) { 381 // skip decls that aren't functions or are for the wrong type 382 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); 383 if ( ! decl ) continue; 384 385 // exit early if already a matching user-defined function; 386 // earlier function will have mutated table 387 if ( ! LinkageSpec::isOverridable( decl->linkage ) ) return true; 388 389 // skip mutating intrinsic functions 390 if ( decl->linkage == LinkageSpec::Intrinsic ) continue; 391 392 // user-defined non-copy functions do not override copy functions 393 if ( InitTweak::isCopyFunction( decl, decl->name ) ) continue; 394 395 // this function to be deleted after mangleTable iteration is complete 396 deleted.push_back( entry ); 397 } 398 399 // mark deletions to update mangle table 400 // this needs to be a separate loop because of iterator invalidation 401 for ( const auto& entry : deleted ) { 402 ++* stats().map_mutations; 403 mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } ); 404 } 405 } else if ( function->linkage != LinkageSpec::Intrinsic ) { 406 // this is an overridable generated function 407 // if there already exists a matching user-defined function, delete this appropriately 408 for ( const auto& entry : * mangleTable ) { 409 // skip decls that aren't functions or are for the wrong type 410 const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey ); 411 if ( ! decl ) continue; 412 413 // skip non-user-defined functions 414 if ( LinkageSpec::isOverridable( decl->linkage ) ) continue; 415 416 if ( dataIsCopyFunc ) { 417 // remove current function if exists a user-defined copy function 418 // since the signatures for copy functions don't need to match exactly, using 419 // a delete statement is the wrong approach 420 if ( InitTweak::isCopyFunction( decl, decl->name ) ) return false; 421 } else { 422 // mark current function deleted by first user-defined function found 423 data.deleteStmt = decl; 424 return true; 425 } 426 } 427 } 428 429 // nothing (more) to fix, return true 423 430 return true; 424 431 } 425 432 426 void Indexer::addId( DeclarationWithType *decl, ConflictFunction handleConflicts, Expression * baseExpr, BaseSyntaxNode * deleteStmt ) { 427 if ( decl->name == "" ) return; 428 debugPrint( "Adding Id " << decl->name << std::endl ); 429 makeWritable(); 430 433 void Indexer::addId(const DeclarationWithType * decl, OnConflict handleConflicts, const Expression * baseExpr, 434 const Declaration * deleteStmt ) { 435 ++* stats().add_calls; 431 436 const std::string &name = decl->name; 437 if ( name == "" ) return; 438 432 439 std::string mangleName; 433 440 if ( LinkageSpec::isOverridable( decl->linkage ) ) { 434 // mangle the name without including the appropriate suffix, so overridable routines are placed into the435 // same "bucket" as their user defined versions.441 // mangle the name without including the appropriate suffix, so overridable routines 442 // are placed into the same "bucket" as their user defined versions. 436 443 mangleName = Mangler::mangle( decl, false ); 437 444 } else { … … 439 446 } // if 440 447 441 // this ensures that no two declarations with the same unmangled name at the same scope both have C linkage 442 if ( ! LinkageSpec::isMangled( decl->linkage ) ) { 443 // NOTE this is broken in Richard's original code in such a way that it never triggers (it 444 // doesn't check decls that have the same manglename, and all C-linkage decls are defined to 445 // have their name as their manglename, hence the error can never trigger). 446 // The code here is closer to correct, but name mangling would have to be completely 447 // isomorphic to C type-compatibility, which it may not be. 448 if ( hasIncompatibleCDecl( name, mangleName, scope ) ) { 448 // this ensures that no two declarations with the same unmangled name at the same scope 449 // both have C linkage 450 if ( LinkageSpec::isMangled( decl->linkage ) ) { 451 // Check that a Cforall declaration doesn't override any C declaration 452 if ( hasCompatibleCDecl( name, mangleName ) ) { 453 SemanticError( decl, "Cforall declaration hides C function " ); 454 } 455 } else { 456 // NOTE: only correct if name mangling is completely isomorphic to C 457 // type-compatibility, which it may not be. 458 if ( hasIncompatibleCDecl( name, mangleName ) ) { 449 459 SemanticError( decl, "conflicting overload of C function " ); 450 460 } 451 } else { 452 // Check that a Cforall declaration doesn't override any C declaration 453 if ( hasCompatibleCDecl( name, mangleName, scope ) ) { 454 SemanticError( decl, "Cforall declaration hides C function " ); 455 } 456 } 457 458 // Skip repeat declarations of the same identifier 459 IdData * existing = lookupIdAtScope( name, mangleName, scope ); 460 if ( existing && existing->id && addedIdConflicts( *existing, decl, deleteStmt, handleConflicts ) ) return; 461 462 // add to indexer 463 tables->idTable[ name ][ mangleName ] = IdData{ decl, baseExpr, deleteStmt }; 464 ++tables->size; 465 } 466 467 void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) { 461 } 462 463 // ensure tables exist and add identifier 464 MangleTable::Ptr mangleTable; 465 if ( ! idTable ) { 466 idTable = IdTable::new_ptr(); 467 mangleTable = MangleTable::new_ptr(); 468 } else { 469 ++* stats().map_lookups; 470 auto decls = idTable->find( name ); 471 if ( decls == idTable->end() ) { 472 mangleTable = MangleTable::new_ptr(); 473 } else { 474 mangleTable = decls->second; 475 // skip in-scope repeat declarations of same identifier 476 ++* stats().map_lookups; 477 auto existing = mangleTable->find( mangleName ); 478 if ( existing != mangleTable->end() 479 && existing->second.scope == scope 480 && existing->second.id ) { 481 if ( addedIdConflicts( existing->second, decl, handleConflicts, deleteStmt ) ) { 482 if ( handleConflicts.mode == OnConflict::Delete ) { 483 // set delete expression for conflicting identifier 484 lazyInitScope(); 485 * stats().map_mutations += 2; 486 idTable = idTable->set( 487 name, 488 mangleTable->set( 489 mangleName, 490 IdData{ existing->second, handleConflicts.deleteStmt } ) ); 491 } 492 return; 493 } 494 } 495 } 496 } 497 498 // add/overwrite with new identifier 499 lazyInitScope(); 500 IdData data{ decl, baseExpr, deleteStmt, scope }; 501 // Ensure that auto-generated ctor/dtor/assignment are deleted if necessary 502 if ( ! removeSpecialOverrides( data, mangleTable ) ) return; 503 * stats().map_mutations += 2; 504 idTable = idTable->set( name, mangleTable->set( mangleName, std::move(data) ) ); 505 } 506 507 void Indexer::addId( const DeclarationWithType * decl, const Expression * baseExpr ) { 468 508 // default handling of conflicts is to raise an error 469 addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr, decl->isDeleted ? decl : nullptr );470 } 471 472 void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode* deleteStmt ) {509 addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr ); 510 } 511 512 void Indexer::addDeletedId( const DeclarationWithType * decl, const Declaration * deleteStmt ) { 473 513 // default handling of conflicts is to raise an error 474 addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, nullptr, deleteStmt );475 } 476 477 bool addedTypeConflicts( NamedTypeDecl *existing, NamedTypeDecl *added ) {478 if ( existing-> get_base() == 0) {514 addId( decl, OnConflict::error(), nullptr, deleteStmt ); 515 } 516 517 bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) { 518 if ( existing->base == nullptr ) { 479 519 return false; 480 } else if ( added-> get_base() == 0) {520 } else if ( added->base == nullptr ) { 481 521 return true; 482 522 } else { 483 SemanticError( added, "redeclaration of " ); 484 } 485 } 486 487 void Indexer::addType( NamedTypeDecl *decl ) { 488 debugPrint( "Adding type " << decl->name << std::endl ); 489 makeWritable(); 490 491 const std::string &id = decl->get_name(); 492 TypeTable::iterator existing = tables->typeTable.find( id ); 493 if ( existing == tables->typeTable.end() ) { 494 NamedTypeDecl *parent = tables->base.lookupTypeAtScope( id, scope ); 495 if ( ! parent || ! addedTypeConflicts( parent, decl ) ) { 496 tables->typeTable.insert( existing, std::make_pair( id, decl ) ); 497 ++tables->size; 498 } 499 } else { 500 if ( ! addedTypeConflicts( existing->second, decl ) ) { 501 existing->second = decl; 502 } 503 } 504 } 505 506 bool addedDeclConflicts( AggregateDecl *existing, AggregateDecl *added ) { 523 assert( existing->base && added->base ); 524 // typedef redeclarations are errors only if types are different 525 if ( ! ResolvExpr::typesCompatible( existing->base, added->base, Indexer() ) ) { 526 SemanticError( added->location, "redeclaration of " + added->name ); 527 } 528 } 529 // does not need to be added to the table if both existing and added have a base that are 530 // the same 531 return true; 532 } 533 534 void Indexer::addType( const NamedTypeDecl * decl ) { 535 ++* stats().add_calls; 536 const std::string & id = decl->name; 537 538 if ( ! typeTable ) { 539 typeTable = TypeTable::new_ptr(); 540 } else { 541 ++* stats().map_lookups; 542 auto existing = typeTable->find( id ); 543 if ( existing != typeTable->end() 544 && existing->second.scope == scope 545 && addedTypeConflicts( existing->second.decl, decl ) ) return; 546 } 547 548 lazyInitScope(); 549 ++* stats().map_mutations; 550 typeTable = typeTable->set( id, Scoped<NamedTypeDecl>{ decl, scope } ); 551 } 552 553 bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) { 507 554 if ( ! existing->body ) { 508 555 return false; … … 513 560 } 514 561 515 void Indexer::addStruct( const std::string &id ) { 516 debugPrint( "Adding fwd decl for struct " << id << std::endl ); 562 void Indexer::addStruct( const std::string & id ) { 517 563 addStruct( new StructDecl( id ) ); 518 564 } 519 565 520 void Indexer::addStruct( StructDecl *decl ) { 521 debugPrint( "Adding struct " << decl->name << std::endl ); 522 makeWritable(); 523 524 const std::string &id = decl->get_name(); 525 StructTable::iterator existing = tables->structTable.find( id ); 526 if ( existing == tables->structTable.end() ) { 527 StructDecl *parent = tables->base.lookupStructAtScope( id, scope ); 528 if ( ! parent || ! addedDeclConflicts( parent, decl ) ) { 529 tables->structTable.insert( existing, std::make_pair( id, decl ) ); 530 ++tables->size; 531 } 532 } else { 533 if ( ! addedDeclConflicts( existing->second, decl ) ) { 534 existing->second = decl; 535 } 536 } 537 } 538 539 void Indexer::addEnum( EnumDecl *decl ) { 540 debugPrint( "Adding enum " << decl->name << std::endl ); 541 makeWritable(); 542 543 const std::string &id = decl->get_name(); 544 EnumTable::iterator existing = tables->enumTable.find( id ); 545 if ( existing == tables->enumTable.end() ) { 546 EnumDecl *parent = tables->base.lookupEnumAtScope( id, scope ); 547 if ( ! parent || ! addedDeclConflicts( parent, decl ) ) { 548 tables->enumTable.insert( existing, std::make_pair( id, decl ) ); 549 ++tables->size; 550 } 551 } else { 552 if ( ! addedDeclConflicts( existing->second, decl ) ) { 553 existing->second = decl; 554 } 555 } 556 } 557 558 void Indexer::addUnion( const std::string &id ) { 559 debugPrint( "Adding fwd decl for union " << id << std::endl ); 566 void Indexer::addStruct( const StructDecl * decl ) { 567 ++* stats().add_calls; 568 const std::string & id = decl->name; 569 570 if ( ! structTable ) { 571 structTable = StructTable::new_ptr(); 572 } else { 573 ++* stats().map_lookups; 574 auto existing = structTable->find( id ); 575 if ( existing != structTable->end() 576 && existing->second.scope == scope 577 && addedDeclConflicts( existing->second.decl, decl ) ) return; 578 } 579 580 lazyInitScope(); 581 ++* stats().map_mutations; 582 structTable = structTable->set( id, Scoped<StructDecl>{ decl, scope } ); 583 } 584 585 void Indexer::addEnum( const EnumDecl * decl ) { 586 ++* stats().add_calls; 587 const std::string & id = decl->name; 588 589 if ( ! enumTable ) { 590 enumTable = EnumTable::new_ptr(); 591 } else { 592 ++* stats().map_lookups; 593 auto existing = enumTable->find( id ); 594 if ( existing != enumTable->end() 595 && existing->second.scope == scope 596 && addedDeclConflicts( existing->second.decl, decl ) ) return; 597 } 598 599 lazyInitScope(); 600 ++* stats().map_mutations; 601 enumTable = enumTable->set( id, Scoped<EnumDecl>{ decl, scope } ); 602 } 603 604 void Indexer::addUnion( const std::string & id ) { 560 605 addUnion( new UnionDecl( id ) ); 561 606 } 562 607 563 void Indexer::addUnion( UnionDecl *decl ) {564 debugPrint( "Adding union " << decl->name << std::endl );565 makeWritable();566 567 const std::string &id = decl->get_name();568 UnionTable::iterator existing = tables->unionTable.find( id);569 if ( existing == tables->unionTable.end() ){570 UnionDecl *parent = tables->base.lookupUnionAtScope( id, scope );571 if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {572 tables->unionTable.insert( existing, std::make_pair( id, decl ) );573 ++tables->size;574 }575 } else {576 if ( ! addedDeclConflicts( existing->second, decl ) ) { 577 existing->second = decl;578 }579 }580 } 581 582 void Indexer::addTrait( TraitDecl *decl ) {583 debugPrint( "Adding trait " << decl->name << std::endl );584 makeWritable();585 586 const std::string &id = decl->get_name();587 TraitTable::iterator existing = tables->traitTable.find( id);588 if ( existing == tables->traitTable.end() ){589 TraitDecl *parent = tables->base.lookupTraitAtScope( id, scope );590 if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {591 tables->traitTable.insert( existing, std::make_pair( id, decl ) );592 ++tables->size;593 }594 } else {595 if ( ! addedDeclConflicts( existing->second, decl ) ) { 596 existing->second = decl;597 }598 }599 } 600 601 void Indexer::addMembers( AggregateDecl * aggr, Expression * expr, ConflictFunctionhandleConflicts ) {608 void Indexer::addUnion( const UnionDecl * decl ) { 609 ++* stats().add_calls; 610 const std::string & id = decl->name; 611 612 if ( ! unionTable ) { 613 unionTable = UnionTable::new_ptr(); 614 } else { 615 ++* stats().map_lookups; 616 auto existing = unionTable->find( id ); 617 if ( existing != unionTable->end() 618 && existing->second.scope == scope 619 && addedDeclConflicts( existing->second.decl, decl ) ) return; 620 } 621 622 lazyInitScope(); 623 ++* stats().map_mutations; 624 unionTable = unionTable->set( id, Scoped<UnionDecl>{ decl, scope } ); 625 } 626 627 void Indexer::addTrait( const TraitDecl * decl ) { 628 ++* stats().add_calls; 629 const std::string & id = decl->name; 630 631 if ( ! traitTable ) { 632 traitTable = TraitTable::new_ptr(); 633 } else { 634 ++* stats().map_lookups; 635 auto existing = traitTable->find( id ); 636 if ( existing != traitTable->end() 637 && existing->second.scope == scope 638 && addedDeclConflicts( existing->second.decl, decl ) ) return; 639 } 640 641 lazyInitScope(); 642 ++* stats().map_mutations; 643 traitTable = traitTable->set( id, Scoped<TraitDecl>{ decl, scope } ); 644 } 645 646 void Indexer::addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts ) { 602 647 for ( Declaration * decl : aggr->members ) { 603 648 if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) { 604 649 addId( dwt, handleConflicts, expr ); 605 650 if ( dwt->name == "" ) { 606 Type * t = dwt->get_type()->stripReferences();607 if ( dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType *>( t ) ) {651 const Type * t = dwt->get_type()->stripReferences(); 652 if ( dynamic_cast<const StructInstType *>( t ) || dynamic_cast<const UnionInstType *>( t ) ) { 608 653 Expression * base = expr->clone(); 609 654 ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost? … … 616 661 } 617 662 618 void Indexer::addWith( std::list< Expression * > & withExprs, BaseSyntaxNode* withStmt ) {619 for ( Expression * expr : withExprs ) {663 void Indexer::addWith( const std::list< Expression * > & withExprs, const Declaration * withStmt ) { 664 for ( const Expression * expr : withExprs ) { 620 665 if ( expr->result ) { 621 666 AggregateDecl * aggr = expr->result->stripReferences()->getAggr(); 622 667 assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() ); 623 668 624 addMembers( aggr, expr, [withStmt](IdData & existing, const std::string &) { 625 // on conflict, delete the identifier 626 existing.deleteStmt = withStmt; 627 return true; 628 }); 669 addMembers( aggr, expr, OnConflict::deleteWith( withStmt ) ); 629 670 } 630 671 } … … 644 685 } 645 686 646 void Indexer::addFunctionType( FunctionType * ftype ) {687 void Indexer::addFunctionType( const FunctionType * ftype ) { 647 688 addTypes( ftype->forall ); 648 689 addIds( ftype->returnVals ); 649 690 addIds( ftype->parameters ); 650 }651 652 void Indexer::enterScope() {653 ++scope;654 655 if ( doDebug ) {656 std::cerr << "--- Entering scope " << scope << std::endl;657 }658 }659 660 void Indexer::leaveScope() {661 using std::cerr;662 663 assert( scope > 0 && "cannot leave initial scope" );664 if ( doDebug ) {665 cerr << "--- Leaving scope " << scope << " containing" << std::endl;666 }667 --scope;668 669 while ( tables && tables->scope > scope ) {670 if ( doDebug ) {671 dump( tables->idTable, cerr );672 dump( tables->typeTable, cerr );673 dump( tables->structTable, cerr );674 dump( tables->enumTable, cerr );675 dump( tables->unionTable, cerr );676 dump( tables->traitTable, cerr );677 }678 679 // swap tables for base table until we find one at an appropriate scope680 Indexer::Impl *base = newRef( tables->base.tables );681 deleteRef( tables );682 tables = base;683 }684 }685 686 void Indexer::print( std::ostream &os, int indent ) const {687 using std::cerr;688 689 if ( tables ) {690 os << "--- scope " << tables->scope << " ---" << std::endl;691 692 os << "===idTable===" << std::endl;693 dump( tables->idTable, os );694 os << "===typeTable===" << std::endl;695 dump( tables->typeTable, os );696 os << "===structTable===" << std::endl;697 dump( tables->structTable, os );698 os << "===enumTable===" << std::endl;699 dump( tables->enumTable, os );700 os << "===unionTable===" << std::endl;701 dump( tables->unionTable, os );702 os << "===contextTable===" << std::endl;703 dump( tables->traitTable, os );704 705 tables->base.print( os, indent );706 } else {707 os << "--- end ---" << std::endl;708 }709 710 691 } 711 692 … … 715 696 Expression * base = baseExpr->clone(); 716 697 ResolvExpr::referenceToRvalueConversion( base, cost ); 717 ret = new MemberExpr( id, base );698 ret = new MemberExpr( const_cast<DeclarationWithType *>(id), base ); 718 699 // xxx - this introduces hidden environments, for now remove them. 719 700 // std::swap( base->env, ret->env ); … … 721 702 base->env = nullptr; 722 703 } else { 723 ret = new VariableExpr( id);724 } 725 if ( deleteStmt ) ret = new DeletedExpr( ret, deleteStmt);704 ret = new VariableExpr( const_cast<DeclarationWithType *>(id) ); 705 } 706 if ( deleteStmt ) ret = new DeletedExpr( ret, const_cast<Declaration *>(deleteStmt) ); 726 707 return ret; 727 708 }
Note:
See TracChangeset
for help on using the changeset viewer.