21 using namespace clang;
27 class DebugIteratorModeling
28 :
public Checker<eval::Call> {
30 std::unique_ptr<BugType> DebugMsgBugType;
32 template <
typename Getter>
33 void analyzerContainerDataField(
const CallExpr *CE, CheckerContext &C,
35 void analyzerContainerBegin(
const CallExpr *CE, CheckerContext &C)
const;
36 void analyzerContainerEnd(
const CallExpr *CE, CheckerContext &C)
const;
37 template <
typename Getter>
38 void analyzerIteratorDataField(
const CallExpr *CE, CheckerContext &C,
39 Getter
get, SVal Default)
const;
40 void analyzerIteratorPosition(
const CallExpr *CE, CheckerContext &C)
const;
41 void analyzerIteratorContainer(
const CallExpr *CE, CheckerContext &C)
const;
42 void analyzerIteratorValidity(
const CallExpr *CE, CheckerContext &C)
const;
43 ExplodedNode *reportDebugMsg(llvm::StringRef Msg, CheckerContext &C)
const;
45 typedef void (DebugIteratorModeling::*FnCheck)(
const CallExpr *,
46 CheckerContext &)
const;
49 {{0,
"clang_analyzer_container_begin", 1},
50 &DebugIteratorModeling::analyzerContainerBegin},
51 {{0,
"clang_analyzer_container_end", 1},
52 &DebugIteratorModeling::analyzerContainerEnd},
53 {{0,
"clang_analyzer_iterator_position", 1},
54 &DebugIteratorModeling::analyzerIteratorPosition},
55 {{0,
"clang_analyzer_iterator_container", 1},
56 &DebugIteratorModeling::analyzerIteratorContainer},
57 {{0,
"clang_analyzer_iterator_validity", 1},
58 &DebugIteratorModeling::analyzerIteratorValidity},
62 DebugIteratorModeling();
64 bool evalCall(
const CallEvent &Call, CheckerContext &C)
const;
69 DebugIteratorModeling::DebugIteratorModeling() {
70 DebugMsgBugType.reset(
71 new BugType(
this,
"Checking analyzer assumptions",
"debug",
75 bool DebugIteratorModeling::evalCall(
const CallEvent &Call,
76 CheckerContext &C)
const {
77 const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
81 const FnCheck *Handler = Callbacks.lookup(Call);
85 (this->**Handler)(CE, C);
89 template <
typename Getter>
90 void DebugIteratorModeling::analyzerContainerDataField(
const CallExpr *CE,
94 reportDebugMsg(
"Missing container argument", C);
98 auto State = C.getState();
99 const MemRegion *Cont = C.getSVal(CE->
getArg(0)).getAsRegion();
105 State =
State->BindExpr(CE, C.getLocationContext(),
106 nonloc::SymbolVal(Field));
107 C.addTransition(
State);
113 auto &BVF = C.getSValBuilder().getBasicValueFactory();
114 State =
State->BindExpr(CE, C.getLocationContext(),
115 nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));
118 void DebugIteratorModeling::analyzerContainerBegin(
const CallExpr *CE,
119 CheckerContext &C)
const {
120 analyzerContainerDataField(CE, C, [](
const ContainerData *D) {
121 return D->getBegin();
125 void DebugIteratorModeling::analyzerContainerEnd(
const CallExpr *CE,
126 CheckerContext &C)
const {
127 analyzerContainerDataField(CE, C, [](
const ContainerData *D) {
132 template <
typename Getter>
133 void DebugIteratorModeling::analyzerIteratorDataField(
const CallExpr *CE,
136 SVal Default)
const {
138 reportDebugMsg(
"Missing iterator argument", C);
142 auto State = C.getState();
143 SVal
V = C.getSVal(CE->
getArg(0));
146 State =
State->BindExpr(CE, C.getLocationContext(),
get(Pos));
148 State =
State->BindExpr(CE, C.getLocationContext(), Default);
150 C.addTransition(
State);
153 void DebugIteratorModeling::analyzerIteratorPosition(
const CallExpr *CE,
154 CheckerContext &C)
const {
155 auto &BVF = C.getSValBuilder().getBasicValueFactory();
156 analyzerIteratorDataField(CE, C, [](
const IteratorPosition *
P) {
157 return nonloc::SymbolVal(P->getOffset());
158 }, nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));
161 void DebugIteratorModeling::analyzerIteratorContainer(
const CallExpr *CE,
162 CheckerContext &C)
const {
163 auto &BVF = C.getSValBuilder().getBasicValueFactory();
164 analyzerIteratorDataField(CE, C, [](
const IteratorPosition *P) {
165 return loc::MemRegionVal(P->getContainer());
166 }, loc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));
169 void DebugIteratorModeling::analyzerIteratorValidity(
const CallExpr *CE,
170 CheckerContext &C)
const {
171 auto &BVF = C.getSValBuilder().getBasicValueFactory();
172 analyzerIteratorDataField(CE, C, [&BVF](
const IteratorPosition *P) {
174 nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get((P->isValid()))));
175 }, nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));
178 ExplodedNode *DebugIteratorModeling::reportDebugMsg(llvm::StringRef Msg,
179 CheckerContext &C)
const {
180 ExplodedNode *N = C.generateNonFatalErrorNode();
184 auto &BR = C.getBugReporter();
185 BR.emitReport(std::make_unique<PathSensitiveBugReport>(*DebugMsgBugType,
190 void ento::registerDebugIteratorModeling(CheckerManager &mgr) {
191 mgr.registerChecker<DebugIteratorModeling>();
194 bool ento::shouldRegisterDebugIteratorModeling(
const LangOptions &LO) {
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
const SymExpr * SymbolRef
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
const IteratorPosition * getIteratorPosition(ProgramStateRef State, const SVal &Val)
const ContainerData * getContainerData(ProgramStateRef State, const MemRegion *Cont)
Dataflow Directional Tag Classes.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
An immutable map from CallDescriptions to arbitrary data.