[cfe-commits] r169042 - in /cfe/trunk: include/clang/Basic/SourceManager.h include/clang/Frontend/DiagnosticRenderer.h include/clang/Frontend/TextDiagnostic.h include/clang/Serialization/ASTReader.h lib/Frontend/DiagnosticRenderer.cpp lib/Frontend/TextDiagnostic.cpp lib/Serialization/ASTReader.cpp test/Modules/build-fail-notes.m

Douglas Gregor dgregor at apple.com
Fri Nov 30 13:58:49 PST 2012


Author: dgregor
Date: Fri Nov 30 15:58:49 2012
New Revision: 169042

URL: http://llvm.org/viewvc/llvm-project?rev=169042&view=rev
Log:
When we're emitting a diagnostic with a source location in an imported
module, provide a module import stack similar to what we would get for
an include stack, e.g.,

In module 'DependsOnModule' imported from build-fail-notes.m:4:
In module 'Module' imported from DependsOnModule.framework/Headers/DependsOnModule.h:1:
Inputs/Module.framework/Headers/Module.h:15:12: note: previous definition is here
@interface Module

<rdar://problem/12696425>

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/Serialization/ASTReader.h
    cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp
    cfe/trunk/lib/Frontend/TextDiagnostic.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/test/Modules/build-fail-notes.m

Modified: cfe/trunk/include/clang/Basic/SourceManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/SourceManager.h?rev=169042&r1=169041&r2=169042&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/SourceManager.h (original)
+++ cfe/trunk/include/clang/Basic/SourceManager.h Fri Nov 30 15:58:49 2012
@@ -430,6 +430,11 @@
   /// \returns true if an error occurred that prevented the source-location
   /// entry from being loaded.
   virtual bool ReadSLocEntry(int ID) = 0;
+
+  /// \brief Retrieve the module import location and name for the given ID, if
+  /// in fact it was loaded from a module (rather than, say, a precompiled
+  /// header).
+  virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) = 0;
 };
 
 
@@ -990,6 +995,21 @@
     return Entry.getFile().getIncludeLoc();
   }
 
+  // \brief Returns the import location if the given source location is
+  // located within a module, or an invalid location if the source location
+  // is within the current translation unit.
+  std::pair<SourceLocation, StringRef>
+  getModuleImportLoc(SourceLocation Loc) const {
+    FileID FID = getFileID(Loc);
+
+    // Positive file IDs are in the current translation unit, and -1 is a
+    // placeholder.
+    if (FID.ID >= -1)
+      return std::make_pair(SourceLocation(), "");
+
+    return ExternalSLocEntries->getModuleImportLoc(FID.ID);
+  }
+
   /// \brief Given a SourceLocation object \p Loc, return the expansion
   /// location referenced by the ID.
   SourceLocation getExpansionLoc(SourceLocation Loc) const {

Modified: cfe/trunk/include/clang/Frontend/DiagnosticRenderer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/DiagnosticRenderer.h?rev=169042&r1=169041&r2=169042&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/DiagnosticRenderer.h (original)
+++ cfe/trunk/include/clang/Frontend/DiagnosticRenderer.h Fri Nov 30 15:58:49 2012
@@ -19,6 +19,7 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/PointerUnion.h"
 
 namespace clang {
@@ -92,6 +93,9 @@
   
   virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
                                    const SourceManager &SM) = 0;
+  virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
+                                  StringRef ModuleName,
+                                  const SourceManager &SM) = 0;
   virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
                                           StringRef ModuleName,
                                           const SourceManager &SM) = 0;
@@ -103,9 +107,12 @@
 
   
 private:
-  void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level,
-                        const SourceManager &SM);
+  void emitIncludeStack(SourceLocation Loc, PresumedLoc PLoc,
+                        DiagnosticsEngine::Level Level, const SourceManager &SM);
   void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
+  void emitImportStack(SourceLocation Loc, const SourceManager &SM);
+  void emitImportStackRecursively(SourceLocation Loc, StringRef ModuleName,
+                                  const SourceManager &SM);
   void emitModuleBuildPath(const SourceManager &SM);
   void emitMacroExpansionsAndCarets(SourceLocation Loc,
                                     DiagnosticsEngine::Level Level,
@@ -154,6 +161,10 @@
                                    PresumedLoc PLoc,
                                    const SourceManager &SM);
 
