aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/Module.h24
-rw-r--r--lib/Basic/Module.cpp9
-rw-r--r--lib/Frontend/FrontendActions.cpp35
-rw-r--r--lib/Lex/ModuleMap.cpp14
-rw-r--r--lib/Serialization/ASTReader.cpp4
-rw-r--r--lib/Serialization/ASTWriter.cpp4
6 files changed, 56 insertions, 34 deletions
diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h
index 26a0b28182..0f2a9a7b3d 100644
--- a/include/clang/Basic/Module.h
+++ b/include/clang/Basic/Module.h
@@ -16,6 +16,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
@@ -29,7 +30,8 @@ namespace llvm {
namespace clang {
class FileEntry;
-
+class DirectoryEntry;
+
/// \brief Describes the name of a module.
typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
ModuleId;
@@ -47,10 +49,8 @@ public:
/// module.
Module *Parent;
- /// \brief The umbrella header, if any.
- ///
- /// Only the top-level module can have an umbrella header.
- const FileEntry *UmbrellaHeader;
+ /// \brief The umbrella header or directory.
+ llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;
/// \brief The submodules of this module, indexed by name.
llvm::StringMap<Module *> SubModules;
@@ -130,7 +130,7 @@ public:
/// \brief Construct a top-level module.
explicit Module(StringRef Name, SourceLocation DefinitionLoc,
bool IsFramework)
- : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), UmbrellaHeader(0),
+ : Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), Umbrella(),
IsFramework(IsFramework), IsExplicit(false), InferSubmodules(false),
InferExplicitSubmodules(false), InferExportWildcard(false),
NameVisibility(Hidden) { }
@@ -139,7 +139,7 @@ public:
Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
bool IsFramework, bool IsExplicit)
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
- UmbrellaHeader(0), IsFramework(IsFramework), IsExplicit(IsExplicit),
+ Umbrella(), IsFramework(IsFramework), IsExplicit(IsExplicit),
InferSubmodules(false), InferExplicitSubmodules(false),
InferExportWildcard(false),NameVisibility(Hidden) { }
@@ -184,6 +184,16 @@ public:
return getTopLevelModule()->Name;
}
+ /// \brief Retrieve the directory for which this module serves as the
+ /// umbrella.
+ const DirectoryEntry *getUmbrellaDir() const;
+
+ /// \brief Retrieve the header that serves as the umbrella header for this
+ /// module.
+ const FileEntry *getUmbrellaHeader() const {
+ return Umbrella.dyn_cast<const FileEntry *>();
+ }
+
/// \brief Print the module map for this module to the given stream.
///
void print(llvm::raw_ostream &OS, unsigned Indent = 0) const;
diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp
index 97bddfa97e..169715736b 100644
--- a/lib/Basic/Module.cpp
+++ b/lib/Basic/Module.cpp
@@ -65,6 +65,13 @@ std::string Module::getFullModuleName() const {
return Result;
}
+const DirectoryEntry *Module::getUmbrellaDir() const {
+ if (const FileEntry *Header = getUmbrellaHeader())
+ return Header->getDir();
+
+ return Umbrella.dyn_cast<const DirectoryEntry *>();
+}
+
static void printModuleId(llvm::raw_ostream &OS, const ModuleId &Id) {
for (unsigned I = 0, N = Id.size(); I != N; ++I) {
if (I)
@@ -81,7 +88,7 @@ void Module::print(llvm::raw_ostream &OS, unsigned Indent) const {
OS << "explicit ";
OS << "module " << Name << " {\n";
- if (UmbrellaHeader) {
+ if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) {
OS.indent(Indent + 2);
OS << "umbrella \"";
OS.write_escaped(UmbrellaHeader->getName());
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 1a2df01bdf..190cdba582 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -145,14 +145,16 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
Includes += "\"\n";
}
- if (Module->UmbrellaHeader && Module->Parent) {
- // Include the umbrella header for submodules.
- if (LangOpts.ObjC1)
- Includes += "#import \"";
- else
- Includes += "#include \"";
- Includes += Module->UmbrellaHeader->getName();
- Includes += "\"\n";
+ if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
+ if (Module->Parent) {
+ // Include the umbrella header for submodules.
+ if (LangOpts.ObjC1)
+ Includes += "#import \"";
+ else
+ Includes += "#include \"";
+ Includes += UmbrellaHeader->getName();
+ Includes += "\"\n";
+ }
}
// Recurse into submodules.
@@ -197,29 +199,32 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
return false;
}
+ // Do we have an umbrella header for this module?
+ const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader();
+
// Collect the set of #includes we need to build the module.
llvm::SmallString<256> HeaderContents;
collectModuleHeaderIncludes(CI.getLangOpts(), Module, HeaderContents);
- if (Module->UmbrellaHeader && HeaderContents.empty()) {
+ if (UmbrellaHeader && HeaderContents.empty()) {
// Simple case: we have an umbrella header and there are no additional
// includes, we can just parse the umbrella header directly.
- setCurrentFile(Module->UmbrellaHeader->getName(), getCurrentFileKind());
+ setCurrentFile(UmbrellaHeader->getName(), getCurrentFileKind());
return true;
}
FileManager &FileMgr = CI.getFileManager();
llvm::SmallString<128> HeaderName;
time_t ModTime;
- if (Module->UmbrellaHeader) {
+ if (UmbrellaHeader) {
// Read in the umbrella header.
// FIXME: Go through the source manager; the umbrella header may have
// been overridden.
std::string ErrorStr;
llvm::MemoryBuffer *UmbrellaContents
- = FileMgr.getBufferForFile(Module->UmbrellaHeader, &ErrorStr);
+ = FileMgr.getBufferForFile(UmbrellaHeader, &ErrorStr);
if (!UmbrellaContents) {
CI.getDiagnostics().Report(diag::err_missing_umbrella_header)
- << Module->UmbrellaHeader->getName() << ErrorStr;
+ << UmbrellaHeader->getName() << ErrorStr;
return false;
}
@@ -232,8 +237,8 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
HeaderContents += OldContents;
// Pretend that we're parsing the umbrella header.
- HeaderName = Module->UmbrellaHeader->getName();
- ModTime = Module->UmbrellaHeader->getModificationTime();
+ HeaderName = UmbrellaHeader->getName();
+ ModTime = UmbrellaHeader->getModificationTime();
delete UmbrellaContents;
} else {
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index 0c9922ff2a..8457b1cea9 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -106,9 +106,9 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) {
Module *Result = KnownDir->second;
// Search up the module stack until we find a module with an umbrella
- // header.
+ // directory.
Module *UmbrellaModule = Result;
- while (!UmbrellaModule->UmbrellaHeader && UmbrellaModule->Parent)
+ while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
UmbrellaModule = UmbrellaModule->Parent;
if (UmbrellaModule->InferSubmodules) {
@@ -260,7 +260,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
Modules[ModuleName] = Result;
// umbrella "umbrella-header-name"
- Result->UmbrellaHeader = UmbrellaHeader;
+ Result->Umbrella = UmbrellaHeader;
Headers[UmbrellaHeader] = Result;
UmbrellaDirs[FrameworkDir] = Result;
@@ -336,7 +336,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
Headers[UmbrellaHeader] = Mod;
- Mod->UmbrellaHeader = UmbrellaHeader;
+ Mod->Umbrella = UmbrellaHeader;
const DirectoryEntry *UmbrellaDir = UmbrellaHeader->getDir();
if (Mod->IsFramework)
@@ -864,10 +864,10 @@ void ModuleMapParser::parseUmbrellaDecl() {
SourceLocation FileNameLoc = consumeToken();
// Check whether we already have an umbrella header.
- if (ActiveModule->UmbrellaHeader) {
+ if (ActiveModule->getUmbrellaHeader()) {
Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict)
<< ActiveModule->getFullModuleName()
- << ActiveModule->UmbrellaHeader->getName();
+ << ActiveModule->getUmbrellaHeader()->getName();
HadError = true;
return;
}
@@ -1064,7 +1064,7 @@ void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) {
}
// Inferred modules must have umbrella headers.
- if (!Failed && !ActiveModule->UmbrellaHeader) {
+ if (!Failed && !ActiveModule->getUmbrellaHeader()) {
Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
Failed = true;
}
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 76ba9e2b26..21be3aa50c 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -3099,9 +3099,9 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
StringRef FileName(BlobStart, BlobLen);
if (const FileEntry *Umbrella = PP.getFileManager().getFile(FileName)) {
- if (!CurrentModule->UmbrellaHeader)
+ if (!CurrentModule->getUmbrellaHeader())
ModMap.setUmbrellaHeader(CurrentModule, Umbrella);
- else if (CurrentModule->UmbrellaHeader != Umbrella) {
+ else if (CurrentModule->getUmbrellaHeader() != Umbrella) {
Error("mismatched umbrella headers in submodule");
return Failure;
}
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 946bc76c40..1bd9050fe0 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1941,11 +1941,11 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
// Emit the umbrella header, if there is one.
- if (Mod->UmbrellaHeader) {
+ if (const FileEntry *UmbrellaHeader = Mod->getUmbrellaHeader()) {
Record.clear();
Record.push_back(SUBMODULE_UMBRELLA);
Stream.EmitRecordWithBlob(UmbrellaAbbrev, Record,
- Mod->UmbrellaHeader->getName());
+ UmbrellaHeader->getName());
}
// Emit the headers.