]> granicus.if.org Git - clang/commitdiff
Frontend: Continue flushing out LogDiagnosticPrinter.
authorDaniel Dunbar <daniel@zuster.org>
Thu, 7 Apr 2011 18:37:34 +0000 (18:37 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Thu, 7 Apr 2011 18:37:34 +0000 (18:37 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129091 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Frontend/LogDiagnosticPrinter.h
lib/Frontend/LogDiagnosticPrinter.cpp

index b79fc95eb3acd8d1c1cf679ead55d9c76b8bf13f..8ac6093318d260ec63da78577735a97130f5ab51 100644 (file)
 
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/SmallVector.h"
 
 namespace clang {
 class DiagnosticOptions;
 class LangOptions;
 
 class LogDiagnosticPrinter : public DiagnosticClient {
+  struct DiagEntry {
+    /// The primary message line of the diagnostic.
+    std::string Message;
+  
+    /// The source file name, if available.
+    std::string Filename;
+  
+    /// The source file line number, if available.
+    unsigned Line;
+  
+    /// The source file column number, if available.
+    unsigned Column;
+  
+    /// The ID of the diagnostic.
+    unsigned DiagnosticID;
+  
+    /// The level of the diagnostic.
+    Diagnostic::Level DiagnosticLevel;
+  };
+  
   llvm::raw_ostream &OS;
   const LangOptions *LangOpts;
   const DiagnosticOptions *DiagOpts;
@@ -26,6 +47,8 @@ class LogDiagnosticPrinter : public DiagnosticClient {
   FullSourceLoc LastLoc;
   unsigned OwnsOutputStream : 1;
 
+  llvm::SmallVector<DiagEntry, 8> Entries;
+
 public:
   LogDiagnosticPrinter(llvm::raw_ostream &OS, const DiagnosticOptions &Diags,
                        bool OwnsOutputStream = false);
@@ -35,9 +58,7 @@ public:
     LangOpts = &LO;
   }
 
-  void EndSourceFile() {
-    LangOpts = 0;
-  }
+  void EndSourceFile();
 
   virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
                                 const DiagnosticInfo &Info);
index f148d5e6a26c414a51d1efae71016a9e121f7593..ca661a6af7f0c8c0fa919e54e4d36a89ae6bdd0f 100644 (file)
@@ -8,6 +8,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Frontend/LogDiagnosticPrinter.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
@@ -24,16 +26,90 @@ LogDiagnosticPrinter::~LogDiagnosticPrinter() {
     delete &OS;
 }
 
-void LogDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
-                                             const DiagnosticInfo &Info) {
-  // Default implementation (Warnings/errors count).
-  DiagnosticClient::HandleDiagnostic(Level, Info);
+static llvm::StringRef getLevelName(Diagnostic::Level Level) {
+  switch (Level) {
+  default:
+    return "<unknown>";
+  case Diagnostic::Ignored: return "ignored";
+  case Diagnostic::Note:    return "note";
+  case Diagnostic::Warning: return "warning";
+  case Diagnostic::Error:   return "error";
+  case Diagnostic::Fatal:   return "fatal error";
+  }
+}
+
+void LogDiagnosticPrinter::EndSourceFile() {
+  // We emit all the diagnostics in EndSourceFile. However, we don't emit any
+  // entry if no diagnostics were present.
+  //
+  // Note that DiagnosticClient has no "end-of-compilation" callback, so we will
+  // miss any diagnostics which are emitted after and outside the translation
+  // unit processing.
+  if (Entries.empty())
+    return;
 
   // Write to a temporary string to ensure atomic write of diagnostic object.
   llvm::SmallString<512> Msg;
   llvm::raw_svector_ostream OS(Msg);
 
-  OS << "hello!\n";
+  OS << "{\n";
+  // FIXME: Output main translation unit file name.
+  // FIXME: Include the invocation, if dwarf-debug-flags is available.
+  OS << "  \"diagnostics\" : [\n";
+  for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
+    DiagEntry &DE = Entries[i];
+
+    OS << "    {\n";
+    OS << "      \"filename\" : \"" << DE.Filename << "\",\n";
+    OS << "      \"line\" : " << DE.Line << ",\n";
+    OS << "      \"column\" : " << DE.Column << ",\n";
+    OS << "      \"message\" : \"" << DE.Message << "\",\n";
+    OS << "      \"level\" : \"" << getLevelName(DE.DiagnosticLevel) << "\"\n";
+    OS << "    }" << ((i + 1 != e) ? "," : "") << '\n';
+  }
+  OS << "  ]\n";
+  OS << "},\n";
 
   this->OS << OS.str();
 }
+
+void LogDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level,
+                                            const DiagnosticInfo &Info) {
+  // Default implementation (Warnings/errors count).
+  DiagnosticClient::HandleDiagnostic(Level, Info);
+
+  // Create the diag entry.
+  DiagEntry DE;
+  DE.DiagnosticID = Info.getID();
+  DE.DiagnosticLevel = Level;
+
+  // Format the message.
+  llvm::SmallString<100> MessageStr;
+  Info.FormatDiagnostic(MessageStr);
+  DE.Message = MessageStr.str();
+
+  // Set the location information.
+  DE.Filename = "";
+  DE.Line = DE.Column = 0;
+  if (Info.getLocation().isValid()) {
+    const SourceManager &SM = Info.getSourceManager();
+    PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation());
+
+    if (PLoc.isInvalid()) {
+      // At least print the file name if available:
+      FileID FID = SM.getFileID(Info.getLocation());
+      if (!FID.isInvalid()) {
+        const FileEntry *FE = SM.getFileEntryForID(FID);
+        if (FE && FE->getName())
+          DE.Filename = FE->getName();
+      }
+    } else {
+      DE.Filename = PLoc.getFilename();
+      DE.Line = PLoc.getLine();
+      DE.Column = PLoc.getColumn();
+    }
+  }
+
+  // Record the diagnostic entry.
+  Entries.push_back(DE);
+}