[cfe-commits] r169021 - in /cfe/trunk: include/clang/Basic/SourceManager.h include/clang/Frontend/DiagnosticRenderer.h include/clang/Frontend/TextDiagnostic.h include/clang/Lex/PreprocessorOptions.h lib/Frontend/CompilerInstance.cpp lib/Frontend/DiagnosticRenderer.cpp lib/Frontend/TextDiagnostic.cpp test/Modules/build-fail-notes.m test/Modules/cycles.c test/Modules/epic-fail.m

Douglas Gregor dgregor at apple.com
Fri Nov 30 10:38:50 PST 2012


Author: dgregor
Date: Fri Nov 30 12:38:50 2012
New Revision: 169021

URL: http://llvm.org/viewvc/llvm-project?rev=169021&view=rev
Log:
When an error occurs while building a module on demand, provide "While
building module 'Foo' imported from..." notes (the same we we provide
"In file included from..." notes) in the diagnostic, so that we know
how this module got included in the first place. This is part of
<rdar://problem/12696425>.

Added:
    cfe/trunk/test/Modules/build-fail-notes.m
Modified:
    cfe/trunk/include/clang/Basic/SourceManager.h
    cfe/trunk/include/clang/Frontend/DiagnosticRenderer.h
    cfe/trunk/include/clang/Frontend/TextDiagnostic.h
    cfe/trunk/include/clang/Lex/PreprocessorOptions.h
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp
    cfe/trunk/lib/Frontend/TextDiagnostic.cpp
    cfe/trunk/test/Modules/cycles.c
    cfe/trunk/test/Modules/epic-fail.m

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=169021&r1=169020&r2=169021&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Fri Nov 30 12:38:50 2012
@@ -40,6 +40,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
@@ -508,6 +509,11 @@
 
 };
 
+/// \brief The path used when building modules on demand, which is used
+/// to provide a link between the source managers of the different compiler
+/// instances.
+typedef llvm::ArrayRef<std::pair<std::string, FullSourceLoc> > ModuleBuildPath;
+
 /// \brief This class handles loading and caching of source files into memory.
 ///
 /// This object owns the MemoryBuffer objects for all of the loaded
@@ -645,6 +651,15 @@
 
   mutable llvm::DenseMap<FileID, MacroArgsMap *> MacroArgsCacheMap;
 
+  /// \brief The path of modules being built, which is used to detect
+  /// cycles in the module dependency graph as modules are being built, as
+  /// well as to describe 
+  ///
+  /// There is no way to set this value from the command line. If we ever need
+  /// to do so (e.g., if on-demand module construction moves out-of-process),
+  /// we can add a cc1-level option to do so.
+  SmallVector<std::pair<std::string, FullSourceLoc>, 2> StoredModuleBuildPath;
+
   // SourceManager doesn't support copy construction.
   explicit SourceManager(const SourceManager&) LLVM_DELETED_FUNCTION;
   void operator=(const SourceManager&) LLVM_DELETED_FUNCTION;
@@ -669,6 +684,22 @@
   /// (likely to change while trying to use them).
   bool userFilesAreVolatile() const { return UserFilesAreVolatile; }
 
+  /// \brief Retrieve the module build path.
+  ModuleBuildPath getModuleBuildPath() const {
+    return StoredModuleBuildPath;
+  }
+
+  /// \brief Set the module build path.
+  void setModuleBuildPath(ModuleBuildPath path) {
+    StoredModuleBuildPath.clear();
+    StoredModuleBuildPath.append(path.begin(), path.end());
+  }
+
+  /// \brief Append an entry to the module build path.
+  void appendModuleBuildPath(StringRef moduleName, FullSourceLoc importLoc) {
+    StoredModuleBuildPath.push_back(std::make_pair(moduleName.str(),importLoc));
+  }
+
   /// \brief Create the FileID for a memory buffer that will represent the
   /// FileID for the main source.
   ///

Modified: cfe/trunk/include/clang/Frontend/DiagnosticRenderer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/DiagnosticRenderer.h?rev=169021&r1=169020&r2=169021&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/DiagnosticRenderer.h (original)
+++ cfe/trunk/include/clang/Frontend/DiagnosticRenderer.h Fri Nov 30 12:38:50 2012
@@ -92,7 +92,10 @@
   
   virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
                                    const SourceManager &SM) = 0;
