diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index be581332f0a..b09f5414a46 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -434,6 +434,12 @@ public: return ImportBufferID; } + /// Traverse the decls within this file. + /// + /// \returns true if traversal was aborted, false if it completed + /// successfully. + bool walk(ASTWalker &walker); + private: // Make placement new and vanilla new/delete illegal for SourceFiles. void *operator new(size_t Bytes) throw() = delete; diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h index afe283afe0d..c494fa975ab 100644 --- a/include/swift/Subsystems.h +++ b/include/swift/Subsystems.h @@ -60,14 +60,19 @@ namespace swift { explicit SILParserState(SILModule *M); ~SILParserState(); }; - - /// verify - Check that the translation unit is well formed (i.e. following - /// the invariants of the AST, not that the code written by the user makes - /// sense), aborting and spewing errors if not. - void verify(TranslationUnit *TU); + /// @{ + + /// \brief Check that the translation unit is well formed, aborting and spewing + /// errors if not. + /// + /// "Well-formed" here means following the invariants of the AST, not that the + /// code written by the user makes sense. + void verify(SourceFile &SF); void verify(Decl *D); + /// @} + /// \brief Parse a single buffer into the given translation unit. If the /// translation unit is the main module, stop parsing after the next /// stmt-brace-item with side-effects. @@ -108,10 +113,12 @@ namespace swift { /// automatic imports of the standard library. void performAutoImport(SourceFile &SF); - /// performNameBinding - Once parsing is complete, this walks the AST to - /// resolve names and do other top-level validation. StartElem indicates - /// where to start for incremental name binding in the main module. - void performNameBinding(TranslationUnit *TU, unsigned StartElem = 0); + /// Once parsing is complete, this walks the AST to resolve imports, record + /// operators, and do other top-level validation. + /// + /// \param StartElem Where to start for incremental name binding in the main + /// source file. + void performNameBinding(SourceFile &SF, unsigned StartElem = 0); /// performTypeChecking - Once parsing and namebinding are complete, this /// walks the AST to resolve types and diagnose problems therein. StartElem diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 8676316ea21..640acfeba90 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -1092,13 +1092,18 @@ TranslationUnit::getCachedVisibleDecls() const { bool TranslationUnit::walk(ASTWalker &Walker) { llvm::SaveAndRestore SAR(Walker.Parent, this); - for (Decl *D : MainSourceFile->Decls) { - if (D->walk(Walker)) + return MainSourceFile->walk(Walker); +} + +bool SourceFile::walk(ASTWalker &walker) { + for (Decl *D : Decls) { + if (D->walk(walker)) return true; } return false; } + //===----------------------------------------------------------------------===// // LoadedModule Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/Verifier.cpp b/lib/AST/Verifier.cpp index 6a2b294cd86..ce5c359745d 100644 --- a/lib/AST/Verifier.cpp +++ b/lib/AST/Verifier.cpp @@ -1384,9 +1384,9 @@ namespace { }; } -void swift::verify(TranslationUnit *TU) { - Verifier verifier(TU); - TU->walk(verifier); +void swift::verify(SourceFile &SF) { + Verifier verifier(&SF.TU); + SF.walk(verifier); } void swift::verify(Decl *D) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 11f768b4cf8..7b130791808 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -91,7 +91,7 @@ bool Parser::parseTopLevel() { // Note that the translation unit is fully parsed and verify it. SF.ASTStage = SourceFile::Parsed; - verify(&SF.TU); + verify(SF); State->markParserPosition(Tok.getLoc(), PreviousLoc); diff --git a/lib/Sema/NameBinding.cpp b/lib/Sema/NameBinding.cpp index 474afdcdeca..19dffe39853 100644 --- a/lib/Sema/NameBinding.cpp +++ b/lib/Sema/NameBinding.cpp @@ -43,26 +43,11 @@ typedef llvm::PointerUnion BoundScope; namespace { class NameBinder { public: - TranslationUnit *TU; + SourceFile &SF; ASTContext &Context; - NameBinder(TranslationUnit *TU) : TU(TU), Context(TU->Ctx) { - for (auto importPair : TU->MainSourceFile->getImports()) { - Module *M = importPair.first.second; - // Don't add the builtin module to the LoadedModules list. - if (isa(M)) - continue; - - Module *&ref = Context.LoadedModules[M->Name.str()]; - if (ref) - assert(ref == M || isa(M)); - else - ref = M; - } - } - ~NameBinder() { - } - + NameBinder(SourceFile &SF) : SF(SF), Context(SF.TU.Ctx) {} + template InFlightDiagnostic diagnose(ArgTypes... Args) { return Context.Diags.diagnose(Args...); @@ -82,21 +67,16 @@ NameBinder::getModule(ArrayRef> modulePath) { assert(!modulePath.empty()); auto moduleID = modulePath[0]; - // TODO: We currently just recursively parse referenced modules. This works - // fine for now since they are each a single file. Ultimately we'll want a - // compiled form of AST's like clang's that support lazy deserialization. - // The Builtin module cannot be explicitly imported unless we're a .sil file // or in the REPL. - if ((TU->MainSourceFile->Kind == SourceFile::SIL || - TU->MainSourceFile->Kind == SourceFile::REPL) && + if ((SF.Kind == SourceFile::SIL || SF.Kind == SourceFile::REPL) && moduleID.first.str() == "Builtin") - return TU->Ctx.TheBuiltinModule; + return Context.TheBuiltinModule; // If the imported module name is the same as the current translation unit, // skip the Swift module loader and use the Clang module loader instead. // This allows a Swift module to extend a Clang module of the same name. - if (moduleID.first == TU->Name && modulePath.size() == 1) { + if (moduleID.first == SF.TU.Name && modulePath.size() == 1) { if (auto importer = Context.getClangModuleLoader()) return importer->loadModule(moduleID.second, modulePath); return nullptr; @@ -311,7 +291,7 @@ namespace { /// \brief AST mutation listener that captures any added declarations and /// types, then adds them to the translation unit. class CaptureExternalsListener : public ASTMutationListener { - TranslationUnit *TU; + ASTContext &Ctx; CaptureExternalsListener(const CaptureExternalsListener &) = delete; @@ -319,17 +299,17 @@ namespace { operator=(const CaptureExternalsListener &) = delete; public: - explicit CaptureExternalsListener(TranslationUnit *TU) : TU(TU) { - TU->getASTContext().addMutationListener(*this); + explicit CaptureExternalsListener(ASTContext &ctx) : Ctx(ctx) { + Ctx.addMutationListener(*this); } ~CaptureExternalsListener() { - TU->getASTContext().removeMutationListener(*this); + Ctx.removeMutationListener(*this); } /// \brief A new declaration was added to the AST. virtual void addedExternalDecl(Decl *decl) { - TU->getASTContext().ExternalDefinitions.insert(decl); + Ctx.ExternalDefinitions.insert(decl); } }; } @@ -340,50 +320,51 @@ namespace { /// 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(TranslationUnit *TU, unsigned StartElem) { +void swift::performNameBinding(SourceFile &SF, unsigned StartElem) { // Make sure we skip adding the standard library imports if the // translation unit is empty. - if (TU->MainSourceFile->Decls.empty()) { - TU->MainSourceFile->ASTStage = SourceFile::NameBound; + if (SF.Decls.empty()) { + SF.ASTStage = SourceFile::NameBound; return; } - CaptureExternalsListener Capture(TU); + CaptureExternalsListener Capture(SF.TU.Ctx); // Reset the name lookup cache so we find new decls. // FIXME: This is inefficient. - TU->clearLookupCache(); + SF.TU.clearLookupCache(); - NameBinder Binder(TU); + NameBinder Binder(SF); SmallVector, 8> ImportedModules; - ImportedModules.append(TU->MainSourceFile->getImports().begin(), - TU->MainSourceFile->getImports().end()); + ImportedModules.append(SF.getImports().begin(), SF.getImports().end()); // Do a prepass over the declarations to find and load the imported modules // and map operator decls. - for (unsigned i = StartElem, e = TU->MainSourceFile->Decls.size(); i != e; ++i) { - if (ImportDecl *ID = dyn_cast(TU->MainSourceFile->Decls[i])) { + for (auto D : llvm::makeArrayRef(SF.Decls).slice(StartElem)) { + if (ImportDecl *ID = dyn_cast(D)) { if (auto import = Binder.addImport(ID)) ImportedModules.push_back(*import); - } else if (auto *OD = dyn_cast(TU->MainSourceFile->Decls[i])) - insertOperatorDecl(Binder, TU->MainSourceFile->PrefixOperators, OD); - else if (auto *OD = dyn_cast(TU->MainSourceFile->Decls[i])) - insertOperatorDecl(Binder, TU->MainSourceFile->PostfixOperators, OD); - else if (auto *OD = dyn_cast(TU->MainSourceFile->Decls[i])) - insertOperatorDecl(Binder, TU->MainSourceFile->InfixOperators, OD); + + } else if (auto *OD = dyn_cast(D)) { + insertOperatorDecl(Binder, SF.PrefixOperators, OD); + } else if (auto *OD = dyn_cast(D)) { + insertOperatorDecl(Binder, SF.PostfixOperators, OD); + } else if (auto *OD = dyn_cast(D)) { + insertOperatorDecl(Binder, SF.InfixOperators, OD); + } } - if (ImportedModules.size() > TU->MainSourceFile->getImports().size()) - TU->MainSourceFile->setImports(TU->Ctx.AllocateCopy(ImportedModules)); + if (ImportedModules.size() > SF.getImports().size()) + SF.setImports(SF.TU.Ctx.AllocateCopy(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? llvm::DenseMap CheckTypes; - for (unsigned i = 0, e = TU->MainSourceFile->Decls.size(); i != e; ++i) { - Decl *D = TU->MainSourceFile->Decls[i]; + for (unsigned i = 0, e = SF.Decls.size(); i != e; ++i) { + Decl *D = SF.Decls[i]; if (D->isInvalid()) // No need to diagnose redeclarations of invalid declarations, we have // already complained about them in some other way. @@ -410,7 +391,7 @@ void swift::performNameBinding(TranslationUnit *TU, unsigned StartElem) { } } - TU->MainSourceFile->ASTStage = SourceFile::NameBound; - verify(TU); + SF.ASTStage = SourceFile::NameBound; + verify(SF); } diff --git a/lib/Sema/SourceLoader.cpp b/lib/Sema/SourceLoader.cpp index a61eafe8121..4f13e2108be 100644 --- a/lib/Sema/SourceLoader.cpp +++ b/lib/Sema/SourceLoader.cpp @@ -141,7 +141,7 @@ Module *SourceLoader::loadModule(SourceLoc importLoc, // FIXME: Support recursive definitions in immediate modes by making type // checking even lazier. if (SkipBodies) - performNameBinding(importTU); + performNameBinding(*importFile); else performTypeChecking(importTU); diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 9c1e46740d4..3f1b0bedd1e 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -467,7 +467,7 @@ static bool haveDifferentFixity(const ValueDecl *lhs, const ValueDecl *rhs) { void swift::performTypeChecking(TranslationUnit *TU, unsigned StartElem) { // Make sure that name binding has been completed before doing any type // checking. - performNameBinding(TU, StartElem); + performNameBinding(*TU->MainSourceFile, StartElem); TypeChecker TC(TU->Ctx); auto &DefinedFunctions = TC.definedFunctions;