From 8f0f480a10cd5b62914fd53611e696c5069fc62d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 6 Apr 2010 00:26:48 +0000 Subject: [PATCH] Give llvm::SourceMgr the ability to have a client-specified diagnostic handler. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@100503 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/IRReader.h | 10 ++++++---- include/llvm/Support/SourceMgr.h | 31 ++++++++++++++++++++++++++++--- lib/AsmParser/Parser.cpp | 2 +- lib/Support/SourceMgr.cpp | 9 ++++++++- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/include/llvm/Support/IRReader.h b/include/llvm/Support/IRReader.h index 66314e057ef..2a43c5fa906 100644 --- a/include/llvm/Support/IRReader.h +++ b/include/llvm/Support/IRReader.h @@ -38,7 +38,8 @@ namespace llvm { std::string ErrMsg; Module *M = getLazyBitcodeModule(Buffer, Context, &ErrMsg); if (M == 0) { - Err = SMDiagnostic(Buffer->getBufferIdentifier(), -1, -1, ErrMsg, ""); + Err = SMDiagnostic(SMLoc(), Buffer->getBufferIdentifier(), -1, -1, + ErrMsg, ""); // ParseBitcodeFile does not take ownership of the Buffer in the // case of an error. delete Buffer; @@ -59,7 +60,7 @@ namespace llvm { std::string ErrMsg; MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); if (F == 0) { - Err = SMDiagnostic(Filename, -1, -1, + Err = SMDiagnostic(SMLoc(), Filename, -1, -1, "Could not open input file '" + Filename + "'", ""); return 0; } @@ -81,7 +82,8 @@ namespace llvm { // ParseBitcodeFile does not take ownership of the Buffer. delete Buffer; if (M == 0) - Err = SMDiagnostic(Buffer->getBufferIdentifier(), -1, -1, ErrMsg, ""); + Err = SMDiagnostic(SMLoc(), Buffer->getBufferIdentifier(), + -1, -1, ErrMsg, ""); return M; } @@ -97,7 +99,7 @@ namespace llvm { std::string ErrMsg; MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrMsg); if (F == 0) { - Err = SMDiagnostic(Filename, -1, -1, + Err = SMDiagnostic(SMLoc(), Filename, -1, -1, "Could not open input file '" + Filename + "'", ""); return 0; } diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 158e7c9f426..caa67c03c59 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -31,6 +31,12 @@ namespace llvm { /// SourceMgr - This owns the files read by a parser, handles include stacks, /// and handles diagnostic wrangling. class SourceMgr { +public: + /// DiagHandlerTy - Clients that want to handle their own diagnostics in a + /// custom way can register a function pointer+context as a diagnostic + /// handler. It gets called each time PrintMessage is invoked. + typedef void (*DiagHandlerTy)(const SMDiagnostic&, void *Context); +private: struct SrcBuffer { /// Buffer - The memory buffer for the file. MemoryBuffer *Buffer; @@ -51,16 +57,26 @@ class SourceMgr { /// is really private to SourceMgr.cpp. mutable void *LineNoCache; + DiagHandlerTy DiagHandler; + void *DiagContext; + SourceMgr(const SourceMgr&); // DO NOT IMPLEMENT void operator=(const SourceMgr&); // DO NOT IMPLEMENT public: - SourceMgr() : LineNoCache(0) {} + SourceMgr() : LineNoCache(0), DiagHandler(0), DiagContext(0) {} ~SourceMgr(); void setIncludeDirs(const std::vector &Dirs) { IncludeDirectories = Dirs; } + /// setDiagHandler - Specify a diagnostic handler to be invoked every time + /// PrintMessage is called. + void setDiagHandler(DiagHandlerTy DH, void *Ctx = 0) { + DiagHandler = DH; + DiagContext = Ctx; + } + const SrcBuffer &getBufferInfo(unsigned i) const { assert(i < Buffers.size() && "Invalid Buffer ID!"); return Buffers[i]; @@ -128,6 +144,7 @@ private: /// SMDiagnostic - Instances of this class encapsulate one diagnostic report, /// allowing printing to a raw_ostream as a caret diagnostic. class SMDiagnostic { + SMLoc Loc; std::string Filename; int LineNo, ColumnNo; std::string Message, LineContents; @@ -135,12 +152,20 @@ class SMDiagnostic { public: SMDiagnostic() : LineNo(0), ColumnNo(0), ShowLine(0) {} - SMDiagnostic(const std::string &FN, int Line, int Col, + SMDiagnostic(SMLoc L, const std::string &FN, int Line, int Col, const std::string &Msg, const std::string &LineStr, bool showline = true) - : Filename(FN), LineNo(Line), ColumnNo(Col), Message(Msg), + : Loc(L), Filename(FN), LineNo(Line), ColumnNo(Col), Message(Msg), LineContents(LineStr), ShowLine(showline) {} + SMLoc getLoc() const { return Loc; } + const std::string getFilename() { return Filename; } + int getLineNo() const { return LineNo; } + int getColumnNo() const { return ColumnNo; } + const std::string &getMessage() const { return Message; } + const std::string &getLineContents() const { return LineContents; } + bool getShowLine() const { return ShowLine; } + void Print(const char *ProgName, raw_ostream &S) const; }; diff --git a/lib/AsmParser/Parser.cpp b/lib/AsmParser/Parser.cpp index 1ab37345b20..7280cf479f2 100644 --- a/lib/AsmParser/Parser.cpp +++ b/lib/AsmParser/Parser.cpp @@ -44,7 +44,7 @@ Module *llvm::ParseAssemblyFile(const std::string &Filename, SMDiagnostic &Err, std::string ErrorStr; MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr); if (F == 0) { - Err = SMDiagnostic("", -1, -1, + Err = SMDiagnostic(SMLoc(), "", -1, -1, "Could not open input file '" + Filename + "': " + ErrorStr, ""); return 0; diff --git a/lib/Support/SourceMgr.cpp b/lib/Support/SourceMgr.cpp index 83c7964ca00..fe2fbd96f77 100644 --- a/lib/Support/SourceMgr.cpp +++ b/lib/Support/SourceMgr.cpp @@ -168,13 +168,20 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, const std::string &Msg, } PrintedMsg += Msg; - return SMDiagnostic(CurMB->getBufferIdentifier(), FindLineNumber(Loc, CurBuf), + return SMDiagnostic(Loc, + CurMB->getBufferIdentifier(), FindLineNumber(Loc, CurBuf), Loc.getPointer()-LineStart, PrintedMsg, LineStr, ShowLine); } void SourceMgr::PrintMessage(SMLoc Loc, const std::string &Msg, const char *Type, bool ShowLine) const { + // Report the message with the diagnostic handler if present. + if (DiagHandler) { + DiagHandler(GetMessage(Loc, Msg, Type, ShowLine), DiagContext); + return; + } + raw_ostream &OS = errs(); int CurBuf = FindBufferContainingLoc(Loc);