]> granicus.if.org Git - clang/commitdiff
Give better diagnostics when -fmodule-file= finds a bad file: if the file is
authorRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 28 Feb 2015 03:09:52 +0000 (03:09 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Sat, 28 Feb 2015 03:09:52 +0000 (03:09 +0000)
found indirectly, explain how we got there, and distinguish between 'file not
found' and 'file found but invalid'.

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

include/clang/Basic/DiagnosticFrontendKinds.td
lib/Frontend/CompilerInstance.cpp
test/Modules/explicit-build.cpp

index 13e2865a52bf0e2734fff678f138b12dbca24751..f4ab4800c9e79551f15efb20b09e5be1ccad51d1 100644 (file)
@@ -197,7 +197,11 @@ def err_conflicting_module_names : Error<
 def err_conflicting_module_files : Error<
   "module '%0' is defined in both '%1' and '%2'">;
 def err_module_file_not_found : Error<
-  "file '%0' is not a precompiled module file">, DefaultFatal;
+  "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;
 
index 07812bdc83916768bc472c6bdc6663bfae1c8891..2dac20bcb0ffe9d418b9d28d0ce62a40c0909189 100644 (file)
@@ -1279,6 +1279,7 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
   struct ReadModuleNames : ASTReaderListener {
     CompilerInstance &CI;
     std::vector<StringRef> ModuleFileStack;
+    std::vector<StringRef> ModuleNameStack;
     bool Failed;
     bool TopFileIsModule;
 
@@ -1295,20 +1296,29 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
       }
 
       ModuleFileStack.push_back(FileName);
+      ModuleNameStack.push_back(StringRef());
       if (ASTReader::readASTFileControlBlock(FileName, CI.getFileManager(),
                                              *this)) {
-        CI.getDiagnostics().Report(SourceLocation(),
-                                   diag::err_module_file_not_found)
+        CI.getDiagnostics().Report(
+            SourceLocation(), CI.getFileManager().getBufferForFile(FileName)
+                                  ? diag::err_module_file_invalid
+                                  : diag::err_module_file_not_found)
             << FileName;
-        // FIXME: Produce a note stack explaining how we got here.
+        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();
     }
 
     void ReadModuleName(StringRef ModuleName) override {
       if (ModuleFileStack.size() == 1)
         TopFileIsModule = true;
+      ModuleNameStack.back() = ModuleName;
 
       auto &ModuleFile = CI.ModuleFileOverrides[ModuleName];
       if (!ModuleFile.empty() &&
index ce3a1af4162617dc47c8b127beaf619d866fc20d..ff98f92b1f5556e7dbfd0270923ffa94c82571c3 100644 (file)
 // RUN:            -fmodule-file=%t/not.pcm \
 // RUN:            %s 2>&1 | FileCheck --check-prefix=CHECK-BAD-FILE %s
 //
+// CHECK-BAD-FILE: fatal error: file '{{.*}}not.pcm' is not a valid precompiled module file
+
 // RUN: not %clang_cc1 -x c++ -std=c++11 -fmodules -fmodules-cache-path=%t -Rmodule-build -fno-modules-error-recovery \
 // RUN:            -fmodule-file=%t/nonexistent.pcm \
-// RUN:            %s 2>&1 | FileCheck --check-prefix=CHECK-BAD-FILE %s
+// RUN:            %s 2>&1 | FileCheck --check-prefix=CHECK-NO-FILE %s
+//
+// CHECK-NO-FILE: fatal error: module file '{{.*}}nonexistent.pcm' not found
+
+// RUN: mv %t/a.pcm %t/a-tmp.pcm
+// RUN: not %clang_cc1 -x c++ -std=c++11 -fmodules -fmodules-cache-path=%t -Rmodule-build -fno-modules-error-recovery \
+// RUN:            -I%S/Inputs/explicit-build \
+// RUN:            -fmodule-file=%t/c.pcm \
+// RUN:            %s 2>&1 | FileCheck --check-prefix=CHECK-NO-FILE-INDIRECT %s
+// RUN: mv %t/a-tmp.pcm %t/a.pcm
 //
-// CHECK-BAD-FILE: fatal error: file '{{.*}}t.pcm' is not a precompiled module file
+// 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 that we don't get upset if B's timestamp is newer than C's.