aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/IteratorChecker.cpp')
-rw-r--r--lib/StaticAnalyzer/Checkers/IteratorChecker.cpp51
1 files changed, 28 insertions, 23 deletions
diff --git a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
index 6f1060b5f26d..97ace68569ef 100644
--- a/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
@@ -71,7 +71,7 @@
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
#include <utility>
@@ -248,7 +248,7 @@ public:
};
DefaultBool ChecksEnabled[CK_NumCheckKinds];
- CheckName CheckNames[CK_NumCheckKinds];
+ CheckerNameRef CheckNames[CK_NumCheckKinds];
void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
@@ -356,14 +356,12 @@ bool isZero(ProgramStateRef State, const NonLoc &Val);
IteratorChecker::IteratorChecker() {
OutOfRangeBugType.reset(
- new BugType(this, "Iterator out of range", "Misuse of STL APIs",
- /*SuppressOnSink=*/true));
+ new BugType(this, "Iterator out of range", "Misuse of STL APIs"));
MismatchedBugType.reset(
new BugType(this, "Iterator(s) mismatched", "Misuse of STL APIs",
/*SuppressOnSink=*/true));
InvalidatedBugType.reset(
- new BugType(this, "Iterator invalidated", "Misuse of STL APIs",
- /*SuppressOnSink=*/true));
+ new BugType(this, "Iterator invalidated", "Misuse of STL APIs"));
}
void IteratorChecker::checkPreCall(const CallEvent &Call,
@@ -406,13 +404,15 @@ void IteratorChecker::checkPreCall(const CallEvent &Call,
} else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
// Check for out-of-range incrementions and decrementions
- if (Call.getNumArgs() >= 1) {
+ if (Call.getNumArgs() >= 1 &&
+ Call.getArgExpr(0)->getType()->isIntegralOrEnumerationType()) {
verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
InstCall->getCXXThisVal(),
Call.getArgSVal(0));
}
} else {
- if (Call.getNumArgs() >= 2) {
+ if (Call.getNumArgs() >= 2 &&
+ Call.getArgExpr(1)->getType()->isIntegralOrEnumerationType()) {
verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
Call.getArgSVal(0), Call.getArgSVal(1));
}
@@ -565,7 +565,8 @@ void IteratorChecker::checkPostCall(const CallEvent &Call,
if (Func->isOverloadedOperator()) {
const auto Op = Func->getOverloadedOperator();
if (isAssignmentOperator(Op)) {
- const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call);
+ // Overloaded 'operator=' must be a non-static member function.
+ const auto *InstCall = cast<CXXInstanceCall>(&Call);
if (cast<CXXMethodDecl>(Func)->isMoveAssignmentOperator()) {
handleAssign(C, InstCall->getCXXThisVal(), Call.getOriginExpr(),
Call.getArgSVal(0));
@@ -590,14 +591,16 @@ void IteratorChecker::checkPostCall(const CallEvent &Call,
return;
} else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) {
if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
- if (Call.getNumArgs() >= 1) {
+ if (Call.getNumArgs() >= 1 &&
+ Call.getArgExpr(0)->getType()->isIntegralOrEnumerationType()) {
handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
Call.getReturnValue(),
InstCall->getCXXThisVal(), Call.getArgSVal(0));
return;
}
} else {
- if (Call.getNumArgs() >= 2) {
+ if (Call.getNumArgs() >= 2 &&
+ Call.getArgExpr(1)->getType()->isIntegralOrEnumerationType()) {
handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
Call.getReturnValue(), Call.getArgSVal(0),
Call.getArgSVal(1));
@@ -923,7 +926,7 @@ void IteratorChecker::verifyDereference(CheckerContext &C,
auto State = C.getState();
const auto *Pos = getIteratorPosition(State, Val);
if (Pos && isPastTheEnd(State, *Pos)) {
- auto *N = C.generateNonFatalErrorNode(State);
+ auto *N = C.generateErrorNode(State);
if (!N)
return;
reportOutOfRangeBug("Past-the-end iterator dereferenced.", Val, C, N);
@@ -935,7 +938,7 @@ void IteratorChecker::verifyAccess(CheckerContext &C, const SVal &Val) const {
auto State = C.getState();
const auto *Pos = getIteratorPosition(State, Val);
if (Pos && !Pos->isValid()) {
- auto *N = C.generateNonFatalErrorNode(State);
+ auto *N = C.generateErrorNode(State);
if (!N) {
return;
}
@@ -1043,14 +1046,14 @@ void IteratorChecker::verifyRandomIncrOrDecr(CheckerContext &C,
// The result may be the past-end iterator of the container, but any other
// out of range position is undefined behaviour
if (isAheadOfRange(State, advancePosition(C, Op, *Pos, Value))) {
- auto *N = C.generateNonFatalErrorNode(State);
+ auto *N = C.generateErrorNode(State);
if (!N)
return;
reportOutOfRangeBug("Iterator decremented ahead of its valid range.", LHS,
C, N);
}
if (isBehindPastTheEnd(State, advancePosition(C, Op, *Pos, Value))) {
- auto *N = C.generateNonFatalErrorNode(State);
+ auto *N = C.generateErrorNode(State);
if (!N)
return;
reportOutOfRangeBug("Iterator incremented behind the past-the-end "
@@ -1587,7 +1590,8 @@ IteratorPosition IteratorChecker::advancePosition(CheckerContext &C,
void IteratorChecker::reportOutOfRangeBug(const StringRef &Message,
const SVal &Val, CheckerContext &C,
ExplodedNode *ErrNode) const {
- auto R = llvm::make_unique<BugReport>(*OutOfRangeBugType, Message, ErrNode);
+ auto R = std::make_unique<PathSensitiveBugReport>(*OutOfRangeBugType, Message,
+ ErrNode);
R->markInteresting(Val);
C.emitReport(std::move(R));
}
@@ -1596,7 +1600,8 @@ void IteratorChecker::reportMismatchedBug(const StringRef &Message,
const SVal &Val1, const SVal &Val2,
CheckerContext &C,
ExplodedNode *ErrNode) const {
- auto R = llvm::make_unique<BugReport>(*MismatchedBugType, Message, ErrNode);
+ auto R = std::make_unique<PathSensitiveBugReport>(*MismatchedBugType, Message,
+ ErrNode);
R->markInteresting(Val1);
R->markInteresting(Val2);
C.emitReport(std::move(R));
@@ -1606,7 +1611,8 @@ void IteratorChecker::reportMismatchedBug(const StringRef &Message,
const SVal &Val, const MemRegion *Reg,
CheckerContext &C,
ExplodedNode *ErrNode) const {
- auto R = llvm::make_unique<BugReport>(*MismatchedBugType, Message, ErrNode);
+ auto R = std::make_unique<PathSensitiveBugReport>(*MismatchedBugType, Message,
+ ErrNode);
R->markInteresting(Val);
R->markInteresting(Reg);
C.emitReport(std::move(R));
@@ -1615,7 +1621,8 @@ void IteratorChecker::reportMismatchedBug(const StringRef &Message,
void IteratorChecker::reportInvalidatedBug(const StringRef &Message,
const SVal &Val, CheckerContext &C,
ExplodedNode *ErrNode) const {
- auto R = llvm::make_unique<BugReport>(*InvalidatedBugType, Message, ErrNode);
+ auto R = std::make_unique<PathSensitiveBugReport>(*InvalidatedBugType,
+ Message, ErrNode);
R->markInteresting(Val);
C.emitReport(std::move(R));
}
@@ -2373,12 +2380,10 @@ bool ento::shouldRegisterIteratorModeling(const LangOptions &LO) {
auto *checker = Mgr.getChecker<IteratorChecker>(); \
checker->ChecksEnabled[IteratorChecker::CK_##name] = true; \
checker->CheckNames[IteratorChecker::CK_##name] = \
- Mgr.getCurrentCheckName(); \
+ Mgr.getCurrentCheckerName(); \
} \
\
- bool ento::shouldRegister##name(const LangOptions &LO) { \
- return true; \
- }
+ bool ento::shouldRegister##name(const LangOptions &LO) { return true; }
REGISTER_CHECKER(IteratorRangeChecker)
REGISTER_CHECKER(MismatchedIteratorChecker)