From 2f510aed9cbd24dca1fdc5aabe27325e5ade9e1a Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 2 Jul 2009 22:24:20 +0000 Subject: [PATCH] add an explicit class for holding llvm::SourceMgr diagnostics and use it to print them. This gives us column numbers in the diag line. Before: t.s:4: error: unexpected token in argument list mov %eax %edx ^ now: t.s:4:11: error: unexpected token in argument list mov %eax %edx ^ git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74732 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/SourceMgr.h | 42 ++++++++++++++++--- lib/Support/SourceMgr.cpp | 71 +++++++++++++++++++++++--------- 2 files changed, 88 insertions(+), 25 deletions(-) diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 23044a8bd03..0260d2d7518 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -7,9 +7,9 @@ // //===----------------------------------------------------------------------===// // -// This file declares the SourceMgr class. This class is used as a simple -// substrate for diagnostics, #include handling, and other low level things for -// simple parsers. +// This file declares the SMLoc, SMDiagnostic and SourceMgr classes. This +// provides a simple substrate for diagnostics, #include handling, and other low +// level things for simple parsers. // //===----------------------------------------------------------------------===// @@ -23,6 +23,8 @@ namespace llvm { class MemoryBuffer; class SourceMgr; + class SMDiagnostic; + class raw_ostream; class SMLoc { const char *Ptr; @@ -44,8 +46,8 @@ public: } }; -/// SourceMgr - This owns the files read by tblgen, handles include stacks, -/// and handles printing of diagnostics. +/// SourceMgr - This owns the files read by a parser, handles include stacks, +/// and handles diagnostic wrangling. class SourceMgr { struct SrcBuffer { /// Buffer - The memory buffer for the file. @@ -117,7 +119,35 @@ public: void PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type) const; private: - void PrintIncludeStack(SMLoc IncludeLoc) const; + void PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const; +}; + + +/// SMDiagnostic - Instances of this class encapsulate one diagnostic report, +/// allowing printing to a raw_ostream as a caret diagnostic. +class SMDiagnostic { + std::string Filename; + int LineNo, ColumnNo; + std::string Message, LineContents; +public: + SMDiagnostic() : LineNo(0), ColumnNo(0) {} + SMDiagnostic(const std::string &FN, int Line, int Col, + const std::string &Msg, const std::string &LineStr) + : Filename(FN), LineNo(Line), ColumnNo(Col), Message(Msg), + LineContents(LineStr) {} + SMDiagnostic(const SMDiagnostic &RHS) { + operator=(RHS); + } + + void operator=(const SMDiagnostic &E) { + Filename = E.Filename; + LineNo = E.LineNo; + ColumnNo = E.ColumnNo; + Message = E.Message; + LineContents = E.LineContents; + } + + void Print(const char *ProgName, raw_ostream &S); }; } // end llvm namespace diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp index 6232265cb3b..123531e21db 100644 --- a/lib/Support/SourceMgr.cpp +++ b/lib/Support/SourceMgr.cpp @@ -76,17 +76,17 @@ unsigned SourceMgr::FindLineNumber(SMLoc Loc, int BufferID) const { return LineNo; } -void SourceMgr::PrintIncludeStack(SMLoc IncludeLoc) const { +void SourceMgr::PrintIncludeStack(SMLoc IncludeLoc, raw_ostream &OS) const { if (IncludeLoc == SMLoc()) return; // Top of stack. int CurBuf = FindBufferContainingLoc(IncludeLoc); assert(CurBuf != -1 && "Invalid or unspecified location!"); - PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc); + PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS); - errs() << "Included from " - << getBufferInfo(CurBuf).Buffer->getBufferIdentifier() - << ":" << FindLineNumber(IncludeLoc, CurBuf) << ":\n"; + OS << "Included from " + << getBufferInfo(CurBuf).Buffer->getBufferIdentifier() + << ":" << FindLineNumber(IncludeLoc, CurBuf) << ":\n"; } @@ -99,19 +99,11 @@ void SourceMgr::PrintMessage(SMLoc Loc, const std::string &Msg, int CurBuf = FindBufferContainingLoc(Loc); assert(CurBuf != -1 && "Invalid or unspecified location!"); - PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc); + PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc, OS); MemoryBuffer *CurMB = getBufferInfo(CurBuf).Buffer; - OS << CurMB->getBufferIdentifier() << ":" - << FindLineNumber(Loc, CurBuf) << ": "; - - if (Type) - OS << Type << ": "; - - OS << Msg << "\n"; - // Scan backward to find the start of the line. const char *LineStart = Loc.getPointer(); while (LineStart != CurMB->getBufferStart() && @@ -122,10 +114,51 @@ void SourceMgr::PrintMessage(SMLoc Loc, const std::string &Msg, while (LineEnd != CurMB->getBufferEnd() && LineEnd[0] != '\n' && LineEnd[0] != '\r') ++LineEnd; + + std::string PrintedMsg; + if (Type) { + PrintedMsg = Type; + PrintedMsg += ": "; + } + PrintedMsg += Msg; + + // Print out the line. - OS << std::string(LineStart, LineEnd) << "\n"; - // Print out spaces before the caret. - for (const char *Pos = LineStart; Pos != Loc.getPointer(); ++Pos) - OS << (*Pos == '\t' ? '\t' : ' '); - OS << "^\n"; + SMDiagnostic(CurMB->getBufferIdentifier(), FindLineNumber(Loc, CurBuf), + Loc.getPointer()-LineStart, PrintedMsg, + std::string(LineStart, LineEnd)).Print(0, OS); + } + +//===----------------------------------------------------------------------===// +// SMDiagnostic Implementation +//===----------------------------------------------------------------------===// + +void SMDiagnostic::Print(const char *ProgName, raw_ostream &S) { + if (ProgName && ProgName[0]) + S << ProgName << ": "; + + if (Filename == "-") + S << ""; + else + S << Filename; + + if (LineNo != -1) { + S << ':' << LineNo; + if (ColumnNo != -1) + S << ':' << (ColumnNo+1); + } + + S << ": " << Message << '\n'; + + if (LineNo != -1 && ColumnNo != -1) { + S << LineContents << '\n'; + + // Print out spaces/tabs before the caret. + for (unsigned i = 0; i != unsigned(ColumnNo); ++i) + S << (LineContents[i] == '\t' ? '\t' : ' '); + S << "^\n"; + } +} + +