-  
+  virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
+                                          StringRef ModuleName,
+                                          const SourceManager &SM) = 0;
+
   virtual void beginDiagnostic(DiagOrStoredDiag D,
                                DiagnosticsEngine::Level Level) {}
   virtual void endDiagnostic(DiagOrStoredDiag D,
@@ -103,6 +106,7 @@
   void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level,
                         const SourceManager &SM);
   void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
+  void emitModuleBuildPath(const SourceManager &SM);
   void emitMacroExpansionsAndCarets(SourceLocation Loc,
                                     DiagnosticsEngine::Level Level,
                                     SmallVectorImpl<CharSourceRange>& Ranges,
@@ -149,7 +153,11 @@
   virtual void emitIncludeLocation(SourceLocation Loc,
                                    PresumedLoc PLoc,
                                    const SourceManager &SM);
-  
+
+  virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
+                                          StringRef ModuleName,
+                                          const SourceManager &SM);
+
   virtual void emitNote(SourceLocation Loc, StringRef Message,
                         const SourceManager *SM) = 0;
 };

Modified: cfe/trunk/include/clang/Frontend/TextDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/TextDiagnostic.h?rev=169021&r1=169020&r2=169021&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/TextDiagnostic.h (original)
+++ cfe/trunk/include/clang/Frontend/TextDiagnostic.h Fri Nov 30 12:38:50 2012
@@ -103,6 +103,10 @@
   virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
                                    const SourceManager &SM);
 
+  virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
+                                          StringRef ModuleName,
+                                          const SourceManager &SM);
+
 private:
   void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
                            SmallVectorImpl<CharSourceRange>& Ranges,

Modified: cfe/trunk/include/clang/Lex/PreprocessorOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/PreprocessorOptions.h?rev=169021&r1=169020&r2=169021&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/PreprocessorOptions.h (original)
+++ cfe/trunk/include/clang/Lex/PreprocessorOptions.h Fri Nov 30 12:38:50 2012
@@ -10,6 +10,7 @@
 #ifndef LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
 #define LLVM_CLANG_LEX_PREPROCESSOROPTIONS_H_
 
+#include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
@@ -120,14 +121,6 @@
   /// with support for lifetime-qualified pointers.
   ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary;
     
-  /// \brief The path of modules being build, which is used to detect
-  /// cycles in the module dependency graph as modules are being built.
-  ///
-  /// There is no way to set this value from the command line. If we ever need
-  /// to do so (e.g., if on-demand module construction moves out-of-process),
-  /// we can add a cc1-level option to do so.
-  SmallVector<std::string, 2> ModuleBuildPath;
-
   /// \brief Records the set of modules
   class FailedModulesSet : public llvm::RefCountedBase<FailedModulesSet> {
     llvm::StringSet<> Failed;

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=169021&r1=169020&r2=169021&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Fri Nov 30 12:38:50 2012
@@ -762,6 +762,7 @@
 /// \brief Compile a module file for the given module, using the options 
 /// provided by the importing compiler instance.
 static void compileModule(CompilerInstance &ImportingInstance,
+                          SourceLocation ImportLoc,
                           Module *Module,
                           StringRef ModuleFileName) {
   llvm::LockFileManager Locked(ModuleFileName);
@@ -797,10 +798,6 @@
   // Note the name of the module we're building.
   Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName();
 
-  // Note that this module is part of the module build path, so that we
-  // can detect cycles in the module graph.
-  PPOpts.ModuleBuildPath.push_back(Module->getTopLevelModuleName());
-
   // Make sure that the failed-module structure has been allocated in
   // the importing instance, and propagate the pointer to the newly-created
   // instance.
@@ -861,7 +858,18 @@
                              &ImportingInstance.getDiagnosticClient(),
                              /*ShouldOwnClient=*/true,
                              /*ShouldCloneClient=*/true);
-  
+
+  // Note that this module is part of the module build path, so that we
+  // can detect cycles in the module graph.
+  Instance.createFileManager(); // FIXME: Adopt file manager from importer?
+  Instance.createSourceManager(Instance.getFileManager());
+  SourceManager &SourceMgr = Instance.getSourceManager();
+  SourceMgr.setModuleBuildPath(
+    ImportingInstance.getSourceManager().getModuleBuildPath());
+  SourceMgr.appendModuleBuildPath(Module->getTopLevelModuleName(),
+    FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager()));
+
+
   // Construct a module-generating action.
   GenerateModuleAction CreateModuleAction;
   
