[PATCH] D76590: [Analyzer] Model `empty()` member function of containers

Balogh, Ádám via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 4 06:55:27 PDT 2020


baloghadamsoftware marked 2 inline comments as done.
baloghadamsoftware added inline comments.


================
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;
----------------
martong wrote:
> I understand that the container SVal is no longer `const`, but why did the iterator loose its constness?
We passed it earlier as a constant reference, but `SVal` is small, it should be passed by value.


================
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();
----------------
martong wrote:
> Why do we skip the `const` qualifiers here?
Do you mean for `SVal`? See above.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp:436
+    if (!StateEmpty && !StateNonEmpty) {
+      C.generateSink(State, C.getPredecessor());
+      return;
----------------
martong wrote:
> 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?
Yes, see the comment I added. If data about emptiness based on the difference of begin and and and the return value of `empty()` contradict each other then we are on an impossible branch.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:19
 
+ProgramStateRef relateSymbols(ProgramStateRef State, SymbolRef Sym1,
+                              SymbolRef Sym2, bool Equal);
----------------
martong wrote:
> Docs, docs, docs.
This function is moved here, it is nothing new.


================
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>()) {
----------------
martong wrote:
> Perhaps we should guard `Op` with an assert, I mean it should be either == or !=.
Actually, this works for any comparison operator. So it is enough to assume that `Op` is a comparison operator.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:290
+  if (StateTrue)
+    StateTrue = StateTrue->assume(RetVal, true);
+  if (StateFalse)
----------------
martong wrote:
> Why do we `assume` here again? We already had an assume in `relateSymbols`, hadn't we?
In `relateSymbols` we assumed the comparison of the two symbols. Here we assume the `RetVal`. The new states are `nullptr` if we cannot assume the same for both.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:297
+
+ProgramStateRef relateSymbols(ProgramStateRef State, SymbolRef Sym1,
+                              SymbolRef Sym2, bool Equal) {
----------------
martong wrote:
> Would `assumeEqual` be a better name?
This method is just moved from another source file.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:301
+
+  // FIXME: This code should be reworked as follows:
+  // 1. Subtract the operands using evalBinOp().
----------------
martong wrote:
> Please explain in the comment what is the problem with the current impl.
Ditto. The community requested a future refactoring.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:313-314
+
+  auto NewState = State->assume(comparison.castAs<DefinedSVal>(), Equal);
+  if (!NewState)
+    return nullptr;
----------------
martong wrote:
> Could we merge the declaration of the new state into the parens of the `if`?
No, because we use it later in the function. (See below.)


================
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)
----------------
martong wrote:
> It seems like we don't use it anywhere.
We use this in the definition of the `assert()` macro. And we use that macro in the new test cases.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76590/new/

https://reviews.llvm.org/D76590



More information about the cfe-commits mailing list