Index: clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -91,8 +91,7 @@ unsigned num); void HandlePiece(Rewriter &R, FileID BugFileID, const PathDiagnosticPiece &P, - const std::vector &PopUpRanges, unsigned num, - unsigned max); + unsigned num, unsigned max); void HighlightRange(Rewriter& R, FileID BugFileID, SourceRange Range, const char *HighlightStart = "", @@ -607,50 +606,31 @@ )<<<"; } -static void -HandlePopUpPieceStartTag(Rewriter &R, - const std::vector &PopUpRanges) { - for (const auto &Range : PopUpRanges) { - html::HighlightRange(R, Range.getBegin(), Range.getEnd(), "", - "", - /*IsTokenRange=*/true); - } -} - -static void HandlePopUpPieceEndTag(Rewriter &R, - const PathDiagnosticPopUpPiece &Piece, - std::vector &PopUpRanges, - unsigned int LastReportedPieceIndex, - unsigned int PopUpPieceIndex) { +static void HandlePopUpPieceTag(Rewriter &R, + const PathDiagnosticPopUpPiece &Piece, + unsigned int LastReportedPieceIndex, + unsigned int PopUpPieceIndex) { SmallString<256> Buf; llvm::raw_svector_ostream Out(Buf); SourceRange Range(Piece.getLocation().asRange()); + if (Range.getBegin().isMacroID() || Range.getEnd().isMacroID()) + return; // Write out the path indices with a right arrow and the message as a row. - Out << "
" + Out << ""; + Out << "" + << "
" + "
" << LastReportedPieceIndex; // Also annotate the state transition with extra indices. Out << '.' << PopUpPieceIndex; - Out << "
" << Piece.getString() << "
" << Piece.getString() << "
"; - // If no report made at this range mark the variable and add the end tags. - if (std::find(PopUpRanges.begin(), PopUpRanges.end(), Range) == - PopUpRanges.end()) { - // Store that we create a report at this range. - PopUpRanges.push_back(Range); - - Out << "
"; - html::HighlightRange(R, Range.getBegin(), Range.getEnd(), - "", Buf.c_str(), - /*IsTokenRange=*/true); - } else { - // Otherwise inject just the new row at the end of the range. - html::HighlightRange(R, Range.getBegin(), Range.getEnd(), "", Buf.c_str(), - /*IsTokenRange=*/true); - } + html::HighlightRange(R, Range.getBegin(), Range.getEnd(), + "", Buf.c_str(), + /*IsTokenRange=*/true); } void HTMLDiagnostics::RewriteFile(Rewriter &R, @@ -674,7 +654,6 @@ std::map IndexMap; // Stores the different ranges where we have reported something. - std::vector PopUpRanges; for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) { const auto &Piece = *I->get(); @@ -684,17 +663,26 @@ // This adds diagnostic bubbles, but not navigation. // Navigation through note pieces would be added later, // as a separate pass through the piece list. - HandlePiece(R, FID, Piece, PopUpRanges, NumNotePieces, TotalNotePieces); + HandlePiece(R, FID, Piece, NumNotePieces, TotalNotePieces); --NumNotePieces; } else { - HandlePiece(R, FID, Piece, PopUpRanges, NumRegularPieces, - TotalRegularPieces); + HandlePiece(R, FID, Piece, NumRegularPieces, TotalRegularPieces); --NumRegularPieces; } } + // Add line numbers, header, footer, etc. + html::EscapeText(R, FID); + html::AddLineNumbers(R, FID); + + // If we have a preprocessor, relex the file and syntax highlight. + // We might not have a preprocessor if we come from a deserialized AST file, + // for example. + html::SyntaxHighlight(R, FID, PP); + html::HighlightMacros(R, FID, PP); + // Secondary indexing if we are having multiple pop-ups between two notes. - // (e.g. [(13) 'a' is 'true']; [(13.1) 'b' is 'false']; [(13.2) 'c' is...) + // (e.g. [(13) 'a' is 'true']; [(13.1) 'b' is 'false']; [(13.2) 'c' is...]) NumRegularPieces = TotalRegularPieces; for (auto I = path.rbegin(), E = path.rend(); I != E; ++I) { const auto &Piece = *I->get(); @@ -707,8 +695,7 @@ // This marks the variable, adds the end tag and the message // (list element) as a row. The start tag will be added after the // rows has been written out. Note: It stores every different range. - HandlePopUpPieceEndTag(R, *PopUpP, PopUpRanges, NumRegularPieces, - PopUpPieceIndex); + HandlePopUpPieceTag(R, *PopUpP, NumRegularPieces, PopUpPieceIndex); if (PopUpPieceIndex > 0) --IndexMap[NumRegularPieces]; @@ -717,24 +704,10 @@ --NumRegularPieces; } } - - // Add the
start tag of pop-up pieces based on the stored ranges. - HandlePopUpPieceStartTag(R, PopUpRanges); - - // Add line numbers, header, footer, etc. - html::EscapeText(R, FID); - html::AddLineNumbers(R, FID); - - // If we have a preprocessor, relex the file and syntax highlight. - // We might not have a preprocessor if we come from a deserialized AST file, - // for example. - html::SyntaxHighlight(R, FID, PP); - html::HighlightMacros(R, FID, PP); } void HTMLDiagnostics::HandlePiece(Rewriter &R, FileID BugFileID, const PathDiagnosticPiece &P, - const std::vector &PopUpRanges, unsigned num, unsigned max) { // For now, just draw a box above the line in question, and emit the // warning. @@ -870,7 +843,7 @@ << (num - 1) << "\" title=\"Previous event (" << (num - 1) - << ")\">←"; + << ")\">←"; } os << " +// CHECK-NOT: +// CHECK-SAME: +// CHECK-SAME: MACRO +// CHECK-SAME: +// CHECK-SAME: if (b) +// CHECK-SAME: +// CHECK-SAME: Index: clang/test/Analysis/html_diagnostics/variable-popups.c =================================================================== --- /dev/null +++ clang/test/Analysis/html_diagnostics/variable-popups.c @@ -0,0 +1,23 @@ +// RUN: rm -fR %t +// RUN: mkdir %t +// RUN: %clang_analyze_cc1 -analyzer-checker=core \ +// RUN: -analyzer-output=html -o %t -verify %s +// RUN: cat %t/report-*.html | FileCheck %s + +void bar(int); + +void foo2() { + int a; + int b = 1; + if (b) + bar(a); // expected-warning{{1st function call argument is an uninitialized value}} +} + +// CHECK: b +// CHECK-SAME:
"; @@ -947,14 +920,8 @@ // Now highlight the ranges. ArrayRef Ranges = P.getRanges(); - for (const auto &Range : Ranges) { - // If we have already highlighted the range as a pop-up there is no work. - if (std::find(PopUpRanges.begin(), PopUpRanges.end(), Range) != - PopUpRanges.end()) - continue; - + for (const auto &Range : Ranges) HighlightRange(R, LPosInfo.first, Range); - } } static void EmitAlphaCounter(raw_ostream &os, unsigned n) { Index: clang/test/Analysis/html_diagnostics/td-hotfix.c =================================================================== --- /dev/null +++ clang/test/Analysis/html_diagnostics/td-hotfix.c @@ -0,0 +1,31 @@ +// RUN: rm -fR %t +// RUN: mkdir %t +// RUN: %clang_analyze_cc1 -analyzer-checker=core \ +// RUN: -analyzer-output=html -o %t -verify %s +// RUN: cat %t/report-*.html | FileCheck %s + +void bar(int); + +void foo() { + int a; + bar(a); // expected-warning{{1st function call argument is an uninitialized value}} +} + +// CHECK-LABEL:
+// CHECK-SAME: +// CHECK-SAME: +// CHECK-SAME: +// CHECK-SAME: +// CHECK-NOT: +// CHECK-SAME: +// CHECK-SAME: +// CHECK-SAME:
+// CHECK-SAME:
2
+// CHECK-SAME:
+// CHECK-SAME:
+// CHECK-SAME: +// CHECK-SAME:
+// CHECK-SAME:
+// CHECK-SAME: 1st function call argument is an uninitialized value +// CHECK-SAME:
+// CHECK-SAME:
Index: clang/test/Analysis/html_diagnostics/variable-popups-2.c =================================================================== --- /dev/null +++ clang/test/Analysis/html_diagnostics/variable-popups-2.c @@ -0,0 +1,28 @@ +// RUN: rm -fR %t +// RUN: mkdir %t +// RUN: %clang_analyze_cc1 -analyzer-checker=core \ +// RUN: -analyzer-output=html -o %t -verify %s +// RUN: cat %t/report-*.html | FileCheck %s + +void bar(int); + +#define MACRO if (b) + +void foo2() { + int a; + int b = 1; + MACRO + bar(a); // expected-warning{{1st function call argument is an uninitialized value}} +} + +// For now we don't emit popups inside macros due to UI limitations. +// Once we do, we should test it thoroughly. + +// CHECK-LABEL:
+// CHECK-SAME: +// CHECK-SAME: +// CHECK-SAME:
+// CHECK-SAME:
1.1
+// CHECK-SAME:
'b' is 1
+// CHECK-SAME: