================
@@ -277,23 +277,85 @@ bool isContainerInvalidationMethod(const CXXMethodDecl
&MD) {
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))
+ // `pop_back` is excluded: it only invalidates references to the removed
+ // element, not to other elements.
+ // https://en.cppreference.com/w/cpp/container/vector/pop_back.html
+ static const llvm::StringSet<> Vector = {// Insertion
+ "insert", "emplace", "emplace_back",
+ "push_back", "insert_range",
+ "append_range",
+ // Removal
+ "erase", "clear",
+ // Memory management
+ "reserve", "resize",
"shrink_to_fit",
+ // Assignment
+ "assign", "assign_range"};
+
+ // `pop_*` methods are excluded: they only invalidate references to the
+ // removed element, not to other elements.
+ // https://en.cppreference.com/w/cpp/container/deque.html#Invalidation_notes
+ static const llvm::StringSet<> Deque = {// Insertion
+ "insert", "emplace", "insert_range",
+ // Removal
+ "erase", "clear",
+ // Memory management
+ "resize", "shrink_to_fit",
+ // Assignment
+ "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"};
+
+ // `erase` and `extract` are excluded: they only affect the removed element,
+ // not to other elements.
+ // https://en.cppreference.com/w/cpp/container/map/erase.html
+ // https://en.cppreference.com/w/cpp/container/map/extract.html
+ static const llvm::StringSet<> NodeBased = {// Removal
+ "clear"};
+
+ // 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
+ "replace"};
+
+ const StringRef ContainerName = getName(*RD);
+ const llvm::StringSet<> *InvalidatingMethods =
----------------
usx95 wrote:
Not particular to this PR but I expect this function
`isContainerInvalidationMethod`and specially this `StringSwitch` to be very
hot. Consider adding a TODO to cache this by `CXXMethodDecl` pointer in case
this becomes a bottleneck.
https://github.com/llvm/llvm-project/pull/183000
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits