summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorDaniel Jasper <djasper@google.com>2013-12-17 10:31:37 +0000
committerDaniel Jasper <djasper@google.com>2013-12-17 10:31:37 +0000
commit0761a8a085f404482b375f71e670da8ef2ea612e (patch)
tree910ebae7cd5a93306422c0bceeb7bd0bfaf2ac3a /clang/lib
parent59bb0878e21df577f5d92ffef509d88ed6da1a95 (diff)
downloadbcm5719-llvm-0761a8a085f404482b375f71e670da8ef2ea612e.tar.gz
bcm5719-llvm-0761a8a085f404482b375f71e670da8ef2ea612e.zip
Modules: Don't warn upon missing headers while reading the module map.
Instead, mark the module as unavailable so that clang errors as soon as someone tries to build this module. This works towards the long-term goal of not stat'ing the header files at all while reading the module map and instead read them only when the module is being built (there is a corresponding FIXME in parseHeaderDecl()). However, it seems non-trivial to get there and this unblock us and moves us into the right direction. Also changed the implementation to reuse the same DiagnosticsEngine. llvm-svn: 197485
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/Module.cpp6
-rw-r--r--clang/lib/Frontend/CompilerInstance.cpp18
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp15
-rw-r--r--clang/lib/Lex/HeaderSearch.cpp2
-rw-r--r--clang/lib/Lex/ModuleMap.cpp55
5 files changed, 55 insertions, 41 deletions
diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp
index d08cef1a156..c6a1d602a94 100644
--- a/clang/lib/Basic/Module.cpp
+++ b/clang/lib/Basic/Module.cpp
@@ -69,11 +69,15 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts,
bool
Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target,
- Requirement &Req) const {
+ Requirement &Req, HeaderDirective &MissingHeader) const {
if (IsAvailable)
return true;
for (const Module *Current = this; Current; Current = Current->Parent) {
+ if (!Current->MissingHeaders.empty()) {
+ MissingHeader = Current->MissingHeaders.front();
+ return false;
+ }
for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) {
if (hasFeature(Current->Requirements[I].first, LangOpts, Target) !=
Current->Requirements[I].second) {
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index eccb94cc4a4..48ba0056071 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1360,11 +1360,19 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// Check whether this module is available.
clang::Module::Requirement Requirement;
- if (!Module->isAvailable(getLangOpts(), getTarget(), Requirement)) {
- getDiagnostics().Report(ImportLoc, diag::err_module_unavailable)
- << Module->getFullModuleName()
- << Requirement.second << Requirement.first
- << SourceRange(Path.front().second, Path.back().second);
+ clang::Module::HeaderDirective MissingHeader;
+ if (!Module->isAvailable(getLangOpts(), getTarget(), Requirement,
+ MissingHeader)) {
+ if (MissingHeader.FileNameLoc.isValid()) {
+ getDiagnostics().Report(MissingHeader.FileNameLoc,
+ diag::err_module_header_missing)
+ << MissingHeader.IsUmbrella << MissingHeader.FileName;
+ } else {
+ getDiagnostics().Report(ImportLoc, diag::err_module_unavailable)
+ << Module->getFullModuleName()
+ << Requirement.second << Requirement.first
+ << SourceRange(Path.front().second, Path.back().second);
+ }
LastModuleImportLoc = ImportLoc;
LastModuleImportResult = ModuleLoadResult();
return ModuleLoadResult();
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index b5f15830024..e0c68c84a3e 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -247,10 +247,17 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
// Check whether we can build this module at all.
clang::Module::Requirement Requirement;
- if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement)) {
- CI.getDiagnostics().Report(diag::err_module_unavailable)
- << Module->getFullModuleName()
- << Requirement.second << Requirement.first;
+ clang::Module::HeaderDirective MissingHeader;
+ if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement,
+ MissingHeader)) {
+ if (MissingHeader.FileNameLoc.isValid()) {
+ CI.getDiagnostics().Report(diag::err_module_header_missing)
+ << MissingHeader.IsUmbrella << MissingHeader.FileName;
+ } else {
+ CI.getDiagnostics().Report(diag::err_module_unavailable)
+ << Module->getFullModuleName()
+ << Requirement.second << Requirement.first;
+ }
return false;
}
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index 5770aaadf40..254c0293df9 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -48,7 +48,7 @@ HeaderSearch::HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts,
const LangOptions &LangOpts,
const TargetInfo *Target)
: HSOpts(HSOpts), FileMgr(SourceMgr.getFileManager()), FrameworkMap(64),
- ModMap(SourceMgr, *Diags.getClient(), LangOpts, Target, *this)
+ ModMap(SourceMgr, Diags, LangOpts, Target, *this)
{
AngledDirIdx = 0;
SystemDirIdx = 0;
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 8a1fcaa69e7..b9a47031289 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/lib/Lex/ModuleMap.cpp
@@ -59,7 +59,7 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
if (!Context) {
if (Complain)
- Diags->Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
+ Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
<< Id[0].first << Mod->getFullModuleName();
return 0;
@@ -70,7 +70,7 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
Module *Sub = lookupModuleQualified(Id[I].first, Context);
if (!Sub) {
if (Complain)
- Diags->Report(Id[I].second, diag::err_mmap_missing_module_qualified)
+ Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
<< Id[I].first << Context->getFullModuleName()
<< SourceRange(Id[0].second, Id[I-1].second);
@@ -83,19 +83,12 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
return Context;
}
-ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticConsumer &DC,
+ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const LangOptions &LangOpts, const TargetInfo *Target,
HeaderSearch &HeaderInfo)
- : SourceMgr(SourceMgr), LangOpts(LangOpts), Target(Target),
+ : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
HeaderInfo(HeaderInfo), BuiltinIncludeDir(0), CompilingModule(0),
- SourceModule(0) {
- IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs);
- Diags = IntrusiveRefCntPtr<DiagnosticsEngine>(
- new DiagnosticsEngine(DiagIDs, new DiagnosticOptions));
- Diags->setClient(new ForwardingDiagnosticConsumer(DC),
- /*ShouldOwnClient=*/true);
- Diags->setSourceManager(&SourceMgr);
-}
+ SourceModule(0) {}
ModuleMap::~ModuleMap() {
for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
@@ -1480,12 +1473,13 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
HadError = true;
return;
}
- std::string FileName = Tok.getString();
- SourceLocation FileNameLoc = consumeToken();
+ Module::HeaderDirective Header;
+ Header.FileName = Tok.getString();
+ Header.FileNameLoc = consumeToken();
// Check whether we already have an umbrella.
if (LeadingToken == MMToken::UmbrellaKeyword && ActiveModule->Umbrella) {
- Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash)
+ Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
<< ActiveModule->getFullModuleName();
HadError = true;
return;
@@ -1495,12 +1489,12 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
const FileEntry *File = 0;
const FileEntry *BuiltinFile = 0;
SmallString<128> PathName;
- if (llvm::sys::path::is_absolute(FileName)) {
- PathName = FileName;
+ if (llvm::sys::path::is_absolute(Header.FileName)) {
+ PathName = Header.FileName;
File = SourceMgr.getFileManager().getFile(PathName);
} else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) {
PathName = Dir->getName();
- llvm::sys::path::append(PathName, FileName);
+ llvm::sys::path::append(PathName, Header.FileName);
File = SourceMgr.getFileManager().getFile(PathName);
} else {
// Search for the header file within the search directory.
@@ -1511,18 +1505,18 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
appendSubframeworkPaths(ActiveModule, PathName);
// Check whether this file is in the public headers.
- llvm::sys::path::append(PathName, "Headers", FileName);
+ llvm::sys::path::append(PathName, "Headers", Header.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", FileName);
+ llvm::sys::path::append(PathName, "PrivateHeaders", Header.FileName);
File = SourceMgr.getFileManager().getFile(PathName);
}
} else {
// Lookup for normal headers.
- llvm::sys::path::append(PathName, FileName);
+ llvm::sys::path::append(PathName, Header.FileName);
File = SourceMgr.getFileManager().getFile(PathName);
// If this is a system module with a top-level header, this header
@@ -1530,9 +1524,9 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
// supplied by Clang. Find that builtin header.
if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword &&
BuiltinIncludeDir && BuiltinIncludeDir != Directory &&
- isBuiltinHeader(FileName)) {
+ isBuiltinHeader(Header.FileName)) {
SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
- llvm::sys::path::append(BuiltinPathName, FileName);
+ llvm::sys::path::append(BuiltinPathName, Header.FileName);
BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
// If Clang supplies this header but the underlying system does not,
@@ -1577,10 +1571,13 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
}
} else if (LeadingToken != MMToken::ExcludeKeyword) {
// Ignore excluded header files. They're optional anyway.
-
- Diags.Report(FileNameLoc, diag::err_mmap_header_not_found)
- << (LeadingToken == MMToken::UmbrellaKeyword) << FileName;
- HadError = true;
+
+ // If we find a module that has a missing header, we mark this module as
+ // unavailable and store the header directive for displaying diagnostics.
+ // Other submodules in the same module can still be used.
+ Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
+ ActiveModule->IsAvailable = false;
+ ActiveModule->MissingHeaders.push_back(Header);
}
}
@@ -2119,11 +2116,9 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem) {
// Parse this module map file.
Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts);
- Diags->getClient()->BeginSourceFile(MMapLangOpts);
- ModuleMapParser Parser(L, SourceMgr, Target, *Diags, *this, File->getDir(),
+ ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File->getDir(),
BuiltinIncludeDir, IsSystem);
bool Result = Parser.parseModuleMapFile();
- Diags->getClient()->EndSourceFile();
ParsedModuleMap[File] = Result;
return Result;
}
OpenPOWER on IntegriCloud