Index: clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -75,28 +75,162 @@ class BugReport : public llvm::ilist_node { public: using ranges_iterator = const SourceRange *; - using VisitorList = SmallVector, 8>; - using visitor_iterator = VisitorList::iterator; - using visitor_range = llvm::iterator_range; using NoteList = SmallVector, 4>; + enum class Kind { Basic, PathSensitive }; + protected: friend class BugReportEquivClass; friend class BugReporter; + Kind K; const BugType& BT; const Decl *DeclWithIssue = nullptr; std::string ShortDescription; std::string Description; PathDiagnosticLocation Location; - PathDiagnosticLocation UniqueingLocation; - const Decl *UniqueingDecl; - const ExplodedNode *ErrorNode = nullptr; SmallVector Ranges; - const SourceRange ErrorNodeRange; NoteList Notes; + BugReport(Kind kind, const BugType &bt, StringRef desc) + : K(kind), BT(bt), Description(desc) {} + + BugReport(Kind kind, const BugType &bt, StringRef shortDesc, StringRef desc) + : K(kind), BT(bt), ShortDescription(shortDesc), Description(desc) {} + + BugReport(Kind kind, const BugType &bt, StringRef desc, + PathDiagnosticLocation loc) + : K(kind), BT(bt), Description(desc), Location(loc) {} + +public: + virtual ~BugReport() = default; + + Kind getKind() const { return K; } + + const BugType& getBugType() const { return BT; } + + StringRef getDescription() const { return Description; } + + StringRef getShortDescription(bool UseFallback = true) const { + if (ShortDescription.empty() && UseFallback) + return Description; + return ShortDescription; + } + + /// Get the location on which the report should be uniqued. + virtual PathDiagnosticLocation getUniqueingLocation() const { + return Location; + } + + /// Get the declaration containing the uniqueing location. + virtual const Decl *getUniqueingDecl() const { + return DeclWithIssue; + } + + /// Return the canonical declaration, be it a method or class, where + /// this issue semantically occurred. + virtual const Decl *getDeclWithIssue() const { + return DeclWithIssue; + } + + /// Specifically set the Decl where an issue occurred. This isn't necessary + /// for BugReports that cover a path as it will be automatically inferred. + void setDeclWithIssue(const Decl *declWithIssue) { + DeclWithIssue = declWithIssue; + } + + /// Add new item to the list of additional notes that need to be attached to + /// this path-insensitive report. If you want to add extra notes to a + /// path-sensitive report, you need to use a BugReporterVisitor because it + /// allows you to specify where exactly in the auto-generated path diagnostic + /// the extra note should appear. + void addNote(StringRef Msg, const PathDiagnosticLocation &Pos, + ArrayRef Ranges) { + auto P = std::make_shared(Pos, Msg); + + for (const auto &R : Ranges) + P->addRange(R); + + Notes.push_back(std::move(P)); + } + + // FIXME: Instead of making an overload, we could have default-initialized + // Ranges with {}, however it crashes the MSVC 2013 compiler. + void addNote(StringRef Msg, const PathDiagnosticLocation &Pos) { + std::vector Ranges; + addNote(Msg, Pos, Ranges); + } + + const NoteList &getNotes() { + return Notes; + } + + /// Return the "definitive" location of the reported bug. + /// + /// While a bug can span an entire path, usually there is a specific + /// location that can be used to identify where the key issue occurred. + /// This location is used by clients rendering diagnostics. + virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const { + assert(Location.isValid()); + return Location; + } + + /// Add a range to a bug report. + /// + /// Ranges are used to highlight regions of interest in the source code. + /// They should be at the same source code line as the BugReport location. + /// By default, the source range of the statement corresponding to the error + /// node will be used; add a single invalid range to specify absence of + /// ranges. + void addRange(SourceRange R) { + assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used " + "to specify that the report does not have a range."); + Ranges.push_back(R); + } + + /// Get the SourceRanges associated with the report. + virtual llvm::iterator_range getRanges() const { + return llvm::make_range(Ranges.begin(), Ranges.end()); + } + + /// Profile to identify equivalent bug reports for error report coalescing. + /// Reports are uniqued to ensure that we do not emit multiple diagnostics + /// for each bug. + virtual void Profile(llvm::FoldingSetNodeID& hash) const; +}; + +class BasicBugReport : public BugReport { +public: + BasicBugReport(const BugType &bt, StringRef desc) + : BugReport(Kind::Basic, bt, desc) {} + + BasicBugReport(const BugType &bt, StringRef shortDesc, StringRef desc) + : BugReport(Kind::Basic, bt, shortDesc, desc) {} + + BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l) + : BugReport(Kind::Basic, bt, desc, l) {} + + static bool classof(const BugReport *R) { + return R->getKind() == Kind::Basic; + } +}; + +class PathSensitiveBugReport : public BugReport { +public: + using VisitorList = SmallVector, 8>; + using visitor_iterator = VisitorList::iterator; + using visitor_range = llvm::iterator_range; + +protected: + /// The ExplodedGraph node against which the report was thrown. It corresponds + /// to the end of the execution path that demonstrates the bug. + const ExplodedNode *ErrorNode = nullptr; + + /// The range that corresponds to ErrorNode's program point. It is usually + /// highlighted in the report. + const SourceRange ErrorNodeRange; + /// A (stack of) a set of symbols that are registered with this /// report as being "interesting", and thus used to help decide which /// diagnostics to include when constructing the final path diagnostic. @@ -143,21 +277,24 @@ /// Conditions we're already tracking. llvm::SmallSet TrackedConditions; -public: - BugReport(const BugType &bt, StringRef desc, const ExplodedNode *errornode) - : BT(bt), Description(desc), ErrorNode(errornode), - ErrorNodeRange(getStmt() ? getStmt()->getSourceRange() - : SourceRange()) {} + /// Reports with different uniqueing locations are considered to be different + /// for the purposes of deduplication. + PathDiagnosticLocation UniqueingLocation; + const Decl *UniqueingDecl; + + const Stmt *getStmt() const; - BugReport(const BugType &bt, StringRef shortDesc, StringRef desc, - const ExplodedNode *errornode) - : BT(bt), ShortDescription(shortDesc), Description(desc), - ErrorNode(errornode), +public: + PathSensitiveBugReport(const BugType &bt, StringRef desc, + const ExplodedNode *errorNode) + : BugReport(Kind::PathSensitive, bt, desc), ErrorNode(errorNode), ErrorNodeRange(getStmt() ? getStmt()->getSourceRange() : SourceRange()) {} - BugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l) - : BT(bt), Description(desc), Location(l), + PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc, + const ExplodedNode *errorNode) + : BugReport(Kind::PathSensitive, bt, shortDesc, desc), + ErrorNode(errorNode), ErrorNodeRange(getStmt() ? getStmt()->getSourceRange() : SourceRange()) {} @@ -168,40 +305,22 @@ /// to the user. This method allows to rest the location which should be used /// for uniquing reports. For example, memory leaks checker, could set this to /// the allocation site, rather then the location where the bug is reported. - BugReport(BugType &bt, StringRef desc, const ExplodedNode *errornode, - PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique) - : BT(bt), Description(desc), UniqueingLocation(LocationToUnique), - UniqueingDecl(DeclToUnique), ErrorNode(errornode), - ErrorNodeRange(getStmt() ? getStmt()->getSourceRange() - : SourceRange()) {} - - virtual ~BugReport() = default; - - const BugType& getBugType() const { return BT; } - //BugType& getBugType() { return BT; } + PathSensitiveBugReport(BugType &bt, StringRef desc, + const ExplodedNode *errorNode, + PathDiagnosticLocation LocationToUnique, + const Decl *DeclToUnique) + : BugReport(Kind::PathSensitive, bt, desc), ErrorNode(errorNode), + ErrorNodeRange(getStmt() ? getStmt()->getSourceRange() : SourceRange()), + UniqueingLocation(LocationToUnique), UniqueingDecl(DeclToUnique) { + assert(errorNode); + } - /// True when the report has an execution path associated with it. - /// - /// A report is said to be path-sensitive if it was thrown against a - /// particular exploded node in the path-sensitive analysis graph. - /// Path-sensitive reports have their intermediate path diagnostics - /// auto-generated, perhaps with the help of checker-defined visitors, - /// and may contain extra notes. - /// Path-insensitive reports consist only of a single warning message - /// in a specific location, and perhaps extra notes. - /// Path-sensitive checkers are allowed to throw path-insensitive reports. - bool isPathSensitive() const { return ErrorNode != nullptr; } + static bool classof(const BugReport *R) { + return R->getKind() == Kind::PathSensitive; + } const ExplodedNode *getErrorNode() const { return ErrorNode; } - StringRef getDescription() const { return Description; } - - StringRef getShortDescription(bool UseFallback = true) const { - if (ShortDescription.empty() && UseFallback) - return Description; - return ShortDescription; - } - /// Indicates whether or not any path pruning should take place /// when generating a PathDiagnostic from this BugReport. bool shouldPrunePath() const { return !DoNotPrunePath; } @@ -209,6 +328,22 @@ /// Disable all path pruning when generating a PathDiagnostic. void disablePathPruning() { DoNotPrunePath = true; } + /// Get the location on which the report should be uniqued. + PathDiagnosticLocation getUniqueingLocation() const override { + return UniqueingLocation; + } + + /// Get the declaration containing the uniqueing location. + const Decl *getUniqueingDecl() const override { + return UniqueingDecl; + } + + const Decl *getDeclWithIssue() const override; + + llvm::iterator_range getRanges() const override; + + PathDiagnosticLocation getLocation(const SourceManager &SM) const override; + void markInteresting(SymbolRef sym); void markInteresting(const MemRegion *R); void markInteresting(SVal V); @@ -240,76 +375,10 @@ Invalidations.insert(std::make_pair(Tag, Data)); } - /// Return the canonical declaration, be it a method or class, where - /// this issue semantically occurred. - const Decl *getDeclWithIssue() const; - - /// Specifically set the Decl where an issue occurred. This isn't necessary - /// for BugReports that cover a path as it will be automatically inferred. - void setDeclWithIssue(const Decl *declWithIssue) { - DeclWithIssue = declWithIssue; - } - - /// Add new item to the list of additional notes that need to be attached to - /// this path-insensitive report. If you want to add extra notes to a - /// path-sensitive report, you need to use a BugReporterVisitor because it - /// allows you to specify where exactly in the auto-generated path diagnostic - /// the extra note should appear. - void addNote(StringRef Msg, const PathDiagnosticLocation &Pos, - ArrayRef Ranges) { - auto P = std::make_shared(Pos, Msg); - - for (const auto &R : Ranges) - P->addRange(R); - - Notes.push_back(std::move(P)); - } - - // FIXME: Instead of making an override, we could have default-initialized - // Ranges with {}, however it crashes the MSVC 2013 compiler. - void addNote(StringRef Msg, const PathDiagnosticLocation &Pos) { - std::vector Ranges; - addNote(Msg, Pos, Ranges); - } - - virtual const NoteList &getNotes() { - return Notes; - } - - /// Return the "definitive" location of the reported bug. - /// - /// While a bug can span an entire path, usually there is a specific - /// location that can be used to identify where the key issue occurred. - /// This location is used by clients rendering diagnostics. - virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const; - - /// Get the location on which the report should be uniqued. - PathDiagnosticLocation getUniqueingLocation() const { - return UniqueingLocation; - } - - /// Get the declaration containing the uniqueing location. - const Decl *getUniqueingDecl() const { - return UniqueingDecl; - } - - const Stmt *getStmt() const; - - /// Add a range to a bug report. - /// - /// Ranges are used to highlight regions of interest in the source code. - /// They should be at the same source code line as the BugReport location. - /// By default, the source range of the statement corresponding to the error - /// node will be used; add a single invalid range to specify absence of - /// ranges. - void addRange(SourceRange R) { - assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used " - "to specify that the report does not have a range."); - Ranges.push_back(R); - } - - /// Get the SourceRanges associated with the report. - virtual llvm::iterator_range getRanges() const; + /// Profile to identify equivalent bug reports for error report coalescing. + /// Reports are uniqued to ensure that we do not emit multiple diagnostics + /// for each bug. + void Profile(llvm::FoldingSetNodeID &hash) const override; /// Add custom or predefined bug report visitors to this report. /// @@ -334,11 +403,6 @@ bool addTrackedCondition(const ExplodedNode *Cond) { return TrackedConditions.insert(Cond).second; } - - /// Profile to identify equivalent bug reports for error report coalescing. - /// Reports are uniqued to ensure that we do not emit multiple diagnostics - /// for each bug. - virtual void Profile(llvm::FoldingSetNodeID& hash) const; }; //===----------------------------------------------------------------------===// @@ -399,12 +463,6 @@ /// Generate and flush the diagnostics for the given bug report. void FlushReport(BugReportEquivClass& EQ); - /// Generate the diagnostics for the given bug report. - std::unique_ptr - generateDiagnosticForConsumerMap(BugReport *exampleReport, - ArrayRef consumers, - ArrayRef bugReports); - /// The set of bug reports tracked by the BugReporter. llvm::FoldingSet EQClasses; @@ -433,18 +491,12 @@ const AnalyzerOptions &getAnalyzerOptions() { return D.getAnalyzerOptions(); } - virtual std::unique_ptr - generatePathDiagnostics(ArrayRef consumers, - ArrayRef &bugReports) { - return {}; - } - /// Add the given report to the set of reports tracked by BugReporter. /// /// The reports are usually generated by the checkers. Further, they are /// folded based on the profile value, which is done to coalesce similar /// reports. - void emitReport(std::unique_ptr R); + virtual void emitReport(std::unique_ptr R); void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, @@ -463,12 +515,34 @@ /// category. BugType *getBugTypeForName(CheckName CheckName, StringRef name, StringRef category); + + virtual BugReport * + findReportInEquivalenceClass(BugReportEquivClass &eqClass, + SmallVectorImpl &bugReports) { + return &*eqClass.begin(); + } + +protected: + /// Generate the diagnostics for the given bug report. + virtual std::unique_ptr + generateDiagnosticForConsumerMap(BugReport *exampleReport, + ArrayRef consumers, + ArrayRef bugReports); }; /// GRBugReporter is used for generating path-sensitive reports. -class PathSensitiveBugReporter : public BugReporter { +class PathSensitiveBugReporter final : public BugReporter { ExprEngine& Eng; + BugReport *findReportInEquivalenceClass( + BugReportEquivClass &eqClass, + SmallVectorImpl &bugReports) override; + + /// Generate the diagnostics for the given bug report. + std::unique_ptr + generateDiagnosticForConsumerMap(BugReport *exampleReport, + ArrayRef consumers, + ArrayRef bugReports) override; public: PathSensitiveBugReporter(BugReporterData& d, ExprEngine& eng) : BugReporter(d), Eng(eng) {} @@ -486,9 +560,11 @@ /// \return A mapping from consumers to the corresponding diagnostics. /// Iterates through the bug reports within a single equivalence class, /// stops at a first non-invalidated report. - std::unique_ptr - generatePathDiagnostics(ArrayRef consumers, - ArrayRef &bugReports) override; + std::unique_ptr generatePathDiagnostics( + ArrayRef consumers, + ArrayRef &bugReports); + + void emitReport(std::unique_ptr R) override; }; Index: clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -33,7 +33,7 @@ namespace ento { -class BugReport; +class PathSensitiveBugReport; class BugReporterContext; class ExplodedNode; class MemRegion; @@ -60,29 +60,29 @@ /// BugReport while processing a node. virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, - BugReport &BR) = 0; + PathSensitiveBugReport &BR) = 0; /// Last function called on the visitor, no further calls to VisitNode /// would follow. virtual void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode, - BugReport &BR); + PathSensitiveBugReport &BR); /// Provide custom definition for the final diagnostic piece on the /// path - the piece, which is displayed before the path is expanded. /// /// NOTE that this function can be implemented on at most one used visitor, /// and otherwise it crahes at runtime. - virtual PathDiagnosticPieceRef - getEndPath(BugReporterContext &BRC, const ExplodedNode *N, - BugReport &BR); + virtual PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, + const ExplodedNode *N, + PathSensitiveBugReport &BR); virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; /// Generates the default final diagnostic piece. - static PathDiagnosticPieceRef getDefaultEndPath(const BugReporterContext &BRC, - const ExplodedNode *N, - const BugReport &BR); + static PathDiagnosticPieceRef + getDefaultEndPath(const BugReporterContext &BRC, const ExplodedNode *N, + const PathSensitiveBugReport &BR); }; namespace bugreporter { @@ -111,7 +111,8 @@ /// \return Whether or not the function was able to add visitors for this /// statement. Note that returning \c true does not actually imply /// that any visitors were added. -bool trackExpressionValue(const ExplodedNode *N, const Expr *E, BugReport &R, +bool trackExpressionValue(const ExplodedNode *N, const Expr *E, + PathSensitiveBugReport &R, TrackingKind TKind = TrackingKind::Thorough, bool EnableNullFPSuppression = true); @@ -157,7 +158,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; class TrackConstraintBRVisitor final : public BugReporterVisitor { @@ -183,7 +184,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; private: /// Checks if the constraint is valid in the current state. @@ -201,7 +202,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; /// If the statement is a message send expression with nil receiver, returns /// the receiver expression. Returns NULL otherwise. @@ -226,40 +227,42 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; PathDiagnosticPieceRef VisitNodeImpl(const ExplodedNode *N, - BugReporterContext &BRC, BugReport &BR); + BugReporterContext &BRC, + PathSensitiveBugReport &BR); - PathDiagnosticPieceRef VisitTerminator(const Stmt *Term, - const ExplodedNode *N, - const CFGBlock *SrcBlk, - const CFGBlock *DstBlk, BugReport &R, - BugReporterContext &BRC); + PathDiagnosticPieceRef + VisitTerminator(const Stmt *Term, const ExplodedNode *N, + const CFGBlock *SrcBlk, const CFGBlock *DstBlk, + PathSensitiveBugReport &R, BugReporterContext &BRC); PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, - BugReporterContext &BRC, BugReport &R, + BugReporterContext &BRC, + PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue); PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR, - BugReporterContext &BRC, BugReport &R, + BugReporterContext &BRC, + PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue, bool IsAssuming); - PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, - const BinaryOperator *BExpr, - BugReporterContext &BRC, BugReport &R, - const ExplodedNode *N, bool TookTrue, - bool IsAssuming); + PathDiagnosticPieceRef + VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr, + BugReporterContext &BRC, PathSensitiveBugReport &R, + const ExplodedNode *N, bool TookTrue, bool IsAssuming); PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const MemberExpr *ME, - BugReporterContext &BRC, BugReport &R, + BugReporterContext &BRC, + PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue, bool IsAssuming); PathDiagnosticPieceRef VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr, - BugReporterContext &BRC, BugReport &R, + BugReporterContext &BRC, PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue); /// Tries to print the value of the given expression. @@ -278,7 +281,7 @@ const Expr *ParentEx, raw_ostream &Out, BugReporterContext &BRC, - BugReport &R, + PathSensitiveBugReport &R, const ExplodedNode *N, Optional &prunable, bool IsSameFieldName); @@ -302,12 +305,12 @@ } PathDiagnosticPieceRef VisitNode(const ExplodedNode *, BugReporterContext &, - BugReport &) override { + PathSensitiveBugReport &) override { return nullptr; } void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; /// When a region containing undefined value or '0' value is passed @@ -330,7 +333,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; class SuppressInlineDefensiveChecksVisitor final : public BugReporterVisitor { @@ -359,7 +362,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; /// The bug visitor will walk all the nodes in a path and collect all the @@ -377,10 +380,10 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; @@ -391,7 +394,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &R) override; + PathSensitiveBugReport &R) override; }; } // namespace ento Index: clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp =================================================================== --- clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp +++ clang/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp @@ -36,8 +36,8 @@ if (!BT) BT.reset(new BugType(this, "call to main", "example analyzer plugin")); - std::unique_ptr report = - std::make_unique(*BT, BT->getName(), N); + auto report = + std::make_unique(*BT, BT->getName(), N); report->addRange(Callee->getSourceRange()); C.emitReport(std::move(report)); } Index: clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp @@ -75,7 +75,8 @@ // reference is outside the range. // Generate a report for this bug. - auto report = std::make_unique(*BT, BT->getDescription(), N); + auto report = + std::make_unique(*BT, BT->getDescription(), N); report->addRange(LoadS->getSourceRange()); C.emitReport(std::move(report)); Index: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp @@ -256,7 +256,7 @@ break; } - auto BR = std::make_unique(*BT, os.str(), errorNode); + auto BR = std::make_unique(*BT, os.str(), errorNode); BR->addVisitor(std::move(Visitor)); checkerContext.emitReport(std::move(BR)); } Index: clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -211,7 +211,7 @@ if (!BT) BT.reset(new APIMisuse(this, "nil argument")); - auto R = std::make_unique(*BT, Msg, N); + auto R = std::make_unique(*BT, Msg, N); R->addRange(Range); bugreporter::trackExpressionValue(N, E, *R); C.emitReport(std::move(R)); @@ -520,7 +520,7 @@ if (!BT) BT.reset(new APIMisuse(this, "Bad use of CFNumber APIs")); - auto report = std::make_unique(*BT, os.str(), N); + auto report = std::make_unique(*BT, os.str(), N); report->addRange(CE->getArg(2)->getSourceRange()); C.emitReport(std::move(report)); } @@ -575,7 +575,7 @@ OS << "Null pointer argument in call to " << cast(Call.getDecl())->getName(); - auto report = std::make_unique(BT, OS.str(), N); + auto report = std::make_unique(BT, OS.str(), N); report->addRange(Call.getArgSourceRange(0)); bugreporter::trackExpressionValue(N, Call.getArgExpr(0), *report); C.emitReport(std::move(report)); @@ -635,7 +635,7 @@ "of class '" << Class->getName() << "' and not the class directly"; - auto report = std::make_unique(*BT, os.str(), N); + auto report = std::make_unique(*BT, os.str(), N); report->addRange(msg.getSourceRange()); C.emitReport(std::move(report)); } @@ -788,7 +788,8 @@ ArgTy.print(os, C.getLangOpts()); os << "'"; - auto R = std::make_unique(*BT, os.str(), errorNode.getValue()); + auto R = std::make_unique(*BT, os.str(), + errorNode.getValue()); R->addRange(msg.getArgSourceRange(I)); C.emitReport(std::move(R)); } Index: clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp @@ -173,7 +173,8 @@ llvm::raw_string_ostream os(msg); os << "Call to blocking function '" << Call.getCalleeIdentifier()->getName() << "' inside of critical section"; - auto R = std::make_unique(*BlockInCritSectionBugType, os.str(), ErrNode); + auto R = std::make_unique(*BlockInCritSectionBugType, + os.str(), ErrNode); R->addRange(Call.getSourceRange()); R->markInteresting(BlockDescSym); C.emitReport(std::move(R)); Index: clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp @@ -34,7 +34,9 @@ if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) { if (!BT) BT.reset(new BuiltinBug(this, "Assignment of a non-Boolean value")); - C.emitReport(std::make_unique(*BT, BT->getDescription(), N)); + + C.emitReport( + std::make_unique(*BT, BT->getDescription(), N)); } } Index: clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -566,7 +566,7 @@ categories::UnixAPI, "Improper arguments")); // Generate a report for this bug. - auto report = std::make_unique( + auto report = std::make_unique( *BT_Overlap, "Arguments must not be overlapping buffers", N); report->addRange(First->getSourceRange()); report->addRange(Second->getSourceRange()); @@ -583,7 +583,7 @@ "Null pointer argument in call to byte string function")); BuiltinBug *BT = static_cast(BT_Null.get()); - auto Report = std::make_unique(*BT, WarningMsg, N); + auto Report = std::make_unique(*BT, WarningMsg, N); Report->addRange(S->getSourceRange()); if (const auto *Ex = dyn_cast(S)) bugreporter::trackExpressionValue(N, Ex, *Report); @@ -607,7 +607,7 @@ // FIXME: It would be nice to eventually make this diagnostic more clear, // e.g., by referencing the original declaration or by saying *why* this // reference is outside the range. - auto Report = std::make_unique(*BT, WarningMsg, N); + auto Report = std::make_unique(*BT, WarningMsg, N); Report->addRange(S->getSourceRange()); C.emitReport(std::move(Report)); } @@ -622,7 +622,8 @@ Filter.CheckNameCStringNotNullTerm, categories::UnixAPI, "Argument is not a null-terminated string.")); - auto Report = std::make_unique(*BT_NotCString, WarningMsg, N); + auto Report = + std::make_unique(*BT_NotCString, WarningMsg, N); Report->addRange(S->getSourceRange()); C.emitReport(std::move(Report)); @@ -644,7 +645,8 @@ "This expression will create a string whose length is too big to " "be represented as a size_t"; - auto Report = std::make_unique(*BT_NotCString, WarningMsg, N); + auto Report = + std::make_unique(*BT_NotCString, WarningMsg, N); C.emitReport(std::move(Report)); } } Index: clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -95,7 +95,7 @@ if (!N) return; - auto R = std::make_unique(*BT, BT->getName(), N); + auto R = std::make_unique(*BT, BT->getName(), N); if (BadE) { R->addRange(BadE->getSourceRange()); if (BadE->isGLValue()) @@ -175,7 +175,7 @@ if (PSV.isUndef()) { if (ExplodedNode *N = C.generateErrorNode()) { LazyInit_BT(BD, BT); - auto R = std::make_unique(*BT, Os.str(), N); + auto R = std::make_unique(*BT, Os.str(), N); R->addRange(ArgRange); if (ArgEx) bugreporter::trackExpressionValue(N, ArgEx, *R); @@ -252,7 +252,7 @@ SmallString<200> Buf; llvm::raw_svector_ostream Os(Buf); describeUninitializedArgumentInCall(Call, ArgumentNumber, Os); - auto R = std::make_unique(*BT, Os.str(), N); + auto R = std::make_unique(*BT, Os.str(), N); R->addRange(ArgRange); if (ArgEx) @@ -295,7 +295,7 @@ } // Generate a report for this bug. - auto R = std::make_unique(*BT, os.str(), N); + auto R = std::make_unique(*BT, os.str(), N); R->addRange(ArgRange); if (ArgEx) @@ -358,7 +358,7 @@ else Desc = "Argument to 'delete' is uninitialized"; BugType *BT = BT_cxx_delete_undef.get(); - auto R = std::make_unique(*BT, Desc, N); + auto R = std::make_unique(*BT, Desc, N); bugreporter::trackExpressionValue(N, DE, *R); C.emitReport(std::move(R)); return; @@ -420,8 +420,8 @@ << (Params == 1 ? "" : "s") << " is called with fewer (" << Call.getNumArgs() << ")"; - C.emitReport( - std::make_unique(*BT_call_few_args, os.str(), N)); + C.emitReport(std::make_unique(*BT_call_few_args, + os.str(), N)); } } @@ -482,7 +482,7 @@ } assert(BT && "Unknown message kind."); - auto R = std::make_unique(*BT, BT->getName(), N); + auto R = std::make_unique(*BT, BT->getName(), N); const ObjCMessageExpr *ME = msg.getOriginExpr(); R->addRange(ME->getReceiverRange()); @@ -525,7 +525,8 @@ os << "' that will be garbage"; } - auto report = std::make_unique(*BT_msg_ret, os.str(), N); + auto report = + std::make_unique(*BT_msg_ret, os.str(), N); report->addRange(ME->getReceiverRange()); // FIXME: This won't track "self" in messages to super. if (const Expr *receiver = ME->getInstanceReceiver()) { Index: clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp @@ -132,7 +132,8 @@ BT.reset(new BuiltinBug(this, "Cast region with wrong size.", "Cast a region whose size is not a multiple" " of the destination type size.")); - auto R = std::make_unique(*BT, BT->getDescription(), errorNode); + auto R = std::make_unique(*BT, BT->getDescription(), + errorNode); R->addRange(CE->getSourceRange()); C.emitReport(std::move(R)); } Index: clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp +++ clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp @@ -576,9 +576,8 @@ OS << " by a synthesized property but not released" " before '[super dealloc]'"; - std::unique_ptr BR( - new BugReport(*MissingReleaseBugType, OS.str(), ErrNode)); - + auto BR = std::make_unique(*MissingReleaseBugType, + OS.str(), ErrNode); C.emitReport(std::move(BR)); } @@ -699,8 +698,8 @@ OS << " property but was released in 'dealloc'"; } - std::unique_ptr BR( - new BugReport(*ExtraReleaseBugType, OS.str(), ErrNode)); + auto BR = std::make_unique(*ExtraReleaseBugType, + OS.str(), ErrNode); BR->addRange(M.getOriginExpr()->getSourceRange()); C.emitReport(std::move(BR)); @@ -741,8 +740,8 @@ OS << "'" << *PropImpl->getPropertyIvarDecl() << "' should be released rather than deallocated"; - std::unique_ptr BR( - new BugReport(*MistakenDeallocBugType, OS.str(), ErrNode)); + auto BR = std::make_unique(*MistakenDeallocBugType, + OS.str(), ErrNode); BR->addRange(M.getOriginExpr()->getSourceRange()); C.emitReport(std::move(BR)); Index: clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp @@ -127,7 +127,7 @@ BT_BreakJail.reset(new BuiltinBug( this, "Break out of jail", "No call of chdir(\"/\") immediately " "after chroot")); - C.emitReport(std::make_unique( + C.emitReport(std::make_unique( *BT_BreakJail, BT_BreakJail->getDescription(), N)); } } Index: clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/CloneChecker.cpp @@ -114,8 +114,8 @@ for (const CloneDetector::CloneGroup &Group : CloneGroups) { // We group the clones by printing the first as a warning and all others // as a note. - auto R = std::make_unique(*BT_Exact, "Duplicate code detected", - makeLocation(Group.front(), Mgr)); + auto R = std::make_unique( + *BT_Exact, "Duplicate code detected", makeLocation(Group.front(), Mgr)); R->addRange(Group.front().getSourceRange()); for (unsigned i = 1; i < Group.size(); ++i) @@ -169,7 +169,7 @@ // which may confuse the user. // Think how to perform more accurate suggestions? - auto R = std::make_unique( + auto R = std::make_unique( *BT_Suspicious, "Potential copy-paste error; did you really mean to use '" + Pair.FirstCloneInfo.Variable->getNameAsString() + "' here?", Index: clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp @@ -121,7 +121,7 @@ new BuiltinBug(this, "Conversion", "Possible loss of sign/precision.")); // Generate a report for this bug. - auto R = std::make_unique(*BT, Msg, N); + auto R = std::make_unique(*BT, Msg, N); C.emitReport(std::move(R)); } Index: clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp +++ clang/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp @@ -333,7 +333,8 @@ if (!Node) return; - auto Report = std::make_unique(BT_stmtLoc, "Statement", Node); + auto Report = + std::make_unique(BT_stmtLoc, "Statement", Node); C.emitReport(std::move(Report)); } Index: clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp @@ -47,7 +47,7 @@ } PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; private: bool Satisfied; @@ -92,7 +92,7 @@ "Logic error")); ExplodedNode *N = C.generateNonFatalErrorNode(); - auto R = std::make_unique(*BT, BT->getName(), N); + auto R = std::make_unique(*BT, BT->getName(), N); // Mark region of problematic base class for later use in the BugVisitor. R->markInteresting(BaseClassRegion); @@ -102,7 +102,8 @@ PathDiagnosticPieceRef DeleteWithNonVirtualDtorChecker::DeleteBugVisitor::VisitNode( - const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { + const ExplodedNode *N, BugReporterContext &BRC, + PathSensitiveBugReport &BR) { // Stop traversal after the first conversion was found on a path. if (Satisfied) return nullptr; Index: clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -179,7 +179,7 @@ break; } - auto report = std::make_unique( + auto report = std::make_unique( *BT_null, buf.empty() ? BT_null->getDescription() : StringRef(buf), N); bugreporter::trackExpressionValue(N, bugreporter::getDerefExpr(S), *report); @@ -200,8 +200,8 @@ BT_undef.reset( new BuiltinBug(this, "Dereference of undefined pointer value")); - auto report = - std::make_unique(*BT_undef, BT_undef->getDescription(), N); + auto report = std::make_unique( + *BT_undef, BT_undef->getDescription(), N); bugreporter::trackExpressionValue(N, bugreporter::getDerefExpr(S), *report); C.emitReport(std::move(report)); } Index: clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp @@ -47,7 +47,7 @@ if (!BT) BT.reset(new BuiltinBug(this, "Division by zero")); - auto R = std::make_unique(*BT, Msg, N); + auto R = std::make_unique(*BT, Msg, N); R->addVisitor(std::move(Visitor)); bugreporter::trackExpressionValue(N, getDenomExpr(N), *R); C.emitReport(std::move(R)); Index: clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp @@ -49,7 +49,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; private: // The tracked region. @@ -80,8 +80,8 @@ QualType::print(StaticType.getTypePtr(), Qualifiers(), OS, C.getLangOpts(), llvm::Twine()); OS << "'"; - std::unique_ptr R( - new BugReport(*BT, OS.str(), C.generateNonFatalErrorNode())); + auto R = std::make_unique( + *BT, OS.str(), C.generateNonFatalErrorNode()); R->markInteresting(Reg); R->addVisitor(std::make_unique(Reg)); R->addRange(ReportedNode->getSourceRange()); @@ -89,7 +89,7 @@ } PathDiagnosticPieceRef DynamicTypeChecker::DynamicTypeBugVisitor::VisitNode( - const ExplodedNode *N, BugReporterContext &BRC, BugReport &) { + const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) { ProgramStateRef State = N->getState(); ProgramStateRef StatePrev = N->getFirstPred()->getState(); Index: clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ clang/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp @@ -85,7 +85,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; private: // The tracked symbol. @@ -919,8 +919,8 @@ OS << "' to incompatible type '"; QualType::print(To, Qualifiers(), OS, C.getLangOpts(), llvm::Twine()); OS << "'"; - std::unique_ptr R( - new BugReport(*ObjCGenericsBugType, OS.str(), N)); + auto R = std::make_unique(*ObjCGenericsBugType, + OS.str(), N); R->markInteresting(Sym); R->addVisitor(std::make_unique(Sym)); if (ReportedNode) @@ -929,7 +929,8 @@ } PathDiagnosticPieceRef DynamicTypePropagation::GenericsBugVisitor::VisitNode( - const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { + const ExplodedNode *N, BugReporterContext &BRC, + PathSensitiveBugReport &BR) { ProgramStateRef state = N->getState(); ProgramStateRef statePrev = N->getFirstPred()->getState(); Index: clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp @@ -83,7 +83,7 @@ new BuiltinBug(this, "Enum cast out of range", "The value provided to the cast expression is not in " "the valid range of values for the enum")); - C.emitReport(std::make_unique( + C.emitReport(std::make_unique( *EnumValueCastOutOfRange, EnumValueCastOutOfRange->getDescription(), N)); } Index: clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp @@ -148,7 +148,7 @@ if (!BT) BT.reset(new BugType(this, "Checking analyzer assumptions", "debug")); - BR.emitReport(std::make_unique(*BT, Msg, N)); + BR.emitReport(std::make_unique(*BT, Msg, N)); return N; } Index: clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp @@ -55,7 +55,8 @@ "Using a fixed address is not portable because that " "address will probably not be valid in all " "environments or platforms.")); - auto R = std::make_unique(*BT, BT->getDescription(), N); + auto R = + std::make_unique(*BT, BT->getDescription(), N); R->addRange(B->getRHS()->getSourceRange()); C.emitReport(std::move(R)); } Index: clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -718,7 +718,7 @@ // Generate diagnostic. if (ExplodedNode *N = C.generateNonFatalErrorNode()) { initBugType(); - auto report = std::make_unique(*BT, Msg, N); + auto report = std::make_unique(*BT, Msg, N); report->addRange(E->getSourceRange()); report->addVisitor(std::make_unique(TaintedSVal)); C.emitReport(std::move(report)); Index: clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp @@ -54,9 +54,9 @@ ID.AddPointer(getTag()); } - virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, - BugReporterContext &BRC, - BugReport &BR) override; + virtual PathDiagnosticPieceRef + VisitNode(const ExplodedNode *N, BugReporterContext &BRC, + PathSensitiveBugReport &BR) override; // FIXME: Scan the map once in the visitor's constructor and do a direct // lookup by region. @@ -279,7 +279,7 @@ } // end namespace clang PathDiagnosticPieceRef InnerPointerChecker::InnerPointerBRVisitor::VisitNode( - const ExplodedNode *N, BugReporterContext &BRC, BugReport &) { + const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) { if (!isSymbolTracked(N->getState(), PtrToBuf) || isSymbolTracked(N->getFirstPred()->getState(), PtrToBuf)) return nullptr; Index: clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -1591,7 +1591,8 @@ void IteratorChecker::reportOutOfRangeBug(const StringRef &Message, const SVal &Val, CheckerContext &C, ExplodedNode *ErrNode) const { - auto R = std::make_unique(*OutOfRangeBugType, Message, ErrNode); + auto R = std::make_unique(*OutOfRangeBugType, Message, + ErrNode); R->markInteresting(Val); C.emitReport(std::move(R)); } @@ -1600,7 +1601,8 @@ const SVal &Val1, const SVal &Val2, CheckerContext &C, ExplodedNode *ErrNode) const { - auto R = std::make_unique(*MismatchedBugType, Message, ErrNode); + auto R = std::make_unique(*MismatchedBugType, Message, + ErrNode); R->markInteresting(Val1); R->markInteresting(Val2); C.emitReport(std::move(R)); @@ -1610,7 +1612,8 @@ const SVal &Val, const MemRegion *Reg, CheckerContext &C, ExplodedNode *ErrNode) const { - auto R = std::make_unique(*MismatchedBugType, Message, ErrNode); + auto R = std::make_unique(*MismatchedBugType, Message, + ErrNode); R->markInteresting(Val); R->markInteresting(Reg); C.emitReport(std::move(R)); @@ -1619,7 +1622,8 @@ void IteratorChecker::reportInvalidatedBug(const StringRef &Message, const SVal &Val, CheckerContext &C, ExplodedNode *ErrNode) const { - auto R = std::make_unique(*InvalidatedBugType, Message, ErrNode); + auto R = std::make_unique(*InvalidatedBugType, + Message, ErrNode); R->markInteresting(Val); C.emitReport(std::move(R)); } Index: clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp @@ -125,7 +125,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; void Profile(llvm::FoldingSetNodeID &ID) const override { ID.Add(NonLocalizedString); @@ -761,8 +761,8 @@ return; // Generate the bug report. - std::unique_ptr R(new BugReport( - *BT, "User-facing text should use localized string macro", ErrNode)); + auto R = std::make_unique( + *BT, "User-facing text should use localized string macro", ErrNode); if (argumentNumber) { R->addRange(M.getArgExpr(argumentNumber - 1)->getSourceRange()); } else { @@ -1000,7 +1000,8 @@ PathDiagnosticPieceRef NonLocalizedStringBRVisitor::VisitNode(const ExplodedNode *Succ, - BugReporterContext &BRC, BugReport &BR) { + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { if (Satisfied) return nullptr; Index: clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/MIGChecker.cpp @@ -274,7 +274,7 @@ if (!N) return; - auto R = std::make_unique( + auto R = std::make_unique( BT, "MIG callback fails with error after deallocating argument value. " "This is a use-after-free vulnerability because the caller will try to " Index: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h =================================================================== --- clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h +++ clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h @@ -91,7 +91,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; private: const MemRegion *const RequestRegion; Index: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp +++ clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp @@ -30,8 +30,8 @@ ErrorText = "Double nonblocking on request " + RequestRegion->getDescriptiveName() + ". "; - auto Report = std::make_unique(*DoubleNonblockingBugType, - ErrorText, ExplNode); + auto Report = std::make_unique( + *DoubleNonblockingBugType, ErrorText, ExplNode); Report->addRange(MPICallEvent.getSourceRange()); SourceRange Range = RequestRegion->sourceRange(); @@ -53,8 +53,8 @@ std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() + " has no matching wait. "}; - auto Report = - std::make_unique(*MissingWaitBugType, ErrorText, ExplNode); + auto Report = std::make_unique(*MissingWaitBugType, + ErrorText, ExplNode); SourceRange Range = RequestRegion->sourceRange(); if (Range.isValid()) @@ -73,8 +73,8 @@ std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() + " has no matching nonblocking call. "}; - auto Report = - std::make_unique(*UnmatchedWaitBugType, ErrorText, ExplNode); + auto Report = std::make_unique(*UnmatchedWaitBugType, + ErrorText, ExplNode); Report->addRange(CE.getSourceRange()); SourceRange Range = RequestRegion->sourceRange(); @@ -84,8 +84,10 @@ BReporter.emitReport(std::move(Report)); } -PathDiagnosticPieceRef MPIBugReporter::RequestNodeVisitor::VisitNode( - const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { +PathDiagnosticPieceRef +MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode *N, + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { if (IsNodeFound) return nullptr; Index: clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp @@ -117,7 +117,8 @@ const AllocationPair &AP, ExplodedNode *N, CheckerContext &C) const; /// Mark an AllocationPair interesting for diagnostic reporting. - void markInteresting(BugReport *R, const AllocationPair &AP) const { + void markInteresting(PathSensitiveBugReport *R, + const AllocationPair &AP) const { R->markInteresting(AP.first); R->markInteresting(AP.second->Region); } @@ -141,7 +142,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; }; } @@ -236,7 +237,7 @@ os << "Deallocator doesn't match the allocator: '" << FunctionsToTrack[PDeallocIdx].Name << "' should be used."; - auto Report = std::make_unique(*BT, os.str(), N); + auto Report = std::make_unique(*BT, os.str(), N); Report->addVisitor(std::make_unique(AP.first)); Report->addRange(ArgExpr->getSourceRange()); markInteresting(Report.get(), AP); @@ -280,7 +281,8 @@ << "the allocator: missing a call to '" << FunctionsToTrack[DIdx].Name << "'."; - auto Report = std::make_unique(*BT, os.str(), N); + auto Report = + std::make_unique(*BT, os.str(), N); Report->addVisitor(std::make_unique(V)); Report->addRange(ArgExpr->getSourceRange()); Report->markInteresting(AS->Region); @@ -334,7 +336,7 @@ if (!N) return; initBugType(); - auto Report = std::make_unique( + auto Report = std::make_unique( *BT, "Trying to free data which has not been allocated.", N); Report->addRange(ArgExpr->getSourceRange()); if (AS) @@ -487,9 +489,9 @@ C.getSourceManager(), AllocNode->getLocationContext()); - auto Report = - std::make_unique(*BT, os.str(), N, LocUsedForUniqueing, - AllocNode->getLocationContext()->getDecl()); + auto Report = std::make_unique( + *BT, os.str(), N, LocUsedForUniqueing, + AllocNode->getLocationContext()->getDecl()); Report->addVisitor(std::make_unique(AP.first)); markInteresting(Report.get(), AP); @@ -615,7 +617,8 @@ PathDiagnosticPieceRef MacOSKeychainAPIChecker::SecKeychainBugVisitor::VisitNode( - const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { + const ExplodedNode *N, BugReporterContext &BRC, + PathSensitiveBugReport &BR) { const AllocationState *AS = N->getState()->get(Sym); if (!AS) return nullptr; Index: clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp @@ -139,7 +139,8 @@ BT_dispatchOnce.reset(new BugType(this, "Improper use of 'dispatch_once'", "API Misuse (Apple)")); - auto report = std::make_unique(*BT_dispatchOnce, os.str(), N); + auto report = + std::make_unique(*BT_dispatchOnce, os.str(), N); report->addRange(CE->getArg(0)->getSourceRange()); C.emitReport(std::move(report)); } Index: clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -524,11 +524,11 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, const ExplodedNode *EndPathNode, - BugReport &BR) override { + PathSensitiveBugReport &BR) override { if (!IsLeak) return nullptr; @@ -1823,7 +1823,8 @@ printExpectedAllocName(os, C, DeallocExpr); - auto R = std::make_unique(*BT_BadFree[*CheckKind], os.str(), N); + auto R = std::make_unique(*BT_BadFree[*CheckKind], + os.str(), N); R->markInteresting(MR); R->addRange(Range); C.emitReport(std::move(R)); @@ -1847,7 +1848,7 @@ BT_FreeAlloca[*CheckKind].reset(new BugType( CheckNames[*CheckKind], "Free alloca()", categories::MemoryError)); - auto R = std::make_unique( + auto R = std::make_unique( *BT_FreeAlloca[*CheckKind], "Memory allocated by alloca() should not be deallocated", N); R->markInteresting(ArgVal.getAsRegion()); @@ -1903,7 +1904,8 @@ os << ", not " << DeallocOs.str(); } - auto R = std::make_unique(*BT_MismatchedDealloc, os.str(), N); + auto R = std::make_unique(*BT_MismatchedDealloc, + os.str(), N); R->markInteresting(Sym); R->addRange(Range); R->addVisitor(std::make_unique(Sym)); @@ -1962,7 +1964,8 @@ else os << "allocated memory"; - auto R = std::make_unique(*BT_OffsetFree[*CheckKind], os.str(), N); + auto R = std::make_unique(*BT_OffsetFree[*CheckKind], + os.str(), N); R->markInteresting(MR->getBaseRegion()); R->addRange(Range); C.emitReport(std::move(R)); @@ -1988,10 +1991,11 @@ AllocationFamily AF = C.getState()->get(Sym)->getAllocationFamily(); - auto R = std::make_unique(*BT_UseFree[*CheckKind], + auto R = std::make_unique( + *BT_UseFree[*CheckKind], AF == AF_InnerBuffer - ? "Inner pointer of container used after re/deallocation" - : "Use of memory after it is freed", + ? "Inner pointer of container used after re/deallocation" + : "Use of memory after it is freed", N); R->markInteresting(Sym); @@ -2022,7 +2026,7 @@ BT_DoubleFree[*CheckKind].reset(new BugType( CheckNames[*CheckKind], "Double free", categories::MemoryError)); - auto R = std::make_unique( + auto R = std::make_unique( *BT_DoubleFree[*CheckKind], (Released ? "Attempt to free released memory" : "Attempt to free non-owned memory"), @@ -2051,7 +2055,7 @@ "Double delete", categories::MemoryError)); - auto R = std::make_unique( + auto R = std::make_unique( *BT_DoubleDelete, "Attempt to delete released memory", N); R->markInteresting(Sym); @@ -2079,8 +2083,8 @@ new BugType(CheckNames[*CheckKind], "Use of zero allocated", categories::MemoryError)); - auto R = std::make_unique(*BT_UseZerroAllocated[*CheckKind], - "Use of zero-allocated memory", N); + auto R = std::make_unique( + *BT_UseZerroAllocated[*CheckKind], "Use of zero-allocated memory", N); R->addRange(Range); if (Sym) { @@ -2119,7 +2123,8 @@ Os << " is a function pointer"; - auto R = std::make_unique(*BT_BadFree[*CheckKind], Os.str(), N); + auto R = std::make_unique(*BT_BadFree[*CheckKind], + Os.str(), N); R->markInteresting(MR); R->addRange(Range); C.emitReport(std::move(R)); @@ -2344,7 +2349,7 @@ os << "Potential memory leak"; } - auto R = std::make_unique( + auto R = std::make_unique( *BT_Leak[*CheckKind], os.str(), N, LocUsedForUniqueing, AllocNode->getLocationContext()->getDecl()); R->markInteresting(Sym); @@ -2906,8 +2911,10 @@ return false; } -PathDiagnosticPieceRef MallocChecker::MallocBugVisitor::VisitNode( - const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { +PathDiagnosticPieceRef +MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N, + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { ProgramStateRef state = N->getState(); ProgramStateRef statePrev = N->getFirstPred()->getState(); Index: clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp @@ -67,7 +67,7 @@ if (!N) return; - auto Report = std::make_unique( + auto Report = std::make_unique( *BT, "Both PROT_WRITE and PROT_EXEC flags are set. This can " "lead to exploitable memory regions, which could be overwritten " "with malicious code", N); Index: clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/MoveChecker.cpp @@ -171,7 +171,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; private: const MoveChecker &Chk; @@ -270,8 +270,10 @@ return MR; } -PathDiagnosticPieceRef MoveChecker::MovedBugVisitor::VisitNode( - const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { +PathDiagnosticPieceRef +MoveChecker::MovedBugVisitor::VisitNode(const ExplodedNode *N, + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { // We need only the last move of the reported object's region. // The visitor walks the ExplodedGraph backwards. if (Found) @@ -427,9 +429,9 @@ break; } - auto R = - std::make_unique(*BT, OS.str(), N, LocUsedForUniqueing, - MoveNode->getLocationContext()->getDecl()); + auto R = std::make_unique( + *BT, OS.str(), N, LocUsedForUniqueing, + MoveNode->getLocationContext()->getDecl()); R->addVisitor(std::make_unique(*this, Region, RD, MK)); C.emitReport(std::move(R)); return N; Index: clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp @@ -67,9 +67,11 @@ return; } - auto Report = std::make_unique( - *BT, "Use -drain instead of -release when using NSAutoreleasePool and " - "garbage collection", N); + auto Report = std::make_unique( + *BT, + "Use -drain instead of -release when using NSAutoreleasePool and " + "garbage collection", + N); Report->addRange(msg.getSourceRange()); C.emitReport(std::move(Report)); } Index: clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp @@ -273,7 +273,8 @@ CFBT.reset(new CFErrorDerefBug(this)); bug = CFBT.get(); } - BR.emitReport(std::make_unique(*bug, os.str(), event.SinkNode)); + BR.emitReport( + std::make_unique(*bug, os.str(), event.SinkNode)); } static bool IsNSError(QualType T, IdentifierInfo *II) { Index: clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp @@ -187,7 +187,7 @@ BTAttrNonNull.reset(new BugType( this, "Argument with 'nonnull' attribute passed null", "API")); - auto R = std::make_unique( + auto R = std::make_unique( *BTAttrNonNull, "Null pointer passed as an argument to a 'nonnull' parameter", ErrorNode); if (ArgE) @@ -201,7 +201,7 @@ if (!BTNullRefArg) BTNullRefArg.reset(new BuiltinBug(this, "Dereference of null pointer")); - auto R = std::make_unique( + auto R = std::make_unique( *BTNullRefArg, "Forming reference to null pointer", ErrorNode); if (ArgE) { const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE); Index: clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp @@ -139,7 +139,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; private: // The tracked region. @@ -163,7 +163,7 @@ if (!BT) BT.reset(new BugType(this, "Nullability", categories::MemoryError)); - auto R = std::make_unique(*BT, Msg, N); + auto R = std::make_unique(*BT, Msg, N); if (Region) { R->markInteresting(Region); R->addVisitor(std::make_unique(Region)); @@ -291,7 +291,8 @@ } PathDiagnosticPieceRef NullabilityChecker::NullabilityBugVisitor::VisitNode( - const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { + const ExplodedNode *N, BugReporterContext &BRC, + PathSensitiveBugReport &BR) { ProgramStateRef State = N->getState(); ProgramStateRef StatePrev = N->getFirstPred()->getState(); Index: clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp @@ -46,8 +46,8 @@ if (!BT_undef) BT_undef.reset(new BuiltinBug(this, "Uninitialized value used as mutex " "for @synchronized")); - auto report = - std::make_unique(*BT_undef, BT_undef->getDescription(), N); + auto report = std::make_unique( + *BT_undef, BT_undef->getDescription(), N); bugreporter::trackExpressionValue(N, Ex, *report); C.emitReport(std::move(report)); } @@ -70,8 +70,8 @@ BT_null.reset(new BuiltinBug( this, "Nil value used as mutex for @synchronized() " "(no synchronization will occur)")); - auto report = - std::make_unique(*BT_null, BT_null->getDescription(), N); + auto report = std::make_unique( + *BT_null, BT_null->getDescription(), N); bugreporter::trackExpressionValue(N, Ex, *report); C.emitReport(std::move(report)); Index: clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp @@ -144,7 +144,8 @@ if (!N) return; initBugType(); - auto R = std::make_unique(*BT, "Index is out of bounds", N); + auto R = std::make_unique( + *BT, "Index is out of bounds", N); R->addRange(IdxExpr->getSourceRange()); bugreporter::trackExpressionValue( N, IdxExpr, *R, bugreporter::TrackingKind::Thorough, false); Index: clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -159,7 +159,7 @@ if (!BT) BT.reset(new BugType(this, "Missing \"self = [(super or self) init...]\"", categories::CoreFoundationObjectiveC)); - C.emitReport(std::make_unique(*BT, errorStr, N)); + C.emitReport(std::make_unique(*BT, errorStr, N)); } void ObjCSelfInitChecker::checkPostObjCMessage(const ObjCMethodCall &Msg, Index: clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp @@ -71,7 +71,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; void Profile(llvm::FoldingSetNodeID &ID) const override { ID.Add(ReceiverSymbol); @@ -187,8 +187,8 @@ Desc = "Use of 'self' after it has been deallocated"; // Generate the report. - std::unique_ptr BR( - new BugReport(*DoubleSuperDeallocBugType, Desc, ErrNode)); + auto BR = std::make_unique(*DoubleSuperDeallocBugType, + Desc, ErrNode); BR->addRange(S->getSourceRange()); BR->addVisitor(std::make_unique(Sym)); C.emitReport(std::move(BR)); @@ -244,7 +244,8 @@ PathDiagnosticPieceRef SuperDeallocBRVisitor::VisitNode(const ExplodedNode *Succ, - BugReporterContext &BRC, BugReport &) { + BugReporterContext &BRC, + PathSensitiveBugReport &) { if (Satisfied) return nullptr; Index: clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp @@ -335,7 +335,8 @@ PathDiagnosticLocation CELoc = PathDiagnosticLocation::create(RD, BR->getSourceManager()); - auto Report = std::make_unique(*PaddingBug, Os.str(), CELoc); + auto Report = + std::make_unique(*PaddingBug, Os.str(), CELoc); Report->setDeclWithIssue(RD); Report->addRange(RD->getSourceRange()); BR->emitReport(std::move(Report)); Index: clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp @@ -173,8 +173,8 @@ this, "Dangerous pointer arithmetic", "Pointer arithmetic on a pointer to base class is dangerous " "because derived and base class may have different size.")); - auto R = std::make_unique(*BT_polyArray, - BT_polyArray->getDescription(), N); + auto R = std::make_unique( + *BT_polyArray, BT_polyArray->getDescription(), N); R->addRange(E->getSourceRange()); R->markInteresting(ArrayRegion); C.emitReport(std::move(R)); @@ -196,8 +196,8 @@ "Pointer arithmetic on non-array " "variables relies on memory layout, " "which is dangerous.")); - auto R = std::make_unique(*BT_pointerArith, - BT_pointerArith->getDescription(), N); + auto R = std::make_unique( + *BT_pointerArith, BT_pointerArith->getDescription(), N); R->addRange(SR); R->markInteresting(Region); C.emitReport(std::move(R)); Index: clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp @@ -63,7 +63,8 @@ new BuiltinBug(this, "Pointer subtraction", "Subtraction of two pointers that do not point to " "the same memory chunk may cause incorrect result.")); - auto R = std::make_unique(*BT, BT->getDescription(), N); + auto R = + std::make_unique(*BT, BT->getDescription(), N); R->addRange(B->getSourceRange()); C.emitReport(std::move(R)); } Index: clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -240,7 +240,7 @@ ExplodedNode *N = C.generateErrorNode(); if (!N) return; - auto report = std::make_unique( + auto report = std::make_unique( *BT_doublelock, "This lock has already been acquired", N); report->addRange(CE->getArg(0)->getSourceRange()); C.emitReport(std::move(report)); @@ -305,7 +305,7 @@ ExplodedNode *N = C.generateErrorNode(); if (!N) return; - auto Report = std::make_unique( + auto Report = std::make_unique( *BT_doubleunlock, "This lock has already been unlocked", N); Report->addRange(CE->getArg(0)->getSourceRange()); C.emitReport(std::move(Report)); @@ -328,7 +328,7 @@ ExplodedNode *N = C.generateErrorNode(); if (!N) return; - auto report = std::make_unique( + auto report = std::make_unique( *BT_lor, "This was not the most recently acquired lock. Possible " "lock order reversal", N); report->addRange(CE->getArg(0)->getSourceRange()); @@ -399,7 +399,8 @@ ExplodedNode *N = C.generateErrorNode(); if (!N) return; - auto Report = std::make_unique(*BT_destroylock, Message, N); + auto Report = + std::make_unique(*BT_destroylock, Message, N); Report->addRange(CE->getArg(0)->getSourceRange()); C.emitReport(std::move(Report)); } @@ -438,7 +439,8 @@ ExplodedNode *N = C.generateErrorNode(); if (!N) return; - auto Report = std::make_unique(*BT_initlock, Message, N); + auto Report = + std::make_unique(*BT_initlock, Message, N); Report->addRange(CE->getArg(0)->getSourceRange()); C.emitReport(std::move(Report)); } @@ -451,7 +453,7 @@ ExplodedNode *N = C.generateErrorNode(); if (!N) return; - auto Report = std::make_unique( + auto Report = std::make_unique( *BT_destroylock, "This lock has already been destroyed", N); Report->addRange(CE->getArg(0)->getSourceRange()); C.emitReport(std::move(Report)); Index: clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h =================================================================== --- clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h +++ clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h @@ -53,7 +53,7 @@ static StringRef bugTypeToName(RefCountBugType BT); }; -class RefCountReport : public BugReport { +class RefCountReport : public PathSensitiveBugReport { protected: SymbolRef Sym; bool isLeak = false; @@ -69,7 +69,7 @@ llvm::iterator_range getRanges() const override { if (!isLeak) - return BugReport::getRanges(); + return PathSensitiveBugReport::getRanges(); return llvm::make_range(ranges_iterator(), ranges_iterator()); } }; Index: clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp +++ clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp @@ -327,11 +327,11 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, const ExplodedNode *N, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; class RefLeakReportVisitor : public RefCountReportVisitor { @@ -340,7 +340,7 @@ PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, const ExplodedNode *N, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; } // end namespace retaincountchecker @@ -448,9 +448,9 @@ return std::make_shared(L, os.str()); } -PathDiagnosticPieceRef RefCountReportVisitor::VisitNode(const ExplodedNode *N, - BugReporterContext &BRC, - BugReport &BR) { +PathDiagnosticPieceRef +RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC, + PathSensitiveBugReport &BR) { const auto &BT = static_cast(BR.getBugType()); const auto *Checker = @@ -715,14 +715,16 @@ PathDiagnosticPieceRef RefCountReportVisitor::getEndPath(BugReporterContext &BRC, - const ExplodedNode *EndN, BugReport &BR) { + const ExplodedNode *EndN, + PathSensitiveBugReport &BR) { BR.markInteresting(Sym); return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR); } PathDiagnosticPieceRef RefLeakReportVisitor::getEndPath(BugReporterContext &BRC, - const ExplodedNode *EndN, BugReport &BR) { + const ExplodedNode *EndN, + PathSensitiveBugReport &BR) { // Tell the BugReporterContext to report cases when the tracked symbol is // assigned to different variables, etc. @@ -813,9 +815,9 @@ } RefCountReport::RefCountReport(const RefCountBug &D, const LangOptions &LOpts, - ExplodedNode *n, SymbolRef sym, - bool isLeak) - : BugReport(D, D.getDescription(), n), Sym(sym), isLeak(isLeak) { + ExplodedNode *n, SymbolRef sym, bool isLeak) + : PathSensitiveBugReport(D, D.getDescription(), n), Sym(sym), + isLeak(isLeak) { if (!isLeak) addVisitor(std::make_unique(sym)); } @@ -823,7 +825,7 @@ RefCountReport::RefCountReport(const RefCountBug &D, const LangOptions &LOpts, ExplodedNode *n, SymbolRef sym, StringRef endText) - : BugReport(D, D.getDescription(), endText, n) { + : PathSensitiveBugReport(D, D.getDescription(), endText, n) { addVisitor(std::make_unique(sym)); } Index: clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp @@ -79,7 +79,8 @@ // reference is outside the range. // Generate a report for this bug. - auto report = std::make_unique(*BT, BT->getDescription(), N); + auto report = + std::make_unique(*BT, BT->getDescription(), N); report->addRange(RetE->getSourceRange()); C.emitReport(std::move(report)); Index: clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp @@ -83,7 +83,8 @@ if (!N) return; - auto Report = std::make_unique(BT, BT.getDescription(), N); + auto Report = + std::make_unique(BT, BT.getDescription(), N); Report->addRange(RetE->getSourceRange()); bugreporter::trackExpressionValue(N, TrackingE ? TrackingE : RetE, *Report); Index: clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp @@ -206,8 +206,8 @@ return; // Generate the report. - auto R = std::make_unique(*DoubleCloseBugType, - "Closing a previously closed file stream", ErrNode); + auto R = std::make_unique( + *DoubleCloseBugType, "Closing a previously closed file stream", ErrNode); R->addRange(Call.getSourceRange()); R->markInteresting(FileDescSym); C.emitReport(std::move(R)); @@ -219,8 +219,9 @@ // Attach bug reports to the leak node. // TODO: Identify the leaked file descriptor. for (SymbolRef LeakedStream : LeakedStreams) { - auto R = std::make_unique(*LeakBugType, - "Opened file is never closed; potential resource leak", ErrNode); + auto R = std::make_unique( + *LeakBugType, "Opened file is never closed; potential resource leak", + ErrNode); R->markInteresting(LeakedStream); C.emitReport(std::move(R)); } Index: clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -162,7 +162,8 @@ llvm::raw_svector_ostream os(buf); SourceRange range = genName(os, R, C.getASTContext()); os << " returned to caller"; - auto report = std::make_unique(*BT_returnstack, os.str(), N); + auto report = + std::make_unique(*BT_returnstack, os.str(), N); report->addRange(RetE->getSourceRange()); if (range.isValid()) report->addRange(range); @@ -199,8 +200,8 @@ llvm::raw_svector_ostream Out(Buf); SourceRange Range = genName(Out, Region, C.getASTContext()); Out << " is captured by an asynchronously-executed block"; - auto Report = - std::make_unique(*BT_capturedstackasync, Out.str(), N); + auto Report = std::make_unique( + *BT_capturedstackasync, Out.str(), N); if (Range.isValid()) Report->addRange(Range); C.emitReport(std::move(Report)); @@ -222,8 +223,8 @@ llvm::raw_svector_ostream Out(Buf); SourceRange Range = genName(Out, Region, C.getASTContext()); Out << " is captured by a returned block"; - auto Report = - std::make_unique(*BT_capturedstackret, Out.str(), N); + auto Report = std::make_unique(*BT_capturedstackret, + Out.str(), N); if (Range.isValid()) Report->addRange(Range); C.emitReport(std::move(Report)); @@ -351,7 +352,8 @@ const VarRegion *VR = cast(P.first->getBaseRegion()); Out << *VR->getDecl() << "' upon returning to the caller. This will be a dangling reference"; - auto Report = std::make_unique(*BT_stackleak, Out.str(), N); + auto Report = + std::make_unique(*BT_stackleak, Out.str(), N); if (Range.isValid()) Report->addRange(Range); Index: clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -277,7 +277,7 @@ new BuiltinBug(this, "Illegal whence argument", "The whence argument to fseek() should be " "SEEK_SET, SEEK_END, or SEEK_CUR.")); - C.emitReport(std::make_unique( + C.emitReport(std::make_unique( *BT_illegalwhence, BT_illegalwhence->getDescription(), N)); } } @@ -345,7 +345,7 @@ if (!BT_nullfp) BT_nullfp.reset(new BuiltinBug(this, "NULL stream pointer", "Stream pointer might be NULL.")); - C.emitReport(std::make_unique( + C.emitReport(std::make_unique( *BT_nullfp, BT_nullfp->getDescription(), N)); } return nullptr; @@ -375,7 +375,7 @@ BT_doubleclose.reset(new BuiltinBug( this, "Double fclose", "Try to close a file Descriptor already" " closed. Cause undefined behaviour.")); - C.emitReport(std::make_unique( + C.emitReport(std::make_unique( *BT_doubleclose, BT_doubleclose->getDescription(), N)); } return nullptr; @@ -405,7 +405,7 @@ BT_ResourceLeak.reset( new BuiltinBug(this, "Resource Leak", "Opened File never closed. Potential Resource leak.")); - C.emitReport(std::make_unique( + C.emitReport(std::make_unique( *BT_ResourceLeak, BT_ResourceLeak->getDescription(), N)); } } Index: clang/lib/StaticAnalyzer/Checkers/Taint.h =================================================================== --- clang/lib/StaticAnalyzer/Checkers/Taint.h +++ clang/lib/StaticAnalyzer/Checkers/Taint.h @@ -91,7 +91,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; } // namespace taint Index: clang/lib/StaticAnalyzer/Checkers/Taint.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/Taint.cpp +++ clang/lib/StaticAnalyzer/Checkers/Taint.cpp @@ -206,7 +206,7 @@ PathDiagnosticPieceRef TaintBugVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) { + PathSensitiveBugReport &BR) { // Find the ExplodedNode where the taint was first introduced if (!isTainted(N->getState(), V) || Index: clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp @@ -52,7 +52,7 @@ if (isTainted(State, E, C.getLocationContext())) { if (ExplodedNode *N = C.generateNonFatalErrorNode()) { initBugType(); - auto report = std::make_unique(*BT, "tainted",N); + auto report = std::make_unique(*BT, "tainted", N); report->addRange(E->getSourceRange()); C.emitReport(std::move(report)); } Index: clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp @@ -71,7 +71,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; class TestAfterDivZeroChecker @@ -92,9 +92,9 @@ REGISTER_SET_WITH_PROGRAMSTATE(DivZeroMap, ZeroState) -PathDiagnosticPieceRef DivisionBRVisitor::VisitNode(const ExplodedNode *Succ, - BugReporterContext &BRC, - BugReport &BR) { +PathDiagnosticPieceRef +DivisionBRVisitor::VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC, + PathSensitiveBugReport &BR) { if (Satisfied) return nullptr; @@ -167,7 +167,7 @@ if (!DivZeroBug) DivZeroBug.reset(new BuiltinBug(this, "Division by zero")); - auto R = std::make_unique( + auto R = std::make_unique( *DivZeroBug, "Value being compared against zero has already been used " "for division", N); Index: clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp @@ -96,7 +96,8 @@ Ex = FindIt.FindExpr(Ex); // Emit the bug report. - auto R = std::make_unique(*BT, BT->getDescription(), N); + auto R = std::make_unique( + *BT, BT->getDescription(), N); bugreporter::trackExpressionValue(N, Ex, *R); R->addRange(Ex->getSourceRange()); Index: clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp @@ -83,7 +83,7 @@ os << "Variable '" << VD->getName() << "' is uninitialized when captured by block"; - auto R = std::make_unique(*BT, os.str(), N); + auto R = std::make_unique(*BT, os.str(), N); if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD)) R->addRange(Ex->getSourceRange()); R->addVisitor(std::make_unique( Index: clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp @@ -170,7 +170,7 @@ << "' expression is undefined"; } } - auto report = std::make_unique(*BT, OS.str(), N); + auto report = std::make_unique(*BT, OS.str(), N); if (Ex) { report->addRange(Ex->getSourceRange()); bugreporter::trackExpressionValue(N, Ex, *report); Index: clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp @@ -52,7 +52,7 @@ BT.reset(new BuiltinBug(this, "Array subscript is undefined")); // Generate a report for this bug. - auto R = std::make_unique(*BT, BT->getName(), N); + auto R = std::make_unique(*BT, BT->getName(), N); R->addRange(A->getIdx()->getSourceRange()); bugreporter::trackExpressionValue(N, A->getIdx(), *R); C.emitReport(std::move(R)); Index: clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp @@ -108,7 +108,7 @@ if (OS.str().empty()) OS << DefaultMsg; - auto R = std::make_unique(*BT, OS.str(), N); + auto R = std::make_unique(*BT, OS.str(), N); if (ex) { R->addRange(ex->getSourceRange()); bugreporter::trackExpressionValue(N, ex, *R); Index: clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -187,7 +187,7 @@ if (Opts.ShouldConvertNotesToWarnings) { for (const auto &Pair : UninitFields) { - auto Report = std::make_unique( + auto Report = std::make_unique( *BT_uninitField, Pair.second, Node, LocUsedForUniqueing, Node->getLocationContext()->getDecl()); Context.emitReport(std::move(Report)); @@ -201,7 +201,7 @@ << (UninitFields.size() == 1 ? "" : "s") << " at the end of the constructor call"; - auto Report = std::make_unique( + auto Report = std::make_unique( *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing, Node->getLocationContext()->getDecl()); Index: clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -135,7 +135,7 @@ LazyInitialize(this, BT_open, "Improper use of 'open'"); - auto Report = std::make_unique(*BT_open, Msg, N); + auto Report = std::make_unique(*BT_open, Msg, N); Report->addRange(SR); C.emitReport(std::move(Report)); } @@ -304,7 +304,8 @@ LazyInitialize(this, BT_pthreadOnce, "Improper use of 'pthread_once'"); - auto report = std::make_unique(*BT_pthreadOnce, os.str(), N); + auto report = + std::make_unique(*BT_pthreadOnce, os.str(), N); report->addRange(CE->getArg(0)->getSourceRange()); C.emitReport(std::move(report)); } @@ -347,7 +348,8 @@ SmallString<256> S; llvm::raw_svector_ostream os(S); os << "Call to '" << fn_name << "' has an allocation size of 0 bytes"; - auto report = std::make_unique(*BT_mallocZero, os.str(), N); + auto report = + std::make_unique(*BT_mallocZero, os.str(), N); report->addRange(arg->getSourceRange()); bugreporter::trackExpressionValue(N, arg, *report); Index: clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -72,7 +72,7 @@ break; } - auto report = std::make_unique(*BT, os.str(), N); + auto report = std::make_unique(*BT, os.str(), N); report->addVisitor(std::move(Visitor)); report->addRange(SizeE->getSourceRange()); bugreporter::trackExpressionValue(N, SizeE, *report); Index: clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/ValistChecker.cpp @@ -79,7 +79,7 @@ } PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, const ExplodedNode *EndPathNode, - BugReport &BR) override { + PathSensitiveBugReport &BR) override { if (!IsLeak) return nullptr; @@ -91,7 +91,7 @@ } PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; private: const MemRegion *Reg; @@ -254,7 +254,7 @@ BT_uninitaccess.reset(new BugType(CheckNames[CK_Uninitialized], "Uninitialized va_list", categories::MemoryError)); - auto R = std::make_unique(*BT_uninitaccess, Msg, N); + auto R = std::make_unique(*BT_uninitaccess, Msg, N); R->markInteresting(VAList); R->addVisitor(std::make_unique(VAList)); C.emitReport(std::move(R)); @@ -295,7 +295,7 @@ OS << " " << VariableName; OS << Msg2; - auto R = std::make_unique( + auto R = std::make_unique( *BT_leakedvalist, OS.str(), N, LocUsedForUniqueing, StartNode->getLocationContext()->getDecl()); R->markInteresting(Reg); @@ -375,7 +375,7 @@ } PathDiagnosticPieceRef ValistChecker::ValistBugVisitor::VisitNode( - const ExplodedNode *N, BugReporterContext &BRC, BugReport &) { + const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) { ProgramStateRef State = N->getState(); ProgramStateRef StatePrev = N->getFirstPred()->getState(); Index: clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/VforkChecker.cpp @@ -132,7 +132,7 @@ if (Details) os << "; " << Details; - auto Report = std::make_unique(*BT, os.str(), N); + auto Report = std::make_unique(*BT, os.str(), N); // TODO: mark vfork call in BugReportVisitor C.emitReport(std::move(Report)); } Index: clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp @@ -144,7 +144,7 @@ return; } - auto Report = std::make_unique(*BT, OS.str(), N); + auto Report = std::make_unique(*BT, OS.str(), N); C.emitReport(std::move(Report)); } Index: clang/lib/StaticAnalyzer/Core/BugReporter.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ 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: 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 @@ /// 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 @@ /// a PathDiagnosticBuilder able to construct bug reports for different /// consumers. Returns None if no valid report is found. static Optional - findValidReport(ArrayRef &bugReports, + findValidReport(ArrayRef &bugReports, PathSensitiveBugReporter &Reporter); PathDiagnosticBuilder( BugReporterContext BRC, std::unique_ptr BugPath, - BugReport *r, const ExplodedNode *ErrorNode, + PathSensitiveBugReport *r, const ExplodedNode *ErrorNode, std::unique_ptr VisitorsDiagnostics); /// This function is responsible for generating diagnostic pieces that are @@ -262,7 +264,7 @@ 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 @@ /// 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(); @@ -1262,7 +1265,19 @@ } static std::unique_ptr -generateEmptyDiagnosticForReport(const BugReport *R, const SourceManager &SM) { +generateDiagnosticForBasicReport(const BasicBugReport *R) { + const BugType &BT = R->getBugType(); + return std::make_unique( + R->getBugType().getCheckName(), R->getDeclWithIssue(), + R->getBugType().getName(), R->getDescription(), + R->getShortDescription(/*UseFallback=*/false), BT.getCategory(), + R->getUniqueingLocation(), R->getUniqueingDecl(), + std::make_unique()); +} + +static std::unique_ptr +generateEmptyDiagnosticForReport(const PathSensitiveBugReport *R, + const SourceManager &SM) { const BugType &BT = R->getBugType(); return std::make_unique( R->getBugType().getCheckName(), R->getDeclWithIssue(), @@ -1908,7 +1923,7 @@ 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())) { @@ -1917,7 +1932,7 @@ PathDiagnosticBuilder::PathDiagnosticBuilder( BugReporterContext BRC, std::unique_ptr BugPath, - BugReport *r, const ExplodedNode *ErrorNode, + PathSensitiveBugReport *r, const ExplodedNode *ErrorNode, std::unique_ptr VisitorsDiagnostics) : BugReporterContext(BRC), BugPath(std::move(BugPath)), R(r), ErrorNode(ErrorNode), @@ -1928,7 +1943,6 @@ PathDiagnosticConstruct Construct(PDC, ErrorNode, R); const SourceManager &SM = getSourceManager(); - const BugReport *R = getBugReport(); const AnalyzerOptions &Opts = getAnalyzerOptions(); StringRef ErrorTag = ErrorNode->getLocation().getTag()->getTagDescription(); @@ -2049,7 +2063,8 @@ // Methods for BugReport and subclasses. //===----------------------------------------------------------------------===// -void BugReport::addVisitor(std::unique_ptr visitor) { +void PathSensitiveBugReport::addVisitor( + std::unique_ptr visitor) { if (!visitor) return; @@ -2064,14 +2079,11 @@ 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,6 +2093,22 @@ } void BugReport::Profile(llvm::FoldingSetNodeID& hash) const { + hash.AddInteger(static_cast(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(getKind())); hash.AddPointer(&BT); hash.AddString(Description); PathDiagnosticLocation UL = getUniqueingLocation(); @@ -2101,7 +2129,7 @@ } } -void BugReport::markInteresting(SymbolRef sym) { +void PathSensitiveBugReport::markInteresting(SymbolRef sym) { if (!sym) return; @@ -2111,7 +2139,7 @@ InterestingRegions.insert(meta->getRegion()); } -void BugReport::markInteresting(const MemRegion *R) { +void PathSensitiveBugReport::markInteresting(const MemRegion *R) { if (!R) return; @@ -2122,22 +2150,22 @@ InterestingSymbols.insert(SR->getSymbol()); } -void BugReport::markInteresting(SVal V) { +void PathSensitiveBugReport::markInteresting(SVal V) { markInteresting(V.getAsRegion()); markInteresting(V.getAsSymbol()); } -void BugReport::markInteresting(const LocationContext *LC) { +void PathSensitiveBugReport::markInteresting(const LocationContext *LC) { if (!LC) return; InterestingLocationContexts.insert(LC); } -bool BugReport::isInteresting(SVal V) const { +bool PathSensitiveBugReport::isInteresting(SVal V) const { return isInteresting(V.getAsRegion()) || isInteresting(V.getAsSymbol()); } -bool BugReport::isInteresting(SymbolRef sym) const { +bool PathSensitiveBugReport::isInteresting(SymbolRef sym) const { if (!sym) return false; // We don't currently consider metadata symbols to be interesting @@ -2145,7 +2173,7 @@ return InterestingSymbols.count(sym); } -bool BugReport::isInteresting(const MemRegion *R) const { +bool PathSensitiveBugReport::isInteresting(const MemRegion *R) const { if (!R) return false; R = R->getBaseRegion(); @@ -2157,13 +2185,13 @@ return false; } -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; @@ -2181,31 +2209,21 @@ return S; } -llvm::iterator_range BugReport::getRanges() const { +iterator_range +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(getStmt())) + if (Ranges.empty() && isa_and_nonnull(getStmt())) return llvm::make_range(&ErrorNodeRange, &ErrorNodeRange + 1); - return llvm::make_range(ranges_iterator(), ranges_iterator()); - } - - // 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()); } -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 SourceManager &SM) const { + assert(!Location.isValid() && + "Either Location or ErrorNode should be specified but not both."); + return PathDiagnosticLocation::createEndOfPath(ErrorNode, SM); } //===----------------------------------------------------------------------===// @@ -2254,7 +2272,7 @@ class BugPathInfo { public: std::unique_ptr BugPath; - BugReport *Report; + PathSensitiveBugReport *Report; const ExplodedNode *ErrorNode; }; @@ -2270,7 +2288,8 @@ /// 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; + using ReportNewNodePair = + std::pair; SmallVector ReportNodes; BugPathInfo CurrentBugPath; @@ -2305,7 +2324,7 @@ public: BugPathGetter(const ExplodedGraph *OriginalGraph, - ArrayRef &bugReports); + ArrayRef &bugReports); BugPathInfo *getNextBugPath(); }; @@ -2313,7 +2332,7 @@ } // namespace BugPathGetter::BugPathGetter(const ExplodedGraph *OriginalGraph, - ArrayRef &bugReports) { + ArrayRef &bugReports) { SmallVector Nodes; for (const auto I : bugReports) { assert(I->isValid() && @@ -2332,7 +2351,7 @@ // in the new graph. llvm::SmallPtrSet 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 " @@ -2520,11 +2539,12 @@ /// Notes associated with {@code ErrorNode} are generated using /// {@code getEndPath}, and the rest are generated with {@code VisitNode}. static std::unique_ptr -generateVisitorsDiagnostics(BugReport *R, const ExplodedNode *ErrorNode, +generateVisitorsDiagnostics(PathSensitiveBugReport *R, + const ExplodedNode *ErrorNode, BugReporterContext &BRC) { std::unique_ptr Notes = std::make_unique(); - 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}. @@ -2574,15 +2594,15 @@ return Notes; } -Optional -PathDiagnosticBuilder::findValidReport(ArrayRef &bugReports, - PathSensitiveBugReporter &Reporter) { +Optional PathDiagnosticBuilder::findValidReport( + ArrayRef &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; @@ -2628,7 +2648,7 @@ std::unique_ptr PathSensitiveBugReporter::generatePathDiagnostics( ArrayRef consumers, - ArrayRef &bugReports) { + ArrayRef &bugReports) { assert(!bugReports.empty()); auto Out = std::make_unique(); @@ -2648,23 +2668,6 @@ } void BugReporter::emitReport(std::unique_ptr 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(); assert(ValidSourceLoc); // If we mess up in a release build, we'd still prefer to just drop the bug @@ -2688,6 +2691,28 @@ EQ->AddReport(std::move(R)); } +void PathSensitiveBugReporter::emitReport(std::unique_ptr R) { + if (auto PR = dyn_cast(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. //===----------------------------------------------------------------------===// @@ -2704,9 +2729,8 @@ } // namespace -static BugReport * -FindReportInEquivalenceClass(BugReportEquivClass& EQ, - SmallVectorImpl &bugReports) { +BugReport *PathSensitiveBugReporter::findReportInEquivalenceClass( + BugReportEquivClass &EQ, SmallVectorImpl &bugReports) { BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end(); assert(I != E); const BugType& BT = I->getBugType(); @@ -2717,10 +2741,9 @@ 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(&I)) { + R = PR; + bugReports.push_back(PR); } } return R; @@ -2735,19 +2758,20 @@ BugReport *exampleReport = nullptr; for (; I != E; ++I) { - const ExplodedNode *errorNode = I->getErrorNode(); - - if (!errorNode) + auto *R = dyn_cast(&*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; } @@ -2780,9 +2804,9 @@ 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; } @@ -2813,7 +2837,7 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) { SmallVector bugReports; - BugReport *report = FindReportInEquivalenceClass(EQ, bugReports); + BugReport *report = findReportInEquivalenceClass(EQ, bugReports); if (!report) return; @@ -2940,16 +2964,24 @@ std::unique_ptr BugReporter::generateDiagnosticForConsumerMap( - BugReport *report, ArrayRef consumers, + BugReport *exampleReport, ArrayRef consumers, ArrayRef bugReports) { + auto *basicReport = cast(exampleReport); + auto Out = std::make_unique(); + for (auto *Consumer : consumers) + (*Out)[Consumer] = generateDiagnosticForBasicReport(basicReport); + return Out; +} - if (!report->isPathSensitive()) { - auto Out = std::make_unique(); - for (auto *Consumer : consumers) - (*Out)[Consumer] = generateEmptyDiagnosticForReport(report, - getSourceManager()); - return Out; - } +std::unique_ptr +PathSensitiveBugReporter::generateDiagnosticForConsumerMap( + BugReport *exampleReport, ArrayRef consumers, + ArrayRef bugReports) { + std::vector BasicBugReports; + std::vector PathSensitiveBugReports; + if (isa(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 @@ -2957,8 +2989,13 @@ // the BugReporterVisitors may mark this bug as a false positive. assert(!bugReports.empty()); MaxBugClassSize.updateMax(bugReports.size()); - std::unique_ptr Out = - generatePathDiagnostics(consumers, bugReports); + + // Avoid copying the whole array because there may be a lot of reports. + ArrayRef convertedArrayOfReports( + reinterpret_cast(&*bugReports.begin()), + reinterpret_cast(&*bugReports.end())); + std::unique_ptr Out = generatePathDiagnostics( + consumers, convertedArrayOfReports); if (Out->empty()) return Out; @@ -2991,7 +3028,7 @@ ArrayRef Ranges) { // 'BT' is owned by BugReporter. BugType *BT = getBugTypeForName(CheckName, name, category); - auto R = std::make_unique(*BT, str, Loc); + auto R = std::make_unique(*BT, str, Loc); R->setDeclWithIssue(DeclWithIssue); for (ArrayRef::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) Index: clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -257,17 +257,18 @@ PathDiagnosticPieceRef BugReporterVisitor::getEndPath(BugReporterContext &, const ExplodedNode *, - BugReport &) { + PathSensitiveBugReport &) { return nullptr; } void BugReporterVisitor::finalizeVisitor(BugReporterContext &, - const ExplodedNode *, BugReport &) {} + const ExplodedNode *, + PathSensitiveBugReport &) {} PathDiagnosticPieceRef BugReporterVisitor::getDefaultEndPath(const BugReporterContext &BRC, const ExplodedNode *EndPathNode, - const BugReport &BR) { + const PathSensitiveBugReport &BR) { PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath( EndPathNode, BRC.getSourceManager()); @@ -337,7 +338,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BR, - BugReport &R) override; + PathSensitiveBugReport &R) override; private: /// Attempts to find the region of interest in a given record decl, @@ -371,10 +372,10 @@ /// \return Diagnostics piece for region not modified in the current function, /// if it decides to emit one. PathDiagnosticPieceRef - maybeEmitNote(BugReport &R, const CallEvent &Call, const ExplodedNode *N, - const RegionVector &FieldChain, const MemRegion *MatchedRegion, - StringRef FirstElement, bool FirstIsReferenceType, - unsigned IndirectionLevel); + maybeEmitNote(PathSensitiveBugReport &R, const CallEvent &Call, + const ExplodedNode *N, const RegionVector &FieldChain, + const MemRegion *MatchedRegion, StringRef FirstElement, + bool FirstIsReferenceType, unsigned IndirectionLevel); /// Pretty-print region \p MatchedRegion to \p os. /// \return Whether printing succeeded. @@ -503,9 +504,9 @@ return None; } -PathDiagnosticPieceRef NoStoreFuncVisitor::VisitNode(const ExplodedNode *N, - BugReporterContext &BR, - BugReport &R) { +PathDiagnosticPieceRef +NoStoreFuncVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BR, + PathSensitiveBugReport &R) { const LocationContext *Ctx = N->getLocationContext(); const StackFrameContext *SCtx = Ctx->getStackFrame(); @@ -617,7 +618,7 @@ ", which participates in a condition later"; PathDiagnosticPieceRef NoStoreFuncVisitor::maybeEmitNote( - BugReport &R, const CallEvent &Call, const ExplodedNode *N, + PathSensitiveBugReport &R, const CallEvent &Call, const ExplodedNode *N, const RegionVector &FieldChain, const MemRegion *MatchedRegion, StringRef FirstElement, bool FirstIsReferenceType, unsigned IndirectionLevel) { @@ -764,7 +765,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override { + PathSensitiveBugReport &BR) override { if (WasModified) return nullptr; @@ -790,7 +791,7 @@ static void addMacroVisitorIfNecessary( const ExplodedNode *N, const MemRegion *R, - bool EnableNullFPSuppression, BugReport &BR, + bool EnableNullFPSuppression, PathSensitiveBugReport &BR, const SVal V) { AnalyzerOptions &Options = N->getState()->getAnalysisManager().options; if (EnableNullFPSuppression && @@ -884,7 +885,7 @@ /// the statement is a call that was inlined, we add the visitor to the /// bug report, so it can print a note later. static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S, - BugReport &BR, + PathSensitiveBugReport &BR, bool InEnableNullFPSuppression, bugreporter::TrackingKind TKind) { if (!CallEvent::isCallStmt(S)) @@ -964,7 +965,7 @@ PathDiagnosticPieceRef visitNodeInitial(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) { + PathSensitiveBugReport &BR) { // Only print a message at the interesting return statement. if (N->getLocationContext() != CalleeSFC) return nullptr; @@ -1091,10 +1092,8 @@ PathDiagnosticPieceRef visitNodeMaybeUnsuppress(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) { -#ifndef NDEBUG + PathSensitiveBugReport &BR) { assert(Options.ShouldAvoidSuppressingNullArgumentPaths); -#endif // Are we at the entry node for this call? Optional CE = N->getLocationAs(); @@ -1140,7 +1139,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override { + PathSensitiveBugReport &BR) override { switch (Mode) { case Initial: return visitNodeInitial(N, BRC, BR); @@ -1154,7 +1153,7 @@ } void finalizeVisitor(BugReporterContext &, const ExplodedNode *, - BugReport &BR) override { + PathSensitiveBugReport &BR) override { if (EnableNullFPSuppression && ShouldInvalidate) BR.markInvalid(ReturnVisitor::getTag(), CalleeSFC); } @@ -1277,9 +1276,8 @@ } /// Show default diagnostics for storing bad region. -static void showBRDefaultDiagnostics(llvm::raw_svector_ostream& os, - const MemRegion *R, - SVal V) { +static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &os, + const MemRegion *R, SVal V) { if (V.getAs()) { bool b = false; if (R->isBoundable()) { @@ -1324,7 +1322,8 @@ PathDiagnosticPieceRef FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, - BugReporterContext &BRC, BugReport &BR) { + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { if (Satisfied) return nullptr; @@ -1501,9 +1500,8 @@ return (bool)N->getState()->assume(Constraint, !Assumption); } -PathDiagnosticPieceRef -TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, - BugReporterContext &BRC, BugReport &) { +PathDiagnosticPieceRef TrackConstraintBRVisitor::VisitNode( + const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) { const ExplodedNode *PrevN = N->getFirstPred(); if (IsSatisfied) return nullptr; @@ -1581,8 +1579,10 @@ return "IDCVisitor"; } -PathDiagnosticPieceRef SuppressInlineDefensiveChecksVisitor::VisitNode( - const ExplodedNode *Succ, BugReporterContext &BRC, BugReport &BR) { +PathDiagnosticPieceRef +SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ, + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { const ExplodedNode *Pred = Succ->getFirstPred(); if (IsSatisfied) return nullptr; @@ -1683,7 +1683,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; } // end of anonymous namespace @@ -1739,8 +1739,10 @@ return false; } -PathDiagnosticPieceRef TrackControlDependencyCondBRVisitor::VisitNode( - const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { +PathDiagnosticPieceRef +TrackControlDependencyCondBRVisitor::VisitNode(const ExplodedNode *N, + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { // We can only reason about control dependencies within the same stack frame. if (Origin->getStackFrame() != N->getStackFrame()) return nullptr; @@ -1881,7 +1883,8 @@ } bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode, - const Expr *E, BugReport &report, + const Expr *E, + PathSensitiveBugReport &report, bugreporter::TrackingKind TKind, bool EnableNullFPSuppression) { @@ -2037,9 +2040,9 @@ return nullptr; } -PathDiagnosticPieceRef NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, - BugReporterContext &BRC, - BugReport &BR) { +PathDiagnosticPieceRef +NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC, + PathSensitiveBugReport &BR) { Optional P = N->getLocationAs(); if (!P) return nullptr; @@ -2082,9 +2085,9 @@ /// to make all PathDiagnosticPieces created by this visitor. const char *ConditionBRVisitor::getTag() { return "ConditionBRVisitor"; } -PathDiagnosticPieceRef ConditionBRVisitor::VisitNode(const ExplodedNode *N, - BugReporterContext &BRC, - BugReport &BR) { +PathDiagnosticPieceRef +ConditionBRVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC, + PathSensitiveBugReport &BR) { auto piece = VisitNodeImpl(N, BRC, BR); if (piece) { piece->setTag(getTag()); @@ -2096,7 +2099,8 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N, - BugReporterContext &BRC, BugReport &BR) { + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { ProgramPoint ProgPoint = N->getLocation(); const std::pair &Tags = ExprEngine::geteagerlyAssumeBinOpBifurcationTags(); @@ -2134,7 +2138,8 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTerminator( const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk, - const CFGBlock *dstBlk, BugReport &R, BugReporterContext &BRC) { + const CFGBlock *dstBlk, PathSensitiveBugReport &R, + BugReporterContext &BRC) { const Expr *Cond = nullptr; // In the code below, Term is a CFG terminator and Cond is a branch condition @@ -2191,8 +2196,8 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(const Expr *Cond, BugReporterContext &BRC, - BugReport &R, const ExplodedNode *N, - bool TookTrue) { + PathSensitiveBugReport &R, + const ExplodedNode *N, bool TookTrue) { ProgramStateRef CurrentState = N->getState(); ProgramStateRef PrevState = N->getFirstPred()->getState(); const LocationContext *LCtx = N->getLocationContext(); @@ -2262,7 +2267,7 @@ const Expr *ParentEx, raw_ostream &Out, BugReporterContext &BRC, - BugReport &report, + PathSensitiveBugReport &report, const ExplodedNode *N, Optional &prunable, bool IsSameFieldName) { @@ -2347,7 +2352,8 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest( const Expr *Cond, const BinaryOperator *BExpr, BugReporterContext &BRC, - BugReport &R, const ExplodedNode *N, bool TookTrue, bool IsAssuming) { + PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue, + bool IsAssuming) { bool shouldInvert = false; Optional shouldPrune; @@ -2462,7 +2468,7 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitConditionVariable( StringRef LhsString, const Expr *CondVarExpr, BugReporterContext &BRC, - BugReport &report, const ExplodedNode *N, bool TookTrue) { + PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue) { // FIXME: If there's already a constraint tracker for this variable, // we shouldn't emit anything here (c.f. the double note in // test/Analysis/inlining/path-notes.c) @@ -2492,7 +2498,8 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest( const Expr *Cond, const DeclRefExpr *DRE, BugReporterContext &BRC, - BugReport &report, const ExplodedNode *N, bool TookTrue, bool IsAssuming) { + PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue, + bool IsAssuming) { const auto *VD = dyn_cast(DRE->getDecl()); if (!VD) return nullptr; @@ -2530,7 +2537,8 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest( const Expr *Cond, const MemberExpr *ME, BugReporterContext &BRC, - BugReport &report, const ExplodedNode *N, bool TookTrue, bool IsAssuming) { + PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue, + bool IsAssuming) { SmallString<256> Buf; llvm::raw_svector_ostream Out(Buf); @@ -2611,7 +2619,8 @@ //===----------------------------------------------------------------------===// void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor( - BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) { + BugReporterContext &BRC, const ExplodedNode *N, + PathSensitiveBugReport &BR) { // Here we suppress false positives coming from system headers. This list is // based on known issues. const AnalyzerOptions &Options = BRC.getAnalyzerOptions(); @@ -2696,9 +2705,9 @@ // Implementation of UndefOrNullArgVisitor. //===----------------------------------------------------------------------===// -PathDiagnosticPieceRef UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, - BugReporterContext &BRC, - BugReport &BR) { +PathDiagnosticPieceRef +UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC, + PathSensitiveBugReport &BR) { ProgramStateRef State = N->getState(); ProgramPoint ProgLoc = N->getLocation(); @@ -2754,7 +2763,8 @@ : Constraints(ConstraintRangeTy::Factory().getEmptyMap()) {} void FalsePositiveRefutationBRVisitor::finalizeVisitor( - BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) { + BugReporterContext &BRC, const ExplodedNode *EndPathNode, + PathSensitiveBugReport &BR) { // Collect new constraints VisitNode(EndPathNode, BRC, BR); @@ -2789,9 +2799,8 @@ BR.markInvalid("Infeasible constraints", EndPathNode->getLocationContext()); } -PathDiagnosticPieceRef -FalsePositiveRefutationBRVisitor::VisitNode(const ExplodedNode *N, - BugReporterContext &, BugReport &) { +PathDiagnosticPieceRef FalsePositiveRefutationBRVisitor::VisitNode( + const ExplodedNode *N, BugReporterContext &, PathSensitiveBugReport &) { // Collect new constraints const ConstraintRangeTy &NewCs = N->getState()->get(); ConstraintRangeTy::Factory &CF = @@ -2827,7 +2836,7 @@ PathDiagnosticPieceRef TagVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &R) { + PathSensitiveBugReport &R) { ProgramPoint PP = N->getLocation(); const NoteTag *T = dyn_cast_or_null(PP.getTag()); if (!T) Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -3005,8 +3005,10 @@ for (const auto &EQ : EQClasses) { for (const BugReport &Report : EQ) { - if (Report.getErrorNode()->getState() == N->getState() && - Report.getErrorNode()->getLocation() == N->getLocation()) + const ExplodedNode *EN = + cast(Report).getErrorNode(); + if (EN->getState() == N->getState() && + EN->getLocation() == N->getLocation()) return true; } } @@ -3131,8 +3133,11 @@ // Iterate through the reports and get their nodes. for (BugReporter::EQClasses_iterator EI = BR.EQClasses_begin(), EE = BR.EQClasses_end(); EI != EE; ++EI) { - const auto *N = const_cast(EI->begin()->getErrorNode()); - if (N) Src.push_back(N); + const auto *R = dyn_cast(&*EI->begin()); + if (!R) + continue; + const auto *N = const_cast(R->getErrorNode()); + Src.push_back(N); } return DumpGraph(Src, Filename); } else {