diff --git a/llvm/include/llvm/ADT/IntervalMap.h b/llvm/include/llvm/ADT/IntervalMap.h --- a/llvm/include/llvm/ADT/IntervalMap.h +++ b/llvm/include/llvm/ADT/IntervalMap.h @@ -1042,6 +1042,17 @@ new(&rootLeaf()) RootLeaf(); } + // The default copy/move constructors and assignment operators would perform + // a shallow copy, leading to an incorrect internal state. To prevent + // accidental use, explicitly delete these operators. + // If necessary, implement them to perform a deep copy. + IntervalMap(const IntervalMap &Other) = delete; + IntervalMap(IntervalMap &&Other) = delete; + // Note: these are already implicitly deleted, because RootLeaf (union + // member) has a non-trivial assignment operator (because of std::pair). + IntervalMap &operator=(const IntervalMap &Other) = delete; + IntervalMap &operator=(IntervalMap &&Other) = delete; + ~IntervalMap() { clear(); rootLeaf().~RootLeaf(); diff --git a/llvm/unittests/ADT/IntervalMapTest.cpp b/llvm/unittests/ADT/IntervalMapTest.cpp --- a/llvm/unittests/ADT/IntervalMapTest.cpp +++ b/llvm/unittests/ADT/IntervalMapTest.cpp @@ -8,6 +8,7 @@ #include "llvm/ADT/IntervalMap.h" #include "gtest/gtest.h" +#include using namespace llvm; @@ -17,6 +18,15 @@ typedef IntervalMap> UUHalfOpenMap; +static_assert(!std::is_copy_constructible::value, + "IntervalMap copy constructor should be deleted"); +static_assert(!std::is_move_constructible::value, + "IntervalMap move constructor should be deleted"); +static_assert(!std::is_copy_assignable::value, + "IntervalMap copy assignment should be deleted"); +static_assert(!std::is_move_assignable::value, + "IntervalMap move assignment should be deleted"); + // Empty map tests TEST(IntervalMapTest, EmptyMap) { UUMap::Allocator allocator;