aboutsummaryrefslogtreecommitdiffstats
path: root/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h')
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h217
1 files changed, 125 insertions, 92 deletions
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
index ef5d327d39da..de0ee5de81b5 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
@@ -33,11 +33,12 @@ class Stmt;
namespace ento {
-class BugReport;
+class PathSensitiveBugReport;
class BugReporterContext;
class ExplodedNode;
class MemRegion;
class PathDiagnosticPiece;
+using PathDiagnosticPieceRef = std::shared_ptr<PathDiagnosticPiece>;
/// BugReporterVisitors are used to add custom diagnostics along a path.
class BugReporterVisitor : public llvm::FoldingSetNode {
@@ -57,32 +58,68 @@ public:
///
/// The last parameter can be used to register a new visitor with the given
/// BugReport while processing a node.
- virtual std::shared_ptr<PathDiagnosticPiece>
- VisitNode(const ExplodedNode *Succ,
- BugReporterContext &BRC, BugReport &BR) = 0;
+ virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ,
+ BugReporterContext &BRC,
+ 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 std::shared_ptr<PathDiagnosticPiece>
- 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 std::shared_ptr<PathDiagnosticPiece>
- getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N,
- BugReport &BR);
+ static PathDiagnosticPieceRef
+ getDefaultEndPath(const BugReporterContext &BRC, const ExplodedNode *N,
+ const PathSensitiveBugReport &BR);
};
+namespace bugreporter {
+
+/// Specifies the type of tracking for an expression.
+enum class TrackingKind {
+ /// Default tracking kind -- specifies that as much information should be
+ /// gathered about the tracked expression value as possible.
+ Thorough,
+ /// Specifies that a more moderate tracking should be used for the expression
+ /// value. This will essentially make sure that functions relevant to the it
+ /// aren't pruned, but otherwise relies on the user reading the code or
+ /// following the arrows.
+ Condition
+};
+
+/// Attempts to add visitors to track expression value back to its point of
+/// origin.
+///
+/// \param N A node "downstream" from the evaluation of the statement.
+/// \param E The expression value which we are tracking
+/// \param R The bug report to which visitors should be attached.
+/// \param EnableNullFPSuppression Whether we should employ false positive
+/// suppression (inlined defensive checks, returned null).
+///
+/// \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,
+ PathSensitiveBugReport &R,
+ TrackingKind TKind = TrackingKind::Thorough,
+ bool EnableNullFPSuppression = true);
+
+const Expr *getDerefExpr(const Stmt *S);
+
+} // namespace bugreporter
+
/// Finds last store into the given region,
/// which is different from a given symbolic value.
class FindLastStoreBRVisitor final : public BugReporterVisitor {
@@ -94,21 +131,34 @@ class FindLastStoreBRVisitor final : public BugReporterVisitor {
/// bug, we are going to employ false positive suppression.
bool EnableNullFPSuppression;
-public:
- /// Creates a visitor for every VarDecl inside a Stmt and registers it with
- /// the BugReport.
- static void registerStatementVarDecls(BugReport &BR, const Stmt *S,
- bool EnableNullFPSuppression);
+ using TrackingKind = bugreporter::TrackingKind;
+ TrackingKind TKind;
+ const StackFrameContext *OriginSFC;
+public:
+ /// \param V We're searching for the store where \c R received this value.
+ /// \param R The region we're tracking.
+ /// \param TKind May limit the amount of notes added to the bug report.
+ /// \param OriginSFC Only adds notes when the last store happened in a
+ /// different stackframe to this one. Disregarded if the tracking kind
+ /// is thorough.
+ /// This is useful, because for non-tracked regions, notes about
+ /// changes to its value in a nested stackframe could be pruned, and
+ /// this visitor can prevent that without polluting the bugpath too
+ /// much.
FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R,
- bool InEnableNullFPSuppression)
- : R(R), V(V), EnableNullFPSuppression(InEnableNullFPSuppression) {}
+ bool InEnableNullFPSuppression, TrackingKind TKind,
+ const StackFrameContext *OriginSFC = nullptr)
+ : R(R), V(V), EnableNullFPSuppression(InEnableNullFPSuppression),
+ TKind(TKind), OriginSFC(OriginSFC) {
+ assert(R);
+ }
void Profile(llvm::FoldingSetNodeID &ID) const override;
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
};
class TrackConstraintBRVisitor final : public BugReporterVisitor {
@@ -132,9 +182,9 @@ public:
/// to make all PathDiagnosticPieces created by this visitor.
static const char *getTag();
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
private:
/// Checks if the constraint is valid in the current state.
@@ -150,9 +200,9 @@ public:
ID.AddPointer(&x);
}
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
/// If the statement is a message send expression with nil receiver, returns
/// the receiver expression. Returns NULL otherwise.
@@ -162,8 +212,10 @@ public:
/// Visitor that tries to report interesting diagnostics from conditions.
class ConditionBRVisitor final : public BugReporterVisitor {
// FIXME: constexpr initialization isn't supported by MSVC2013.
- static const char *const GenericTrueMessage;
- static const char *const GenericFalseMessage;
+ constexpr static llvm::StringLiteral GenericTrueMessage =
+ "Assuming the condition is true";
+ constexpr static llvm::StringLiteral GenericFalseMessage =
+ "Assuming the condition is false";
public:
void Profile(llvm::FoldingSetNodeID &ID) const override {
@@ -175,41 +227,44 @@ public:
/// to make all PathDiagnosticPieces created by this visitor.
static const char *getTag();
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
- std::shared_ptr<PathDiagnosticPiece> VisitNodeImpl(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR);
+ PathDiagnosticPieceRef VisitNodeImpl(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR);
- std::shared_ptr<PathDiagnosticPiece>
+ PathDiagnosticPieceRef
VisitTerminator(const Stmt *Term, const ExplodedNode *N,
- const CFGBlock *srcBlk, const CFGBlock *dstBlk, BugReport &R,
- BugReporterContext &BRC);
+ const CFGBlock *SrcBlk, const CFGBlock *DstBlk,
+ PathSensitiveBugReport &R, BugReporterContext &BRC);
- std::shared_ptr<PathDiagnosticPiece>
- VisitTrueTest(const Expr *Cond, BugReporterContext &BRC, BugReport &R,
- const ExplodedNode *N, bool TookTrue);
+ PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &R,
+ const ExplodedNode *N, bool TookTrue);
- std::shared_ptr<PathDiagnosticPiece>
- VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR,
- BugReporterContext &BRC, BugReport &R, const ExplodedNode *N,
- bool TookTrue, bool IsAssuming);
+ PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &R,
+ const ExplodedNode *N, bool TookTrue,
+ bool IsAssuming);
- std::shared_ptr<PathDiagnosticPiece>
+ PathDiagnosticPieceRef
VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr,
- BugReporterContext &BRC, BugReport &R, const ExplodedNode *N,
- bool TookTrue, bool IsAssuming);
+ BugReporterContext &BRC, PathSensitiveBugReport &R,
+ const ExplodedNode *N, bool TookTrue, bool IsAssuming);
- std::shared_ptr<PathDiagnosticPiece>
- VisitTrueTest(const Expr *Cond, const MemberExpr *ME, BugReporterContext &BRC,
- BugReport &R, const ExplodedNode *N, bool TookTrue,
- bool IsAssuming);
+ PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const MemberExpr *ME,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &R,
+ const ExplodedNode *N, bool TookTrue,
+ bool IsAssuming);
- std::shared_ptr<PathDiagnosticPiece>
+ 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.
@@ -228,7 +283,7 @@ public:
const Expr *ParentEx,
raw_ostream &Out,
BugReporterContext &BRC,
- BugReport &R,
+ PathSensitiveBugReport &R,
const ExplodedNode *N,
Optional<bool> &prunable,
bool IsSameFieldName);
@@ -251,14 +306,13 @@ public:
ID.AddPointer(getTag());
}
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *,
- BugReporterContext &,
- BugReport &) override {
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *, BugReporterContext &,
+ 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
@@ -279,9 +333,9 @@ public:
ID.AddPointer(R);
}
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
};
class SuppressInlineDefensiveChecksVisitor final : public BugReporterVisitor {
@@ -308,9 +362,9 @@ public:
/// to make all PathDiagnosticPieces created by this visitor.
static const char *getTag();
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *Succ,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
};
/// The bug visitor will walk all the nodes in a path and collect all the
@@ -326,12 +380,12 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &BR) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &BR) override;
void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode,
- BugReport &BR) override;
+ PathSensitiveBugReport &BR) override;
};
@@ -340,32 +394,11 @@ class TagVisitor : public BugReporterVisitor {
public:
void Profile(llvm::FoldingSetNodeID &ID) const override;
- std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
- BugReporterContext &BRC,
- BugReport &R) override;
+ PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
+ BugReporterContext &BRC,
+ PathSensitiveBugReport &R) override;
};
-namespace bugreporter {
-
-/// Attempts to add visitors to track expression value back to its point of
-/// origin.
-///
-/// \param N A node "downstream" from the evaluation of the statement.
-/// \param E The expression value which we are tracking
-/// \param R The bug report to which visitors should be attached.
-/// \param EnableNullFPSuppression Whether we should employ false positive
-/// suppression (inlined defensive checks, returned null).
-///
-/// \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 EnableNullFPSuppression = true);
-
-const Expr *getDerefExpr(const Stmt *S);
-
-} // namespace bugreporter
-
} // namespace ento
} // namespace clang