From ec6c3fb3d7d42965d2e84ffad3ab11e8600b85f2 Mon Sep 17 00:00:00 2001 From: Victoria Mitchell Date: Tue, 18 Jan 2022 08:51:10 -0700 Subject: [PATCH 1/3] Revert "Merge pull request #40877 from apple/revert-40810-QuietMisdreavus/sourcefile-export" This reverts commit caf2f087e3822f0148ababfabe0298e4f26d8f17, reversing changes made to 5a9abb2119ab051f7f0aa77cb88a0cb9928199a2. --- include/swift/AST/FileUnit.h | 4 ++ include/swift/AST/Module.h | 4 ++ include/swift/AST/SourceFile.h | 4 ++ lib/AST/Module.cpp | 65 +++++++++++++++++++ .../ClangImporter/EmitWhileBuilding.swift | 6 +- .../Inputs/EmitWhileBuilding/Extra.swift | 1 + 6 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 test/SymbolGraph/ClangImporter/Inputs/EmitWhileBuilding/Extra.swift diff --git a/include/swift/AST/FileUnit.h b/include/swift/AST/FileUnit.h index 0417ea846368c..51cc26bd8e4f4 100644 --- a/include/swift/AST/FileUnit.h +++ b/include/swift/AST/FileUnit.h @@ -16,6 +16,7 @@ #include "swift/AST/Module.h" #include "swift/AST/RawComment.h" #include "swift/Basic/BasicSourceInfo.h" +#include "swift/Basic/Debug.h" #include "llvm/ADT/PointerIntPair.h" @@ -308,6 +309,9 @@ class FileUnit : public DeclContext, public ASTAllocated { return getParentModule()->getRealName().str(); } + SWIFT_DEBUG_DUMPER(dumpDisplayDecls()); + SWIFT_DEBUG_DUMPER(dumpTopLevelDecls()); + /// Traverse the decls within this file. /// /// \returns true if traversal was aborted, false if it completed diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 46ed457ba8bce..18b985bc372ee 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -26,6 +26,7 @@ #include "swift/AST/Type.h" #include "swift/Basic/BasicSourceInfo.h" #include "swift/Basic/Compiler.h" +#include "swift/Basic/Debug.h" #include "swift/Basic/OptionSet.h" #include "swift/Basic/STLExtras.h" #include "swift/Basic/SourceLoc.h" @@ -856,6 +857,9 @@ class ModuleDecl /// transferred from module files to the dSYMs, remove this. bool isExternallyConsumed() const; + SWIFT_DEBUG_DUMPER(dumpDisplayDecls()); + SWIFT_DEBUG_DUMPER(dumpTopLevelDecls()); + SourceRange getSourceRange() const { return SourceRange(); } static bool classof(const DeclContext *DC) { diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index 99136c7051dba..9b7d221a60c45 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -288,6 +288,10 @@ class SourceFile final : public FileUnit { ~SourceFile(); + bool hasImports() const { + return Imports.hasValue(); + } + /// Retrieve an immutable view of the source file's imports. ArrayRef> getImports() const { return *Imports; diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index a17980982965e..c406e45c9f242 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -780,6 +780,22 @@ void SourceFile::lookupObjCMethods( results.append(known->second.begin(), known->second.end()); } +static void collectParsedExportedImports(const ModuleDecl *M, SmallPtrSetImpl &Imports) { + for (const FileUnit *file : M->getFiles()) { + if (const SourceFile *source = dyn_cast(file)) { + if (source->hasImports()) { + for (auto import : source->getImports()) { + if (import.options.contains(ImportFlags::Exported)) { + if (!Imports.contains(import.module.importedModule)) { + Imports.insert(import.module.importedModule); + } + } + } + } + } + } +} + void ModuleDecl::getLocalTypeDecls(SmallVectorImpl &Results) const { FORWARD(getLocalTypeDecls, (Results)); } @@ -788,6 +804,24 @@ void ModuleDecl::getTopLevelDecls(SmallVectorImpl &Results) const { FORWARD(getTopLevelDecls, (Results)); } +void ModuleDecl::dumpDisplayDecls() const { + SmallVector Decls; + getDisplayDecls(Decls); + for (auto *D : Decls) { + D->dump(llvm::errs()); + llvm::errs() << "\n"; + } +} + +void ModuleDecl::dumpTopLevelDecls() const { + SmallVector Decls; + getTopLevelDecls(Decls); + for (auto *D : Decls) { + D->dump(llvm::errs()); + llvm::errs() << "\n"; + } +} + void ModuleDecl::getExportedPrespecializations( SmallVectorImpl &Results) const { FORWARD(getExportedPrespecializations, (Results)); @@ -908,8 +942,23 @@ SourceFile::getExternalRawLocsForDecl(const Decl *D) const { } void ModuleDecl::getDisplayDecls(SmallVectorImpl &Results) const { + if (isParsedModule(this)) { + SmallPtrSet Modules; + collectParsedExportedImports(this, Modules); + for (const ModuleDecl *import : Modules) { + import->getDisplayDecls(Results); + } + } // FIXME: Should this do extra access control filtering? FORWARD(getDisplayDecls, (Results)); + +#ifndef NDEBUG + llvm::DenseSet visited; + for (auto *D : Results) { + auto inserted = visited.insert(D).second; + assert(inserted && "there should be no duplicate decls"); + } +#endif } ProtocolConformanceRef @@ -3066,6 +3115,22 @@ void FileUnit::getTopLevelDeclsWhereAttributesMatch( Results.erase(newEnd, Results.end()); } +void FileUnit::dumpDisplayDecls() const { + SmallVector Decls; + getDisplayDecls(Decls); + for (auto *D : Decls) { + D->dump(llvm::errs()); + } +} + +void FileUnit::dumpTopLevelDecls() const { + SmallVector Decls; + getTopLevelDecls(Decls); + for (auto *D : Decls) { + D->dump(llvm::errs()); + } +} + void swift::simple_display(llvm::raw_ostream &out, const FileUnit *file) { if (!file) { out << "(null)"; diff --git a/test/SymbolGraph/ClangImporter/EmitWhileBuilding.swift b/test/SymbolGraph/ClangImporter/EmitWhileBuilding.swift index f44a3bdcf9b62..7c39f50551537 100644 --- a/test/SymbolGraph/ClangImporter/EmitWhileBuilding.swift +++ b/test/SymbolGraph/ClangImporter/EmitWhileBuilding.swift @@ -1,8 +1,9 @@ // RUN: %empty-directory(%t) // RUN: cp -r %S/Inputs/EmitWhileBuilding/EmitWhileBuilding.framework %t -// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-objc-interop -emit-module-path %t/EmitWhileBuilding.framework/Modules/EmitWhileBuilding.swiftmodule/%target-swiftmodule-name -import-underlying-module -F %t -module-name EmitWhileBuilding -disable-objc-attr-requires-foundation-module %s -emit-symbol-graph -emit-symbol-graph-dir %t +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-objc-interop -emit-module-path %t/EmitWhileBuilding.framework/Modules/EmitWhileBuilding.swiftmodule/%target-swiftmodule-name -import-underlying-module -F %t -module-name EmitWhileBuilding -disable-objc-attr-requires-foundation-module %s %S/Inputs/EmitWhileBuilding/Extra.swift -emit-symbol-graph -emit-symbol-graph-dir %t // RUN: %{python} -m json.tool %t/EmitWhileBuilding.symbols.json %t/EmitWhileBuilding.formatted.symbols.json // RUN: %FileCheck %s --input-file %t/EmitWhileBuilding.formatted.symbols.json +// RUN: %FileCheck %s --input-file %t/EmitWhileBuilding.formatted.symbols.json --check-prefix HEADER // REQUIRES: objc_interop @@ -10,6 +11,9 @@ import Foundation public enum SwiftEnum {} +// HEADER: "precise": "c:@testVariable" + +// CHECK: "precise": "s:17EmitWhileBuilding9SwiftEnumO", // CHECK: "declarationFragments": [ // CHECK-NEXT: { // CHECK-NEXT: "kind": "keyword", diff --git a/test/SymbolGraph/ClangImporter/Inputs/EmitWhileBuilding/Extra.swift b/test/SymbolGraph/ClangImporter/Inputs/EmitWhileBuilding/Extra.swift new file mode 100644 index 0000000000000..7a0e59c907c0b --- /dev/null +++ b/test/SymbolGraph/ClangImporter/Inputs/EmitWhileBuilding/Extra.swift @@ -0,0 +1 @@ +public struct SomeStruct {} From aeaf6b22db0f43da41ab209070910a5b6b559ca1 Mon Sep 17 00:00:00 2001 From: Victoria Mitchell Date: Fri, 14 Jan 2022 16:28:04 -0700 Subject: [PATCH 2/3] [AST] check modules before recursing for display decls --- include/swift/AST/FileUnit.h | 2 ++ include/swift/AST/Module.h | 9 +++++++++ include/swift/ClangImporter/ClangModule.h | 2 ++ lib/AST/Module.cpp | 16 ++++++++++++---- lib/ClangImporter/ClangImporter.cpp | 2 ++ 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/swift/AST/FileUnit.h b/include/swift/AST/FileUnit.h index 51cc26bd8e4f4..a736e10bbbd27 100644 --- a/include/swift/AST/FileUnit.h +++ b/include/swift/AST/FileUnit.h @@ -189,6 +189,8 @@ class FileUnit : public DeclContext, public ASTAllocated { virtual Identifier getDiscriminatorForPrivateValue(const ValueDecl *D) const = 0; + virtual bool shouldCollectDisplayDecls() const { return true; } + /// Finds all top-level decls in this file. /// /// This does a simple local lookup, not recursively looking through imports. diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 18b985bc372ee..31e7c6391ec88 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -760,6 +760,15 @@ class ModuleDecl /// The order of the results is not guaranteed to be meaningful. void getPrecedenceGroups(SmallVectorImpl &Results) const; + /// Determines whether this module should be recursed into when calling + /// \c getDisplayDecls. + /// + /// Some modules should not call \c getDisplayDecls, due to assertions + /// in their implementation. These are usually implicit imports that would be + /// recursed into for parsed modules. This function provides a guard against + /// recusing into modules that should not have decls collected. + bool shouldCollectDisplayDecls() const; + /// Finds all top-level decls that should be displayed to a client of this /// module. /// diff --git a/include/swift/ClangImporter/ClangModule.h b/include/swift/ClangImporter/ClangModule.h index c714765946170..21e93ba159f57 100644 --- a/include/swift/ClangImporter/ClangModule.h +++ b/include/swift/ClangImporter/ClangModule.h @@ -87,6 +87,8 @@ class ClangModuleUnit final : public LoadedFile { ObjCSelector selector, SmallVectorImpl &results) const override; + virtual bool shouldCollectDisplayDecls() const override; + virtual void getTopLevelDecls(SmallVectorImpl &results) const override; virtual void getDisplayDecls(SmallVectorImpl &results) const override; diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index c406e45c9f242..4da86aed85e8f 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -780,15 +780,23 @@ void SourceFile::lookupObjCMethods( results.append(known->second.begin(), known->second.end()); } +bool ModuleDecl::shouldCollectDisplayDecls() const { + for (const FileUnit *file : Files) { + if (!file->shouldCollectDisplayDecls()) + return false; + } + return true; +} + static void collectParsedExportedImports(const ModuleDecl *M, SmallPtrSetImpl &Imports) { for (const FileUnit *file : M->getFiles()) { if (const SourceFile *source = dyn_cast(file)) { if (source->hasImports()) { for (auto import : source->getImports()) { - if (import.options.contains(ImportFlags::Exported)) { - if (!Imports.contains(import.module.importedModule)) { - Imports.insert(import.module.importedModule); - } + if (import.options.contains(ImportFlags::Exported) && + !Imports.contains(import.module.importedModule) && + import.module.importedModule->shouldCollectDisplayDecls()) { + Imports.insert(import.module.importedModule); } } } diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 40a852d2161db..0c2c12ac1d636 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -3120,6 +3120,8 @@ class VectorDeclPtrConsumer : public swift::VisibleDeclConsumer { }; } // unnamed namespace +bool ClangModuleUnit::shouldCollectDisplayDecls() const { return isTopLevel(); } + void ClangModuleUnit::getTopLevelDecls(SmallVectorImpl &results) const { VectorDeclPtrConsumer consumer(results); FilteringDeclaredDeclConsumer filterConsumer(consumer, this); From 7338eb02b7cdc85beed0a23790ca6d0b6bad123c Mon Sep 17 00:00:00 2001 From: Victoria Mitchell Date: Wed, 19 Jan 2022 16:07:31 -0700 Subject: [PATCH 3/3] add test for top-level decls of Clang submodules --- lib/ClangImporter/ClangImporter.cpp | 1 + .../ClangImporter/Inputs/Submodules/Mixed.h | 1 + .../ClangImporter/Inputs/Submodules/Submodule.h | 1 + .../ClangImporter/Inputs/Submodules/module.modulemap | 9 +++++++++ test/SymbolGraph/ClangImporter/Submodules.swift | 11 +++++++++++ 5 files changed, 23 insertions(+) create mode 100644 test/SymbolGraph/ClangImporter/Inputs/Submodules/Mixed.h create mode 100644 test/SymbolGraph/ClangImporter/Inputs/Submodules/Submodule.h create mode 100644 test/SymbolGraph/ClangImporter/Inputs/Submodules/module.modulemap create mode 100644 test/SymbolGraph/ClangImporter/Submodules.swift diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 0c2c12ac1d636..a2fb22a20a0b5 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -3120,6 +3120,7 @@ class VectorDeclPtrConsumer : public swift::VisibleDeclConsumer { }; } // unnamed namespace +// FIXME: should submodules still be crawled for the symbol graph? (SR-15753) bool ClangModuleUnit::shouldCollectDisplayDecls() const { return isTopLevel(); } void ClangModuleUnit::getTopLevelDecls(SmallVectorImpl &results) const { diff --git a/test/SymbolGraph/ClangImporter/Inputs/Submodules/Mixed.h b/test/SymbolGraph/ClangImporter/Inputs/Submodules/Mixed.h new file mode 100644 index 0000000000000..8b6286de54516 --- /dev/null +++ b/test/SymbolGraph/ClangImporter/Inputs/Submodules/Mixed.h @@ -0,0 +1 @@ +double outerVar = 1.0; diff --git a/test/SymbolGraph/ClangImporter/Inputs/Submodules/Submodule.h b/test/SymbolGraph/ClangImporter/Inputs/Submodules/Submodule.h new file mode 100644 index 0000000000000..84aa726df85f8 --- /dev/null +++ b/test/SymbolGraph/ClangImporter/Inputs/Submodules/Submodule.h @@ -0,0 +1 @@ +double innerVar = 2.0; diff --git a/test/SymbolGraph/ClangImporter/Inputs/Submodules/module.modulemap b/test/SymbolGraph/ClangImporter/Inputs/Submodules/module.modulemap new file mode 100644 index 0000000000000..39d64cf87a85f --- /dev/null +++ b/test/SymbolGraph/ClangImporter/Inputs/Submodules/module.modulemap @@ -0,0 +1,9 @@ +module Mixed { + header "Mixed.h" + export * + + explicit module Submodule { + header "Submodule.h" + export * + } +} diff --git a/test/SymbolGraph/ClangImporter/Submodules.swift b/test/SymbolGraph/ClangImporter/Submodules.swift new file mode 100644 index 0000000000000..27e6c125def1f --- /dev/null +++ b/test/SymbolGraph/ClangImporter/Submodules.swift @@ -0,0 +1,11 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/Submodules -emit-module-path %t/Submodules.swiftmodule -enable-objc-interop -module-name Submodules %s -emit-symbol-graph -emit-symbol-graph-dir %t + +// REQUIRES: objc_interop + +// Don't crash when a module declared an `@_exported import` for a Clang non-top-level module. + +@_exported import Mixed +@_exported import Mixed.Submodule + +public func someFunc() {}