================
@@ -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);
----------------
Xazax-hun wrote:
I wonder if the calling code becomes simpler if we return an empty set instead
of a null pointer.
https://github.com/llvm/llvm-project/pull/183000
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits