aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Guo <ryanguo@modular.com>2023-02-13 20:06:44 -0800
committerRyan Guo <ryanguo@modular.com>2023-02-17 08:32:29 -0800
commit132003603ae3453bc385ffd5ed53f5e8057ae1bc (patch)
treeadf479054954e92863f6d53d0ff10077fe14d512
parent2b51c8cd2ac6b9a6a5b713700c8299954980242d (diff)
downloadllvm-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.h8
-rw-r--r--llvm/include/llvm/ADT/StringMap.h14
-rw-r--r--llvm/unittests/ADT/DenseMapTest.cpp8
-rw-r--r--llvm/unittests/ADT/StringMapTest.cpp16
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];