Index: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -74,29 +74,190 @@ /// individual bug reports. 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; + + SmallVector Ranges; + SmallVector, 4> Notes; + SmallVector Fixits; + + BugReport(Kind kind, const BugType &bt, StringRef desc) + : K(kind), BT(bt), Description(desc) {} + + BugReport(Kind K, const BugType &BT, StringRef ShortDescription, + StringRef Description) + : K(K), BT(BT), ShortDescription(ShortDescription), + Description(Description) {} + +public: + virtual ~BugReport() = default; + + Kind getKind() const { return K; } + + const BugType& getBugType() const { return BT; } + + /// A verbose warning message that is appropriate for displaying next to + /// the source code that introduces the problem. The description should be + /// at least a full sentence starting with a capital letter. The period at + /// the end of the warning is traditionally omitted. If the description + /// consists of multiple sentences, periods between the sentences are + /// encouraged, but the period at the end of the description is still omitted. + StringRef getDescription() const { return Description; } + + /// A short general warning message that is appropriate for displaying in + /// the list of all reported bugs. It should describe what kind of bug is found + /// but does not need to try to go into details of that specific bug. + /// Grammatical conventions of getDescription() apply here as well. + StringRef getShortDescription(bool UseFallback = true) const { + if (ShortDescription.empty() && UseFallback) + return Description; + return ShortDescription; + } + + /// The primary location of the bug report that points at the undesirable + /// behavior in the code. UIs should attach the warning description to this + /// location. The warning description should describe the bad behavior + /// at this location. + virtual PathDiagnosticLocation getLocation() const = 0; + + /// The smallest declaration that contains the bug location. + /// This is purely cosmetic; the declaration can be displayed to the user + /// but it does not affect whether the report is emitted. + virtual const Decl *getDeclWithIssue() const = 0; + + /// Get the location on which the report should be uniqued. Two warnings are + /// considered to be equivalent whenever they have the same bug types, + /// descriptions, and uniqueing locations. Out of a class of equivalent + /// warnings only one gets displayed to the user. For most warnings the + /// uniqueing location coincides with their location, but sometimes + /// it makes sense to use different locations. For example, a leak + /// checker can place the warning at the location where the last reference + /// to the leaking resource is dropped but at the same time unique the warning + /// by where that resource is acquired (allocated). + virtual PathDiagnosticLocation getUniqueingLocation() const = 0; + + /// Get the declaration that corresponds to (usually contains) the uniqueing + /// location. This is not actively used for uniqueing, i.e. otherwise + /// identical reports that have different uniqueing decls will be considered + /// equivalent. + virtual const Decl *getUniqueingDecl() const = 0; + + /// Add new item to the list of additional notes that need to be attached to + /// this report. If the report is path-sensitive, these notes will not be + /// displayed as part of the execution path explanation, but will be displayed + /// separately. Use bug visitors if you need to add an extra path note. + 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)); + } + + ArrayRef> getNotes() { + return Notes; + } + + /// 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 ArrayRef getRanges() const { + return Ranges; + } + + /// Add a fix-it hint to the bug report. + /// + /// Fix-it hints are the suggested edits to the code that would resolve + /// the problem explained by the bug report. Fix-it hints should be + /// as conservative as possible because it is not uncommon for the user + /// to blindly apply all fixits to their project. Note that it is very hard + /// to produce a good fix-it hint for most path-sensitive warnings. + void addFixItHint(const FixItHint &F) { + Fixits.push_back(F); + } + + llvm::ArrayRef getFixits() const { return Fixits; } + + /// Reports are uniqued to ensure that we do not emit multiple diagnostics + /// for each bug. + virtual void Profile(llvm::FoldingSetNodeID& hash) const = 0; +}; + +class BasicBugReport : public BugReport { PathDiagnosticLocation Location; - PathDiagnosticLocation UniqueingLocation; - const Decl *UniqueingDecl; + const Decl *DeclWithIssue = nullptr; + +public: + BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l) + : BugReport(Kind::Basic, bt, desc), Location(l) {} + + static bool classof(const BugReport *R) { + return R->getKind() == Kind::Basic; + } + + PathDiagnosticLocation getLocation() const override { + assert(Location.isValid()); + return Location; + } + + const Decl *getDeclWithIssue() const override { + return DeclWithIssue; + } + + PathDiagnosticLocation getUniqueingLocation() const override { + return getLocation(); + } + + const Decl *getUniqueingDecl() const override { + return getDeclWithIssue(); + } + + /// 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; + } + + void Profile(llvm::FoldingSetNodeID& hash) const override; +}; + +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; - SmallVector Ranges; + + /// The range that corresponds to ErrorNode's program point. It is usually + /// highlighted in the report. const SourceRange ErrorNodeRange; - NoteList Notes; - SmallVector Fixits; + + /// Profile to identify equivalent bug reports for error report coalescing. /// A (stack of) a set of symbols that are registered with this /// report as being "interesting", and thus used to help decide which @@ -145,65 +306,50 @@ /// 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; - BugReport(const BugType &bt, StringRef shortDesc, StringRef desc, - const ExplodedNode *errornode) - : BT(bt), ShortDescription(shortDesc), Description(desc), - ErrorNode(errornode), + const Stmt *getStmt() const; + +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()) {} - /// Create a BugReport with a custom uniqueing location. + /// Create a PathSensitiveBugReport with a custom uniqueing location. /// /// The reports that have the same report location, description, bug type, and /// ranges are uniqued - only one of the equivalent reports will be presented /// 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; } @@ -211,6 +357,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; + + ArrayRef getRanges() const override; + + PathDiagnosticLocation getLocation() const override; + /// Marks a symbol as interesting. Different kinds of interestingness will /// be processed differently by visitors (e.g. if the tracking kind is /// condition, will append "will be used as a condition" to the message). @@ -265,87 +427,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 = {}, - ArrayRef Fixits = {}) { - auto P = std::make_shared(Pos, Msg); - - for (const auto &R : Ranges) - P->addRange(R); - - for (const auto &F : Fixits) - P->addFixit(F); - - Notes.push_back(std::move(P)); - } - - 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 the 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; - - /// Add a fix-it hint to the warning message of the bug report. - /// - /// Fix-it hints are the suggested edits to the code that would resolve - /// the problem explained by the bug report. Fix-it hints should be - /// as conservative as possible because it is not uncommon for the user - /// to blindly apply all fixits to their project. It usually is very hard - /// to produce a good fix-it hint for most path-sensitive warnings. - /// Fix-it hints can also be added to notes through the addNote() interface. - void addFixItHint(const FixItHint &F) { - Fixits.push_back(F); - } - - ArrayRef getFixits() const { return Fixits; } + /// 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. /// @@ -370,11 +455,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; }; //===----------------------------------------------------------------------===// @@ -435,12 +515,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; @@ -469,18 +543,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, @@ -501,12 +569,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) {} @@ -524,9 +614,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: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ cfe/trunk/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. @@ -228,40 +229,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. @@ -280,7 +283,7 @@ const Expr *ParentEx, raw_ostream &Out, BugReporterContext &BRC, - BugReport &R, + PathSensitiveBugReport &R, const ExplodedNode *N, Optional &prunable, bool IsSameFieldName); @@ -304,12 +307,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 @@ -332,7 +335,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; class SuppressInlineDefensiveChecksVisitor final : public BugReporterVisitor { @@ -361,7 +364,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 @@ -379,10 +382,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; }; @@ -393,7 +396,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &R) override; + PathSensitiveBugReport &R) override; }; } // namespace ento Index: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -282,8 +282,7 @@ /// Create a location corresponding to the next valid ExplodedNode as end /// of path location. - static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N, - const SourceManager &SM); + static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N); /// Convert the given location into a single kind location. static PathDiagnosticLocation createSingleLocation( Index: cfe/trunk/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp =================================================================== --- cfe/trunk/lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -570,7 +570,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()); @@ -587,7 +587,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); @@ -611,7 +611,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)); } @@ -626,7 +626,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)); @@ -648,7 +649,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: cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ConversionChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/DebugCheckers.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp +++ cfe/trunk/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. @@ -911,8 +911,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) @@ -921,7 +921,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: cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -736,7 +736,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: cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -1590,7 +1590,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)); } @@ -1599,7 +1600,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)); @@ -1609,7 +1611,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)); @@ -1618,7 +1621,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: cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp +++ cfe/trunk/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 { @@ -999,7 +999,8 @@ PathDiagnosticPieceRef NonLocalizedStringBRVisitor::VisitNode(const ExplodedNode *Succ, - BugReporterContext &BRC, BugReport &BR) { + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { if (Satisfied) return nullptr; Index: cfe/trunk/lib/StaticAnalyzer/Checkers/MIGChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MIGChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -524,17 +524,16 @@ 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; PathDiagnosticLocation L = - PathDiagnosticLocation::createEndOfPath(EndPathNode, - BRC.getSourceManager()); + PathDiagnosticLocation::createEndOfPath(EndPathNode); // Do not add the statement itself as a range in case of leak. return std::make_shared(L, BR.getDescription(), false); @@ -1822,7 +1821,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)); @@ -1846,7 +1846,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()); @@ -1902,7 +1902,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)); @@ -1961,7 +1962,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)); @@ -1987,10 +1989,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); @@ -2021,7 +2024,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"), @@ -2050,7 +2053,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); @@ -2078,8 +2081,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) { @@ -2118,7 +2121,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)); @@ -2343,7 +2347,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); @@ -2905,8 +2909,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: cfe/trunk/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp @@ -196,7 +196,8 @@ << IdxOfArg << llvm::getOrdinalSuffix(IdxOfArg) << " parameter expecting 'nonnull'"; - auto R = std::make_unique(*BTAttrNonNull, SBuf, ErrorNode); + auto R = + std::make_unique(*BTAttrNonNull, SBuf, ErrorNode); if (ArgE) bugreporter::trackExpressionValue(ErrorNode, ArgE, *R); @@ -208,7 +209,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: cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h +++ cfe/trunk/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; @@ -67,16 +67,17 @@ ExplodedNode *n, SymbolRef sym, StringRef endText); - llvm::iterator_range getRanges() const override { + ArrayRef getRanges() const override { if (!isLeak) - return BugReport::getRanges(); - return llvm::make_range(ranges_iterator(), ranges_iterator()); + return PathSensitiveBugReport::getRanges(); + return {}; } }; class RefLeakReport : public RefCountReport { const MemRegion* AllocBinding; const Stmt *AllocStmt; + PathDiagnosticLocation Location; // Finds the function declaration where a leak warning for the parameter // 'sym' should be raised. @@ -90,7 +91,7 @@ RefLeakReport(const RefCountBug &D, const LangOptions &LOpts, ExplodedNode *n, SymbolRef sym, CheckerContext &Ctx); - PathDiagnosticLocation getLocation(const SourceManager &SM) const override { + PathDiagnosticLocation getLocation() const override { assert(Location.isValid()); return Location; } Index: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp +++ cfe/trunk/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. @@ -736,13 +738,11 @@ const MemRegion* FirstBinding = AllocI.R; BR.markInteresting(AllocI.InterestingMethodContext); - const SourceManager& SM = BRC.getSourceManager(); - // Compute an actual location for the leak. Sometimes a leak doesn't // occur at an actual statement (e.g., transition between blocks; end // of function) so we need to walk the graph and compute a real location. const ExplodedNode *LeakN = EndN; - PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(LeakN, SM); + PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(LeakN); std::string sbuf; llvm::raw_string_ostream os(sbuf); @@ -813,9 +813,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 +823,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: cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/StreamChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/Taint.h =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/Taint.h +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/Taint.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/Taint.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp @@ -79,19 +79,19 @@ } PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC, const ExplodedNode *EndPathNode, - BugReport &BR) override { + PathSensitiveBugReport &BR) override { if (!IsLeak) return nullptr; - PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath( - EndPathNode, BRC.getSourceManager()); + PathDiagnosticLocation L = + PathDiagnosticLocation::createEndOfPath(EndPathNode); // Do not add the statement itself as a range in case of leak. return std::make_shared(L, BR.getDescription(), false); } PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; private: const MemRegion *Reg; @@ -256,7 +256,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)); @@ -297,7 +297,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); @@ -377,7 +377,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: cfe/trunk/lib/StaticAnalyzer/Checkers/VforkChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/VforkChecker.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp @@ -146,7 +146,7 @@ return; } - auto Report = std::make_unique(*BT, OS.str(), N); + auto Report = std::make_unique(*BT, OS.str(), N); if (ShowFixIts && !IsPure) { // FIXME: These hints are valid only when the virtual call is made Index: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp +++ cfe/trunk/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(); @@ -1263,13 +1266,23 @@ } 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(), + BT.getCheckName(), R->getDeclWithIssue(), BT.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( + BT.getCheckName(), R->getDeclWithIssue(), BT.getName(), + R->getDescription(), R->getShortDescription(/*UseFallback=*/false), + BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(), findExecutedLines(SM, R->getErrorNode())); } @@ -1909,7 +1922,7 @@ PathDiagnosticConstruct::PathDiagnosticConstruct( const PathDiagnosticConsumer *PDC, const ExplodedNode *ErrorNode, - const BugReport *R) + const PathSensitiveBugReport *R) : Consumer(PDC), CurrentNode(ErrorNode), SM(CurrentNode->getCodeDecl().getASTContext().getSourceManager()), PD(generateEmptyDiagnosticForReport(R, getSourceManager())) { @@ -1918,7 +1931,7 @@ 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), @@ -1929,7 +1942,6 @@ PathDiagnosticConstruct Construct(PDC, ErrorNode, R); const SourceManager &SM = getSourceManager(); - const BugReport *R = getBugReport(); const AnalyzerOptions &Opts = getAnalyzerOptions(); StringRef ErrorTag = ErrorNode->getLocation().getTag()->getTagDescription(); @@ -2050,7 +2062,8 @@ // Methods for BugReport and subclasses. //===----------------------------------------------------------------------===// -void BugReport::addVisitor(std::unique_ptr visitor) { +void PathSensitiveBugReport::addVisitor( + std::unique_ptr visitor) { if (!visitor) return; @@ -2065,14 +2078,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,14 +2091,28 @@ return LC->getStackFrame()->getDecl(); } -void BugReport::Profile(llvm::FoldingSetNodeID& hash) const { +void BasicBugReport::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(); if (UL.isValid()) { UL.Profile(hash); - } else if (Location.isValid()) { - Location.Profile(hash); } else { assert(ErrorNode); hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode)); @@ -2131,8 +2155,8 @@ "have, if it was already marked as interesting with a different kind!"); } -void BugReport::markInteresting(SymbolRef sym, - bugreporter::TrackingKind TKind) { +void PathSensitiveBugReport::markInteresting(SymbolRef sym, + bugreporter::TrackingKind TKind) { if (!sym) return; @@ -2142,8 +2166,8 @@ markInteresting(meta->getRegion(), TKind); } -void BugReport::markInteresting(const MemRegion *R, - bugreporter::TrackingKind TKind) { +void PathSensitiveBugReport::markInteresting(const MemRegion *R, + bugreporter::TrackingKind TKind) { if (!R) return; @@ -2154,19 +2178,20 @@ markInteresting(SR->getSymbol(), TKind); } -void BugReport::markInteresting(SVal V, bugreporter::TrackingKind TKind) { +void PathSensitiveBugReport::markInteresting(SVal V, + bugreporter::TrackingKind TKind) { markInteresting(V.getAsRegion(), TKind); markInteresting(V.getAsSymbol(), TKind); } -void BugReport::markInteresting(const LocationContext *LC) { +void PathSensitiveBugReport::markInteresting(const LocationContext *LC) { if (!LC) return; InterestingLocationContexts.insert(LC); } Optional -BugReport::getInterestingnessKind(SVal V) const { +PathSensitiveBugReport::getInterestingnessKind(SVal V) const { auto RKind = getInterestingnessKind(V.getAsRegion()); auto SKind = getInterestingnessKind(V.getAsSymbol()); if (!RKind) @@ -2191,7 +2216,7 @@ } Optional -BugReport::getInterestingnessKind(SymbolRef sym) const { +PathSensitiveBugReport::getInterestingnessKind(SymbolRef sym) const { if (!sym) return None; // We don't currently consider metadata symbols to be interesting @@ -2203,7 +2228,7 @@ } Optional -BugReport::getInterestingnessKind(const MemRegion *R) const { +PathSensitiveBugReport::getInterestingnessKind(const MemRegion *R) const { if (!R) return None; @@ -2217,25 +2242,25 @@ return None; } -bool BugReport::isInteresting(SVal V) const { +bool PathSensitiveBugReport::isInteresting(SVal V) const { return getInterestingnessKind(V).hasValue(); } -bool BugReport::isInteresting(SymbolRef sym) const { +bool PathSensitiveBugReport::isInteresting(SymbolRef sym) const { return getInterestingnessKind(sym).hasValue(); } -bool BugReport::isInteresting(const MemRegion *R) const { +bool PathSensitiveBugReport::isInteresting(const MemRegion *R) const { return getInterestingnessKind(R).hasValue(); } -bool BugReport::isInteresting(const LocationContext *LC) const { +bool PathSensitiveBugReport::isInteresting(const LocationContext *LC) const { if (!LC) return false; return InterestingLocationContexts.count(LC); } -const Stmt *BugReport::getStmt() const { +const Stmt *PathSensitiveBugReport::getStmt() const { if (!ErrorNode) return nullptr; @@ -2253,31 +2278,19 @@ return S; } -llvm::iterator_range BugReport::getRanges() const { +ArrayRef +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())) - 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()); + if (Ranges.empty() && isa_and_nonnull(getStmt())) + return ErrorNodeRange; - return llvm::make_range(Ranges.begin(), Ranges.end()); + return Ranges; } -PathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const { - if (ErrorNode) { - assert(!Location.isValid() && - "Either Location or ErrorNode should be specified but not both."); - return PathDiagnosticLocation::createEndOfPath(ErrorNode, SM); - } - - assert(Location.isValid()); - return Location; +PathDiagnosticLocation +PathSensitiveBugReport::getLocation() const { + return PathDiagnosticLocation::createEndOfPath(ErrorNode); } //===----------------------------------------------------------------------===// @@ -2326,7 +2339,7 @@ class BugPathInfo { public: std::unique_ptr BugPath; - BugReport *Report; + PathSensitiveBugReport *Report; const ExplodedNode *ErrorNode; }; @@ -2342,7 +2355,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; @@ -2377,7 +2391,7 @@ public: BugPathGetter(const ExplodedGraph *OriginalGraph, - ArrayRef &bugReports); + ArrayRef &bugReports); BugPathInfo *getNextBugPath(); }; @@ -2385,7 +2399,7 @@ } // namespace BugPathGetter::BugPathGetter(const ExplodedGraph *OriginalGraph, - ArrayRef &bugReports) { + ArrayRef &bugReports) { SmallVector Nodes; for (const auto I : bugReports) { assert(I->isValid() && @@ -2404,7 +2418,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 " @@ -2592,11 +2606,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}. @@ -2646,15 +2661,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; @@ -2700,7 +2715,7 @@ std::unique_ptr PathSensitiveBugReporter::generatePathDiagnostics( ArrayRef consumers, - ArrayRef &bugReports) { + ArrayRef &bugReports) { assert(!bugReports.empty()); auto Out = std::make_unique(); @@ -2720,24 +2735,7 @@ } 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(); + bool ValidSourceLoc = R->getLocation().isValid(); assert(ValidSourceLoc); // If we mess up in a release build, we'd still prefer to just drop the bug // instead of trying to go on. @@ -2760,6 +2758,28 @@ 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. //===----------------------------------------------------------------------===// @@ -2776,9 +2796,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(); @@ -2789,10 +2808,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; @@ -2807,19 +2825,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; } @@ -2852,9 +2871,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; } @@ -2885,7 +2904,7 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) { SmallVector bugReports; - BugReport *report = FindReportInEquivalenceClass(EQ, bugReports); + BugReport *report = findReportInEquivalenceClass(EQ, bugReports); if (!report) return; @@ -2900,7 +2919,7 @@ // If the path is empty, generate a single step path with the location // of the issue. if (PD->path.empty()) { - PathDiagnosticLocation L = report->getLocation(getSourceManager()); + PathDiagnosticLocation L = report->getLocation(); auto piece = std::make_unique( L, report->getDescription()); for (SourceRange Range : report->getRanges()) @@ -3015,16 +3034,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 @@ -3032,8 +3059,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; @@ -3068,7 +3100,7 @@ ArrayRef Fixits) { // '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 (const auto &SR : Ranges) R->addRange(SR); Index: cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -215,7 +215,7 @@ static bool isVarAnInterestingCondition(const Expr *CondVarExpr, const ExplodedNode *N, - const BugReport *B) { + const PathSensitiveBugReport *B) { // Even if this condition is marked as interesting, it isn't *that* // interesting if it didn't happen in a nested stackframe, the user could just // follow the arrows. @@ -230,7 +230,7 @@ } static bool isInterestingExpr(const Expr *E, const ExplodedNode *N, - const BugReport *B) { + const PathSensitiveBugReport *B) { if (Optional V = getSValForVar(E, N)) return B->getInterestingnessKind(*V).hasValue(); return false; @@ -296,19 +296,20 @@ 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) { - PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath( - EndPathNode, BRC.getSourceManager()); + const PathSensitiveBugReport &BR) { + PathDiagnosticLocation L = + PathDiagnosticLocation::createEndOfPath(EndPathNode); const auto &Ranges = BR.getRanges(); @@ -376,7 +377,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, @@ -410,10 +411,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. @@ -542,9 +543,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(); @@ -656,7 +657,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) { @@ -803,7 +804,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override { + PathSensitiveBugReport &BR) override { if (WasModified) return nullptr; @@ -829,7 +830,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 && @@ -923,7 +924,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)) @@ -1003,7 +1004,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; @@ -1130,10 +1131,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(); @@ -1179,7 +1178,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override { + PathSensitiveBugReport &BR) override { switch (Mode) { case Initial: return visitNodeInitial(N, BRC, BR); @@ -1193,7 +1192,7 @@ } void finalizeVisitor(BugReporterContext &, const ExplodedNode *, - BugReport &BR) override { + PathSensitiveBugReport &BR) override { if (EnableNullFPSuppression && ShouldInvalidate) BR.markInvalid(ReturnVisitor::getTag(), CalleeSFC); } @@ -1316,9 +1315,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()) { @@ -1363,7 +1361,8 @@ PathDiagnosticPieceRef FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, - BugReporterContext &BRC, BugReport &BR) { + BugReporterContext &BRC, + PathSensitiveBugReport &BR) { if (Satisfied) return nullptr; @@ -1540,9 +1539,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; @@ -1620,8 +1618,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; @@ -1722,7 +1722,7 @@ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N, BugReporterContext &BRC, - BugReport &BR) override; + PathSensitiveBugReport &BR) override; }; } // end of anonymous namespace @@ -1778,8 +1778,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; @@ -1925,7 +1927,8 @@ } bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode, - const Expr *E, BugReport &report, + const Expr *E, + PathSensitiveBugReport &report, bugreporter::TrackingKind TKind, bool EnableNullFPSuppression) { @@ -2082,9 +2085,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; @@ -2127,9 +2130,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()); @@ -2141,7 +2144,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(); @@ -2179,7 +2183,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 @@ -2236,8 +2241,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(); @@ -2307,7 +2312,7 @@ const Expr *ParentEx, raw_ostream &Out, BugReporterContext &BRC, - BugReport &report, + PathSensitiveBugReport &report, const ExplodedNode *N, Optional &prunable, bool IsSameFieldName) { @@ -2392,7 +2397,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; @@ -2511,7 +2517,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) @@ -2538,7 +2544,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; @@ -2573,7 +2580,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); @@ -2659,7 +2667,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(); @@ -2730,7 +2739,7 @@ // Skip reports within the sys/queue.h macros as we do not have the ability to // reason about data structure shapes. const SourceManager &SM = BRC.getSourceManager(); - FullSourceLoc Loc = BR.getLocation(SM).asLocation(); + FullSourceLoc Loc = BR.getLocation().asLocation(); while (Loc.isMacroID()) { Loc = Loc.getSpellingLoc(); if (SM.getFilename(Loc).endswith("sys/queue.h")) { @@ -2744,9 +2753,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(); @@ -2802,7 +2811,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); @@ -2837,9 +2847,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 = @@ -2875,7 +2884,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: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -3004,9 +3004,13 @@ llvm::make_range(BR.EQClasses_begin(), BR.EQClasses_end()); for (const auto &EQ : EQClasses) { - for (const BugReport &Report : EQ) { - if (Report.getErrorNode()->getState() == N->getState() && - Report.getErrorNode()->getLocation() == N->getLocation()) + for (const BugReport &R : EQ) { + const auto *PR = dyn_cast(&R); + if (!PR) + continue; + const ExplodedNode *EN = PR->getErrorNode(); + if (EN->getState() == N->getState() && + EN->getLocation() == N->getLocation()) return true; } } @@ -3131,8 +3135,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 { Index: cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -850,11 +850,12 @@ } PathDiagnosticLocation - PathDiagnosticLocation::createEndOfPath(const ExplodedNode *N, - const SourceManager &SM) { +PathDiagnosticLocation::createEndOfPath(const ExplodedNode *N) { assert(N && "Cannot create a location with a null node."); const Stmt *S = getStmt(N); const LocationContext *LC = N->getLocationContext(); + SourceManager &SM = + N->getState()->getStateManager().getContext().getSourceManager(); if (!S) { // If this is an implicit call, return the implicit call point location.