diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/BugReporter.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 260 |
1 files changed, 146 insertions, 114 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index f5d747c7fdd..331d7379577 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -71,6 +71,7 @@ using namespace clang; using namespace ento; +using namespace llvm; #define DEBUG_TYPE "BugReporter" @@ -131,7 +132,8 @@ public: public: PathDiagnosticConstruct(const PathDiagnosticConsumer *PDC, - const ExplodedNode *ErrorNode, const BugReport *R); + const ExplodedNode *ErrorNode, + const PathSensitiveBugReport *R); /// \returns the location context associated with the current position in the /// bug path. @@ -202,7 +204,7 @@ class PathDiagnosticBuilder : public BugReporterContext { /// them being the last entities being able to modify it (for example, /// changing interestingness here would cause inconsistencies as to how this /// file and visitors construct diagnostics), hence its const. - const BugReport *R; + const PathSensitiveBugReport *R; /// The leaf of the bug path. This isn't the same as the bug reports error /// node, which refers to the *original* graph, not the bug path. const ExplodedNode *const ErrorNode; @@ -215,12 +217,12 @@ public: /// a PathDiagnosticBuilder able to construct bug reports for different /// consumers. Returns None if no valid report is found. static Optional<PathDiagnosticBuilder> - findValidReport(ArrayRef<BugReport *> &bugReports, + findValidReport(ArrayRef<PathSensitiveBugReport *> &bugReports, PathSensitiveBugReporter &Reporter); PathDiagnosticBuilder( BugReporterContext BRC, std::unique_ptr<ExplodedGraph> BugPath, - BugReport *r, const ExplodedNode *ErrorNode, + PathSensitiveBugReport *r, const ExplodedNode *ErrorNode, std::unique_ptr<VisitorsDiagnosticsTy> VisitorsDiagnostics); /// This function is responsible for generating diagnostic pieces that are @@ -262,7 +264,7 @@ private: ExecutionContinues(llvm::raw_string_ostream &os, const PathDiagnosticConstruct &C) const; - const BugReport *getBugReport() const { return R; } + const PathSensitiveBugReport *getBugReport() const { return R; } }; } // namespace @@ -369,7 +371,8 @@ static void removeRedundantMsgs(PathPieces &path) { /// that aren't needed. Return true if afterwards the path contains /// "interesting stuff" which means it shouldn't be pruned from the parent path. static bool removeUnneededCalls(const PathDiagnosticConstruct &C, - PathPieces &pieces, const BugReport *R, + PathPieces &pieces, + const PathSensitiveBugReport *R, bool IsInteresting = false) { bool containsSomethingInteresting = IsInteresting; const unsigned N = pieces.size(); @@ -1263,13 +1266,23 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode( } static std::unique_ptr<PathDiagnostic> -generateEmptyDiagnosticForReport(const BugReport *R, const SourceManager &SM) { +generateDiagnosticForBasicReport(const BasicBugReport *R) { const BugType &BT = R->getBugType(); return std::make_unique<PathDiagnostic>( - R->getBugType().getCheckName(), R->getDeclWithIssue(), - R->getBugType().getName(), R->getDescription(), - R->getShortDescription(/*UseFallback=*/false), BT.getCategory(), - R->getUniqueingLocation(), R->getUniqueingDecl(), + BT.getCheckName(), R->getDeclWithIssue(), BT.getName(), + R->getDescription(), R->getShortDescription(/*UseFallback=*/false), + BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(), + std::make_unique<FilesToLineNumsMap>()); +} + +static std::unique_ptr<PathDiagnostic> +generateEmptyDiagnosticForReport(const PathSensitiveBugReport *R, + const SourceManager &SM) { + const BugType &BT = R->getBugType(); + return std::make_unique<PathDiagnostic>( + BT.getCheckName(), R->getDeclWithIssue(), BT.getName(), + R->getDescription(), R->getShortDescription(/*UseFallback=*/false), + BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(), findExecutedLines(SM, R->getErrorNode())); } @@ -1909,7 +1922,7 @@ static void updateExecutedLinesWithDiagnosticPieces(PathDiagnostic &PD) { PathDiagnosticConstruct::PathDiagnosticConstruct( const PathDiagnosticConsumer *PDC, const ExplodedNode *ErrorNode, - const BugReport *R) + const PathSensitiveBugReport *R) : Consumer(PDC), CurrentNode(ErrorNode), SM(CurrentNode->getCodeDecl().getASTContext().getSourceManager()), PD(generateEmptyDiagnosticForReport(R, getSourceManager())) { @@ -1918,7 +1931,7 @@ PathDiagnosticConstruct::PathDiagnosticConstruct( PathDiagnosticBuilder::PathDiagnosticBuilder( BugReporterContext BRC, std::unique_ptr<ExplodedGraph> BugPath, - BugReport *r, const ExplodedNode *ErrorNode, + PathSensitiveBugReport *r, const ExplodedNode *ErrorNode, std::unique_ptr<VisitorsDiagnosticsTy> VisitorsDiagnostics) : BugReporterContext(BRC), BugPath(std::move(BugPath)), R(r), ErrorNode(ErrorNode), @@ -1929,7 +1942,6 @@ PathDiagnosticBuilder::generate(const PathDiagnosticConsumer *PDC) const { PathDiagnosticConstruct Construct(PDC, ErrorNode, R); const SourceManager &SM = getSourceManager(); - const BugReport *R = getBugReport(); const AnalyzerOptions &Opts = getAnalyzerOptions(); StringRef ErrorTag = ErrorNode->getLocation().getTag()->getTagDescription(); @@ -2050,7 +2062,8 @@ void BuiltinBug::anchor() {} // Methods for BugReport and subclasses. //===----------------------------------------------------------------------===// -void BugReport::addVisitor(std::unique_ptr<BugReporterVisitor> visitor) { +void PathSensitiveBugReport::addVisitor( + std::unique_ptr<BugReporterVisitor> visitor) { if (!visitor) return; @@ -2065,14 +2078,11 @@ void BugReport::addVisitor(std::unique_ptr<BugReporterVisitor> visitor) { Callbacks.push_back(std::move(visitor)); } -void BugReport::clearVisitors() { +void PathSensitiveBugReport::clearVisitors() { Callbacks.clear(); } -const Decl *BugReport::getDeclWithIssue() const { - if (DeclWithIssue) - return DeclWithIssue; - +const Decl *PathSensitiveBugReport::getDeclWithIssue() const { const ExplodedNode *N = getErrorNode(); if (!N) return nullptr; @@ -2081,14 +2091,28 @@ const Decl *BugReport::getDeclWithIssue() const { return LC->getStackFrame()->getDecl(); } -void BugReport::Profile(llvm::FoldingSetNodeID& hash) const { +void BasicBugReport::Profile(llvm::FoldingSetNodeID& hash) const { + hash.AddInteger(static_cast<int>(getKind())); + hash.AddPointer(&BT); + hash.AddString(Description); + assert(Location.isValid()); + Location.Profile(hash); + + for (SourceRange range : Ranges) { + if (!range.isValid()) + continue; + hash.AddInteger(range.getBegin().getRawEncoding()); + hash.AddInteger(range.getEnd().getRawEncoding()); + } +} + +void PathSensitiveBugReport::Profile(llvm::FoldingSetNodeID &hash) const { + hash.AddInteger(static_cast<int>(getKind())); hash.AddPointer(&BT); hash.AddString(Description); PathDiagnosticLocation UL = getUniqueingLocation(); if (UL.isValid()) { UL.Profile(hash); - } else if (Location.isValid()) { - Location.Profile(hash); } else { assert(ErrorNode); hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); @@ -2131,8 +2155,8 @@ static void insertToInterestingnessMap( "have, if it was already marked as interesting with a different kind!"); } -void BugReport::markInteresting(SymbolRef sym, - bugreporter::TrackingKind TKind) { +void PathSensitiveBugReport::markInteresting(SymbolRef sym, + bugreporter::TrackingKind TKind) { if (!sym) return; @@ -2142,8 +2166,8 @@ void BugReport::markInteresting(SymbolRef sym, markInteresting(meta->getRegion(), TKind); } -void BugReport::markInteresting(const MemRegion *R, - bugreporter::TrackingKind TKind) { +void PathSensitiveBugReport::markInteresting(const MemRegion *R, + bugreporter::TrackingKind TKind) { if (!R) return; @@ -2154,19 +2178,20 @@ void BugReport::markInteresting(const MemRegion *R, markInteresting(SR->getSymbol(), TKind); } -void BugReport::markInteresting(SVal V, bugreporter::TrackingKind TKind) { +void PathSensitiveBugReport::markInteresting(SVal V, + bugreporter::TrackingKind TKind) { markInteresting(V.getAsRegion(), TKind); markInteresting(V.getAsSymbol(), TKind); } -void BugReport::markInteresting(const LocationContext *LC) { +void PathSensitiveBugReport::markInteresting(const LocationContext *LC) { if (!LC) return; InterestingLocationContexts.insert(LC); } Optional<bugreporter::TrackingKind> -BugReport::getInterestingnessKind(SVal V) const { +PathSensitiveBugReport::getInterestingnessKind(SVal V) const { auto RKind = getInterestingnessKind(V.getAsRegion()); auto SKind = getInterestingnessKind(V.getAsSymbol()); if (!RKind) @@ -2191,7 +2216,7 @@ BugReport::getInterestingnessKind(SVal V) const { } Optional<bugreporter::TrackingKind> -BugReport::getInterestingnessKind(SymbolRef sym) const { +PathSensitiveBugReport::getInterestingnessKind(SymbolRef sym) const { if (!sym) return None; // We don't currently consider metadata symbols to be interesting @@ -2203,7 +2228,7 @@ BugReport::getInterestingnessKind(SymbolRef sym) const { } Optional<bugreporter::TrackingKind> -BugReport::getInterestingnessKind(const MemRegion *R) const { +PathSensitiveBugReport::getInterestingnessKind(const MemRegion *R) const { if (!R) return None; @@ -2217,25 +2242,25 @@ BugReport::getInterestingnessKind(const MemRegion *R) const { return None; } -bool BugReport::isInteresting(SVal V) const { +bool PathSensitiveBugReport::isInteresting(SVal V) const { return getInterestingnessKind(V).hasValue(); } -bool BugReport::isInteresting(SymbolRef sym) const { +bool PathSensitiveBugReport::isInteresting(SymbolRef sym) const { return getInterestingnessKind(sym).hasValue(); } -bool BugReport::isInteresting(const MemRegion *R) const { +bool PathSensitiveBugReport::isInteresting(const MemRegion *R) const { return getInterestingnessKind(R).hasValue(); } -bool BugReport::isInteresting(const LocationContext *LC) const { +bool PathSensitiveBugReport::isInteresting(const LocationContext *LC) const { if (!LC) return false; return InterestingLocationContexts.count(LC); } -const Stmt *BugReport::getStmt() const { +const Stmt *PathSensitiveBugReport::getStmt() const { if (!ErrorNode) return nullptr; @@ -2253,31 +2278,19 @@ const Stmt *BugReport::getStmt() const { return S; } -llvm::iterator_range<BugReport::ranges_iterator> BugReport::getRanges() const { +ArrayRef<SourceRange> +PathSensitiveBugReport::getRanges() const { // If no custom ranges, add the range of the statement corresponding to // the error node. - if (Ranges.empty()) { - if (dyn_cast_or_null<Expr>(getStmt())) - return llvm::make_range(&ErrorNodeRange, &ErrorNodeRange + 1); - return llvm::make_range(ranges_iterator(), ranges_iterator()); - } + if (Ranges.empty() && isa_and_nonnull<Expr>(getStmt())) + return ErrorNodeRange; - // User-specified absence of range info. - if (Ranges.size() == 1 && !Ranges.begin()->isValid()) - return llvm::make_range(ranges_iterator(), ranges_iterator()); - - return llvm::make_range(Ranges.begin(), Ranges.end()); + return Ranges; } -PathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { - if (ErrorNode) { - assert(!Location.isValid() && - "Either Location or ErrorNode should be specified but not both."); - return PathDiagnosticLocation::createEndOfPath(ErrorNode, SM); - } - - assert(Location.isValid()); - return Location; +PathDiagnosticLocation +PathSensitiveBugReport::getLocation() const { + return PathDiagnosticLocation::createEndOfPath(ErrorNode); } //===----------------------------------------------------------------------===// @@ -2326,7 +2339,7 @@ namespace { class BugPathInfo { public: std::unique_ptr<ExplodedGraph> BugPath; - BugReport *Report; + PathSensitiveBugReport *Report; const ExplodedNode *ErrorNode; }; @@ -2342,7 +2355,8 @@ class BugPathGetter { /// Since the getErrorNode() or BugReport refers to the original ExplodedGraph, /// we need to pair it to the error node of the constructed trimmed graph. - using ReportNewNodePair = std::pair<BugReport *, const ExplodedNode *>; + using ReportNewNodePair = + std::pair<PathSensitiveBugReport *, const ExplodedNode *>; SmallVector<ReportNewNodePair, 32> ReportNodes; BugPathInfo CurrentBugPath; @@ -2377,7 +2391,7 @@ class BugPathGetter { public: BugPathGetter(const ExplodedGraph *OriginalGraph, - ArrayRef<BugReport *> &bugReports); + ArrayRef<PathSensitiveBugReport *> &bugReports); BugPathInfo *getNextBugPath(); }; @@ -2385,7 +2399,7 @@ public: } // namespace BugPathGetter::BugPathGetter(const ExplodedGraph *OriginalGraph, - ArrayRef<BugReport *> &bugReports) { + ArrayRef<PathSensitiveBugReport *> &bugReports) { SmallVector<const ExplodedNode *, 32> Nodes; for (const auto I : bugReports) { assert(I->isValid() && @@ -2404,7 +2418,7 @@ BugPathGetter::BugPathGetter(const ExplodedGraph *OriginalGraph, // in the new graph. llvm::SmallPtrSet<const ExplodedNode *, 32> RemainingNodes; - for (BugReport *Report : bugReports) { + for (PathSensitiveBugReport *Report : bugReports) { const ExplodedNode *NewNode = ForwardMap.lookup(Report->getErrorNode()); assert(NewNode && "Failed to construct a trimmed graph that contains this error " @@ -2592,11 +2606,12 @@ static void CompactMacroExpandedPieces(PathPieces &path, /// Notes associated with {@code ErrorNode} are generated using /// {@code getEndPath}, and the rest are generated with {@code VisitNode}. static std::unique_ptr<VisitorsDiagnosticsTy> -generateVisitorsDiagnostics(BugReport *R, const ExplodedNode *ErrorNode, +generateVisitorsDiagnostics(PathSensitiveBugReport *R, + const ExplodedNode *ErrorNode, BugReporterContext &BRC) { std::unique_ptr<VisitorsDiagnosticsTy> Notes = std::make_unique<VisitorsDiagnosticsTy>(); - BugReport::VisitorList visitors; + PathSensitiveBugReport::VisitorList visitors; // Run visitors on all nodes starting from the node *before* the last one. // The last node is reserved for notes generated with {@code getEndPath}. @@ -2646,15 +2661,15 @@ generateVisitorsDiagnostics(BugReport *R, const ExplodedNode *ErrorNode, return Notes; } -Optional<PathDiagnosticBuilder> -PathDiagnosticBuilder::findValidReport(ArrayRef<BugReport *> &bugReports, - PathSensitiveBugReporter &Reporter) { +Optional<PathDiagnosticBuilder> PathDiagnosticBuilder::findValidReport( + ArrayRef<PathSensitiveBugReport *> &bugReports, + PathSensitiveBugReporter &Reporter) { BugPathGetter BugGraph(&Reporter.getGraph(), bugReports); while (BugPathInfo *BugPath = BugGraph.getNextBugPath()) { // Find the BugReport with the original location. - BugReport *R = BugPath->Report; + PathSensitiveBugReport *R = BugPath->Report; assert(R && "No original report found for sliced graph."); assert(R->isValid() && "Report selected by trimmed graph marked invalid."); const ExplodedNode *ErrorNode = BugPath->ErrorNode; @@ -2700,7 +2715,7 @@ PathDiagnosticBuilder::findValidReport(ArrayRef<BugReport *> &bugReports, std::unique_ptr<DiagnosticForConsumerMapTy> PathSensitiveBugReporter::generatePathDiagnostics( ArrayRef<PathDiagnosticConsumer *> consumers, - ArrayRef<BugReport *> &bugReports) { + ArrayRef<PathSensitiveBugReport *> &bugReports) { assert(!bugReports.empty()); auto Out = std::make_unique<DiagnosticForConsumerMapTy>(); @@ -2720,24 +2735,7 @@ PathSensitiveBugReporter::generatePathDiagnostics( } void BugReporter::emitReport(std::unique_ptr<BugReport> R) { - if (const ExplodedNode *E = R->getErrorNode()) { - // An error node must either be a sink or have a tag, otherwise - // it could get reclaimed before the path diagnostic is created. - assert((E->isSink() || E->getLocation().getTag()) && - "Error node must either be a sink or have a tag"); - - const AnalysisDeclContext *DeclCtx = - E->getLocationContext()->getAnalysisDeclContext(); - // The source of autosynthesized body can be handcrafted AST or a model - // file. The locations from handcrafted ASTs have no valid source locations - // and have to be discarded. Locations from model files should be preserved - // for processing and reporting. - if (DeclCtx->isBodyAutosynthesized() && - !DeclCtx->isBodyAutosynthesizedFromModelFile()) - return; - } - - bool ValidSourceLoc = R->getLocation(getSourceManager()).isValid(); + bool ValidSourceLoc = R->getLocation().isValid(); assert(ValidSourceLoc); // If we mess up in a release build, we'd still prefer to just drop the bug // instead of trying to go on. @@ -2760,6 +2758,28 @@ void BugReporter::emitReport(std::unique_ptr<BugReport> R) { EQ->AddReport(std::move(R)); } +void PathSensitiveBugReporter::emitReport(std::unique_ptr<BugReport> R) { + if (auto PR = dyn_cast<PathSensitiveBugReport>(R.get())) + if (const ExplodedNode *E = PR->getErrorNode()) { + // An error node must either be a sink or have a tag, otherwise + // it could get reclaimed before the path diagnostic is created. + assert((E->isSink() || E->getLocation().getTag()) && + "Error node must either be a sink or have a tag"); + + const AnalysisDeclContext *DeclCtx = + E->getLocationContext()->getAnalysisDeclContext(); + // The source of autosynthesized body can be handcrafted AST or a model + // file. The locations from handcrafted ASTs have no valid source + // locations and have to be discarded. Locations from model files should + // be preserved for processing and reporting. + if (DeclCtx->isBodyAutosynthesized() && + !DeclCtx->isBodyAutosynthesizedFromModelFile()) + return; + } + + BugReporter::emitReport(std::move(R)); +} + //===----------------------------------------------------------------------===// // Emitting reports in equivalence classes. //===----------------------------------------------------------------------===// @@ -2776,9 +2796,8 @@ struct FRIEC_WLItem { } // namespace -static BugReport * -FindReportInEquivalenceClass(BugReportEquivClass& EQ, - SmallVectorImpl<BugReport*> &bugReports) { +BugReport *PathSensitiveBugReporter::findReportInEquivalenceClass( + BugReportEquivClass &EQ, SmallVectorImpl<BugReport *> &bugReports) { BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); assert(I != E); const BugType& BT = I->getBugType(); @@ -2789,10 +2808,9 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ, if (!BT.isSuppressOnSink()) { BugReport *R = &*I; for (auto &I : EQ) { - const ExplodedNode *N = I.getErrorNode(); - if (N) { - R = &I; - bugReports.push_back(R); + if (auto *PR = dyn_cast<PathSensitiveBugReport>(&I)) { + R = PR; + bugReports.push_back(PR); } } return R; @@ -2807,19 +2825,20 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ, BugReport *exampleReport = nullptr; for (; I != E; ++I) { - const ExplodedNode *errorNode = I->getErrorNode(); - - if (!errorNode) + auto *R = dyn_cast<PathSensitiveBugReport>(&*I); + if (!R) continue; + + const ExplodedNode *errorNode = R->getErrorNode(); if (errorNode->isSink()) { llvm_unreachable( "BugType::isSuppressSink() should not be 'true' for sink end nodes"); } // No successors? By definition this nodes isn't post-dominated by a sink. if (errorNode->succ_empty()) { - bugReports.push_back(&*I); + bugReports.push_back(R); if (!exampleReport) - exampleReport = &*I; + exampleReport = R; continue; } @@ -2852,9 +2871,9 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ, if (Succ->succ_empty()) { // If we found an end-of-path node that is not a sink. if (!Succ->isSink()) { - bugReports.push_back(&*I); + bugReports.push_back(R); if (!exampleReport) - exampleReport = &*I; + exampleReport = R; WL.clear(); break; } @@ -2885,7 +2904,7 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ, void BugReporter::FlushReport(BugReportEquivClass& EQ) { SmallVector<BugReport*, 10> bugReports; - BugReport *report = FindReportInEquivalenceClass(EQ, bugReports); + BugReport *report = findReportInEquivalenceClass(EQ, bugReports); if (!report) return; @@ -2900,7 +2919,7 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) { // If the path is empty, generate a single step path with the location // of the issue. if (PD->path.empty()) { - PathDiagnosticLocation L = report->getLocation(getSourceManager()); + PathDiagnosticLocation L = report->getLocation(); auto piece = std::make_unique<PathDiagnosticEventPiece>( L, report->getDescription()); for (SourceRange Range : report->getRanges()) @@ -3015,16 +3034,24 @@ findExecutedLines(const SourceManager &SM, const ExplodedNode *N) { std::unique_ptr<DiagnosticForConsumerMapTy> BugReporter::generateDiagnosticForConsumerMap( - BugReport *report, ArrayRef<PathDiagnosticConsumer *> consumers, + BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers, ArrayRef<BugReport *> bugReports) { + auto *basicReport = cast<BasicBugReport>(exampleReport); + auto Out = std::make_unique<DiagnosticForConsumerMapTy>(); + for (auto *Consumer : consumers) + (*Out)[Consumer] = generateDiagnosticForBasicReport(basicReport); + return Out; +} - if (!report->isPathSensitive()) { - auto Out = std::make_unique<DiagnosticForConsumerMapTy>(); - for (auto *Consumer : consumers) - (*Out)[Consumer] = generateEmptyDiagnosticForReport(report, - getSourceManager()); - return Out; - } +std::unique_ptr<DiagnosticForConsumerMapTy> +PathSensitiveBugReporter::generateDiagnosticForConsumerMap( + BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers, + ArrayRef<BugReport *> bugReports) { + std::vector<BasicBugReport *> BasicBugReports; + std::vector<PathSensitiveBugReport *> PathSensitiveBugReports; + if (isa<BasicBugReport>(exampleReport)) + return BugReporter::generateDiagnosticForConsumerMap(exampleReport, + consumers, bugReports); // Generate the full path sensitive diagnostic, using the generation scheme // specified by the PathDiagnosticConsumer. Note that we have to generate @@ -3032,8 +3059,13 @@ BugReporter::generateDiagnosticForConsumerMap( // the BugReporterVisitors may mark this bug as a false positive. assert(!bugReports.empty()); MaxBugClassSize.updateMax(bugReports.size()); - std::unique_ptr<DiagnosticForConsumerMapTy> Out = - generatePathDiagnostics(consumers, bugReports); + + // Avoid copying the whole array because there may be a lot of reports. + ArrayRef<PathSensitiveBugReport *> convertedArrayOfReports( + reinterpret_cast<PathSensitiveBugReport *const *>(&*bugReports.begin()), + reinterpret_cast<PathSensitiveBugReport *const *>(&*bugReports.end())); + std::unique_ptr<DiagnosticForConsumerMapTy> Out = generatePathDiagnostics( + consumers, convertedArrayOfReports); if (Out->empty()) return Out; @@ -3068,7 +3100,7 @@ void BugReporter::EmitBasicReport(const Decl *DeclWithIssue, ArrayRef<FixItHint> Fixits) { // 'BT' is owned by BugReporter. BugType *BT = getBugTypeForName(CheckName, name, category); - auto R = std::make_unique<BugReport>(*BT, str, Loc); + auto R = std::make_unique<BasicBugReport>(*BT, str, Loc); R->setDeclWithIssue(DeclWithIssue); for (const auto &SR : Ranges) R->addRange(SR); |

