Changed implementation as promised and updated description.
Hi klimek, rsmith, doug.gregor,
http://llvm-reviews.chandlerc.com/D2352
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D2352?vs=5952&id=5982#toc
Files:
include/clang/Basic/DiagnosticFrontendKinds.td
include/clang/Basic/DiagnosticLexKinds.td
include/clang/Basic/Module.h
include/clang/Lex/ModuleMap.h
lib/Basic/Module.cpp
lib/Frontend/CompilerInstance.cpp
lib/Frontend/FrontendActions.cpp
lib/Lex/HeaderSearch.cpp
lib/Lex/ModuleMap.cpp
test/Modules/Inputs/submodules/module.map
test/Modules/submodules.cpp
Index: include/clang/Basic/DiagnosticFrontendKinds.td
===================================================================
--- include/clang/Basic/DiagnosticFrontendKinds.td
+++ include/clang/Basic/DiagnosticFrontendKinds.td
@@ -138,6 +138,8 @@
InGroup<IncompleteUmbrella>;
def err_module_unavailable : Error<
"module '%0' %select{is incompatible with|requires}1 feature '%2'">;
+def err_module_header_missing : Error<
+ "%select{|umbrella }0header '%1' not found">;
def warn_module_config_macro_undef : Warning<
"%select{definition|#undef}0 of configuration macro '%1' has no effect on "
"the import of '%2'; pass '%select{-D%1=...|-U%1}0' on the command line "
Index: include/clang/Basic/DiagnosticLexKinds.td
===================================================================
--- include/clang/Basic/DiagnosticLexKinds.td
+++ include/clang/Basic/DiagnosticLexKinds.td
@@ -551,8 +551,6 @@
def err_mmap_module_redefinition : Error<
"redefinition of module '%0'">;
def note_mmap_prev_definition : Note<"previously defined here">;
-def err_mmap_header_not_found : Error<
- "%select{|umbrella }0header '%1' not found">;
def err_mmap_umbrella_dir_not_found : Error<
"umbrella directory '%0' not found">;
def err_mmap_umbrella_clash : Error<
Index: include/clang/Basic/Module.h
===================================================================
--- include/clang/Basic/Module.h
+++ include/clang/Basic/Module.h
@@ -88,7 +88,19 @@
SmallVector<const FileEntry *, 2> ExcludedHeaders;
/// \brief The headers that are private to this module.
- llvm::SmallVector<const FileEntry *, 2> PrivateHeaders;
+ SmallVector<const FileEntry *, 2> PrivateHeaders;
+
+ /// \brief Information about a header directive as found in the module map
+ /// file.
+ struct HeaderDirective {
+ SourceLocation FileNameLoc;
+ std::string FileName;
+ bool IsUmbrella;
+ };
+
+ /// \brief Headers that are mentioned in the module map file bug could not be
+ /// found on the file system.
+ SmallVector<HeaderDirective, 1> MissingHeaders;
/// \brief An individual requirement: a feature name and a flag indicating
/// the required state of that feature.
@@ -276,7 +288,8 @@
/// this module.
bool isAvailable(const LangOptions &LangOpts,
const TargetInfo &Target,
- Requirement &Req) const;
+ Requirement &Req,
+ HeaderDirective &MissingHeader) const;
/// \brief Determine whether this module is a submodule.
bool isSubModule() const { return Parent != 0; }
Index: include/clang/Lex/ModuleMap.h
===================================================================
--- include/clang/Lex/ModuleMap.h
+++ include/clang/Lex/ModuleMap.h
@@ -38,7 +38,7 @@
class ModuleMap {
SourceManager &SourceMgr;
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
+ DiagnosticsEngine &Diags;
const LangOptions &LangOpts;
const TargetInfo *Target;
HeaderSearch &HeaderInfo;
@@ -188,7 +188,7 @@
/// \param LangOpts Language options for this translation unit.
///
/// \param Target The target for this translation unit.
- ModuleMap(SourceManager &SourceMgr, DiagnosticConsumer &DC,
+ ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
const LangOptions &LangOpts, const TargetInfo *Target,
HeaderSearch &HeaderInfo);
Index: lib/Basic/Module.cpp
===================================================================
--- lib/Basic/Module.cpp
+++ lib/Basic/Module.cpp
@@ -69,11 +69,15 @@
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) {
Index: lib/Frontend/CompilerInstance.cpp
===================================================================
--- lib/Frontend/CompilerInstance.cpp
+++ lib/Frontend/CompilerInstance.cpp
@@ -1360,11 +1360,19 @@
// 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();
Index: lib/Frontend/FrontendActions.cpp
===================================================================
--- lib/Frontend/FrontendActions.cpp
+++ lib/Frontend/FrontendActions.cpp
@@ -247,10 +247,17 @@
// 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;
}
Index: lib/Lex/HeaderSearch.cpp
===================================================================
--- lib/Lex/HeaderSearch.cpp
+++ lib/Lex/HeaderSearch.cpp
@@ -48,7 +48,7 @@
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;
Index: lib/Lex/ModuleMap.cpp
===================================================================
--- lib/Lex/ModuleMap.cpp
+++ lib/Lex/ModuleMap.cpp
@@ -59,7 +59,7 @@
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 *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 @@
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(),
@@ -1474,12 +1467,13 @@
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;
@@ -1489,12 +1483,12 @@
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.
@@ -1505,28 +1499,28 @@
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
// may have a counterpart (or replacement) in the set of headers
// 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,
@@ -1571,10 +1565,13 @@
}
} 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);
}
}
@@ -2113,11 +2110,9 @@
// 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;
}
Index: test/Modules/Inputs/submodules/module.map
===================================================================
--- test/Modules/Inputs/submodules/module.map
+++ test/Modules/Inputs/submodules/module.map
@@ -10,3 +10,8 @@
module c { header "import-self-c.h" }
module d { header "import-self-d.h" }
}
+
+module missing_headers {
+ module missing { header "missing.h" }
+ module not_missing { header "not_missing.h" }
+}
Index: test/Modules/submodules.cpp
===================================================================
--- test/Modules/submodules.cpp
+++ test/Modules/submodules.cpp
@@ -34,3 +34,8 @@
// FIXME: This should be valid; import_self.b re-exports import_self.d.
extern MyTypeD import_self_test_d; // expected-error {{must be imported from module 'import_self.d'}}
// [email protected]:1 {{here}}
+
+// expected-error@Inputs/submodules/module.map:15{{header 'missing.h' not found}}
+@import missing_headers.missing;
+@import missing_headers.not_missing;
+void f() { NotMissingFunction(); };
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits