forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 353
Cherry pick lifetime analysis work from upstream #11947
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Xazax-hun
wants to merge
35
commits into
swiftlang:stable/21.x
Choose a base branch
from
Xazax-hun:gaborh/lifetime-analysis-on-21.x
base: stable/21.x
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Cherry pick lifetime analysis work from upstream #11947
Xazax-hun
wants to merge
35
commits into
swiftlang:stable/21.x
from
Xazax-hun:gaborh/lifetime-analysis-on-21.x
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Refactored the lifetime safety analysis to use a generic dataflow framework with a policy-based design. - Introduced a generic `DataflowAnalysis` template class that can be specialized for different analyses - Renamed `LifetimeLattice` to `LoanPropagationLattice` to better reflect its purpose - Created a `LoanPropagationAnalysis` class that inherits from the generic framework - Moved transfer functions from the standalone `Transferer` class into the analysis class - Restructured the code to separate the dataflow engine from the specific analysis logic - Updated debug output and test expectations to use the new class names In order to add more analyses, e.g. [loan expiry](llvm#148712) and origin liveness, the previous implementation would have separate, nearly identical dataflow runners for each analysis. This change creates a single, reusable component, which will make it much simpler to add subsequent analyses without repeating boilerplate code. This is quite close to the existing dataflow framework!
Generalize the dataflow analysis to support both forward and backward analyses. Some program analyses would be expressed as backward dataflow problems (like liveness analysis). This change enables the framework to support both forward analyses (like the loan propagation analysis) and backward analyses with the same infrastructure.
Add per-program-point state tracking to the dataflow analysis framework. - Added a `ProgramPoint` type representing a pair of a CFGBlock and a Fact within that block - Added a `PerPointStates` map to store lattice states at each program point - Modified the `transferBlock` method to store intermediate states after each fact is processed - Added a `getLoans` method to the `LoanPropagationAnalysis` class that uses program points This change enables more precise analysis by tracking program state at each individual program point rather than just at block boundaries. This is necessary for answering queries about the state of loans, origins, and other properties at specific points in the program, which is required for error reporting in the lifetime safety analysis.
)" This reverts commit 54b5068.
This PR adds the `ExpiredLoansAnalysis` class to track which loans have expired. The analysis uses a dataflow lattice (`ExpiredLattice`) to maintain the set of expired loans at each program point. This is a very light weight dataflow analysis and is expected to reach fixed point in ~2 iterations. In principle, this does not need a dataflow analysis but is used for convenience in favour of lean code.
…150670) Fix a crash in the lifetime safety dataflow analysis when handling null CFG blocks. Added a null check for adjacent blocks in the dataflow analysis algorithm to prevent dereferencing null pointers. This occurs when processing CFG blocks with unreachable successors or predecessors. Original crash: https://compiler-explorer.com/z/qfzfqG5vM Fixes llvm#150095
…9731) Implement use-after-free detection in the lifetime safety analysis with two warning levels. - Added a `LifetimeSafetyReporter` interface for reporting lifetime safety issues - Created two warning levels: - Definite errors (reported with `-Wexperimental-lifetime-safety-permissive`) - Potential errors (reported with `-Wexperimental-lifetime-safety-strict`) - Implemented a `LifetimeChecker` class that analyzes loan propagation and expired loans to detect use-after-free issues. - Added tracking of use sites through a new `UseFact` class. - Enhanced the `ExpireFact` to track the expressions where objects are destroyed. - Added test cases for both definite and potential use-after-free scenarios. The implementation now tracks pointer uses and can determine when a pointer is dereferenced after its loan has been expired, with appropriate diagnostics. The two warning levels provide flexibility - definite errors for high-confidence issues and potential errors for cases that depend on control flow.
…149577) Enhanced the lifetime safety analysis benchmark script with more detailed performance metrics and a new nested loop test case. This is a worst case for loan expiry analysis. ### What changed? - Added a new test case `nested_loops` that generates code with N levels of nested loops to test how analysis performance scales with loop nesting depth - Improved the trace file analysis to extract durations for sub-phases of the lifetime analysis (FactGenerator, LoanPropagation, ExpiredLoans) - Enhanced the markdown report generation to include: - Relative timing results as percentages of total Clang time - More detailed complexity analysis for each analysis phase Report # Lifetime Analysis Performance Report > Generated on: 2025-08-18 13:29:57 --- ## Test Case: Pointer Cycle in Loop **Timing Results:** | N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Expired Loans (%) | |:---------------|-----------:|------------------:|-------------------:|---------------------:|------------------:| | 10 | 10.75 ms | 24.61% | 0.00% | 24.38% | 0.00% | | 25 | 64.98 ms | 86.08% | 0.00% | 86.02% | 0.00% | | 50 | 709.37 ms | 98.53% | 0.00% | 98.51% | 0.00% | | 75 | 3.13 s | 99.63% | 0.00% | 99.63% | 0.00% | | 100 | 9.44 s | 99.85% | 0.00% | 99.84% | 0.00% | | 150 | 45.31 s | 99.96% | 0.00% | 99.96% | 0.00% | **Complexity Analysis:** | Analysis Phase | Complexity O(n<sup>k</sup>) | |:------------------|:--------------------------| | Total Analysis | O(n<sup>3.87</sup> ± 0.01) | | FactGenerator | (Negligible) | | LoanPropagation | O(n<sup>3.87</sup> ± 0.01) | | ExpiredLoans | (Negligible) | --- ## Test Case: CFG Merges **Timing Results:** | N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Expired Loans (%) | |:---------------|-----------:|------------------:|-------------------:|---------------------:|------------------:| | 10 | 8.54 ms | 0.00% | 0.00% | 0.00% | 0.00% | | 50 | 40.85 ms | 65.09% | 0.00% | 64.61% | 0.00% | | 100 | 207.70 ms | 93.58% | 0.00% | 93.46% | 0.00% | | 200 | 1.54 s | 98.82% | 0.00% | 98.78% | 0.00% | | 400 | 12.04 s | 99.72% | 0.00% | 99.71% | 0.01% | | 800 | 96.73 s | 99.94% | 0.00% | 99.94% | 0.00% | **Complexity Analysis:** | Analysis Phase | Complexity O(n<sup>k</sup>) | |:------------------|:--------------------------| | Total Analysis | O(n<sup>3.01</sup> ± 0.00) | | FactGenerator | (Negligible) | | LoanPropagation | O(n<sup>3.01</sup> ± 0.00) | | ExpiredLoans | (Negligible) | --- ## Test Case: Deeply Nested Loops **Timing Results:** | N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Expired Loans (%) | |:---------------|-----------:|------------------:|-------------------:|---------------------:|------------------:| | 10 | 8.25 ms | 0.00% | 0.00% | 0.00% | 0.00% | | 50 | 27.25 ms | 51.87% | 0.00% | 45.71% | 5.93% | | 100 | 113.42 ms | 82.48% | 0.00% | 72.74% | 9.62% | | 200 | 730.05 ms | 95.24% | 0.00% | 83.95% | 11.25% | | 400 | 5.40 s | 98.74% | 0.01% | 87.05% | 11.68% | | 800 | 41.86 s | 99.62% | 0.00% | 87.77% | 11.84% | **Complexity Analysis:** | Analysis Phase | Complexity O(n<sup>k</sup>) | |:------------------|:--------------------------| | Total Analysis | O(n<sup>2.97</sup> ± 0.00) | | FactGenerator | (Negligible) | | LoanPropagation | O(n<sup>2.96</sup> ± 0.00) | | ExpiredLoans | O(n<sup>2.97</sup> ± 0.00) | ---
) The previous debug output only showed numeric IDs for origins, making it difficult to understand what each origin represented. This change makes the debug output more informative by showing what kind of entity each origin refers to (declaration or expression) and additional details like declaration names or expression class names. This improved output makes it easier to debug and understand the lifetime safety analysis.
…lvm#153661) This PR fixes a bug in the lifetime safety analysis where `ImplicitCastExpr` nodes were causing duplicate loan generation. The changes: 1. Remove the recursive `Visit(ICE->getSubExpr())` call in `VisitImplicitCastExpr` to prevent duplicate processing of the same expression 2. Ensure the CFG build options are properly configured for lifetime safety analysis by moving the flag check earlier 3. Enhance the unit test infrastructure to properly handle multiple loans per variable 4. Add a test case that verifies implicit casts to const don't create duplicate loans 5. Add a test case for ternary operators with a FIXME note about origin propagation These changes prevent the analysis from generating duplicate loans when expressions are wrapped in implicit casts, which improves the accuracy of the lifetime safety analysis.
llvm#154316) Instead of identifying various forms of pointer usage (like dereferencing, member access, or function calls) individually, this new approach simplifies the logic by treating all `DeclRefExpr`s as uses of their underlying origin When a `DeclRefExpr` appears on the left-hand side of an assignment, the corresponding `UseFact` is marked as a "write" operation. These write operations are then exempted from use-after-free checks.
This will add label `clang:temporal-safety` to PRs touching the mentioned files.
…156896) This patch refactors the C++ lifetime safety analysis to implement a more consistent model for tracking borrows. The central idea is to make loan creation a consequence of referencing a variable, while making loan propagation dependent on the type's semantics. This change introduces a more uniform model for tracking borrows from non-pointer types: * Centralised Loan Creation: A Loan is now created for every `DeclRefExpr` that refers to a **non-pointer type** (e.g., `std::string`, `int`). This correctly models that any use of an **gl-value** is a borrow of its storage, replacing the previous heuristic-based loan creation. * The address-of operator (&) no longer creates loans. Instead, it propagates the origin (and thus the loans) of its sub-expression. This is guarded to exclude expressions that are already pointer types, deferring the complexity of pointers-to-pointers. **Future Work: Multi-Origin Model** This patch deliberately defers support for creating loans on references to pointer-type expressions (e.g., `&my_pointer`). The current single-origin model is unable to distinguish between a loan to the pointer variable itself (its storage) and a loan to the object it points to. The future plan is to move to a multi-origin model where a type has a "list of origins" governed by its level of indirection, which will allow the analysis to track these distinct lifetimes separately. Once this more advanced model is in place, the restriction can be lifted, and all `DeclRefExpr` nodes, regardless of type, can uniformly create a loan, making the analysis consistent.
This extends the lifetime safety analysis to support C++ types annotated with `gsl::Pointer`, which represent non-owning "view" types like `std::string_view`. These types have the same lifetime safety concerns as raw pointers and references. - Added support for detecting and analyzing `gsl::Pointer` annotated types in lifetime safety analysis - Implemented handling for various expressions involving `gsl::Pointer` types: - Constructor expressions - Member call expressions (especially conversion operators) - Functional cast expressions - Initialization list expressions - Materialized temporary expressions - Updated the pointer type detection to recognize `gsl::Pointer` types - Added handling for function calls that create borrows through reference parameters Fixes: llvm#152513
…m#159582) Optimize lifetime safety analysis performance - Added early return optimization in `join` function for ImmutableSet when sets are identical - Improved ImmutableMap join logic to avoid unnecessary operations when values are equal I was under the impression that ImmutableSets/Maps would not modify the underlying if already existing elements are added to the container (and was hoping for structural equality in this aspect). It looks like the current implementation of `ImmutableSet` would perform addition nevertheless thereby creating (presumably `O(log(N))` tree nodes. This change considerably brings down compile times for some edge cases which happened to be present in the LLVM codebase. Now it is actually possible to compile LLVM in under 20 min with the lifetime analysis. The compile time hit is still significant but not as bad as before this change where it was not possible to compile LLVM without severely limiting analysis' scope (giving up on CFG with > 3000 blocks). Fixes llvm#157420 <details> <summary>Report (Before)</summary> </details> <details> <summary>Report (After)</summary> # Lifetime Analysis Performance Report > Generated on: 2025-09-18 14:28:00 --- ## Test Case: Pointer Cycle in Loop **Timing Results:** | N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Expired Loans (%) | |:---------------|-----------:|------------------:|-------------------:|---------------------:|------------------:| | 25 | 53.76 ms | 85.58% | 0.00% | 85.46% | 0.00% | | 50 | 605.35 ms | 98.39% | 0.00% | 98.37% | 0.00% | | 75 | 2.89 s | 99.62% | 0.00% | 99.61% | 0.00% | | 100 | 8.62 s | 99.80% | 0.00% | 99.80% | 0.00% | **Complexity Analysis:** | Analysis Phase | Complexity O(n<sup>k</sup>) | |:------------------|:--------------------------| | Total Analysis | O(n<sup>3.82</sup> ± 0.01) | | FactGenerator | (Negligible) | | LoanPropagation | O(n<sup>3.82</sup> ± 0.01) | | ExpiredLoans | (Negligible) | --- ## Test Case: CFG Merges **Timing Results:** | N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Expired Loans (%) | |:---------------|-----------:|------------------:|-------------------:|---------------------:|------------------:| | 400 | 66.02 ms | 58.61% | 1.04% | 56.53% | 1.02% | | 1000 | 319.24 ms | 81.31% | 0.63% | 80.04% | 0.64% | | 2000 | 1.43 s | 92.00% | 0.40% | 91.32% | 0.28% | | 5000 | 9.35 s | 97.01% | 0.25% | 96.63% | 0.12% | **Complexity Analysis:** | Analysis Phase | Complexity O(n<sup>k</sup>) | |:------------------|:--------------------------| | Total Analysis | O(n<sup>2.12</sup> ± 0.02) | | FactGenerator | O(n<sup>1.54</sup> ± 0.02) | | LoanPropagation | O(n<sup>2.12</sup> ± 0.03) | | ExpiredLoans | O(n<sup>1.13</sup> ± 0.03) | --- ## Test Case: Deeply Nested Loops **Timing Results:** | N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Expired Loans (%) | |:---------------|-----------:|------------------:|-------------------:|---------------------:|------------------:| | 50 | 137.30 ms | 90.72% | 0.00% | 90.42% | 0.00% | | 100 | 1.09 s | 98.13% | 0.00% | 98.02% | 0.09% | | 150 | 4.06 s | 99.24% | 0.00% | 99.18% | 0.05% | | 200 | 10.44 s | 99.66% | 0.00% | 99.63% | 0.03% | **Complexity Analysis:** | Analysis Phase | Complexity O(n<sup>k</sup>) | |:------------------|:--------------------------| | Total Analysis | O(n<sup>3.29</sup> ± 0.01) | | FactGenerator | (Negligible) | | LoanPropagation | O(n<sup>3.29</sup> ± 0.01) | | ExpiredLoans | O(n<sup>1.42</sup> ± 0.19) | --- </details>
…lvm#159850) Disable canonicalization in immutable collections for lifetime analysis. Modified the `LifetimeFactory` struct in `LifetimeSafety.cpp` to explicitly initialize the immutable collection factories with `canonicalize=false`. This prevents the factories from canonicalizing their data structures, which can improve performance by avoiding unnecessary comparisons and digest computations.
…158489) Add support for `lifetimebound` attributes in the lifetime safety analysis to track loans from function parameters to return values. Implemented support for `lifetimebound` attributes on function parameters This change replaces the single `AssignOriginFact` with two separate operations: `OriginFlowFact` and `KillOriginFact`. The key difference is in semantics: * Old `AssignOriginFact`: Replaced the destination origin's loans entirely with the source origin's loans. * New `OriginFlowFact`: Can now optionally merge the source origin's loans to the destination's existing loans. * New `KillOriginFact`: Clears all loans from an origin. For function calls with `lifetimebound` parameters, we kill the the return value' origin first then use `OriginFlowFact` to accumulate loans from multiple parameters into the return value's origin - enabling tracking multiple lifetimebound arguments. - Added a new `LifetimeAnnotations.h/cpp` to provide helper functions for inspecting and inferring lifetime annotations - Moved several functions from `CheckExprLifetime.cpp` to the new file to make them reusable The `lifetimebound` attribute is a key mechanism for expressing lifetime dependencies between function parameters and return values. This change enables the lifetime safety analysis to properly track these dependencies, allowing it to detect more potential dangling reference issues.
) This PR replaces the forward `ExpiredLoansAnalysis` with a backward `LiveOriginAnalysis` that tracks which origins are live at each program point, along with confidence levels (Definite or Maybe). The new approach: - Tracks liveness of origins rather than expiration of loans - Uses a backward dataflow analysis to determine which origins are live at each point. - Provides more precise confidence levels for use-after-free warnings and avoids previous false-positives The `LifetimeChecker` now checks for use-after-free by examining if an origin is live when a loan expires, rather than checking if a loan is expired when an origin is used. More details describing the design flaw in using `ExpiredLoans` is mentioned in llvm#156959 (comment) Fixes: llvm#156959 (With this, we can build LLVM with no false-positives 🎉 ) <details> <summary> Benchmark report </summary> > Generated on: 2025-09-24 13:08:03 --- **Timing Results:** | N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Live Origins (%) | |:---------------|-----------:|------------------:|-------------------:|---------------------:|------------------:| | 50 | 54.12 ms | 80.80% | 0.00% | 80.42% | 0.00% | | 75 | 150.22 ms | 91.54% | 0.00% | 91.19% | 0.00% | | 100 | 317.12 ms | 94.90% | 0.00% | 94.77% | 0.00% | | 200 | 2.40 s | 98.58% | 0.00% | 98.54% | 0.03% | | 300 | 9.85 s | 99.25% | 0.00% | 99.24% | 0.01% | **Complexity Analysis:** | Analysis Phase | Complexity O(n<sup>k</sup>) | |:------------------|:--------------------------| | Total Analysis | O(n<sup>3.47</sup> ± 0.06) | | FactGenerator | (Negligible) | | LoanPropagation | O(n<sup>3.47</sup> ± 0.06) | | LiveOrigins | (Negligible) | --- **Timing Results:** | N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Live Origins (%) | |:---------------|-----------:|------------------:|-------------------:|---------------------:|------------------:| | 400 | 105.22 ms | 72.61% | 0.68% | 71.38% | 0.52% | | 1000 | 610.74 ms | 88.88% | 0.33% | 88.32% | 0.23% | | 2000 | 2.50 s | 95.32% | 0.21% | 94.99% | 0.11% | | 5000 | 17.20 s | 98.20% | 0.14% | 98.01% | 0.05% | **Complexity Analysis:** | Analysis Phase | Complexity O(n<sup>k</sup>) | |:------------------|:--------------------------| | Total Analysis | O(n<sup>2.14</sup> ± 0.00) | | FactGenerator | O(n<sup>1.59</sup> ± 0.05) | | LoanPropagation | O(n<sup>2.14</sup> ± 0.00) | | LiveOrigins | O(n<sup>1.19</sup> ± 0.04) | --- **Timing Results:** | N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Live Origins (%) | |:---------------|-----------:|------------------:|-------------------:|---------------------:|------------------:| | 50 | 141.95 ms | 91.14% | 0.00% | 90.99% | 0.00% | | 100 | 1.09 s | 98.17% | 0.00% | 98.13% | 0.00% | | 150 | 3.87 s | 99.28% | 0.00% | 99.27% | 0.00% | | 200 | 9.81 s | 99.61% | 0.00% | 99.60% | 0.00% | **Complexity Analysis:** | Analysis Phase | Complexity O(n<sup>k</sup>) | |:------------------|:--------------------------| | Total Analysis | O(n<sup>3.23</sup> ± 0.02) | | FactGenerator | (Negligible) | | LoanPropagation | O(n<sup>3.23</sup> ± 0.02) | | LiveOrigins | (Negligible) | --- **Timing Results:** | N (Input Size) | Total Time | Analysis Time (%) | Fact Generator (%) | Loan Propagation (%) | Live Origins (%) | |:---------------|-----------:|------------------:|-------------------:|---------------------:|------------------:| | 500 | 155.10 ms | 72.03% | 0.47% | 67.49% | 4.06% | | 1000 | 568.40 ms | 85.60% | 0.24% | 80.53% | 4.83% | | 2000 | 2.25 s | 93.00% | 0.13% | 86.99% | 5.88% | | 4000 | 9.06 s | 96.62% | 0.10% | 89.68% | 6.84% | **Complexity Analysis:** | Analysis Phase | Complexity O(n<sup>k</sup>) | |:------------------|:--------------------------| | Total Analysis | O(n<sup>2.07</sup> ± 0.01) | | FactGenerator | O(n<sup>1.52</sup> ± 0.13) | | LoanPropagation | O(n<sup>2.06</sup> ± 0.01) | | LiveOrigins | O(n<sup>2.23</sup> ± 0.00) | --- <details>
Restructure the C++ Lifetime Safety Analysis into modular components
with clear separation of concerns.
This PR reorganizes the C++ Lifetime Safety Analysis code by:
1. Breaking up the monolithic `LifetimeSafety.cpp` (1500+ lines) into
multiple smaller, focused files
2. Creating a dedicated `LifetimeSafety` directory with a clean
component structure
3. Introducing header files for each component with proper documentation
4. Moving existing code into the appropriate component files:
- `Checker.h/cpp`: Core lifetime checking logic
- `Dataflow.h`: Generic dataflow analysis framework
- `Facts.h`: Lifetime-relevant events and fact management
- `FactsGenerator.h/cpp`: AST traversal for fact generation
- `LiveOrigins.h/cpp`: Backward dataflow analysis for origin liveness
- `LoanPropagation.h/cpp`: Forward dataflow analysis for loan tracking
- `Loans.h`: Loan and access path definitions
- `Origins.h`: Origin management
- `Reporter.h`: Interface for reporting lifetime violations
- `Utils.h`: Common utilities for the analysis
The code functionality remains the same, but is now better organized
with clearer interfaces between components.
…vm#162474)" This reverts commit 24a5d8a. Add link libs to the new clang library
Fix Python virtual environment paths for Windows in the Lifetime Safety Analysis benchmark ### What changed? - Added conditional path setting for the Python executable in the virtual environment based on the platform - For Windows, use `Scripts/python` path - For other platforms, use `bin/python` path - Updated the commands that use the Python virtual environment to use the platform-specific path ### How to test? `ninja benchmark_lifetime_safety_analysis` Fixes llvm#166143
…nd block-local origins (llvm#165789) ## Summary Optimizes the lifetime analysis loan propagation by preventing block-local origins from participating in expensive join operations at block boundaries. ## Problem The lifetime analysis currently performs join operations on all origins at every block boundary. However, many origins are block-local: they exist only to propagate loans between persistent origins across temporary declarations and expressions within a single block. Including them in joins is unnecessary and expensive. ## Solution This PR classifies origins into two categories: - **Persistent origins**: referenced in multiple basic blocks, must participate in joins - **Block-local origins**: confined to a single block, can be discarded at block boundaries ### Implementation 1. **Pre-pass** (`computePersistentOrigins`): Analyzes all facts in the CFG to identify which origins appear in multiple blocks 2. **Split lattice**: Maintains two separate `OriginLoanMap`s: - `PersistentOrigins`: participates in join operations - `BlockLocalOrigins`: used during block execution, discarded at boundaries 3. **Optimized join**: Only merges persistent origins; block-local map is reset to empty ### Benefits - Significantly reduces join complexity, especially in functions with many temporary locals - Performance scales with the ratio of temporary to persistent origins - Correctness preserved: block-local loan propagation still works within blocks Fixes: llvm#165780 Fixes: llvm#164625. It brings down regression from **150% to 2%**. ---
Fixes test failure introduced by a typo in llvm#165789
…up (llvm#165963) Optimize the FactManager and DataflowAnalysis classes by using vector-based storage with ID-based lookups instead of maps. - Added a `FactID` type using the `utils::ID` template to uniquely identify facts - Modified `Fact` class to store and manage IDs - Changed `FactManager` to use vector-based storage indexed by block ID instead of a map - Updated `DataflowAnalysis` to use vector-based storage for states instead of maps - Modified lookups to use ID-based indexing for better performance Improves compile time hit on long-tail targets like `tools/clang/lib/CodeGen/CMakeFiles/obj.clangCodeGen.dir/TargetBuiltins/RISCV.cpp.o` from [21%](http://llvm-compile-time-tracker.com/compare_clang.php?from=6e25a04027ca786b7919657c7df330a33985ceea&to=20b42efa277c8b1915db757863e1fc26531cfd53&stat=instructions%3Au&sortBy=absolute-difference) to [3.2%](http://llvm-compile-time-tracker.com/compare_clang.php?from=6e25a04027ca786b7919657c7df330a33985ceea&to=d2d1cd1109c3a85344457bfff6f092ae7b96b211&stat=instructions%3Au&sortBy=absolute-difference)
Identified with readability-container-contains.
Added support for conditional operators in the lifetime safety analysis. Added a `VisitConditionalOperator` method to the `FactsGenerator` class to handle the ternary operator (`?:`) in lifetime safety analysis. Fixes llvm#157108
…67245) Add support for handling parenthesized expressions in lifetime safety analysis. Modified the `OriginManager::get` method to ignore parentheses when retrieving origins by recursively calling itself on the unparenthesized expression. This ensures that expressions with extra parentheses are properly analyzed for lifetime safety issues.
Adding "use-after-return" in Lifetime Analysis. Detecting when a function returns a reference to its own stack memory: [UAR Design Doc](https://docs.google.com/document/d/1Wxjn_rJD_tuRdejP81dlb9VOckTkCq5-aE1nGcerb_o/edit?usp=sharing) Consider the following example: ```cpp std::string_view foo() { std::string_view a; std::string str = "small scoped string"; a = str; return a; } ``` The code adds a new Fact "OriginEscape" in the end of the CFG to determine any loan that is escaping the function as shown below: ``` Function: foo Block B2: End of Block Block B1: OriginFlow (Dest: 0 (Decl: a), Src: 1 (Expr: CXXConstructExpr)) OriginFlow (Dest: 2 (Expr: ImplicitCastExpr), Src: 3 (Expr: StringLiteral)) Issue (0 (Path: operator=), ToOrigin: 4 (Expr: DeclRefExpr)) OriginFlow (Dest: 5 (Expr: ImplicitCastExpr), Src: 4 (Expr: DeclRefExpr)) Use (0 (Decl: a), Write) Issue (1 (Path: str), ToOrigin: 6 (Expr: DeclRefExpr)) OriginFlow (Dest: 7 (Expr: ImplicitCastExpr), Src: 6 (Expr: DeclRefExpr)) OriginFlow (Dest: 8 (Expr: CXXMemberCallExpr), Src: 7 (Expr: ImplicitCastExpr)) OriginFlow (Dest: 9 (Expr: ImplicitCastExpr), Src: 8 (Expr: CXXMemberCallExpr)) OriginFlow (Dest: 10 (Expr: ImplicitCastExpr), Src: 9 (Expr: ImplicitCastExpr)) OriginFlow (Dest: 11 (Expr: MaterializeTemporaryExpr), Src: 10 (Expr: ImplicitCastExpr)) OriginFlow (Dest: 0 (Decl: a), Src: 11 (Expr: MaterializeTemporaryExpr)) Use (0 (Decl: a), Read) OriginFlow (Dest: 12 (Expr: ImplicitCastExpr), Src: 0 (Decl: a)) OriginFlow (Dest: 13 (Expr: CXXConstructExpr), Src: 12 (Expr: ImplicitCastExpr)) Expire (1 (Path: str)) OriginEscapes (13 (Expr: CXXConstructExpr)) End of Block Block B0: End of Block ``` The confidence of the report is determined by checking if at least one of the loans returned is not expired (strict). If all loans are expired it is considered permissive. More information [UAR Design Doc](https://docs.google.com/document/d/1Wxjn_rJD_tuRdejP81dlb9VOckTkCq5-aE1nGcerb_o/edit?usp=sharing)
…llvm#168855) Handling Trivially Destructed Types This PR uses `AddLifetime` to handle expiry of loans to trivially destructed types. Example: ```cpp int * trivial_uar(){ int *ptr; int x = 1; ptr = &x; return ptr; } ``` The CFG created now has an Expire Fact for trivially destructed types: ``` Function: trivial_uar Block B2: End of Block Block B1: Issue (0 (Path: x), ToOrigin: 0 (Expr: DeclRefExpr)) OriginFlow (Dest: 1 (Expr: UnaryOperator), Src: 0 (Expr: DeclRefExpr)) Use (2 (Decl: ptr), Write) OriginFlow (Dest: 2 (Decl: ptr), Src: 1 (Expr: UnaryOperator)) Use (2 (Decl: ptr), Read) OriginFlow (Dest: 3 (Expr: ImplicitCastExpr), Src: 2 (Decl: ptr)) Expire (0 (Path: x)) OriginEscapes (3 (Expr: ImplicitCastExpr)) End of Block Block B0: End of Block ``` This Expire Fact issues UAR and UAF warnings. Fixes llvm#162862
This PR enhances the CFG builder to properly handle function parameters in lifetime analysis: 1. Added code to include parameters in the initial scope during CFG construction for both `FunctionDecl` and `BlockDecl` types 2. Added a special case to skip reference parameters, as they don't need automatic destruction 3. Fixed several test cases that were previously marked as "FIXME" due to missing parameter lifetime tracking Previously, Clang's lifetime analysis was not properly tracking the lifetime of function parameters, causing it to miss important use-after-return bugs when parameter values were returned by reference or address. This change ensures that parameters are properly tracked in the CFG, allowing the analyzer to correctly identify when stack memory associated with parameters is returned. Fixes llvm#169014
…otations (llvm#169620) Refactored GSL pointer and owner type detection functions to improve code organization and reusability.
Add lifetime annotation suggestion in lifetime analysis.
This PR introduces a new feature to Clang's lifetime analysis to detect
and suggest missing `[[clang::lifetimebound]]` annotations on function
parameters.
It introduces the concept of `placeholder loans`. At the entry of a
function, a special placeholder loan is created for each pointer or
reference parameter. The analysis then tracks these loans using
`OriginFlow` facts. If an `OriginEscapesFact` shows that an origin
holding a placeholder loan escapes the function's scope (e.g., via a
return statement), a new warning is issued.
This warning, controlled by the warning flag
`-Wexperimental-lifetime-safety-suggestions`, suggests adding the
`[[clang::lifetimebound]]` attribute to the corresponding parameter.
Example:
```cpp
std::string_view foo(std::string_view a) {
return a;
}
```
Facts:
```
Function: foo
Block B2:
Issue (0 (Placeholder loan) , ToOrigin: 0 (Decl: a))
End of Block
Block B1:
Use (0 (Decl: a), Read)
OriginFlow (Dest: 1 (Expr: ImplicitCastExpr), Src: 0 (Decl: a))
OriginFlow (Dest: 2 (Expr: CXXConstructExpr), Src: 1 (Expr: ImplicitCastExpr))
OriginEscapes (2 (Expr: CXXConstructExpr))
End of Block
Block B0:
End of Block
```
Sample warning:
```
o.cpp:61:39: warning: param should be marked [[clang::lifetimebound]] [-Wexperimental-lifetime-safety-suggestions]
61 | std::string_view foo(std::string_view a) {
| ~~~~~~~~~~~~~~~~~^
| [[clang::lifetimebound]]
o.cpp:62:9: note: param escapes here
62 | return a;
```
Fixes: llvm#169939
Author
|
@swift-ci please test |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.