[cfe-commits] r39603 - in /cfe/cfe/trunk: Driver/TextDiagnosticPrinter.cpp Driver/TextDiagnosticPrinter.h Driver/clang.cpp clang.xcodeproj/project.pbxproj include/clang/Basic/Diagnostic.h

bwendlin at cs.uiuc.edu bwendlin at cs.uiuc.edu
Wed Jul 11 09:46:09 PDT 2007


Author: bwendlin
Date: Wed Jul 11 11:46:09 2007
New Revision: 39603

URL: http://llvm.org/viewvc/llvm-project?rev=39603&view=rev
Log:
Submitted by: Bill Wendling
Reviewed by: Chris Lattner

- Separated out the diagnostic client from the clang driver. This is in
  preparation for creating a diagnostic client that will be used to check
  error and warning messages.

Added:
    cfe/cfe/trunk/Driver/TextDiagnosticPrinter.cpp   (with props)
    cfe/cfe/trunk/Driver/TextDiagnosticPrinter.h   (with props)
Modified:
    cfe/cfe/trunk/Driver/clang.cpp
    cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
    cfe/cfe/trunk/include/clang/Basic/Diagnostic.h

Added: cfe/cfe/trunk/Driver/TextDiagnosticPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Driver/TextDiagnosticPrinter.cpp?rev=39603&view=auto

==============================================================================
--- cfe/cfe/trunk/Driver/TextDiagnosticPrinter.cpp (added)
+++ cfe/cfe/trunk/Driver/TextDiagnosticPrinter.cpp Wed Jul 11 11:46:09 2007
@@ -0,0 +1,255 @@
+//===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bill Wendling and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This diagnostic client prints out their diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TextDiagnosticPrinter.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Streams.h"
+#include <iostream>
+#include <string>
+using namespace llvm;
+using namespace clang;
+
+static cl::opt<bool>
+NoShowColumn("fno-show-column",
+             cl::desc("Do not include column number on diagnostics"));
+static cl::opt<bool>
+NoCaretDiagnostics("fno-caret-diagnostics",
+                   cl::desc("Do not include source line and caret with"
+                            " diagnostics"));
+
+void TextDiagnosticPrinter::
+PrintIncludeStack(SourceLocation Pos) {
+  unsigned FileID = Pos.getFileID();
+  if (FileID == 0) return;
+  
+  // Print out the other include frames first.
+  PrintIncludeStack(SourceMgr.getIncludeLoc(FileID));
+  
+  unsigned LineNo = SourceMgr.getLineNumber(Pos);
+  
+  const MemoryBuffer *Buffer = SourceMgr.getBuffer(FileID);
+  cerr << "In file included from " << Buffer->getBufferIdentifier()
+       << ":" << LineNo << ":\n";
+}
+
+
+/// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
+/// any characters in LineNo that intersect the SourceRange.
+void TextDiagnosticPrinter::HighlightRange(const SourceRange &R, 
+                                           unsigned LineNo,
+                                           std::string &CaratLine,
+                                           const std::string &SourceLine) {
+  assert(CaratLine.size() == SourceLine.size() &&
+         "Expect a correspondence between source and carat line!");
+  if (!R.isValid()) return;
+
+  unsigned StartLineNo = SourceMgr.getLineNumber(R.Begin());
+  if (StartLineNo > LineNo) return;  // No intersection.
+  
+  unsigned EndLineNo = SourceMgr.getLineNumber(R.End());
+  if (EndLineNo < LineNo) return;  // No intersection.
+  
+  // Compute the column number of the start.
+  unsigned StartColNo = 0;
+  if (StartLineNo == LineNo) {
+    StartColNo = SourceMgr.getColumnNumber(R.Begin());
+    if (StartColNo) --StartColNo;  // Zero base the col #.
+  }
+
+  // Pick the first non-whitespace column.
+  while (StartColNo < SourceLine.size() &&
+         (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
+    ++StartColNo;
+  
+  // Compute the column number of the end.
+  unsigned EndColNo = CaratLine.size();
+  if (EndLineNo == LineNo) {
+    EndColNo = SourceMgr.getColumnNumber(R.End());
+    if (EndColNo) {
+      --EndColNo;  // Zero base the col #.
+      
+      // Add in the length of the token, so that we cover multi-char tokens.
+      EndColNo += GetTokenLength(R.End());
+    } else {
+      EndColNo = CaratLine.size();
+    }
+  }
+  
+  // Pick the last non-whitespace column.
+  while (EndColNo-1 &&
+         (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
+    --EndColNo;
+  
+  // Fill the range with ~'s.
+  assert(StartColNo <= EndColNo && "Invalid range!");
+  for (unsigned i = StartColNo; i != EndColNo; ++i)
+    CaratLine[i] = '~';
+}
+
+
+/// GetTokenLength - Given the source location of a token, determine its length.
+/// This is a fully general function that uses a lexer to relex the token.
+unsigned TextDiagnosticPrinter::GetTokenLength(SourceLocation Loc) {
+  const char *StrData = 
+    SourceMgr.getCharacterData(SourceMgr.getLogicalLoc(Loc));
+  
+  // Note, this could be special cased for common tokens like identifiers, ')',
+  // etc to make this faster, if it mattered.
+
+  unsigned FileID = Loc.getFileID();
+  
+  // Create a lexer starting at the beginning of this token.
+  Lexer TheLexer(SourceMgr.getBuffer(FileID), FileID,
+                 *ThePreprocessor,  StrData);
+  
+  LexerToken TheTok;
+  TheLexer.LexRawToken(TheTok);
+
+  return TheTok.getLength();
+}
+
+
+void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, 
+                                             SourceLocation Pos,
+                                             diag::kind ID,
+                                             const std::string *Strs,
+                                             unsigned NumStrs,
+                                             const SourceRange *Ranges,
+                                             unsigned NumRanges) {
+  unsigned LineNo = 0, FilePos = 0, FileID = 0, ColNo = 0;
+  unsigned LineStart = 0, LineEnd = 0;
+  const MemoryBuffer *Buffer = 0;
+  
+  if (Pos.isValid()) {
+    LineNo = SourceMgr.getLineNumber(Pos);
+    FileID  = SourceMgr.getLogicalLoc(Pos).getFileID();
+    
+    // If this is a warning or note, and if it a system header, suppress the
+    // diagnostic.
+    if (Level == Diagnostic::Warning ||
+        Level == Diagnostic::Note) {
+      SourceLocation PhysLoc = SourceMgr.getPhysicalLoc(Pos);
+      const FileEntry *F = SourceMgr.getFileEntryForFileID(PhysLoc.getFileID());
+      DirectoryLookup::DirType DirInfo = TheHeaderSearch->getFileDirFlavor(F);
+      if (DirInfo == DirectoryLookup::SystemHeaderDir ||
+          DirInfo == DirectoryLookup::ExternCSystemHeaderDir)
+        return;
+    }
+    
+    // First, if this diagnostic is not in the main file, print out the
+    // "included from" lines.
+    if (LastWarningLoc != SourceMgr.getIncludeLoc(FileID)) {
+      LastWarningLoc = SourceMgr.getIncludeLoc(FileID);
+      PrintIncludeStack(LastWarningLoc);
+    }
+  
+    // Compute the column number.  Rewind from the current position to the start
+    // of the line.
+    ColNo = SourceMgr.getColumnNumber(Pos);
+    FilePos = SourceMgr.getSourceFilePos(Pos);
+    LineStart = FilePos-ColNo+1;  // Column # is 1-based
+  
+    // Compute the line end.  Scan forward from the error position to the end of
+    // the line.
+    Buffer = SourceMgr.getBuffer(FileID);
+    const char *Buf = Buffer->getBufferStart();
+    const char *BufEnd = Buffer->getBufferEnd();
+    LineEnd = FilePos;
+    while (Buf+LineEnd != BufEnd && 
+           Buf[LineEnd] != '\n' && Buf[LineEnd] != '\r')
+      ++LineEnd;
+  
+    cerr << Buffer->getBufferIdentifier() 
+         << ":" << LineNo << ":";
+    if (ColNo && !NoShowColumn) 
+      cerr << ColNo << ":";
+    cerr << " ";
+  }
+  
+  switch (Level) {
+  default: assert(0 && "Unknown diagnostic type!");
+  case Diagnostic::Note:                 cerr << "note: "; break;
+  case Diagnostic::Warning:              cerr << "warning: "; break;
+  case Diagnostic::Error:   ++NumErrors; cerr << "error: "; break;
+  case Diagnostic::Fatal:   ++NumErrors; cerr << "fatal error: "; break;
+  case Diagnostic::Sorry:   ++NumErrors; cerr << "sorry, unimplemented: ";
+    break;
+  }
+  
+  std::string Msg = Diagnostic::getDescription(ID);
+  
+  // Replace all instances of %0 in Msg with 'Extra'.
+  for (unsigned i = 0; i < Msg.size()-1; ++i) {
+    if (Msg[i] == '%' && isdigit(Msg[i+1])) {
+      unsigned StrNo = Msg[i+1]-'0';
+      Msg = std::string(Msg.begin(), Msg.begin()+i) +
+            (StrNo < NumStrs ? Strs[StrNo] : "<<<INTERNAL ERROR>>>") +
+            std::string(Msg.begin()+i+2, Msg.end());
+    }
+  }
+  cerr << Msg << "\n";
+  
+  if (!NoCaretDiagnostics && Pos.isValid()) {
+    // Get the line of the source file.
+    const char *Buf = Buffer->getBufferStart();
+    std::string SourceLine(Buf+LineStart, Buf+LineEnd);
+    
+    // Create a line for the carat that is filled with spaces that is the same
+    // length as the line of source code.
+    std::string CaratLine(LineEnd-LineStart, ' ');
+    
+    // Highlight all of the characters covered by Ranges with ~ characters.
+    for (unsigned i = 0; i != NumRanges; ++i)
+      HighlightRange(Ranges[i], LineNo, CaratLine, SourceLine);
+    
+    // Next, insert the carat itself.
+    if (ColNo-1 < CaratLine.size())
+      CaratLine[ColNo-1] = '^';
+    else
+      CaratLine.push_back('^');
+    
+    // Scan the source line, looking for tabs.  If we find any, manually expand
+    // them to 8 characters and update the CaratLine to match.
+    for (unsigned i = 0; i != SourceLine.size(); ++i) {
+      if (SourceLine[i] != '\t') continue;
+      
+      // Replace this tab with at least one space.
+      SourceLine[i] = ' ';
+      
+      // Compute the number of spaces we need to insert.
+      unsigned NumSpaces = ((i+8)&~7) - (i+1);
+      assert(NumSpaces < 8 && "Invalid computation of space amt");
+      
+      // Insert spaces into the SourceLine.
+      SourceLine.insert(i+1, NumSpaces, ' ');
+      
+      // Insert spaces or ~'s into CaratLine.
+      CaratLine.insert(i+1, NumSpaces, CaratLine[i] == '~' ? '~' : ' ');
+    }
+    
+    // Finally, remove any blank spaces from the end of CaratLine.
+    while (CaratLine[CaratLine.size()-1] == ' ')
+      CaratLine.erase(CaratLine.end()-1);
+    
+    // Emit what we have computed.
+    cerr << SourceLine << "\n";
+    cerr << CaratLine << "\n";
+  }
+  
+  ++NumDiagnostics;
+}

Propchange: cfe/cfe/trunk/Driver/TextDiagnosticPrinter.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/cfe/trunk/Driver/TextDiagnosticPrinter.cpp

------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: cfe/cfe/trunk/Driver/TextDiagnosticPrinter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Driver/TextDiagnosticPrinter.h?rev=39603&view=auto

==============================================================================
--- cfe/cfe/trunk/Driver/TextDiagnosticPrinter.h (added)
+++ cfe/cfe/trunk/Driver/TextDiagnosticPrinter.h Wed Jul 11 11:46:09 2007
@@ -0,0 +1,56 @@
+//===--- TextDiagnosticPrinter.h - Text Diagnostic Client -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bill Wendling and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which prints the diagnostics to
+// standard error.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DIAGNOSTIC_CLIENTS_H_
+#define DIAGNOSTIC_CLIENTS_H_
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+
+namespace llvm {
+  namespace clang {
+    class SourceManager;
+    class HeaderSearch;
+    class Preprocessor;
+
+    class TextDiagnosticPrinter : public DiagnosticClient {
+      SourceManager &SourceMgr;
+      SourceLocation LastWarningLoc;
+      HeaderSearch *TheHeaderSearch;
+      Preprocessor *ThePreprocessor;
+    public:
+      TextDiagnosticPrinter(SourceManager &sourceMgr)
+        : SourceMgr(sourceMgr) {}
+
+      void setHeaderSearch(HeaderSearch &HS) { TheHeaderSearch = &HS; }
+      void setPreprocessor(Preprocessor &P) { ThePreprocessor = &P; }
+
+      void PrintIncludeStack(SourceLocation Pos);
+      void HighlightRange(const SourceRange &R, unsigned LineNo,
+                          std::string &CaratLine,
+                          const std::string &SourceLine);
+      unsigned GetTokenLength(SourceLocation Loc);
+
+      virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                    SourceLocation Pos,
+                                    diag::kind ID, const std::string *Strs,
+                                    unsigned NumStrs,
+                                    const SourceRange *Ranges, 
+                                    unsigned NumRanges);
+    };
+
+  } // end namspace clang
+} // end namespace llvm
+
+#endif

Propchange: cfe/cfe/trunk/Driver/TextDiagnosticPrinter.h

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/cfe/trunk/Driver/TextDiagnosticPrinter.h

------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: cfe/cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Driver/clang.cpp?rev=39603&r1=39602&r2=39603&view=diff

==============================================================================
--- cfe/cfe/trunk/Driver/clang.cpp (original)
+++ cfe/cfe/trunk/Driver/clang.cpp Wed Jul 11 11:46:09 2007
@@ -23,25 +23,21 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang.h"
+#include "TextDiagnosticPrinter.h"
 #include "clang/Sema/ASTStreamer.h"
 #include "clang/AST/AST.h"
 #include "clang/Parse/Parser.h"
 #include "clang/Lex/HeaderSearch.h"
-#include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/MemoryBuffer.h"
-#include "llvm/System/MappedFile.h"
 #include "llvm/System/Signals.h"
 #include <iostream>
 using namespace llvm;
 using namespace clang;
 
-static unsigned NumDiagnostics = 0;
-static unsigned NumErrors = 0;
-
 //===----------------------------------------------------------------------===//
 // Global options.
 //===----------------------------------------------------------------------===//
@@ -327,261 +323,6 @@
     Diags.setDiagnosticMapping(diag::pp_macro_not_used, diag::MAP_IGNORE);
 }
 
-static cl::opt<bool>
-NoShowColumn("fno-show-column",
-             cl::desc("Do not include column number on diagnostics"));
-static cl::opt<bool>
-NoCaretDiagnostics("fno-caret-diagnostics",
-                   cl::desc("Do not include source line and caret with"
-                            " diagnostics"));
-
-/// DiagnosticPrinterSTDERR - This is a concrete diagnostic client, which prints
-/// the diagnostics to standard error.
-class DiagnosticPrinterSTDERR : public DiagnosticClient {
-  SourceManager &SourceMgr;
-  SourceLocation LastWarningLoc;
-  HeaderSearch *TheHeaderSearch;
-  Preprocessor *ThePreprocessor;
-public:
-  DiagnosticPrinterSTDERR(SourceManager &sourceMgr)
-    : SourceMgr(sourceMgr) {}
-  
-  void setHeaderSearch(HeaderSearch &HS) { TheHeaderSearch = &HS; }
-  void setPreprocessor(Preprocessor &P) { ThePreprocessor = &P; }
-  
-  void PrintIncludeStack(SourceLocation Pos);
-  void HighlightRange(const SourceRange &R, unsigned LineNo,
-                      std::string &CaratLine, const std::string &SourceLine);
-  unsigned GetTokenLength(SourceLocation Loc);
-    
-  virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, SourceLocation Pos,
-                                diag::kind ID, const std::string *Strs,
-                                unsigned NumStrs, const SourceRange *Ranges, 
-                                unsigned NumRanges);
-};
-
-void DiagnosticPrinterSTDERR::
-PrintIncludeStack(SourceLocation Pos) {
-  unsigned FileID = Pos.getFileID();
-  if (FileID == 0) return;
-  
-  // Print out the other include frames first.
-  PrintIncludeStack(SourceMgr.getIncludeLoc(FileID));
-  
-  unsigned LineNo = SourceMgr.getLineNumber(Pos);
-  
-  const MemoryBuffer *Buffer = SourceMgr.getBuffer(FileID);
-  std::cerr << "In file included from " << Buffer->getBufferIdentifier()
-            << ":" << LineNo << ":\n";
-}
-
-
-/// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
-/// any characters in LineNo that intersect the SourceRange.
-void DiagnosticPrinterSTDERR::HighlightRange(const SourceRange &R, 
-                                             unsigned LineNo,
-                                             std::string &CaratLine,
-                                             const std::string &SourceLine) {
-  assert(CaratLine.size() == SourceLine.size() &&
-         "Expect a correspondence between source and carat line!");
-  if (!R.isValid()) return;
-
-  unsigned StartLineNo = SourceMgr.getLineNumber(R.Begin());
-  if (StartLineNo > LineNo) return;  // No intersection.
-  
-  unsigned EndLineNo = SourceMgr.getLineNumber(R.End());
-  if (EndLineNo < LineNo) return;  // No intersection.
-  
-  // Compute the column number of the start.
-  unsigned StartColNo = 0;
-  if (StartLineNo == LineNo) {
-    StartColNo = SourceMgr.getColumnNumber(R.Begin());
-    if (StartColNo) --StartColNo;  // Zero base the col #.
-  }
-
-  // Pick the first non-whitespace column.
-  while (StartColNo < SourceLine.size() &&
-         (SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
-    ++StartColNo;
-  
-  // Compute the column number of the end.
-  unsigned EndColNo = CaratLine.size();
-  if (EndLineNo == LineNo) {
-    EndColNo = SourceMgr.getColumnNumber(R.End());
-    if (EndColNo) {
-      --EndColNo;  // Zero base the col #.
-      
-      // Add in the length of the token, so that we cover multi-char tokens.
-      EndColNo += GetTokenLength(R.End());
-    } else {
-      EndColNo = CaratLine.size();
-    }
-  }
-  
-  // Pick the last non-whitespace column.
-  while (EndColNo-1 &&
-         (SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
-    --EndColNo;
-  
-  // Fill the range with ~'s.
-  assert(StartColNo <= EndColNo && "Invalid range!");
-  for (unsigned i = StartColNo; i != EndColNo; ++i)
-    CaratLine[i] = '~';
-}
-
-
-/// GetTokenLength - Given the source location of a token, determine its length.
-/// This is a fully general function that uses a lexer to relex the token.
-unsigned DiagnosticPrinterSTDERR::GetTokenLength(SourceLocation Loc) {
-  const char *StrData = 
-    SourceMgr.getCharacterData(SourceMgr.getLogicalLoc(Loc));
-  
-  // Note, this could be special cased for common tokens like identifiers, ')',
-  // etc to make this faster, if it mattered.
-
-  unsigned FileID = Loc.getFileID();
-  
-  // Create a lexer starting at the beginning of this token.
-  Lexer TheLexer(SourceMgr.getBuffer(FileID), FileID,
-                 *ThePreprocessor,  StrData);
-  
-  LexerToken TheTok;
-  TheLexer.LexRawToken(TheTok);
-
-  return TheTok.getLength();
-}
-
-
-void DiagnosticPrinterSTDERR::HandleDiagnostic(Diagnostic::Level Level, 
-                                               SourceLocation Pos,
-                                               diag::kind ID,
-                                               const std::string *Strs,
-                                               unsigned NumStrs,
-                                               const SourceRange *Ranges,
-                                               unsigned NumRanges) {
-  unsigned LineNo = 0, FilePos = 0, FileID = 0, ColNo = 0;
-  unsigned LineStart = 0, LineEnd = 0;
-  const MemoryBuffer *Buffer = 0;
-  
-  if (Pos.isValid()) {
-    LineNo = SourceMgr.getLineNumber(Pos);
-    FileID  = SourceMgr.getLogicalLoc(Pos).getFileID();
-    
-    // If this is a warning or note, and if it a system header, suppress the
-    // diagnostic.
-    if (Level == Diagnostic::Warning ||
-        Level == Diagnostic::Note) {
-      SourceLocation PhysLoc = SourceMgr.getPhysicalLoc(Pos);
-      const FileEntry *F = SourceMgr.getFileEntryForFileID(PhysLoc.getFileID());
-      DirectoryLookup::DirType DirInfo = TheHeaderSearch->getFileDirFlavor(F);
-      if (DirInfo == DirectoryLookup::SystemHeaderDir ||
-          DirInfo == DirectoryLookup::ExternCSystemHeaderDir)
-        return;
-    }
-    
-    // First, if this diagnostic is not in the main file, print out the
-    // "included from" lines.
-    if (LastWarningLoc != SourceMgr.getIncludeLoc(FileID)) {
-      LastWarningLoc = SourceMgr.getIncludeLoc(FileID);
-      PrintIncludeStack(LastWarningLoc);
-    }
-  
-    // Compute the column number.  Rewind from the current position to the start
-    // of the line.
-    ColNo = SourceMgr.getColumnNumber(Pos);
-    FilePos = SourceMgr.getSourceFilePos(Pos);
-    LineStart = FilePos-ColNo+1;  // Column # is 1-based
-  
-    // Compute the line end.  Scan forward from the error position to the end of
-    // the line.
-    Buffer = SourceMgr.getBuffer(FileID);
-    const char *Buf = Buffer->getBufferStart();
-    const char *BufEnd = Buffer->getBufferEnd();
-    LineEnd = FilePos;
-    while (Buf+LineEnd != BufEnd && 
-           Buf[LineEnd] != '\n' && Buf[LineEnd] != '\r')
-      ++LineEnd;
-  
-    std::cerr << Buffer->getBufferIdentifier() 
-              << ":" << LineNo << ":";
-    if (ColNo && !NoShowColumn) 
-      std::cerr << ColNo << ":";
-    std::cerr << " ";
-  }
-  
-  switch (Level) {
-  default: assert(0 && "Unknown diagnostic type!");
-  case Diagnostic::Note:                 std::cerr << "note: "; break;
-  case Diagnostic::Warning:              std::cerr << "warning: "; break;
-  case Diagnostic::Error:   ++NumErrors; std::cerr << "error: "; break;
-  case Diagnostic::Fatal:   ++NumErrors; std::cerr << "fatal error: "; break;
-  case Diagnostic::Sorry:   ++NumErrors; std::cerr << "sorry, unimplemented: ";
-    break;
-  }
-  
-  std::string Msg = Diagnostic::getDescription(ID);
-  
-  // Replace all instances of %0 in Msg with 'Extra'.
-  for (unsigned i = 0; i < Msg.size()-1; ++i) {
-    if (Msg[i] == '%' && isdigit(Msg[i+1])) {
-      unsigned StrNo = Msg[i+1]-'0';
-      Msg = std::string(Msg.begin(), Msg.begin()+i) +
-            (StrNo < NumStrs ? Strs[StrNo] : "<<<INTERNAL ERROR>>>") +
-            std::string(Msg.begin()+i+2, Msg.end());
-    }
-  }
-  std::cerr << Msg << "\n";
-  
-  if (!NoCaretDiagnostics && Pos.isValid()) {
-    // Get the line of the source file.
-    const char *Buf = Buffer->getBufferStart();
-    std::string SourceLine(Buf+LineStart, Buf+LineEnd);
-    
-    // Create a line for the carat that is filled with spaces that is the same
-    // length as the line of source code.
-    std::string CaratLine(LineEnd-LineStart, ' ');
-    
-    // Highlight all of the characters covered by Ranges with ~ characters.
-    for (unsigned i = 0; i != NumRanges; ++i)
-      HighlightRange(Ranges[i], LineNo, CaratLine, SourceLine);
-    
-    // Next, insert the carat itself.
-    if (ColNo-1 < CaratLine.size())
-      CaratLine[ColNo-1] = '^';
-    else
-      CaratLine.push_back('^');
-    
-    // Scan the source line, looking for tabs.  If we find any, manually expand
-    // them to 8 characters and update the CaratLine to match.
-    for (unsigned i = 0; i != SourceLine.size(); ++i) {
-      if (SourceLine[i] != '\t') continue;
-      
-      // Replace this tab with at least one space.
-      SourceLine[i] = ' ';
-      
-      // Compute the number of spaces we need to insert.
-      unsigned NumSpaces = ((i+8)&~7) - (i+1);
-      assert(NumSpaces < 8 && "Invalid computation of space amt");
-      
-      // Insert spaces into the SourceLine.
-      SourceLine.insert(i+1, NumSpaces, ' ');
-      
-      // Insert spaces or ~'s into CaratLine.
-      CaratLine.insert(i+1, NumSpaces, CaratLine[i] == '~' ? '~' : ' ');
-    }
-    
-    // Finally, remove any blank spaces from the end of CaratLine.
-    while (CaratLine[CaratLine.size()-1] == ' ')
-      CaratLine.erase(CaratLine.end()-1);
-    
-    // Emit what we have computed.
-    std::cerr << SourceLine << "\n";
-    std::cerr << CaratLine << "\n";
-  }
-  
-  ++NumDiagnostics;
-}
-
 //===----------------------------------------------------------------------===//
 // Preprocessor Initialization
 //===----------------------------------------------------------------------===//
@@ -1043,7 +784,7 @@
 ///
 static void ProcessInputFile(const std::string &InFile, 
                              SourceManager &SourceMgr, Diagnostic &Diags,
-                             DiagnosticPrinterSTDERR &OurDiagnosticClient,
+                             TextDiagnosticPrinter &OurDiagnosticClient,
                              HeaderSearch &HeaderInfo, TargetInfo &Target,
                              const LangOptions &LangInfo) {
   FileManager &FileMgr = HeaderInfo.getFileMgr();
@@ -1067,7 +808,7 @@
     if (File) MainFileID = SourceMgr.createFileID(File, SourceLocation());
     if (MainFileID == 0) {
       std::cerr << "Error reading '" << InFile << "'!\n";
-      ++NumErrors;
+      OurDiagnosticClient.incrNumErrors();
       return;
     }
   } else {
@@ -1075,7 +816,7 @@
     if (SB) MainFileID = SourceMgr.createFileIDForMemBuffer(SB);
     if (MainFileID == 0) {
       std::cerr << "Error reading standard input!  Empty?\n";
-      ++NumErrors;
+      OurDiagnosticClient.incrNumErrors();
       return;
     }
   }
@@ -1176,7 +917,7 @@
   SourceManager SourceMgr;
   
   // Print diagnostics to stderr.
-  DiagnosticPrinterSTDERR OurDiagnosticClient(SourceMgr);
+  TextDiagnosticPrinter OurDiagnosticClient(SourceMgr);
   
   // Configure our handling of diagnostics.
   Diagnostic Diags(OurDiagnosticClient);
@@ -1210,9 +951,9 @@
     ProcessInputFile(InputFilenames[i], SourceMgr, Diags, OurDiagnosticClient,
                      HeaderInfo, *Target, LangInfo);
   
-  if (NumDiagnostics)
-    std::cerr << NumDiagnostics << " diagnostic"
-              << (NumDiagnostics == 1 ? "" : "s")
+  if (OurDiagnosticClient.getNumDiagnostics())
+    std::cerr << OurDiagnosticClient.getNumDiagnostics() << " diagnostic"
+              << (OurDiagnosticClient.getNumDiagnostics() == 1 ? "" : "s")
               << " generated.\n";
   
   if (Stats) {
@@ -1222,5 +963,5 @@
     std::cerr << "\n";
   }
   
-  return NumErrors != 0;
+  return OurDiagnosticClient.getNumErrors() != 0;
 }

Modified: cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=39603&r1=39602&r2=39603&view=diff

==============================================================================
--- cfe/cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/cfe/trunk/clang.xcodeproj/project.pbxproj Wed Jul 11 11:46:09 2007
@@ -106,25 +106,10 @@
 		DED7D7D80A524302003AD0FB /* README.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D7D70A524302003AD0FB /* README.txt */; };
 		DED7D9180A52518C003AD0FB /* ScratchBuffer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DED7D9170A52518C003AD0FB /* ScratchBuffer.h */; };
 		DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */; };
+		F0226FD20C18084500141F42 /* TextDiagnosticPrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F0226FD00C18084500141F42 /* TextDiagnosticPrinter.cpp */; };
+		F0226FD30C18084500141F42 /* TextDiagnosticPrinter.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = F0226FD10C18084500141F42 /* TextDiagnosticPrinter.h */; };
 /* End PBXBuildFile section */
 
-/* Begin PBXBuildStyle section */
-		84916C3B0C1736920080778F /* Development */ = {
-			isa = PBXBuildStyle;
-			buildSettings = {
-				COPY_PHASE_STRIP = NO;
-			};
-			name = Development;
-		};
-		84916C3C0C1736920080778F /* Deployment */ = {
-			isa = PBXBuildStyle;
-			buildSettings = {
-				COPY_PHASE_STRIP = YES;
-			};
-			name = Deployment;
-		};
-/* End PBXBuildStyle section */
-
 /* Begin PBXCopyFilesBuildPhase section */
 		8DD76F690486A84900D96B5E /* CopyFiles */ = {
 			isa = PBXCopyFilesBuildPhase;
@@ -180,6 +165,7 @@
 				DE928B7D0C0A615100231DA4 /* CodeGenModule.h in CopyFiles */,
 				DE928B810C0A615B00231DA4 /* CodeGenFunction.h in CopyFiles */,
 				84916BE70C161E800080778F /* Attr.h in CopyFiles */,
+				F0226FD30C18084500141F42 /* TextDiagnosticPrinter.h in CopyFiles */,
 			);
 			runOnlyForDeploymentPostprocessing = 1;
 		};
