From c6c3e3d0b12fd269050f0d4fac5076ed1d9ed281 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 11 Mar 2014 02:02:47 +0000 Subject: [PATCH] If a module map is found in a relative -I path, convert the filenames within it to absolute paths when building the includes file for the module. Without this, the module build would fail, because the relative paths we were using are not necessarily relative to a directory in our include path. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203528 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/Basic/DiagnosticFrontendKinds.td | 2 + lib/Frontend/FrontendActions.cpp | 84 +++++++++++++------ test/Modules/Inputs/include-relative/a.h | 1 + .../Inputs/include-relative/module.map | 1 + test/Modules/include-relative.c | 11 +++ 5 files changed, 73 insertions(+), 26 deletions(-) create mode 100644 test/Modules/Inputs/include-relative/a.h create mode 100644 test/Modules/Inputs/include-relative/module.map create mode 100644 test/Modules/include-relative.c diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 41a83a0b8e..32c824a930 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/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/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index b41da6da5c..786fadb2fe 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -128,27 +128,38 @@ operator+=(SmallVectorImpl &Includes, StringRef RHS) { return Includes; } -static void addHeaderInclude(StringRef HeaderName, - SmallVectorImpl &Includes, - const LangOptions &LangOpts, - bool IsExternC) { +static llvm::error_code addHeaderInclude(StringRef HeaderName, + SmallVectorImpl &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 &Includes, - const LangOptions &LangOpts, - bool IsExternC) { - addHeaderInclude(Header->getName(), Includes, LangOpts, IsExternC); +static llvm::error_code addHeaderInclude(const FileEntry *Header, + SmallVectorImpl &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 &Includes) { +static llvm::error_code +collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, + ModuleMap &ModMap, clang::Module *Module, + SmallVectorImpl &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/test/Modules/Inputs/include-relative/a.h b/test/Modules/Inputs/include-relative/a.h new file mode 100644 index 0000000000..b95284b323 --- /dev/null +++ b/test/Modules/Inputs/include-relative/a.h @@ -0,0 +1 @@ +extern int n; diff --git a/test/Modules/Inputs/include-relative/module.map b/test/Modules/Inputs/include-relative/module.map new file mode 100644 index 0000000000..bb00c840ce --- /dev/null +++ b/test/Modules/Inputs/include-relative/module.map @@ -0,0 +1 @@ +module a { header "a.h" } diff --git a/test/Modules/include-relative.c b/test/Modules/include-relative.c new file mode 100644 index 0000000000..264df5f318 --- /dev/null +++ b/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; } -- 2.40.0