================
@@ -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:

For the test case:

```cpp
void multi_level_pointer_in_loop_2() {
  MyObj obj;
  MyObj* p;
  for (int i = 0; i < 10; ++i) {
    MyObj** pp;
    pp = &p;
    (void)**pp;
  }
  (void)*p;
}
```

Debug output:

```
  Block B3:
    ...
    Expire (2 (Path: pp))
    Expire (3 (Path: pp))
    ExpireOrigin (6 (Decl: pp, Type : MyObj **))
    ExpireOrigin (7 (Decl: pp, Type : MyObj *))
  Block ...:
    ...
  Block B1:
    ...
    Expire (1 (Path: p))
    Expire (5 (Path: p))
    ExpireOrigin (2 (Decl: p, Type : MyObj *))
```

Even though we go through the list, we don't emit expire facts for `p`'s 
origins, the list only contains origins private to `pp`. Origin 7 `(Decl: pp, 
Type: MyObj *)` is pp's own inner tracking slot, distinct from origin 2 `(Decl: 
p, Type: MyObj *)`. The dataflow copies loans from p's origin into pp's inner 
origin via `OriginFlowFact`, but they remain separate origin IDs. Expiring 7 
does not affect 2.

That said, I may be missing the semantic issue you're pointing out. Could you 
elaborate on what "does not reflect the language semantics" means here? Is 
there a concrete scenario where expiring pp's inner origins would produce a 
wrong result?

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