[PATCH] D76590: [Analyzer] Model `empty()` member function of containers
Gabor Marton via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 23 08:41:50 PDT 2020
martong added inline comments.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp:34
- void handleBegin(CheckerContext &C, const Expr *CE, const SVal &RetVal,
- const SVal &Cont) const;
- void handleEnd(CheckerContext &C, const Expr *CE, const SVal &RetVal,
- const SVal &Cont) const;
- void handleAssignment(CheckerContext &C, const SVal &Cont,
- const Expr *CE = nullptr,
- const SVal &OldCont = UndefinedVal()) const;
- void handleAssign(CheckerContext &C, const SVal &Cont) const;
- void handleClear(CheckerContext &C, const SVal &Cont) const;
- void handlePushBack(CheckerContext &C, const SVal &Cont) const;
- void handlePopBack(CheckerContext &C, const SVal &Cont) const;
- void handlePushFront(CheckerContext &C, const SVal &Cont) const;
- void handlePopFront(CheckerContext &C, const SVal &Cont) const;
- void handleInsert(CheckerContext &C, const SVal &Cont,
- const SVal &Iter) const;
- void handleErase(CheckerContext &C, const SVal &Cont, const SVal &Iter) const;
- void handleErase(CheckerContext &C, const SVal &Cont, const SVal &Iter1,
- const SVal &Iter2) const;
- void handleEraseAfter(CheckerContext &C, const SVal &Cont,
- const SVal &Iter) const;
- void handleEraseAfter(CheckerContext &C, const SVal &Cont, const SVal &Iter1,
- const SVal &Iter2) const;
+ void handleBegin(CheckerContext &C, const Expr *CE, SVal RetVal,
+ SVal Cont) const;
----------------
Perhaps it would be easier to read these functions if we had a documentation for their parameters. Maybe we could have some of them documented in one comment since many seem to have similar params.
Or maybe just renaming `Cont` to `Container` would help also.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp:56
+ SVal RetVal) const;
+ void handleErase(CheckerContext &C, const Expr *CE, SVal Cont, SVal Iter,
+ SVal RetVal) const;
----------------
I understand that the container SVal is no longer `const`, but why did the iterator loose its constness?
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp:74
- typedef void (ContainerModeling::*NoItParamFn)(CheckerContext &,
- const SVal &) const;
+ typedef void (ContainerModeling::*NoItParamFn)(CheckerContext &, const Expr *,
+ SVal, SVal) const;
----------------
Just a nit, if we are at counting below (one, two) then perhaps `Zero` would be more coherent with the other typedefs?
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp:277
void ContainerModeling::handleBegin(CheckerContext &C, const Expr *CE,
- const SVal &RetVal, const SVal &Cont) const {
+ SVal RetVal, SVal Cont) const {
const auto *ContReg = Cont.getAsRegion();
----------------
Why do we skip the `const` qualifiers here?
================
Comment at: clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp:436
+ if (!StateEmpty && !StateNonEmpty) {
+ C.generateSink(State, C.getPredecessor());
+ return;
----------------
Is there really no sense to continue the analysis here? In what state we are here exactly? Is there an inconsistency between the `begin` , `end` and the return value?
================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:19
+ProgramStateRef relateSymbols(ProgramStateRef State, SymbolRef Sym1,
+ SymbolRef Sym2, bool Equal);
----------------
Docs, docs, docs.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:274
+assumeComparison(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
+ DefinedSVal RetVal, OverloadedOperatorKind Op) {
+ if (const auto TruthVal = RetVal.getAs<nonloc::ConcreteInt>()) {
----------------
Perhaps we should guard `Op` with an assert, I mean it should be either == or !=.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:276
+ if (const auto TruthVal = RetVal.getAs<nonloc::ConcreteInt>()) {
+ if ((State = relateSymbols(State, Sym1, Sym2,
+ (Op == OO_EqualEqual) ==
----------------
Could we spare the `if` with just keeping the declaration of `State` and then
```
return std::make_pair(State, nullptr);
```
?
================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:277-278
+ if ((State = relateSymbols(State, Sym1, Sym2,
+ (Op == OO_EqualEqual) ==
+ (TruthVal->getValue() != 0)))) {
+ return std::make_pair(State, nullptr);
----------------
This is hard to read for me. Also, Isn't it enough just to write `TruthVal->getValue()` ?
================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:290
+ if (StateTrue)
+ StateTrue = StateTrue->assume(RetVal, true);
+ if (StateFalse)
----------------
Why do we `assume` here again? We already had an assume in `relateSymbols`, hadn't we?
================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:301
+
+ // FIXME: This code should be reworked as follows:
+ // 1. Subtract the operands using evalBinOp().
----------------
Please explain in the comment what is the problem with the current impl.
================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:313-314
+
+ auto NewState = State->assume(comparison.castAs<DefinedSVal>(), Equal);
+ if (!NewState)
+ return nullptr;
----------------
Could we merge the declaration of the new state into the parens of the `if`?
================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.h:172
long Scale);
+std::pair<ProgramStateRef, ProgramStateRef>
+assumeComparison(ProgramStateRef State, SymbolRef Sym1, SymbolRef Sym2,
----------------
Documentation would be helpful.
================
Comment at: clang/test/Analysis/container-modeling.cpp:19
+extern void __assert_fail (__const char *__assertion, __const char *__file,
+ unsigned int __line, __const char *__function)
----------------
It seems like we don't use it anywhere.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D76590/new/
https://reviews.llvm.org/D76590
More information about the cfe-commits
mailing list