@@ -63,23 +63,43 @@ int symbolgraphgen::emitSymbolGraphForModule(
63
63
ModuleDecl *M, const SymbolGraphOptions &Options) {
64
64
ModuleDecl::ImportCollector importCollector (Options.MinimumAccessLevel );
65
65
66
- bool IncludeClangSubmodules = false ;
67
- if (auto *ClangModule = M->findUnderlyingClangModule ()) {
68
- // If a Clang module has a definition that includes `export *; module * {
69
- // export *; }` then we want to treat those inferred submodules as part of
70
- // the parent module, to preserve historical behavior.
71
- if (ClangModule->InferSubmodules && ClangModule->InferExportWildcard ) {
72
- IncludeClangSubmodules = true ;
66
+ SmallPtrSet<const clang::Module *, 2 > ExportedClangModules = {};
67
+ SmallPtrSet<const clang::Module *, 2 > WildcardExportClangModules = {};
68
+ if (const auto *ClangModule = M->findUnderlyingClangModule ()) {
69
+ // Scan through the Clang module's exports and collect them for later
70
+ // handling
71
+ for (auto ClangExport : ClangModule->Exports ) {
72
+ if (ClangExport.getInt ()) {
73
+ // Blanket exports are represented as a true boolean tag
74
+ if (const auto *ExportParent = ClangExport.getPointer ()) {
75
+ // If a pointer is present, this is a scoped blanket export, like
76
+ // `export Submodule.*`
77
+ WildcardExportClangModules.insert (ExportParent);
78
+ } else {
79
+ // Otherwise it represents a full blanket `export *`
80
+ WildcardExportClangModules.insert (ClangModule);
81
+ }
82
+ } else if (!ClangExport.getInt () && ClangExport.getPointer ()) {
83
+ // This is an explicit `export Submodule`
84
+ ExportedClangModules.insert (ClangExport.getPointer ());
85
+ }
73
86
}
74
87
}
75
88
76
- auto importFilter = [&Options, &IncludeClangSubmodules ,
77
- &M ](const ModuleDecl *module ) {
89
+ auto importFilter = [&Options, &WildcardExportClangModules ,
90
+ &ExportedClangModules ](const ModuleDecl *module ) {
78
91
if (!module )
79
92
return false ;
80
93
81
- if (IncludeClangSubmodules && module ->isSubmoduleOf (M)) {
82
- return true ;
94
+ if (const auto *ClangModule = module ->findUnderlyingClangModule ()) {
95
+ if (ExportedClangModules.contains (ClangModule)) {
96
+ return true ;
97
+ }
98
+
99
+ for (const auto *ClangParent : WildcardExportClangModules) {
100
+ if (ClangModule->isSubModuleOf (ClangParent))
101
+ return true ;
102
+ }
83
103
}
84
104
85
105
if (Options.AllowedReexportedModules .has_value ())
@@ -90,7 +110,8 @@ int symbolgraphgen::emitSymbolGraphForModule(
90
110
return false ;
91
111
};
92
112
93
- if (Options.AllowedReexportedModules .has_value () || IncludeClangSubmodules)
113
+ if (Options.AllowedReexportedModules .has_value () ||
114
+ !WildcardExportClangModules.empty () || !ExportedClangModules.empty ())
94
115
importCollector.importFilter = std::move (importFilter);
95
116
96
117
SmallVector<Decl *, 64 > ModuleDecls;
0 commit comments