Index: clang/include/clang/StaticAnalyzer/Checkers/Checkers.td =================================================================== --- clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -697,6 +697,15 @@ def ContainerModeling : Checker<"ContainerModeling">, HelpText<"Models C++ containers">, + CheckerOptions<[ + CmdLineOption + ]>, Documentation, Hidden; Index: clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp +++ clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp @@ -44,12 +44,18 @@ void handlePopBack(CheckerContext &C, SVal Cont, const Expr *ContE) const; void handlePushFront(CheckerContext &C, SVal Cont, const Expr *ContE) const; void handlePopFront(CheckerContext &C, SVal Cont, const Expr *ContE) const; - void handleInsert(CheckerContext &C, SVal Cont, SVal Iter) const; - void handleErase(CheckerContext &C, SVal Cont, SVal Iter) const; - void handleErase(CheckerContext &C, SVal Cont, SVal Iter1, SVal Iter2) const; - void handleEraseAfter(CheckerContext &C, SVal Cont, SVal Iter) const; + void handleInsert(CheckerContext &C, SVal Cont, SVal Iter, SVal RetVal, + const Expr *CE) const; + void handleInsertAfter(CheckerContext &C, SVal Cont, SVal Iter, SVal RetVal, + const Expr *CE) const; + void handleErase(CheckerContext &C, SVal Cont, SVal Iter, SVal RetVal, + const Expr *CE) const; + void handleErase(CheckerContext &C, SVal Cont, SVal Iter1, SVal Iter2, + SVal RetVal) const; + void handleEraseAfter(CheckerContext &C, SVal Cont, SVal Iter, SVal RetVal, + const Expr *CE) const; void handleEraseAfter(CheckerContext &C, SVal Cont, SVal Iter1, - SVal Iter2) const; + SVal Iter2, SVal RetVal) const; const NoteTag *getChangeTag(CheckerContext &C, StringRef Text, const MemRegion *ContReg, const Expr *ContE) const; @@ -59,16 +65,18 @@ public: ContainerModeling() = default; + DefaultBool AggressiveEraseModeling; + void checkPostCall(const CallEvent &Call, CheckerContext &C) const; void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const; void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; using NoItParamFn = void (ContainerModeling::*)(CheckerContext &, SVal, const Expr *) const; - using OneItParamFn = void (ContainerModeling::*)(CheckerContext &, SVal, - SVal) const; + using OneItParamFn = void (ContainerModeling::*)(CheckerContext &, SVal, SVal, + SVal, const Expr*) const; using TwoItParamFn = void (ContainerModeling::*)(CheckerContext &, SVal, SVal, - SVal) const; + SVal, SVal) const; CallDescriptionMap NoIterParamFunctions = { {{0, "clear", 0}, @@ -92,8 +100,12 @@ CallDescriptionMap OneIterParamFunctions = { {{0, "insert", 2}, &ContainerModeling::handleInsert}, + {{0, "insert_after", 2}, + &ContainerModeling::handleInsertAfter}, {{0, "emplace", 2}, &ContainerModeling::handleInsert}, + {{0, "emplace_after", 2}, + &ContainerModeling::handleInsertAfter}, {{0, "erase", 1}, &ContainerModeling::handleErase}, {{0, "erase_after", 1}, @@ -179,6 +191,29 @@ } } else { if (const auto *InstCall = dyn_cast(&Call)) { + const auto *OrigExpr = Call.getOriginExpr(); + if (!OrigExpr) + return; + + QualType RetType = Call.getResultType(); + SVal RetVal = Call.getReturnValue(); + if (isIteratorType(RetType) && RetVal.isUnknown()) { + ProgramStateRef State = C.getState(); + auto &SymMgr = C.getSymbolManager(); + auto *LCtx = C.getLocationContext(); + SymbolRef RetSym = SymMgr.conjureSymbol(OrigExpr, LCtx, RetType, + C.blockCount()); + if (RetType->getUnqualifiedDesugaredType()->isPointerType()) { + auto &RegMgr = C.getStoreManager().getRegionManager(); + const MemRegion *RetReg = RegMgr.getSymbolicRegion(RetSym); + RetVal = loc::MemRegionVal(RetReg); + } else { + RetVal = nonloc::SymbolVal(RetSym); + } + State = State->BindExpr(OrigExpr, LCtx, RetVal); + C.addTransition(State); + } + const NoItParamFn *Handler0 = NoIterParamFunctions.lookup(Call); if (Handler0) { (this->**Handler0)(C, InstCall->getCXXThisVal(), @@ -188,30 +223,25 @@ const OneItParamFn *Handler1 = OneIterParamFunctions.lookup(Call); if (Handler1) { - (this->**Handler1)(C, InstCall->getCXXThisVal(), Call.getArgSVal(0)); + (this->**Handler1)(C, InstCall->getCXXThisVal(), Call.getArgSVal(0), + RetVal, Call.getOriginExpr()); return; } const TwoItParamFn *Handler2 = TwoIterParamFunctions.lookup(Call); if (Handler2) { (this->**Handler2)(C, InstCall->getCXXThisVal(), Call.getArgSVal(0), - Call.getArgSVal(1)); + Call.getArgSVal(1), RetVal); return; } - const auto *OrigExpr = Call.getOriginExpr(); - if (!OrigExpr) - return; - if (isBeginCall(Func)) { - handleBegin(C, OrigExpr, Call.getReturnValue(), - InstCall->getCXXThisVal()); + handleBegin(C, OrigExpr, RetVal, InstCall->getCXXThisVal()); return; } if (isEndCall(Func)) { - handleEnd(C, OrigExpr, Call.getReturnValue(), - InstCall->getCXXThisVal()); + handleEnd(C, OrigExpr, RetVal, InstCall->getCXXThisVal()); return; } } @@ -445,12 +475,10 @@ State = invalidateIteratorPositions(State, EndSym, BO_GE); } auto &SymMgr = C.getSymbolManager(); - auto &BVF = SymMgr.getBasicVals(); auto &SVB = C.getSValBuilder(); const auto newEndSym = - SVB.evalBinOp(State, BO_Add, - nonloc::SymbolVal(EndSym), - nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))), + SVB.evalBinOp(State, BO_Add, nonloc::SymbolVal(EndSym), + SVB.makeIntVal(1, false), SymMgr.getType(EndSym)).getAsSymbol(); const NoteTag *ChangeTag = getChangeTag(C, "extended to the back by 1 position", ContReg, ContE); @@ -474,12 +502,10 @@ if (const auto EndSym = CData->getEnd()) { auto &SymMgr = C.getSymbolManager(); - auto &BVF = SymMgr.getBasicVals(); auto &SVB = C.getSValBuilder(); const auto BackSym = - SVB.evalBinOp(State, BO_Sub, - nonloc::SymbolVal(EndSym), - nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))), + SVB.evalBinOp(State, BO_Sub, nonloc::SymbolVal(EndSym), + SVB.makeIntVal(1, false), SymMgr.getType(EndSym)).getAsSymbol(); const NoteTag *ChangeTag = getChangeTag(C, "shrank from the back by 1 position", ContReg, ContE); @@ -519,12 +545,10 @@ if (const auto BeginSym = CData->getBegin()) { auto &SymMgr = C.getSymbolManager(); - auto &BVF = SymMgr.getBasicVals(); auto &SVB = C.getSValBuilder(); const auto newBeginSym = - SVB.evalBinOp(State, BO_Sub, - nonloc::SymbolVal(BeginSym), - nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))), + SVB.evalBinOp(State, BO_Sub, nonloc::SymbolVal(BeginSym), + SVB.makeIntVal(1, false), SymMgr.getType(BeginSym)).getAsSymbol(); const NoteTag *ChangeTag = getChangeTag(C, "extended to the front by 1 position", ContReg, ContE); @@ -556,12 +580,10 @@ State = invalidateIteratorPositions(State, BeginSym, BO_EQ); } auto &SymMgr = C.getSymbolManager(); - auto &BVF = SymMgr.getBasicVals(); auto &SVB = C.getSValBuilder(); const auto newBeginSym = - SVB.evalBinOp(State, BO_Add, - nonloc::SymbolVal(BeginSym), - nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))), + SVB.evalBinOp(State, BO_Add, nonloc::SymbolVal(BeginSym), + SVB.makeIntVal(1, false), SymMgr.getType(BeginSym)).getAsSymbol(); const NoteTag *ChangeTag = getChangeTag(C, "shrank from the front by 1 position", ContReg, ContE); @@ -570,8 +592,8 @@ } } -void ContainerModeling::handleInsert(CheckerContext &C, SVal Cont, - SVal Iter) const { +void ContainerModeling::handleInsert(CheckerContext &C, SVal Cont, SVal Iter, + SVal RetVal, const Expr*) const { const auto *ContReg = Cont.getAsRegion(); if (!ContReg) return; @@ -597,12 +619,47 @@ State = setContainerData(State, ContReg, CData->newEnd(nullptr)); } } - C.addTransition(State); } + + // Set the return value + if (!RetVal.isUnknown()) { + auto RetPos = + IteratorPosition::getPosition(Pos->getContainer(), Pos->getOffset()); + State = setIteratorPosition(State, RetVal, RetPos); + } + C.addTransition(State); } -void ContainerModeling::handleErase(CheckerContext &C, SVal Cont, - SVal Iter) const { +void ContainerModeling::handleInsertAfter(CheckerContext &C, SVal Cont, + SVal Iter, SVal RetVal, + const Expr*) const { + const auto *ContReg = Cont.getAsRegion(); + if (!ContReg) + return; + + ContReg = ContReg->getMostDerivedObjectRegion(); + + auto State = C.getState(); + const auto *Pos = getIteratorPosition(State, Iter); + if (!Pos) + return; + + // Set the return value + if (!RetVal.isUnknown()) { + auto &SymMgr = C.getSymbolManager(); + auto &SVB = C.getSValBuilder(); + const auto RetOffset = + SVB.evalBinOp(State, BO_Add, nonloc::SymbolVal(Pos->getOffset()), + SVB.makeIntVal(1, false), + SymMgr.getType(Pos->getOffset())).getAsSymbol(); + auto RetPos = IteratorPosition::getPosition(Pos->getContainer(), RetOffset); + State = setIteratorPosition(State, RetVal, RetPos); + } + C.addTransition(State); +} + +void ContainerModeling::handleErase(CheckerContext &C, SVal Cont, SVal Iter, + SVal RetVal, const Expr *CE) const { const auto *ContReg = Cont.getAsRegion(); if (!ContReg) return; @@ -632,11 +689,52 @@ } else { State = invalidateIteratorPositions(State, Pos->getOffset(), BO_EQ); } + + // Set the return value + if (!RetVal.isUnknown()) { + auto &SymMgr = C.getSymbolManager(); + auto &SVB = C.getSValBuilder(); + const auto RetOffset = + SVB.evalBinOp(State, BO_Add, nonloc::SymbolVal(Pos->getOffset()), + SVB.makeIntVal(1, false), + SymMgr.getType(Pos->getOffset())).getAsSymbol(); + auto RetPos = IteratorPosition::getPosition(Pos->getContainer(), RetOffset); + State = setIteratorPosition(State, RetVal, RetPos); + + if (AggressiveEraseModeling) { + SymbolRef EndSym = getContainerEnd(State, ContReg); + // For std::vector and std::queue-like containers we just removed the + // end symbol from the container data because the past-the-end iterator + // was also invalidated. The next call to member function `end()` would + // create a new one, but we need it now so we create it now. + if (!EndSym) { + State = createContainerEnd(State, ContReg, CE, C.getASTContext().LongTy, + C.getLocationContext(), C.blockCount()); + EndSym = getContainerEnd(State, ContReg); + } + const auto RetEnd = + SVB.evalBinOp(State, BO_EQ, nonloc::SymbolVal(RetOffset), + nonloc::SymbolVal(EndSym), SVB.getConditionType()) + .getAs(); + if (RetEnd) { + ProgramStateRef StateEnd, StateNotEnd; + std::tie(StateEnd, StateNotEnd) = State->assume(*RetEnd); + if (StateEnd) { + C.addTransition(StateEnd); + } + if (StateNotEnd) { + C.addTransition(StateNotEnd); + } + return; + } + } + } + C.addTransition(State); } void ContainerModeling::handleErase(CheckerContext &C, SVal Cont, SVal Iter1, - SVal Iter2) const { + SVal Iter2, SVal RetVal) const { const auto *ContReg = Cont.getAsRegion(); if (!ContReg) return; @@ -668,11 +766,24 @@ State = invalidateIteratorPositions(State, Pos1->getOffset(), BO_GE, Pos2->getOffset(), BO_LT); } + + // Set the return value + if (!RetVal.isUnknown()) { + auto RetPos = + IteratorPosition::getPosition(Pos2->getContainer(), Pos2->getOffset()); + State = setIteratorPosition(State, RetVal, RetPos); + } C.addTransition(State); } void ContainerModeling::handleEraseAfter(CheckerContext &C, SVal Cont, - SVal Iter) const { + SVal Iter, SVal RetVal, + const Expr *CE) const { + const auto *ContReg = Cont.getAsRegion(); + if (!ContReg) + return; + + ContReg = ContReg->getMostDerivedObjectRegion(); auto State = C.getState(); const auto *Pos = getIteratorPosition(State, Iter); if (!Pos) @@ -681,19 +792,51 @@ // Invalidate the deleted iterator position, which is the position of the // parameter plus one. auto &SymMgr = C.getSymbolManager(); - auto &BVF = SymMgr.getBasicVals(); auto &SVB = C.getSValBuilder(); const auto NextSym = - SVB.evalBinOp(State, BO_Add, - nonloc::SymbolVal(Pos->getOffset()), - nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(1))), + SVB.evalBinOp(State, BO_Add, nonloc::SymbolVal(Pos->getOffset()), + SVB.makeIntVal(1, false), SymMgr.getType(Pos->getOffset())).getAsSymbol(); State = invalidateIteratorPositions(State, NextSym, BO_EQ); + + // Set the return value + if (!RetVal.isUnknown()) { + const auto RetOffset = + SVB.evalBinOp(State, BO_Add, nonloc::SymbolVal(NextSym), + SVB.makeIntVal(1, false), + SymMgr.getType(NextSym)).getAsSymbol(); + auto RetPos = IteratorPosition::getPosition(Pos->getContainer(), RetOffset); + State = setIteratorPosition(State, RetVal, RetPos); + + if (AggressiveEraseModeling) { + if (const auto *CData = getContainerData(State, ContReg)) { + if (const SymbolRef EndSym = CData->getEnd()) { + const auto RetEnd = + SVB.evalBinOp(State, BO_EQ, nonloc::SymbolVal(RetOffset), + nonloc::SymbolVal(EndSym), SVB.getConditionType()) + .getAs(); + if (RetEnd) { + ProgramStateRef StateEnd, StateNotEnd; + std::tie(StateEnd, StateNotEnd) = State->assume(*RetEnd); + if (StateEnd) { + C.addTransition(StateEnd); + } + if (StateNotEnd) { + C.addTransition(StateNotEnd); + } + return; + } + } + } + } + } + C.addTransition(State); } void ContainerModeling::handleEraseAfter(CheckerContext &C, SVal Cont, - SVal Iter1, SVal Iter2) const { + SVal Iter1, SVal Iter2, + SVal RetVal) const { auto State = C.getState(); const auto *Pos1 = getIteratorPosition(State, Iter1); const auto *Pos2 = getIteratorPosition(State, Iter2); @@ -703,6 +846,13 @@ // Invalidate the deleted iterator position range (first..last) State = invalidateIteratorPositions(State, Pos1->getOffset(), BO_GT, Pos2->getOffset(), BO_LT); + + // Set the return value + if (!RetVal.isUnknown()) { + auto RetPos = + IteratorPosition::getPosition(Pos2->getContainer(), Pos2->getOffset()); + State = setIteratorPosition(State, RetVal, RetPos); + } C.addTransition(State); } @@ -1065,7 +1215,11 @@ } // namespace void ento::registerContainerModeling(CheckerManager &mgr) { - mgr.registerChecker(); + auto *Checker = mgr.registerChecker(); + Checker->AggressiveEraseModeling = + mgr.getAnalyzerOptions().getCheckerBooleanOption( + "alpha.cplusplus.ContainerModeling", "AggressiveEraseModeling"); + } bool ento::shouldRegisterContainerModeling(const CheckerManager &mgr) { Index: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/Iterator.cpp +++ clang/lib/StaticAnalyzer/Checkers/Iterator.cpp @@ -17,7 +17,7 @@ namespace iterator { bool isIteratorType(const QualType &Type) { - if (Type->isPointerType()) + if (Type->getUnqualifiedDesugaredType()->isPointerType()) return true; const auto *CRD = Type->getUnqualifiedDesugaredType()->getAsCXXRecordDecl(); Index: clang/test/Analysis/Inputs/system-header-simulator-cxx.h =================================================================== --- clang/test/Analysis/Inputs/system-header-simulator-cxx.h +++ clang/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -88,6 +88,9 @@ const Ptr& base() const { return ptr; } + template + friend struct __vector_iterator; + private: Ptr ptr; }; @@ -143,6 +146,9 @@ const Ptr& base() const { return ptr; } + template + friend struct __deque_iterator; + private: Ptr ptr; }; @@ -175,11 +181,11 @@ Ref operator*() const { return item->data; } Ptr operator->() const { return &item->data; } - bool operator==(const iterator &rhs) const { return item == rhs->item; } - bool operator==(const const_iterator &rhs) const { return item == rhs->item; } + bool operator==(const iterator &rhs) const { return item == rhs.item; } + bool operator==(const const_iterator &rhs) const { return item == rhs.item; } - bool operator!=(const iterator &rhs) const { return item != rhs->item; } - bool operator!=(const const_iterator &rhs) const { return item != rhs->item; } + bool operator!=(const iterator &rhs) const { return item != rhs.item; } + bool operator!=(const const_iterator &rhs) const { return item != rhs.item; } const T* &base() const { return item; } @@ -211,11 +217,11 @@ Ref operator*() const { return item->data; } Ptr operator->() const { return &item->data; } - bool operator==(const iterator &rhs) const { return item == rhs->item; } - bool operator==(const const_iterator &rhs) const { return item == rhs->item; } + bool operator==(const iterator &rhs) const { return item == rhs.item; } + bool operator==(const const_iterator &rhs) const { return item == rhs.item; } - bool operator!=(const iterator &rhs) const { return item != rhs->item; } - bool operator!=(const const_iterator &rhs) const { return item != rhs->item; } + bool operator!=(const iterator &rhs) const { return item != rhs.item; } + bool operator!=(const const_iterator &rhs) const { return item != rhs.item; } const T* &base() const { return item; } Index: clang/test/Analysis/analyzer-config.c =================================================================== --- clang/test/Analysis/analyzer-config.c +++ clang/test/Analysis/analyzer-config.c @@ -7,6 +7,7 @@ // CHECK-NEXT: alpha.clone.CloneChecker:IgnoredFilesPattern = "" // CHECK-NEXT: alpha.clone.CloneChecker:MinimumCloneComplexity = 50 // CHECK-NEXT: alpha.clone.CloneChecker:ReportNormalClones = true +// CHECK-NEXT: alpha.cplusplus.ContainerModeling:AggressiveEraseModeling = false // CHECK-NEXT: alpha.cplusplus.STLAlgorithmModeling:AggressiveStdFindModeling = false // CHECK-NEXT: alpha.osx.cocoa.DirectIvarAssignment:AnnotatedFunctions = false // CHECK-NEXT: alpha.security.MmapWriteExec:MmapProtExec = 0x04 Index: clang/test/Analysis/diagnostics/explicit-suppression.cpp =================================================================== --- clang/test/Analysis/diagnostics/explicit-suppression.cpp +++ clang/test/Analysis/diagnostics/explicit-suppression.cpp @@ -19,6 +19,6 @@ void testCopyNull(C *I, C *E) { std::copy(I, E, (C *)0); #ifndef SUPPRESSED - // expected-warning@../Inputs/system-header-simulator-cxx.h:699 {{Called C++ object pointer is null}} + // expected-warning@../Inputs/system-header-simulator-cxx.h:705 {{Called C++ object pointer is null}} #endif } Index: clang/test/Analysis/iterator-modeling.cpp =================================================================== --- clang/test/Analysis/iterator-modeling.cpp +++ clang/test/Analysis/iterator-modeling.cpp @@ -873,9 +873,9 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $L.begin() - 1 - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.begin()}} } void list_insert_behind_begin(std::list &L, int n) { @@ -890,10 +890,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} FIXME: Should be $L.begin() - 1 - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.begin() + 1{{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.begin() - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.begin() + 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$L.begin()}} } template Iter return_any_iterator(const Iter &It); @@ -911,10 +911,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$i1{{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i - 1 - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$i1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1}} } void list_insert_ahead_of_end(std::list &L, int n) { @@ -929,10 +929,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end() - 1{{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.end() - 2 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end() - 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$L.end() - 1}} } void list_insert_end(std::list &L, int n) { @@ -947,10 +947,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end() - 1{{$}}}} FIXME: should be $L.end() - 2 - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.end() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end() - 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$L.end()}} } /// std::vector-like containers: Only the iterators before the insertion point @@ -968,7 +968,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $V.begin() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$V.begin()}} } void vector_insert_behind_begin(std::vector &V, int n) { @@ -983,8 +983,8 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} FIXME: Should be $V.begin() - 1 - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); // FIXME: expect -warning $V.begin() + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); //expected-warning{{$V.begin()}} } void vector_insert_unknown(std::vector &V, int n) { @@ -1000,8 +1000,8 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expecte warning $i1 - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1}} } void vector_insert_ahead_of_end(std::vector &V, int n) { @@ -1016,8 +1016,8 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.end() - 2 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$V.end() - 1}} } void vector_insert_end(std::vector &V, int n) { @@ -1032,9 +1032,9 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$V.end() - 1{{$}}}} FIXME: Should be $V.end() - 2 - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.end() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$V.end() - 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$V.end()}} } /// std::deque-like containers: All iterators, including the past-the-end @@ -1051,7 +1051,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $D.begin() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$D.begin()}} } void deque_insert_behind_begin(std::deque &D, int n) { @@ -1066,7 +1066,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$D.begin() + 1}} } void deque_insert_unknown(std::deque &D, int n) { @@ -1082,7 +1082,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1}} } void deque_insert_ahead_of_end(std::deque &D, int n) { @@ -1097,7 +1097,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.end() - 2 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$D.end() - 1}} } void deque_insert_end(std::deque &D, int n) { @@ -1112,7 +1112,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.end() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$D.end()}} } /// insert_after() [std::forward_list-like containers] @@ -1136,9 +1136,9 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $FL.begin() + 1 - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$FL.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$FL.begin() + 1}} } void forward_list_insert_after_behind_begin(std::forward_list &FL, int n) { @@ -1153,10 +1153,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL.begin() + 1{{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $FL.begin() + 2 - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$FL.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$FL.begin() + 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$FL.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$FL.begin() + 2}} } void forward_list_insert_after_unknown(std::forward_list &FL, int n) { @@ -1172,10 +1172,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$i1{{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1 - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$FL.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$i1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$FL.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1 + 1}} } /// emplace() @@ -1201,9 +1201,9 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $L.begin() - 1 - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.begin()}} } void list_emplace_behind_begin(std::list &L, int n) { @@ -1218,10 +1218,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} FIXME: Should be $L.begin() - 1 - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.begin() + 1{{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.begin() - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.begin() + 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$L.begin() + 1}} } template Iter return_any_iterator(const Iter &It); @@ -1239,10 +1239,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$i1{{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i - 1 - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$i1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i}} } void list_emplace_ahead_of_end(std::list &L, int n) { @@ -1257,10 +1257,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end() - 1{{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.end() - 2 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end() - 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$L.end() - 1}} } void list_emplace_end(std::list &L, int n) { @@ -1275,10 +1275,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end() - 1{{$}}}} FIXME: should be $L.end() - 2 - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.end() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end() - 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$L.end()}} } /// std::vector-like containers: Only the iterators before the emplacement point @@ -1295,7 +1295,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $V.begin() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$V.begin()}} } void vector_emplace_behind_begin(std::vector &V, int n) { @@ -1310,8 +1310,8 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} FIXME: Should be $V.begin() - 1 - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); // FIXME: expect -warning $V.begin() + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // // expected-warning{{$V.begin() + 1}} } void vector_emplace_unknown(std::vector &V, int n) { @@ -1327,8 +1327,8 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expecte warning $i1 - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1}} } void vector_emplace_ahead_of_end(std::vector &V, int n) { @@ -1343,8 +1343,8 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.end() - 2 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$V.end() - 1}} } void vector_emplace_end(std::vector &V, int n) { @@ -1359,9 +1359,9 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$V.end() - 1{{$}}}} FIXME: Should be $V.end() - 2 - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.end() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$V.end() - 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$V.end()}} } /// std::deque-like containers: All iterators, including the past-the-end @@ -1377,7 +1377,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $D.begin() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$D.begin()}} } void deque_emplace_behind_begin(std::deque &D, int n) { @@ -1391,7 +1391,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$D.begin() + 1}} } void deque_emplace_unknown(std::deque &D, int n) { @@ -1407,7 +1407,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1}} } void deque_emplace_ahead_of_end(std::deque &D, int n) { @@ -1422,7 +1422,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.end() - 2 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$D.end() - 1}} } void deque_emplace_end(std::deque &D, int n) { @@ -1437,7 +1437,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.end() - 1 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$D.end()}} } /// emplace_after() [std::forward_list-like containers] @@ -1461,9 +1461,9 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $FL.begin() + 1 - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$FL.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$FL.begin() + 1}} } void forward_list_emplace_after_behind_begin(std::forward_list &FL, @@ -1479,10 +1479,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL.begin() + 1{{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $FL.begin() + 2 - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$FL.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$FL.begin() + 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$FL.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$FL.begin() + 2}} } void forward_list_emplace_after_unknown(std::forward_list &FL, int n) { @@ -1498,10 +1498,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$i1{{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1 - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$FL.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$i1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$FL.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1 + 1}} } /// erase() @@ -1529,9 +1529,9 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.begin() + 1{{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.begin() + 1 - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.begin() + 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$L.begin() + 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} } void list_erase_behind_begin(std::list &L, int n) { @@ -1546,9 +1546,9 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} FIXME: Should be $L.begin() + 1 - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.begin() + 2 - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} FIXME: Should be $L.begin() + 1 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$L.begin() + 2}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} } void list_erase_unknown(std::list &L) { @@ -1564,9 +1564,9 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1 - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1 + 1}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} } void list_erase_ahead_of_end(std::list &L) { @@ -1581,9 +1581,9 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.end() + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$L.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$L.end()}} } /// std::vector-like containers: Invalidates iterators at or after the point of @@ -1601,7 +1601,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.begin() + 1 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$V.begin() + 1}} } void vector_erase_behind_begin(std::vector &V, int n) { @@ -1616,8 +1616,8 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} FIXME: Should be $V.begin() + 1 - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.begin() + 2 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} FIXME: Should be $V.begin() + 1 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$V.begin() + 2}} } void vector_erase_unknown(std::vector &V) { @@ -1633,8 +1633,8 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1 + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1 + 1}} } void vector_erase_ahead_of_end(std::vector &V) { @@ -1649,8 +1649,8 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.end() + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$V.end()}} } /// std::deque-like containers: All iterators are invalidated, unless the erased @@ -1673,7 +1673,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() + 1 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$D.begin() + 1}} } void deque_erase_behind_begin(std::deque &D, int n) { @@ -1688,7 +1688,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() + 2 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$D.begin() + 2}} } void deque_erase_unknown(std::deque &D) { @@ -1704,7 +1704,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1 + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1 + 1}} } void deque_erase_ahead_of_end(std::deque &D) { @@ -1719,7 +1719,7 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}} - // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.end() + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$D.end()}} } /// erase_after() [std::forward_list-like containers] @@ -1749,10 +1749,10 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i3)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$FL.begin() + 2{{$}}}} FIXME: Should be $FL.begin() + 1 - // clang_analyzer_express(clang_analyzer_iterator_position(i4)); FIXME: expect warning $FL.begin() + 1 - clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning-re {{$FL.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$FL.begin() + 2}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$FL.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i4)); // expected-warning{{$FL.begin() + 2}} } void forward_list_erase_after_unknown(std::forward_list &FL) { @@ -1774,11 +1774,11 @@ clang_analyzer_eval(clang_analyzer_iterator_validity(i3)); //expected-warning{{TRUE}} clang_analyzer_eval(clang_analyzer_iterator_validity(i4)); //expected-warning{{TRUE}} - clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$i1{{$}}}} - clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning-re {{$i1 + 2{{$}}}} FIXME: Should be $i1 + 1 - // clang_analyzer_express(clang_analyzer_iterator_position(i5)); FIXME: expect warning $i1 + 1 - clang_analyzer_express(clang_analyzer_iterator_position(i4)); // expected-warning-re {{$FL.end(){{$}}}} + clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}} + clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$i1}} + clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$i1 + 2}} + clang_analyzer_express(clang_analyzer_iterator_position(i4)); // expected-warning{{$FL.end()}} + clang_analyzer_express(clang_analyzer_iterator_position(i5)); // expected-warning{{$i1 + 2}} } struct simple_iterator_base { Index: clang/test/Analysis/iterator-range-aggressive-erase-modeling.cpp =================================================================== --- /dev/null +++ clang/test/Analysis/iterator-range-aggressive-erase-modeling.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_analyze_cc1 -std=c++11 \ +// RUN: -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange \ +// RUN: -analyzer-config aggressive-binary-operation-simplification=true \ +// RUN: -analyzer-config c++-container-inlining=false %s \ +// RUN: -analyzer-config alpha.cplusplus.ContainerModeling:AggressiveEraseModeling=true \ +// RUN: -verify + +// RUN: %clang_analyze_cc1 -std=c++11 \ +// RUN: -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange \ +// RUN: -analyzer-config aggressive-binary-operation-simplification=true \ +// RUN: -analyzer-config c++-container-inlining=true -DINLINE=1 %s \ +// RUN: -analyzer-config alpha.cplusplus.ContainerModeling:AggressiveEraseModeling=true \ +// RUN: -verify + +#include "Inputs/system-header-simulator-cxx.h" + +extern void __assert_fail (__const char *__assertion, __const char *__file, + unsigned int __line, __const char *__function) + __attribute__ ((__noreturn__)); +#define assert(expr) \ + ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__)) + +void bad_erase_loop(std::list L) { + for (auto i = L.cbegin(); i != L.end(); ++i) { // expected-warning{{Iterator incremented behind the past-the-end iterator}} + i = L.erase(i); + } +} + +void bad_erase_loop(std::vector V) { + for (auto i = V.cbegin(); i != V.end(); ++i) { // expected-warning{{Iterator incremented behind the past-the-end iterator}} + i = V.erase(i); + } +} +void bad_erase_loop(std::deque D) { + for (auto i = D.cbegin(); i != D.end(); ++i) { // expected-warning{{Iterator incremented behind the past-the-end iterator}} + i = D.erase(i); + } +}