]> granicus.if.org Git - clang/commitdiff
Fix an assertion hit when the serialized diagnostics writer receive a diagnostic
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 10 May 2012 05:03:45 +0000 (05:03 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 10 May 2012 05:03:45 +0000 (05:03 +0000)
from the frontend when the location is invalid and the SourceManager null.

Instead of keeping the SourceManager object in DiagnosticRenderer, propagate it
to the calls accordingly (as reference when it is expected to not be null, or pointer
when it may be null).
This effectively makes DiagnosticRenderer not tied to a specific SourceManager,
removing a hack from TextDiagnosticPrinter.

rdar://11386874

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

include/clang/Frontend/DiagnosticRenderer.h
include/clang/Frontend/TextDiagnostic.h
include/clang/Frontend/TextDiagnosticPrinter.h
lib/Frontend/DiagnosticRenderer.cpp
lib/Frontend/SerializedDiagnosticPrinter.cpp
lib/Frontend/TextDiagnostic.cpp
lib/Frontend/TextDiagnosticPrinter.cpp
test/Misc/serialized-diags-frontend.c [new file with mode: 0644]
tools/libclang/CIndexDiagnostic.cpp

index 5ad88a8a5364701a51ac5f97b9716b6acfd18f4e..09d7ecb51d80a30420290b7e6b94d4db02285b9a 100644 (file)
@@ -43,7 +43,6 @@ typedef llvm::PointerUnion<const Diagnostic *,
 /// class.
 class DiagnosticRenderer {
 protected:
-  const SourceManager &SM;
   const LangOptions &LangOpts;
   const DiagnosticOptions &DiagOpts;
   
@@ -66,8 +65,7 @@ protected:
   /// which change the amount of information displayed.
   DiagnosticsEngine::Level LastLevel;
 
-  DiagnosticRenderer(const SourceManager &SM,
-                     const LangOptions &LangOpts,
+  DiagnosticRenderer(const LangOptions &LangOpts,
                      const DiagnosticOptions &DiagOpts);
   
   virtual ~DiagnosticRenderer();
@@ -76,20 +74,24 @@ protected:
                                      DiagnosticsEngine::Level Level,
                                      StringRef Message,
                                      ArrayRef<CharSourceRange> Ranges,
+                                     const SourceManager *SM,
                                      DiagOrStoredDiag Info) = 0;
   
   virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
                                  DiagnosticsEngine::Level Level,
-                                 ArrayRef<CharSourceRange> Ranges) = 0;
+                                 ArrayRef<CharSourceRange> Ranges,
+                                 const SourceManager &SM) = 0;
   
   virtual void emitBasicNote(StringRef Message) = 0;
   
   virtual void emitCodeContext(SourceLocation Loc,
                                DiagnosticsEngine::Level Level,
                                SmallVectorImpl<CharSourceRange>& Ranges,
-                               ArrayRef<FixItHint> Hints) = 0;
+                               ArrayRef<FixItHint> Hints,
+                               const SourceManager &SM) = 0;
   
-  virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc) = 0;
+  virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
+                                   const SourceManager &SM) = 0;
   
   virtual void beginDiagnostic(DiagOrStoredDiag D,
                                DiagnosticsEngine::Level Level) {}
@@ -98,12 +100,14 @@ protected:
 
   
 private:
-  void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level);
-  void emitIncludeStackRecursively(SourceLocation Loc);
+  void emitIncludeStack(SourceLocation Loc, DiagnosticsEngine::Level Level,
+                        const SourceManager &SM);
+  void emitIncludeStackRecursively(SourceLocation Loc, const SourceManager &SM);
   void emitMacroExpansionsAndCarets(SourceLocation Loc,
                                     DiagnosticsEngine::Level Level,
                                     SmallVectorImpl<CharSourceRange>& Ranges,
                                     ArrayRef<FixItHint> Hints,
+                                    const SourceManager &SM,
                                     unsigned &MacroDepth,
                                     unsigned OnMacroInst = 0);
 public:
@@ -119,9 +123,12 @@ public:
   /// \param Message The diagnostic message to emit.
   /// \param Ranges The underlined ranges for this code snippet.
   /// \param FixItHints The FixIt hints active for this diagnostic.
+  /// \param SM The SourceManager; will be null if the diagnostic came from the
+  ///        frontend, thus \param Loc will be invalid.
   void emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level,
                       StringRef Message, ArrayRef<CharSourceRange> Ranges,
                       ArrayRef<FixItHint> FixItHints,
+                      const SourceManager *SM,
                       DiagOrStoredDiag D = (Diagnostic *)0);
 
   void emitStoredDiagnostic(StoredDiagnostic &Diag);
@@ -131,19 +138,20 @@ public:
 /// notes.  It is up to subclasses to further define the behavior.
 class DiagnosticNoteRenderer : public DiagnosticRenderer {
 public:
-  DiagnosticNoteRenderer(const SourceManager &SM,
-                         const LangOptions &LangOpts,
+  DiagnosticNoteRenderer(const LangOptions &LangOpts,
                          const DiagnosticOptions &DiagOpts)
-    : DiagnosticRenderer(SM, LangOpts, DiagOpts) {}
+    : DiagnosticRenderer(LangOpts, DiagOpts) {}
   
   virtual ~DiagnosticNoteRenderer();
   
   virtual void emitBasicNote(StringRef Message);
     
   virtual void emitIncludeLocation(SourceLocation Loc,
-                                   PresumedLoc PLoc);
+                                   PresumedLoc PLoc,
+                                   const SourceManager &SM);
   
-  virtual void emitNote(SourceLocation Loc, StringRef Message) = 0;
+  virtual void emitNote(SourceLocation Loc, StringRef Message,
+                        const SourceManager *SM) = 0;
 };
 } // end clang namespace
 #endif
index 314003bce2c521ce41367df5f4265ad08f22c480..bc84a761bfcbade27e740f625106e8bce98c71c1 100644 (file)
@@ -39,7 +39,6 @@ class TextDiagnostic : public DiagnosticRenderer {
 
 public:
   TextDiagnostic(raw_ostream &OS,
-                 const SourceManager &SM,
                  const LangOptions &LangOpts,
                  const DiagnosticOptions &DiagOpts);
 
@@ -83,39 +82,46 @@ protected:
                                      DiagnosticsEngine::Level Level,
                                      StringRef Message,
                                      ArrayRef<CharSourceRange> Ranges,
+                                     const SourceManager *SM,
                                      DiagOrStoredDiag D);
 
   virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
                                  DiagnosticsEngine::Level Level,
-                                 ArrayRef<CharSourceRange> Ranges);
+                                 ArrayRef<CharSourceRange> Ranges,
+                                 const SourceManager &SM);
   
   virtual void emitCodeContext(SourceLocation Loc,
                                DiagnosticsEngine::Level Level,
                                SmallVectorImpl<CharSourceRange>& Ranges,
-                               ArrayRef<FixItHint> Hints) {
-    emitSnippetAndCaret(Loc, Level, Ranges, Hints);
+                               ArrayRef<FixItHint> Hints,
+                               const SourceManager &SM) {
+    emitSnippetAndCaret(Loc, Level, Ranges, Hints, SM);
   }
   
   virtual void emitBasicNote(StringRef Message);
   
-  virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc);
+  virtual void emitIncludeLocation(SourceLocation Loc, PresumedLoc PLoc,
+                                   const SourceManager &SM);
 
 private:
   void emitSnippetAndCaret(SourceLocation Loc, DiagnosticsEngine::Level Level,
                            SmallVectorImpl<CharSourceRange>& Ranges,
-                           ArrayRef<FixItHint> Hints);
+                           ArrayRef<FixItHint> Hints,
+                           const SourceManager &SM);
 
   void emitSnippet(StringRef SourceLine);
 
   void highlightRange(const CharSourceRange &R,
                       unsigned LineNo, FileID FID,
                       const SourceColumnMap &map,
-                      std::string &CaretLine);
+                      std::string &CaretLine,
+                      const SourceManager &SM);
 
   std::string buildFixItInsertionLine(unsigned LineNo,
                                       const SourceColumnMap &map,
-                                      ArrayRef<FixItHint> Hints);
-  void emitParseableFixits(ArrayRef<FixItHint> Hints);
+                                      ArrayRef<FixItHint> Hints,
+                                      const SourceManager &SM);
+  void emitParseableFixits(ArrayRef<FixItHint> Hints, const SourceManager &SM);
 };
 
 } // end namespace clang
