[all-commits] [llvm/llvm-project] c5654d: [LifetimeSafety] Introduce buildOriginFlowChain fo...

Yuan Suo via All-commits all-commits at lists.llvm.org
Fri Jun 12 08:38:22 PDT 2026


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: c5654d53c008522d2da165f05b682aafa36d7189
      https://github.com/llvm/llvm-project/commit/c5654d53c008522d2da165f05b682aafa36d7189
  Author: Yuan Suo <suoyuan666 at s5n.xyz>
  Date:   2026-06-12 (Fri, 12 Jun 2026)

  Changed paths:
    M clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
    M clang/include/clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h
    M clang/include/clang/Basic/DiagnosticSemaKinds.td
    M clang/lib/Analysis/LifetimeSafety/Checker.cpp
    M clang/lib/Analysis/LifetimeSafety/LoanPropagation.cpp
    M clang/lib/Sema/SemaLifetimeSafety.h
    M clang/test/Sema/LifetimeSafety/annotation-suggestions.cpp
    M clang/test/Sema/LifetimeSafety/nocfg.cpp
    M clang/test/Sema/LifetimeSafety/safety.cpp

  Log Message:
  -----------
  [LifetimeSafety] Introduce buildOriginFlowChain for use-after-scope (#199345)

After adding `buildOriginFlowChain`, we need to choose a diagnostic type
that is as simple as possible to verify its feasibility during `Sema`
diagnostics.

I did not choose the annotation suggestions described in
https://github.com/llvm/llvm-project/pull/188467/#issuecomment-4359071778
as the first target to implement, because it does not seem to occur
within a single CFG block. The `IssueFact` always resides in the block
preceding the `OriginEscapesFact`, which causes me to always get an
empty `OriginFlowChain`.

Since we use `buildOriginFlowChain`, we can directly trace distinct
assignment steps that occur within a single source-level expression. For
example:

```cpp
#include <vector>
#include <string>

template<class... T> void use(T... arg);

void operator_star_arrow_of_iterators_false_positive_no_cfg_analysis() {
  std::vector<std::pair<int, std::string>> v;
  const char* p = v.begin()->second.data();
  const char* q = (*v.begin()).second.data();
  const std::string& r = (*v.begin()).second;

  auto temporary = []() { return std::vector<std::pair<int, std::string>>{{1, "1"}}; };
  const char* x = temporary().begin()->second.data();
  const char* y = (*temporary().begin()).second.data();
  const std::string& z = (*temporary().begin()).second;
  use(p, q, r, x, y, z);
}
```

The code above produces the following diagnostic output:

```txt
pr.cpp:13:19: warning: local temporary object does not live long enough [-Wlifetime-safety-use-after-scope]
   13 |   const char* x = temporary().begin()->second.data();
      |                   ^~~~~~~~~~~
pr.cpp:13:52: note: destroyed here
   13 |   const char* x = temporary().begin()->second.data();
      |                                                    ^
pr.cpp:13:19: note: expression aliases the storage of local temporary object
   13 |   const char* x = temporary().begin()->second.data();
      |                   ^~~~~~~~~~~~~~~~~~~
pr.cpp:13:19: note: expression aliases the storage of local temporary object
   13 |   const char* x = temporary().begin()->second.data();
      |                   ^~~~~~~~~~~~~~~~~~~~~
pr.cpp:13:19: note: expression aliases the storage of local temporary object
   13 |   const char* x = temporary().begin()->second.data();
      |                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr.cpp:16:16: note: later used here
   16 |   use(p, q, r, x, y, z);
      |                ^
pr.cpp:15:28: warning: local temporary object does not live long enough [-Wlifetime-safety-use-after-scope]
   15 |   const std::string& z = (*temporary().begin()).second;
      |                            ^~~~~~~~~~~
pr.cpp:15:49: note: destroyed here
   15 |   const std::string& z = (*temporary().begin()).second;
      |                                                 ^
pr.cpp:15:28: note: expression aliases the storage of local temporary object
   15 |   const std::string& z = (*temporary().begin()).second;
      |                            ^~~~~~~~~~~~~~~~~~~
pr.cpp:15:27: note: expression aliases the storage of local temporary object
   15 |   const std::string& z = (*temporary().begin()).second;
      |                           ^~~~~~~~~~~~~~~~~~~~
pr.cpp:16:22: note: later used here
   16 |   use(p, q, r, x, y, z);
      |                      ^
pr.cpp:14:21: warning: local temporary object does not live long enough [-Wlifetime-safety-use-after-scope]
   14 |   const char* y = (*temporary().begin()).second.data();
      |                     ^~~~~~~~~~~
pr.cpp:14:54: note: destroyed here
   14 |   const char* y = (*temporary().begin()).second.data();
      |                                                      ^
pr.cpp:14:21: note: expression aliases the storage of local temporary object
   14 |   const char* y = (*temporary().begin()).second.data();
      |                     ^~~~~~~~~~~~~~~~~~~
pr.cpp:14:20: note: expression aliases the storage of local temporary object
   14 |   const char* y = (*temporary().begin()).second.data();
      |                    ^~~~~~~~~~~~~~~~~~~~
pr.cpp:14:19: note: expression aliases the storage of local temporary object
   14 |   const char* y = (*temporary().begin()).second.data();
      |                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr.cpp:16:19: note: later used here
   16 |   use(p, q, r, x, y, z);
      |                   ^
3 warnings generated.
```

---------

Signed-off-by: Yuan Suo <suoyuan666 at s5n.xyz>



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list