NoQ requested changes to this revision.
NoQ added inline comments.
This revision now requires changes to proceed.


================
Comment at: clang/lib/StaticAnalyzer/Checkers/Iterator.cpp:330-336
+SVal getReturnIterator(const CallEvent &Call) {
+  Optional<SVal> RetValUnderConstr = Call.getReturnValueUnderConstruction();
+  if (RetValUnderConstr.hasValue())
+    return *RetValUnderConstr;
+
+  return Call.getReturnValue();
+}
----------------
NoQ wrote:
> I still believe you have not addressed the problem while moving the functions 
> from D81718 to this patch. The caller of this function has no way of knowing 
> whether the return value is the prvalue of the iterator or the glvalue of the 
> iterator.
> 
> Looks like most callers are safe because they expect the object of interest 
> to also be already tracked. But it's quite possible that both are tracked, 
> say:
> 
> ```lang=c++
>   Container1<T> container1 = ...;
>   Container2<Container1::iterator> container2 = { container1.begin() };
>   container2.begin(); // ???
> ```
> 
> Suppose `Container1::iterator` is implemented as an object and 
> `Container2::iterator` is implemented as a pointer. In this case 
> `getIteratorPosition(getReturnIterator())` would yield the position of 
> `container1.begin()` whereas the correct answer is the position of 
> `container2.begin()`.
> 
> This problem may seem artificial but it is trivial to avoid if you simply 
> stop defending your convoluted solution of looking at value classes instead 
> of AST types.
Ugh, the problem is much worse. D82185 is entirely broken for the exact reason 
i described above and you only didn't notice it because you wrote almost no 
tests.

Consider the test you've added in D82185:

```lang=c++
void begin_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
  auto i = c.begin();

  clang_analyzer_eval(clang_analyzer_iterator_container(i) == &c); // 
expected-warning{{TRUE}}
}
```

It breaks very easily if you modify it slightly:
```lang=c++
void begin_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
  auto i = c.begin();
  ++i; // <==

  clang_analyzer_eval(clang_analyzer_iterator_container(i) == &c); // Says 
FALSE!
}
```
The iterator obviously still points to the same container, so why does the test 
fail? Because you're tracking the wrong iterator: you treated your 
`&SymRegion{conj_$3}` as a glvalue whereas you should have treated it as a 
prvalue. In other words, your checker thinks that `&SymRegion{conj_$3}` is the 
location of an iterator object rather than the iterator itself, and after you 
increment the pointer it thinks that it's a completely unrelated iterator.

There's a separate concern about why does it say `FALSE` (should be `UNKNOWN`) 
but you get the point.


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

https://reviews.llvm.org/D77229

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to