+  virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
+                                  StringRef ModuleName,
+                                  const SourceManager &SM);
+
   virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
                                           StringRef ModuleName,
                                           const SourceManager &SM);

Modified: cfe/trunk/include/clang/Frontend/TextDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/TextDiagnostic.h?rev=169042&r1=169041&r2=169042&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/TextDiagnostic.h (original)
+++ cfe/trunk/include/clang/Frontend/TextDiagnostic.h Fri Nov 30 15:58:49 2012
@@ -103,6 +103,10 @@
   virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
                                    const SourceManager &SM);
 
+  virtual void emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
+                                  StringRef ModuleName,
+                                  const SourceManager &SM);
+
   virtual void emitBuildingModuleLocation(SourceLocation Loc, PresumedLoc PLoc,
                                           StringRef ModuleName,
                                           const SourceManager &SM);

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=169042&r1=169041&r2=169042&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Fri Nov 30 15:58:49 2012
@@ -1546,6 +1546,10 @@
   /// \brief Read the source location entry with index ID.
   virtual bool ReadSLocEntry(int ID);
 
+  /// \brief Retrieve the module import location and module name for the
+  /// given source manager entry ID.
+  virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID);
+
   /// \brief Retrieve the global submodule ID given a module and its local ID
   /// number.
   serialization::SubmoduleID 

Modified: cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp?rev=169042&r1=169041&r2=169042&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp (original)
+++ cfe/trunk/lib/Frontend/DiagnosticRenderer.cpp Fri Nov 30 15:58:49 2012
@@ -132,7 +132,7 @@
   
     // First, if this diagnostic is not in the main file, print out the
     // "included from" lines.
-    emitIncludeStack(PLoc.getIncludeLoc(), Level, *SM);
+    emitIncludeStack(Loc, PLoc, Level, *SM);
   }
   
   // Next, emit the actual diagnostic message.
@@ -184,21 +184,30 @@
 /// repeated warnings occur within the same file. It also handles the logic
 /// of customizing the formatting and display of the include stack.
 ///
+/// \param Loc   The diagnostic location.
+/// \param PLoc  The presumed location of the diagnostic location.
 /// \param Level The diagnostic level of the message this stack pertains to.
-/// \param Loc   The include location of the current file (not the diagnostic
-///              location).
 void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
+                                          PresumedLoc PLoc,
                                           DiagnosticsEngine::Level Level,
                                           const SourceManager &SM) {
+  SourceLocation IncludeLoc = PLoc.getIncludeLoc();
+
   // Skip redundant include stacks altogether.
-  if (LastIncludeLoc == Loc)
+  if (LastIncludeLoc == IncludeLoc)
     return;
-  LastIncludeLoc = Loc;
+  
+  LastIncludeLoc = IncludeLoc;
   
   if (!DiagOpts->ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
     return;
-  
-  emitIncludeStackRecursively(Loc, SM);
+
+  if (IncludeLoc.isValid())
+    emitIncludeStackRecursively(IncludeLoc, SM);
+  else {
+    emitModuleBuildPath(SM);
+    emitImportStack(Loc, SM);
+  }
 }
 
 /// \brief Helper to recursivly walk up the include stack and print each layer
@@ -213,7 +222,17 @@
   PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
   if (PLoc.isInvalid())
     return;
-  
+
+  // If this source location was imported from a module, print the module
+  // import stack rather than the 
+  // FIXME: We want submodule granularity here.
+  std::pair<SourceLocation, StringRef> Imported = SM.getModuleImportLoc(Loc);
+  if (Imported.first.isValid()) {
+    // This location was imported by a module. Emit the module import stack.
+    emitImportStackRecursively(Imported.first, Imported.second, SM);
+    return;
+  }
+
   // Emit the other include frames first.
   emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM);
   
@@ -221,6 +240,41 @@
   emitIncludeLocation(Loc, PLoc, SM);
 }
 
