#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"
namespace clang {
class FileEntry;
-
+class DirectoryEntry;
+
/// \brief Describes the name of a module.
typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2>
ModuleId;
/// 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;
/// \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) { }
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) { }
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;
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)
OS << "explicit ";
OS << "module " << Name << " {\n";
- if (UmbrellaHeader) {
+ if (const FileEntry *UmbrellaHeader = getUmbrellaHeader()) {
OS.indent(Indent + 2);
OS << "umbrella \"";
OS.write_escaped(UmbrellaHeader->getName());
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.
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;
}
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 {
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) {
Modules[ModuleName] = Result;
// umbrella "umbrella-header-name"
- Result->UmbrellaHeader = UmbrellaHeader;
+ Result->Umbrella = UmbrellaHeader;
Headers[UmbrellaHeader] = Result;
UmbrellaDirs[FrameworkDir] = Result;
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)
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;
}
}
// 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;
}
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;
}
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.