]> granicus.if.org Git - clang/commitdiff
[modules] When compiling a preprocessed module map, look for headers relative
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 31 May 2017 20:56:55 +0000 (20:56 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 31 May 2017 20:56:55 +0000 (20:56 +0000)
to the original module map.

Also use the path and name of the original module map when emitting that
information into the .pcm file. The upshot of this is that the produced .pcm
file will track information for headers in their original locations (where the
module was preprocessed), not relative to whatever directory the preprocessed
module map was in when it was built.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@304346 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Module.h
include/clang/Lex/HeaderSearch.h
lib/Frontend/FrontendAction.cpp
lib/Lex/HeaderSearch.cpp
lib/Serialization/ASTWriter.cpp
test/Modules/preprocess-module.cpp
test/Modules/preprocess-nested.cpp

index 28aa7db52992a8d17753b8713979bfacf8c24204..326d84eeb6c28c8db4b4d4a2134fd82ffa371fba 100644 (file)
@@ -83,6 +83,10 @@ public:
   /// are found.
   const DirectoryEntry *Directory;
 
+  /// \brief The presumed file name for the module map defining this module.
+  /// Only non-empty when building from preprocessed source.
+  std::string PresumedModuleMapFile;
+
   /// \brief The umbrella header or directory.
   llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;
 
index 6e24e1893ab6abd5d497f72a7d563488b1e66eb3..ee17dcbb8b5a32cf49601dc70f1276ffc69cbf84 100644 (file)
@@ -543,10 +543,13 @@ public:
   /// \param Offset [inout] An offset within ID to start parsing. On exit,
   ///        filled by the end of the parsed contents (either EOF or the
   ///        location of an end-of-module-map pragma).
-  ///
+  /// \param OriginalModuleMapFile The original path to the module map file,
+  ///        used to resolve paths within the module (this is required when
+  ///        building the module from preprocessed source).
   /// \returns true if an error occurred, false otherwise.
   bool loadModuleMapFile(const FileEntry *File, bool IsSystem,
-                         FileID ID = FileID(), unsigned *Offset = nullptr);
+                         FileID ID = FileID(), unsigned *Offset = nullptr,
+                         StringRef OriginalModuleMapFile = StringRef());
 
   /// \brief Collect the set of all known, top-level modules.
   ///
index 874c1b6be41ee16d0b51bbe897809eb0aa882379..cd67e469ddad51f25ca2a80868af82166264617c 100644 (file)
@@ -373,10 +373,11 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
   return std::error_code();
 }
 
-static bool
-loadModuleMapForModuleBuild(CompilerInstance &CI, StringRef Filename,
-                            bool IsSystem, bool IsPreprocessed,
-                            unsigned &Offset) {
+static bool loadModuleMapForModuleBuild(CompilerInstance &CI,
+                                        StringRef Filename, bool IsSystem,
+                                        bool IsPreprocessed,
+                                        std::string &PresumedModuleMapFile,
+                                        unsigned &Offset) {
   auto &SrcMgr = CI.getSourceManager();
   HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
 
@@ -388,16 +389,15 @@ loadModuleMapForModuleBuild(CompilerInstance &CI, StringRef Filename,
   // line directives are not part of the module map syntax in general.
   Offset = 0;
   if (IsPreprocessed) {
-    std::string PresumedModuleMapFile;
     SourceLocation EndOfLineMarker =
         ReadOriginalFileName(CI, PresumedModuleMapFile, /*AddLineNote*/true);
     if (EndOfLineMarker.isValid())
       Offset = CI.getSourceManager().getDecomposedLoc(EndOfLineMarker).second;
-    // FIXME: Use PresumedModuleMapFile as the MODULE_MAP_FILE in the PCM.
   }
 
   // Load the module map file.
-  if (HS.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset))
+  if (HS.loadModuleMapFile(ModuleMap, IsSystem, ModuleMapID, &Offset,
+                           PresumedModuleMapFile))
     return true;
 
   if (SrcMgr.getBuffer(ModuleMapID)->getBufferSize() == Offset)
@@ -664,15 +664,19 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
   if (Input.getKind().getFormat() == InputKind::ModuleMap) {
     CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap);
 
+    std::string PresumedModuleMapFile;
     unsigned OffsetToContents;
     if (loadModuleMapForModuleBuild(CI, Input.getFile(), Input.isSystem(),
-                                    Input.isPreprocessed(), OffsetToContents))
+                                    Input.isPreprocessed(),
+                                    PresumedModuleMapFile, OffsetToContents))
       goto failure;
 
     auto *CurrentModule = prepareToBuildModule(CI, Input.getFile());
     if (!CurrentModule)
       goto failure;
 
+    CurrentModule->PresumedModuleMapFile = PresumedModuleMapFile;
+
     if (OffsetToContents)
       // If the module contents are in the same file, skip to them.
       CI.getPreprocessor().setSkipMainFilePreamble(OffsetToContents, true);
