================
@@ -454,6 +462,17 @@ void FactsGenerator::handleLifetimeEnds(const 
CFGLifetimeEnds &LifetimeEnds) {
             BL->getID(), LifetimeEnds.getTriggerStmt()->getEndLoc()));
     }
   }
+  // In loops, the back-edge can make a dead origin appear live at its
+  // pointee's ExpireFact. Expiring the origin here prevents that.
+  if (OriginList *List = getOriginsList(*LifetimeEndsVD)) {
+    for (OriginList *L = List; L; L = L->peelOuterOrigin()) {
----------------
aeft wrote:

If we don't go through the whole origin list, it fails the below case: 
```cpp
void multi_level_pointer_in_loop() {
  for (int i = 0; i < 10; ++i) {
    MyObj obj;
    MyObj* p;
    MyObj** pp;
    if (i > 5) {
      p = &obj; 
      pp = &p;
    }
    (void)**pp;
  }
}
```
```
/tmp/test_multi.cpp:8:12: warning: object whose reference is captured may not 
live long enough [-Wlifetime-safety-strict]
    8 |       p = &obj;
      |            ^~~
/tmp/test_multi.cpp:12:3: note: destroyed here
   12 |   }
      |   ^
/tmp/test_multi.cpp:11:13: note: later used here
   11 |     (void)**pp;
      |             ^~
```


Here is the debug output:
```
  Block B4:
    Issue (2 (Path: obj), ToOrigin: 2 (Expr: DeclRefExpr, Decl: obj))
    OriginFlow: 
        Dest: 3 (Expr: UnaryOperator, Type : MyObj *)
        Src:  2 (Expr: DeclRefExpr, Decl: obj)
    Use (5 (Decl: p, Type : MyObj *), Write)
    Issue (3 (Path: p), ToOrigin: 4 (Expr: DeclRefExpr, Decl: p))
    OriginFlow: 
        Dest: 5 (Decl: p, Type : MyObj *)
        Src:  3 (Expr: UnaryOperator, Type : MyObj *)
    Use (5 (Decl: p, Type : MyObj *), Read)
    Issue (4 (Path: p), ToOrigin: 6 (Expr: DeclRefExpr, Decl: p))
    OriginFlow: 
        Dest: 7 (Expr: UnaryOperator, Type : MyObj **)
        Src:  6 (Expr: DeclRefExpr, Decl: p)
    OriginFlow: 
        Dest: 8 (Expr: UnaryOperator, Type : MyObj *)
        Src:  5 (Decl: p, Type : MyObj *)
    Use (10 (Decl: pp, Type : MyObj **), 11 (Decl: pp, Type : MyObj *), Write)
    Issue (5 (Path: pp), ToOrigin: 9 (Expr: DeclRefExpr, Decl: pp))
    OriginFlow: 
        Dest: 10 (Decl: pp, Type : MyObj **)
        Src:  7 (Expr: UnaryOperator, Type : MyObj **)
    OriginFlow: 
        Dest: 11 (Decl: pp, Type : MyObj *)
        Src:  8 (Expr: UnaryOperator, Type : MyObj *)
  End of Block
  Block B3:
    Use (10 (Decl: pp, Type : MyObj **), 11 (Decl: pp, Type : MyObj *), Read)
    Issue (6 (Path: pp), ToOrigin: 12 (Expr: DeclRefExpr, Decl: pp))
    OriginFlow: 
        Dest: 13 (Expr: ImplicitCastExpr, Type : MyObj **)
        Src:  10 (Decl: pp, Type : MyObj **)
    OriginFlow: 
        Dest: 14 (Expr: ImplicitCastExpr, Type : MyObj *)
        Src:  11 (Decl: pp, Type : MyObj *)
    OriginFlow: 
        Dest: 15 (Expr: UnaryOperator, Type : MyObj *&)
        Src:  13 (Expr: ImplicitCastExpr, Type : MyObj **)
    OriginFlow: 
        Dest: 16 (Expr: UnaryOperator, Type : MyObj *)
        Src:  14 (Expr: ImplicitCastExpr, Type : MyObj *)
    OriginFlow: 
        Dest: 17 (Expr: ImplicitCastExpr, Type : MyObj *)
        Src:  16 (Expr: UnaryOperator, Type : MyObj *)
    OriginFlow: 
        Dest: 18 (Expr: UnaryOperator, Type : MyObj &)
        Src:  17 (Expr: ImplicitCastExpr, Type : MyObj *)
    Expire (2 (Path: obj))
    Expire (5 (Path: pp))
    Expire (6 (Path: pp))
    ExpireOrigin (10 (Decl: pp, Type : MyObj **))
    Expire (3 (Path: p))
    Expire (4 (Path: p))
    ExpireOrigin (5 (Decl: p, Type : MyObj *))
  End of Block 
```

`pp` has two origins (one per indirection level), both with unique OriginIDs 
tied to pp's `ValueDecl`:
```
10 (Decl: pp, Type: MyObj **)  // outer, holds L_p
11 (Decl: pp, Type: MyObj *)    // inner, holds L_obj (propagated via flow from 
p)
```

These are pp's private tracking slots, not shared with p's origin (ID=5). When 
pp dies, both become unreachable. Without clearing origin 11, the checker finds 
it still live and holding L_obj at Expire(obj), causing a false positive.

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

Reply via email to