@@ -939,14 +947,17 @@
       // build the module.
 
       // Check whether there is a cycle in the module graph.
-      SmallVectorImpl<std::string> &ModuleBuildPath
-        = getPreprocessorOpts().ModuleBuildPath;
-      SmallVectorImpl<std::string>::iterator Pos
-        = std::find(ModuleBuildPath.begin(), ModuleBuildPath.end(), ModuleName);
-      if (Pos != ModuleBuildPath.end()) {
+      ModuleBuildPath Path = getSourceManager().getModuleBuildPath();
+      ModuleBuildPath::iterator Pos = Path.begin(), PosEnd = Path.end();
+      for (; Pos != PosEnd; ++Pos) {
+        if (Pos->first == ModuleName)
+          break;
+      }
+
+      if (Pos != PosEnd) {
         SmallString<256> CyclePath;
-        for (; Pos != ModuleBuildPath.end(); ++Pos) {
-          CyclePath += *Pos;
+        for (; Pos != PosEnd; ++Pos) {
+          CyclePath += Pos->first;
           CyclePath += " -> ";
         }
         CyclePath += ModuleName;
@@ -970,7 +981,7 @@
       getDiagnostics().Report(ModuleNameLoc, diag::warn_module_build)
         << ModuleName;
       BuildingModule = true;
-      compileModule(*this, Module, ModuleFileName);
+      compileModule(*this, ModuleNameLoc, Module, ModuleFileName);
       ModuleFile = FileMgr->getFile(ModuleFileName);
 
       if (!ModuleFile)
@@ -1040,7 +1051,7 @@
         return ModuleLoadResult();
       }
 
-      compileModule(*this, Module, ModuleFileName);
+      compileModule(*this, ModuleNameLoc, Module, ModuleFileName);
 
       // Try loading the module again.
       ModuleFile = FileMgr->getFile(ModuleFileName);

Modified: cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp?rev=169021&r1=169020&r2=169021&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp (original)
+++ cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp Fri Nov 30 12:38:50 2012
@@ -205,8 +205,10 @@
 /// on the way back down.
 void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
                                                      const SourceManager &SM) {
-  if (Loc.isInvalid())
+  if (Loc.isInvalid()) {
+    emitModuleBuildPath(SM);
     return;
+  }
   
   PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
   if (PLoc.isInvalid())
@@ -219,6 +221,21 @@
   emitIncludeLocation(Loc, PLoc, SM);
 }
 
+/// \brief Emit the module build path, for cases where a module is (re-)built
+/// on demand.
+void DiagnosticRenderer::emitModuleBuildPath(const SourceManager &SM) {
+  ModuleBuildPath Path = SM.getModuleBuildPath();
+  for (unsigned I = 0, N = Path.size(); I != N; ++I) {
+    const SourceManager &CurSM = Path[I].second.getManager();
+    SourceLocation CurLoc = Path[I].second;
+    emitBuildingModuleLocation(CurLoc,
+                               CurSM.getPresumedLoc(CurLoc,
+                                                    DiagOpts->ShowPresumedLoc),
+                               Path[I].first,
+                               CurSM);
+  }
+}
+
 // Helper function to fix up source ranges.  It takes in an array of ranges,
 // and outputs an array of ranges where we want to draw the range highlighting
 // around the location specified by CaretLoc.
@@ -390,6 +407,20 @@
   emitNote(Loc, Message.str(), &SM);
 }
 
+void
+DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc,
+                                                   PresumedLoc PLoc,
+                                                   StringRef ModuleName,
+                                                   const SourceManager &SM) {
+  // Generate a note indicating the include location.
+  SmallString<200> MessageStorage;
+  llvm::raw_svector_ostream Message(MessageStorage);
+  Message << "while building module '" << ModuleName << "' imported from "
+          << PLoc.getFilename() << ':' << PLoc.getLine() << ":";
+  emitNote(Loc, Message.str(), &SM);
+}
+
+
 void DiagnosticNoteRenderer::emitBasicNote(StringRef Message) {
   emitNote(SourceLocation(), Message, 0);  
 }

