forked from OSchip/llvm-project
Add the notion of "framework" modules to module maps. Framework
modules (obviously) describe frameworks, and understand the header layout of frameworks. llvm-svn: 144921
This commit is contained in:
parent
0eff3e5c21
commit
755b205519
|
@ -392,7 +392,7 @@ def note_mmap_prev_definition : Note<"previously defined here">;
|
|||
def err_mmap_header_conflict : Error<
|
||||
"header '%0' is already part of module '%1'">;
|
||||
def err_mmap_header_not_found : Error<
|
||||
"%select{|umbrella }0 header '%1' not found">;
|
||||
"%select{|umbrella }0header '%1' not found">;
|
||||
def err_mmap_umbrella_header_conflict : Error<
|
||||
"module '%0' already has an umbrella header ('%1')">;
|
||||
def err_mmap_umbrella_header_submodule : Error<
|
||||
|
|
|
@ -59,19 +59,23 @@ public:
|
|||
/// \brief The headers that are part of this module.
|
||||
llvm::SmallVector<const FileEntry *, 2> Headers;
|
||||
|
||||
/// \brief Whether this is a framework module.
|
||||
bool IsFramework;
|
||||
|
||||
/// \brief Whether this is an explicit submodule.
|
||||
bool IsExplicit;
|
||||
|
||||
/// \brief Construct a top-level module.
|
||||
explicit Module(StringRef Name, SourceLocation DefinitionLoc)
|
||||
explicit Module(StringRef Name, SourceLocation DefinitionLoc,
|
||||
bool IsFramework)
|
||||
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(0), UmbrellaHeader(0),
|
||||
IsExplicit(false) { }
|
||||
IsFramework(IsFramework), IsExplicit(false) { }
|
||||
|
||||
/// \brief Construct a new module or submodule.
|
||||
Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
|
||||
bool IsExplicit)
|
||||
bool IsFramework, bool IsExplicit)
|
||||
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
|
||||
UmbrellaHeader(0), IsExplicit(IsExplicit) {
|
||||
UmbrellaHeader(0), IsFramework(IsFramework), IsExplicit(IsExplicit) {
|
||||
}
|
||||
|
||||
~Module();
|
||||
|
@ -79,6 +83,18 @@ public:
|
|||
/// \brief Determine whether this module is a submodule.
|
||||
bool isSubModule() const { return Parent != 0; }
|
||||
|
||||
/// \brief Determine whether this module is a part of a framework,
|
||||
/// either because it is a framework module or because it is a submodule
|
||||
/// of a framework module.
|
||||
bool isPartOfFramework() const {
|
||||
for (const Module *Mod = this; Mod; Mod = Mod->Parent)
|
||||
if (Mod->IsFramework)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Retrieve the full name of this module, including the path from
|
||||
/// its top-level module.
|
||||
std::string getFullModuleName() const;
|
||||
|
|
|
@ -162,7 +162,8 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName,
|
|||
if (!UmbrellaHeader)
|
||||
return 0;
|
||||
|
||||
Module *Result = new Module(ModuleName, SourceLocation());
|
||||
Module *Result = new Module(ModuleName, SourceLocation(),
|
||||
/*IsFramework=*/true);
|
||||
Result->UmbrellaHeader = UmbrellaHeader;
|
||||
Headers[UmbrellaHeader] = Result;
|
||||
UmbrellaDirs[FrameworkDir] = Result;
|
||||
|
@ -177,6 +178,8 @@ static void indent(llvm::raw_ostream &OS, unsigned Spaces) {
|
|||
static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M,
|
||||
unsigned Indent) {
|
||||
indent(OS, Indent);
|
||||
if (M->IsFramework)
|
||||
OS << "framework ";
|
||||
if (M->IsExplicit)
|
||||
OS << "explicit ";
|
||||
OS << M->Name << " {\n";
|
||||
|
@ -230,6 +233,7 @@ namespace clang {
|
|||
HeaderKeyword,
|
||||
Identifier,
|
||||
ExplicitKeyword,
|
||||
FrameworkKeyword,
|
||||
ModuleKeyword,
|
||||
UmbrellaKeyword,
|
||||
StringLiteral,
|
||||
|
@ -333,6 +337,7 @@ retry:
|
|||
Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString())
|
||||
.Case("header", MMToken::HeaderKeyword)
|
||||
.Case("explicit", MMToken::ExplicitKeyword)
|
||||
.Case("framework", MMToken::FrameworkKeyword)
|
||||
.Case("module", MMToken::ModuleKeyword)
|
||||
.Case("umbrella", MMToken::UmbrellaKeyword)
|
||||
.Default(MMToken::Identifier);
|
||||
|
@ -416,18 +421,26 @@ void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
|
|||
/// \brief Parse a module declaration.
|
||||
///
|
||||
/// module-declaration:
|
||||
/// 'module' identifier { module-member* }
|
||||
/// 'framework'[opt] 'module' identifier { module-member* }
|
||||
///
|
||||
/// module-member:
|
||||
/// umbrella-declaration
|
||||
/// header-declaration
|
||||
/// 'explicit'[opt] module-declaration
|
||||
void ModuleMapParser::parseModuleDecl() {
|
||||
assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword));
|
||||
|
||||
// Parse 'explicit' keyword, if present.
|
||||
assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
|
||||
Tok.is(MMToken::FrameworkKeyword));
|
||||
|
||||
// Parse 'framework' or 'explicit' keyword, if present.
|
||||
bool Framework = false;
|
||||
bool Explicit = false;
|
||||
if (Tok.is(MMToken::ExplicitKeyword)) {
|
||||
|
||||
if (Tok.is(MMToken::FrameworkKeyword)) {
|
||||
consumeToken();
|
||||
Framework = true;
|
||||
}
|
||||
// Parse 'explicit' keyword, if present.
|
||||
else if (Tok.is(MMToken::ExplicitKeyword)) {
|
||||
consumeToken();
|
||||
Explicit = true;
|
||||
}
|
||||
|
@ -481,7 +494,8 @@ void ModuleMapParser::parseModuleDecl() {
|
|||
}
|
||||
|
||||
// Start defining this module.
|
||||
ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit);
|
||||
ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework,
|
||||
Explicit);
|
||||
ModuleSpace[ModuleName] = ActiveModule;
|
||||
|
||||
bool Done = false;
|
||||
|
@ -562,11 +576,32 @@ void ModuleMapParser::parseUmbrellaDecl() {
|
|||
// Look for this file.
|
||||
llvm::SmallString<128> PathName;
|
||||
PathName += Directory->getName();
|
||||
llvm::sys::path::append(PathName, FileName);
|
||||
unsigned PathLength = PathName.size();
|
||||
const FileEntry *File = 0;
|
||||
if (ActiveModule->isPartOfFramework()) {
|
||||
// Check whether this file is in the public headers.
|
||||
llvm::sys::path::append(PathName, "Headers");
|
||||
llvm::sys::path::append(PathName, FileName);
|
||||
File = SourceMgr.getFileManager().getFile(PathName);
|
||||
|
||||
if (!File) {
|
||||
// Check whether this file is in the private headers.
|
||||
PathName.resize(PathLength);
|
||||
llvm::sys::path::append(PathName, "PrivateHeaders");
|
||||
llvm::sys::path::append(PathName, FileName);
|
||||
File = SourceMgr.getFileManager().getFile(PathName);
|
||||
}
|
||||
|
||||
// FIXME: Deal with subframeworks.
|
||||
} else {
|
||||
// Lookup for normal headers.
|
||||
llvm::sys::path::append(PathName, FileName);
|
||||
File = SourceMgr.getFileManager().getFile(PathName);
|
||||
}
|
||||
|
||||
// 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 (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) {
|
||||
if (File) {
|
||||
if (const Module *OwningModule = Map.Headers[File]) {
|
||||
Diags.Report(FileNameLoc, diag::err_mmap_header_conflict)
|
||||
<< FileName << OwningModule->getFullModuleName();
|
||||
|
@ -609,6 +644,10 @@ void ModuleMapParser::parseHeaderDecl() {
|
|||
// Look for this file.
|
||||
llvm::SmallString<128> PathName;
|
||||
PathName += Directory->getName();
|
||||
|
||||
if (ActiveModule->isPartOfFramework())
|
||||
llvm::sys::path::append(PathName, "Headers");
|
||||
|
||||
llvm::sys::path::append(PathName, FileName);
|
||||
|
||||
// FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
|
||||
|
@ -641,6 +680,7 @@ bool ModuleMapParser::parseModuleMapFile() {
|
|||
return HadError;
|
||||
|
||||
case MMToken::ModuleKeyword:
|
||||
case MMToken::FrameworkKeyword:
|
||||
parseModuleDecl();
|
||||
break;
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
int depends_on_module_other;
|
|
@ -0,0 +1,4 @@
|
|||
framework module DependsOnModule {
|
||||
umbrella "DependsOnModule.h"
|
||||
header "other.h"
|
||||
}
|
Loading…
Reference in New Issue