75 using namespace clang;
82 struct IteratorPosition {
92 : Cont(C), Offset(Of) {}
95 const MemRegion *getContainer()
const {
return Cont; }
99 return IteratorPosition(C, Of);
102 IteratorPosition setTo(
SymbolRef NewOf)
const {
103 return IteratorPosition(Cont, NewOf);
107 return Cont == X.Cont && Offset == X.Offset;
111 return Cont != X.Cont || Offset != X.Offset;
114 void Profile(llvm::FoldingSetNodeID &
ID)
const {
120 typedef llvm::PointerUnion<const MemRegion *, SymbolRef> RegionOrSymbol;
123 struct ContainerData {
130 static ContainerData fromBegin(
SymbolRef B) {
131 return ContainerData(B,
nullptr);
134 static ContainerData fromEnd(
SymbolRef E) {
135 return ContainerData(
nullptr, E);
141 ContainerData newBegin(
SymbolRef B)
const {
return ContainerData(B, End); }
143 ContainerData newEnd(
SymbolRef E)
const {
return ContainerData(Begin, E); }
146 return Begin == X.Begin && End == X.End;
150 return Begin != X.Begin || End != X.End;
153 void Profile(llvm::FoldingSetNodeID &ID)
const {
163 RegionOrSymbol Left, Right;
168 : Left(L), Right(R), Equality(Eq) {}
170 RegionOrSymbol getLeft()
const {
return Left; }
171 RegionOrSymbol getRight()
const {
return Right; }
172 bool isEquality()
const {
return Equality; }
174 return Left == X.Left && Right == X.Right && Equality == X.Equality;
177 return Left != X.Left || Right != X.Right || Equality != X.Equality;
179 void Profile(llvm::FoldingSetNodeID &ID)
const { ID.AddInteger(Equality); }
182 class IteratorChecker
183 :
public Checker<check::PreCall, check::PostCall,
184 check::PreStmt<CXXOperatorCallExpr>,
185 check::PostStmt<MaterializeTemporaryExpr>,
186 check::LiveSymbols, check::DeadSymbols,
189 std::unique_ptr<BugType> OutOfRangeBugType;
199 const SVal &RetVal,
const SVal &LHS,
200 const SVal &RHS)
const;
202 const SVal &Cont)
const;
204 const SVal &Cont)
const;
208 const SVal &RetVal,
const SVal &LHS,
209 const SVal &RHS)
const;
210 void reportOutOfRangeBug(
const StringRef &Message,
const SVal &Val,
217 CK_IteratorRangeChecker,
232 bool Assumption)
const;
260 RegionOrSymbol RVal,
bool Equal);
263 const SVal &RVal,
bool Eq);
276 RegionOrSymbol RegOrSym);
278 const IteratorPosition &Pos);
280 RegionOrSymbol RegOrSym,
281 const IteratorPosition &Pos);
284 RegionOrSymbol RegOrSym,
285 const IteratorPosition &Pos,
bool Equal);
287 const IteratorPosition &Pos1,
288 const IteratorPosition &Pos2,
293 const ContainerData &CData);
299 IteratorChecker::IteratorChecker() {
300 OutOfRangeBugType.reset(
301 new BugType(
this,
"Iterator out of range",
"Misuse of STL APIs"));
302 OutOfRangeBugType->setSuppressOnSink(
true);
305 void IteratorChecker::checkPreCall(
const CallEvent &Call,
308 const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.
getDecl());
312 if (Func->isOverloadedOperator()) {
313 if (ChecksEnabled[CK_IteratorRangeChecker] &&
315 if (
const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
318 verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
320 InstCall->getCXXThisVal(), Call.
getArgSVal(0));
324 verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(),
329 }
else if (ChecksEnabled[CK_IteratorRangeChecker] &&
332 if (
const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
333 verifyDereference(C, InstCall->getCXXThisVal());
341 void IteratorChecker::checkPostCall(
const CallEvent &Call,
344 const auto *Func = dyn_cast_or_null<FunctionDecl>(Call.
getDecl());
348 if (Func->isOverloadedOperator()) {
349 const auto Op = Func->getOverloadedOperator();
351 if (
const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
352 handleComparison(C, Call.
getReturnValue(), InstCall->getCXXThisVal(),
359 if (
const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
361 handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
363 InstCall->getCXXThisVal(), Call.
getArgSVal(0));
367 handleRandomIncrOrDecr(C, Func->getOverloadedOperator(),
373 if (
const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
374 handleIncrement(C, Call.
getReturnValue(), InstCall->getCXXThisVal(),
381 if (
const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
382 handleDecrement(C, Call.
getReturnValue(), InstCall->getCXXThisVal(),
402 if (
const auto *InstCall = dyn_cast<CXXInstanceCall>(&Call)) {
405 InstCall->getCXXThisVal());
410 InstCall->getCXXThisVal());
416 if (isa<CXXConstructorCall>(&Call) && Call.
getNumArgs() == 1) {
419 if (cast<CXXConstructorDecl>(Func)->isMoveConstructor()) {
432 for (
unsigned i = 0; i < Call.
getNumArgs(); ++i) {
436 Pos->getContainer());
446 const auto *ThisExpr = COCE->
getArg(0);
451 const auto CurrentThis =
State->getSVal(ThisExpr, LCtx);
452 if (
const auto *Reg = CurrentThis.getAsRegion()) {
456 const auto OldThis = OldState->getSVal(ThisExpr, LCtx);
490 auto RegionMap = State->get<IteratorRegionMap>();
491 for (
const auto Reg : RegionMap) {
492 const auto Offset = Reg.second.getOffset();
494 if (isa<SymbolData>(*i))
498 auto SymbolMap = State->get<IteratorSymbolMap>();
499 for (
const auto Sym : SymbolMap) {
500 const auto Offset = Sym.second.getOffset();
502 if (isa<SymbolData>(*i))
506 auto ContMap = State->get<ContainerMap>();
507 for (
const auto Cont : ContMap) {
508 const auto CData = Cont.second;
509 if (CData.getBegin()) {
512 if (CData.getEnd()) {
518 void IteratorChecker::checkDeadSymbols(
SymbolReaper &SR,
523 auto RegionMap = State->get<IteratorRegionMap>();
524 for (
const auto Reg : RegionMap) {
526 State = State->remove<IteratorRegionMap>(Reg.first);
530 auto SymbolMap = State->get<IteratorSymbolMap>();
531 for (
const auto Sym : SymbolMap) {
532 if (!SR.
isLive(Sym.first)) {
533 State = State->remove<IteratorSymbolMap>(Sym.first);
537 auto ContMap = State->get<ContainerMap>();
538 for (
const auto Cont : ContMap) {
543 State = State->remove<ContainerMap>(Cont.first);
548 auto ComparisonMap = State->get<IteratorComparisonMap>();
549 for (
const auto Comp : ComparisonMap) {
550 if (!SR.
isLive(Comp.first)) {
551 State = State->remove<IteratorComparisonMap>(Comp.first);
559 bool Assumption)
const {
567 if (Opc != BO_EQ && Opc != BO_NE)
570 bool Negated =
false;
578 if (SIE->getRHS() != 0)
582 Negated = SIE->getOpcode() == BO_EQ;
584 if (Opc != BO_EQ && Opc != BO_NE)
593 (Comp->isEquality() == Assumption) != Negated);
609 State =
saveComparison(State, Condition, LVal, RVal, Op == OO_EqualEqual);
614 (Op == OO_EqualEqual) == (TruthVal->getValue() != 0)))) {
623 const SVal &Val)
const {
629 "IteratorOutOfRange");
633 reportOutOfRangeBug(
"Iterator accessed outside of its range.", Val, C, N);
638 const SVal &Iter,
bool Postfix)
const {
647 const auto OldOffset = Pos->getOffset();
652 SymMgr.getType(OldOffset)).getAsSymbol();
653 auto NewPos = Pos->setTo(NewOffset);
661 const SVal &Iter,
bool Postfix)
const {
670 const auto OldOffset = Pos->getOffset();
675 SymMgr.getType(OldOffset)).getAsSymbol();
676 auto NewPos = Pos->setTo(NewOffset);
692 SValBuilder &SVB = State->getStateManager().getSValBuilder();
701 llvm::APSInt Max = AT.getMaxValue() / AT.getValue(Scale);
702 SVal IsCappedFromAbove =
706 NewState = NewState->assume(*DV,
true);
711 llvm::APSInt Min = -Max;
712 SVal IsCappedFromBelow =
716 NewState = NewState->assume(*DV,
true);
728 const SVal &RHS)
const {
736 const auto *value = &RHS;
738 const auto val = State->getRawSVal(*loc);
744 auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
745 const auto OldOffset = Pos->getOffset();
751 SymMgr.getType(OldOffset)).getAsSymbol();
755 NewOffset = SymMgr.conjureSymbol(
nullptr, LCtx, SymMgr.getType(OldOffset),
759 auto NewPos = Pos->setTo(NewOffset);
760 auto &TgtVal = (Op == OO_PlusEqual || Op == OO_MinusEqual) ? LHS : RetVal;
769 const SVal &RHS)
const {
779 value = State->getRawSVal(*loc);
788 auto BinOp = (Op == OO_Plus || Op == OO_PlusEqual) ? BO_Add : BO_Sub;
789 const auto OldOffset = Pos->getOffset();
796 SymMgr.getType(OldOffset)).getAsSymbol();
797 auto NewPos = Pos->setTo(NewOffset);
804 reportOutOfRangeBug(
"Iterator accessed past its end.", LHS, C, N);
809 const SVal &RetVal,
const SVal &Cont)
const {
815 ContReg = CBOR->getSuperRegion();
830 IteratorPosition::getPosition(ContReg, BeginSym));
835 const SVal &RetVal,
const SVal &Cont)
const {
841 ContReg = CBOR->getSuperRegion();
856 IteratorPosition::getPosition(ContReg, EndSym));
864 Cont = CBOR->getSuperRegion();
873 IteratorPosition::getPosition(Cont, Sym));
877 void IteratorChecker::reportOutOfRangeBug(
const StringRef &Message,
880 auto R = llvm::make_unique<BugReport>(*OutOfRangeBugType, Message, ErrNode);
881 R->markInteresting(Val);
906 const auto Name = CRD->
getName();
907 if (!(Name.endswith_lower(
"iterator") || Name.endswith_lower(
"iter") ||
908 Name.endswith_lower(
"it")))
911 bool HasCopyCtor =
false, HasCopyAssign =
true, HasDtor =
false,
912 HasPreIncrOp =
false, HasPostIncrOp =
false, HasDerefOp =
false;
913 for (
const auto *Method : CRD->
methods()) {
914 if (
const auto *Ctor = dyn_cast<CXXConstructorDecl>(Method)) {
915 if (Ctor->isCopyConstructor()) {
916 HasCopyCtor = !Ctor->isDeleted() && Ctor->getAccess() ==
AS_public;
920 if (
const auto *Dtor = dyn_cast<CXXDestructorDecl>(Method)) {
921 HasDtor = !Dtor->isDeleted() && Dtor->getAccess() ==
AS_public;
924 if (Method->isCopyAssignmentOperator()) {
925 HasCopyAssign = !Method->isDeleted() && Method->getAccess() ==
AS_public;
928 if (!Method->isOverloadedOperator())
930 const auto OPK = Method->getOverloadedOperator();
931 if (OPK == OO_PlusPlus) {
932 HasPreIncrOp = HasPreIncrOp || (Method->getNumParams() == 0);
933 HasPostIncrOp = HasPostIncrOp || (Method->getNumParams() == 1);
936 if (OPK == OO_Star) {
937 HasDerefOp = (Method->getNumParams() == 0);
942 return HasCopyCtor && HasCopyAssign && HasDtor && HasPreIncrOp &&
943 HasPostIncrOp && HasDerefOp;
950 return IdInfo->
getName().endswith_lower(
"begin");
957 return IdInfo->
getName().endswith_lower(
"end");
961 return OK == OO_EqualEqual || OK == OO_ExclaimEqual;
965 return OK == OO_Star || OK == OO_Arrow || OK == OO_ArrowStar ||
970 return OK == OO_PlusPlus;
974 return OK == OO_MinusMinus;
978 return OK == OO_Plus || OK == OO_PlusEqual || OK == OO_Minus ||
983 if (
const auto *BSE = dyn_cast<BinarySymExpr>(SE)) {
984 return BSE->getOpcode();
985 }
else if (
const auto *SC = dyn_cast<SymbolConjured>(SE)) {
986 const auto *COE = dyn_cast_or_null<CXXOperatorCallExpr>(SC->getStmt());
989 if (COE->getOperator() == OO_EqualEqual) {
991 }
else if (COE->getOperator() == OO_ExclaimEqual) {
1005 return LCVal->getRegion();
1007 return RegionOrSymbol();
1011 RegionOrSymbol LVal,
1012 RegionOrSymbol RVal,
bool Equal) {
1015 if (LPos && !RPos) {
1017 }
else if (!LPos && RPos) {
1019 }
else if (LPos && RPos) {
1027 const SVal &RVal,
bool Eq) {
1030 if (!Left || !Right)
1032 return State->set<IteratorComparisonMap>(Condition,
1038 return State->get<IteratorComparisonMap>(Condition);
1046 return CDataPtr->getBegin();
1054 return CDataPtr->getEnd();
1063 if (CDataPtr->getBegin()) {
1066 const auto CData = CDataPtr->newBegin(Sym);
1069 const auto CData = ContainerData::fromBegin(Sym);
1078 if (CDataPtr->getEnd()) {
1081 const auto CData = CDataPtr->newEnd(Sym);
1084 const auto CData = ContainerData::fromEnd(Sym);
1090 return State->get<ContainerMap>(Cont);
1094 const ContainerData &CData) {
1095 return State->set<ContainerMap>(Cont, CData);
1101 return State->get<IteratorRegionMap>(Reg);
1103 return State->get<IteratorSymbolMap>(Sym);
1105 return State->get<IteratorRegionMap>(LCVal->getRegion());
1111 RegionOrSymbol RegOrSym) {
1113 return State->get<IteratorRegionMap>(RegOrSym.get<
const MemRegion *>());
1115 return State->get<IteratorSymbolMap>(RegOrSym.get<
SymbolRef>());
1121 const IteratorPosition &Pos) {
1123 return State->set<IteratorRegionMap>(Reg, Pos);
1125 return State->set<IteratorSymbolMap>(Sym, Pos);
1127 return State->set<IteratorRegionMap>(LCVal->getRegion(), Pos);
1133 RegionOrSymbol RegOrSym,
1134 const IteratorPosition &Pos) {
1136 return State->set<IteratorRegionMap>(RegOrSym.get<
const MemRegion *>(),
1139 return State->set<IteratorSymbolMap>(RegOrSym.get<
SymbolRef>(), Pos);
1146 return State->remove<IteratorRegionMap>(Reg);
1148 return State->remove<IteratorSymbolMap>(Sym);
1150 return State->remove<IteratorRegionMap>(LCVal->getRegion());
1156 RegionOrSymbol RegOrSym,
1157 const IteratorPosition &Pos,
1167 const IteratorPosition &Pos1,
1168 const IteratorPosition &Pos2,
1170 auto &SVB = State->getStateManager().getSValBuilder();
1177 const auto comparison =
1180 SVB.getConditionType());
1183 "Symbol comparison must be a `DefinedSVal`");
1185 auto NewState = State->assume(comparison.castAs<
DefinedSVal>(), Equal);
1186 if (
const auto CompSym = comparison.getAsSymbol()) {
1187 assert(isa<SymIntExpr>(CompSym) &&
1188 "Symbol comparison must be a `SymIntExpr`");
1190 cast<SymIntExpr>(CompSym)->
getOpcode()) &&
1191 "Symbol comparison must be a comparison");
1199 auto RegionMap = State->get<IteratorRegionMap>();
1200 for (
const auto Reg : RegionMap) {
1201 if (Reg.second.getContainer() == Cont)
1205 auto SymbolMap = State->get<IteratorSymbolMap>();
1206 for (
const auto Sym : SymbolMap) {
1207 if (Sym.second.getContainer() == Cont)
1215 auto &BVF = State->getBasicVals();
1222 const auto *Cont = Pos.getContainer();
1230 const auto Beg = CData->getBegin();
1232 if (isLess(State, Pos.getOffset(), Beg)) {
1237 const auto End = CData->getEnd();
1239 if (isGreaterOrEqual(State, Pos.getOffset(),
End)) {
1248 return compare(State, Sym1, Sym2, BO_LT);
1252 return compare(State, Sym1, Sym2, BO_GE);
1262 auto &SVB = State->getStateManager().getSValBuilder();
1264 const auto comparison =
1265 SVB.evalBinOp(State, Opc, NL1, NL2, SVB.getConditionType());
1268 "Symbol comparison must be a `DefinedSVal`");
1270 return !State->assume(comparison.castAs<
DefinedSVal>(),
false);
1275 #define REGISTER_CHECKER(name) \ 1276 void ento::register##name(CheckerManager &Mgr) { \ 1277 auto *checker = Mgr.registerChecker<IteratorChecker>(); \ 1278 checker->ChecksEnabled[IteratorChecker::CK_##name] = true; \ 1279 checker->CheckNames[IteratorChecker::CK_##name] = \ 1280 Mgr.getCurrentCheckName(); \ A call to an overloaded operator written using operator syntax.
const ProgramStateRef processComparison(ProgramStateRef State, RegionOrSymbol LVal, RegionOrSymbol RVal, bool Equal)
Represents a function declaration or definition.
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
void markLive(SymbolRef sym)
Unconditionally marks a symbol as live.
SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont)
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
bool isSimpleComparisonOperator(OverloadedOperatorKind OK)
bool operator==(CanQual< T > x, CanQual< U > y)
REGISTER_MAP_WITH_PROGRAMSTATE(IteratorRegionMap, const MemRegion *, IteratorPosition) REGISTER_MAP_WITH_PROGRAMSTATE(IteratorComparisonMap
A helper class which wraps a boolean value set to false by default.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
The base class of the type hierarchy.
bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos)
const ProgramStateRef & getState() const
bool isZero(ProgramStateRef State, const NonLoc &Val)
Represents a prvalue temporary that is written into memory so that a reference can bind to it...
Value representing integer constant.
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call.
BasicValueFactory & getBasicVals()
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Expr * GetTemporaryExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue...
symbol_iterator symbol_begin() const
ProgramStateRef adjustIteratorPosition(ProgramStateRef State, RegionOrSymbol RegOrSym, const IteratorPosition &Pos, bool Equal)
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument.
const SymExpr * getAsSymbolicExpression() const
getAsSymbolicExpression - If this Sval wraps a symbolic expression then return that expression...
bool isLiveRegion(const MemRegion *region)
SVal getReturnValue() const
Returns the return value of the call.
A record of the "type" of an APSInt, used for conversions.
Represents a symbolic expression like 'x' + 3.
bool isEndCall(const FunctionDecl *Func)
ExplodedNode * getFirstPred()
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs, typeofs, etc., as well as any qualifiers.
virtual QualType getType() const =0
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
const IteratorPosition * getIteratorPosition(ProgramStateRef State, RegionOrSymbol RegOrSym)
const RegionTy * getAs() const
Expr - This represents one expression.
static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y)
bool isDereferenceOperator(OverloadedOperatorKind OK)
QualType getConditionType() const
SymbolManager & getSymbolManager()
ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont, const SymbolRef Sym)
virtual const Decl * getDecl() const
Returns the declaration of the function or method that will be called.
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
const ContainerData * getContainerData(ProgramStateRef State, const MemRegion *Cont)
bool isComparisonOp() const
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Generate a sink node.
ProgramStateRef setIteratorPosition(ProgramStateRef State, RegionOrSymbol RegOrSym, const IteratorPosition &Pos)
const MemRegion * getAsRegion() const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
SymbolRef getContainerBegin(ProgramStateRef State, const MemRegion *Cont)
A class responsible for cleaning up unused symbols.
bool isDecrementOperator(OverloadedOperatorKind OK)
ProgramStateRef relateIteratorPositions(ProgramStateRef State, const IteratorPosition &Pos1, const IteratorPosition &Pos2, bool Equal)
const IteratorComparison * loadComparison(ProgramStateRef State, const SymExpr *Condition)
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.
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
StringRef getName() const
Return the actual identifier string.
Dataflow Directional Tag Classes.
ASTContext & getASTContext()
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
#define REGISTER_CHECKER(name)
static symbol_iterator symbol_end()
BinaryOperator::Opcode getOpcode(const SymExpr *SE)
Represents symbolic expression that isn't a location.
Represents an abstract call to a function or method along a particular path.
const SymbolConjured * conjureSymbol(const Stmt *E, const LocationContext *LCtx, QualType T, unsigned VisitCount, const void *SymbolTag=nullptr)
bool isIteratorType(const QualType &Type)
ProgramStateRef removeIteratorPosition(ProgramStateRef State, const SVal &Val)
APSIntType getAPSIntType(QualType T) const
Returns the type of the APSInt used to store values of the given QualType.
ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont, const ContainerData &CData)
BasicValueFactory & getBasicValueFactory()
const ProgramStateRef & getState() const
SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op, const ConcreteInt &R) const
const ProgramStateRef saveComparison(ProgramStateRef State, const SymExpr *Condition, const SVal &LVal, const SVal &RVal, bool Eq)
const SymExpr * getAsSymExpr() const
QualType getResultType() const
Returns the result type, adjusted for references.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont)
Represents a C++ struct/union/class.
bool isBeginCall(const FunctionDecl *Func)
const RegionOrSymbol getRegionOrSymbol(const SVal &Val)
bool operator!=(CanQual< T > x, CanQual< U > y)
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
SValBuilder & getSValBuilder()
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
ProgramStateRef createContainerBegin(ProgramStateRef State, const MemRegion *Cont, const SymbolRef Sym)
bool isPointerType() const
bool isIncrementOperator(OverloadedOperatorKind OK)
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
const LocationContext * getLocationContext() const
bool isIterator(const CXXRecordDecl *CRD)
static ProgramStateRef assumeNoOverflow(ProgramStateRef State, SymbolRef Sym, long Scale)
bool isLive(SymbolRef sym)
bool isRandomIncrOrDecrOperator(OverloadedOperatorKind OK)
method_range methods() const