31 const auto Name = CRD->
getName();
32 if (!(Name.ends_with_insensitive(
"iterator") ||
33 Name.ends_with_insensitive(
"iter") || Name.ends_with_insensitive(
"it")))
36 bool HasCopyCtor =
false, HasCopyAssign =
true, HasDtor =
false,
37 HasPreIncrOp =
false, HasPostIncrOp =
false, HasDerefOp =
false;
38 for (
const auto *Method : CRD->
methods()) {
39 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(Method)) {
40 if (Ctor->isCopyConstructor()) {
41 HasCopyCtor = !Ctor->isDeleted() && Ctor->getAccess() ==
AS_public;
45 if (
const auto *Dtor = dyn_cast<CXXDestructorDecl>(Method)) {
46 HasDtor = !Dtor->isDeleted() && Dtor->getAccess() ==
AS_public;
49 if (Method->isCopyAssignmentOperator()) {
50 HasCopyAssign = !Method->isDeleted() && Method->getAccess() ==
AS_public;
53 if (!Method->isOverloadedOperator())
55 const auto OPK = Method->getOverloadedOperator();
56 if (OPK == OO_PlusPlus) {
57 HasPreIncrOp = HasPreIncrOp || (Method->getNumParams() == 0);
58 HasPostIncrOp = HasPostIncrOp || (Method->getNumParams() == 1);
62 HasDerefOp = (Method->getNumParams() == 0);
67 return HasCopyCtor && HasCopyAssign && HasDtor && HasPreIncrOp &&
68 HasPostIncrOp && HasDerefOp;
72 return OK == OO_EqualEqual || OK == OO_ExclaimEqual || OK == OO_Less ||
73 OK == OO_LessEqual || OK == OO_Greater || OK == OO_GreaterEqual;
77 const auto *IdInfo =
Func->getIdentifier();
80 if (
Func->getNumParams() < 2 ||
Func->getNumParams() > 3)
84 return IdInfo->getName() ==
"insert";
88 const auto *IdInfo =
Func->getIdentifier();
91 if (
Func->getNumParams() < 2)
95 return IdInfo->getName() ==
"emplace";
99 const auto *IdInfo =
Func->getIdentifier();
102 if (
Func->getNumParams() < 1 ||
Func->getNumParams() > 2)
106 if (
Func->getNumParams() == 2 &&
109 return IdInfo->getName() ==
"erase";
113 const auto *IdInfo =
Func->getIdentifier();
116 if (
Func->getNumParams() < 1 ||
Func->getNumParams() > 2)
120 if (
Func->getNumParams() == 2 &&
123 return IdInfo->getName() ==
"erase_after";
141 return OK == OO_Star || OK == OO_Arrow || OK == OO_ArrowStar ||
146 return OK == UO_Deref;
150 return OK == BO_PtrMemI;
154 return OK == OO_PlusPlus;
158 return OK == UO_PreInc || OK == UO_PostInc;
162 return OK == OO_MinusMinus;
166 return OK == UO_PreDec || OK == UO_PostDec;
170 return OK == OO_Plus || OK == OO_PlusEqual || OK == OO_Minus ||
175 return OK == BO_Add || OK == BO_AddAssign ||
176 OK == BO_Sub || OK == BO_SubAssign;
187 Reg = Reg->getMostDerivedObjectRegion();
200 Reg = Reg->getMostDerivedObjectRegion();
213 unsigned blockCount) {
214 auto &StateMgr = State->getStateManager();
215 auto &SymMgr = StateMgr.getSymbolManager();
216 auto &ACtx = StateMgr.getContext();
218 auto Sym = SymMgr.conjureSymbol(S, LCtx, ACtx.LongTy, blockCount);
226 const SVal &Distance) {
231 auto &SymMgr = State->getStateManager().getSymbolManager();
232 auto &SVB = State->getStateManager().getSValBuilder();
233 auto &BVF = State->getStateManager().getBasicVals();
235 assert ((Op == OO_Plus || Op == OO_PlusEqual ||
236 Op == OO_Minus || Op == OO_MinusEqual) &&
237 "Advance operator must be one of +, -, += and -=.");
238 auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
246 if (IntDist.
getValue().isNegative()) {
248 BinOp = (BinOp == BO_Add) ? BO_Sub : BO_Add;
251 Pos->setTo(SVB.evalBinOp(State, BinOp,
253 IntDist, SymMgr.
getType(Pos->getOffset()))
267 SValBuilder &SVB = State->getStateManager().getSValBuilder();
277 SVal IsCappedFromAbove =
281 NewState = NewState->assume(*DV,
true);
286 llvm::APSInt Min = -Max;
287 SVal IsCappedFromBelow =
291 NewState = NewState->assume(*DV,
true);
306 auto &SVB = State->getStateManager().getSValBuilder();
308 const auto comparison =
309 SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType());
311 assert(isa<DefinedSVal>(comparison) &&
312 "Symbol comparison must be a `DefinedSVal`");
314 return !State->assume(comparison.castAs<
DefinedSVal>(),
false);
Represents a C++ struct/union/class.
method_range methods() const
Represents a function declaration or definition.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A (possibly-)qualified type.
Stmt - This represents one statement.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isPointerType() const
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
A record of the "type" of an APSInt, used for conversions.
llvm::APSInt getMaxValue() const LLVM_READONLY
Returns the maximum value for this type.
llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY
APSIntType getAPSIntType(QualType T) const
Returns the type of the APSInt used to store values of the given QualType.
MemRegion - The root abstract class for all memory regions.
BasicValueFactory & getBasicValueFactory()
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy)=0
Create a new value which represents a binary expression with two non- location operands.
QualType getConditionType() const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
QualType getType(const ASTContext &) const
Try to get a reasonable type for the given value.
const MemRegion * getAsRegion() const
virtual QualType getType() const =0
Value representing integer constant.
const llvm::APSInt & getValue() const
Represents symbolic expression that isn't a location.
bool isEraseCall(const FunctionDecl *Func)
bool isIterator(const CXXRecordDecl *CRD)
bool isInsertCall(const FunctionDecl *Func)
bool isIteratorType(const QualType &Type)
bool isAccessOperator(OverloadedOperatorKind OK)
ProgramStateRef advancePosition(ProgramStateRef State, const SVal &Iter, OverloadedOperatorKind Op, const SVal &Distance)
bool isEmplaceCall(const FunctionDecl *Func)
const IteratorPosition * getIteratorPosition(ProgramStateRef State, const SVal &Val)
bool isEraseAfterCall(const FunctionDecl *Func)
ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym, long Scale)
ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val, const IteratorPosition &Pos)
bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK)
const ContainerData * getContainerData(ProgramStateRef State, const MemRegion *Cont)
bool compare(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2, BinaryOperator::Opcode Opc)
bool isDecrementOperator(OverloadedOperatorKind OK)
bool isComparisonOperator(OverloadedOperatorKind OK)
bool isDereferenceOperator(OverloadedOperatorKind OK)
bool isIncrementOperator(OverloadedOperatorKind OK)
ProgramStateRef createIteratorPosition(ProgramStateRef State, const SVal &Val, const MemRegion *Cont, const Stmt *S, const LocationContext *LCtx, unsigned blockCount)
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
static IteratorPosition getPosition(const MemRegion *C, SymbolRef Of)