summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
diff options
context:
space:
mode:
authorAdam Balogh <adam.balogh@ericsson.com>2018-09-10 09:05:31 +0000
committerAdam Balogh <adam.balogh@ericsson.com>2018-09-10 09:05:31 +0000
commit3659f7a8a98393cefa14e4f8b467f7258dcf9aed (patch)
tree55bc32b9aa0efbb09d9d8b6ec7a13b6fb52444d5 /clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
parent6b23b1a74fdd9408fb76157b16f9a703bd90a594 (diff)
downloadbcm5719-llvm-3659f7a8a98393cefa14e4f8b467f7258dcf9aed.tar.gz
bcm5719-llvm-3659f7a8a98393cefa14e4f8b467f7258dcf9aed.zip
[Analyzer] Iterator Checker - Part 6: Mismatched iterator checker for constructors and comparisons
Extension of the mismatched iterator checker for constructors taking range of first..last (first and last must be iterators of the same container) and also for comparisons of iterators of different containers (one does not compare iterators of different containers, since the set of iterators is partially ordered, there are no relations between iterators of different containers, except that they are always non-equal). Differential Revision: https://reviews.llvm.org/D32860 llvm-svn: 341792
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp61
1 files changed, 60 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
index a4c2891e59b..423ed4a2318 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
@@ -236,6 +236,9 @@ class IteratorChecker
void reportMismatchedBug(const StringRef &Message, const SVal &Val1,
const SVal &Val2, CheckerContext &C,
ExplodedNode *ErrNode) const;
+ void reportMismatchedBug(const StringRef &Message, const SVal &Val,
+ const MemRegion *Reg, CheckerContext &C,
+ ExplodedNode *ErrNode) const;
void reportInvalidatedBug(const StringRef &Message, const SVal &Val,
CheckerContext &C, ExplodedNode *ErrNode) const;
@@ -276,6 +279,7 @@ namespace {
bool isIteratorType(const QualType &Type);
bool isIterator(const CXXRecordDecl *CRD);
+bool isComparisonOperator(OverloadedOperatorKind OK);
bool isBeginCall(const FunctionDecl *Func);
bool isEndCall(const FunctionDecl *Func);
bool isAssignmentOperator(OverloadedOperatorKind OK);
@@ -397,8 +401,48 @@ void IteratorChecker::checkPreCall(const CallEvent &Call,
} else {
verifyDereference(C, Call.getArgSVal(0));
}
+ } else if (ChecksEnabled[CK_MismatchedIteratorChecker] &&
+ isComparisonOperator(Func->getOverloadedOperator())) {
+ // Check for comparisons of iterators of different containers
+ if (const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
+ if (Call.getNumArgs() < 1)
+ return;
+
+ if (!isIteratorType(InstCall->getCXXThisExpr()->getType()) ||
+ !isIteratorType(Call.getArgExpr(0)->getType()))
+ return;
+
+ verifyMatch(C, InstCall->getCXXThisVal(), Call.getArgSVal(0));
+ } else {
+ if (Call.getNumArgs() < 2)
+ return;
+
+ if (!isIteratorType(Call.getArgExpr(0)->getType()) ||
+ !isIteratorType(Call.getArgExpr(1)->getType()))
+ return;
+
+ verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
+ }
}
- } else if (!isa<CXXConstructorCall>(&Call)) {
+ } else if (isa<CXXConstructorCall>(&Call)) {
+ // Check match of first-last iterator pair in a constructor of a container
+ if (Call.getNumArgs() < 2)
+ return;
+
+ const auto *Ctr = cast<CXXConstructorDecl>(Call.getDecl());
+ if (Ctr->getNumParams() < 2)
+ return;
+
+ if (Ctr->getParamDecl(0)->getName() != "first" ||
+ Ctr->getParamDecl(1)->getName() != "last")
+ return;
+
+ if (!isIteratorType(Call.getArgExpr(0)->getType()) ||
+ !isIteratorType(Call.getArgExpr(1)->getType()))
+ return;
+
+ verifyMatch(C, Call.getArgSVal(0), Call.getArgSVal(1));
+ } else {
// The main purpose of iterators is to abstract away from different
// containers and provide a (maybe limited) uniform access to them.
// This implies that any correctly written template function that
@@ -1102,6 +1146,16 @@ void IteratorChecker::reportMismatchedBug(const StringRef &Message,
C.emitReport(std::move(R));
}
+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);
+ R->markInteresting(Val);
+ R->markInteresting(Reg);
+ C.emitReport(std::move(R));
+}
+
void IteratorChecker::reportInvalidatedBug(const StringRef &Message,
const SVal &Val, CheckerContext &C,
ExplodedNode *ErrNode) const {
@@ -1173,6 +1227,11 @@ bool isIterator(const CXXRecordDecl *CRD) {
HasPostIncrOp && HasDerefOp;
}
+bool isComparisonOperator(OverloadedOperatorKind OK) {
+ return OK == OO_EqualEqual || OK == OO_ExclaimEqual || OK == OO_Less ||
+ OK == OO_LessEqual || OK == OO_Greater || OK == OO_GreaterEqual;
+}
+
bool isBeginCall(const FunctionDecl *Func) {
const auto *IdInfo = Func->getIdentifier();
if (!IdInfo)
OpenPOWER on IntegriCloud