[llvm] bccd1b9 - [StringMap] Invalidate iterators in remove() (#202520)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 9 01:12:39 PDT 2026


Author: Fangrui Song
Date: 2026-06-09T08:12:33Z
New Revision: bccd1b9cb744e5dd96ee59baa4bf4583457feea3

URL: https://github.com/llvm/llvm-project/commit/bccd1b9cb744e5dd96ee59baa4bf4583457feea3
DIFF: https://github.com/llvm/llvm-project/commit/bccd1b9cb744e5dd96ee59baa4bf4583457feea3.diff

LOG: [StringMap] Invalidate iterators in remove() (#202520)

erase() bumps the epoch to invalidate iterators (#202237), but the
lower-level remove() — which detaches an entry without destroying it,
used
by ValueSymbolTable via Value::setName() — did not. Move the
incrementEpoch() into remove() so remove-while-iterating fails fast
under
LLVM_ENABLE_ABI_BREAKING_CHECKS too.

Aided by Claude Opus 4.8

Added: 
    

Modified: 
    llvm/include/llvm/ADT/StringMap.h
    llvm/lib/Transforms/IPO/StripSymbols.cpp
    llvm/unittests/ADT/StringMapTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ADT/StringMap.h b/llvm/include/llvm/ADT/StringMap.h
index 5ce35f5c7a6ce..77853f240fc10 100644
--- a/llvm/include/llvm/ADT/StringMap.h
+++ b/llvm/include/llvm/ADT/StringMap.h
@@ -430,11 +430,13 @@ class LLVM_ALLOCATORHOLDER_EMPTYBASE StringMap
 
   /// remove - Remove the specified key/value pair from the map, but do not
   /// erase it.  This aborts if the key is not in the map.
-  void remove(MapEntryTy *KeyValue) { RemoveKey(KeyValue); }
+  void remove(MapEntryTy *KeyValue) {
+    incrementEpoch();
+    RemoveKey(KeyValue);
+  }
 
   void erase(iterator I) {
     MapEntryTy &V = *I;
-    incrementEpoch();
     remove(&V);
     V.Destroy(getAllocator());
   }

diff  --git a/llvm/lib/Transforms/IPO/StripSymbols.cpp b/llvm/lib/Transforms/IPO/StripSymbols.cpp
index ec701b6d0037b..5e00ef468f9ef 100644
--- a/llvm/lib/Transforms/IPO/StripSymbols.cpp
+++ b/llvm/lib/Transforms/IPO/StripSymbols.cpp
@@ -22,6 +22,7 @@
 #include "llvm/Transforms/IPO/StripSymbols.h"
 
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DerivedTypes.h"
@@ -76,15 +77,17 @@ static void RemoveDeadConstant(Constant *C) {
 // Strip the symbol table of its names.
 //
 static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
-  for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) {
-    Value *V = VI->getValue();
-    ++VI;
-    if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()) {
+  // Collect the values to rename first: setName("") removes the value from the
+  // symbol table, which invalidates iterators into it.
+  SmallVector<Value *, 0> ToStrip;
+  for (const ValueName &VN : ST) {
+    Value *V = VN.getValue();
+    if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage())
       if (!PreserveDbgInfo || !V->getName().starts_with("llvm.dbg"))
-        // Set name to "", removing from symbol table!
-        V->setName("");
-    }
+        ToStrip.push_back(V);
   }
+  for (Value *V : ToStrip)
+    V->setName("");
 }
 
 // Strip any named types of their names.

diff  --git a/llvm/unittests/ADT/StringMapTest.cpp b/llvm/unittests/ADT/StringMapTest.cpp
index d350b46525ba0..6b357d20504e1 100644
--- a/llvm/unittests/ADT/StringMapTest.cpp
+++ b/llvm/unittests/ADT/StringMapTest.cpp
@@ -785,6 +785,17 @@ TEST(StringMapCustomTest, EraseInvalidatesIterators) {
   EXPECT_DEATH((void)It->second, "invalid iterator access");
 }
 
+TEST(StringMapCustomTest, RemoveInvalidatesIterators) {
+  StringMap<int> Map;
+  Map["a"] = 1;
+  Map["b"] = 2;
+  auto It = Map.find("a");
+  auto *Entry = &*Map.find("b");
+  Map.remove(Entry);
+  Entry->Destroy(Map.getAllocator());
+  EXPECT_DEATH((void)It->second, "invalid iterator access");
+}
+
 TEST(StringMapCustomTest, ClearInvalidatesIterators) {
   StringMap<int> Map;
   Map["a"] = 1;


        


More information about the llvm-commits mailing list