index 9b6ac24cca7e62080b478992302aa0105fdf8ba6..23cf5211cd016dc89268a784d87854526e92d9a3 100644 (file)
@@ -26,9 +26,7 @@ class TextDiagnostic;
 
 class TextDiagnosticPrinter : public DiagnosticConsumer {
   raw_ostream &OS;
-  const LangOptions *LangOpts;
   const DiagnosticOptions *DiagOpts;
-  const SourceManager *SM;
 
   /// \brief Handle to the currently active text diagnostic emitter.
   OwningPtr<TextDiagnostic> TextDiag;
index 6c3bb1d6953453a6ffe49fd81ad27b40e3665a96..7249943d3aa6592cde67b019f34c568c46f70773 100644 (file)
@@ -123,10 +123,9 @@ static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM,
   return SM.getPresumedLoc(Loc);
 }
 
-DiagnosticRenderer::DiagnosticRenderer(const SourceManager &SM,
-                                       const LangOptions &LangOpts,
+DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts,
                                        const DiagnosticOptions &DiagOpts)
-: SM(SM), LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
+: LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {}
 
 DiagnosticRenderer::~DiagnosticRenderer() {}
 
@@ -184,18 +183,23 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
                                         StringRef Message,
                                         ArrayRef<CharSourceRange> Ranges,
                                         ArrayRef<FixItHint> FixItHints,
+                                        const SourceManager *SM,
                                         DiagOrStoredDiag D) {
+  assert(SM || Loc.isInvalid());
   
   beginDiagnostic(D, Level);
   
-  PresumedLoc PLoc = getDiagnosticPresumedLoc(SM, Loc);
+  PresumedLoc PLoc;
+  if (Loc.isValid()) {
+    PLoc = getDiagnosticPresumedLoc(*SM, Loc);
   
-  // First, if this diagnostic is not in the main file, print out the
-  // "included from" lines.
-  emitIncludeStack(PLoc.getIncludeLoc(), Level);
+    // First, if this diagnostic is not in the main file, print out the
+    // "included from" lines.
+    emitIncludeStack(PLoc.getIncludeLoc(), Level, *SM);
+  }
   
   // Next, emit the actual diagnostic message.
-  emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, D);
+  emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D);
   
   // Only recurse if we have a valid location.
   if (Loc.isValid()) {
@@ -205,7 +209,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
     
     llvm::SmallVector<FixItHint, 8> MergedFixits;
     if (!FixItHints.empty()) {
-      mergeFixits(FixItHints, SM, LangOpts, MergedFixits);
+      mergeFixits(FixItHints, *SM, LangOpts, MergedFixits);
       FixItHints = MergedFixits;
     }
 
@@ -216,7 +220,7 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
         MutableRanges.push_back(I->RemoveRange);
     
     unsigned MacroDepth = 0;
-    emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints,
+    emitMacroExpansionsAndCarets(Loc, Level, MutableRanges, FixItHints, *SM,
                                  MacroDepth);
   }
   
@@ -230,6 +234,8 @@ void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc,
 void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
   emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(),
                  Diag.getRanges(), Diag.getFixIts(),
+                 Diag.getLocation().isValid() ? &Diag.getLocation().getManager()
+                                              : 0,
                  &Diag);
 }
 
@@ -245,7 +251,8 @@ void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
 /// \param Loc   The include location of the current file (not the diagnostic
 ///              location).
 void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
