/// performNameBinding - Once parsing is complete, this walks the AST to /// resolve names and do other top-level validation. /// /// At this parsing has been performed, but we still have UnresolvedDeclRefExpr /// nodes for unresolved value names, and we may have unresolved type names as /// well. This handles import directives and forward references. void swift::performNameBinding(SourceFile &SF, unsigned StartElem) { // Make sure we skip adding the standard library imports if the // source file is empty. if (SF.ASTStage == SourceFile::NameBound || SF.Decls.empty()) { SF.ASTStage = SourceFile::NameBound; return; } // Reset the name lookup cache so we find new decls. // FIXME: This is inefficient. SF.clearLookupCache(); NameBinder Binder(SF); SmallVector<std::pair<ImportedModule, ImportOptions>, 8> ImportedModules; // Do a prepass over the declarations to find and load the imported modules // and map operator decls. for (auto D : llvm::makeArrayRef(SF.Decls).slice(StartElem)) { if (ImportDecl *ID = dyn_cast<ImportDecl>(D)) { Binder.addImport(ImportedModules, ID); } else if (auto *OD = dyn_cast<PrefixOperatorDecl>(D)) { insertOperatorDecl(Binder, SF.PrefixOperators, OD); } else if (auto *OD = dyn_cast<PostfixOperatorDecl>(D)) { insertOperatorDecl(Binder, SF.PostfixOperators, OD); } else if (auto *OD = dyn_cast<InfixOperatorDecl>(D)) { insertOperatorDecl(Binder, SF.InfixOperators, OD); } } SF.addImports(ImportedModules); // FIXME: This algorithm has quadratic memory usage. (In practice, // import statements after the first "chunk" should be rare, though.) // FIXME: Can we make this more efficient? SF.ASTStage = SourceFile::NameBound; verify(SF); }
/// performNameBinding - Once parsing is complete, this walks the AST to /// resolve names and do other top-level validation. /// /// At this point parsing has been performed, but we still have /// UnresolvedDeclRefExpr nodes for unresolved value names, and we may have /// unresolved type names as well. This handles import directives and forward /// references. void swift::performNameBinding(SourceFile &SF, unsigned StartElem) { SharedTimer timer("Name binding"); // Make sure we skip adding the standard library imports if the // source file is empty. if (SF.ASTStage == SourceFile::NameBound || SF.Decls.empty()) { SF.ASTStage = SourceFile::NameBound; return; } // Reset the name lookup cache so we find new decls. // FIXME: This is inefficient. SF.clearLookupCache(); NameBinder Binder(SF); SmallVector<SourceFile::ImportedModuleDesc, 8> ImportedModules; // Do a prepass over the declarations to find and load the imported modules // and map operator decls. for (auto D : llvm::makeArrayRef(SF.Decls).slice(StartElem)) { if (auto *ID = dyn_cast<ImportDecl>(D)) { Binder.addImport(ImportedModules, ID); } else if (auto *OD = dyn_cast<PrefixOperatorDecl>(D)) { insertOperatorDecl(Binder, SF.PrefixOperators, OD); } else if (auto *OD = dyn_cast<PostfixOperatorDecl>(D)) { insertOperatorDecl(Binder, SF.PostfixOperators, OD); } else if (auto *OD = dyn_cast<InfixOperatorDecl>(D)) { insertOperatorDecl(Binder, SF.InfixOperators, OD); } else if (auto *PGD = dyn_cast<PrecedenceGroupDecl>(D)) { insertPrecedenceGroupDecl(Binder, SF, PGD); } } SF.addImports(ImportedModules); SF.ASTStage = SourceFile::NameBound; verify(SF); }