r244416 - [modules] PR22534: Load files specified by -fmodule-file= eagerly. In particular, this avoids the need to re-parse module map files when using such a module.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Sun Aug 9 01:48:42 PDT 2015


Author: rsmith
Date: Sun Aug  9 03:48:41 2015
New Revision: 244416

URL: http://llvm.org/viewvc/llvm-project?rev=244416&view=rev
Log:
[modules] PR22534: Load files specified by -fmodule-file= eagerly. In particular, this avoids the need to re-parse module map files when using such a module.

Added:
    cfe/trunk/test/Modules/explicit-build-missing-files.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td
    cfe/trunk/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/test/Index/pch-depending-on-deleted-module.c
    cfe/trunk/test/Modules/dependency-gen.modulemap
    cfe/trunk/test/Modules/explicit-build.cpp
    cfe/trunk/test/Modules/fatal-module-loader-error.m
    cfe/trunk/test/Modules/relative-dep-gen.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=244416&r1=244415&r2=244416&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Sun Aug  9 03:48:41 2015
@@ -194,9 +194,8 @@ def err_unable_to_make_temp : Error<
   "unable to make temporary file: %0">;
   
 // Modules
-def err_module_file_conflict : Error<"module '%0' found in both '%1' and '%2'">;
 def err_module_format_unhandled : Error<
-  "no handler registered for module format '%0'">;
+  "no handler registered for module format '%0'">, DefaultFatal;
 
 // TransformActions
 // TODO: Use a custom category name to distinguish rewriter errors.

Modified: cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td?rev=244416&r1=244415&r2=244416&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticFrontendKinds.td Sun Aug  9 03:48:41 2015
@@ -194,16 +194,6 @@ def remark_module_build_done : Remark<"f
 def err_conflicting_module_names : Error<
   "conflicting module names specified: '-fmodule-name=%0' and "
   "'-fmodule-implementation-of %1'">;
-def err_conflicting_module_files : Error<
-  "module '%0' is defined in both '%1' and '%2'">;
-def err_module_file_not_found : Error<
-  "module file '%0' not found">, DefaultFatal;
-def err_module_file_invalid : Error<
-  "file '%0' is not a valid precompiled module file">, DefaultFatal;
-def note_module_file_imported_by : Note<
-  "imported by %select{|module '%2' in }1'%0'">;
-def err_module_file_not_module : Error<
-  "AST file '%0' was not built as a module">, DefaultFatal;
 
 def err_missing_vfs_overlay_file : Error<
   "virtual filesystem overlay file '%0' not found">, DefaultFatal;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td?rev=244416&r1=244415&r2=244416&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td Sun Aug  9 03:48:41 2015
@@ -53,6 +53,20 @@ def err_pch_different_branch : Error<
 def err_pch_with_compiler_errors : Error<
     "PCH file contains compiler errors">;
 
+def err_module_file_conflict : Error<
+  "module '%0' is defined in both '%1' and '%2'">, DefaultFatal;
+def err_module_file_not_found : Error<
+  "%select{PCH|module|AST}0 file '%1' not found%select{|: %3}2">, DefaultFatal;
+def err_module_file_out_of_date : Error<
+  "%select{PCH|module|AST}0 file '%1' is out of date and "
+  "needs to be rebuilt%select{|: %3}2">, DefaultFatal;
+def err_module_file_invalid : Error<
+  "file '%1' is not a valid precompiled %select{PCH|module|AST}0 file">, DefaultFatal;
+def note_module_file_imported_by : Note<
+  "imported by %select{|module '%2' in }1'%0'">;
+def err_module_file_not_module : Error<
+  "AST file '%0' was not built as a module">, DefaultFatal;
+
 def err_imported_module_not_found : Error<
     "module '%0' in AST file '%1' (imported by AST file '%2') "
     "is not defined in any loaded module map file; "
@@ -82,9 +96,6 @@ def err_pch_pp_detailed_record : Error<
     "'-detailed-preprocessing-record' but %select{precompiled header was not "
     "built with it|it is not present on the command line}0">;
 