-                                          DiagnosticsEngine::Level Level) {
+                                          DiagnosticsEngine::Level Level,
+                                          const SourceManager &SM) {
   // Skip redundant include stacks altogether.
   if (LastIncludeLoc == Loc)
     return;
@@ -254,12 +261,13 @@ void DiagnosticRenderer::emitIncludeStack(SourceLocation Loc,
   if (!DiagOpts.ShowNoteIncludeStack && Level == DiagnosticsEngine::Note)
     return;
   
-  emitIncludeStackRecursively(Loc);
+  emitIncludeStackRecursively(Loc, SM);
 }
 
 /// \brief Helper to recursivly walk up the include stack and print each layer
 /// on the way back down.
-void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) {
+void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc,
+                                                     const SourceManager &SM) {
   if (Loc.isInvalid())
     return;
   
@@ -268,10 +276,10 @@ void DiagnosticRenderer::emitIncludeStackRecursively(SourceLocation Loc) {
     return;
   
   // Emit the other include frames first.
-  emitIncludeStackRecursively(PLoc.getIncludeLoc());
+  emitIncludeStackRecursively(PLoc.getIncludeLoc(), SM);
   
   // Emit the inclusion text/note.
-  emitIncludeLocation(Loc, PLoc);
+  emitIncludeLocation(Loc, PLoc, SM);
 }
 
 /// \brief Recursively emit notes for each macro expansion and caret
@@ -292,6 +300,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
        DiagnosticsEngine::Level Level,
        SmallVectorImpl<CharSourceRange>& Ranges,
        ArrayRef<FixItHint> Hints,
+       const SourceManager &SM,
        unsigned &MacroDepth,
        unsigned OnMacroInst)
 {
@@ -302,7 +311,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
   if (Loc.isFileID()) {
     assert(MacroDepth == 0 && "We shouldn't hit a leaf node twice!");
     MacroDepth = OnMacroInst;
-    emitCodeContext(Loc, Level, Ranges, Hints);
+    emitCodeContext(Loc, Level, Ranges, Hints, SM);
     return;
   }
   // Otherwise recurse through each macro expansion layer.
@@ -314,7 +323,7 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
   SourceLocation OneLevelUp = getImmediateMacroCallerLoc(SM, Loc);
   
   // FIXME: Map ranges?
-  emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, MacroDepth,
+  emitMacroExpansionsAndCarets(OneLevelUp, Level, Ranges, Hints, SM, MacroDepth,
                                OnMacroInst + 1);
   
   // Save the original location so we can find the spelling of the macro call.
@@ -365,22 +374,23 @@ void DiagnosticRenderer::emitMacroExpansionsAndCarets(
           << getImmediateMacroName(MacroLoc, SM, LangOpts) << "'";
   emitDiagnostic(SM.getSpellingLoc(Loc), DiagnosticsEngine::Note,
                  Message.str(),
-                 Ranges, ArrayRef<FixItHint>());
+                 Ranges, ArrayRef<FixItHint>(), &SM);
 }
 
 DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {}
 
 void DiagnosticNoteRenderer::emitIncludeLocation(SourceLocation Loc,
-                                                 PresumedLoc PLoc) {
+                                                 PresumedLoc PLoc,
+                                                 const SourceManager &SM) {
   // Generate a note indicating the include location.
   SmallString<200> MessageStorage;
   llvm::raw_svector_ostream Message(MessageStorage);
   Message << "in file included from " << PLoc.getFilename() << ':'
           << PLoc.getLine() << ":";
-  emitNote(Loc, Message.str());
+  emitNote(Loc, Message.str(), &SM);
 }
 
 void DiagnosticNoteRenderer::emitBasicNote(StringRef Message) {
-  emitNote(SourceLocation(), Message);  
+  emitNote(SourceLocation(), Message, 0);  
 }
 
index 7bf8742a8040748b03e52ae0f30480ba010b69b9..a20f30d6be837118a4b1402dd03415c2e4795793 100644 (file)
@@ -53,10 +53,9 @@ class SDiagsRenderer : public DiagnosticNoteRenderer {
   RecordData &Record;
 public:
   SDiagsRenderer(SDiagsWriter &Writer, RecordData &Record,
-                 const SourceManager &SM,
                  const LangOptions &LangOpts,
                  const DiagnosticOptions &DiagOpts)
-    : DiagnosticNoteRenderer(SM, LangOpts, DiagOpts),
+    : DiagnosticNoteRenderer(LangOpts, DiagOpts),
       Writer(Writer), Record(Record){}
 
   virtual ~SDiagsRenderer() {}
@@ -67,18 +66,21 @@ protected:
                                      DiagnosticsEngine::Level Level,
                                      StringRef Message,
                                      ArrayRef<CharSourceRange> Ranges,
+                                     const SourceManager *SM,
                                      DiagOrStoredDiag D);
   
   virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
                                  DiagnosticsEngine::Level Level,
-                                 ArrayRef<CharSourceRange> Ranges) {}
+                                 ArrayRef<CharSourceRange> Ranges,
+                                 const SourceManager &SM) {}
   
-  void emitNote(SourceLocation Loc, StringRef Message);
+  void emitNote(SourceLocation Loc, StringRef Message, const SourceManager *SM);
   
   virtual void emitCodeContext(SourceLocation Loc,
                                DiagnosticsEngine::Level Level,
                                SmallVectorImpl<CharSourceRange>& Ranges,
-                               ArrayRef<FixItHint> Hints);
+                               ArrayRef<FixItHint> Hints,
+                               const SourceManager &SM);
   
   virtual void beginDiagnostic(DiagOrStoredDiag D,
                                DiagnosticsEngine::Level Level);
@@ -137,15 +139,16 @@ private:
   unsigned getEmitFile(const char *Filename);
 
   /// \brief Add SourceLocation information the specified record.  
-  void AddLocToRecord(SourceLocation Loc, const SourceManager &SM,
+  void AddLocToRecord(SourceLocation Loc, const SourceManager *SM,
                       PresumedLoc PLoc, RecordDataImpl &Record,
                       unsigned TokSize = 0);
 
   /// \brief Add SourceLocation information the specified record.
   void AddLocToRecord(SourceLocation Loc, RecordDataImpl &Record,
-                      const SourceManager &SM,
+                      const SourceManager *SM,
                       unsigned TokSize = 0) {
-    AddLocToRecord(Loc, SM, SM.getPresumedLoc(Loc), Record, TokSize);
+    AddLocToRecord(Loc, SM, SM ? SM->getPresumedLoc(Loc) : PresumedLoc(),
+                   Record, TokSize);
   }
 
   /// \brief Add CharSourceRange information the specified record.
@@ -241,7 +244,7 @@ static void EmitRecordID(unsigned ID, const char *Name,
 }
 
 void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
-                                  const SourceManager &SM,
+                                  const SourceManager *SM,
                                   PresumedLoc PLoc,
                                   RecordDataImpl &Record,
                                   unsigned TokSize) {
@@ -257,19 +260,19 @@ void SDiagsWriter::AddLocToRecord(SourceLocation Loc,
   Record.push_back(getEmitFile(PLoc.getFilename()));
   Record.push_back(PLoc.getLine());
   Record.push_back(PLoc.getColumn()+TokSize);
-  Record.push_back(SM.getFileOffset(Loc));
+  Record.push_back(SM->getFileOffset(Loc));
 }
 
 void SDiagsWriter::AddCharSourceRangeToRecord(CharSourceRange Range,
                                               RecordDataImpl &Record,
                                               const SourceManager &SM) {
-  AddLocToRecord(Range.getBegin(), Record, SM);
+  AddLocToRecord(Range.getBegin(), Record, &SM);
   unsigned TokSize = 0;
   if (Range.isTokenRange())
     TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
                                         SM, *LangOpts);
   
-  AddLocToRecord(Range.getEnd(), Record, SM, TokSize);
+  AddLocToRecord(Range.getEnd(), Record, &SM, TokSize);
 }
 
 unsigned SDiagsWriter::getEmitFile(const char *FileName){
@@ -484,13 +487,15 @@ void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
   diagBuf.clear();   
   Info.FormatDiagnostic(diagBuf);
 
-  SourceManager &SM = Info.getSourceManager();
-  SDiagsRenderer Renderer(*this, Record, SM, *LangOpts, DiagOpts);
+  const SourceManager *
+    SM = Info.hasSourceManager() ? &Info.getSourceManager() : 0;
+  SDiagsRenderer Renderer(*this, Record, *LangOpts, DiagOpts);
   Renderer.emitDiagnostic(Info.getLocation(), DiagLevel,
                           diagBuf.str(),
                           Info.getRanges(),
                           llvm::makeArrayRef(Info.getFixItHints(),
                                              Info.getNumFixItHints()),
+                          SM,
                           &Info);
 }
 
