aboutsummaryrefslogtreecommitdiff
path: root/lib/Lex/ModuleMap.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-12-08 19:11:24 +0000
committerDouglas Gregor <dgregor@apple.com>2011-12-08 19:11:24 +0000
commit77d029f6a24dbf70d97e61757945df53fb250ea0 (patch)
treea5b04a494d0f58aa79d0523e53213a842ffe5dd2 /lib/Lex/ModuleMap.cpp
parentd5c3fa29c6a06ed9c74e03b4a96f786cbc156b7c (diff)
Implement umbrella directories for modules, which are similar to
umbrella headers in the sense that all of the headers within that directory (and eventually its subdirectories) are considered to be part of the module with that umbrella directory. However, unlike umbrella headers, which are expected to include all of the headers within their subdirectories, Clang will automatically include all of the headers it finds in the named subdirectory. The intent here is to allow a module map to trivially turn a subdirectory into a module, where the module's structure can mimic the directory structure. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146165 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Lex/ModuleMap.cpp')
-rw-r--r--lib/Lex/ModuleMap.cpp83
1 files changed, 73 insertions, 10 deletions
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index e4c9d77ad6..c9efbf0b53 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -346,6 +346,11 @@ void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
UmbrellaDirs[UmbrellaDir] = Mod;
}
+void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
+ Mod->Umbrella = UmbrellaDir;
+ UmbrellaDirs[UmbrellaDir] = Mod;
+}
+
void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
Mod->Headers.push_back(Header);
Headers[Header] = Mod;
@@ -494,6 +499,7 @@ namespace clang {
bool parseModuleId(ModuleId &Id);
void parseModuleDecl();
void parseHeaderDecl(SourceLocation UmbrellaLoc);
+ void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
void parseExportDecl();
void parseInferredSubmoduleDecl(bool Explicit);
@@ -796,9 +802,14 @@ void ModuleMapParser::parseModuleDecl() {
parseExportDecl();
break;
- case MMToken::UmbrellaKeyword:
- parseHeaderDecl(consumeToken());
+ case MMToken::UmbrellaKeyword: {
+ SourceLocation UmbrellaLoc = consumeToken();
+ if (Tok.is(MMToken::HeaderKeyword))
+ parseHeaderDecl(UmbrellaLoc);
+ else
+ parseUmbrellaDirDecl(UmbrellaLoc);
break;
+ }
case MMToken::HeaderKeyword:
parseHeaderDecl(SourceLocation());
@@ -863,11 +874,10 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
std::string FileName = Tok.getString();
SourceLocation FileNameLoc = consumeToken();
- // Check whether we already have an umbrella header.
- if (Umbrella && ActiveModule->getUmbrellaHeader()) {
- Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
- << ActiveModule->getFullModuleName()
- << ActiveModule->getUmbrellaHeader()->getName();
+ // Check whether we already have an umbrella.
+ if (Umbrella && ActiveModule->Umbrella) {
+ Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
+ << ActiveModule->getFullModuleName();
HadError = true;
return;
}
@@ -935,9 +945,62 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
}
} else {
Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
- << false << FileName;
+ << Umbrella << FileName;
+ HadError = true;
+ }
+}
+
+/// \brief Parse an umbrella directory declaration.
+///
+/// umbrella-dir-declaration:
+/// umbrella string-literal
+void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
+ // Parse the directory name.
+ if (!Tok.is(MMToken::StringLiteral)) {
+ Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
+ << "umbrella";
+ HadError = true;
+ return;
+ }
+
+ std::string DirName = Tok.getString();
+ SourceLocation DirNameLoc = consumeToken();
+
+ // Check whether we already have an umbrella.
+ if (ActiveModule->Umbrella) {
+ Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
+ << ActiveModule->getFullModuleName();
+ HadError = true;
+ return;
+ }
+
+ // Look for this file.
+ const DirectoryEntry *Dir = 0;
+ if (llvm::sys::path::is_absolute(DirName))
+ Dir = SourceMgr.getFileManager().getDirectory(DirName);
+ else {
+ llvm::SmallString<128> PathName;
+ PathName = Directory->getName();
+ llvm::sys::path::append(PathName, DirName);
+ Dir = SourceMgr.getFileManager().getDirectory(PathName);
+ }
+
+ if (!Dir) {
+ Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
+ << DirName;
HadError = true;
+ return;
}
+
+ if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
+ Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
+ << OwningModule->getFullModuleName();
+ HadError = true;
+ return;
+ }
+
+ // Record this umbrella directory.
+ Map.setUmbrellaDir(ActiveModule, Dir);
}
/// \brief Parse a module export declaration.
@@ -998,8 +1061,8 @@ void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
Failed = true;
}
- // Inferred modules must have umbrella headers.
- if (!Failed && !ActiveModule->getUmbrellaHeader()) {
+ // Inferred modules must have umbrella directories.
+ if (!Failed && !ActiveModule->getUmbrellaDir()) {
Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
Failed = true;
}