@@ -108,14 +108,16 @@ static bool contributesToParentTypeStorage(const AbstractStorageDecl *ASD) {
108
108
return !ND->isResilient () && ASD->hasStorage () && !ASD->isStatic ();
109
109
}
110
110
111
- PrintOptions PrintOptions::printSwiftInterfaceFile (bool preferTypeRepr,
111
+ PrintOptions PrintOptions::printSwiftInterfaceFile (ModuleDecl *ModuleToPrint,
112
+ bool preferTypeRepr,
112
113
bool printFullConvention,
113
114
bool printSPIs) {
114
115
PrintOptions result;
115
116
result.IsForSwiftInterface = true ;
116
117
result.PrintLongAttrsOnSeparateLines = true ;
117
118
result.TypeDefinitions = true ;
118
119
result.PrintIfConfig = false ;
120
+ result.CurrentModule = ModuleToPrint;
119
121
result.FullyQualifiedTypes = true ;
120
122
result.UseExportedModuleNames = true ;
121
123
result.AllowNullTypes = false ;
@@ -3649,6 +3651,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
3649
3651
3650
3652
ASTPrinter &Printer;
3651
3653
const PrintOptions &Options;
3654
+ Optional<llvm::DenseMap<const clang::Module *, ModuleDecl *>>
3655
+ VisibleClangModules;
3652
3656
3653
3657
void printGenericArgs (ArrayRef<Type> Args) {
3654
3658
if (Args.empty ())
@@ -3679,7 +3683,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
3679
3683
}
3680
3684
}
3681
3685
3682
- // / Determinee whether the given type has a simple representation
3686
+ // / Determine whether the given type has a simple representation
3683
3687
// / under the current print options.
3684
3688
bool isSimpleUnderPrintOptions (Type T) {
3685
3689
if (auto typealias = dyn_cast<TypeAliasType>(T.getPointer ())) {
@@ -3701,19 +3705,100 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
3701
3705
return T->hasSimpleTypeRepr ();
3702
3706
}
3703
3707
3708
+ // / Computes the map that is cached by `getVisibleClangModules()`.
3709
+ // / Do not call directly.
3710
+ llvm::DenseMap<const clang::Module *, ModuleDecl *>
3711
+ computeVisibleClangModules () {
3712
+ assert (Options.CurrentModule &&
3713
+ " CurrentModule needs to be set to determine imported Clang modules" );
3714
+
3715
+ llvm::DenseMap<const clang::Module *, ModuleDecl *> Result;
3716
+
3717
+ // For the current module, consider both private and public imports.
3718
+ ModuleDecl::ImportFilter Filter = ModuleDecl::ImportFilterKind::Exported;
3719
+ Filter |= ModuleDecl::ImportFilterKind::Default;
3720
+ Filter |= ModuleDecl::ImportFilterKind::SPIAccessControl;
3721
+ SmallVector<ImportedModule, 4 > Imports;
3722
+ Options.CurrentModule ->getImportedModules (Imports, Filter);
3723
+
3724
+ SmallVector<ModuleDecl *, 4 > ModulesToProcess;
3725
+ for (const auto &Import : Imports) {
3726
+ ModulesToProcess.push_back (Import.importedModule );
3727
+ }
3728
+
3729
+ SmallPtrSet<ModuleDecl *, 4 > Processed;
3730
+ while (!ModulesToProcess.empty ()) {
3731
+ ModuleDecl *Mod = ModulesToProcess.back ();
3732
+ ModulesToProcess.pop_back ();
3733
+
3734
+ if (!Processed.insert (Mod).second )
3735
+ continue ;
3736
+
3737
+ if (const clang::Module *ClangModule = Mod->findUnderlyingClangModule ())
3738
+ Result[ClangModule] = Mod;
3739
+
3740
+ // For transitive imports, consider only public imports.
3741
+ Imports.clear ();
3742
+ Mod->getImportedModules (Imports, ModuleDecl::ImportFilterKind::Exported);
3743
+ for (const auto &Import : Imports) {
3744
+ ModulesToProcess.push_back (Import.importedModule );
3745
+ }
3746
+ }
3747
+
3748
+ return Result;
3749
+ }
3750
+
3751
+ // / Returns all Clang modules that are visible from `Options.CurrentModule`.
3752
+ // / This includes any modules that are imported transitively through public
3753
+ // / (`@_exported`) imports.
3754
+ // /
3755
+ // / The returned map associates each visible Clang module with the
3756
+ // / corresponding Swift module.
3757
+ const llvm::DenseMap<const clang::Module *, ModuleDecl *> &
3758
+ getVisibleClangModules () {
3759
+ if (!VisibleClangModules) {
3760
+ VisibleClangModules = computeVisibleClangModules ();
3761
+ }
3762
+ return *VisibleClangModules;
3763
+ }
3764
+
3704
3765
template <typename T>
3705
3766
void printModuleContext (T *Ty) {
3706
3767
FileUnit *File = cast<FileUnit>(Ty->getDecl ()->getModuleScopeContext ());
3707
3768
ModuleDecl *Mod = File->getParentModule ();
3769
+ StringRef ExportedModuleName = File->getExportedModuleName ();
3770
+
3771
+ // Clang declarations need special treatment: Multiple Clang modules can
3772
+ // contain the same declarations from a textually included header, but not
3773
+ // all of these modules may be visible. We therefore need to make sure we
3774
+ // choose a module that is visible from the current module. This is possible
3775
+ // only if we know what the current module is.
3776
+ const clang::Decl *ClangDecl = Ty->getDecl ()->getClangDecl ();
3777
+ if (ClangDecl && Options.CurrentModule ) {
3778
+ for (auto *Redecl : ClangDecl->redecls ()) {
3779
+ clang::Module *ClangModule =
3780
+ Redecl->getOwningModule ()->getTopLevelModule ();
3781
+ if (!ClangModule)
3782
+ continue ;
3783
+
3784
+ if (ModuleDecl *VisibleModule =
3785
+ getVisibleClangModules ().lookup (ClangModule)) {
3786
+ Mod = VisibleModule;
3787
+ ExportedModuleName = ClangModule->ExportAsModule ;
3788
+ break ;
3789
+ }
3790
+ }
3791
+ }
3708
3792
3709
3793
if (Options.MapCrossImportOverlaysToDeclaringModule ) {
3710
3794
if (ModuleDecl *Declaring = Mod->getDeclaringModuleIfCrossImportOverlay ())
3711
3795
Mod = Declaring;
3712
3796
}
3713
3797
3714
3798
Identifier Name = Mod->getName ();
3715
- if (Options.UseExportedModuleNames )
3716
- Name = Mod->getASTContext ().getIdentifier (File->getExportedModuleName ());
3799
+ if (Options.UseExportedModuleNames && !ExportedModuleName.empty ()) {
3800
+ Name = Mod->getASTContext ().getIdentifier (ExportedModuleName);
3801
+ }
3717
3802
3718
3803
Printer.printModuleRef (Mod, Name);
3719
3804
Printer << " ." ;
0 commit comments