Skip to content

Commit d3676d4

Browse files
Bigcheesejansvoboda11
authored andcommitted
[clang][modules] Build inferred modules
This patch enables explicitly building inferred modules. Effectively a cherry-pick of swiftlang#699 authored by @Bigcheese with libclang and dependency scanner changes omitted. Contains the following changes: 1. [Clang] Fix the header paths in clang::Module for inferred modules. * The UmbrellaAsWritten and NameAsWritten fields in clang::Module are a lie for framework modules. For those they actually are the path to the header or umbrella relative to the clang::Module::Directory. * The exception to this case is for inferred modules. Here it actually is the name as written, because we print out the module and read it back in when implicitly building modules. This causes a problem when explicitly building an inferred module, as we skip the printing out step. * In order to fix this issue this patch adds a new field for the path we want to use in getInputBufferForModule. It also makes NameAsWritten actually be the name written in the module map file (or that would be, in the case of an inferred module). 2. [Clang] Allow explicitly building an inferred module. * Building the actual module still fails, but make sure it fails for the right reason. Split from D100934. Reviewed By: dexonsmith Differential Revision: https://reviews.llvm.org/D102491
1 parent 65936b9 commit d3676d4

File tree

10 files changed

+69
-31
lines changed

10 files changed

+69
-31
lines changed

clang/include/clang/Basic/Module.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ class Module {
141141
/// The name of the umbrella entry, as written in the module map.
142142
std::string UmbrellaAsWritten;
143143

144+
// The path to the umbrella entry relative to the root module's \c Directory.
145+
std::string UmbrellaRelativeToRootModuleDirectory;
146+
144147
/// The module through which entities defined in this module will
145148
/// eventually be exposed, for use in "private" modules.
146149
std::string ExportAsModule;
@@ -188,6 +191,7 @@ class Module {
188191
/// file.
189192
struct Header {
190193
std::string NameAsWritten;
194+
std::string PathRelativeToRootModuleDirectory;
191195
const FileEntry *Entry;
192196

193197
explicit operator bool() { return Entry; }
@@ -197,6 +201,7 @@ class Module {
197201
/// file.
198202
struct DirectoryName {
199203
std::string NameAsWritten;
204+
std::string PathRelativeToRootModuleDirectory;
200205
const DirectoryEntry *Entry;
201206

202207
explicit operator bool() { return Entry; }
@@ -545,7 +550,8 @@ class Module {
545550
/// module.
546551
Header getUmbrellaHeader() const {
547552
if (auto *FE = Umbrella.dyn_cast<const FileEntry *>())
548-
return Header{UmbrellaAsWritten, FE};
553+
return Header{UmbrellaAsWritten, UmbrellaRelativeToRootModuleDirectory,
554+
FE};
549555
return Header{};
550556
}
551557

clang/include/clang/Lex/ModuleMap.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -649,12 +649,14 @@ class ModuleMap {
649649
/// Sets the umbrella header of the given module to the given
650650
/// header.
651651
void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
652-
Twine NameAsWritten);
652+
const Twine &NameAsWritten,
653+
const Twine &PathRelativeToRootModuleDirectory);
653654

654655
/// Sets the umbrella directory of the given module to the given
655656
/// directory.
656657
void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
657-
Twine NameAsWritten);
658+
const Twine &NameAsWritten,
659+
const Twine &PathRelativeToRootModuleDirectory);
658660

659661
/// Adds this header to the given module.
660662
/// \param Role The role of the header wrt the module.

clang/lib/Basic/Module.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,9 +245,10 @@ bool Module::fullModuleNameIs(ArrayRef<StringRef> nameParts) const {
245245

246246
Module::DirectoryName Module::getUmbrellaDir() const {
247247
if (Header U = getUmbrellaHeader())
248-
return {"", U.Entry->getDir()};
248+
return {"", "", U.Entry->getDir()};
249249

250-
return {UmbrellaAsWritten, Umbrella.dyn_cast<const DirectoryEntry *>()};
250+
return {UmbrellaAsWritten, UmbrellaRelativeToRootModuleDirectory,
251+
Umbrella.dyn_cast<const DirectoryEntry *>()};
251252
}
252253

253254
void Module::addTopHeader(const FileEntry *File) {

clang/lib/Frontend/FrontendAction.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,8 @@ static std::error_code collectModuleHeaderIncludes(
342342
// file relative to the module build directory (the directory containing
343343
// the module map file) so this will find the same file that we found
344344
// while parsing the module map.
345-
addHeaderInclude(H.NameAsWritten, Includes, LangOpts, Module->IsExternC);
345+
addHeaderInclude(H.PathRelativeToRootModuleDirectory, Includes, LangOpts,
346+
Module->IsExternC);
346347
}
347348
}
348349
// Note that Module->PrivateHeaders will not be a TopHeader.
@@ -351,8 +352,8 @@ static std::error_code collectModuleHeaderIncludes(
351352
Module->addTopHeader(UmbrellaHeader.Entry);
352353
if (Module->Parent)
353354
// Include the umbrella header for submodules.
354-
addHeaderInclude(UmbrellaHeader.NameAsWritten, Includes, LangOpts,
355-
Module->IsExternC);
355+
addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory,
356+
Includes, LangOpts, Module->IsExternC);
356357
} else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) {
357358
// Add all of the headers we find in this subdirectory.
358359
std::error_code EC;
@@ -386,7 +387,8 @@ static std::error_code collectModuleHeaderIncludes(
386387
auto PathIt = llvm::sys::path::rbegin(Dir->path());
387388
for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt)
388389
Components.push_back(*PathIt);
389-
SmallString<128> RelativeHeader(UmbrellaDir.NameAsWritten);
390+
SmallString<128> RelativeHeader(
391+
UmbrellaDir.PathRelativeToRootModuleDirectory);
390392
for (auto It = Components.rbegin(), End = Components.rend(); It != End;
391393
++It)
392394
llvm::sys::path::append(RelativeHeader, *It);
@@ -470,7 +472,7 @@ static Module *prepareToBuildModule(CompilerInstance &CI,
470472
// Dig out the module definition.
471473
HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
472474
Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule,
473-
/*AllowSearch=*/false);
475+
/*AllowSearch=*/true);
474476
if (!M) {
475477
CI.getDiagnostics().Report(diag::err_missing_module)
476478
<< CI.getLangOpts().CurrentModule << ModuleMapFilename;
@@ -528,8 +530,8 @@ getInputBufferForModule(CompilerInstance &CI, Module *M) {
528530
SmallString<256> HeaderContents;
529531
std::error_code Err = std::error_code();
530532
if (Module::Header UmbrellaHeader = M->getUmbrellaHeader())
531-
addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents,
532-
CI.getLangOpts(), M->IsExternC);
533+
addHeaderInclude(UmbrellaHeader.PathRelativeToRootModuleDirectory,
534+
HeaderContents, CI.getLangOpts(), M->IsExternC);
533535
Err = collectModuleHeaderIncludes(
534536
CI.getLangOpts(), FileMgr, CI.getDiagnostics(),
535537
CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M,

clang/lib/Frontend/FrontendActions.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,8 @@ bool GenerateHeaderModuleAction::BeginSourceFileAction(
297297
<< Name;
298298
continue;
299299
}
300-
Headers.push_back({std::string(Name), &FE->getFileEntry()});
300+
Headers.push_back(
301+
{std::string(Name), std::string(Name), &FE->getFileEntry()});
301302
}
302303
HS.getModuleMap().createHeaderModule(CI.getLangOpts().CurrentModule, Headers);
303304

clang/lib/Lex/ModuleMap.cpp

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,10 @@ void ModuleMap::resolveHeader(Module *Mod,
260260
<< UmbrellaMod->getFullModuleName();
261261
else
262262
// Record this umbrella header.
263-
setUmbrellaHeader(Mod, *File, RelativePathName.str());
263+
setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str());
264264
} else {
265-
Module::Header H = {std::string(RelativePathName.str()), *File};
265+
Module::Header H = {Header.FileName, std::string(RelativePathName.str()),
266+
*File};
266267
if (Header.Kind == Module::HK_Excluded)
267268
excludeHeader(Mod, H);
268269
else
@@ -305,7 +306,7 @@ bool ModuleMap::resolveAsBuiltinHeader(
305306
return false;
306307

307308
auto Role = headerKindToRole(Header.Kind);
308-
Module::Header H = {std::string(Path.str()), *File};
309+
Module::Header H = {Header.FileName, std::string(Path.str()), *File};
309310
addHeader(Mod, H, Role);
310311
return true;
311312
}
@@ -1038,11 +1039,13 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
10381039
Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10391040
Result->Directory = FrameworkDir;
10401041

1042+
// Chop off the first framework bit, as that is implied.
1043+
StringRef RelativePath = UmbrellaName.str().substr(
1044+
Result->getTopLevelModule()->Directory->getName().size());
1045+
RelativePath = llvm::sys::path::relative_path(RelativePath);
1046+
10411047
// umbrella header "umbrella-header-name"
1042-
//
1043-
// The "Headers/" component of the name is implied because this is
1044-
// a framework module.
1045-
setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h");
1048+
setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath);
10461049

10471050
// export *
10481051
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
@@ -1121,11 +1124,14 @@ Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11211124
return Result;
11221125
}
11231126

1124-
void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
1125-
Twine NameAsWritten) {
1127+
void ModuleMap::setUmbrellaHeader(
1128+
Module *Mod, const FileEntry *UmbrellaHeader, const Twine &NameAsWritten,
1129+
const Twine &PathRelativeToRootModuleDirectory) {
11261130
Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
11271131
Mod->Umbrella = UmbrellaHeader;
11281132
Mod->UmbrellaAsWritten = NameAsWritten.str();
1133+
Mod->UmbrellaRelativeToRootModuleDirectory =
1134+
PathRelativeToRootModuleDirectory.str();
11291135
UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
11301136

11311137
// Notify callbacks that we just added a new header.
@@ -1134,9 +1140,12 @@ void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
11341140
}
11351141

11361142
void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
1137-
Twine NameAsWritten) {
1143+
const Twine &NameAsWritten,
1144+
const Twine &PathRelativeToRootModuleDirectory) {
11381145
Mod->Umbrella = UmbrellaDir;
11391146
Mod->UmbrellaAsWritten = NameAsWritten.str();
1147+
Mod->UmbrellaRelativeToRootModuleDirectory =
1148+
PathRelativeToRootModuleDirectory.str();
11401149
UmbrellaDirs[UmbrellaDir] = Mod;
11411150
}
11421151

