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

Utkarsh Saxena via cfe-commits cfe-commits at lists.llvm.org
Fri May 1 04:47:04 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.
----------------
usx95 wrote:

This is indeed a prior limitation but it is not related to origins of `std::string`. The problem is the range based `for`loop here which expands to using iterators (`subdirs.begin()`) and using them to iterate the vector.

The invalidation by `operator=` is indeed correct. It would invalidate pre-existing `char*` from the string elements.

The problem is invalidating content of strings (via assignment) does not invalidate the iterator to the outer vector. And we cannot differentiate between them,

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


More information about the cfe-commits mailing list