@@ -114,15 +114,15 @@ static void removeRedundantMsgs(PathPieces &path) {
114114 path.pop_front ();
115115
116116 switch (piece->getKind ()) {
117- case clang::ento:: PathDiagnosticPiece::Call:
117+ case PathDiagnosticPiece::Call:
118118 removeRedundantMsgs (cast<PathDiagnosticCallPiece>(piece)->path );
119119 break ;
120- case clang::ento:: PathDiagnosticPiece::Macro:
120+ case PathDiagnosticPiece::Macro:
121121 removeRedundantMsgs (cast<PathDiagnosticMacroPiece>(piece)->subPieces );
122122 break ;
123- case clang::ento:: PathDiagnosticPiece::ControlFlow:
123+ case PathDiagnosticPiece::ControlFlow:
124124 break ;
125- case clang::ento:: PathDiagnosticPiece::Event: {
125+ case PathDiagnosticPiece::Event: {
126126 if (i == N-1 )
127127 break ;
128128
@@ -142,6 +142,8 @@ static void removeRedundantMsgs(PathPieces &path) {
142142 }
143143 break ;
144144 }
145+ case PathDiagnosticPiece::Note:
146+ break ;
145147 }
146148 path.push_back (piece);
147149 }
@@ -199,6 +201,9 @@ static bool removeUnneededCalls(PathPieces &pieces, BugReport *R,
199201 }
200202 case PathDiagnosticPiece::ControlFlow:
201203 break ;
204+
205+ case PathDiagnosticPiece::Note:
206+ break ;
202207 }
203208
204209 pieces.push_back (piece);
@@ -2554,6 +2559,12 @@ BugReport::~BugReport() {
25542559 while (!interestingSymbols.empty ()) {
25552560 popInterestingSymbolsAndRegions ();
25562561 }
2562+
2563+ // FIXME: Replace Notes with a list of shared pointers.
2564+ for (const auto *P: Notes) {
2565+ delete P;
2566+ }
2567+ Notes.clear ();
25572568}
25582569
25592570const Decl *BugReport::getDeclWithIssue () const {
@@ -3405,25 +3416,28 @@ void BugReporter::FlushReport(BugReport *exampleReport,
34053416 exampleReport->getUniqueingLocation (),
34063417 exampleReport->getUniqueingDecl ()));
34073418
3408- MaxBugClassSize = std::max (bugReports.size (),
3409- static_cast <size_t >(MaxBugClassSize));
3419+ if (exampleReport->isPathSensitive ()) {
3420+ // Generate the full path diagnostic, using the generation scheme
3421+ // specified by the PathDiagnosticConsumer. Note that we have to generate
3422+ // path diagnostics even for consumers which do not support paths, because
3423+ // the BugReporterVisitors may mark this bug as a false positive.
3424+ assert (!bugReports.empty ());
3425+
3426+ MaxBugClassSize =
3427+ std::max (bugReports.size (), static_cast <size_t >(MaxBugClassSize));
34103428
3411- // Generate the full path diagnostic, using the generation scheme
3412- // specified by the PathDiagnosticConsumer. Note that we have to generate
3413- // path diagnostics even for consumers which do not support paths, because
3414- // the BugReporterVisitors may mark this bug as a false positive.
3415- if (!bugReports.empty ())
34163429 if (!generatePathDiagnostic (*D.get (), PD, bugReports))
34173430 return ;
34183431
3419- MaxValidBugClassSize = std::max (bugReports. size (),
3420- static_cast <size_t >(MaxValidBugClassSize));
3432+ MaxValidBugClassSize =
3433+ std::max (bugReports. size (), static_cast <size_t >(MaxValidBugClassSize));
34213434
3422- // Examine the report and see if the last piece is in a header. Reset the
3423- // report location to the last piece in the main source file.
3424- AnalyzerOptions& Opts = getAnalyzerOptions ();
3425- if (Opts.shouldReportIssuesInMainSourceFile () && !Opts.AnalyzeAll )
3426- D->resetDiagnosticLocationToMainFile ();
3435+ // Examine the report and see if the last piece is in a header. Reset the
3436+ // report location to the last piece in the main source file.
3437+ AnalyzerOptions &Opts = getAnalyzerOptions ();
3438+ if (Opts.shouldReportIssuesInMainSourceFile () && !Opts.AnalyzeAll )
3439+ D->resetDiagnosticLocationToMainFile ();
3440+ }
34273441
34283442 // If the path is empty, generate a single step path with the location
34293443 // of the issue.
@@ -3436,6 +3450,28 @@ void BugReporter::FlushReport(BugReport *exampleReport,
34363450 D->setEndOfPath (std::move (piece));
34373451 }
34383452
3453+ PathPieces &Pieces = D->getMutablePieces ();
3454+ bool ShouldConvert = getAnalyzerOptions ().shouldDisplayNotesAsEvents ();
3455+ // For path diagnostic consumers that don't support extra notes,
3456+ // we may optionally convert those to path notes.
3457+ for (auto I = exampleReport->getNotes ().rbegin (),
3458+ E = exampleReport->getNotes ().rend (); I != E; ++I) {
3459+ const PathDiagnosticNotePiece *Piece = *I;
3460+ // FIXME: getNotes() was supposed to return a list of shared pointers,
3461+ // and then we wouldn't normally create a new piece here,
3462+ // unless ShouldConvert is set.
3463+ PathDiagnosticPiece *ConvertedPiece =
3464+ ShouldConvert
3465+ ? static_cast <PathDiagnosticPiece *>(new PathDiagnosticEventPiece (
3466+ Piece->getLocation (), Piece->getString ()))
3467+ : static_cast <PathDiagnosticPiece *>(new PathDiagnosticNotePiece (
3468+ Piece->getLocation (), Piece->getString ()));
3469+ for (const auto &R : Piece->getRanges ())
3470+ ConvertedPiece->addRange (R);
3471+
3472+ Pieces.push_front (ConvertedPiece);
3473+ }
3474+
34393475 // Get the meta data.
34403476 const BugReport::ExtraTextList &Meta = exampleReport->getExtraText ();
34413477 for (BugReport::ExtraTextList::const_iterator i = Meta.begin (),
@@ -3520,6 +3556,13 @@ LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
35203556 // FIXME: Print which macro is being invoked.
35213557}
35223558
3559+ LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump () const {
3560+ llvm::errs () << " NOTE\n --------------\n " ;
3561+ llvm::errs () << getString () << " \n " ;
3562+ llvm::errs () << " ---- at ----\n " ;
3563+ getLocation ().dump ();
3564+ }
3565+
35233566LLVM_DUMP_METHOD void PathDiagnosticLocation::dump () const {
35243567 if (!isValid ()) {
35253568 llvm::errs () << " <INVALID>\n " ;
0 commit comments