-def err_not_a_pch_file : Error<
-    "'%0' does not appear to be a precompiled header file">, DefaultFatal;
-
 def err_module_odr_violation_missing_decl : Error<
   "%q0 from module '%1' is not present in definition of %q2"
   "%select{ in module '%4'| provided earlier}3">, NoSFINAE;

Modified: cfe/trunk/lib/CodeGen/ObjectFilePCHContainerOperations.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ObjectFilePCHContainerOperations.cpp?rev=244416&r1=244415&r2=244416&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ObjectFilePCHContainerOperations.cpp (original)
+++ cfe/trunk/lib/CodeGen/ObjectFilePCHContainerOperations.cpp Sun Aug  9 03:48:41 2015
@@ -58,7 +58,7 @@ public:
                         const std::string &OutputFileName,
                         raw_pwrite_stream *OS,
                         std::shared_ptr<PCHBuffer> Buffer)
-      : Diags(diags), HeaderSearchOpts(HSO), PreprocessorOpts(PPO),
+      : Diags(diags), Ctx(nullptr), HeaderSearchOpts(HSO), PreprocessorOpts(PPO),
         TargetOpts(TO), LangOpts(LO), OS(OS), Buffer(Buffer) {
     // The debug info output isn't affected by CodeModel and
     // ThreadModel, but the backend expects them to be nonempty.
@@ -71,6 +71,11 @@ public:
   virtual ~PCHContainerGenerator() {}
 
   void Initialize(ASTContext &Context) override {
+    if (Ctx) {
+      assert(Ctx == &Context);
+      return;
+    }
+
     Ctx = &Context;
     VMContext.reset(new llvm::LLVMContext());
     M.reset(new llvm::Module(MainFileName, *VMContext));

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=244416&r1=244415&r2=244416&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Sun Aug  9 03:48:41 2015
@@ -1261,8 +1261,10 @@ void CompilerInstance::createModuleManag
     getASTContext().setExternalSource(ModuleManager);
     if (hasSema())
       ModuleManager->InitializeSema(getSema());
-    if (hasASTConsumer())
+    if (hasASTConsumer()) {
+      getASTConsumer().Initialize(getASTContext());
       ModuleManager->StartTranslationUnit(&getASTConsumer());
+    }
 
     if (TheDependencyFileGenerator)
       TheDependencyFileGenerator->AttachToASTReader(*ModuleManager);
@@ -1284,86 +1286,44 @@ bool CompilerInstance::loadModuleFile(St
   // the files we were handed.
   struct ReadModuleNames : ASTReaderListener {
     CompilerInstance &CI;
-    std::vector<StringRef> ModuleFileStack;
-    std::vector<StringRef> ModuleNameStack;
-    bool Failed;
-    bool TopFileIsModule;
-
-    ReadModuleNames(CompilerInstance &CI)
-        : CI(CI), Failed(false), TopFileIsModule(false) {}
-
-    bool needsImportVisitation() const override { return true; }
-
-    void visitImport(StringRef FileName) override {
-      if (!CI.ExplicitlyLoadedModuleFiles.insert(FileName).second) {
-        if (ModuleFileStack.size() == 0)
-          TopFileIsModule = true;
-        return;
-      }
-
-      ModuleFileStack.push_back(FileName);
-      ModuleNameStack.push_back(StringRef());
-      if (ASTReader::readASTFileControlBlock(FileName, CI.getFileManager(),
-                                             CI.getPCHContainerReader(),
-                                             *this)) {
-        CI.getDiagnostics().Report(
-            SourceLocation(), CI.getFileManager().getBufferForFile(FileName)
-                                  ? diag::err_module_file_invalid
-                                  : diag::err_module_file_not_found)
-            << FileName;
-        for (int I = ModuleFileStack.size() - 2; I >= 0; --I)
-          CI.getDiagnostics().Report(SourceLocation(),
-                                     diag::note_module_file_imported_by)
-              << ModuleFileStack[I]
-              << !ModuleNameStack[I].empty() << ModuleNameStack[I];
-        Failed = true;
-      }
-      ModuleNameStack.pop_back();
-      ModuleFileStack.pop_back();
-    }
+    llvm::SmallVector<IdentifierInfo*, 8> LoadedModules;
+
+    ReadModuleNames(CompilerInstance &CI) : CI(CI) {}
 
     void ReadModuleName(StringRef ModuleName) override {
-      if (ModuleFileStack.size() == 1)
-        TopFileIsModule = true;
-      ModuleNameStack.back() = ModuleName;
-
-      auto &ModuleFile = CI.ModuleFileOverrides[ModuleName];
-      if (!ModuleFile.empty() &&
-          CI.getFileManager().getFile(ModuleFile) !=
-              CI.getFileManager().getFile(ModuleFileStack.back()))
-        CI.getDiagnostics().Report(SourceLocation(),
-                                   diag::err_conflicting_module_files)
-            << ModuleName << ModuleFile << ModuleFileStack.back();
-      ModuleFile = ModuleFileStack.back();
+      LoadedModules.push_back(
+          CI.getPreprocessor().getIdentifierInfo(ModuleName));
+    }
+
+    void registerAll() {
+      for (auto *II : LoadedModules) {
+        CI.KnownModules[II] = CI.getPreprocessor()
+                                  .getHeaderSearchInfo()
+                                  .getModuleMap()
+                                  .findModule(II->getName());
+      }
+      LoadedModules.clear();
     }
-  } RMN(*this);
+  };
 
   // If we don't already have an ASTReader, create one now.
   if (!ModuleManager)
     createModuleManager();
 
-  // Tell the module manager about this module file.
-  if (getModuleManager()->getModuleManager().addKnownModuleFile(FileName)) {
-    getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_found)
-      << FileName;
+  auto Listener = llvm::make_unique<ReadModuleNames>(*this);
+  auto &ListenerRef = *Listener;
+  ASTReader::ListenerScope ReadModuleNamesListener(*ModuleManager,
+                                                   std::move(Listener));
+
+  // Try to load the module file.
+  if (ModuleManager->ReadAST(FileName, serialization::MK_ExplicitModule,
+                             SourceLocation(), ASTReader::ARR_None)
+          != ASTReader::Success)
     return false;
-  }
-
-  // Build our mapping of module names to module files from this file
-  // and its imports.
-  RMN.visitImport(FileName);
-
-  if (RMN.Failed)
-    return false;
-
-  // If we never found a module name for the top file, then it's not a module,
-  // it's a PCH or preamble or something.
-  if (!RMN.TopFileIsModule) {
-    getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_module)
-      << FileName;
-    return false;
-  }
 
+  // We successfully loaded the module file; remember the set of provided
+  // modules so that we don't try to load implicit modules for them.
+  ListenerRef.registerAll();
   return true;
 }
 
@@ -1412,6 +1372,7 @@ CompilerInstance::loadModule(SourceLocat
       return ModuleLoadResult();
     }
 
+    // FIXME: Rmove ModuleFileOverrides
     auto Override = ModuleFileOverrides.find(ModuleName);
     bool Explicit = Override != ModuleFileOverrides.end();
 
@@ -1507,7 +1468,7 @@ CompilerInstance::loadModule(SourceLocat
     case ASTReader::ConfigurationMismatch:
     case ASTReader::HadErrors:
       ModuleLoader::HadFatalFailure = true;
-      // FIXME: The ASTReader will already have complained, but can we showhorn
+      // FIXME: The ASTReader will already have complained, but can we shoehorn
       // that diagnostic information into a more useful form?
       KnownModules[Path[0].first] = nullptr;
       return ModuleLoadResult();

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=244416&r1=244415&r2=244416&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Sun Aug  9 03:48:41 2015
@@ -2029,6 +2029,21 @@ void ASTReader::ResolveImportedPath(std:
   Filename.assign(Buffer.begin(), Buffer.end());
 }
 
+static bool isDiagnosedResult(ASTReader::ASTReadResult ARR, unsigned Caps) {
+  switch (ARR) {
+  case ASTReader::Failure: return true;
+  case ASTReader::Missing: return !(Caps & ASTReader::ARR_Missing);
+  case ASTReader::OutOfDate: return !(Caps & ASTReader::ARR_OutOfDate);
+  case ASTReader::VersionMismatch: return !(Caps & ASTReader::ARR_VersionMismatch);
+  case ASTReader::ConfigurationMismatch:
+    return !(Caps & ASTReader::ARR_ConfigurationMismatch);
+  case ASTReader::HadErrors: return true;
+  case ASTReader::Success: return false;
+  }
+
+  llvm_unreachable("unknown ASTReadResult");
+}
+
 ASTReader::ASTReadResult
 ASTReader::ReadControlBlock(ModuleFile &F,
                             SmallVectorImpl<ImportedModule> &Loaded,
@@ -2064,8 +2079,9 @@ ASTReader::ReadControlBlock(ModuleFile &
           PP.getHeaderSearchInfo().getHeaderSearchOpts();
 
       // All user input files reside at the index range [0, NumUserInputs), and
-      // system input files reside at [NumUserInputs, NumInputs).
-      if (!DisableValidation) {
+      // system input files reside at [NumUserInputs, NumInputs). For explicitly
+      // loaded module files, ignore missing inputs.
+      if (!DisableValidation && F.Kind != MK_ExplicitModule) {
         bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
 
         // If we are reading a module, we will create a verification timestamp,
@@ -2181,10 +2197,23 @@ ASTReader::ReadControlBlock(ModuleFile &
         ASTFileSignature StoredSignature = Record[Idx++];
         auto ImportedFile = ReadPath(F, Record, Idx);
 
+        // If our client can't cope with us being out of date, we can't cope with
+        // our dependency being missing.
+        unsigned Capabilities = ClientLoadCapabilities;
+        if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+          Capabilities &= ~ARR_Missing;
+
         // Load the AST file.
-        switch(ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F, Loaded,
-                           StoredSize, StoredModTime, StoredSignature,
-                           ClientLoadCapabilities)) {
+        auto Result = ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F,
+                                  Loaded, StoredSize, StoredModTime,
+                                  StoredSignature, Capabilities);
+
+        // If we diagnosed a problem, produce a backtrace.
+        if (isDiagnosedResult(Result, Capabilities))
+          Diag(diag::note_module_file_imported_by)
+              << F.FileName << !F.ModuleName.empty() << F.ModuleName;
+
+        switch (Result) {
         case Failure: return Failure;
           // If we have to ignore the dependency, we'll have to ignore this too.
         case Missing:
@@ -3152,11 +3181,18 @@ ASTReader::ReadModuleMapFileBlock(Record
     const FileEntry *ModMap = M ? Map.getModuleMapFileForUniquing(M) : nullptr;
     if (!ModMap) {
       assert(ImportedBy && "top-level import should be verified");
-      if ((ClientLoadCapabilities & ARR_Missing) == 0)
-        Diag(diag::err_imported_module_not_found) << F.ModuleName << F.FileName
-                                                  << ImportedBy->FileName
-                                                  << F.ModuleMapPath;
-      return Missing;
+      if ((ClientLoadCapabilities & ARR_OutOfDate) == 0) {
+        if (auto *ASTFE = M ? M->getASTFile() : nullptr)
+          // This module was defined by an imported (explicit) module.
+          Diag(diag::err_module_file_conflict) << F.ModuleName << F.FileName
+                                               << ASTFE->getName();
+        else
+          // This module was built with a different module map.
+          Diag(diag::err_imported_module_not_found)
+              << F.ModuleName << F.FileName << ImportedBy->FileName
+              << F.ModuleMapPath;
+      }
+      return OutOfDate;
     }
 
     assert(M->Name == F.ModuleName && "found module with different name");
@@ -3557,6 +3593,20 @@ static bool startsWithASTFileMagic(Bitst
          Stream.Read(8) == 'H';
 }
 
+static unsigned moduleKindForDiagnostic(ModuleKind Kind) {
+  switch (Kind) {
+  case MK_PCH:
+    return 0; // PCH
+  case MK_ImplicitModule:
+  case MK_ExplicitModule:
+    return 1; // module
+  case MK_MainFile:
+  case MK_Preamble:
+    return 2; // main source file
+  }
+  llvm_unreachable("unknown module kind");
+}
+
 ASTReader::ASTReadResult
 ASTReader::ReadASTCore(StringRef FileName,
                        ModuleKind Type,
@@ -3589,11 +3639,9 @@ ASTReader::ReadASTCore(StringRef FileNam
       return Missing;
 
     // Otherwise, return an error.
-    {
-      std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
-                      + ErrorStr;
-      Error(Msg);
-    }
+    Diag(diag::err_module_file_not_found) << moduleKindForDiagnostic(Type)
+                                          << FileName << ErrorStr.empty()
+                                          << ErrorStr;
     return Failure;
 
   case ModuleManager::OutOfDate:
@@ -3603,11 +3651,9 @@ ASTReader::ReadASTCore(StringRef FileNam
       return OutOfDate;
 
     // Otherwise, return an error.
-    {
-      std::string Msg = "Unable to load module \"" + FileName.str() + "\": "
-                      + ErrorStr;
-      Error(Msg);
-    }
+    Diag(diag::err_module_file_out_of_date) << moduleKindForDiagnostic(Type)
+                                            << FileName << ErrorStr.empty()
+                                            << ErrorStr;
     return Failure;
   }
 
@@ -3628,7 +3674,8 @@ ASTReader::ReadASTCore(StringRef FileNam
   
   // Sniff for the signature.
   if (!startsWithASTFileMagic(Stream)) {
-    Diag(diag::err_not_a_pch_file) << FileName;
+    Diag(diag::err_module_file_invalid) << moduleKindForDiagnostic(Type)
+                                        << FileName;
     return Failure;
   }
 
@@ -3661,6 +3708,18 @@ ASTReader::ReadASTCore(StringRef FileNam
       HaveReadControlBlock = true;
       switch (ReadControlBlock(F, Loaded, ImportedBy, ClientLoadCapabilities)) {
       case Success:
+        // Check that we didn't try to load a non-module AST file as a module.
+        //
+        // FIXME: Should we also perform the converse check? Loading a module as
+        // a PCH file sort of works, but it's a bit wonky.
+        if ((Type == MK_ImplicitModule || Type == MK_ExplicitModule) &&
+            F.ModuleName.empty()) {
+          auto Result = (Type == MK_ImplicitModule) ? OutOfDate : Failure;
+          if (Result != OutOfDate ||
+              (ClientLoadCapabilities & ARR_OutOfDate) == 0)
+            Diag(diag::err_module_file_not_module) << FileName;
+          return Result;
+        }
         break;
 
       case Failure: return Failure;
@@ -3690,8 +3749,6 @@ ASTReader::ReadASTCore(StringRef FileNam
       break;
     }
   }
-  
-  return Success;
 }
 
 void ASTReader::InitializeContext() {

Modified: cfe/trunk/test/Index/pch-depending-on-deleted-module.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/pch-depending-on-deleted-module.c?rev=244416&r1=244415&r2=244416&view=diff
==============================================================================
--- cfe/trunk/test/Index/pch-depending-on-deleted-module.c (original)
+++ cfe/trunk/test/Index/pch-depending-on-deleted-module.c Sun Aug  9 03:48:41 2015
@@ -9,6 +9,6 @@
 // RUN: not %clang_cc1 -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -I %S/Inputs/Headers -verify-pch %t/use_LibA.pch 2>&1 | FileCheck -check-prefix=VERIFY %s
 // RUN: not c-index-test -test-load-source all -x c -fmodules -fimplicit-module-maps -Xclang -fdisable-module-hash -fmodules-cache-path=%t/modules-cache -I %S/Inputs/Headers -include-pch %t/use_LibA.pch %s 2>&1 | FileCheck -check-prefix=INDEX %s
 
-// VERIFY: fatal error: malformed or corrupted AST file: 'Unable to load module
+// VERIFY: fatal error: module file '{{.*}}LibA.pcm' not found
 // INDEX: {{^}}Failure: AST deserialization error occurred{{$}}
 

Modified: cfe/trunk/test/Modules/dependency-gen.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/dependency-gen.modulemap?rev=244416&r1=244415&r2=244416&view=diff
==============================================================================
--- cfe/trunk/test/Modules/dependency-gen.modulemap (original)
+++ cfe/trunk/test/Modules/dependency-gen.modulemap Sun Aug  9 03:48:41 2015
@@ -1,10 +1,10 @@
 // RUN: cd %S
 // RUN: rm -rf %t
 //
-// RUN: %clang_cc1 -I. -x c++ -fmodule-name=test -fmodules -emit-module -fno-validate-pch -fmodules-strict-decluse %s -dependency-file - -MT implicit.pcm -o %t/implicit.pcm -fmodules-cache-path=%t -fmodule-map-file-home-is-cwd | FileCheck %s
+// RUN: %clang_cc1 -I. -x c++ -fmodule-name=test -fmodules -emit-module -fno-validate-pch -fmodules-strict-decluse %s -dependency-file - -MT implicit.pcm -o %t/implicit.pcm -fmodules-cache-path=%t -fmodule-map-file-home-is-cwd | FileCheck %s --check-prefix=IMPLICIT
 //
 // RUN: %clang_cc1 -I. -x c++ -fmodule-name=test-base -fmodules -emit-module -fno-validate-pch -fmodules-strict-decluse Inputs/dependency-gen-base.modulemap -o %t/base.pcm -fmodule-map-file-home-is-cwd
-// RUN: %clang_cc1 -I. -x c++ -fmodule-name=test -fmodules -emit-module -fno-validate-pch -fmodules-strict-decluse -fmodule-file=%t/base.pcm %s -dependency-file - -MT explicit.pcm -o %t/explicit.pcm -fmodules-cache-path=%t -fmodule-map-file-home-is-cwd | FileCheck %s
+// RUN: %clang_cc1 -I. -x c++ -fmodule-name=test -fmodules -emit-module -fno-validate-pch -fmodules-strict-decluse -fmodule-file=%t/base.pcm %s -dependency-file - -MT explicit.pcm -o %t/explicit.pcm -fmodules-cache-path=%t -fmodule-map-file-home-is-cwd | FileCheck %s --check-prefix=EXPLICIT
 module "test" {
   export *
   header "Inputs/dependency-gen.h"
@@ -14,10 +14,30 @@ module "test" {
 extern module "test-base2" "Inputs/dependency-gen-base2.modulemap"
 extern module "test-base" "Inputs/dependency-gen-base.modulemap"
 
-// CHECK-DAG: {{[/\\]}}dependency-gen.modulemap
-// CHECK-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-base.modulemap
-// CHECK-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-base2.modulemap
+// For implicit use of a module via the module cache, the input files
+// referenced by the .pcm are also dependencies of this build.
+//
+// IMPLICIT-DAG: {{[/\\]}}dependency-gen.modulemap
+// IMPLICIT-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-base.modulemap
+// IMPLICIT-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-base2.modulemap
+// IMPLICIT-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen.h
+// IMPLICIT-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-included.h
+// IMPLICIT-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-included2.h
 
-// CHECK-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen.h
-// CHECK-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-included.h
-// CHECK-DAG: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen-included2.h
+// For an explicit use of a module via -fmodule-file=, the other module maps
+// and included headers are not dependencies of this target (they are instead
+// dependencies of the explicitly-specified .pcm input).
+//
+// FIXME: We should avoid loading the other referenced module maps (we already
+// have a parsed copy of their contents from the .pcm file) and thus not list
+// them here.
+//
+// FIXME: We should list a dependency on the explicitly specified .pcm files
+// (whether or not -module-file-deps is specified on the command line).
+//
+// EXPLICIT-FIXME-NOT: dependency-gen-
+// EXPLICIT-FIXME: {{.*}}/base.pcm
+//
+// EXPLICIT: {{^}}explicit.pcm:
+// EXPLICIT: {{.*}}/dependency-gen.modulemap
+// EXPLICIT: {{ |\.[/\\]}}Inputs{{[/\\]}}dependency-gen.h

Added: cfe/trunk/test/Modules/explicit-build-missing-files.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/explicit-build-missing-files.cpp?rev=244416&view=auto
==============================================================================
--- cfe/trunk/test/Modules/explicit-build-missing-files.cpp (added)
+++ cfe/trunk/test/Modules/explicit-build-missing-files.cpp Sun Aug  9 03:48:41 2015
@@ -0,0 +1,21 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo 'extern int a;' > %t/a.h
+// RUN: echo 'extern int b;' > %t/b.h
+// RUN: echo 'module a { header "a.h" header "b.h" }' > %t/modulemap
+
+// We lazily check that the files referenced by an explicitly-specified .pcm
+// file exist. Test this by removing files and ensuring that the compilation
+// still succeeds.
+//
+// RUN: %clang_cc1 -fmodules -I %t -emit-module -fmodule-name=a -x c++ %t/modulemap -o %t/a.pcm
+// RUN: %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s
+// RUN: rm %t/modulemap
+// RUN: %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s
+// RUN: rm %t/b.h
+// RUN: %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s
+// RUN: rm %t/a.h
+// RUN: %clang_cc1 -fmodules -I %t -fmodule-file=%t/a.pcm %s -verify
+
+#include "a.h" // expected-error {{file not found}}
+int x = b;

Modified: cfe/trunk/test/Modules/explicit-build.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/explicit-build.cpp?rev=244416&r1=244415&r2=244416&view=diff
==============================================================================
--- cfe/trunk/test/Modules/explicit-build.cpp (original)
+++ cfe/trunk/test/Modules/explicit-build.cpp Sun Aug  9 03:48:41 2015
@@ -179,6 +179,7 @@
 // CHECK-NO-FILE-INDIRECT:      error: module file '{{.*}}a.pcm' not found
 // CHECK-NO-FILE-INDIRECT-NEXT: note: imported by module 'b' in '{{.*}}b.pcm'
 // CHECK-NO-FILE-INDIRECT-NEXT: note: imported by module 'c' in '{{.*}}c.pcm'
+// CHECK-NO-FILE-INDIRECT-NOT:  note:
 
 // -------------------------------
 // Check that we don't get upset if B's timestamp is newer than C's.
@@ -198,4 +199,6 @@
 // RUN:            -fmodule-file=%t/c.pcm \
 // RUN:            %s -DHAVE_A -DHAVE_B -DHAVE_C 2>&1 | FileCheck --check-prefix=CHECK-MISMATCHED-B %s
 //
-// CHECK-MISMATCHED-B: fatal error: malformed or corrupted AST file: {{.*}}b.pcm": module file out of date
+// CHECK-MISMATCHED-B:      fatal error: module file '{{.*}}b.pcm' is out of date and needs to be rebuilt
+// CHECK-MISMATCHED-B-NEXT: note: imported by module 'c'
+// CHECK-MISMATCHED-B-NOT:  note:

Modified: cfe/trunk/test/Modules/fatal-module-loader-error.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/fatal-module-loader-error.m?rev=244416&r1=244415&r2=244416&view=diff
==============================================================================
--- cfe/trunk/test/Modules/fatal-module-loader-error.m (original)
+++ cfe/trunk/test/Modules/fatal-module-loader-error.m Sun Aug  9 03:48:41 2015
@@ -8,13 +8,13 @@
 
 #ifdef IMPLICIT
 
-// expected-error at +1{{does not appear to be}}
+// expected-error at +1{{Module.pcm' is not a valid precompiled module file}}
 #import <Module/Module.h>
 #pragma clang __debug crash;
 
 #else
 
-// expected-error at +1{{does not appear to be}}
+// expected-error at +1{{Module.pcm' is not a valid precompiled module file}}
 @import Module;
 #pragma clang __debug crash;
 

Modified: cfe/trunk/test/Modules/relative-dep-gen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/relative-dep-gen.cpp?rev=244416&r1=244415&r2=244416&view=diff
==============================================================================
--- cfe/trunk/test/Modules/relative-dep-gen.cpp (original)
+++ cfe/trunk/test/Modules/relative-dep-gen.cpp Sun Aug  9 03:48:41 2015
@@ -25,6 +25,6 @@
 // CHECK-BUILD:   Inputs/relative-dep-gen-1.h
 // CHECK-BUILD:   Inputs/relative-dep-gen-2.h
 // CHECK-USE: use.o:
-// CHECK-USE:   Inputs/relative-dep-gen{{(-cwd)?}}.modulemap
-// CHECK-USE:   relative-dep-gen.cpp
-// CHECK-USE:   Inputs/relative-dep-gen-1.h
+// CHECK-USE-DAG:   Inputs/relative-dep-gen{{(-cwd)?}}.modulemap
+// CHECK-USE-DAG:   relative-dep-gen.cpp
+// CHECK-USE-DAG:   Inputs/relative-dep-gen-1.h




More information about the cfe-commits mailing list