Revision tags: llvmorg-21-init, llvmorg-19.1.7, llvmorg-19.1.6, llvmorg-19.1.5, llvmorg-19.1.4, llvmorg-19.1.3, llvmorg-19.1.2, llvmorg-19.1.1, llvmorg-19.1.0, llvmorg-19.1.0-rc4, llvmorg-19.1.0-rc3, llvmorg-19.1.0-rc2 |
|
#
0362a299 |
| 29-Jul-2024 |
martinboehme <mboehme@google.com> |
[clang][dataflow] Fix bug in `buildContainsExprConsumedInDifferentBlock()`. (#100874)
This was missing a call to `ignoreCFGOmittedNodes()`. As a result, the function would erroneously conclude that
[clang][dataflow] Fix bug in `buildContainsExprConsumedInDifferentBlock()`. (#100874)
This was missing a call to `ignoreCFGOmittedNodes()`. As a result, the function would erroneously conclude that a block did not contain an expression consumed in a different block if the expression in question was surrounded by a `ParenExpr` in the consuming block. The patch adds a test that triggers this scenario (and fails without the fix).
To prevent this kind of bug in the future, the patch also adds a new method `blockForStmt()` to `AdornedCFG` that calls `ignoreCFGOmittedNodes()` and is preferred over accessing `getStmtToBlock()` directly.
show more ...
|
Revision tags: llvmorg-19.1.0-rc1, llvmorg-20-init, llvmorg-18.1.8, llvmorg-18.1.7, llvmorg-18.1.6 |
|
#
80d9ae9c |
| 15-May-2024 |
Samira Bazuzi <bazuzi@google.com> |
[clang][dataflow] Fully support Environment construction for Stmt analysis. (#91616)
Assume in fewer places that the analysis is of a `FunctionDecl`, and
initialize the `Environment` properly for `
[clang][dataflow] Fully support Environment construction for Stmt analysis. (#91616)
Assume in fewer places that the analysis is of a `FunctionDecl`, and
initialize the `Environment` properly for `Stmt`s.
Moves constructors for `Environment` to header to make it more obvious
that there are only minor differences between them and very little
initialization in the constructors.
Tested with check-clang-tooling.
show more ...
|
Revision tags: llvmorg-18.1.5, llvmorg-18.1.4 |
|
#
bbd259af |
| 04-Apr-2024 |
Yitzhak Mandelbaum <ymand@users.noreply.github.com> |
[clang][dataflow] Refactor `widen` API to be explicit about change effect. (#87233)
The previous API relied on pointer equality of inputs and outputs to
signal whether a change occured. This was to
[clang][dataflow] Refactor `widen` API to be explicit about change effect. (#87233)
The previous API relied on pointer equality of inputs and outputs to
signal whether a change occured. This was too subtle and led to bugs in
practice. It was also very limiting: the override could not return an equivalent (but
not identical) value.
show more ...
|
Revision tags: llvmorg-18.1.3, llvmorg-18.1.2 |
|
#
59ff3adc |
| 19-Mar-2024 |
martinboehme <mboehme@google.com> |
[clang][dataflow][NFC] Rename `ControlFlowContext` to `AdornedCFG`. (#85640)
This expresses better what the class actually does, and it reduces the number of `Context`s that we have in the codebase.
[clang][dataflow][NFC] Rename `ControlFlowContext` to `AdornedCFG`. (#85640)
This expresses better what the class actually does, and it reduces the number of `Context`s that we have in the codebase.
A deprecated alias `ControlFlowContext` is available from the old header.
show more ...
|
Revision tags: llvmorg-18.1.1 |
|
#
d5aecf0c |
| 07-Mar-2024 |
martinboehme <mboehme@google.com> |
[clang][nullability] Don't discard expression state before end of full-expression. (#82611)
In https://github.com/llvm/llvm-project/pull/72985, I made a change to
discard
expression state (`ExprTo
[clang][nullability] Don't discard expression state before end of full-expression. (#82611)
In https://github.com/llvm/llvm-project/pull/72985, I made a change to
discard
expression state (`ExprToLoc` and `ExprToVal`) at the beginning of each
basic
block. I did so with the claim that "we never need to access entries
from these
maps outside of the current basic block", noting that there are
exceptions to
this claim when control flow happens inside a full-expression (the
operands of
`&&`, `||`, and the conditional operator live in different basic blocks
than the
operator itself) but that we already have a mechanism for retrieving the
values
of these operands from the environment for the block they are computed
in.
It turns out, however, that the operands of these operators aren't the
only
expressions whose values can be accessed from a different basic block;
when
control flow happens within a full-expression, that control flow can be
"interposed" between an expression and its parent. Here is an example:
```cxx
void f(int*, int);
bool cond();
void target() {
int i = 0;
f(&i, cond() ? 1 : 0);
}
```
([godbolt](https://godbolt.org/z/hrbj1Mj3o))
In the CFG[^1] , note how the expression for `&i` is computed in block
B4,
but the parent of this expression (the `CallExpr`) is located in block
B1.
The the argument expression `&i` and the `CallExpr` are essentially
"torn apart"
into different basic blocks by the conditional operator in the second
argument.
In other words, the edge between the `CallExpr` and its argument `&i`
straddles
the boundary between two blocks.
I used to think that this scenario -- where an edge between an
expression and
one of its children straddles a block boundary -- could only happen
between the
expression that triggers the control flow (`&&`, `||`, or the
conditional
operator) and its children, but the example above shows that other
expressions
can be affected as well; the control flow is still triggered by `&&`,
`||` or
the conditional operator, but the expressions affected lie outside these
operators.
Discarding expression state too soon is harmful. For example, an
analysis that
checks the arguments of the `CallExpr` above would not be able to
retrieve a
value for the `&i` argument.
This patch therefore ensures that we don't discard expression state
before the
end of a full-expression. In other cases -- when the evaluation of a
full-expression is complete -- we still want to discard expression state
for the
reasons explained in https://github.com/llvm/llvm-project/pull/72985
(avoid
performing joins on boolean values that are no longer needed, which
unnecessarily extends the flow condition; improve debuggability by
removing
clutter from the expression state).
The impact on performance from this change is about a 1% slowdown in the
Crubit nullability check benchmarks:
```
name old cpu/op new cpu/op delta
BM_PointerAnalysisCopyPointer 71.9µs ± 1% 71.9µs ± 2% ~ (p=0.987 n=15+20)
BM_PointerAnalysisIntLoop 190µs ± 1% 192µs ± 2% +1.06% (p=0.000 n=14+16)
BM_PointerAnalysisPointerLoop 325µs ± 5% 324µs ± 4% ~ (p=0.496 n=18+20)
BM_PointerAnalysisBranch 193µs ± 0% 192µs ± 4% ~ (p=0.488 n=14+18)
BM_PointerAnalysisLoopAndBranch 521µs ± 1% 525µs ± 3% +0.94% (p=0.017 n=18+19)
BM_PointerAnalysisTwoLoops 337µs ± 1% 341µs ± 3% +1.19% (p=0.004 n=17+19)
BM_PointerAnalysisJoinFilePath 1.62ms ± 2% 1.64ms ± 3% +0.92% (p=0.021 n=20+20)
BM_PointerAnalysisCallInLoop 1.14ms ± 1% 1.15ms ± 4% ~ (p=0.135 n=16+18)
```
[^1]:
```
[B5 (ENTRY)]
Succs (1): B4
[B1]
1: [B4.9] ? [B2.1] : [B3.1]
2: [B4.4]([B4.6], [B1.1])
Preds (2): B2 B3
Succs (1): B0
[B2]
1: 1
Preds (1): B4
Succs (1): B1
[B3]
1: 0
Preds (1): B4
Succs (1): B1
[B4]
1: 0
2: int i = 0;
3: f
4: [B4.3] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(int *, int))
5: i
6: &[B4.5]
7: cond
8: [B4.7] (ImplicitCastExpr, FunctionToPointerDecay, _Bool (*)(void))
9: [B4.8]()
T: [B4.9] ? ... : ...
Preds (1): B5
Succs (2): B2 B3
[B0 (EXIT)]
Preds (1): B1
```
show more ...
|
Revision tags: llvmorg-18.1.0, llvmorg-18.1.0-rc4 |
|
#
e899641d |
| 22-Feb-2024 |
martinboehme <mboehme@google.com> |
[clang][dataflow] Fix inaccuracies in `buildStmtToBasicBlockMap()`. (#82496)
See the comments added to the code for details on the inaccuracies that have now been fixed.
The patch adds tests that f
[clang][dataflow] Fix inaccuracies in `buildStmtToBasicBlockMap()`. (#82496)
See the comments added to the code for details on the inaccuracies that have now been fixed.
The patch adds tests that fail with the old implementation.
show more ...
|
Revision tags: llvmorg-18.1.0-rc3, llvmorg-18.1.0-rc2 |
|
#
672fb27b |
| 06-Feb-2024 |
Yitzhak Mandelbaum <ymand@users.noreply.github.com> |
[clang][dataflow] Add new `join` API and replace existing `merge` implementations. (#80361)
This patch adds a new interface for the join operation, now properly called `join`. Originally, the framew
[clang][dataflow] Add new `join` API and replace existing `merge` implementations. (#80361)
This patch adds a new interface for the join operation, now properly called `join`. Originally, the framework offered a single `merge` operation, which could serve either as a join or a widening. In practice, though we found this conflation didn't work for non-trivial anlyses, and split of the widening operation (`widen`). This change completes the transition by introducing a proper `join` with strict join semantics.
In the process, it drops an odd (and often misused) aspect of `merge` wherein callees could implictly instruct the framework to drop the current entry by returning `false`. This features was never used correctly in analyses and doesn't belong in a join operation, so it is omitted.
---------
Co-authored-by: Dmitri Gribenko <gribozavr@gmail.com> Co-authored-by: martinboehme <mboehme@google.com>
show more ...
|
Revision tags: llvmorg-18.1.0-rc1, llvmorg-19-init |
|
#
f3dd8f10 |
| 23-Jan-2024 |
Yitzhak Mandelbaum <ymand@users.noreply.github.com> |
[clang][dataflow] Make cap on block visits configurable by caller. (#77481)
Previously, we hard-coded the cap on block visits inside the framework. This patch enables the caller to specify the cap i
[clang][dataflow] Make cap on block visits configurable by caller. (#77481)
Previously, we hard-coded the cap on block visits inside the framework. This patch enables the caller to specify the cap in the APIs for running an analysis.
show more ...
|
#
71b3ead8 |
| 04-Jan-2024 |
Martin Storsjö <martin@martin.st> |
[clang][dataflow] Remove a redundant trailing semicolon. NFC.
This silences the following warning with GCC:
llvm-project/llvm/tools/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnal
[clang][dataflow] Remove a redundant trailing semicolon. NFC.
This silences the following warning with GCC:
llvm-project/llvm/tools/clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp:89:4: warning: extra ‘;’ [-Wpedantic] 89 | }; | ^ | -
show more ...
|
#
469374e5 |
| 21-Dec-2023 |
martinboehme <mboehme@google.com> |
[clang][dataflow] Disallow setting properties on `RecordValue`s. (#76042)
Instead, synthetic fields should now be used for the same purpose. These have a number of advantages, as described in https:
[clang][dataflow] Disallow setting properties on `RecordValue`s. (#76042)
Instead, synthetic fields should now be used for the same purpose. These have a number of advantages, as described in https://github.com/llvm/llvm-project/pull/73860, and longer-term, we want to eliminate `RecordValue` entirely.
As `RecordValue`s cannot have properties any more, I have replaced the `OptionalIntAnalysis` with an equivalent analysis that tracks nullness of pointers (instead of whether an optional has a value). This serves the same purpose, namely to check whether the framework applies a custom `merge()` operation to widen properties.
show more ...
|
#
0474a92c |
| 11-Dec-2023 |
martinboehme <mboehme@google.com> |
[clang][dataflow] Convert `SpecialBoolAnalysis` to synthetic fields. (#74706)
We're working towards eliminating `RecordValue`; this eliminates one more blocker on that path.
|
Revision tags: llvmorg-17.0.6 |
|
#
c4c59192 |
| 22-Nov-2023 |
martinboehme <mboehme@google.com> |
[clang][dataflow] Clear `ExprToLoc` and `ExprToVal` at the start of a block. (#72985)
We never need to access entries from these maps outside of the current
basic
block. This could only ever becom
[clang][dataflow] Clear `ExprToLoc` and `ExprToVal` at the start of a block. (#72985)
We never need to access entries from these maps outside of the current
basic
block. This could only ever become a consideration when flow control
happens
inside a full-expression (i.e. we have multiple basic blocks for a full
expression); there are two kinds of expression where this can happen,
but we
already deal with these in other ways:
* Short-circuiting logical operators (`&&` and `||`) have operands that
live in
different basic blocks than the operator itself, but we already have
code in
the framework to retrieve the value of these operands from the
environment
for the block they are computed in, rather than in the environment of
the
block containing the operator.
* The conditional operator similarly has operands that live in different
basic
blocks. However, we currently don't implement a transfer function for
the
conditional operator. When we do this, we need to retrieve the values of
the
operands from the environments of the basic blocks they live in, as we
already do for logical operators. This patch adds a comment to this
effect
to the code.
Clearing out `ExprToLoc` and `ExprToVal` has two benefits:
* We avoid performing joins on boolean expressions contained in
`ExprToVal` and
hence extending the flow condition in cases where this is not needed.
Simpler
flow conditions should reduce the amount of work we do in the SAT
solver.
* Debugging becomes easier when flow conditions are simpler and
`ExprToLoc` /
`ExprToVal` don’t contain any extraneous entries.
Benchmark results on Crubit's `pointer_nullability_analysis_benchmark
show a
slight runtime increase for simple benchmarks, offset by substantial
runtime
reductions for more complex benchmarks:
```
name old cpu/op new cpu/op delta
BM_PointerAnalysisCopyPointer 29.8µs ± 1% 29.9µs ± 4% ~ (p=0.879 n=46+49)
BM_PointerAnalysisIntLoop 101µs ± 3% 104µs ± 4% +2.96% (p=0.000 n=55+57)
BM_PointerAnalysisPointerLoop 378µs ± 3% 245µs ± 3% -35.09% (p=0.000 n=47+55)
BM_PointerAnalysisBranch 118µs ± 2% 122µs ± 3% +3.37% (p=0.000 n=59+59)
BM_PointerAnalysisLoopAndBranch 779µs ± 3% 413µs ± 5% -47.01% (p=0.000 n=56+45)
BM_PointerAnalysisTwoLoops 187µs ± 3% 192µs ± 5% +2.80% (p=0.000 n=57+58)
BM_PointerAnalysisJoinFilePath 17.4ms ± 3% 7.2ms ± 3% -58.75% (p=0.000 n=58+57)
BM_PointerAnalysisCallInLoop 14.7ms ± 4% 10.3ms ± 2% -29.87% (p=0.000 n=56+58)
```
show more ...
|
Revision tags: llvmorg-17.0.5, llvmorg-17.0.4 |
|
#
526c9b7e |
| 30-Oct-2023 |
martinboehme <mboehme@google.com> |
[clang][nullability] Use `proves()` and `assume()` instead of deprecated synonyms. (#70297)
|
Revision tags: llvmorg-17.0.3 |
|
#
342dca75 |
| 16-Oct-2023 |
Yitzhak Mandelbaum <ymand@users.noreply.github.com> |
[clang][dataflow] Check for backedges directly (instead of loop statements). (#68923)
Widen on backedge nodes, instead of nodes with a loop statement as terminator. This fixes #67834 and a precision
[clang][dataflow] Check for backedges directly (instead of loop statements). (#68923)
Widen on backedge nodes, instead of nodes with a loop statement as terminator. This fixes #67834 and a precision loss from assignment in a loop condition. The commit contains tests for both of these issues.
show more ...
|
#
3743c53d |
| 14-Oct-2023 |
Kazu Hirata <kazu@google.com> |
[clang] Remove unused using decls (NFC)
Identified with misc-unused-using-decls.
|
Revision tags: llvmorg-17.0.2 |
|
#
834cb919 |
| 26-Sep-2023 |
martinboehme <mboehme@google.com> |
[clang][dataflow] Remove declarations from `DeclToLoc` when their lifetime ends. (#67300)
After https://reviews.llvm.org/D153273, we're now able to use `CFGLifetimeEnds` together with the other CFG
[clang][dataflow] Remove declarations from `DeclToLoc` when their lifetime ends. (#67300)
After https://reviews.llvm.org/D153273, we're now able to use `CFGLifetimeEnds` together with the other CFG options we use.
show more ...
|
Revision tags: llvmorg-17.0.1, llvmorg-17.0.0 |
|
#
004a7cea |
| 13-Sep-2023 |
Yitzhak Mandelbaum <ymand@users.noreply.github.com> |
[clang][dataflow] Change `diagnoseFunction` to use `llvm::SmallVector` instead of `std::vector`. (#66014)
The template is agnostic as to the type used by the list, as long as it is compatible with `
[clang][dataflow] Change `diagnoseFunction` to use `llvm::SmallVector` instead of `std::vector`. (#66014)
The template is agnostic as to the type used by the list, as long as it is compatible with `llvm::move` and `std::back_inserter`. In practice, we've encountered analyses which use different types (`llvm::SmallVector` vs `std::vector`), so it seems preferable to leave this open to the caller.
show more ...
|
Revision tags: llvmorg-17.0.0-rc4 |
|
#
37458c66 |
| 31-Aug-2023 |
Martin Braenne <mboehme@google.com> |
[clang][dataflow] Eliminate deprecated `DataflowAnalysis` constructor.
Reviewed By: ymandel, xazax.hun
Differential Revision: https://reviews.llvm.org/D159261
|
#
6eb1b237 |
| 29-Aug-2023 |
Martin Braenne <mboehme@google.com> |
[clang][dataflow][NFC] Remove obsolete references to `ReferenceValue` from comments.
`ReferenceValue` was removed in https://reviews.llvm.org/D155922.
Reviewed By: xazax.hun
Differential Revision:
[clang][dataflow][NFC] Remove obsolete references to `ReferenceValue` from comments.
`ReferenceValue` was removed in https://reviews.llvm.org/D155922.
Reviewed By: xazax.hun
Differential Revision: https://reviews.llvm.org/D159090
show more ...
|
#
824b1365 |
| 25-Aug-2023 |
Yitzhak Mandelbaum <yitzhakm@google.com> |
[clang][dataflow] Support range-for loops in fixpoint algorithm.
Adds support for recognizing range-for loops in the main algorithm for computing the model fixpoint.
Differential Revision: https://
[clang][dataflow] Support range-for loops in fixpoint algorithm.
Adds support for recognizing range-for loops in the main algorithm for computing the model fixpoint.
Differential Revision: https://reviews.llvm.org/D158848
show more ...
|
Revision tags: llvmorg-17.0.0-rc3, llvmorg-17.0.0-rc2 |
|
#
9ecdbe38 |
| 01-Aug-2023 |
Martin Braenne <mboehme@google.com> |
[clang][dataflow] Rename `AggregateStorageLocation` to `RecordStorageLocation` and `StructValue` to `RecordValue`.
- Both of these constructs are used to represent structs, classes, and unions; Cl
[clang][dataflow] Rename `AggregateStorageLocation` to `RecordStorageLocation` and `StructValue` to `RecordValue`.
- Both of these constructs are used to represent structs, classes, and unions; Clang uses the collective term "record" for these.
- The term "aggregate" in `AggregateStorageLocation` implies that, at some point, the intention may have been to use it also for arrays, but it don't think it's possible to use it for arrays. Records and arrays are very different and therefore need to be modeled differently. Records have a fixed set of named fields, which can have different type; arrays have a variable number of elements, but they all have the same type.
- Futhermore, "aggregate" has a very specific meaning in C++ (https://en.cppreference.com/w/cpp/language/aggregate_initialization). Aggregates of class type may not have any user-declared or inherited constructors, no private or protected non-static data members, no virtual member functions, and so on, but we use `AggregateStorageLocations` to model all objects of class type.
In addition, for consistency, we also rename the following:
- `getAggregateLoc()` (in `RecordValue`, formerly known as `StructValue`) to simply `getLoc()`.
- `refreshStructValue()` to `refreshRecordValue()`
We keep the old names around as deprecated synonyms to enable clients to be migrated to the new names.
Reviewed By: ymandel, xazax.hun
Differential Revision: https://reviews.llvm.org/D156788
show more ...
|
#
b244b6ae |
| 31-Jul-2023 |
Martin Braenne <mboehme@google.com> |
[clang][dataflow] Remove `Strict` suffix from accessors.
For the time being, we're keeping the `Strict` versions around as deprecated synonyms so that clients can be migrated, but these synonyms wil
[clang][dataflow] Remove `Strict` suffix from accessors.
For the time being, we're keeping the `Strict` versions around as deprecated synonyms so that clients can be migrated, but these synonyms will be removed soon.
Depends On D156673
Reviewed By: ymandel, xazax.hun
Differential Revision: https://reviews.llvm.org/D156674
show more ...
|
Revision tags: llvmorg-17.0.0-rc1 |
|
#
e95134b9 |
| 26-Jul-2023 |
Martin Braenne <mboehme@google.com> |
[clang][dataflow] Reverse course on `getValue()` deprecation.
In the [value categories RFC](https://discourse.llvm.org/t/70086), I proposed that the end state of the migration should be that `getVal
[clang][dataflow] Reverse course on `getValue()` deprecation.
In the [value categories RFC](https://discourse.llvm.org/t/70086), I proposed that the end state of the migration should be that `getValue()` should only be legal to call on prvalues.
As a stepping stone, to allow migrating off existing calls to `getValue()`, I proposed introducing `getValueStrict()`, which would already have the new semantics.
However, I've now reconsidered this. Any expression, whether prvalue or glvalue, has a value, so really there isn't any reason to forbid calling `getValue()` on glvalues. I'm therefore removing the deprecation from `getValue()` and transitioning existing `getValueStrict()` calls back to `getValue()`.
The other "strict" accessors are a different case. `setValueStrict()` should only be called on prvalues because glvalues need to have a storage location associated with them; it doesn't make sense to only set a value for them. And, of course, `getStorageLocationStrict()` and `setStorageLocationStrict()` should obviously only be called on glvalues because prvalues don't have storage locations.
Reviewed By: ymandel, xazax.hun
Differential Revision: https://reviews.llvm.org/D155921
show more ...
|
#
1429240e |
| 25-Jul-2023 |
Yitzhak Mandelbaum <yitzhakm@google.com> |
[clang][dataflow] Add convenience function for analysing and `FunctionDecl` and diagnosing it.
The convenience function captures running the analysis and then collecting diagnostics based on a `Diag
[clang][dataflow] Add convenience function for analysing and `FunctionDecl` and diagnosing it.
The convenience function captures running the analysis and then collecting diagnostics based on a `Diagnoser` object. This pattern is valuable to clang-tidy checks which analyze a function at a time, though it could be more generally useful for analysis clients.
Differential Revision: https://reviews.llvm.org/D156254
show more ...
|
Revision tags: llvmorg-18-init |
|
#
d17f455a |
| 17-Jul-2023 |
Martin Braenne <mboehme@google.com> |
[clang][dataflow] Add `refreshStructValue()`.
Besides being a useful abstraction, this function will help insulate existing clients of the framework from upcoming changes to the API of `StructValue`
[clang][dataflow] Add `refreshStructValue()`.
Besides being a useful abstraction, this function will help insulate existing clients of the framework from upcoming changes to the API of `StructValue` and `AggregateStorageLocation`.
Depends On D155202
Reviewed By: ymandel, xazax.hun
Differential Revision: https://reviews.llvm.org/D155204
show more ...
|