diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-03-10 05:16:17 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-03-10 05:16:17 +0000 |
commit | 0e5c8d4ca6c7e472ddde13495c8d3558983de85a (patch) | |
tree | 8b1bb76cc882b981616b3e238d38bf822c698a79 /lib/Frontend/HTMLDiagnostics.cpp | |
parent | 2223622d113d7cba04c2dfdbe032e2ba6ba10bc4 (diff) | |
download | clang-0e5c8d4ca6c7e472ddde13495c8d3558983de85a.tar.gz |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66524 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend/HTMLDiagnostics.cpp')
-rw-r--r-- | lib/Frontend/HTMLDiagnostics.cpp | 184 |
1 files changed, 135 insertions, 49 deletions
diff --git a/lib/Frontend/HTMLDiagnostics.cpp b/lib/Frontend/HTMLDiagnostics.cpp index 02b327db2a..0b266cda0f 100644 --- a/lib/Frontend/HTMLDiagnostics.cpp +++ b/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<tr><td class=\"num\"></td><td class=\"line\"><div id=\""; + + if (num == max) + os << "EndPath"; + else + os << "Path" << num; + + os << "\" class=\"msg"; + if (Kind) + os << " msg" << Kind; + os << "\" style=\"margin-left:" << PosNo << "ex"; + + // Output a maximum size. + if (!isa<PathDiagnosticMacroPiece>(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 << "<table class=\"msgT\"><tr><td valign=\"top\">"; + os << "<div class=\"PathIndex"; + if (Kind) os << " PathIndex" << Kind; + os << "\">" << num << "</div>"; + os << "</td><td>"; + } + + if (const PathDiagnosticMacroPiece *MP = + dyn_cast<PathDiagnosticMacroPiece>(&P)) { + + os << "Within the expansion of the macro '"; - std::string sbuf; - llvm::raw_string_ostream os(sbuf); - - os << "\n<tr><td class=\"num\"></td><td class=\"line\"><div id=\""; - - if (num == max) - os << "EndPath"; - else - os << "Path" << num; - - os << "\" class=\"msg"; - if (Kind) os << " msg" << Kind; - os << "\" style=\"margin-left:" << PosNo << "ex"; - if (em < max_line/2) os << "; max-width:" << em << "em"; - os << "\">"; - - if (max > 1) { - os << "<table class=\"msgT\"><tr><td valign=\"top\">"; - os << "<div class=\"PathIndex"; - if (Kind) os << " PathIndex" << Kind; - os << "\">" << num << "</div>"; - os << "</td><td>"; + // Get the name of the macro by relexing it. + { + FullSourceLoc L = MP->getLocation().getInstantiationLoc(); + assert(L.isFileID()); + std::pair<const char*, const char*> 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 << "</td></tr></table>"; - } - - os << "</div></td></tr>"; - // 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 << "</td></tr></table>"; } - // Now highlight the ranges. - + os << "</div></td></tr>"; + + // 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<char, 10> buf; + + do { + unsigned x = n % ('z' - 'a'); + buf.push_back('a' + x); + n = n / ('z' - 'a'); + } while (n); + + assert(!buf.empty()); + + for (llvm::SmallVectorImpl<char>::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<PathDiagnosticMacroPiece>(*I)) { + num = ProcessMacroPiece(os, *MP, num); + continue; + } + + if (PathDiagnosticEventPiece *EP = dyn_cast<PathDiagnosticEventPiece>(*I)) { + os << "<div class=\"msg msgEvent\" style=\"width:94%; " + "margin-left:5px\">" + "<table class=\"msgT\"><tr>" + "<td valign=\"top\"><div class=\"PathIndex PathIndexEvent\">"; + EmitAlphaCounter(os, num++); + os << "</div></td><td valign=\"top\">" + << html::EscapeText(EP->getString()) + << "</td></tr></table></div>\n"; + } + } + + return num; +} + void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID, SourceRange Range, const char *HighlightStart, |