================
@@ -272,28 +272,109 @@ bool isUniquePtrRelease(const CXXMethodDecl &MD) {
          MD.getNumParams() == 0 && isStdUniquePtr(*MD.getParent());
 }
 
+/// Returns the set of methods that invalidate iterators for the given
+/// container, or nullptr if the container is not recognized.
+///
+/// Iterator invalidation rules per the C++ standard:
+/// https://en.cppreference.com/w/cpp/container#Iterator_invalidation
+static const llvm::StringSet<> *
+getInvalidatingMethods(StringRef ContainerName) {
+  static const llvm::StringSet<> Vector = {// Insertion
+                                           "insert", "emplace", "emplace_back",
+                                           "push_back", "insert_range",
+                                           "append_range",
+                                           // Removal
+                                           "pop_back", "erase", "clear",
+                                           // Memory management
+                                           "reserve", "resize", 
"shrink_to_fit",
+                                           // Assignment
+                                           "swap", "assign", "assign_range"};
+
+  static const llvm::StringSet<> Deque = {
+      // Insertion
+      "insert", "emplace", "emplace_back", "push_back", "push_front",
+      "emplace_front", "insert_range", "append_range",
+      // Removal
+      "pop_back", "pop_front", "erase", "clear",
+      // Memory management
+      "resize", "shrink_to_fit",
+      // Assignment
+      "swap", "assign", "assign_range"};
+
+  static const llvm::StringSet<> String = {
+      // Insertion
+      "insert", "push_back", "append", "replace", "replace_with_range",
+      "insert_range", "append_range",
+      // Removal
+      "pop_back", "erase", "clear",
+      // Memory management
+      "reserve", "resize", "resize_and_overwrite", "shrink_to_fit",
+      // Assignment
+      "swap", "assign", "assign_range"};
+
+  // FIXME: Add queue and stack and check for underlying container
+  // (e.g. no invalidation for std::list).
+  static const llvm::StringSet<> PriorityQueue = {// Insertion
+                                                  "push", "emplace",
+                                                  "push_range",
+                                                  // Removal
+                                                  "pop",
+                                                  // Assignment
+                                                  "swap"};
+
+  static const llvm::StringSet<> Associative = {// Removal
+                                                "clear",
+                                                // Assignment
+                                                "swap"};
+
+  // For unordered associative containers, `try_emplace` and `insert_or_assign`
+  // only exist on `unordered_map`. Listing them here is harmless since the
+  // methods won't be found on other types.
+  static const llvm::StringSet<> UnorderedAssociative = {
+      // Insertion
+      "insert", "emplace", "emplace_hint", "try_emplace", "insert_or_assign",
+      "insert_range", "merge",
+      // Removal
+      "clear",
+      // Hash policy
+      "rehash", "reserve",
+      // Assignment
+      "swap"};
+
+  // For `flat_*` container adaptors, `try_emplace` and `insert_or_assign`
+  // only exist on `flat_map`. Listing them here is harmless since the methods
+  // won't be found on other types.
+  static const llvm::StringSet<> Flat = {// Insertion
+                                         "insert", "emplace", "emplace_hint",
+                                         "try_emplace", "insert_or_assign",
+                                         "insert_range", "merge",
+                                         // Removal
+                                         "extract", "erase", "clear",
+                                         // Assignment
+                                         "swap", "replace"};
+
+  return llvm::StringSwitch<const llvm::StringSet<> *>(ContainerName)
+      .Case("vector", &Vector)
+      .Case("basic_string", &String)
+      .Case("deque", &Deque)
+      .Case("priority_queue", &PriorityQueue)
+      .Cases({"set", "multiset", "map", "multimap"}, &Associative)
+      .Cases({"unordered_set", "unordered_multiset", "unordered_map",
+              "unordered_multimap"},
+             &UnorderedAssociative)
+      .Cases({"flat_map", "flat_set", "flat_multimap", "flat_multiset"}, &Flat)
+      .Default(nullptr);
+}
+
 bool isContainerInvalidationMethod(const CXXMethodDecl &MD) {
   const CXXRecordDecl *RD = MD.getParent();
   if (!isInStlNamespace(RD))
     return false;
 
   StringRef ContainerName = getName(*RD);
-  static const llvm::StringSet<> Containers = {
-      // Sequence
-      "vector", "basic_string", "deque",
-      // Adaptors
-      // FIXME: Add queue and stack and check for underlying container (e.g. no
-      // invalidation for std::list).
-      "priority_queue",
-      // Associative
-      "set", "multiset", "map", "multimap",
-      // Unordered Associative
-      "unordered_set", "unordered_multiset", "unordered_map",
-      "unordered_multimap",
-      // C++23 Flat
-      "flat_map", "flat_set", "flat_multimap", "flat_multiset"};
-
-  if (!Containers.contains(ContainerName))
+  const llvm::StringSet<> *InvalidatingMethods =
+      getInvalidatingMethods(ContainerName);
----------------
usx95 wrote:

I think we can just inline the function here.

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

Reply via email to