summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticFrontendKinds.td2
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp84
-rw-r--r--clang/test/Modules/Inputs/include-relative/a.h1
-rw-r--r--clang/test/Modules/Inputs/include-relative/module.map1
-rw-r--r--clang/test/Modules/include-relative.c11
5 files changed, 73 insertions, 26 deletions
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 41a83a0b8ed..32c824a9302 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -152,6 +152,8 @@ 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 err_module_cannot_create_includes : Error<
+ "cannot create includes file for module %0: %1">;
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 "
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index b41da6da5c7..786fadb2fe6 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -128,27 +128,38 @@ operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {
return Includes;
}
-static void addHeaderInclude(StringRef HeaderName,
- SmallVectorImpl<char> &Includes,
- const LangOptions &LangOpts,
- bool IsExternC) {
+static llvm::error_code addHeaderInclude(StringRef HeaderName,
+ SmallVectorImpl<char> &Includes,
+ const LangOptions &LangOpts,
+ bool IsExternC) {
if (IsExternC && LangOpts.CPlusPlus)
Includes += "extern \"C\" {\n";
if (LangOpts.ObjC1)
Includes += "#import \"";
else
Includes += "#include \"";
- Includes += HeaderName;
+ // Use an absolute path for the include; there's no reason to think that
+ // a relative path will work (. might not be on our include path) or that
+ // it will find the same file.
+ if (llvm::sys::path::is_absolute(HeaderName)) {
+ Includes += HeaderName;
+ } else {
+ SmallString<256> Header = HeaderName;
+ if (llvm::error_code Err = llvm::sys::fs::make_absolute(Header))
+ return Err;
+ Includes += Header;
+ }
Includes += "\"\n";
if (IsExternC && LangOpts.CPlusPlus)
Includes += "}\n";
+ return llvm::error_code::success();
}
-static void addHeaderInclude(const FileEntry *Header,
- SmallVectorImpl<char> &Includes,
- const LangOptions &LangOpts,
- bool IsExternC) {
- addHeaderInclude(Header->getName(), Includes, LangOpts, IsExternC);
+static llvm::error_code addHeaderInclude(const FileEntry *Header,
+ SmallVectorImpl<char> &Includes,
+ const LangOptions &LangOpts,
+ bool IsExternC) {
+ return addHeaderInclude(Header->getName(), Includes, LangOpts, IsExternC);
}
/// \brief Collect the set of header includes needed to construct the given
@@ -158,20 +169,21 @@ static void addHeaderInclude(const FileEntry *Header,
///
/// \param Includes Will be augmented with the set of \#includes or \#imports
/// needed to load all of the named headers.
-static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
- FileManager &FileMgr,
- ModuleMap &ModMap,
- clang::Module *Module,
- SmallVectorImpl<char> &Includes) {
+static llvm::error_code
+collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
+ ModuleMap &ModMap, clang::Module *Module,
+ SmallVectorImpl<char> &Includes) {
// Don't collect any headers for unavailable modules.
if (!Module->isAvailable())
- return;
+ return llvm::error_code::success();
// Add includes for each of these headers.
for (unsigned I = 0, N = Module->NormalHeaders.size(); I != N; ++I) {
const FileEntry *Header = Module->NormalHeaders[I];
Module->addTopHeader(Header);
- addHeaderInclude(Header, Includes, LangOpts, Module->IsExternC);
+ if (llvm::error_code Err =
+ addHeaderInclude(Header, Includes, LangOpts, Module->IsExternC))
+ return Err;
}
// Note that Module->PrivateHeaders will not be a TopHeader.
@@ -179,7 +191,9 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
Module->addTopHeader(UmbrellaHeader);
if (Module->Parent) {
// Include the umbrella header for submodules.
- addHeaderInclude(UmbrellaHeader, Includes, LangOpts, Module->IsExternC);
+ if (llvm::error_code Err = addHeaderInclude(UmbrellaHeader, Includes,
+ LangOpts, Module->IsExternC))
+ return Err;
}
} else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) {
// Add all of the headers we find in this subdirectory.
@@ -204,16 +218,25 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts,
Module->addTopHeader(Header);
}
- // Include this header umbrella header for submodules.
- addHeaderInclude(Dir->path(), Includes, LangOpts, Module->IsExternC);
+ // Include this header as part of the umbrella directory.
+ if (llvm::error_code Err = addHeaderInclude(Dir->path(), Includes,
+ LangOpts, Module->IsExternC))
+ return Err;
}
+
+ if (EC)
+ return EC;
}
// Recurse into submodules.
for (clang::Module::submodule_iterator Sub = Module->submodule_begin(),
SubEnd = Module->submodule_end();
Sub != SubEnd; ++Sub)
- collectModuleHeaderIncludes(LangOpts, FileMgr, ModMap, *Sub, Includes);
+ if (llvm::error_code Err = collectModuleHeaderIncludes(
+ LangOpts, FileMgr, ModMap, *Sub, Includes))
+ return Err;
+
+ return llvm::error_code::success();
}
bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
@@ -280,12 +303,21 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
// Collect the set of #includes we need to build the module.
SmallString<256> HeaderContents;
+ llvm::error_code Err = llvm::error_code::success();
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader())
- addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts(),
- Module->IsExternC);
- collectModuleHeaderIncludes(CI.getLangOpts(), FileMgr,
- CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(),
- Module, HeaderContents);
+ Err = addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts(),
+ Module->IsExternC);
+ if (!Err)
+ Err = collectModuleHeaderIncludes(
+ CI.getLangOpts(), FileMgr,
+ CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), Module,
+ HeaderContents);
+
+ if (Err) {
+ CI.getDiagnostics().Report(diag::err_module_cannot_create_includes)
+ << Module->getFullModuleName() << Err.message();
+ return false;
+ }
llvm::MemoryBuffer *InputBuffer =
llvm::MemoryBuffer::getMemBufferCopy(HeaderContents,
diff --git a/clang/test/Modules/Inputs/include-relative/a.h b/clang/test/Modules/Inputs/include-relative/a.h
new file mode 100644
index 00000000000..b95284b323b
--- /dev/null
+++ b/clang/test/Modules/Inputs/include-relative/a.h
@@ -0,0 +1 @@
+extern int n;
diff --git a/clang/test/Modules/Inputs/include-relative/module.map b/clang/test/Modules/Inputs/include-relative/module.map
new file mode 100644
index 00000000000..bb00c840ce3
--- /dev/null
+++ b/clang/test/Modules/Inputs/include-relative/module.map
@@ -0,0 +1 @@
+module a { header "a.h" }
diff --git a/clang/test/Modules/include-relative.c b/clang/test/Modules/include-relative.c
new file mode 100644
index 00000000000..264df5f3189
--- /dev/null
+++ b/clang/test/Modules/include-relative.c
@@ -0,0 +1,11 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: cp -r %S/Inputs/include-relative %t/include-relative
+// RUN: cd %t
+// RUN: %clang_cc1 -fmodules -x c -verify -fmodules-cache-path=%t -I include-relative %s
+
+// expected-no-diagnostics
+
+#include "a.h"
+
+int f() { return n; }
OpenPOWER on IntegriCloud