index f5b7c59e446fb732ee8c987fc948dee4c87bdd89..9084bc352f76fc66c25fb1246deead6f8979c9bd 100644 (file)
@@ -1326,14 +1326,27 @@ static const FileEntry *getPrivateModuleMap(const FileEntry *File,
 }
 
 bool HeaderSearch::loadModuleMapFile(const FileEntry *File, bool IsSystem,
-                                     FileID ID, unsigned *Offset) {
+                                     FileID ID, unsigned *Offset,
+                                     StringRef OriginalModuleMapFile) {
   // Find the directory for the module. For frameworks, that may require going
   // up from the 'Modules' directory.
   const DirectoryEntry *Dir = nullptr;
   if (getHeaderSearchOpts().ModuleMapFileHomeIsCwd)
     Dir = FileMgr.getDirectory(".");
   else {
-    Dir = File->getDir();
+    if (!OriginalModuleMapFile.empty()) {
+      // We're building a preprocessed module map. Find or invent the directory
+      // that it originally occupied.
+      Dir = FileMgr.getDirectory(
+          llvm::sys::path::parent_path(OriginalModuleMapFile));
+      if (!Dir) {
+        auto *FakeFile = FileMgr.getVirtualFile(OriginalModuleMapFile, 0, 0);
+        Dir = FakeFile->getDir();
+      }
+    } else {
+      Dir = File->getDir();
+    }
+
     StringRef DirName(Dir->getName());
     if (llvm::sys::path::filename(DirName) == "Modules") {
       DirName = llvm::sys::path::parent_path(DirName);
index c931b13f65f32fb4691ed4b9769b36d323630a1b..95cb54f944e47aaef7fab822927410469c85524a 100644 (file)
@@ -1422,8 +1422,8 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
     Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
                               getClangFullRepositoryVersion());
   }
-  if (WritingModule) {
 
+  if (WritingModule) {
     // Module name
     auto Abbrev = std::make_shared<BitCodeAbbrev>();
     Abbrev->Add(BitCodeAbbrevOp(MODULE_NAME));
@@ -1466,9 +1466,10 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
     Record.clear();
 
     auto &Map = PP.getHeaderSearchInfo().getModuleMap();
-
-    // Primary module map file.
-    AddPath(Map.getModuleMapFileForUniquing(WritingModule)->getName(), Record);
+    AddPath(WritingModule->PresumedModuleMapFile.empty()
+                ? Map.getModuleMapFileForUniquing(WritingModule)->getName()
+                : StringRef(WritingModule->PresumedModuleMapFile),
+            Record);
 
     // Additional module map files.
     if (auto *AdditionalModMaps =
index eaab3136938f97a9fbb6eaa37bacfec03162e76a..9d1a2bb6801f7c2ece6db0af548f5255e74694d0 100644 (file)
@@ -14,8 +14,6 @@
 // RUN: FileCheck %s --input-file %t/rewrite.ii    --check-prefix=CHECK --check-prefix=REWRITE
 
 // Check that we can build a module from the preprocessed output.
-// FIXME: For now, we need the headers to exist.
-// RUN: touch %t/file.h %t/file2.h
 // RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/no-rewrite.ii -emit-module -o %t/no-rewrite.pcm
 // RUN: %clang_cc1 -fmodules -fmodule-name=file -fmodule-file=%t/fwd.pcm -x c++-module-map-cpp-output %t/rewrite.ii -emit-module -o %t/rewrite.pcm
 
@@ -27,6 +25,8 @@
 // Check the module we built works.
 // RUN: %clang_cc1 -fmodules -fmodule-file=%t/no-rewrite.pcm %s -I%t -verify -fno-modules-error-recovery
 // RUN: %clang_cc1 -fmodules -fmodule-file=%t/rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DREWRITE
+// RUN: %clang_cc1 -fmodules -fmodule-file=%t/no-rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DINCLUDE -I%S/Inputs/preprocess
+// RUN: %clang_cc1 -fmodules -fmodule-file=%t/rewrite.pcm %s -I%t -verify -fno-modules-error-recovery -DREWRITE -DINCLUDE -I%S/Inputs/preprocess
 
 
 // == module map
@@ -102,7 +102,11 @@ __FILE *a; // expected-error {{declaration of '__FILE' must be imported}}
 // expected-note@no-rewrite.ii:1 {{here}}
 #endif
 
+#ifdef INCLUDE
+#include "file.h"
+#else
 #pragma clang module import file
+#endif
 
 FILE *b;
-int x = file2;
+int x = file2; // ok, found in file2.h, even under -DINCLUDE
index 8fccf137e94f1d2671746f0e605eb7dd38780098..f26b65507ecef9752a4eeac265ec3a69d75dc1fa 100644 (file)
@@ -8,8 +8,6 @@
 // RUN: FileCheck %s --input-file %t/rewrite.ii    --check-prefix=CHECK --check-prefix=REWRITE
 
 // Check that we can build a module from the preprocessed output.
-// FIXME: For now, the files need to exist.
-// RUN: touch %t/a.h %t/b.h %t/c.h
 // RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-name=nested -x c++-module-map-cpp-output %t/no-rewrite.ii -emit-module -o %t/no-rewrite.pcm
 // RUN: %clang_cc1 -fmodules -fmodules-local-submodule-visibility -fmodule-name=nested -x c++-module-map-cpp-output %t/rewrite.ii -emit-module -o %t/rewrite.pcm