Revision tags: llvmorg-18.1.8, llvmorg-18.1.7, llvmorg-18.1.6, llvmorg-18.1.5, llvmorg-18.1.4, llvmorg-18.1.3, llvmorg-18.1.2, llvmorg-18.1.1, llvmorg-18.1.0, llvmorg-18.1.0-rc4, llvmorg-18.1.0-rc3, llvmorg-18.1.0-rc2, llvmorg-18.1.0-rc1, llvmorg-19-init, llvmorg-17.0.6, llvmorg-17.0.5, llvmorg-17.0.4, llvmorg-17.0.3, llvmorg-17.0.2, llvmorg-17.0.1, llvmorg-17.0.0, llvmorg-17.0.0-rc4, llvmorg-17.0.0-rc3, llvmorg-17.0.0-rc2, llvmorg-17.0.0-rc1, llvmorg-18-init, llvmorg-16.0.6, llvmorg-16.0.5, llvmorg-16.0.4, llvmorg-16.0.3, llvmorg-16.0.2, llvmorg-16.0.1, llvmorg-16.0.0, llvmorg-16.0.0-rc4, llvmorg-16.0.0-rc3, llvmorg-16.0.0-rc2, llvmorg-16.0.0-rc1, llvmorg-17-init, llvmorg-15.0.7, llvmorg-15.0.6, llvmorg-15.0.5, llvmorg-15.0.4 |
|
#
6194229c |
| 19-Oct-2022 |
Tomasz Kamiński <tomasz.kamiński@sonarsource.com> |
[analyzer] Make directly bounded LazyCompoundVal as lazily copied
Previously, `LazyCompoundVal` bindings to subregions referred by `LazyCopoundVals`, were not marked as //lazily copied//.
This chan
[analyzer] Make directly bounded LazyCompoundVal as lazily copied
Previously, `LazyCompoundVal` bindings to subregions referred by `LazyCopoundVals`, were not marked as //lazily copied//.
This change returns `LazyCompoundVals` from `getInterestingValues()`, so their regions can be marked as //lazily copied// in `RemoveDeadBindingsWorker::VisitBinding()`.
Depends on D134947
Authored by: Tomasz Kamiński <tomasz.kamiński@sonarsource.com>
Reviewed By: martong
Differential Revision: https://reviews.llvm.org/D135136
show more ...
|
#
a6b42040 |
| 19-Oct-2022 |
Tomasz Kamiński <tomasz.kamiński@sonarsource.com> |
[analyzer] Fix the liveness of Symbols for values in regions referred by LazyCompoundVal
To illustrate our current understanding, let's start with the following program: https://godbolt.org/z/33f6vh
[analyzer] Fix the liveness of Symbols for values in regions referred by LazyCompoundVal
To illustrate our current understanding, let's start with the following program: https://godbolt.org/z/33f6vheh1 ```lang=c++ void clang_analyzer_printState();
struct C { int x; int y; int more_padding; };
struct D { C c; int z; };
C foo(D d, int new_x, int new_y) { d.c.x = new_x; // B1 assert(d.c.x < 13); // C1
C c = d.c; // L
assert(d.c.y < 10); // C2 assert(d.z < 5); // C3
d.c.y = new_y; // B2
assert(d.c.y < 10); // C4
return c; // R } ``` In the code, we create a few bindings to subregions of root region `d` (`B1`, `B2`), a constrain on the values (`C1`, `C2`, ….), and create a `lazyCompoundVal` for the part of the region `d` at point `L`, which is returned at point `R`.
Now, the question is which of these should remain live as long the return value of the `foo` call is live. In perfect a word we should preserve:
# only the bindings of the subregions of `d.c`, which were created before the copy at `L`. In our example, this includes `B1`, and not `B2`. In other words, `new_x` should be live but `new_y` shouldn’t.
# constraints on the values of `d.c`, that are reachable through `c`. This can be created both before the point of making the copy (`L`) or after. In our case, that would be `C1` and `C2`. But not `C3` (`d.z` value is not reachable through `c`) and `C4` (the original value of`d.c.y` was overridden at `B2` after the creation of `c`).
The current code in the `RegionStore` covers the use case (1), by using the `getInterestingValues()` to extract bindings to parts of the referred region present in the store at the point of copy. This also partially covers point (2), in case when constraints are applied to a location that has binding at the point of the copy (in our case `d.c.x` in `C1` that has value `new_x`), but it fails to preserve the constraints that require creating a new symbol for location (`d.c.y` in `C2`).
We introduce the concept of //lazily copied// locations (regions) to the `SymbolReaper`, i.e. for which a program can access the value stored at that location, but not its address. These locations are constructed as a set of regions referred to by `lazyCompoundVal`. A //readable// location (region) is a location that //live// or //lazily copied// . And symbols that refer to values in regions are alive if the region is //readable//.
For simplicity, we follow the current approach to live regions and mark the base region as //lazily copied//, and consider any subregions as //readable//. This makes some symbols falsy live (`d.z` in our example) and keeps the corresponding constraints alive.
The rename `Regions` to `LiveRegions` inside `RegionStore` is NFC change, that was done to make it clear, what is difference between regions stored in this two sets.
Regression Test: https://reviews.llvm.org/D134941 Co-authored-by: Balazs Benics <benicsbalazs@gmail.com>
Reviewed By: martong, xazax.hun
Differential Revision: https://reviews.llvm.org/D134947
show more ...
|
Revision tags: llvmorg-15.0.3, working, llvmorg-15.0.2 |
|
#
73716baa |
| 03-Oct-2022 |
Tomasz Kamiński <tomasz.kamiński@sonarsource.com> |
[analyzer][NFC] Add tests for D132236
D132236 would have introduced regressions in the symbol lifetime handling. However, the testsuite did not catch this, so here we have some tests, which would ha
[analyzer][NFC] Add tests for D132236
D132236 would have introduced regressions in the symbol lifetime handling. However, the testsuite did not catch this, so here we have some tests, which would have break if D132236 had landed.
This patch addresses the comment https://reviews.llvm.org/D132236#3753238
Co-authored-by: Balazs Benics <balazs.benics@sonarsource.com>
Reviewed By: martong
Differential Revision: https://reviews.llvm.org/D134941
show more ...
|
Revision tags: llvmorg-15.0.1 |
|
#
afcd862b |
| 13-Sep-2022 |
Balazs Benics <benicsbalazs@gmail.com> |
[analyzer] LazyCompoundVals should be always bound as default bindings
`LazyCompoundVals` should only appear as `default` bindings in the store. This fixes the second case in this patch-stack.
Depe
[analyzer] LazyCompoundVals should be always bound as default bindings
`LazyCompoundVals` should only appear as `default` bindings in the store. This fixes the second case in this patch-stack.
Depends on: D132142
Reviewed By: xazax.hun
Differential Revision: https://reviews.llvm.org/D132143
show more ...
|
#
f8643a9b |
| 13-Sep-2022 |
Balazs Benics <benicsbalazs@gmail.com> |
[analyzer] Prefer wrapping SymbolicRegions by ElementRegions
It turns out that in certain cases `SymbolRegions` are wrapped by `ElementRegions`; in others, it's not. This discrepancy can cause the a
[analyzer] Prefer wrapping SymbolicRegions by ElementRegions
It turns out that in certain cases `SymbolRegions` are wrapped by `ElementRegions`; in others, it's not. This discrepancy can cause the analyzer not to recognize if the two regions are actually referring to the same entity, which then can lead to unreachable paths discovered.
Consider this example:
```lang=C++ struct Node { int* ptr; }; void with_structs(Node* n1) { Node c = *n1; // copy Node* n2 = &c; clang_analyzer_dump(*n1); // lazy... clang_analyzer_dump(*n2); // lazy... clang_analyzer_dump(n1->ptr); // rval(n1->ptr): reg_$2<int * SymRegion{reg_$0<struct Node * n1>}.ptr> clang_analyzer_dump(n2->ptr); // rval(n2->ptr): reg_$1<int * Element{SymRegion{reg_$0<struct Node * n1>},0 S64b,struct Node}.ptr> clang_analyzer_eval(n1->ptr != n2->ptr); // UNKNOWN, bad! (void)(*n1); (void)(*n2); } ```
The copy of `n1` will insert a new binding to the store; but for doing that it actually must create a `TypedValueRegion` which it could pass to the `LazyCompoundVal`. Since the memregion in question is a `SymbolicRegion` - which is untyped, it needs to first wrap it into an `ElementRegion` basically implementing this untyped -> typed conversion for the sake of passing it to the `LazyCompoundVal`. So, this is why we have `Element{SymRegion{.}, 0,struct Node}` for `n1`.
The problem appears if the analyzer evaluates a read from the expression `n1->ptr`. The same logic won't apply for `SymbolRegionValues`, since they accept raw `SubRegions`, hence the `SymbolicRegion` won't be wrapped into an `ElementRegion` in that case.
Later when we arrive at the equality comparison, we cannot prove that they are equal.
For more details check the corresponding thread on discourse: https://discourse.llvm.org/t/are-symbolicregions-really-untyped/64406
---
In this patch, I'm eagerly wrapping each `SymbolicRegion` by an `ElementRegion`; basically canonicalizing to this form. It seems reasonable to do so since any object can be thought of as a single array of that object; so this should not make much of a difference.
The tests also underpin this assumption, as only a few were broken by this change; and actually fixed a FIXME along the way.
About the second example, which does the same copy operation - but on the heap - it will be fixed by the next patch.
Reviewed By: martong
Differential Revision: https://reviews.llvm.org/D132142
show more ...
|