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;
186 Reg = Reg->getMostDerivedObjectRegion();
199 Reg = Reg->getMostDerivedObjectRegion();
212 unsigned blockCount) {
213 auto &StateMgr = State->getStateManager();
214 auto &SymMgr = StateMgr.getSymbolManager();
215 auto &ACtx = StateMgr.getContext();
217 auto Sym = SymMgr.conjureSymbol(S, LCtx, ACtx.LongTy, blockCount);
229 auto &SymMgr = State->getStateManager().getSymbolManager();
230 auto &SVB = State->getStateManager().getSValBuilder();
231 auto &BVF = State->getStateManager().getBasicVals();
233 assert ((Op == OO_Plus || Op == OO_PlusEqual ||
234 Op == OO_Minus || Op == OO_MinusEqual) &&
235 "Advance operator must be one of +, -, += and -=.");
236 auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
244 if (IntDist.
getValue().isNegative()) {
246 BinOp = (BinOp == BO_Add) ? BO_Sub : BO_Add;
249 Pos->setTo(SVB.evalBinOp(State, BinOp,
251 IntDist, SymMgr.
getType(Pos->getOffset()))
265 SValBuilder &SVB = State->getStateManager().getSValBuilder();
275 SVal IsCappedFromAbove =
279 NewState = NewState->assume(*DV,
true);
285 SVal IsCappedFromBelow =
289 NewState = NewState->assume(*DV,
true);
304 auto &SVB = State->getStateManager().getSValBuilder();
306 const auto comparison =
307 SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType());
309 assert(isa<DefinedSVal>(comparison) &&
310 "Symbol comparison must be a `DefinedSVal`");
312 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
While nonloc::CompoundVal covers a few simple use cases, nonloc::LazyCompoundVal is a more performant...
Represents symbolic expression that isn't a location.
bool isEraseCall(const FunctionDecl *Func)
const IteratorPosition * getIteratorPosition(ProgramStateRef State, SVal Val)
bool isIterator(const CXXRecordDecl *CRD)
bool isInsertCall(const FunctionDecl *Func)
bool isIteratorType(const QualType &Type)
ProgramStateRef createIteratorPosition(ProgramStateRef State, SVal Val, const MemRegion *Cont, const Stmt *S, const LocationContext *LCtx, unsigned blockCount)
bool isAccessOperator(OverloadedOperatorKind OK)
bool isEmplaceCall(const FunctionDecl *Func)
bool isEraseAfterCall(const FunctionDecl *Func)
ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym, long Scale)
bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK)
ProgramStateRef advancePosition(ProgramStateRef State, SVal Iter, OverloadedOperatorKind Op, SVal Distance)
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)
ProgramStateRef setIteratorPosition(ProgramStateRef State, SVal Val, const IteratorPosition &Pos)
bool isDereferenceOperator(OverloadedOperatorKind OK)
bool isIncrementOperator(OverloadedOperatorKind OK)
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
const FunctionProtoType * T
static IteratorPosition getPosition(const MemRegion *C, SymbolRef Of)