From b4947e4378fee65ba0d7410da03ab9f185e56074 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Tue, 10 Mar 2009 05:16:17 +0000 Subject: BugReporter: - Group control flow and event PathDiagnosticPieces into PathDiagnosticMacroPieces. - Afterwards, eliminate any PathDiagnosticMacroPieces from a PathDiagnostic that contain no informative events. HTMLDiagnostics: - Use new information about PathDiagnosticMacroPieces to specially format message bubbles for macro expansions containing interesting events. llvm-svn: 66524 --- clang/lib/Frontend/HTMLDiagnostics.cpp | 184 ++++++++++++++++++++++++--------- 1 file changed, 135 insertions(+), 49 deletions(-) (limited to 'clang/lib/Frontend') diff --git a/clang/lib/Frontend/HTMLDiagnostics.cpp b/clang/lib/Frontend/HTMLDiagnostics.cpp index 02b327db2ad..0b266cda0f0 100644 --- a/clang/lib/Frontend/HTMLDiagnostics.cpp +++ b/clang/lib/Frontend/HTMLDiagnostics.cpp @@ -20,6 +20,7 @@ #include "clang/Rewrite/Rewriter.h" #include "clang/Rewrite/HTMLRewrite.h" #include "clang/Lex/Lexer.h" +#include "clang/Lex/Preprocessor.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Streams.h" @@ -48,6 +49,10 @@ public: virtual void HandlePathDiagnostic(const PathDiagnostic* D); + unsigned ProcessMacroPiece(llvm::raw_ostream& os, + const PathDiagnosticMacroPiece& P, + unsigned num); + void HandlePiece(Rewriter& R, FileID BugFileID, const PathDiagnosticPiece& P, unsigned num, unsigned max); @@ -364,7 +369,32 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, PosNo += *c == '\t' ? 8 : 1; // Create the html for the message. - { + + const char *Kind = 0; + switch (P.getKind()) { + case PathDiagnosticPiece::Event: Kind = "Event"; break; + case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break; + // Setting Kind to "Control" is intentional. + case PathDiagnosticPiece::Macro: Kind = "Control"; break; + } + + std::string sbuf; + llvm::raw_string_ostream os(sbuf); + + os << "\n
(P)) { // Get the string and determining its maximum substring. const std::string& Msg = P.getString(); unsigned max_token = 0; @@ -383,9 +413,10 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, cnt = 0; } - if (cnt > max_token) max_token = cnt; + if (cnt > max_token) + max_token = cnt; - // Next, determine the approximate size of the message bubble in em. + // Determine the approximate size of the message bubble in em. unsigned em; const unsigned max_line = 120; @@ -394,7 +425,7 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, else { unsigned characters = max_line; unsigned lines = len / max_line; - + if (lines > 0) { for (; characters > max_token; --characters) if (len / characters > lines) { @@ -402,60 +433,71 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, break; } } - - em = characters / 2; - } - // Now generate the message bubble. - const char *Kind = 0; - switch (P.getKind()) { - case PathDiagnosticPiece::Event: Kind = "Event"; break; - case PathDiagnosticPiece::ControlFlow: Kind = "Control"; break; - case PathDiagnosticPiece::Macro: Kind = "Macro"; break; + em = characters / 2; } + + if (em < max_line/2) + os << "; max-width:" << em << "em"; + } + else + os << "; max-width:100em"; + + os << "\">"; + + if (max > 1) { + os << ""; - // Insert the new html. - unsigned DisplayPos = LineEnd - FileStart; - SourceLocation Loc = - SM.getLocForStartOfFile(LPosInfo.first).getFileLocWithOffset(DisplayPos); - - R.InsertStrBefore(Loc, os.str()); + // Within a macro piece. Write out each event. + ProcessMacroPiece(os, *MP, 0); + } + else { + os << html::EscapeText(P.getString()); + + if (max > 1) + os << "
"; + os << "
" << num << "
"; + os << "
"; + } + + if (const PathDiagnosticMacroPiece *MP = + dyn_cast(&P)) { + + os << "Within the expansion of the macro '"; - std::string sbuf; - llvm::raw_string_ostream os(sbuf); - - os << "\n
"; - - if (max > 1) { - os << "
"; - os << "
" << num << "
"; - os << "
"; + // Get the name of the macro by relexing it. + { + FullSourceLoc L = MP->getLocation().getInstantiationLoc(); + assert(L.isFileID()); + std::pair BufferInfo = L.getBufferData(); + const char* MacroName = L.getDecomposedLoc().second + BufferInfo.first; + Lexer rawLexer(L, PP->getLangOptions(), BufferInfo.first, + MacroName, BufferInfo.second); + + Token TheTok; + rawLexer.LexFromRawLexer(TheTok); + for (unsigned i = 0, n = TheTok.getLength(); i < n; ++i) + os << MacroName[i]; } + + os << "':\n"; - os << html::EscapeText(Msg); - - if (max > 1) { + if (max > 1) os << "
"; - } - - os << "
"; } - // Now highlight the ranges. - + os << "
"; + + // Insert the new html. + unsigned DisplayPos = LineEnd - FileStart; + SourceLocation Loc = + SM.getLocForStartOfFile(LPosInfo.first).getFileLocWithOffset(DisplayPos); + + R.InsertStrBefore(Loc, os.str()); + + // Now highlight the ranges. for (const SourceRange *I = P.ranges_begin(), *E = P.ranges_end(); I != E; ++I) HighlightRange(R, LPosInfo.first, *I); @@ -482,6 +524,50 @@ void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID, #endif } +static void EmitAlphaCounter(llvm::raw_ostream& os, unsigned n) { + llvm::SmallVector buf; + + do { + unsigned x = n % ('z' - 'a'); + buf.push_back('a' + x); + n = n / ('z' - 'a'); + } while (n); + + assert(!buf.empty()); + + for (llvm::SmallVectorImpl::reverse_iterator I=buf.rbegin(), + E=buf.rend(); I!=E; ++I) + os << *I; +} + +unsigned HTMLDiagnostics::ProcessMacroPiece(llvm::raw_ostream& os, + const PathDiagnosticMacroPiece& P, + unsigned num) { + + for (PathDiagnosticMacroPiece::const_iterator I=P.begin(), E=P.end(); + I!=E; ++I) { + + if (const PathDiagnosticMacroPiece *MP = + dyn_cast(*I)) { + num = ProcessMacroPiece(os, *MP, num); + continue; + } + + if (PathDiagnosticEventPiece *EP = dyn_cast(*I)) { + os << "
" + "" + "
"; + EmitAlphaCounter(os, num++); + os << "
" + << html::EscapeText(EP->getString()) + << "
\n"; + } + } + + return num; +} + void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID, SourceRange Range, const char *HighlightStart, -- cgit v1.2.3