diff options
author | Ryan Guo <ryanguo@modular.com> | 2023-02-13 20:06:44 -0800 |
---|---|---|
committer | Ryan Guo <ryanguo@modular.com> | 2023-02-17 08:32:29 -0800 |
commit | 132003603ae3453bc385ffd5ed53f5e8057ae1bc (patch) | |
tree | adf479054954e92863f6d53d0ff10077fe14d512 | |
parent | 2b51c8cd2ac6b9a6a5b713700c8299954980242d (diff) | |
download | llvm-132003603ae3453bc385ffd5ed53f5e8057ae1bc.zip llvm-132003603ae3453bc385ffd5ed53f5e8057ae1bc.tar.gz llvm-132003603ae3453bc385ffd5ed53f5e8057ae1bc.tar.bz2 |
[ADT] Add `at` method (assertive lookup) to DenseMap and StringMap
This patch makes it easier for users when they want to use validated
lookup on DenseMap/StringMap as a composable C++ expression. For
instance:
```
// instead of
if (auto val = map.lookup(key))
return val;
assert("...");
// we can write
return map.at(key);
```
Differential Revision: https://reviews.llvm.org/D143976
-rw-r--r-- | llvm/include/llvm/ADT/DenseMap.h | 8 | ||||
-rw-r--r-- | llvm/include/llvm/ADT/StringMap.h | 14 | ||||
-rw-r--r-- | llvm/unittests/ADT/DenseMapTest.cpp | 8 | ||||
-rw-r--r-- | llvm/unittests/ADT/StringMapTest.cpp | 16 |
4 files changed, 43 insertions, 3 deletions
diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h index 9da6f479..12a6673 100644 --- a/llvm/include/llvm/ADT/DenseMap.h +++ b/llvm/include/llvm/ADT/DenseMap.h @@ -201,6 +201,14 @@ public: return ValueT(); } + /// at - Return the entry for the specified key, or abort if no such + /// entry exists. + const ValueT &at(const_arg_type_t<KeyT> Val) const { + auto Iter = this->find(std::move(Val)); + assert(Iter != this->end() && "DenseMap::at failed due to a missing key"); + return Iter->second; + } + // Inserts key,value pair into the map if the key isn't already in the map. // If the key is already in the map, it returns false and doesn't update the // value. diff --git a/llvm/include/llvm/ADT/StringMap.h b/llvm/include/llvm/ADT/StringMap.h index 0849bef..443714c 100644 --- a/llvm/include/llvm/ADT/StringMap.h +++ b/llvm/include/llvm/ADT/StringMap.h @@ -231,12 +231,20 @@ public: /// lookup - Return the entry for the specified key, or a default /// constructed value if no such entry exists. ValueTy lookup(StringRef Key) const { - const_iterator it = find(Key); - if (it != end()) - return it->second; + const_iterator Iter = find(Key); + if (Iter != end()) + return Iter->second; return ValueTy(); } + /// at - Return the entry for the specified key, or abort if no such + /// entry exists. + const ValueTy &at(StringRef Val) const { + auto Iter = this->find(std::move(Val)); + assert(Iter != this->end() && "StringMap::at failed due to a missing key"); + return Iter->second; + } + /// Lookup the ValueTy for the \p Key, or create a default constructed value /// if the key is not in the map. ValueTy &operator[](StringRef Key) { return try_emplace(Key).first->second; } diff --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp index 2d01316..ba4e764 100644 --- a/llvm/unittests/ADT/DenseMapTest.cpp +++ b/llvm/unittests/ADT/DenseMapTest.cpp @@ -125,6 +125,10 @@ TYPED_TEST(DenseMapTest, EmptyIntMapTest) { EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.end()); EXPECT_EQ(typename TypeParam::mapped_type(), this->Map.lookup(this->getKey())); + + // LookupOrTrap tests + EXPECT_DEATH({ this->Map.at(this->getKey()); }, + "DenseMap::at failed due to a missing key"); } // Constant map tests @@ -156,6 +160,10 @@ TYPED_TEST(DenseMapTest, SingleEntryMapTest) { EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.begin()); EXPECT_EQ(this->getValue(), this->Map.lookup(this->getKey())); EXPECT_EQ(this->getValue(), this->Map[this->getKey()]); + + // LookupOrTrap tests + EXPECT_DEATH({ this->Map.at(this->getKey(1)); }, + "DenseMap::at failed due to a missing key"); } // Test clear() method diff --git a/llvm/unittests/ADT/StringMapTest.cpp b/llvm/unittests/ADT/StringMapTest.cpp index f40f22a..25562d3 100644 --- a/llvm/unittests/ADT/StringMapTest.cpp +++ b/llvm/unittests/ADT/StringMapTest.cpp @@ -205,6 +205,22 @@ TEST_F(StringMapTest, CopyCtorTest) { EXPECT_EQ(5, Map2.lookup("funf")); } +TEST_F(StringMapTest, LookupOrTrapTest) { + llvm::StringMap<int> Map; + + // key not found on empty map + EXPECT_DEATH({ Map.at("a"); }, "StringMap::at failed due to a missing key"); + + // keys both found and not found on non-empty map + Map["a"] = 1; + Map["b"] = 2; + Map["c"] = 3; + EXPECT_EQ(1, Map.at("a")); + EXPECT_EQ(2, Map.at("b")); + EXPECT_EQ(3, Map.at("c")); + EXPECT_DEATH({ Map.at("d"); }, "StringMap::at failed due to a missing key"); +} + // A more complex iteration test. TEST_F(StringMapTest, IterationTest) { bool visited[100]; |