@@ -500,6 +505,7 @@ SDiagsRenderer::emitDiagnosticMessage(SourceLocation Loc,
                                       DiagnosticsEngine::Level Level,
                                       StringRef Message,
                                       ArrayRef<clang::CharSourceRange> Ranges,
+                                      const SourceManager *SM,
                                       DiagOrStoredDiag D) {
   // Emit the RECORD_DIAG record.
   Writer.Record.clear();
@@ -539,7 +545,8 @@ void SDiagsRenderer::endDiagnostic(DiagOrStoredDiag D,
 void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
                                      DiagnosticsEngine::Level Level,
                                      SmallVectorImpl<CharSourceRange> &Ranges,
-                                     ArrayRef<FixItHint> Hints) {  
+                                     ArrayRef<FixItHint> Hints,
+                                     const SourceManager &SM) {  
   // Emit Source Ranges.
   for (ArrayRef<CharSourceRange>::iterator it=Ranges.begin(), ei=Ranges.end();
        it != ei; ++it) {
@@ -562,7 +569,8 @@ void SDiagsRenderer::emitCodeContext(SourceLocation Loc,
   }
 }
 
-void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message) {
+void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
+                              const SourceManager *SM) {
   Writer.Stream.EnterSubblock(BLOCK_DIAG, 4);
   RecordData Record;
   Record.push_back(RECORD_DIAG);
index bed82e0f0bc77fa6d631cdf7363a22413da5b35c..454018b29693ea59e7baa27e97ecb8281ff8cf21 100644 (file)
@@ -602,10 +602,9 @@ static bool printWordWrapped(raw_ostream &OS, StringRef Str,
 }
 
 TextDiagnostic::TextDiagnostic(raw_ostream &OS,
-                               const SourceManager &SM,
                                const LangOptions &LangOpts,
                                const DiagnosticOptions &DiagOpts)
-  : DiagnosticRenderer(SM, LangOpts, DiagOpts), OS(OS) {}
+  : DiagnosticRenderer(LangOpts, DiagOpts), OS(OS) {}
 
 TextDiagnostic::~TextDiagnostic() {}
 
@@ -615,11 +614,13 @@ TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc,
                                       DiagnosticsEngine::Level Level,
                                       StringRef Message,
                                       ArrayRef<clang::CharSourceRange> Ranges,
+                                      const SourceManager *SM,
                                       DiagOrStoredDiag D) {
   uint64_t StartOfLocationInfo = OS.tell();
 
   // Emit the location of this particular diagnostic.
-  emitDiagnosticLoc(Loc, PLoc, Level, Ranges);
+  if (Loc.isValid())
+    emitDiagnosticLoc(Loc, PLoc, Level, Ranges, *SM);
   
   if (DiagOpts.ShowColors)
     OS.resetColor();
@@ -693,7 +694,8 @@ TextDiagnostic::printDiagnosticMessage(raw_ostream &OS,
 /// ranges necessary.
 void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
                                        DiagnosticsEngine::Level Level,
-                                       ArrayRef<CharSourceRange> Ranges) {
+                                       ArrayRef<CharSourceRange> Ranges,
+                                       const SourceManager &SM) {
   if (PLoc.isInvalid()) {
     // At least print the file name if available:
     FileID FID = SM.getFileID(Loc);
@@ -799,7 +801,8 @@ void TextDiagnostic::emitBasicNote(StringRef Message) {
 }
 
 void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
-                                         PresumedLoc PLoc) {
+                                         PresumedLoc PLoc,
+                                         const SourceManager &SM) {
   if (DiagOpts.ShowLocation)
     OS << "In file included from " << PLoc.getFilename() << ':'
        << PLoc.getLine() << ":\n";
@@ -817,7 +820,8 @@ void TextDiagnostic::emitIncludeLocation(SourceLocation Loc,
 void TextDiagnostic::emitSnippetAndCaret(
     SourceLocation Loc, DiagnosticsEngine::Level Level,
     SmallVectorImpl<CharSourceRange>& Ranges,
-    ArrayRef<FixItHint> Hints) {
+    ArrayRef<FixItHint> Hints,
+    const SourceManager &SM) {
   assert(!Loc.isInvalid() && "must have a valid source location here");
   assert(Loc.isFileID() && "must have a file location here");
 
@@ -878,7 +882,7 @@ void TextDiagnostic::emitSnippetAndCaret(
   for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
                                                   E = Ranges.end();
        I != E; ++I)
-    highlightRange(*I, LineNo, FID, sourceColMap, CaretLine);
+    highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM);
 
   // Next, insert the caret itself.
   ColNo = sourceColMap.byteToColumn(ColNo-1);
@@ -888,7 +892,7 @@ void TextDiagnostic::emitSnippetAndCaret(
 
   std::string FixItInsertionLine = buildFixItInsertionLine(LineNo,
                                                            sourceColMap,
-                                                           Hints);
+                                                           Hints, SM);
 
   // If the source line is too long for our terminal, select only the
   // "interesting" source region within that line.
@@ -931,7 +935,7 @@ void TextDiagnostic::emitSnippetAndCaret(
   }
 
   // Print out any parseable fixit information requested by the options.
-  emitParseableFixits(Hints);
+  emitParseableFixits(Hints, SM);
 }
 
 void TextDiagnostic::emitSnippet(StringRef line) {
@@ -974,7 +978,8 @@ void TextDiagnostic::emitSnippet(StringRef line) {
 void TextDiagnostic::highlightRange(const CharSourceRange &R,
                                     unsigned LineNo, FileID FID,
                                     const SourceColumnMap &map,
-                                    std::string &CaretLine) {
+                                    std::string &CaretLine,
+                                    const SourceManager &SM) {
   if (!R.isValid()) return;
 
   SourceLocation Begin = SM.getExpansionLoc(R.getBegin());
@@ -1059,7 +1064,8 @@ void TextDiagnostic::highlightRange(const CharSourceRange &R,
 std::string TextDiagnostic::buildFixItInsertionLine(
   unsigned LineNo,
   const SourceColumnMap &map,
-  ArrayRef<FixItHint> Hints) {
+  ArrayRef<FixItHint> Hints,
+  const SourceManager &SM) {
 
   std::string FixItInsertionLine;
   if (Hints.empty() || !DiagOpts.ShowFixits)
@@ -1114,7 +1120,8 @@ std::string TextDiagnostic::buildFixItInsertionLine(
   return FixItInsertionLine;
 }
 
-void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints) {
+void TextDiagnostic::emitParseableFixits(ArrayRef<FixItHint> Hints,
+                                         const SourceManager &SM) {
   if (!DiagOpts.ShowParseableFixits)
     return;
 
index 6445a0cc79bb7125b493db2bac32e09422855cab..d07917f2349d9cde1acbe8aa9aead6a4e7011f28 100644 (file)
@@ -27,7 +27,7 @@ using namespace clang;
 TextDiagnosticPrinter::TextDiagnosticPrinter(raw_ostream &os,
                                              const DiagnosticOptions &diags,
                                              bool _OwnsOutputStream)
-  : OS(os), LangOpts(0), DiagOpts(&diags), SM(0),
+  : OS(os), DiagOpts(&diags),
     OwnsOutputStream(_OwnsOutputStream) {
 }
 
@@ -38,11 +38,11 @@ TextDiagnosticPrinter::~TextDiagnosticPrinter() {
 
 void TextDiagnosticPrinter::BeginSourceFile(const LangOptions &LO,
                                             const Preprocessor *PP) {
-  LangOpts = &LO;
+  // Build the TextDiagnostic utility.
+  TextDiag.reset(new TextDiagnostic(OS, LO, *DiagOpts));
 }
 
 void TextDiagnosticPrinter::EndSourceFile() {
-  LangOpts = 0;
   TextDiag.reset(0);
 }
 
@@ -152,22 +152,16 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
   }
 
   // Assert that the rest of our infrastructure is setup properly.
-  assert(LangOpts && "Unexpected diagnostic outside source file processing");
   assert(DiagOpts && "Unexpected diagnostic without options set");
   assert(Info.hasSourceManager() &&
          "Unexpected diagnostic with no source manager");
-
-  // Rebuild the TextDiagnostic utility if missing or the source manager has
-  // changed.
-  if (!TextDiag || SM != &Info.getSourceManager()) {
-    SM = &Info.getSourceManager();
-    TextDiag.reset(new TextDiagnostic(OS, *SM, *LangOpts, *DiagOpts));
-  }
+  assert(TextDiag && "Unexpected diagnostic outside source file processing");
 
   TextDiag->emitDiagnostic(Info.getLocation(), Level, DiagMessageStream.str(),
                            Info.getRanges(),
                            llvm::makeArrayRef(Info.getFixItHints(),
-                                              Info.getNumFixItHints()));
+                                              Info.getNumFixItHints()),
+                           &Info.getSourceManager());
 
   OS.flush();
 }
diff --git a/test/Misc/serialized-diags-frontend.c b/test/Misc/serialized-diags-frontend.c
new file mode 100644 (file)
index 0000000..453ed14
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: rm -f %t
+// RUN: %clang -fsyntax-only %s -Wblahblah --serialize-diagnostics %t > /dev/null 2>&1 || true
+// RUN: c-index-test -read-diagnostics %t 2>&1 | FileCheck %s
+
+// This test case tests that we can handle frontend diagnostics.
+
+// CHECK: warning: unknown warning option '-Wblahblah'
+// CHECK: Number of diagnostics: 1
index 8fbe3d8c3d38240616753f74f9987725c6040cca..14722e01849150f414d56918a47b711e7c1812fe 100644 (file)
@@ -86,11 +86,10 @@ public:
     
 class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
 public:  
-  CXDiagnosticRenderer(const SourceManager &SM,
-                       const LangOptions &LangOpts,
+  CXDiagnosticRenderer(const LangOptions &LangOpts,
                        const DiagnosticOptions &DiagOpts,
                        CXDiagnosticSetImpl *mainSet)
-  : DiagnosticNoteRenderer(SM, LangOpts, DiagOpts),
+  : DiagnosticNoteRenderer(LangOpts, DiagOpts),
     CurrentSet(mainSet), MainSet(mainSet) {}
   
   virtual ~CXDiagnosticRenderer() {}
@@ -116,26 +115,38 @@ public:
                                      DiagnosticsEngine::Level Level,
                                      StringRef Message,
                                      ArrayRef<CharSourceRange> Ranges,
+                                     const SourceManager *SM,
                                      DiagOrStoredDiag D) {
     if (!D.isNull())
       return;
     
-    CXSourceLocation L = translateSourceLocation(SM, LangOpts, Loc);
+    CXSourceLocation L;
+    if (SM)
+      L = translateSourceLocation(*SM, LangOpts, Loc);
+    else
+      L = clang_getNullLocation();
     CXDiagnosticImpl *CD = new CXDiagnosticCustomNoteImpl(Message, L);
     CurrentSet->appendDiagnostic(CD);
   }
   
   virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
                                  DiagnosticsEngine::Level Level,
-                                 ArrayRef<CharSourceRange> Ranges) {}
+                                 ArrayRef<CharSourceRange> Ranges,
+                                 const SourceManager &SM) {}
 
   virtual void emitCodeContext(SourceLocation Loc,
                                DiagnosticsEngine::Level Level,
                                SmallVectorImpl<CharSourceRange>& Ranges,
-                               ArrayRef<FixItHint> Hints) {}
+                               ArrayRef<FixItHint> Hints,
+                               const SourceManager &SM) {}
   
-  virtual void emitNote(SourceLocation Loc, StringRef Message) {
-    CXSourceLocation L = translateSourceLocation(SM, LangOpts, Loc);
+  virtual void emitNote(SourceLocation Loc, StringRef Message,
+                        const SourceManager *SM) {
+    CXSourceLocation L;
+    if (SM)
+      L = translateSourceLocation(*SM, LangOpts, Loc);
+    else
+      L = clang_getNullLocation();
     CurrentSet->appendDiagnostic(new CXDiagnosticCustomNoteImpl(Message,
                                                                 L));
   }
@@ -181,8 +192,7 @@ CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
     CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
     TU->Diagnostics = Set;
     DiagnosticOptions DOpts;
-    CXDiagnosticRenderer Renderer(AU->getSourceManager(),
-                                  AU->getASTContext().getLangOpts(),
+    CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
                                   DOpts, Set);
     
     for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),