[clang] [LifetimeSafety] Detect iterator invalidation through container aliases (PR #195231)

Zeyi Xu via cfe-commits cfe-commits at lists.llvm.org
Fri May 1 00:53:59 PDT 2026


================
@@ -345,37 +384,41 @@ void Invalidate1Use2IsOk() {
     auto it = s.strings1.begin();
     s.strings2.push_back("1");
     *it;
-}void Invalidate1Use2ViaRefIsOk() {
+}
+
+// FIXME: Requires field-sensitive AccessPaths to fix.
+void Invalidate1Use2ViaRefIsOk() {
     S s;
-    auto it = s.strings2.begin();
+    auto it = s.strings2.begin(); // expected-warning {{object whose reference is captured is later invalidated}}
     auto& strings2 = s.strings2;
-    strings2.push_back("1");
-    *it;
+    strings2.push_back("1");      // expected-note {{invalidated here}}
+    *it;                          // expected-note {{later used here}}
 }
 void Invalidate1UseSIsOk() {
   S s;
   S* p = &s;
   s.strings2.push_back("1");
   (void)*p;
 }
+// FIXME: Distinguish owner-borrow from content-borrow.
 void PointerToContainerIsOk() {
   std::vector<std::string> s;
-  std::vector<std::string>* p = &s;
-  p->push_back("1");
-  (void)*p;
+  std::vector<std::string>* p = &s; // expected-warning {{object whose reference is captured is later invalidated}}
+  p->push_back("1");                // expected-note {{invalidated here}}
+  (void)*p;                         // expected-note {{later used here}}
 }
 void IteratorFromPointerToContainerIsInvalidated() {
-  // FIXME: Detect this.
   std::vector<std::string> s;
-  std::vector<std::string>* p = &s;
+  std::vector<std::string>* p = &s; // expected-warning {{object whose reference is captured is later invalidated}}
   auto it = p->begin();
-  p->push_back("1");
-  *it;
+  p->push_back("1");                // expected-note {{invalidated here}}
+  *it;                              // expected-note {{later used here}}
 }
+// FIXME: `isContainerInvalidationMethod` treats `operator=` as always invalidating.
----------------
zeyi2 wrote:

>From what I see this is likely an existing bug/limitation unrelated to changes in this patch, though I haven't fully verified this.

https://github.com/llvm/llvm-project/blob/8eff63f6e78c89be81e70f8600672f292d6f3731/clang/lib/Analysis/LifetimeSafety/Origins.cpp#L103-L121

It doesn't check `isGslOwnerType`, so `hasOrigins(std::string)` returns `false`. This causes the `OO_Equal` in `VisitCXXOperatorCallExpr` to be skipped.

Happy to dive deeper and send a follow-up PR to fix this if you'd like.

https://github.com/llvm/llvm-project/pull/195231


More information about the cfe-commits mailing list