@@ -2405,6 +2414,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
24052414
}
24062415

24072416
std::string DirName = std::string(Tok.getString());
2417+
std::string DirNameAsWritten = DirName;
24082418
SourceLocation DirNameLoc = consumeToken();
24092419

24102420
// Check whether we already have an umbrella.
@@ -2446,7 +2456,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
24462456
for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24472457
I != E && !EC; I.increment(EC)) {
24482458
if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
2449-
Module::Header Header = {std::string(I->path()), *FE};
2459+
Module::Header Header = {"", std::string(I->path()), *FE};
24502460
Headers.push_back(std::move(Header));
24512461
}
24522462
}
@@ -2467,7 +2477,7 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
24672477
}
24682478

24692479
// Record this umbrella directory.
2470-
Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2480+
Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName);
24712481
}
24722482

24732483
/// Parse a module export declaration.

clang/lib/Serialization/ASTReader.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,10 +1921,9 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
19211921
std::string Filename = std::string(key.Filename);
19221922
if (key.Imported)
19231923
Reader.ResolveImportedPath(M, Filename);
1924-
// FIXME: This is not always the right filename-as-written, but we're not
1925-
// going to use this information to rebuild the module, so it doesn't make
1926-
// a lot of difference.
1927-
Module::Header H = {std::string(key.Filename), *FileMgr.getFile(Filename)};
1924+
// FIXME: NameAsWritten
1925+
Module::Header H = {std::string(key.Filename), "",
1926+
*FileMgr.getFile(Filename)};
19281927
ModMap.addHeader(Mod, H, HeaderRole, /*Imported*/true);
19291928
HFI.isModuleHeader |= !(HeaderRole & ModuleMap::TextualHeader);
19301929
}
@@ -5618,7 +5617,8 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
56185617
ResolveImportedPath(F, Filename);
56195618
if (auto Umbrella = PP.getFileManager().getFile(Filename)) {
56205619
if (!CurrentModule->getUmbrellaHeader())
5621-
ModMap.setUmbrellaHeader(CurrentModule, *Umbrella, Blob);
5620+
// FIXME: NameAsWritten
5621+
ModMap.setUmbrellaHeader(CurrentModule, *Umbrella, Blob, "");
56225622
else if (CurrentModule->getUmbrellaHeader().Entry != *Umbrella) {
56235623
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
56245624
Error("mismatched umbrella headers in submodule");
@@ -5651,7 +5651,8 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
56515651
ResolveImportedPath(F, Dirname);
56525652
if (auto Umbrella = PP.getFileManager().getDirectory(Dirname)) {
56535653
if (!CurrentModule->getUmbrellaDir())
5654-
ModMap.setUmbrellaDir(CurrentModule, *Umbrella, Blob);
5654+
// FIXME: NameAsWritten
5655+
ModMap.setUmbrellaDir(CurrentModule, *Umbrella, Blob, "");
56555656
else if (CurrentModule->getUmbrellaDir().Entry != *Umbrella) {
56565657
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
56575658
Error("mismatched umbrella directories in submodule");
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
typedef int inferred;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
framework module * {}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: rm -rf %t && mkdir %t
2+
//
3+
// RUN: %clang_cc1 -fmodules -fno-implicit-modules -fimplicit-module-maps \
4+
// RUN: -emit-module -x c++ %S/Inputs/explicit-build-inferred/frameworks/module.modulemap \
5+
// RUN: -fmodule-name=Inferred -o %t/Inferred.pcm -F %S/Inputs/explicit-build-inferred/frameworks
6+
//
7+
// RUN: %clang_cc1 -fmodules -fno-implicit-modules -fsyntax-only %s \
8+
// RUN: -fmodule-map-file=%S/Inputs/explicit-build-inferred/frameworks/module.modulemap \
9+
// RUN: -fmodule-file=%t/Inferred.pcm -F %S/Inputs/explicit-build-inferred/frameworks
10+
11+
#include <Inferred/Inferred.h>
12+
13+
inferred a = 0;

0 commit comments

Comments
 (0)