+/// \brief Emit the module import stack associated with the current location.
+void DiagnosticRenderer::emitImportStack(SourceLocation Loc,
+                                         const SourceManager &SM) {
+  if (Loc.isInvalid()) {
+    emitModuleBuildPath(SM);
+    return;
+  }
+
+  std::pair<SourceLocation, StringRef> NextImportLoc
+    = SM.getModuleImportLoc(Loc);
+  emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
+}
+
+/// \brief Helper to recursivly walk up the import stack and print each layer
+/// on the way back down.
+void DiagnosticRenderer::emitImportStackRecursively(SourceLocation Loc,
+                                                    StringRef ModuleName,
+                                                    const SourceManager &SM) {
+  if (Loc.isInvalid()) {
+    return;
+  }
+
+  PresumedLoc PLoc = SM.getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc);
+  if (PLoc.isInvalid())
+    return;
+
+  // Emit the other import frames first.
+  std::pair<SourceLocation, StringRef> NextImportLoc
+    = SM.getModuleImportLoc(Loc);
+  emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second, SM);
+
+  // Emit the inclusion text/note.
+  emitImportLocation(Loc, PLoc, ModuleName, SM);
+}
+
 /// \brief Emit the module build path, for cases where a module is (re-)built
 /// on demand.
 void DiagnosticRenderer::emitModuleBuildPath(const SourceManager &SM) {
@@ -407,6 +461,18 @@
   emitNote(Loc, Message.str(), &SM);
 }
 
+void DiagnosticNoteRenderer::emitImportLocation(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 << "in module '" << ModuleName << "' imported from "
+          << PLoc.getFilename() << ':' << PLoc.getLine() << ":";
+  emitNote(Loc, Message.str(), &SM);
+}
+
 void
 DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc,
                                                    PresumedLoc PLoc,

Modified: cfe/trunk/lib/Frontend/TextDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/TextDiagnostic.cpp?rev=169042&r1=169041&r2=169042&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/TextDiagnostic.cpp (original)
+++ cfe/trunk/lib/Frontend/TextDiagnostic.cpp Fri Nov 30 15:58:49 2012
@@ -884,6 +884,16 @@
     OS << "In included file:\n"; 
 }
 
+void TextDiagnostic::emitImportLocation(SourceLocation Loc, PresumedLoc PLoc,
+                                        StringRef ModuleName,
+                                        const SourceManager &SM) {
+  if (DiagOpts->ShowLocation)
+    OS << "In module '" << ModuleName << "' imported from "
+       << PLoc.getFilename() << ':' << PLoc.getLine() << ":\n";
+  else
+    OS << "In module " << ModuleName << "':\n";
+}
+
 void TextDiagnostic::emitBuildingModuleLocation(SourceLocation Loc,
                                                 PresumedLoc PLoc,
                                                 StringRef ModuleName,

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=169042&r1=169041&r2=169042&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Nov 30 15:58:49 2012
@@ -1000,6 +1000,25 @@
   return false;
 }
 
+std::pair<SourceLocation, StringRef> ASTReader::getModuleImportLoc(int ID) {
+  if (ID == 0)
+    return std::make_pair(SourceLocation(), "");
+
+  if (unsigned(-ID) - 2 >= getTotalNumSLocs() || ID > 0) {
+    Error("source location entry ID out-of-range for AST file");
+    return std::make_pair(SourceLocation(), "");
+  }
+
+  // Find which module file this entry lands in.
+  ModuleFile *M = GlobalSLocEntryMap.find(-ID)->second;
+  if (M->Kind != MK_Module)
+    return std::make_pair(SourceLocation(), "");
+
+  // FIXME: Can we map this down to a particular submodule? That would be
+  // ideal.
+  return std::make_pair(M->ImportLoc, llvm::sys::path::stem(M->FileName));
+}
+
 /// \brief Find the location where the module F is imported.
 SourceLocation ASTReader::getImportLocation(ModuleFile *F) {
   if (F->ImportLoc.isValid())

Modified: cfe/trunk/test/Modules/build-fail-notes.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/build-fail-notes.m?rev=169042&r1=169041&r2=169042&view=diff
==============================================================================
--- cfe/trunk/test/Modules/build-fail-notes.m (original)
+++ cfe/trunk/test/Modules/build-fail-notes.m Fri Nov 30 15:58:49 2012
@@ -10,3 +10,10 @@
 // CHECK: fatal error: could not build module 'Module'
 // CHECK: fatal error: could not build module 'DependsOnModule'
 // CHECK-NOT: error:
+
+// RUN: %clang_cc1 -fmodule-cache-path %t -fmodules -F %S/Inputs %s -fdiagnostics-show-note-include-stack 2>&1 | FileCheck -check-prefix=CHECK-REDEF %s
+extern int Module;
+
+// CHECK-REDEF: In module 'DependsOnModule' imported from
+// CHECK-REDEF: In module 'Module' imported from
+// CHECK-REDEF: Module.h:15:12: note: previous definition is here





More information about the cfe-commits mailing list