[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-16 Thread LLVM Continuous Integration via cfe-commits

llvm-ci wrote:

LLVM Buildbot has detected a new failure on builder `clang-with-lto-ubuntu` 
running on `as-worker-91` while building `clang` at step 7 
"test-stage1-compiler".

Full details are available at: 
https://lab.llvm.org/buildbot/#/builders/49/builds/1866


Here is the relevant piece of the build log for the reference

```
Step 7 (test-stage1-compiler) failure: build (failure)
...
llvm-lit: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using ld64.lld: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/bin/ld64.lld
llvm-lit: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using wasm-ld: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/bin/wasm-ld
llvm-lit: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/utils/lit/tests/lit.cfg:111:
 warning: Setting a timeout per test not supported. Requires the Python psutil 
module but it could not be found. Try installing it via pip or via your 
operating system's package manager.
 Some tests will be skipped and the --timeout command line argument will not 
work.
llvm-lit: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using ld.lld: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/bin/ld.lld
llvm-lit: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using lld-link: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/bin/lld-link
llvm-lit: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using ld64.lld: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/bin/ld64.lld
llvm-lit: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using wasm-ld: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/bin/wasm-ld
-- Testing: 85605 tests, 72 workers --
Testing:  0.. 10.. 
FAIL: Clang :: Sema/warn-lifetime-safety-dataflow.cpp (18361 of 85605)
 TEST 'Clang :: Sema/warn-lifetime-safety-dataflow.cpp' 
FAILED 
Exit Code: 1

Command Output (stderr):
--
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/bin/clang -cc1 
-internal-isystem 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/lib/clang/21/include
 -nostdsysteminc -mllvm -debug-only=LifetimeFacts 
-Wexperimental-lifetime-safety 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
 2>&1 | 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/bin/FileCheck 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
 # RUN: at line 1
+ /home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/bin/clang -cc1 
-internal-isystem 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/lib/clang/21/include
 -nostdsysteminc -mllvm -debug-only=LifetimeFacts 
-Wexperimental-lifetime-safety 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
+ /home/buildbot/as-worker-91/clang-with-lto-ubuntu/build/stage1/bin/FileCheck 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp:9:17:
 error: CHECK-LABEL: expected string not found in input
// CHECK-LABEL: Function: return_local_addr
^
:1:1: note: scanning from here
clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help'
^
:1:105: note: possible intended match here
clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help'

^

Input file: 
Check file: 
/home/buildbot/as-worker-91/clang-with-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp

-dump-input=help explains the following input dump.

Input was:
<<
   1: clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help' 
label:9'0 
X~
 error: no match found
label:9'1   
  ?  possible 
intended match
   2: clang (LLVM option parsing): Did you mean 
'--debug-pass=LifetimeFacts'? 
label:9'0 
~

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-12 Thread LLVM Continuous Integration via cfe-commits

llvm-ci wrote:

LLVM Buildbot has detected a new failure on builder 
`clang-with-thin-lto-ubuntu` running on `as-worker-92` while building `clang` 
at step 7 "test-stage1-compiler".

Full details are available at: 
https://lab.llvm.org/buildbot/#/builders/127/builds/4036


Here is the relevant piece of the build log for the reference

```
Step 7 (test-stage1-compiler) failure: build (failure)
...
llvm-lit: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using ld64.lld: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/bin/ld64.lld
llvm-lit: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using wasm-ld: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/bin/wasm-ld
llvm-lit: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/utils/lit/tests/lit.cfg:111:
 warning: Setting a timeout per test not supported. Requires the Python psutil 
module but it could not be found. Try installing it via pip or via your 
operating system's package manager.
 Some tests will be skipped and the --timeout command line argument will not 
work.
llvm-lit: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using ld.lld: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/bin/ld.lld
llvm-lit: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using lld-link: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/bin/lld-link
llvm-lit: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using ld64.lld: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/bin/ld64.lld
llvm-lit: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/llvm/utils/lit/lit/llvm/config.py:520:
 note: using wasm-ld: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/bin/wasm-ld
-- Testing: 85605 tests, 72 workers --
Testing:  0.. 10.. 
FAIL: Clang :: Sema/warn-lifetime-safety-dataflow.cpp (18359 of 85605)
 TEST 'Clang :: Sema/warn-lifetime-safety-dataflow.cpp' 
FAILED 
Exit Code: 1

Command Output (stderr):
--
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/bin/clang 
-cc1 -internal-isystem 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/lib/clang/21/include
 -nostdsysteminc -mllvm -debug-only=LifetimeFacts 
-Wexperimental-lifetime-safety 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
 2>&1 | 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/bin/FileCheck
 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
 # RUN: at line 1
+ 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/bin/FileCheck
 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
+ /home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/bin/clang 
-cc1 -internal-isystem 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/build/stage1/lib/clang/21/include
 -nostdsysteminc -mllvm -debug-only=LifetimeFacts 
-Wexperimental-lifetime-safety 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp:9:17:
 error: CHECK-LABEL: expected string not found in input
// CHECK-LABEL: Function: return_local_addr
^
:1:1: note: scanning from here
clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help'
^
:1:105: note: possible intended match here
clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help'

^

Input file: 
Check file: 
/home/buildbot/as-worker-92/clang-with-thin-lto-ubuntu/llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp

-dump-input=help explains the following input dump.

Input was:
<<
   1: clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help' 
label:9'0 
X~
 error: no match found
label:9'1   
  ?  possible 
intended matc

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-11 Thread LLVM Continuous Integration via cfe-commits

llvm-ci wrote:

LLVM Buildbot has detected a new failure on builder `clang-x64-windows-msvc` 
running on `windows-gcebot2` while building `clang` at step 4 "annotate".

Full details are available at: 
https://lab.llvm.org/buildbot/#/builders/63/builds/7795


Here is the relevant piece of the build log for the reference

```
Step 4 (annotate) failure: 'python 
../llvm-zorg/zorg/buildbot/builders/annotated/clang-windows.py ...' (failure)
...
[422/424] Running the Clang regression tests
llvm-lit.py: 
C:\b\slave\clang-x64-windows-msvc\llvm-project\llvm\utils\lit\lit\llvm\config.py:57:
 note: using lit tools: C:\Program Files\Git\usr\bin
llvm-lit.py: 
C:\b\slave\clang-x64-windows-msvc\llvm-project\llvm\utils\lit\lit\llvm\config.py:520:
 note: using clang: c:\b\slave\clang-x64-windows-msvc\build\stage1\bin\clang.exe
llvm-lit.py: 
C:\b\slave\clang-x64-windows-msvc\llvm-project\llvm\utils\lit\lit\llvm\subst.py:126:
 note: Did not find cir-opt in 
C:\b\slave\clang-x64-windows-msvc\build\stage1\bin;C:\b\slave\clang-x64-windows-msvc\build\stage1\bin
llvm-lit.py: 
C:\b\slave\clang-x64-windows-msvc\llvm-project\llvm\utils\lit\lit\llvm\config.py:520:
 note: using ld.lld: 
c:\b\slave\clang-x64-windows-msvc\build\stage1\bin\ld.lld.exe
llvm-lit.py: 
C:\b\slave\clang-x64-windows-msvc\llvm-project\llvm\utils\lit\lit\llvm\config.py:520:
 note: using lld-link: 
c:\b\slave\clang-x64-windows-msvc\build\stage1\bin\lld-link.exe
llvm-lit.py: 
C:\b\slave\clang-x64-windows-msvc\llvm-project\llvm\utils\lit\lit\llvm\config.py:520:
 note: using ld64.lld: 
c:\b\slave\clang-x64-windows-msvc\build\stage1\bin\ld64.lld.exe
llvm-lit.py: 
C:\b\slave\clang-x64-windows-msvc\llvm-project\llvm\utils\lit\lit\llvm\config.py:520:
 note: using wasm-ld: 
c:\b\slave\clang-x64-windows-msvc\build\stage1\bin\wasm-ld.exe
-- Testing: 22410 tests, 32 workers --
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90..
FAIL: Clang :: Sema/warn-lifetime-safety-dataflow.cpp (22410 of 22410)
 TEST 'Clang :: Sema/warn-lifetime-safety-dataflow.cpp' 
FAILED 
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
c:\b\slave\clang-x64-windows-msvc\build\stage1\bin\clang.exe -cc1 
-internal-isystem 
C:\b\slave\clang-x64-windows-msvc\build\stage1\lib\clang\21\include 
-nostdsysteminc -mllvm -debug-only=LifetimeFacts -Wexperimental-lifetime-safety 
C:\b\slave\clang-x64-windows-msvc\llvm-project\clang\test\Sema\warn-lifetime-safety-dataflow.cpp
 2>&1 | c:\b\slave\clang-x64-windows-msvc\build\stage1\bin\filecheck.exe 
C:\b\slave\clang-x64-windows-msvc\llvm-project\clang\test\Sema\warn-lifetime-safety-dataflow.cpp
# executed command: 
'c:\b\slave\clang-x64-windows-msvc\build\stage1\bin\clang.exe' -cc1 
-internal-isystem 
'C:\b\slave\clang-x64-windows-msvc\build\stage1\lib\clang\21\include' 
-nostdsysteminc -mllvm -debug-only=LifetimeFacts -Wexperimental-lifetime-safety 
'C:\b\slave\clang-x64-windows-msvc\llvm-project\clang\test\Sema\warn-lifetime-safety-dataflow.cpp'
# note: command had no output on stdout or stderr
# error: command failed with exit status: 1
# executed command: 
'c:\b\slave\clang-x64-windows-msvc\build\stage1\bin\filecheck.exe' 
'C:\b\slave\clang-x64-windows-msvc\llvm-project\clang\test\Sema\warn-lifetime-safety-dataflow.cpp'
# .---command stderr
# | 
C:\b\slave\clang-x64-windows-msvc\llvm-project\clang\test\Sema\warn-lifetime-safety-dataflow.cpp:9:17:
 error: CHECK-LABEL: expected string not found in input
# | // CHECK-LABEL: Function: return_local_addr
# | ^
# | :1:1: note: scanning from here
# | clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help'
# | ^
# | :1:105: note: possible intended match here
# | clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help'
# | 
^
# | 
# | Input file: 
# | Check file: 
C:\b\slave\clang-x64-windows-msvc\llvm-project\clang\test\Sema\warn-lifetime-safety-dataflow.cpp
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<
# |1: clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help' 
# | label:9'0 
X~
 error: no match found
# | label:9'1   
  ?  possible 
intended match
# |2: clang (LLVM option parsing): Did you mean 
'--debug-pass=LifetimeFacts'? 
# | label:9'0 

# | >>
# `-
# error: command failed with

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-11 Thread Utkarsh Saxena via cfe-commits

usx95 wrote:

Sorry for the trouble. Thanks @Prabhuk and @dyung for spotting and fixing this!

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread via cfe-commits

dyung wrote:

57194ac5053628955277e87dc51c74ad982bd543 should fix the test failure in builds 
without assertions.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread via cfe-commits

dyung wrote:

> I am part of a toolchain team at Google and we are seeing clang test failures 
> in our toolchain builders from this PR.
> 
> ```
> Exit Code: 1
> 
> Command Output (stderr):
> --
> /b/s/w/ir/x/w/llvm_build/bin/clang -cc1 -internal-isystem 
> /b/s/w/ir/x/w/llvm_build/lib/clang/21/include -nostdsysteminc -mllvm 
> -debug-only=LifetimeFacts -Wexperimental-lifetime-safety 
> /b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
>  2>&1 | /b/s/w/ir/x/w/llvm_build/bin/FileCheck 
> /b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
>  # RUN: at line 1
> + /b/s/w/ir/x/w/llvm_build/bin/clang -cc1 -internal-isystem 
> /b/s/w/ir/x/w/llvm_build/lib/clang/21/include -nostdsysteminc -mllvm 
> -debug-only=LifetimeFacts -Wexperimental-lifetime-safety 
> /b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
> + /b/s/w/ir/x/w/llvm_build/bin/FileCheck 
> /b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
> /b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp:9:17:
>  error: CHECK-LABEL: expected string not found in input
> // CHECK-LABEL: Function: return_local_addr
> ^
> :1:1: note: scanning from here
> clang (LLVM option parsing): Unknown command line argument 
> '-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help'
> ^
> :1:105: note: possible intended match here
> clang (LLVM option parsing): Unknown command line argument 
> '-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help'
>   
>   ^
> 
> Input file: 
> Check file: 
> /b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
> 
> -dump-input=help explains the following input dump.
> 
> Input was:
> <<
>1: clang (LLVM option parsing): Unknown command line argument 
> '-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help' 
> label:9'0 
> X~
>  error: no match found
> label:9'1 
> ?  possible 
> intended match
>2: clang (LLVM option parsing): Did you mean 
> '--debug-pass=LifetimeFacts'? 
> label:9'0 
> 
> >>
> 
> --
> ```
> 
> I am taking a closer look. Here are the logs: 
> https://logs.chromium.org/logs/fuchsia/buildbucket/cr-buildbucket/8709695680348159649/+/u/clang/tests/stdout

The test just needs asserts to run, I am preparing a patch to fix it and will 
submit it shortly.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Prabhu Rajasekaran via cfe-commits

Prabhuk wrote:

I am part of a toolchain team at Google and we are seeing clang test failures 
in our toolchain builders from this PR.

```
Exit Code: 1

Command Output (stderr):
--
/b/s/w/ir/x/w/llvm_build/bin/clang -cc1 -internal-isystem 
/b/s/w/ir/x/w/llvm_build/lib/clang/21/include -nostdsysteminc -mllvm 
-debug-only=LifetimeFacts -Wexperimental-lifetime-safety 
/b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
 2>&1 | /b/s/w/ir/x/w/llvm_build/bin/FileCheck 
/b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
 # RUN: at line 1
+ /b/s/w/ir/x/w/llvm_build/bin/clang -cc1 -internal-isystem 
/b/s/w/ir/x/w/llvm_build/lib/clang/21/include -nostdsysteminc -mllvm 
-debug-only=LifetimeFacts -Wexperimental-lifetime-safety 
/b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
+ /b/s/w/ir/x/w/llvm_build/bin/FileCheck 
/b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp
/b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp:9:17:
 error: CHECK-LABEL: expected string not found in input
// CHECK-LABEL: Function: return_local_addr
^
:1:1: note: scanning from here
clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help'
^
:1:105: note: possible intended match here
clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help'

^

Input file: 
Check file: 
/b/s/w/ir/x/w/llvm-llvm-project/clang/test/Sema/warn-lifetime-safety-dataflow.cpp

-dump-input=help explains the following input dump.

Input was:
<<
   1: clang (LLVM option parsing): Unknown command line argument 
'-debug-only=LifetimeFacts'. Try: 'clang (LLVM option parsing) --help' 
label:9'0 
X~
 error: no match found
label:9'1   
  ?  possible 
intended match
   2: clang (LLVM option parsing): Did you mean 
'--debug-pass=LifetimeFacts'? 
label:9'0 

>>

--
```

I am taking a closer look. Here are the logs: 
https://logs.chromium.org/logs/fuchsia/buildbucket/cr-buildbucket/8709695680348159649/+/u/clang/tests/stdout

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread LLVM Continuous Integration via cfe-commits

llvm-ci wrote:

LLVM Buildbot has detected a new failure on builder `fuchsia-x86_64-linux` 
running on `fuchsia-debian-64-us-central1-b-1` while building `clang` at step 4 
"annotate".

Full details are available at: 
https://lab.llvm.org/buildbot/#/builders/11/builds/19276


Here is the relevant piece of the build log for the reference

```
Step 4 (annotate) failure: 'python 
../llvm-zorg/zorg/buildbot/builders/annotated/fuchsia-linux.py ...' (failure)
...
[231/2511] Copying CXX header __algorithm/out_value_result.h
[232/2511] Copying CXX header __algorithm/nth_element.h
[233/2511] Copying CXX header __algorithm/shift_right.h
[234/2511] Copying CXX header __algorithm/push_heap.h
[235/2511] Copying CXX header __algorithm/ranges_adjacent_find.h
[236/2511] Copying CXX header __atomic/kill_dependency.h
[237/2511] Generating header complex.h from 
/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/runtimes/../libc/include/complex.yaml
[238/2511] Building CXX object 
libc/src/stdlib/CMakeFiles/libc.src.stdlib.memalignment.dir/memalignment.cpp.obj
[239/2511] Building CXX object 
libc/src/strings/CMakeFiles/libc.src.strings.strcasecmp.dir/strcasecmp.cpp.obj
[240/2511] Building CXX object 
libc/src/compiler/generic/CMakeFiles/libc.src.compiler.generic.__stack_chk_fail.dir/__stack_chk_fail.cpp.obj
FAILED: 
libc/src/compiler/generic/CMakeFiles/libc.src.compiler.generic.__stack_chk_fail.dir/__stack_chk_fail.cpp.obj
 
/var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-oxh7zwbj/./bin/clang++ 
--target=riscv32-unknown-elf -DLIBC_NAMESPACE=__llvm_libc_21_0_0_git 
-I/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/libc -isystem 
/var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-oxh7zwbj/include/riscv32-unknown-unknown-elf
 --target=riscv32-unknown-elf -march=rv32imafc -mabi=ilp32f 
-Wno-atomic-alignment "-Dvfprintf(stream, format, vlist)=vprintf(format, 
vlist)" "-Dfprintf(stream, format, ...)=printf(format)" -D_LIBCPP_PRINT=1 -fPIC 
-fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time 
-Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter 
-Wwrite-strings -Wcast-qual -Wmissing-field-initializers -Wimplicit-fallthrough 
-Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor 
-Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion 
-Wmisleading-indentation -Wctad-maybe-unsupported -ffunction-sections 
-fdata-sections 
-ffile-prefix-map=/var/lib/buildbot/fuchsia-x86_64-linux/build/llvm-build-oxh7zwbj/runtimes/runtimes-riscv32-unknown-elf-bins=../../../../llvm-project
 -ffile-prefix-map=/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/= 
-no-canonical-prefixes -Os -DNDEBUG --target=riscv32-unknown-elf 
-DLIBC_QSORT_IMPL=LIBC_QSORT_HEAP_SORT -DLIBC_ADD_NULL_CHECKS 
"-DLIBC_MATH=(LIBC_MATH_SKIP_ACCURATE_PASS | LIBC_MATH_SMALL_TABLES)" 
-DLIBC_ERRNO_MODE=LIBC_ERRNO_MODE_EXTERNAL -fpie -ffreestanding 
-DLIBC_FULL_BUILD -nostdlibinc -ffixed-point -fno-builtin -fno-exceptions 
-fno-lax-vector-conversions -fno-unwind-tables -fno-asynchronous-unwind-tables 
-fno-rtti -ftrivial-auto-var-init=pattern -fno-omit-frame-pointer -Wall -Wextra 
-Werror -Wconversion -Wno-sign-conversion -Wdeprecated -Wno-c99-extensions 
-Wno-gnu-imaginary-constant -Wno-pedantic -Wimplicit-fallthrough 
-Wwrite-strings -Wextra-semi -Wnewline-eof -Wnonportable-system-include-path 
-Wstrict-prototypes -Wthread-safety -Wglobal-constructors 
-DLIBC_COPT_PUBLIC_PACKAGING -MD -MT 
libc/src/compiler/generic/CMakeFiles/libc.src.compiler.generic.__stack_chk_fail.dir/__stack_chk_fail.cpp.obj
 -MF 
libc/src/compiler/generic/CMakeFiles/libc.src.compiler.generic.__stack_chk_fail.dir/__stack_chk_fail.cpp.obj.d
 -o 
libc/src/compiler/generic/CMakeFiles/libc.src.compiler.generic.__stack_chk_fail.dir/__stack_chk_fail.cpp.obj
 -c 
/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/libc/src/compiler/generic/__stack_chk_fail.cpp
/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/libc/src/compiler/generic/__stack_chk_fail.cpp:16:1:
 error: unknown type name 'uintptr_t'
   16 | uintptr_t __stack_chk_guard = static_cast(0xa9fff01234);
  | ^
/var/lib/buildbot/fuchsia-x86_64-linux/llvm-project/libc/src/compiler/generic/__stack_chk_fail.cpp:16:43:
 error: unknown type name 'uintptr_t'
   16 | uintptr_t __stack_chk_guard = static_cast(0xa9fff01234);
  |   ^
2 errors generated.
[241/2511] Building CXX object 
libc/startup/baremetal/CMakeFiles/libc.startup.baremetal.fini.dir/fini.cpp.obj
[242/2511] Copying CXX header __atomic/support/c11.h
[243/2511] Copying CXX header __algorithm/ranges_remove_if.h
[244/2511] Copying CXX header __algorithm/partition_copy.h
[245/2511] Building CXX object 
libc/src/string/CMakeFiles/libc.src.string.strspn.dir/strspn.cpp.obj
[246/2511] Copying CXX header __algorithm/ranges_set_union.h
[247/2511] Copying CXX header __algorithm/partition.h
[248/2511] Copying CXX header __algorithm/remove_copy_if.h
[249/2511] Copying CXX header __algorith

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Gábor Horváth via cfe-commits


@@ -0,0 +1,510 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is created.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  /// A pointer to the AST node that this origin represents. This union
+  /// distinguishes between origins from lvalues (named variables or parameter)

Xazax-hun wrote:

I think this might not be entirely correct. The value category might be 
independent of whether we have variables or expressions. Consider:

```
int* &f();

f() = nullptr; 
```

Here, the expression `f()` is an lvalue but we do not have a declaration. 

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Utkarsh Saxena via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  Loan &addLoan(AccessPath Path, SourceLocation Loc) {
+AllLoans.emplace_back(getNextLoanID(), Path, Loc);
+return AllLoans.back();
+  }
+
+  const Loan &getLoan(LoanID ID) const {
+assert(ID.Value < AllLoans.size());
+return AllLoans[ID.Value];
+  }
+  llvm::ArrayRef getLoans() const { return AllLoans; }
+
+private:
+  LoanID getNextLoanID() { return NextLoanID++; }
+
+  LoanID NextLoanID{0};
+  /// TODO(opt): Profile and evaluate the usefullness of small buffer
+  /// optimisation.
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  Origin &addOrigin(OriginID ID, const clang::ValueDecl &D) {
+AllOrigins.emplace_back(ID, &D);
+return AllOrigins.back();
+  }
+  Origin &addOrigin(OriginID ID, const clang::Expr &E) {
+AllOrigins.emplace_back(ID, &E);
+return AllOrigins.back();
+  }
+
+  OriginID get(const Expr &E) {
+// Origin of DeclRefExpr is that of the declaration it refers to.
+if (const auto *DRE = dyn_cast(&E))
+  return get(*DRE->getDecl());
+auto It = ExprToOriginID.find(&E);
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == ExprToOriginID.end())
+  return getOrCreate(E);
+
+return It->second;
+  }
+
+  OriginID get(const ValueDecl &D) {
+auto It = DeclToOriginID.find(&D);
+// TODO: This should be an assert(It != DeclToOriginID.end()). The current
+// implementation fa

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Utkarsh Saxena via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  Loan &addLoan(AccessPath Path, SourceLocation Loc) {
+AllLoans.emplace_back(getNextLoanID(), Path, Loc);
+return AllLoans.back();
+  }
+
+  const Loan &getLoan(LoanID ID) const {
+assert(ID.Value < AllLoans.size());
+return AllLoans[ID.Value];
+  }
+  llvm::ArrayRef getLoans() const { return AllLoans; }
+
+private:
+  LoanID getNextLoanID() { return NextLoanID++; }
+
+  LoanID NextLoanID{0};
+  /// TODO(opt): Profile and evaluate the usefullness of small buffer
+  /// optimisation.
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  Origin &addOrigin(OriginID ID, const clang::ValueDecl &D) {
+AllOrigins.emplace_back(ID, &D);
+return AllOrigins.back();
+  }
+  Origin &addOrigin(OriginID ID, const clang::Expr &E) {
+AllOrigins.emplace_back(ID, &E);
+return AllOrigins.back();
+  }
+
+  OriginID get(const Expr &E) {
+// Origin of DeclRefExpr is that of the declaration it refers to.
+if (const auto *DRE = dyn_cast(&E))
+  return get(*DRE->getDecl());
+auto It = ExprToOriginID.find(&E);
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == ExprToOriginID.end())
+  return getOrCreate(E);
+
+return It->second;
+  }
+
+  OriginID get(const ValueDecl &D) {
+auto It = DeclToOriginID.find(&D);
+// TODO: This should be an assert(It != DeclToOriginID.end()). The current
+// implementation fa

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Utkarsh Saxena via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  Loan &addLoan(AccessPath Path, SourceLocation Loc) {
+AllLoans.emplace_back(getNextLoanID(), Path, Loc);
+return AllLoans.back();
+  }
+
+  const Loan &getLoan(LoanID ID) const {
+assert(ID.Value < AllLoans.size());
+return AllLoans[ID.Value];
+  }
+  llvm::ArrayRef getLoans() const { return AllLoans; }
+
+private:
+  LoanID getNextLoanID() { return NextLoanID++; }
+
+  LoanID NextLoanID{0};
+  /// TODO(opt): Profile and evaluate the usefullness of small buffer
+  /// optimisation.
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  Origin &addOrigin(OriginID ID, const clang::ValueDecl &D) {
+AllOrigins.emplace_back(ID, &D);
+return AllOrigins.back();
+  }
+  Origin &addOrigin(OriginID ID, const clang::Expr &E) {
+AllOrigins.emplace_back(ID, &E);
+return AllOrigins.back();
+  }
+
+  OriginID get(const Expr &E) {
+// Origin of DeclRefExpr is that of the declaration it refers to.
+if (const auto *DRE = dyn_cast(&E))
+  return get(*DRE->getDecl());
+auto It = ExprToOriginID.find(&E);
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == ExprToOriginID.end())
+  return getOrCreate(E);
+
+return It->second;
+  }
+
+  OriginID get(const ValueDecl &D) {
+auto It = DeclToOriginID.find(&D);
+// TODO: This should be an assert(It != DeclToOriginID.end()). The current
+// implementation fa

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Utkarsh Saxena via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;

usx95 wrote:

That's correct. Added a comment.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Utkarsh Saxena via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.

usx95 wrote:

created. Thanks.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Yitzhak Mandelbaum via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  Loan &addLoan(AccessPath Path, SourceLocation Loc) {
+AllLoans.emplace_back(getNextLoanID(), Path, Loc);
+return AllLoans.back();
+  }
+
+  const Loan &getLoan(LoanID ID) const {
+assert(ID.Value < AllLoans.size());
+return AllLoans[ID.Value];
+  }
+  llvm::ArrayRef getLoans() const { return AllLoans; }
+
+private:
+  LoanID getNextLoanID() { return NextLoanID++; }
+
+  LoanID NextLoanID{0};
+  /// TODO(opt): Profile and evaluate the usefullness of small buffer
+  /// optimisation.
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  Origin &addOrigin(OriginID ID, const clang::ValueDecl &D) {
+AllOrigins.emplace_back(ID, &D);
+return AllOrigins.back();
+  }
+  Origin &addOrigin(OriginID ID, const clang::Expr &E) {
+AllOrigins.emplace_back(ID, &E);
+return AllOrigins.back();
+  }
+
+  OriginID get(const Expr &E) {
+// Origin of DeclRefExpr is that of the declaration it refers to.
+if (const auto *DRE = dyn_cast(&E))
+  return get(*DRE->getDecl());
+auto It = ExprToOriginID.find(&E);
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == ExprToOriginID.end())
+  return getOrCreate(E);
+
+return It->second;
+  }
+
+  OriginID get(const ValueDecl &D) {
+auto It = DeclToOriginID.find(&D);
+// TODO: This should be an assert(It != DeclToOriginID.end()). The current
+// implementation fa

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Yitzhak Mandelbaum via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  Loan &addLoan(AccessPath Path, SourceLocation Loc) {
+AllLoans.emplace_back(getNextLoanID(), Path, Loc);
+return AllLoans.back();
+  }
+
+  const Loan &getLoan(LoanID ID) const {
+assert(ID.Value < AllLoans.size());
+return AllLoans[ID.Value];
+  }
+  llvm::ArrayRef getLoans() const { return AllLoans; }
+
+private:
+  LoanID getNextLoanID() { return NextLoanID++; }
+
+  LoanID NextLoanID{0};
+  /// TODO(opt): Profile and evaluate the usefullness of small buffer
+  /// optimisation.
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  Origin &addOrigin(OriginID ID, const clang::ValueDecl &D) {
+AllOrigins.emplace_back(ID, &D);
+return AllOrigins.back();
+  }
+  Origin &addOrigin(OriginID ID, const clang::Expr &E) {
+AllOrigins.emplace_back(ID, &E);
+return AllOrigins.back();
+  }
+
+  OriginID get(const Expr &E) {
+// Origin of DeclRefExpr is that of the declaration it refers to.
+if (const auto *DRE = dyn_cast(&E))
+  return get(*DRE->getDecl());
+auto It = ExprToOriginID.find(&E);
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == ExprToOriginID.end())
+  return getOrCreate(E);
+
+return It->second;
+  }
+
+  OriginID get(const ValueDecl &D) {
+auto It = DeclToOriginID.find(&D);
+// TODO: This should be an assert(It != DeclToOriginID.end()). The current
+// implementation fa

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Yitzhak Mandelbaum via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  Loan &addLoan(AccessPath Path, SourceLocation Loc) {
+AllLoans.emplace_back(getNextLoanID(), Path, Loc);
+return AllLoans.back();
+  }
+
+  const Loan &getLoan(LoanID ID) const {
+assert(ID.Value < AllLoans.size());
+return AllLoans[ID.Value];
+  }
+  llvm::ArrayRef getLoans() const { return AllLoans; }
+
+private:
+  LoanID getNextLoanID() { return NextLoanID++; }
+
+  LoanID NextLoanID{0};
+  /// TODO(opt): Profile and evaluate the usefullness of small buffer
+  /// optimisation.
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  Origin &addOrigin(OriginID ID, const clang::ValueDecl &D) {
+AllOrigins.emplace_back(ID, &D);
+return AllOrigins.back();
+  }
+  Origin &addOrigin(OriginID ID, const clang::Expr &E) {
+AllOrigins.emplace_back(ID, &E);
+return AllOrigins.back();
+  }
+
+  OriginID get(const Expr &E) {
+// Origin of DeclRefExpr is that of the declaration it refers to.
+if (const auto *DRE = dyn_cast(&E))
+  return get(*DRE->getDecl());
+auto It = ExprToOriginID.find(&E);
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == ExprToOriginID.end())
+  return getOrCreate(E);
+
+return It->second;
+  }
+
+  OriginID get(const ValueDecl &D) {
+auto It = DeclToOriginID.find(&D);
+// TODO: This should be an assert(It != DeclToOriginID.end()). The current
+// implementation fa

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Yitzhak Mandelbaum via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {

ymand wrote:

class comment? Same for OriginManager below.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Yitzhak Mandelbaum via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  Loan &addLoan(AccessPath Path, SourceLocation Loc) {
+AllLoans.emplace_back(getNextLoanID(), Path, Loc);
+return AllLoans.back();
+  }
+
+  const Loan &getLoan(LoanID ID) const {
+assert(ID.Value < AllLoans.size());
+return AllLoans[ID.Value];
+  }
+  llvm::ArrayRef getLoans() const { return AllLoans; }
+
+private:
+  LoanID getNextLoanID() { return NextLoanID++; }
+
+  LoanID NextLoanID{0};
+  /// TODO(opt): Profile and evaluate the usefullness of small buffer
+  /// optimisation.
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  Origin &addOrigin(OriginID ID, const clang::ValueDecl &D) {
+AllOrigins.emplace_back(ID, &D);
+return AllOrigins.back();
+  }
+  Origin &addOrigin(OriginID ID, const clang::Expr &E) {
+AllOrigins.emplace_back(ID, &E);
+return AllOrigins.back();
+  }
+
+  OriginID get(const Expr &E) {
+// Origin of DeclRefExpr is that of the declaration it refers to.
+if (const auto *DRE = dyn_cast(&E))
+  return get(*DRE->getDecl());
+auto It = ExprToOriginID.find(&E);
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == ExprToOriginID.end())
+  return getOrCreate(E);
+
+return It->second;
+  }
+
+  OriginID get(const ValueDecl &D) {
+auto It = DeclToOriginID.find(&D);
+// TODO: This should be an assert(It != DeclToOriginID.end()). The current
+// implementation fa

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Yitzhak Mandelbaum via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.

ymand wrote:

"taken" or "created"?

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand approved this pull request.

Really nice!

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Yitzhak Mandelbaum via cfe-commits

https://github.com/ymand edited https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-10 Thread Yitzhak Mandelbaum via cfe-commits


@@ -0,0 +1,504 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Model access paths of other types, e.g., s.field, heap and globals.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  AccessPath(const clang::ValueDecl *D) : D(D) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;

ymand wrote:

comment documenting this in a little more detail than struct comment above? for 
example, when is one vs the other used? I gather this roughly corresponds to 
lvalue vs rvalue; if that's correct, maybe mention.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-09 Thread Utkarsh Saxena via cfe-commits

usx95 wrote:

In 1-2 days, I will go ahead and merge this if there are no more comments from 
other reviewers. cc: @ymand 

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 commented:

> Something for future PRs: I think it would be nice to have some sort of 
> coverage statistics. While initially you do not aim to cover all of C++, it 
> would be good to know what portion of nodes are missing from the fact 
> generation when we run this on some real world code. That can give us some 
> progress indicators.

Good idea. I was thinking along similar lines and have some ideas for initial 
metrics:
- Use an RAV to visit all expressions in a function and count number of 
expressions which should have an origin (i.e., it is of pointer type) but does 
not have an origin associated with the expression. 
- Count origins that are created but are never associated with a Loan; this 
would be a signal that we don't understand the pointer's source.

I will add these in a follow-up patch.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Utkarsh Saxena via cfe-commits


@@ -0,0 +1,508 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  enum class Kind : uint8_t {
+StackVariable,
+Temporary,// TODO: Handle.
+Field,// TODO: Handle like `s.y`.
+Heap, // TODO: Handle.
+ArrayElement, // TODO: Handle.
+Static,   // TODO: Handle.
+  };
+
+  Kind PathKind;
+
+  AccessPath(const clang::ValueDecl *D, Kind K) : D(D), PathKind(K) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.

usx95 wrote:

That's right. An opaque loan is a borrow where the specific storage location is 
unknown (within the current function). Return value of an external function or 
output param of a function parameter can be some sources.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Utkarsh Saxena via cfe-commits


@@ -0,0 +1,728 @@
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+struct Point {
+  const clang::CFGBlock *Block;
+  /// Index into Block->Elements().
+  unsigned ElementIndex;
+
+  Point(const clang::CFGBlock *B = nullptr, unsigned Idx = 0)
+  : Block(B), ElementIndex(Idx) {}
+
+  bool operator==(const Point &Other) const {
+return Block == Other.Block && ElementIndex == Other.ElementIndex;
+  }
+};
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Handle member accesseslike `s.y`.
+struct Path {
+  const clang::ValueDecl *D;
+
+  enum class Kind : uint8_t {

usx95 wrote:

For the need of`AccessPath::Kind`, you are right. I think we can do without it. 
Let me remove it for now.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Utkarsh Saxena via cfe-commits


@@ -0,0 +1,728 @@
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+struct Point {
+  const clang::CFGBlock *Block;
+  /// Index into Block->Elements().
+  unsigned ElementIndex;
+
+  Point(const clang::CFGBlock *B = nullptr, unsigned Idx = 0)
+  : Block(B), ElementIndex(Idx) {}
+
+  bool operator==(const Point &Other) const {
+return Block == Other.Block && ElementIndex == Other.ElementIndex;
+  }
+};
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Handle member accesseslike `s.y`.
+struct Path {
+  const clang::ValueDecl *D;
+
+  enum class Kind : uint8_t {
+StackVariable,
+Heap,// TODO: Handle.
+Field,   // TODO: Handle.
+ArrayElement,// TODO: Handle.
+TemporaryObject, // TODO: Handle.
+StaticOrGlobal,  // TODO: Handle.
+  };
+
+  Kind PathKind;
+
+  Path(const clang::ValueDecl *D, Kind K) : D(D), PathKind(K) {}
+};
+
+using LoanID = uint32_t;
+using OriginID = uint32_t;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct LoanInfo {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  Path SourcePath;
+  SourceLocation IssueLoc;
+
+  LoanInfo(LoanID id, Path path, SourceLocation loc)
+  : ID(id), SourcePath(path), IssueLoc(loc) {}
+};
+
+enum class OriginKind : uint8_t { Variable, ExpressionResult };
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Also represent Origins of complex types (fields, inner types).
+struct OriginInfo {
+  OriginID ID;
+  OriginKind Kind;
+  union {
+const clang::ValueDecl *Decl;
+const clang::Expr *Expression;
+  };
+  OriginInfo(OriginID id, OriginKind kind, const clang::ValueDecl *D)
+  : ID(id), Kind(kind), Decl(D) {}
+  OriginInfo(OriginID id, OriginKind kind, const clang::Expr *E)
+  : ID(id), Kind(kind), Expression(E) {}
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  LoanInfo &addLoanInfo(Path path, SourceLocation loc) {
+NextLoanIDVal++;
+AllLoans.emplace_back(NextLoanIDVal, path, loc);
+return AllLoans.back();
+  }
+
+  const LoanInfo *getLoanInfo(LoanID id) const {
+if (id < AllLoans.size())
+  return &AllLoans[id];
+return nullptr;
+  }
+  llvm::ArrayRef getLoanInfos() const { return AllLoans; }
+
+private:
+  LoanID NextLoanIDVal = 0;
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  OriginID getNextOriginID() { return NextOriginIDVal++; }
+  OriginInfo &addOriginInfo(OriginID id, const clang::ValueDecl *D) {
+assert(D != nullptr);
+AllOrigins.emplace_back(id, OriginKind::Variable, D);
+return AllOrigins.back();
+  }
+  OriginInfo &addOriginInfo(OriginID id, const clang::Expr *E) {
+assert(E != nullptr);
+AllOrigins.emplace_back(id, OriginKind::ExpressionResult, E);
+return AllOrigins.back();
+  }
+
+  OriginID getOrCreate(const Expr *E) {
+auto It = ExprToOriginID.find(E);
+if (It != ExprToOriginID.end())
+  return It->second;
+
+if (const auto *DRE = dyn_cast(E)) {
+  // Origin of DeclRefExpr is that of the declaration it refers to.
+  return getOrCreate(DRE->getDecl());
+}
+OriginID NewID = getNextOriginID();
+addOriginInfo(NewID, E);
+ExprToOriginID[E] = NewID;
+return NewID;
+  }
+
+  const OriginInfo *getOriginInfo(OriginID id) const {
+if (id < AllOrigins.size())
+  return &AllOrigins[id];
+return nullptr;
+  }
+
+  llvm::ArrayRef getOriginInfos() const { return AllOrigins; }
+
+  OriginID getOrCreate(const ValueDecl *D) {
+auto It = DeclToOriginID.find(D);
+if (It != DeclToOriginID.end())
+  return It->second;
+OriginID NewID = getNextOriginID();
+addOriginInfo(NewID, D);
+DeclToOriginID[D] = NewID;
+return NewID;
+  }
+
+private:
+  OriginID NextOriginIDVal = 0;
+  llvm::SmallVector AllOrigins;
+  llvm::DenseMap DeclToOriginID;
+  llvm::DenseMap ExprToOriginID;
+};
+
+/// An abstract base class for a single, atomic lifetime-relevant event.
+class Fact {
+
+public:
+  enum class Kind : uint8_t {
+/// A new loan is issued from a borrow expression (e.g., &x).
+Issue,
+/// A loan expires

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff HEAD~1 HEAD --extensions h,cpp -- 
clang/include/clang/Analysis/Analyses/LifetimeSafety.h 
clang/lib/Analysis/LifetimeSafety.cpp 
clang/test/Sema/warn-lifetime-safety-dataflow.cpp 
clang/lib/Sema/AnalysisBasedWarnings.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 7c234912c..4cce77e38 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2872,8 +2872,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
 
   // TODO: Enable lifetime safety analysis for other languages once it is
   // stable.
-  if (EnableLifetimeSafetyAnalysis &&
-  S.getLangOpts().CPlusPlus) {
+  if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
 if (CFG *cfg = AC.getCFG())
   runLifetimeSafetyAnalysis(*cast(D), *cfg, AC);
   }

``




https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Gábor Horváth via cfe-commits


@@ -0,0 +1,508 @@
+//===- LifetimeSafety.cpp - C++ Lifetime Safety Analysis -*- 
C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/PostOrderCFGView.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  enum class Kind : uint8_t {
+StackVariable,
+Temporary,// TODO: Handle.
+Field,// TODO: Handle like `s.y`.
+Heap, // TODO: Handle.
+ArrayElement, // TODO: Handle.
+Static,   // TODO: Handle.
+  };
+
+  Kind PathKind;
+
+  AccessPath(const clang::ValueDecl *D, Kind K) : D(D), PathKind(K) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.

Xazax-hun wrote:

Could you elaborate what do you mean by an opaque loan? Would this be something 
coming from a e.g., a function call?

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Gábor Horváth via cfe-commits

https://github.com/Xazax-hun edited 
https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Gábor Horváth via cfe-commits

https://github.com/Xazax-hun approved this pull request.

There are some discussions open on this PR e.g., whether access paths need 
kinds. But I don't think those are blockers, this is exploratory work and it is 
expected that some design decisions might be revisited along the way when we 
learn something new. I am OK with the current status of this PR.

Something for future PRs: I think it would be nice to have some sort of 
coverage statistics. While initially you do not aim to cover all of C++, it 
would be good to know what portion of nodes are missing from the fact 
generation when we run this on some real world code. That can give us some 
progress indicators. 

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Gábor Horváth via cfe-commits

https://github.com/Xazax-hun edited 
https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Gábor Horváth via cfe-commits


@@ -0,0 +1,728 @@
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+struct Point {
+  const clang::CFGBlock *Block;
+  /// Index into Block->Elements().
+  unsigned ElementIndex;
+
+  Point(const clang::CFGBlock *B = nullptr, unsigned Idx = 0)
+  : Block(B), ElementIndex(Idx) {}
+
+  bool operator==(const Point &Other) const {
+return Block == Other.Block && ElementIndex == Other.ElementIndex;
+  }
+};
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+/// TODO: Handle member accesseslike `s.y`.
+struct Path {
+  const clang::ValueDecl *D;
+
+  enum class Kind : uint8_t {
+StackVariable,
+Heap,// TODO: Handle.
+Field,   // TODO: Handle.
+ArrayElement,// TODO: Handle.
+TemporaryObject, // TODO: Handle.
+StaticOrGlobal,  // TODO: Handle.
+  };
+
+  Kind PathKind;
+
+  Path(const clang::ValueDecl *D, Kind K) : D(D), PathKind(K) {}
+};
+
+using LoanID = uint32_t;
+using OriginID = uint32_t;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct LoanInfo {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  Path SourcePath;
+  SourceLocation IssueLoc;
+
+  LoanInfo(LoanID id, Path path, SourceLocation loc)
+  : ID(id), SourcePath(path), IssueLoc(loc) {}
+};
+
+enum class OriginKind : uint8_t { Variable, ExpressionResult };
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Also represent Origins of complex types (fields, inner types).
+struct OriginInfo {
+  OriginID ID;
+  OriginKind Kind;
+  union {
+const clang::ValueDecl *Decl;
+const clang::Expr *Expression;
+  };
+  OriginInfo(OriginID id, OriginKind kind, const clang::ValueDecl *D)
+  : ID(id), Kind(kind), Decl(D) {}
+  OriginInfo(OriginID id, OriginKind kind, const clang::Expr *E)
+  : ID(id), Kind(kind), Expression(E) {}
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  LoanInfo &addLoanInfo(Path path, SourceLocation loc) {
+NextLoanIDVal++;
+AllLoans.emplace_back(NextLoanIDVal, path, loc);
+return AllLoans.back();
+  }
+
+  const LoanInfo *getLoanInfo(LoanID id) const {
+if (id < AllLoans.size())
+  return &AllLoans[id];
+return nullptr;
+  }
+  llvm::ArrayRef getLoanInfos() const { return AllLoans; }
+
+private:
+  LoanID NextLoanIDVal = 0;
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  OriginID getNextOriginID() { return NextOriginIDVal++; }
+  OriginInfo &addOriginInfo(OriginID id, const clang::ValueDecl *D) {
+assert(D != nullptr);
+AllOrigins.emplace_back(id, OriginKind::Variable, D);
+return AllOrigins.back();
+  }
+  OriginInfo &addOriginInfo(OriginID id, const clang::Expr *E) {
+assert(E != nullptr);
+AllOrigins.emplace_back(id, OriginKind::ExpressionResult, E);
+return AllOrigins.back();
+  }
+
+  OriginID getOrCreate(const Expr *E) {
+auto It = ExprToOriginID.find(E);
+if (It != ExprToOriginID.end())
+  return It->second;
+
+if (const auto *DRE = dyn_cast(E)) {
+  // Origin of DeclRefExpr is that of the declaration it refers to.
+  return getOrCreate(DRE->getDecl());
+}
+OriginID NewID = getNextOriginID();
+addOriginInfo(NewID, E);
+ExprToOriginID[E] = NewID;
+return NewID;
+  }
+
+  const OriginInfo *getOriginInfo(OriginID id) const {
+if (id < AllOrigins.size())
+  return &AllOrigins[id];
+return nullptr;
+  }
+
+  llvm::ArrayRef getOriginInfos() const { return AllOrigins; }
+
+  OriginID getOrCreate(const ValueDecl *D) {
+auto It = DeclToOriginID.find(D);
+if (It != DeclToOriginID.end())
+  return It->second;
+OriginID NewID = getNextOriginID();
+addOriginInfo(NewID, D);
+DeclToOriginID[D] = NewID;
+return NewID;
+  }
+
+private:
+  OriginID NextOriginIDVal = 0;
+  llvm::SmallVector AllOrigins;
+  llvm::DenseMap DeclToOriginID;
+  llvm::DenseMap ExprToOriginID;
+};
+
+/// An abstract base class for a single, atomic lifetime-relevant event.
+class Fact {
+
+public:
+  enum class Kind : uint8_t {
+/// A new loan is issued from a borrow expression (e.g., &x).
+Issue,
+/// A loan expires

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Utkarsh Saxena via cfe-commits


@@ -0,0 +1,13 @@
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIME_SAFETY_H

usx95 wrote:

Done. Thanks.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Utkarsh Saxena via cfe-commits


@@ -0,0 +1,13 @@
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIME_SAFETY_H

usx95 wrote:

Done.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-07 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-06 Thread Baranov Victor via cfe-commits

https://github.com/vbvictor edited 
https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-06 Thread Baranov Victor via cfe-commits

https://github.com/vbvictor edited 
https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-06 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,508 @@
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  enum class Kind : uint8_t {
+StackVariable,
+Temporary,// TODO: Handle.
+Field,// TODO: Handle like `s.y`.
+Heap, // TODO: Handle.
+ArrayElement, // TODO: Handle.
+Static,   // TODO: Handle.
+  };
+
+  Kind PathKind;
+
+  AccessPath(const clang::ValueDecl *D, Kind K) : D(D), PathKind(K) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  Loan &addLoan(AccessPath Path, SourceLocation Loc) {
+AllLoans.emplace_back(getNextLoanID(), Path, Loc);
+return AllLoans.back();
+  }
+
+  const Loan &getLoan(LoanID ID) const {
+assert(ID.Value < AllLoans.size());
+return AllLoans[ID.Value];
+  }
+  llvm::ArrayRef getLoans() const { return AllLoans; }
+
+private:
+  LoanID getNextLoanID() { return NextLoanID++; }
+
+  LoanID NextLoanID{0};
+  /// TODO(opt): Profile and evaluate the usefullness of small buffer
+  /// optimisation.
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  Origin &addOrigin(OriginID ID, const clang::ValueDecl &D) {
+AllOrigins.emplace_back(ID, &D);
+return AllOrigins.back();
+  }
+  Origin &addOrigin(OriginID ID, const clang::Expr &E) {
+AllOrigins.emplace_back(ID, &E);
+return AllOrigins.back();
+  }
+
+  OriginID get(const Expr &E) {
+// Origin of DeclRefExpr is that of the declaration it refers to.
+if (const auto *DRE = dyn_cast(&E)) {
+  return get(*DRE->getDecl());
+}
+auto It = ExprToOriginID.find(&E);
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == ExprToOriginID.end())
+  return getOrCreate(E);
+
+return It->second;
+  }
+
+  OriginID get(const ValueDecl &D) {
+auto It = DeclToOriginID.find(&D);
+assert(It != DeclToOriginID.end());
+return It->second;
+  }
+
+  OriginID getOrCreate(const Expr &E) {
+auto It = ExprToOriginID.find(&E);
+if (It != ExprToOriginID.en

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-06 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,508 @@
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  enum class Kind : uint8_t {
+StackVariable,
+Temporary,// TODO: Handle.
+Field,// TODO: Handle like `s.y`.
+Heap, // TODO: Handle.
+ArrayElement, // TODO: Handle.
+Static,   // TODO: Handle.
+  };
+
+  Kind PathKind;
+
+  AccessPath(const clang::ValueDecl *D, Kind K) : D(D), PathKind(K) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  Loan &addLoan(AccessPath Path, SourceLocation Loc) {
+AllLoans.emplace_back(getNextLoanID(), Path, Loc);
+return AllLoans.back();
+  }
+
+  const Loan &getLoan(LoanID ID) const {
+assert(ID.Value < AllLoans.size());
+return AllLoans[ID.Value];
+  }
+  llvm::ArrayRef getLoans() const { return AllLoans; }
+
+private:
+  LoanID getNextLoanID() { return NextLoanID++; }
+
+  LoanID NextLoanID{0};
+  /// TODO(opt): Profile and evaluate the usefullness of small buffer
+  /// optimisation.
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  Origin &addOrigin(OriginID ID, const clang::ValueDecl &D) {
+AllOrigins.emplace_back(ID, &D);
+return AllOrigins.back();
+  }
+  Origin &addOrigin(OriginID ID, const clang::Expr &E) {
+AllOrigins.emplace_back(ID, &E);
+return AllOrigins.back();
+  }
+
+  OriginID get(const Expr &E) {
+// Origin of DeclRefExpr is that of the declaration it refers to.
+if (const auto *DRE = dyn_cast(&E)) {
+  return get(*DRE->getDecl());
+}
+auto It = ExprToOriginID.find(&E);
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == ExprToOriginID.end())
+  return getOrCreate(E);
+
+return It->second;
+  }
+
+  OriginID get(const ValueDecl &D) {
+auto It = DeclToOriginID.find(&D);
+assert(It != DeclToOriginID.end());
+return It->second;
+  }
+
+  OriginID getOrCreate(const Expr &E) {
+auto It = ExprToOriginID.find(&E);
+if (It != ExprToOriginID.en

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-06 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,508 @@
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  enum class Kind : uint8_t {
+StackVariable,
+Temporary,// TODO: Handle.
+Field,// TODO: Handle like `s.y`.
+Heap, // TODO: Handle.
+ArrayElement, // TODO: Handle.
+Static,   // TODO: Handle.
+  };
+
+  Kind PathKind;
+
+  AccessPath(const clang::ValueDecl *D, Kind K) : D(D), PathKind(K) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  Loan &addLoan(AccessPath Path, SourceLocation Loc) {
+AllLoans.emplace_back(getNextLoanID(), Path, Loc);
+return AllLoans.back();
+  }
+
+  const Loan &getLoan(LoanID ID) const {
+assert(ID.Value < AllLoans.size());
+return AllLoans[ID.Value];
+  }
+  llvm::ArrayRef getLoans() const { return AllLoans; }
+
+private:
+  LoanID getNextLoanID() { return NextLoanID++; }
+
+  LoanID NextLoanID{0};
+  /// TODO(opt): Profile and evaluate the usefullness of small buffer
+  /// optimisation.
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  Origin &addOrigin(OriginID ID, const clang::ValueDecl &D) {
+AllOrigins.emplace_back(ID, &D);
+return AllOrigins.back();
+  }
+  Origin &addOrigin(OriginID ID, const clang::Expr &E) {
+AllOrigins.emplace_back(ID, &E);
+return AllOrigins.back();
+  }
+
+  OriginID get(const Expr &E) {
+// Origin of DeclRefExpr is that of the declaration it refers to.
+if (const auto *DRE = dyn_cast(&E)) {
+  return get(*DRE->getDecl());
+}
+auto It = ExprToOriginID.find(&E);
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == ExprToOriginID.end())
+  return getOrCreate(E);
+
+return It->second;
+  }
+
+  OriginID get(const ValueDecl &D) {
+auto It = DeclToOriginID.find(&D);
+assert(It != DeclToOriginID.end());
+return It->second;
+  }
+
+  OriginID getOrCreate(const Expr &E) {
+auto It = ExprToOriginID.find(&E);
+if (It != ExprToOriginID.en

[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-06 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,508 @@
+#include "clang/Analysis/Analyses/LifetimeSafety.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableSet.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TimeProfiler.h"
+#include 
+
+namespace clang {
+namespace {
+
+/// Represents the storage location being borrowed, e.g., a specific stack
+/// variable.
+struct AccessPath {
+  const clang::ValueDecl *D;
+
+  enum class Kind : uint8_t {
+StackVariable,
+Temporary,// TODO: Handle.
+Field,// TODO: Handle like `s.y`.
+Heap, // TODO: Handle.
+ArrayElement, // TODO: Handle.
+Static,   // TODO: Handle.
+  };
+
+  Kind PathKind;
+
+  AccessPath(const clang::ValueDecl *D, Kind K) : D(D), PathKind(K) {}
+};
+
+/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
+/// Used for giving ID to loans and origins.
+template  struct ID {
+  uint32_t Value = 0;
+
+  bool operator==(const ID &Other) const { return Value == Other.Value; }
+  bool operator!=(const ID &Other) const { return !(*this == Other); }
+  bool operator<(const ID &Other) const { return Value < Other.Value; }
+  ID operator++(int) {
+ID Tmp = *this;
+++Value;
+return Tmp;
+  }
+  void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
+IDBuilder.AddInteger(Value);
+  }
+};
+
+template 
+inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID ID) {
+  return OS << ID.Value;
+}
+
+using LoanID = ID;
+using OriginID = ID;
+
+/// Information about a single borrow, or "Loan". A loan is created when a
+/// reference or pointer is taken.
+struct Loan {
+  /// TODO: Represent opaque loans.
+  /// TODO: Represent nullptr: loans to no path. Accessing it UB! Currently it
+  /// is represented as empty LoanSet
+  LoanID ID;
+  AccessPath Path;
+  SourceLocation IssueLoc;
+
+  Loan(LoanID id, AccessPath path, SourceLocation loc)
+  : ID(id), Path(path), IssueLoc(loc) {}
+};
+
+/// An Origin is a symbolic identifier that represents the set of possible
+/// loans a pointer-like object could hold at any given time.
+/// TODO: Enhance the origin model to handle complex types, pointer
+/// indirection and reborrowing. The plan is to move from a single origin per
+/// variable/expression to a "list of origins" governed by the Type.
+/// For example, the type 'int**' would have two origins.
+/// See discussion:
+/// 
https://github.com/llvm/llvm-project/pull/142313/commits/0cd187b01e61b200d92ca0b640789c1586075142#r2137644238
+struct Origin {
+  OriginID ID;
+  llvm::PointerUnion Ptr;
+
+  Origin(OriginID ID, const clang::ValueDecl *D) : ID(ID), Ptr(D) {}
+  Origin(OriginID ID, const clang::Expr *E) : ID(ID), Ptr(E) {}
+
+  const clang::ValueDecl *getDecl() const {
+return Ptr.dyn_cast();
+  }
+  const clang::Expr *getExpr() const {
+return Ptr.dyn_cast();
+  }
+};
+
+class LoanManager {
+public:
+  LoanManager() = default;
+
+  Loan &addLoan(AccessPath Path, SourceLocation Loc) {
+AllLoans.emplace_back(getNextLoanID(), Path, Loc);
+return AllLoans.back();
+  }
+
+  const Loan &getLoan(LoanID ID) const {
+assert(ID.Value < AllLoans.size());
+return AllLoans[ID.Value];
+  }
+  llvm::ArrayRef getLoans() const { return AllLoans; }
+
+private:
+  LoanID getNextLoanID() { return NextLoanID++; }
+
+  LoanID NextLoanID{0};
+  /// TODO(opt): Profile and evaluate the usefullness of small buffer
+  /// optimisation.
+  llvm::SmallVector AllLoans;
+};
+
+class OriginManager {
+public:
+  OriginManager() = default;
+
+  Origin &addOrigin(OriginID ID, const clang::ValueDecl &D) {
+AllOrigins.emplace_back(ID, &D);
+return AllOrigins.back();
+  }
+  Origin &addOrigin(OriginID ID, const clang::Expr &E) {
+AllOrigins.emplace_back(ID, &E);
+return AllOrigins.back();
+  }
+
+  OriginID get(const Expr &E) {
+// Origin of DeclRefExpr is that of the declaration it refers to.
+if (const auto *DRE = dyn_cast(&E)) {
+  return get(*DRE->getDecl());
+}

vbvictor wrote:

```suggestion
if (const auto *DRE = dyn_cast(&E))
  return get(*DRE->getDecl());
```

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-06 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,13 @@
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIME_SAFETY_H

vbvictor wrote:

I think this file has a "Header" with `Part of the LLVM Project ...` and a 
little in-place description like any other file in `Analyses/` dir. Same to 
.cpp file.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-06 Thread Baranov Victor via cfe-commits

https://github.com/vbvictor commented:

Thank you for your work! Interested to see this feature in clang.
Left a couple of nit comments on code style.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-06 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,13 @@
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIME_SAFETY_H

vbvictor wrote:

```suggestion
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
```
Underscore should be path separators, 
https://llvm.org/docs/CodingStandards.html#header-guard.

https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-06 Thread Baranov Victor via cfe-commits

https://github.com/vbvictor edited 
https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)

2025-07-06 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/142313
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits