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;
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()) {
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();
213 unsigned blockCount) {
214 auto &StateMgr = State->getStateManager();
215 auto &SymMgr = StateMgr.getSymbolManager();
216 auto &ACtx = StateMgr.getContext();
218 auto *Sym = SymMgr.conjureSymbol(Elem, LCtx, ACtx.LongTy, blockCount);
230 auto &SymMgr = State->getStateManager().getSymbolManager();
231 auto &SVB = State->getStateManager().getSValBuilder();
232 auto &BVF = State->getStateManager().getBasicVals();
234 assert ((Op == OO_Plus || Op == OO_PlusEqual ||
235 Op == OO_Minus || Op == OO_MinusEqual) &&
236 "Advance operator must be one of +, -, += and -=.");
237 auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
245 if (IntDist.
getValue()->isNegative()) {
247 BinOp = (BinOp == BO_Add) ? BO_Sub : BO_Add;
250 Pos->setTo(SVB.evalBinOp(State, BinOp,
252 IntDist, SymMgr.
getType(Pos->getOffset()))
270 assert(
T->isSignedIntegerOrEnumerationType());
280 NewState = NewState->assume(*DV,
true);
290 NewState = NewState->assume(*DV,
true);
305 auto &SVB = State->getStateManager().getSValBuilder();
307 const auto comparison =
308 SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType());
311 "Symbol comparison must be a `DefinedSVal`");
313 return !State->assume(comparison.castAs<
DefinedSVal>(),
false);
BinaryOperatorKind Opcode
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.
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 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.
SValBuilder & getSValBuilder()
BasicValueFactory & getBasicValueFactory()
ProgramStateManager & getStateManager()
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.
APSIntPtr 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.
ProgramStateRef createIteratorPosition(ProgramStateRef State, SVal Val, const MemRegion *Cont, ConstCFGElementRef Elem, const LocationContext *LCtx, unsigned blockCount)
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)
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)
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
bool isa(CodeGen::Address addr)
CFGBlock::ConstCFGElementRef ConstCFGElementRef
const FunctionProtoType * T
static IteratorPosition getPosition(const MemRegion *C, SymbolRef Of)