diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp --- a/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp @@ -264,16 +264,23 @@ CheckerContext &C) const { ProgramStateRef State = C.getState(); BinaryOperatorKind OK = BO->getOpcode(); - SVal RVal = State->getSVal(BO->getRHS(), C.getLocationContext()); + Expr *LHS = BO->getLHS(); + Expr *RHS = BO->getRHS(); + SVal LVal = State->getSVal(LHS, C.getLocationContext()); + SVal RVal = State->getSVal(RHS, C.getLocationContext()); if (isSimpleComparisonOperator(BO->getOpcode())) { - SVal LVal = State->getSVal(BO->getLHS(), C.getLocationContext()); SVal Result = State->getSVal(BO, C.getLocationContext()); handleComparison(C, BO, Result, LVal, RVal, BinaryOperator::getOverloadedOperator(OK)); } else if (isRandomIncrOrDecrOperator(OK)) { - handlePtrIncrOrDecr(C, BO->getLHS(), - BinaryOperator::getOverloadedOperator(OK), RVal); + // In case of operator+ the iterator can be either on the LHS (eg.: it + 1), + // or on the RHS (eg.: 1 + it). Both cases are modeled. + bool IsItOnLHS = BO->getLHS()->getType()->isPointerType(); + Expr *&ItExpr = IsItOnLHS ? LHS : RHS; + SVal &OffsetVal = IsItOnLHS ? RVal : LVal; + handlePtrIncrOrDecr(C, ItExpr, BinaryOperator::getOverloadedOperator(OK), + OffsetVal); } } @@ -563,7 +570,7 @@ const SVal &LHS, const SVal &RHS) const { // Increment or decrement the symbolic expressions which represents the - // position of the iterator + // position of the iterator. auto State = C.getState(); const auto *Pos = getIteratorPosition(State, LHS); diff --git a/clang/test/Analysis/iterator-modeling.cpp b/clang/test/Analysis/iterator-modeling.cpp --- a/clang/test/Analysis/iterator-modeling.cpp +++ b/clang/test/Analysis/iterator-modeling.cpp @@ -1948,7 +1948,7 @@ clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning{{$c.end() - 2}} } -void plus_ptr_iterator(const cont_with_ptr_iterator &c) { +void lhs_plus_ptr_iterator(const cont_with_ptr_iterator &c) { auto i1 = c.begin(); clang_analyzer_denote(clang_analyzer_container_begin(c), "$c.begin()"); @@ -1960,6 +1960,18 @@ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$c.begin() + 2}} } +void rhs_plus_ptr_iterator(const cont_with_ptr_iterator &c) { + auto i1 = c.begin(); + + clang_analyzer_denote(clang_analyzer_container_begin(c), "$c.begin()"); + + auto i2 = 2 + i1; + + clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &c); // expected-warning{{TRUE}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$c.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$c.begin() + 2}} +} + void minus_ptr_iterator(const cont_with_ptr_iterator &c) { auto i1 = c.end();