[cfe-commits] r165921 - in /cfe/trunk: include/clang/Basic/Module.h include/clang/Lex/ModuleMap.h include/clang/Serialization/ASTBitCodes.h lib/Basic/Module.cpp lib/Lex/ModuleMap.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/Modules/Inputs/NoUmbrella.framework/module.map
Douglas Gregor
dgregor at apple.com
Sun Oct 14 23:28:11 PDT 2012
Author: dgregor
Date: Mon Oct 15 01:28:11 2012
New Revision: 165921
URL: http://llvm.org/viewvc/llvm-project?rev=165921&view=rev
Log:
Introduce the notion of excluded headers into the module map
description. Previously, one could emulate this behavior by placing
the header in an always-unavailable submodule, but Argyrios guilted me
into expressing this idea properly.
Modified:
cfe/trunk/include/clang/Basic/Module.h
cfe/trunk/include/clang/Lex/ModuleMap.h
cfe/trunk/include/clang/Serialization/ASTBitCodes.h
cfe/trunk/lib/Basic/Module.cpp
cfe/trunk/lib/Lex/ModuleMap.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map
Modified: cfe/trunk/include/clang/Basic/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Module.h (original)
+++ cfe/trunk/include/clang/Basic/Module.h Mon Oct 15 01:28:11 2012
@@ -73,6 +73,9 @@
/// \brief The headers that are part of this module.
llvm::SmallVector<const FileEntry *, 2> Headers;
+ /// \brief The headers that are explicitly excluded from this module.
+ llvm::SmallVector<const FileEntry *, 2> ExcludedHeaders;
+
/// \brief The top-level headers associated with this module.
llvm::SmallSetVector<const FileEntry *, 2> TopHeaders;
Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleMap.h Mon Oct 15 01:28:11 2012
@@ -52,10 +52,37 @@
/// \brief The top-level modules that are known.
llvm::StringMap<Module *> Modules;
-
+
+ /// \brief A header that is known to reside within a given module,
+ /// whether it was included or excluded.
+ class KnownHeader {
+ llvm::PointerIntPair<Module *, 1, bool> Storage;
+
+ public:
+ KnownHeader() : Storage(0, false) { }
+ KnownHeader(Module *M, bool Excluded) : Storage(M, Excluded) { }
+
+ /// \brief Retrieve the module the header is stored in.
+ Module *getModule() const { return Storage.getPointer(); }
+
+ /// \brief Whether this header is explicitly excluded from the module.
+ bool isExcluded() const { return Storage.getInt(); }
+
+ /// \brief Whether this header is available in the module.
+ bool isAvailable() const {
+ return !isExcluded() && getModule()->isAvailable();
+ }
+
+ // \brief Whether this known header is valid (i.e., it has an
+ // associated module).
+ operator bool() const { return Storage.getPointer() != 0; }
+ };
+
+ typedef llvm::DenseMap<const FileEntry *, KnownHeader> HeadersMap;
+
/// \brief Mapping from each header to the module that owns the contents of the
/// that header.
- llvm::DenseMap<const FileEntry *, Module *> Headers;
+ HeadersMap Headers;
/// \brief Mapping from directories with umbrella headers to the module
/// that is generated from the umbrella header.
@@ -215,7 +242,9 @@
void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir);
/// \brief Adds this header to the given module.
- void addHeader(Module *Mod, const FileEntry *Header);
+ /// \param Excluded Whether this header is explicitly excluded from the
+ /// module; otherwise, it's included in the module.
+ void addHeader(Module *Mod, const FileEntry *Header, bool Excluded);
/// \brief Parse the given module map file, and record any modules we
/// encounter.
Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Mon Oct 15 01:28:11 2012
@@ -565,7 +565,10 @@
/// submodule.
SUBMODULE_EXPORTS = 7,
/// \brief Specifies a required feature.
- SUBMODULE_REQUIRES = 8
+ SUBMODULE_REQUIRES = 8,
+ /// \brief Specifies a header that has been explicitly excluded
+ /// from this submodule.
+ SUBMODULE_EXCLUDED_HEADER = 9
};
/// \brief Record types used within a comments block.
Modified: cfe/trunk/lib/Basic/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Module.cpp (original)
+++ cfe/trunk/lib/Basic/Module.cpp Mon Oct 15 01:28:11 2012
@@ -219,6 +219,13 @@
OS.write_escaped(Headers[I]->getName());
OS << "\"\n";
}
+
+ for (unsigned I = 0, N = ExcludedHeaders.size(); I != N; ++I) {
+ OS.indent(Indent + 2);
+ OS << "exclude header \"";
+ OS.write_escaped(ExcludedHeaders[I]->getName());
+ OS << "\"\n";
+ }
for (submodule_const_iterator MI = submodule_begin(), MIEnd = submodule_end();
MI != MIEnd; ++MI)
Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Mon Oct 15 01:28:11 2012
@@ -146,15 +146,13 @@
}
Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
- llvm::DenseMap<const FileEntry *, Module *>::iterator Known
- = Headers.find(File);
+ HeadersMap::iterator Known = Headers.find(File);
if (Known != Headers.end()) {
- // If a header corresponds to an unavailable module, don't report
- // that it maps to anything.
- if (!Known->second->isAvailable())
+ // If a header is not available, don't report that it maps to anything.
+ if (!Known->second.isAvailable())
return 0;
- return Known->second;
+ return Known->second.getModule();
}
const DirectoryEntry *Dir = File->getDir();
@@ -218,7 +216,7 @@
UmbrellaDirs[SkippedDirs[I]] = Result;
}
- Headers[File] = Result;
+ Headers[File] = KnownHeader(Result, /*Excluded=*/false);
// If a header corresponds to an unavailable module, don't report
// that it maps to anything.
@@ -243,10 +241,9 @@
}
bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) {
- llvm::DenseMap<const FileEntry *, Module *>::iterator Known
- = Headers.find(Header);
+ HeadersMap::iterator Known = Headers.find(Header);
if (Known != Headers.end())
- return !Known->second->isAvailable();
+ return !Known->second.isAvailable();
const DirectoryEntry *Dir = Header->getDir();
llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs;
@@ -381,7 +378,7 @@
// umbrella header "umbrella-header-name"
Result->Umbrella = UmbrellaHeader;
- Headers[UmbrellaHeader] = Result;
+ Headers[UmbrellaHeader] = KnownHeader(Result, /*Excluded=*/false);
UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
// export *
@@ -447,7 +444,7 @@
}
void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
- Headers[UmbrellaHeader] = Mod;
+ Headers[UmbrellaHeader] = KnownHeader(Mod, /*Excluded=*/false);
Mod->Umbrella = UmbrellaHeader;
UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
}
@@ -457,9 +454,13 @@
UmbrellaDirs[UmbrellaDir] = Mod;
}
-void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) {
- Mod->Headers.push_back(Header);
- Headers[Header] = Mod;
+void ModuleMap::addHeader(Module *Mod, const FileEntry *Header,
+ bool Excluded) {
+ if (Excluded)
+ Mod->ExcludedHeaders.push_back(Header);
+ else
+ Mod->Headers.push_back(Header);
+ Headers[Header] = KnownHeader(Mod, Excluded);
}
const FileEntry *
@@ -479,12 +480,10 @@
M->getValue()->print(llvm::errs(), 2);
llvm::errs() << "Headers:";
- for (llvm::DenseMap<const FileEntry *, Module *>::iterator
- H = Headers.begin(),
- HEnd = Headers.end();
+ for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
H != HEnd; ++H) {
llvm::errs() << " \"" << H->first->getName() << "\" -> "
- << H->second->getFullModuleName() << "\n";
+ << H->second.getModule()->getFullModuleName() << "\n";
}
}
@@ -545,6 +544,7 @@
EndOfFile,
HeaderKeyword,
Identifier,
+ ExcludeKeyword,
ExplicitKeyword,
ExportKeyword,
FrameworkKeyword,
@@ -623,7 +623,7 @@
bool parseModuleId(ModuleId &Id);
void parseModuleDecl();
void parseRequiresDecl();
- void parseHeaderDecl(SourceLocation UmbrellaLoc);
+ void parseHeaderDecl(SourceLocation UmbrellaLoc, SourceLocation ExcludeLoc);
void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
void parseExportDecl();
void parseInferredSubmoduleDecl(bool Explicit);
@@ -666,6 +666,7 @@
Tok.StringLength = LToken.getLength();
Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
.Case("header", MMToken::HeaderKeyword)
+ .Case("exclude", MMToken::ExcludeKeyword)
.Case("explicit", MMToken::ExplicitKeyword)
.Case("export", MMToken::ExportKeyword)
.Case("framework", MMToken::FrameworkKeyword)
@@ -1044,14 +1045,25 @@
case MMToken::UmbrellaKeyword: {
SourceLocation UmbrellaLoc = consumeToken();
if (Tok.is(MMToken::HeaderKeyword))
- parseHeaderDecl(UmbrellaLoc);
+ parseHeaderDecl(UmbrellaLoc, SourceLocation());
else
parseUmbrellaDirDecl(UmbrellaLoc);
break;
}
+ case MMToken::ExcludeKeyword: {
+ SourceLocation ExcludeLoc = consumeToken();
+ if (Tok.is(MMToken::HeaderKeyword)) {
+ parseHeaderDecl(SourceLocation(), ExcludeLoc);
+ } else {
+ Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
+ << "exclude";
+ }
+ break;
+ }
+
case MMToken::HeaderKeyword:
- parseHeaderDecl(SourceLocation());
+ parseHeaderDecl(SourceLocation(), SourceLocation());
break;
default:
@@ -1153,12 +1165,15 @@
///
/// header-declaration:
/// 'umbrella'[opt] 'header' string-literal
-void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) {
+/// 'exclude'[opt] 'header' string-literal
+void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc,
+ SourceLocation ExcludeLoc) {
assert(Tok.is(MMToken::HeaderKeyword));
consumeToken();
bool Umbrella = UmbrellaLoc.isValid();
-
+ bool Exclude = ExcludeLoc.isValid();
+ assert(!(Umbrella && Exclude) && "Cannot have both 'umbrella' and 'exclude'");
// Parse the header name.
if (!Tok.is(MMToken::StringLiteral)) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
@@ -1236,15 +1251,15 @@
// FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
// Come up with a lazy way to do this.
if (File) {
- if (const Module *OwningModule = Map.Headers[File]) {
+ if (ModuleMap::KnownHeader OwningModule = Map.Headers[File]) {
Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
- << FileName << OwningModule->getFullModuleName();
+ << FileName << OwningModule.getModule()->getFullModuleName();
HadError = true;
} else if (Umbrella) {
const DirectoryEntry *UmbrellaDir = File->getDir();
- if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) {
+ if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
- << OwningModule->getFullModuleName();
+ << UmbrellaModule->getFullModuleName();
HadError = true;
} else {
// Record this umbrella header.
@@ -1252,11 +1267,11 @@
}
} else {
// Record this header.
- Map.addHeader(ActiveModule, File);
+ Map.addHeader(ActiveModule, File, Exclude);
// If there is a builtin counterpart to this file, add it now.
if (BuiltinFile)
- Map.addHeader(ActiveModule, BuiltinFile);
+ Map.addHeader(ActiveModule, BuiltinFile, Exclude);
}
} else {
Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
@@ -1489,6 +1504,7 @@
break;
case MMToken::Comma:
+ case MMToken::ExcludeKeyword:
case MMToken::ExportKeyword:
case MMToken::HeaderKeyword:
case MMToken::Identifier:
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Mon Oct 15 01:28:11 2012
@@ -3322,7 +3322,27 @@
if (std::find(CurrentModule->Headers.begin(),
CurrentModule->Headers.end(),
File) == CurrentModule->Headers.end())
- ModMap.addHeader(CurrentModule, File);
+ ModMap.addHeader(CurrentModule, File, false);
+ }
+ break;
+ }
+
+ case SUBMODULE_EXCLUDED_HEADER: {
+ if (First) {
+ Error("missing submodule metadata record at beginning of block");
+ return Failure;
+ }
+
+ if (!CurrentModule)
+ break;
+
+ // FIXME: Be more lazy about this!
+ StringRef FileName(BlobStart, BlobLen);
+ if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {
+ if (std::find(CurrentModule->Headers.begin(),
+ CurrentModule->Headers.end(),
+ File) == CurrentModule->Headers.end())
+ ModMap.addHeader(CurrentModule, File, true);
}
break;
}
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Oct 15 01:28:11 2012
@@ -1983,6 +1983,11 @@
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Feature
unsigned RequiresAbbrev = Stream.EmitAbbrev(Abbrev);
+ Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_EXCLUDED_HEADER));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
+ unsigned ExcludedHeaderAbbrev = Stream.EmitAbbrev(Abbrev);
+
// Write the submodule metadata block.
RecordData Record;
Record.push_back(getNumberOfModules(WritingModule));
@@ -2044,6 +2049,13 @@
Stream.EmitRecordWithBlob(HeaderAbbrev, Record,
Mod->Headers[I]->getName());
}
+ // Emit the excluded headers.
+ for (unsigned I = 0, N = Mod->ExcludedHeaders.size(); I != N; ++I) {
+ Record.clear();
+ Record.push_back(SUBMODULE_EXCLUDED_HEADER);
+ Stream.EmitRecordWithBlob(ExcludedHeaderAbbrev, Record,
+ Mod->ExcludedHeaders[I]->getName());
+ }
for (unsigned I = 0, N = Mod->TopHeaders.size(); I != N; ++I) {
Record.clear();
Record.push_back(SUBMODULE_TOPHEADER);
Modified: cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map?rev=165921&r1=165920&r2=165921&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map (original)
+++ cfe/trunk/test/Modules/Inputs/NoUmbrella.framework/module.map Mon Oct 15 01:28:11 2012
@@ -2,8 +2,5 @@
umbrella "Headers"
module * { }
- module unavailable {
- requires unavailable
- header "Boom.h"
- }
+ exclude header "Boom.h"
}
More information about the cfe-commits
mailing list