[clang] [LifetimeSafety] Introduce intra-procedural analysis in Clang (PR #142313)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
@@ -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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
@@ -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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
@@ -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)
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)
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
