]> granicus.if.org Git - clang/commitdiff
If a module map is found in a relative -I path, convert the filenames within it
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 11 Mar 2014 02:02:47 +0000 (02:02 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 11 Mar 2014 02:02:47 +0000 (02:02 +0000)
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

include/clang/Basic/DiagnosticFrontendKinds.td
lib/Frontend/FrontendActions.cpp
test/Modules/Inputs/include-relative/a.h [new file with mode: 0644]
test/Modules/Inputs/include-relative/module.map [new file with mode: 0644]
test/Modules/include-relative.c [new file with mode: 0644]

index 41a83a0b8ed3595a373618671b1bdbeca422bffc..32c824a9302799d6b8ee9ac70342f085ae6c017b 100644 (file)
@@ -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 "
index b41da6da5c77c470480064f69757cd3f444dac63..786fadb2fe6fa894fffff98ae696b6dfcb5c7436 100644 (file)
@@ -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/test/Modules/Inputs/include-relative/a.h b/test/Modules/Inputs/include-relative/a.h
new file mode 100644 (file)
index 0000000..b95284b
--- /dev/null
@@ -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 (file)
index 0000000..bb00c84
--- /dev/null
@@ -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 (file)
index 0000000..264df5f
--- /dev/null
@@ -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; }