Index: clang/lib/StaticAnalyzer/Checkers/DebugIteratorModeling.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/DebugIteratorModeling.cpp +++ clang/lib/StaticAnalyzer/Checkers/DebugIteratorModeling.cpp @@ -88,14 +88,30 @@ } auto State = C.getState(); - SVal V = C.getSVal(CE->getArg(0)); - const auto *Pos = getIteratorPosition(State, V); + SVal Iter = C.getSVal(CE->getArg(0)); + const auto *Pos = getIteratorPosition(State, Iter); + SVal Field = Default; + if (Pos) { - State = State->BindExpr(CE, C.getLocationContext(), get(Pos)); - } else { - State = State->BindExpr(CE, C.getLocationContext(), Default); + Field = get(Pos); } - C.addTransition(State); + + State = State->BindExpr(CE, C.getLocationContext(), Field); + + // Progpagate interestingness from the iterator's position (marked interesting + // by an `ExprInspection` debug call to the iterator itself. + const NoteTag *InterestingTag = + C.getNoteTag([Iter, Field](PathSensitiveBugReport &BR) -> std::string { + if (BR.isInteresting(Field)) { + BR.markInteresting(Iter); + if (const auto &LCV = Iter.getAs()) { + BR.markInteresting(LCV->getRegion()); + } + } + return ""; + }); + + C.addTransition(State, InterestingTag); } void DebugIteratorModeling::analyzerIteratorPosition(const CallExpr *CE, Index: clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp +++ clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp @@ -122,9 +122,11 @@ void assignToContainer(CheckerContext &C, const Expr *CE, SVal RetVal, const MemRegion *Cont) const; const NoteTag *getChangeTag(CheckerContext &C, StringRef Text, - const Expr *ItEx, int64_t Amount = 0, - const Expr *AmEx = nullptr) const; + const Expr *ItE, SVal It1, int64_t Amount = 0, + Optional It2 = None) const; bool noChangeInAdvance(CheckerContext &C, SVal Iter, const Expr *CE) const; + const NoteTag *getInterestingnessPropagationTag(CheckerContext &C, SVal It1, + SVal It2) const; void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const override; @@ -210,7 +212,9 @@ if (cast(Func)->isMoveConstructor()) { State = removeIteratorPosition(State, Arg); } - C.addTransition(State); + const NoteTag *InterestingTag = + getInterestingnessPropagationTag(C, Arg, RetVal); + C.addTransition(State, InterestingTag); return; } } @@ -242,7 +246,9 @@ const auto *Pos = getIteratorPosition(State, Val); if (Pos) { State = setIteratorPosition(State, Loc, *Pos); - C.addTransition(State); + const NoteTag *InterestingTag = + getInterestingnessPropagationTag(C, Val, Loc); + C.addTransition(State, InterestingTag); } else { const auto *OldPos = getIteratorPosition(State, Loc); if (OldPos) { @@ -533,7 +539,9 @@ assert(NewPos && "Iterator should have position after successful advancement"); - const NoteTag *ChangeTag = getChangeTag(C, "incremented", ItEx, 1); + const NoteTag *ChangeTag = + getChangeTag(C, "incremented", ItEx, Iter, 1, + Postfix ? None : Optional(RetVal)); State = setIteratorPosition(State, Iter, *NewPos); State = setIteratorPosition(State, RetVal, Postfix ? *Pos : *NewPos); C.addTransition(State, ChangeTag); @@ -561,7 +569,9 @@ assert(NewPos && "Iterator should have position after successful advancement"); - const NoteTag *ChangeTag = getChangeTag(C, "decremented", ItEx, 1); + const NoteTag *ChangeTag = + getChangeTag(C, "decremented", ItEx, Iter, 1, + Postfix ? None : Optional(RetVal)); State = setIteratorPosition(State, Iter, *NewPos); State = setIteratorPosition(State, RetVal, Postfix ? *Pos : *NewPos); C.addTransition(State, ChangeTag); @@ -607,8 +617,9 @@ if (!ChangeVal) ChangeText = "unchanged"; - const NoteTag *ChangeTag = getChangeTag(C, ChangeText, ItEx, - std::abs(ChangeVal), AmEx); + const NoteTag *ChangeTag = + getChangeTag(C, ChangeText, ItEx, Iter, std::abs(ChangeVal), + (TgtVal == RetVal) ? Optional(RetVal) : None); State = setIteratorPosition(State, TgtVal, *NewPos); C.addTransition(State, ChangeTag); } else { @@ -662,8 +673,9 @@ if (!ChangeVal) ChangeText = "unchanged"; - const NoteTag *ChangeTag = getChangeTag(C, ChangeText, Iterator, - std::abs(ChangeVal), AmEx); + const NoteTag *ChangeTag = + getChangeTag(C, ChangeText, Iterator, OldVal, std::abs(ChangeVal), + NewVal); ProgramStateRef NewState = setIteratorPosition(State, NewVal, *NewPos); C.addTransition(NewState, ChangeTag); @@ -734,19 +746,26 @@ } const NoteTag *IteratorModeling::getChangeTag(CheckerContext &C, StringRef Text, - const Expr *ItEx, int64_t Amount, - const Expr *AmEx) const { - if (const auto *CCE = dyn_cast(ItEx)) { - ItEx = CCE->getArg(0); + const Expr *ItE, SVal It1, + int64_t Amount, + Optional It2) const { + if (const auto *CCE = dyn_cast(ItE)) { + ItE = CCE->getArg(0); } StringRef Name; - if (const auto *DRE = dyn_cast(ItEx->IgnoreParenCasts())) { + if (const auto *DRE = dyn_cast(ItE->IgnoreParenCasts())) { Name = DRE->getDecl()->getName(); } - return C.getNoteTag( - [Text, Name, Amount, AmEx](PathSensitiveBugReport &BR) -> std::string { + return C.getNoteTag([Text, Name, Amount, It1, + It2](PathSensitiveBugReport &BR) -> std::string { + if (It2 && BR.isInteresting(*It2)) + BR.markInteresting(It1); + + if (!BR.isInteresting(It1)) + return ""; + SmallString<256> Msg; llvm::raw_svector_ostream Out(Msg); Out << "Iterator " << (!Name.empty() ? ("'" + Name.str() + "' ") : "") @@ -754,13 +773,30 @@ if (Amount) { Out << " by " << Amount; } - if (AmEx) { - bugreporter::trackExpressionValue(BR.getErrorNode(), AmEx, BR); - } return std::string(Out.str()); }); } +// Propagate interestingness between iterators upon their assignments. This +// is essential for tracking all the changes of an iterator from the beginning +// to the bug location. +// +// Example: i = ++j; +// +// If `j` is affected by a bug, then this function ensures that `i` is tracked +// further up along the path (using `NoteTags`). + +const NoteTag * +IteratorModeling::getInterestingnessPropagationTag(CheckerContext &C, + SVal It1, SVal It2) const { + return C.getNoteTag([It1, It2](PathSensitiveBugReport &BR) -> std::string { + if (BR.isInteresting(It2)) + BR.markInteresting(It1); + + return ""; + }); +} + void IteratorModeling::printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const { auto SymbolMap = State->get(); Index: clang/test/Analysis/iterator-modeling.cpp =================================================================== --- clang/test/Analysis/iterator-modeling.cpp +++ clang/test/Analysis/iterator-modeling.cpp @@ -116,7 +116,7 @@ clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()"); - auto j = i++; // expected-note 2{{Iterator 'i' incremented by 1}} + auto j = i++; // expected-note{{Iterator 'i' incremented by 1}} clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.begin() + 1{{$}}}} // expected-note@-1{{$v.begin() + 1}} @@ -129,7 +129,7 @@ clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()"); - auto j = i--; // expected-note 2{{Iterator 'i' decremented by 1}} + auto j = i--; // expected-note{{Iterator 'i' decremented by 1}} clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.end() - 1{{$}}}} // expected-note@-1{{$v.end() - 1}} @@ -223,7 +223,7 @@ clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()"); - auto i2 = i1 + 2; // expected-note 4{{Iterator 'i1' incremented by 2}} + auto i2 = i1 + 2; // expected-note 2{{Iterator 'i1' incremented by 2}} clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} @@ -231,8 +231,6 @@ // expected-note@-1{{$v.begin()}} clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re{{$v.begin() + 2{{$}}}} // expected-note@-1{{$v.begin() + 2}} - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$v.begin() + 2}} - // expected-note@-1{{$v.begin() + 2}} } void plus_negative(const std::vector &v) { @@ -240,7 +238,7 @@ clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()"); - auto i2 = i1 + (-2); // expected-note 3{{Iterator 'i1' decremented by 2}} + auto i2 = i1 + (-2); // expected-note 2{{Iterator 'i1' decremented by 2}} clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} @@ -255,7 +253,7 @@ clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()"); - auto i2 = i1 + 0; // expected-note 2{{Iterator 'i1' unchanged}} + auto i2 = i1 + 0; // expected-note{{Iterator 'i1' unchanged}} clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} @@ -268,7 +266,7 @@ clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()"); - auto i2 = i1 - 2; // expected-note 3{{Iterator 'i1' decremented by 2}} + auto i2 = i1 - 2; // expected-note 2{{Iterator 'i1' decremented by 2}} clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} @@ -283,7 +281,7 @@ clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()"); - auto i2 = i1 - (-2); // expected-note 3{{Iterator 'i1' incremented by 2}} + auto i2 = i1 - (-2); // expected-note 2{{Iterator 'i1' incremented by 2}} clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} @@ -298,7 +296,7 @@ clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()"); - auto i2 = i1 - 0; // expected-note 2{{Iterator 'i1' unchanged}} + auto i2 = i1 - 0; // expected-note{{Iterator 'i1' unchanged}} clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} @@ -312,7 +310,7 @@ clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()"); auto i2 = i1; - ++i1; // expected-note 2{{Iterator 'i1' incremented by 1}} + ++i1; // expected-note{{Iterator 'i1' incremented by 1}} clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.begin() + 1{{$}}}} // expected-note@-1{{$v.begin() + 1}} @@ -326,7 +324,7 @@ clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()"); auto i2 = i1; - ++i2; // expected-note 2{{Iterator 'i2' incremented by 1}} + ++i2; // expected-note{{Iterator 'i2' incremented by 1}} clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.begin(){{$}}}} // expected-note@-1{{$v.begin()}} @@ -340,7 +338,7 @@ clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()"); auto i2 = i1; - --i1; // expected-note 2{{Iterator 'i1' decremented by 1}} + --i1; // expected-note{{Iterator 'i1' decremented by 1}} clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.end() - 1{{$}}}} // expected-note@-1{{$v.end() - 1}} @@ -354,7 +352,7 @@ clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()"); auto i2 = i1; - --i2; // expected-note 2{{Iterator 'i2' decremented by 1}} + --i2; // expected-note{{Iterator 'i2' decremented by 1}} clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.end(){{$}}}} // expected-note@-1{{$v.end()}} @@ -535,7 +533,6 @@ void list_move_assignment(std::list &L1, std::list &L2) { auto i0 = L1.cbegin(), i1 = L2.cbegin(), i2 = --L2.cend(), i3 = L2.cend(); - // expected-note@-1 7{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L2), "$L2.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L2), "$L2.end()"); @@ -562,7 +559,6 @@ void vector_move_assignment(std::vector &V1, std::vector &V2) { auto i0 = V1.cbegin(), i1 = V2.cbegin(), i2 = --V2.cend(), i3 = V2.cend(); - // expected-note@-1 7{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V2), "$V2.begin()"); @@ -588,7 +584,6 @@ void deque_move_assignment(std::deque &D1, std::deque &D2) { auto i0 = D1.cbegin(), i1 = D2.cbegin(), i2 = --D2.cend(), i3 = D2.cend(); - // expected-note@-1 7{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D2), "$D2.begin()"); @@ -734,7 +729,7 @@ void list_push_back(std::list &L, int n) { auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend(); - // expected-note@-1 6{{Iterator decremented by 1}} + // expected-note@-1{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -760,7 +755,7 @@ void vector_push_back(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend(); - // expected-note@-1 5{{Iterator decremented by 1}} + // expected-note@-1{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -785,7 +780,6 @@ void deque_push_back(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend(); - // expected-note@-1 3{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -811,7 +805,7 @@ void list_emplace_back(std::list &L, int n) { auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend(); - // expected-note@-1 6{{Iterator decremented by 1}} + // expected-note@-1{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -837,7 +831,7 @@ void vector_emplace_back(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend(); - // expected-note@-1 5{{Iterator decremented by 1}} + // expected-note@-1{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -862,7 +856,6 @@ void deque_emplace_back(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend(); - // expected-note@-1 3{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -888,7 +881,6 @@ void list_pop_back(std::list &L, int n) { auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend(); - // expected-note@-1 5{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -913,7 +905,6 @@ void vector_pop_back(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend(); - // expected-note@-1 4{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -937,7 +928,6 @@ void deque_pop_back(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend(); - // expected-note@-1 4{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -988,7 +978,6 @@ void deque_push_front(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend(); - // expected-note@-1 3{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -1057,7 +1046,6 @@ void deque_emplace_front(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend(); - // expected-note@-1 3{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -1104,7 +1092,7 @@ void list_pop_front(std::list &L, int n) { auto i0 = L.cbegin(), i1 = ++L.cbegin(), i2 = L.cend(); - // expected-note@-1 5{{Iterator incremented by 1}} + // expected-note@-1{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -1129,7 +1117,7 @@ void deque_pop_front(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = ++D.cbegin(), i2 = D.cend(); - // expected-note@-1 5{{Iterator incremented by 1}} + // expected-note@-1{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -1154,7 +1142,7 @@ void forward_list_pop_front(std::list &FL, int n) { auto i0 = FL.cbegin(), i1 = ++FL.cbegin(), i2 = FL.cend(); - // expected-note@-1 5{{Iterator incremented by 1}} + // expected-note@-1{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()"); clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()"); @@ -1208,7 +1196,7 @@ void list_insert_behind_begin(std::list &L, int n) { auto i0 = L.cbegin(), i1 = ++L.cbegin(), i2 = L.cend(); - // expected-note@-1 6{{Iterator incremented by 1}} + // expected-note@-1{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -1260,7 +1248,7 @@ void list_insert_ahead_of_end(std::list &L, int n) { auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend(); - // expected-note@-1 6{{Iterator decremented by 1}} + // expected-note@-1{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -1285,7 +1273,7 @@ void list_insert_end(std::list &L, int n) { auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend(); - // expected-note@-1 6{{Iterator decremented by 1}} + // expected-note@-1{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -1330,7 +1318,6 @@ void vector_insert_behind_begin(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = ++V.cbegin(), i2 = V.cend(); - // expected-note@-1 4{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -1372,7 +1359,6 @@ void vector_insert_ahead_of_end(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend(); - // expected-note@-1 4{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -1393,7 +1379,7 @@ void vector_insert_end(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend(); - // expected-note@-1 5{{Iterator decremented by 1}} + // expected-note@-1{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -1435,7 +1421,6 @@ void deque_insert_behind_begin(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = ++D.cbegin(), i2 = D.cend(); - // expected-note@-1 3{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -1473,7 +1458,6 @@ void deque_insert_ahead_of_end(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend(); - // expected-note@-1 3{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -1492,7 +1476,6 @@ void deque_insert_end(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend(); - // expected-note@-1 3{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -1541,7 +1524,7 @@ void forward_list_insert_after_behind_begin(std::forward_list &FL, int n) { auto i0 = FL.cbegin(), i1 = ++FL.cbegin(), i2 = FL.cend(); - // expected-note@-1 6{{Iterator incremented by 1}} + // expected-note@-1{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()"); clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()"); @@ -1623,7 +1606,7 @@ void list_emplace_behind_begin(std::list &L, int n) { auto i0 = L.cbegin(), i1 = ++L.cbegin(), i2 = L.cend(); - // expected-note@-1 6{{Iterator incremented by 1}} + // expected-note@-1{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -1675,7 +1658,7 @@ void list_emplace_ahead_of_end(std::list &L, int n) { auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend(); - // expected-note@-1 6{{Iterator decremented by 1}} + // expected-note@-1{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -1700,7 +1683,7 @@ void list_emplace_end(std::list &L, int n) { auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend(); - // expected-note@-1 6{{Iterator decremented by 1}} + // expected-note@-1{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -1744,7 +1727,6 @@ void vector_emplace_behind_begin(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = ++V.cbegin(), i2 = V.cend(); - // expected-note@-1 4{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -1786,7 +1768,6 @@ void vector_emplace_ahead_of_end(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend(); - // expected-note@-1 4{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -1807,7 +1788,7 @@ void vector_emplace_end(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend(); - // expected-note@-1 5{{Iterator decremented by 1}} + // expected-note@-1{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -1848,7 +1829,6 @@ void deque_emplace_behind_begin(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = ++D.cbegin(), i2 = D.cend(); - // expected-note@-1 3{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -1885,7 +1865,6 @@ void deque_emplace_ahead_of_end(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend(); - // expected-note@-1 3{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -1904,7 +1883,6 @@ void deque_emplace_end(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend(); - // expected-note@-1 3{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -1954,7 +1932,7 @@ void forward_list_emplace_after_behind_begin(std::forward_list &FL, int n) { auto i0 = FL.cbegin(), i1 = ++FL.cbegin(), i2 = FL.cend(); - // expected-note@-1 6{{Iterator incremented by 1}} + // expected-note@-1{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()"); clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()"); @@ -2017,7 +1995,7 @@ void list_erase_begin(std::list &L) { auto i0 = L.cbegin(), i1 = ++L.cbegin(), i2 = L.cend(); - // expected-note@-1 5{{Iterator incremented by 1}} + // expected-note@-1{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -2040,7 +2018,6 @@ void list_erase_behind_begin(std::list &L, int n) { auto i0 = L.cbegin(), i1 = ++L.cbegin(), i2 = L.cend(); - // expected-note@-1 5{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -2086,7 +2063,6 @@ void list_erase_ahead_of_end(std::list &L) { auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend(); - // expected-note@-1 5{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()"); clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()"); @@ -2112,7 +2088,6 @@ void vector_erase_begin(std::vector &V) { auto i0 = V.cbegin(), i1 = ++V.cbegin(), i2 = V.cend(); - // expected-note@-1 3{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -2131,7 +2106,6 @@ void vector_erase_behind_begin(std::vector &V, int n) { auto i0 = V.cbegin(), i1 = ++V.cbegin(), i2 = V.cend(); - // expected-note@-1 4{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -2173,7 +2147,6 @@ void vector_erase_ahead_of_end(std::vector &V) { auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend(); - // expected-note@-1 4{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()"); clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()"); @@ -2202,7 +2175,6 @@ void deque_erase_begin(std::deque &D) { auto i0 = D.cbegin(), i1 = ++D.cbegin(), i2 = D.cend(); - // expected-note@-1 3{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -2221,7 +2193,6 @@ void deque_erase_behind_begin(std::deque &D, int n) { auto i0 = D.cbegin(), i1 = ++D.cbegin(), i2 = D.cend(); - // expected-note@-1 3{{Iterator incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -2259,7 +2230,6 @@ void deque_erase_ahead_of_end(std::deque &D) { auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend(); - // expected-note@-1 3{{Iterator decremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()"); clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()"); @@ -2291,9 +2261,9 @@ void forward_list_erase_after_begin(std::forward_list &FL) { auto i0 = FL.cbegin(), i1 = ++FL.cbegin(), i2 = i1, i3 = FL.cend(); - // expected-note@-1 7{{Iterator incremented by 1}} + // expected-note@-1{{Iterator incremented by 1}} ++i2; - // expected-note@-1 7{{Iterator 'i2' incremented by 1}} + // expected-note@-1{{Iterator 'i2' incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()"); clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()"); @@ -2322,11 +2292,10 @@ auto i0 = FL.cbegin(), i1 = return_any_iterator(FL.cbegin()), i2 = i1, i3 = i1, i4 = FL.cend(); ++i2; - // expected-note@-1 9{{Iterator 'i2' incremented by 1}} ++i3; - // expected-note@-1 9{{Iterator 'i3' incremented by 1}} + // expected-note@-1{{Iterator 'i3' incremented by 1}} ++i3; - // expected-note@-1 9{{Iterator 'i3' incremented by 1}} + // expected-note@-1{{Iterator 'i3' incremented by 1}} clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()"); clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()"); @@ -2555,7 +2524,7 @@ clang_analyzer_denote(clang_analyzer_container_begin(c), "$c.begin()"); - auto i2 = i1 + 2; // expected-note 3{{Iterator 'i1' incremented by 2}} + auto i2 = i1 + 2; // expected-note 2{{Iterator 'i1' incremented by 2}} clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &c); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} @@ -2570,7 +2539,7 @@ clang_analyzer_denote(clang_analyzer_container_end(c), "$c.end()"); - auto i2 = i1 - 2; // expected-note 3{{Iterator 'i1' decremented by 2}} + auto i2 = i1 - 2; // expected-note 2{{Iterator 'i1' decremented by 2}} clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &c); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} @@ -2598,8 +2567,8 @@ clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()"); - auto k = ++j; // expected-note 2{{Iterator 'j' incremented by 1}} - // FIXME: Expect only one note. + auto k = ++j; // expected-note{{Iterator 'j' incremented by 1}} + // Only once! clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning{{$v.begin()}} // expected-note@-1{{$v.begin()}} @@ -2613,8 +2582,7 @@ clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()"); - auto k = ++j; // expected-note{{Iterator 'j' incremented by 1}} - // FIXME: expect no note. + auto k = ++j; // no-note clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning{{$v.begin()}} // expected-note@-1{{$v.begin()}} Index: clang/test/Analysis/iterator-range.cpp =================================================================== --- clang/test/Analysis/iterator-range.cpp +++ clang/test/Analysis/iterator-range.cpp @@ -957,3 +957,4 @@ *i; // expected-warning{{Past-the-end iterator dereferenced}} // expected-note@-1{{Past-the-end iterator dereferenced}} } +