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