[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