@@ -191,7 +177,7 @@
 		1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
 		84916BE40C161E580080778F /* Attr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Attr.cpp; path = AST/Attr.cpp; sourceTree = "<group>"; };
 		84916BE60C161E800080778F /* Attr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Attr.h; path = include/clang/AST/Attr.h; sourceTree = "<group>"; };
-		8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
+		8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
 		DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
 		DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = Parse/ParseExprCXX.cpp; sourceTree = "<group>"; };
 		DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };
@@ -286,6 +272,8 @@
 		DED7D7D70A524302003AD0FB /* README.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README.txt; sourceTree = "<group>"; };
 		DED7D9170A52518C003AD0FB /* ScratchBuffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ScratchBuffer.h; sourceTree = "<group>"; };
 		DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ScratchBuffer.cpp; sourceTree = "<group>"; };
+		F0226FD00C18084500141F42 /* TextDiagnosticPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = TextDiagnosticPrinter.cpp; path = Driver/TextDiagnosticPrinter.cpp; sourceTree = "<group>"; };
+		F0226FD10C18084500141F42 /* TextDiagnosticPrinter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = TextDiagnosticPrinter.h; path = Driver/TextDiagnosticPrinter.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -420,6 +408,8 @@
 				DE5932CD0AD60FF400BC794C /* clang.cpp */,
 				DE5932CE0AD60FF400BC794C /* clang.h */,
 				DED627020AE0C51D001E80A4 /* Targets.cpp */,
+				F0226FD00C18084500141F42 /* TextDiagnosticPrinter.cpp */,
+				F0226FD10C18084500141F42 /* TextDiagnosticPrinter.h */,
 				DED67AEF0B6DB92F00AAD4A3 /* PPCBuiltins.def */,
 				DED67AED0B6DB92A00AAD4A3 /* X86Builtins.def */,
 				DE927FFC0C055DE900231DA4 /* LLVMCodegen.cpp */,
@@ -571,12 +561,6 @@
 		08FB7793FE84155DC02AAC07 /* Project object */ = {
 			isa = PBXProject;
 			buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
-			buildSettings = {
-			};
-			buildStyles = (
-				84916C3B0C1736920080778F /* Development */,
-				84916C3C0C1736920080778F /* Deployment */,
-			);
 			hasScannedForEncodings = 1;
 			mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
 			projectDirPath = "";
@@ -642,6 +626,7 @@
 				DE4772FC0C10EAEC002239E8 /* CGExpr.cpp in Sources */,
 				DE4264FC0C113592005A861D /* CGDecl.cpp in Sources */,
 				84916BE50C161E580080778F /* Attr.cpp in Sources */,
+				F0226FD20C18084500141F42 /* TextDiagnosticPrinter.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: cfe/cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=39603&r1=39602&r2=39603&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/cfe/trunk/include/clang/Basic/Diagnostic.h Wed Jul 11 11:46:09 2007
@@ -131,9 +131,18 @@
 /// DiagnosticClient - This is an abstract interface implemented by clients of
 /// the front-end, which formats and prints fully processed diagnostics.
 class DiagnosticClient {
+protected:
+  unsigned NumDiagnostics;
+  unsigned NumErrors;
 public:
-  
+  DiagnosticClient() : NumDiagnostics(0), NumErrors(0) {}
   virtual ~DiagnosticClient();
+
+  unsigned getNumDiagnostics() const { return NumDiagnostics; }
+  unsigned getNumErrors() const { return NumErrors; }
+
+  void incrNumDiagnostics() { ++NumDiagnostics; }
+  void incrNumErrors() { ++NumErrors; }
   
   /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or 
   /// capturing it to a log as needed.





More information about the cfe-commits mailing list