Modified: cfe/trunk/lib/Frontend/TextDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/TextDiagnostic.cpp?rev=169021&r1=169020&r2=169021&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/TextDiagnostic.cpp (original)
+++ cfe/trunk/lib/Frontend/TextDiagnostic.cpp Fri Nov 30 12:38:50 2012
@@ -884,6 +884,17 @@
     OS << "In included file:\n"; 
 }
 
+void TextDiagnostic::emitBuildingModuleLocation(SourceLocation Loc,
+                                                PresumedLoc PLoc,
+                                                StringRef ModuleName,
+                                                const SourceManager &SM) {
+  if (DiagOpts->ShowLocation)
+    OS << "While building module '" << ModuleName << "' imported from "
+      << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n";
+  else
+    OS << "While building module '" << ModuleName << "':\n";
+}
+
 /// \brief Emit a code snippet and caret line.
 ///
 /// This routine emits a single line's code snippet and caret line..

Added: cfe/trunk/test/Modules/build-fail-notes.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/build-fail-notes.m?rev=169021&view=auto
==============================================================================
--- cfe/trunk/test/Modules/build-fail-notes.m (added)
+++ cfe/trunk/test/Modules/build-fail-notes.m Fri Nov 30 12:38:50 2012
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodule-cache-path %t -fmodules -F %S/Inputs -DgetModuleVersion="epic fail" %s 2>&1 | FileCheck %s
+
+ at __experimental_modules_import DependsOnModule;
+
+// CHECK: While building module 'DependsOnModule' imported from
+// CHECK: While building module 'Module' imported from
+// CHECK: error: expected ';' after top level declarator
+// CHECK: note: expanded from macro 'getModuleVersion'
+// CHECK: fatal error: could not build module 'Module'
+// CHECK: fatal error: could not build module 'DependsOnModule'
+// CHECK-NOT: error:

Modified: cfe/trunk/test/Modules/cycles.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cycles.c?rev=169021&r1=169020&r2=169021&view=diff
==============================================================================
--- cfe/trunk/test/Modules/cycles.c (original)
+++ cfe/trunk/test/Modules/cycles.c Fri Nov 30 12:38:50 2012
@@ -3,10 +3,11 @@
 // FIXME: When we have a syntax for modules in C, use that.
 @__experimental_modules_import MutuallyRecursive1;
 
-// FIXME: Lots of redundant diagnostics here, because the preprocessor
-// can't currently tell the parser not to try to load the module again.
-
+// CHECK: While building module 'MutuallyRecursive1' imported from
+// CHECK: While building module 'MutuallyRecursive2' imported from
 // CHECK: MutuallyRecursive2.h:3:32: fatal error: cyclic dependency in module 'MutuallyRecursive1': MutuallyRecursive1 -> MutuallyRecursive2 -> MutuallyRecursive1
+// CHECK: While building module 'MutuallyRecursive1' imported from
 // CHECK: MutuallyRecursive1.h:2:32: fatal error: could not build module 'MutuallyRecursive2'
 // CHECK: cycles.c:4:32: fatal error: could not build module 'MutuallyRecursive1'
+// CHECK-NOT: error:
 

Modified: cfe/trunk/test/Modules/epic-fail.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/epic-fail.m?rev=169021&r1=169020&r2=169021&view=diff
==============================================================================
--- cfe/trunk/test/Modules/epic-fail.m (original)
+++ cfe/trunk/test/Modules/epic-fail.m Fri Nov 30 12:38:50 2012
@@ -4,8 +4,10 @@
 @__experimental_modules_import Module;
 @__experimental_modules_import DependsOnModule;
 
+// CHECK: While building module 'Module' imported from
 // CHECK: error: expected ';' after top level declarator
 // CHECK: note: expanded from macro 'getModuleVersion'
 // CHECK: fatal error: could not build module 'Module'
+// CHECK: While building module 'DependsOnModule' imported from
 // CHECK: fatal error: could not build module 'Module'
 // CHECK-NOT: error:





More information about the cfe-commits mailing list