@@ -173,57 +173,53 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) {
173
173
174
174
const HeaderSearch &HS = PP.getHeaderSearchInfo ();
175
175
const ModuleMap &MM = HS.getModuleMap ();
176
- const SourceManager &SourceMgr = PP.getSourceManager ();
177
176
178
177
std::set<const FileEntry *> ModuleMaps;
179
- auto CollectIncludingModuleMaps = [&](FileID FID, FileEntryRef F) {
180
- if (!ModuleMaps.insert (F).second )
178
+ std::set<const Module *> ProcessedModules;
179
+ auto CollectModuleMapsForHierarchy = [&](const Module *M) {
180
+ M = M->getTopLevelModule ();
181
+
182
+ if (!ProcessedModules.insert (M).second )
181
183
return ;
182
- SourceLocation Loc = SourceMgr.getIncludeLoc (FID);
183
- // The include location of inferred module maps can point into the header
184
- // file that triggered the inferring. Cut off the walk if that's the case.
185
- while (Loc.isValid () && isModuleMap (SourceMgr.getFileCharacteristic (Loc))) {
186
- FID = SourceMgr.getFileID (Loc);
187
- F = *SourceMgr.getFileEntryRefForID (FID);
188
- if (!ModuleMaps.insert (F).second )
189
- break ;
190
- Loc = SourceMgr.getIncludeLoc (FID);
191
- }
192
- };
193
184
194
- std::set<const Module *> ProcessedModules;
195
- auto CollectIncludingMapsFromAncestors = [&](const Module *M) {
196
- for (const Module *Mod = M; Mod; Mod = Mod->Parent ) {
197
- if (!ProcessedModules.insert (Mod).second )
198
- break ;
185
+ std::queue<const Module *> Q;
186
+ Q.push (M);
187
+ while (!Q.empty ()) {
188
+ const Module *Mod = Q.front ();
189
+ Q.pop ();
190
+
199
191
// The containing module map is affecting, because it's being pointed
200
192
// into by Module::DefinitionLoc.
201
- if (FileID FID = MM.getContainingModuleMapFileID (Mod); FID. isValid () )
202
- CollectIncludingModuleMaps (FID, *SourceMgr. getFileEntryRefForID (FID) );
193
+ if (auto FE = MM.getContainingModuleMapFile (Mod); FE )
194
+ ModuleMaps. insert (*FE );
203
195
// For inferred modules, the module map that allowed inferring is not in
204
196
// the include chain of the virtual containing module map file. It did
205
197
// affect the compilation, though.
206
- if (FileID FID = MM.getModuleMapFileIDForUniquing (Mod); FID.isValid ())
207
- CollectIncludingModuleMaps (FID, *SourceMgr.getFileEntryRefForID (FID));
198
+ if (auto FE = MM.getModuleMapFileForUniquing (Mod); FE)
199
+ ModuleMaps.insert (*FE);
200
+
201
+ for (auto *SubM : Mod->submodules ())
202
+ Q.push (SubM);
208
203
}
209
204
};
210
205
211
206
// Handle all the affecting modules referenced from the root module.
212
207
208
+ CollectModuleMapsForHierarchy (RootModule);
209
+
213
210
std::queue<const Module *> Q;
214
211
Q.push (RootModule);
215
212
while (!Q.empty ()) {
216
- const Module *CurrentModule = Q.front ();
213
+ const Module *RootSubmodule = Q.front ();
217
214
Q.pop ();
218
215
219
- CollectIncludingMapsFromAncestors (CurrentModule);
220
- for (const Module *ImportedModule : CurrentModule->Imports )
221
- CollectIncludingMapsFromAncestors (ImportedModule);
222
- for (const Module *UndeclaredModule : CurrentModule->UndeclaredUses )
223
- CollectIncludingMapsFromAncestors (UndeclaredModule);
216
+ for (const Module *ImportedModule : RootSubmodule->Imports )
217
+ CollectModuleMapsForHierarchy (ImportedModule);
218
+ for (const Module *UndeclaredModule : RootSubmodule->UndeclaredUses )
219
+ CollectModuleMapsForHierarchy (UndeclaredModule);
224
220
225
- for (auto *M : CurrentModule ->submodules ())
226
- Q.push (M );
221
+ for (auto *SubM : RootSubmodule ->submodules ())
222
+ Q.push (SubM );
227
223
}
228
224
229
225
// Handle textually-included headers that belong to other modules.
@@ -249,9 +245,39 @@ GetAffectingModuleMaps(const Preprocessor &PP, Module *RootModule) {
249
245
250
246
for (const auto &KH : HS.findResolvedModulesForHeader (*File))
251
247
if (const Module *M = KH.getModule ())
252
- CollectIncludingMapsFromAncestors (M);
248
+ CollectModuleMapsForHierarchy (M);
253
249
}
254
250
251
+ // Note: This algorithm doesn't handle all edge-cases. Let's say something
252
+ // from \c ModulesToProcess imports X. The algorithm doesn't pick up
253
+ // Y.modulemap as affecting in the following cases:
254
+
255
+ // --- X.modulemap
256
+ // module X { header "X.h" }
257
+ // extern module Y "Y.modulemap
258
+ // --- Y.modulemap
259
+ // module Y { header "Y.h" }
260
+ //
261
+ // Since SourceManager doesn't keep list of files included from X.modulemap,
262
+ // we would need to walk up the include chain from all leaf files to figure
263
+ // out if they are reachable from X.modulemap and if so mark all module map
264
+ // files in the chain as affecting.
265
+
266
+ // --- Y.modulemap
267
+ // module Y { header "Y.h" }
268
+ // extern module X "X.modulemap"
269
+ // --- X.modulemap
270
+ // module X { header "X.h" }
271
+ // module Y.Sub { header "Y_Sub.h" }
272
+ //
273
+ // Only considering X.modulemap affecting means that parsing it without having
274
+ // access to Y.modulemap fails. There is no way to find out this dependence
275
+ // since ModuleMap does not keep a mapping from a module map file to the
276
+ // modules it defines. We could always consider the including module map as
277
+ // affecting, but that is problematic on MacOS, where X might be something
278
+ // like Darwin whose parent module map includes lots of other module maps that
279
+ // describe unrelated top-level modules.
280
+
255
281
return ModuleMaps;
256
282
}
257
283
@@ -1631,6 +1657,7 @@ struct InputFileEntry {
1631
1657
bool IsTransient;
1632
1658
bool BufferOverridden;
1633
1659
bool IsTopLevel;
1660
+ bool IsTopLevelAmongAffecting;
1634
1661
bool IsModuleMap;
1635
1662
uint32_t ContentHash[2 ];
1636
1663
@@ -1639,6 +1666,18 @@ struct InputFileEntry {
1639
1666
1640
1667
} // namespace
1641
1668
1669
+ SourceLocation ASTWriter::getAffectingIncludeLoc (const SourceManager &SourceMgr,
1670
+ const SrcMgr::FileInfo &File) {
1671
+ SourceLocation IncludeLoc = File.getIncludeLoc ();
1672
+ if (IncludeLoc.isValid ()) {
1673
+ FileID IncludeFID = SourceMgr.getFileID (IncludeLoc);
1674
+ assert (IncludeFID.isValid () && " IncludeLoc in invalid file" );
1675
+ if (!IsSLocAffecting[IncludeFID.ID ])
1676
+ IncludeLoc = SourceLocation ();
1677
+ }
1678
+ return IncludeLoc;
1679
+ }
1680
+
1642
1681
void ASTWriter::WriteInputFiles (SourceManager &SourceMgr,
1643
1682
HeaderSearchOptions &HSOpts) {
1644
1683
using namespace llvm ;
@@ -1654,6 +1693,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
1654
1693
IFAbbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Fixed, 1 )); // Overridden
1655
1694
IFAbbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Fixed, 1 )); // Transient
1656
1695
IFAbbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Fixed, 1 )); // Top-level
1696
+ IFAbbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Fixed, 1 )); // Top-level affect
1657
1697
IFAbbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Fixed, 1 )); // Module map
1658
1698
IFAbbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::VBR, 16 )); // Name as req. len
1659
1699
IFAbbrev->Add (BitCodeAbbrevOp (BitCodeAbbrevOp::Blob)); // Name as req. + name
@@ -1693,6 +1733,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
1693
1733
Entry.IsTransient = Cache->IsTransient ;
1694
1734
Entry.BufferOverridden = Cache->BufferOverridden ;
1695
1735
Entry.IsTopLevel = File.getIncludeLoc ().isInvalid ();
1736
+ Entry.IsTopLevelAmongAffecting =
1737
+ getAffectingIncludeLoc (SourceMgr, File).isInvalid ();
1696
1738
Entry.IsModuleMap = isModuleMap (File.getFileCharacteristic ());
1697
1739
1698
1740
auto ContentHash = hash_code (-1 );
@@ -1758,6 +1800,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
1758
1800
Entry.BufferOverridden ,
1759
1801
Entry.IsTransient ,
1760
1802
Entry.IsTopLevel ,
1803
+ Entry.IsTopLevelAmongAffecting ,
1761
1804
Entry.IsModuleMap ,
1762
1805
NameAsRequested.size ()};
1763
1806
@@ -2219,7 +2262,7 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,
2219
2262
SLocEntryOffsets.push_back (Offset);
2220
2263
// Starting offset of this entry within this module, so skip the dummy.
2221
2264
Record.push_back (getAdjustedOffset (SLoc->getOffset ()) - 2 );
2222
- AddSourceLocation (File. getIncludeLoc ( ), Record);
2265
+ AddSourceLocation (getAffectingIncludeLoc (SourceMgr, File ), Record);
2223
2266
Record.push_back (File.getFileCharacteristic ()); // FIXME: stable encoding
2224
2267
Record.push_back (File.hasLineDirectives ());
2225
2268
0 commit comments