aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2012-08-29 21:22:37 +0000
committerAnna Zaks <ganna@apple.com>2012-08-29 21:22:37 +0000
commit80de487e03dd0f44e4572e2122ebc1aa6a3961f5 (patch)
tree4388c41e6efe5f7600ba369e668d157102adf1a1 /include
parenta484fc73ec6331bcaad092270b4ab9c8d1df23c3 (diff)
[analyzer] Improved diagnostic pruning for calls initializing values.
This heuristic addresses the case when a pointer (or ref) is passed to a function, which initializes the variable (or sets it to something other than '0'). On the branch where the inlined function does not set the value, we report use of undefined value (or NULL pointer dereference). The access happens in the caller and the path through the callee would get pruned away with regular path pruning. To solve this issue, we previously disabled diagnostic pruning completely on undefined and null pointer dereference checks, which entailed very verbose diagnostics in most cases. Furthermore, not all of the undef value checks had the diagnostic pruning disabled. This patch implements the following heuristic: if we pass a pointer (or ref) to the region (on which the error is reported) into a function and it's value is either undef or 'NULL' (and is a pointer), do not prune the function. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162863 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/clang/Analysis/ProgramPoint.h1
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h18
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h28
3 files changed, 46 insertions, 1 deletions
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 5de06cd3a5..e66022c876 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -461,6 +461,7 @@ public:
};
/// Represents a point when we begin processing an inlined call.
+/// CallEnter uses the caller's location context.
class CallEnter : public ProgramPoint {
public:
CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
index 48393a379b..c8581e2e23 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -24,6 +24,7 @@
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/ImmutableSet.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallSet.h"
namespace clang {
@@ -95,6 +96,10 @@ protected:
/// for multiple PathDiagnosticConsumers.
llvm::SmallVector<Regions *, 2> interestingRegions;
+ /// A set of location contexts that correspoind to call sites which should be
+ /// considered "interesting".
+ llvm::SmallSet<const LocationContext *, 2> InterestingLocationContexts;
+
/// A set of custom visitors which generate "event" diagnostics at
/// interesting points in the path.
VisitorList Callbacks;
@@ -172,10 +177,12 @@ public:
void markInteresting(SymbolRef sym);
void markInteresting(const MemRegion *R);
void markInteresting(SVal V);
+ void markInteresting(const LocationContext *LC);
bool isInteresting(SymbolRef sym);
bool isInteresting(const MemRegion *R);
bool isInteresting(SVal V);
+ bool isInteresting(const LocationContext *LC);
unsigned getConfigurationChangeToken() const {
return ConfigurationChangeToken;
@@ -342,6 +349,11 @@ private:
/// A vector of BugReports for tracking the allocated pointers and cleanup.
std::vector<BugReportEquivClass *> EQClassesVector;
+ /// A map from PathDiagnosticPiece to the LocationContext of the inlined
+ /// function call it represents.
+ llvm::DenseMap<const PathDiagnosticCallPiece*,
+ const LocationContext*> LocationContextMap;
+
protected:
BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k),
D(d) {}
@@ -382,6 +394,8 @@ public:
PathDiagnosticConsumer &PC,
ArrayRef<BugReport *> &bugReports) {}
+ bool RemoveUneededCalls(PathPieces &pieces, BugReport *R);
+
void Register(BugType *BT);
/// \brief Add the given report to the set of reports tracked by BugReporter.
@@ -411,6 +425,10 @@ public:
static bool classof(const BugReporter* R) { return true; }
+ void addCallPieceLocationContextPair(const PathDiagnosticCallPiece *C,
+ const LocationContext *LC) {
+ LocationContextMap[C] = LC;
+ }
private:
llvm::StringMap<BugType *> StrBugTypes;
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
index e82b5233d7..f3206964e3 100644
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
+++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
@@ -222,7 +222,33 @@ public:
const ExplodedNode *N,
llvm::Optional<bool> &prunable);
};
-
+
+/// \brief When a region containing undefined value or '0' value is passed
+/// as an argument in a call, marks the call as interesting.
+///
+/// As a result, BugReporter will not prune the path through the function even
+/// if the region's contents are not modified/accessed by the call.
+class UndefOrNullArgVisitor
+ : public BugReporterVisitorImpl<UndefOrNullArgVisitor> {
+
+ /// The interesting memory region this visitor is tracking.
+ const MemRegion *R;
+
+public:
+ UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {}
+
+ virtual void Profile(llvm::FoldingSetNodeID &ID) const {
+ static int Tag = 0;
+ ID.AddPointer(&Tag);
+ ID.AddPointer(R);
+ }
+
+ PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+ const ExplodedNode *PrevN,
+ BugReporterContext &BRC,
+ BugReport &BR);
+};
+
namespace bugreporter {
void trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R);