Skip to content

Commit c99089c

Browse files
Merge pull request #40860 from apple/QuietMisdreavus/display-decl-recur
[AST] check modules before recursing for display decls rdar://87601741
2 parents a8cde12 + 7338eb0 commit c99089c

File tree

12 files changed

+129
-1
lines changed

12 files changed

+129
-1
lines changed

include/swift/AST/FileUnit.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "swift/AST/Module.h"
1717
#include "swift/AST/RawComment.h"
1818
#include "swift/Basic/BasicSourceInfo.h"
19+
#include "swift/Basic/Debug.h"
1920

2021
#include "llvm/ADT/PointerIntPair.h"
2122

@@ -188,6 +189,8 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
188189
virtual Identifier
189190
getDiscriminatorForPrivateValue(const ValueDecl *D) const = 0;
190191

192+
virtual bool shouldCollectDisplayDecls() const { return true; }
193+
191194
/// Finds all top-level decls in this file.
192195
///
193196
/// This does a simple local lookup, not recursively looking through imports.
@@ -308,6 +311,9 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
308311
return getParentModule()->getRealName().str();
309312
}
310313

314+
SWIFT_DEBUG_DUMPER(dumpDisplayDecls());
315+
SWIFT_DEBUG_DUMPER(dumpTopLevelDecls());
316+
311317
/// Traverse the decls within this file.
312318
///
313319
/// \returns true if traversal was aborted, false if it completed

include/swift/AST/Module.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "swift/AST/Type.h"
2727
#include "swift/Basic/BasicSourceInfo.h"
2828
#include "swift/Basic/Compiler.h"
29+
#include "swift/Basic/Debug.h"
2930
#include "swift/Basic/OptionSet.h"
3031
#include "swift/Basic/STLExtras.h"
3132
#include "swift/Basic/SourceLoc.h"
@@ -759,6 +760,15 @@ class ModuleDecl
759760
/// The order of the results is not guaranteed to be meaningful.
760761
void getPrecedenceGroups(SmallVectorImpl<PrecedenceGroupDecl*> &Results) const;
761762

763+
/// Determines whether this module should be recursed into when calling
764+
/// \c getDisplayDecls.
765+
///
766+
/// Some modules should not call \c getDisplayDecls, due to assertions
767+
/// in their implementation. These are usually implicit imports that would be
768+
/// recursed into for parsed modules. This function provides a guard against
769+
/// recusing into modules that should not have decls collected.
770+
bool shouldCollectDisplayDecls() const;
771+
762772
/// Finds all top-level decls that should be displayed to a client of this
763773
/// module.
764774
///
@@ -856,6 +866,9 @@ class ModuleDecl
856866
/// transferred from module files to the dSYMs, remove this.
857867
bool isExternallyConsumed() const;
858868

869+
SWIFT_DEBUG_DUMPER(dumpDisplayDecls());
870+
SWIFT_DEBUG_DUMPER(dumpTopLevelDecls());
871+
859872
SourceRange getSourceRange() const { return SourceRange(); }
860873

861874
static bool classof(const DeclContext *DC) {

include/swift/AST/SourceFile.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,10 @@ class SourceFile final : public FileUnit {
288288

289289
~SourceFile();
290290

291+
bool hasImports() const {
292+
return Imports.hasValue();
293+
}
294+
291295
/// Retrieve an immutable view of the source file's imports.
292296
ArrayRef<AttributedImport<ImportedModule>> getImports() const {
293297
return *Imports;

include/swift/ClangImporter/ClangModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ class ClangModuleUnit final : public LoadedFile {
8787
ObjCSelector selector,
8888
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
8989

90+
virtual bool shouldCollectDisplayDecls() const override;
91+
9092
virtual void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
9193

9294
virtual void getDisplayDecls(SmallVectorImpl<Decl*> &results) const override;

lib/AST/Module.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,30 @@ void SourceFile::lookupObjCMethods(
780780
results.append(known->second.begin(), known->second.end());
781781
}
782782

783+
bool ModuleDecl::shouldCollectDisplayDecls() const {
784+
for (const FileUnit *file : Files) {
785+
if (!file->shouldCollectDisplayDecls())
786+
return false;
787+
}
788+
return true;
789+
}
790+
791+
static void collectParsedExportedImports(const ModuleDecl *M, SmallPtrSetImpl<ModuleDecl *> &Imports) {
792+
for (const FileUnit *file : M->getFiles()) {
793+
if (const SourceFile *source = dyn_cast<SourceFile>(file)) {
794+
if (source->hasImports()) {
795+
for (auto import : source->getImports()) {
796+
if (import.options.contains(ImportFlags::Exported) &&
797+
!Imports.contains(import.module.importedModule) &&
798+
import.module.importedModule->shouldCollectDisplayDecls()) {
799+
Imports.insert(import.module.importedModule);
800+
}
801+
}
802+
}
803+
}
804+
}
805+
}
806+
783807
void ModuleDecl::getLocalTypeDecls(SmallVectorImpl<TypeDecl*> &Results) const {
784808
FORWARD(getLocalTypeDecls, (Results));
785809
}
@@ -788,6 +812,24 @@ void ModuleDecl::getTopLevelDecls(SmallVectorImpl<Decl*> &Results) const {
788812
FORWARD(getTopLevelDecls, (Results));
789813
}
790814

815+
void ModuleDecl::dumpDisplayDecls() const {
816+
SmallVector<Decl *, 32> Decls;
817+
getDisplayDecls(Decls);
818+
for (auto *D : Decls) {
819+
D->dump(llvm::errs());
820+
llvm::errs() << "\n";
821+
}
822+
}
823+
824+
void ModuleDecl::dumpTopLevelDecls() const {
825+
SmallVector<Decl *, 32> Decls;
826+
getTopLevelDecls(Decls);
827+
for (auto *D : Decls) {
828+
D->dump(llvm::errs());
829+
llvm::errs() << "\n";
830+
}
831+
}
832+
791833
void ModuleDecl::getExportedPrespecializations(
792834
SmallVectorImpl<Decl *> &Results) const {
793835
FORWARD(getExportedPrespecializations, (Results));
@@ -908,8 +950,23 @@ SourceFile::getExternalRawLocsForDecl(const Decl *D) const {
908950
}
909951

910952
void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results) const {
953+
if (isParsedModule(this)) {
954+
SmallPtrSet<ModuleDecl *, 4> Modules;
955+
collectParsedExportedImports(this, Modules);
956+
for (const ModuleDecl *import : Modules) {
957+
import->getDisplayDecls(Results);
958+
}
959+
}
911960
// FIXME: Should this do extra access control filtering?
912961
FORWARD(getDisplayDecls, (Results));
962+
963+
#ifndef NDEBUG
964+
llvm::DenseSet<Decl *> visited;
965+
for (auto *D : Results) {
966+
auto inserted = visited.insert(D).second;
967+
assert(inserted && "there should be no duplicate decls");
968+
}
969+
#endif
913970
}
914971

915972
ProtocolConformanceRef
@@ -3066,6 +3123,22 @@ void FileUnit::getTopLevelDeclsWhereAttributesMatch(
30663123
Results.erase(newEnd, Results.end());
30673124
}
30683125

3126+
void FileUnit::dumpDisplayDecls() const {
3127+
SmallVector<Decl *, 32> Decls;
3128+
getDisplayDecls(Decls);
3129+
for (auto *D : Decls) {
3130+
D->dump(llvm::errs());
3131+
}
3132+
}
3133+
3134+
void FileUnit::dumpTopLevelDecls() const {
3135+
SmallVector<Decl *, 32> Decls;
3136+
getTopLevelDecls(Decls);
3137+
for (auto *D : Decls) {
3138+
D->dump(llvm::errs());
3139+
}
3140+
}
3141+
30693142
void swift::simple_display(llvm::raw_ostream &out, const FileUnit *file) {
30703143
if (!file) {
30713144
out << "(null)";

lib/ClangImporter/ClangImporter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3124,6 +3124,9 @@ class VectorDeclPtrConsumer : public swift::VisibleDeclConsumer {
31243124
};
31253125
} // unnamed namespace
31263126

3127+
// FIXME: should submodules still be crawled for the symbol graph? (SR-15753)
3128+
bool ClangModuleUnit::shouldCollectDisplayDecls() const { return isTopLevel(); }
3129+
31273130
void ClangModuleUnit::getTopLevelDecls(SmallVectorImpl<Decl*> &results) const {
31283131
VectorDeclPtrConsumer consumer(results);
31293132
FilteringDeclaredDeclConsumer filterConsumer(consumer, this);

test/SymbolGraph/ClangImporter/EmitWhileBuilding.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
// RUN: %empty-directory(%t)
22
// RUN: cp -r %S/Inputs/EmitWhileBuilding/EmitWhileBuilding.framework %t
3-
// 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
3+
// 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
44
// RUN: %{python} -m json.tool %t/EmitWhileBuilding.symbols.json %t/EmitWhileBuilding.formatted.symbols.json
55
// RUN: %FileCheck %s --input-file %t/EmitWhileBuilding.formatted.symbols.json
6+
// RUN: %FileCheck %s --input-file %t/EmitWhileBuilding.formatted.symbols.json --check-prefix HEADER
67

78
// REQUIRES: objc_interop
89

910
import Foundation
1011

1112
public enum SwiftEnum {}
1213

14+
// HEADER: "precise": "c:@testVariable"
15+
16+
// CHECK: "precise": "s:17EmitWhileBuilding9SwiftEnumO",
1317
// CHECK: "declarationFragments": [
1418
// CHECK-NEXT: {
1519
// CHECK-NEXT: "kind": "keyword",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public struct SomeStruct {}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
double outerVar = 1.0;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
double innerVar = 2.0;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module Mixed {
2+
header "Mixed.h"
3+
export *
4+
5+
explicit module Submodule {
6+
header "Submodule.h"
7+
export *
8+
}
9+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %empty-directory(%t)
2+
// 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
3+
4+
// REQUIRES: objc_interop
5+
6+
// Don't crash when a module declared an `@_exported import` for a Clang non-top-level module.
7+
8+
@_exported import Mixed
9+
@_exported import Mixed.Submodule
10+
11+
public func someFunc() {}

0 commit comments

Comments
 (0)