diff --git a/clang/include/clang/AST/UnresolvedSet.h b/clang/include/clang/AST/UnresolvedSet.h --- a/clang/include/clang/AST/UnresolvedSet.h +++ b/clang/include/clang/AST/UnresolvedSet.h @@ -114,9 +114,17 @@ I.I->set(New, AS); } - void erase(unsigned I) { decls()[I] = decls().pop_back_val(); } + void erase(unsigned I) { + auto val = decls().pop_back_val(); + if (I < size()) + decls()[I] = val; + } - void erase(iterator I) { *I.I = decls().pop_back_val(); } + void erase(iterator I) { + auto val = decls().pop_back_val(); + if (I != end()) + *I.I = val; + } void setAccess(iterator I, AccessSpecifier AS) { I.I->setAccess(AS); } diff --git a/clang/unittests/AST/CMakeLists.txt b/clang/unittests/AST/CMakeLists.txt --- a/clang/unittests/AST/CMakeLists.txt +++ b/clang/unittests/AST/CMakeLists.txt @@ -35,6 +35,7 @@ StructuralEquivalenceTest.cpp TemplateNameTest.cpp TypePrinterTest.cpp + UnresolvedSetTest.cpp ) clang_target_link_libraries(ASTTests diff --git a/clang/unittests/AST/UnresolvedSetTest.cpp b/clang/unittests/AST/UnresolvedSetTest.cpp new file mode 100644 --- /dev/null +++ b/clang/unittests/AST/UnresolvedSetTest.cpp @@ -0,0 +1,115 @@ +#include "clang/AST/UnresolvedSet.h" +#include "gtest/gtest.h" + +namespace clang { +class NamedDecl { + int dummy; + +public: + NamedDecl() {} +}; +} // namespace clang + +using namespace clang; + +class UnresolvedSetTest : public ::testing::Test { +protected: + NamedDecl n0, n1, n2, n3; + UnresolvedSet<2> set; + + void SetUp() override { + set.addDecl(&n0); + set.addDecl(&n1); + set.addDecl(&n2); + set.addDecl(&n3); + } +}; + +TEST_F(UnresolvedSetTest, Size) { EXPECT_EQ(set.size(), 4u); } + +TEST_F(UnresolvedSetTest, ArrayOperator) { + EXPECT_EQ(set[0].getDecl(), &n0); + EXPECT_EQ(set[1].getDecl(), &n1); + EXPECT_EQ(set[2].getDecl(), &n2); + EXPECT_EQ(set[3].getDecl(), &n3); +} + +TEST_F(UnresolvedSetTest, EraseIntegerFromStart) { + set.erase(0); + EXPECT_EQ(set.size(), 3u); + EXPECT_EQ(set[0].getDecl(), &n3); + EXPECT_EQ(set[1].getDecl(), &n1); + EXPECT_EQ(set[2].getDecl(), &n2); + + set.erase(0); + EXPECT_EQ(set.size(), 2u); + EXPECT_EQ(set[0].getDecl(), &n2); + EXPECT_EQ(set[1].getDecl(), &n1); + + set.erase(0); + EXPECT_EQ(set.size(), 1u); + EXPECT_EQ(set[0].getDecl(), &n1); + + set.erase(0); + EXPECT_EQ(set.size(), 0u); +} + +TEST_F(UnresolvedSetTest, EraseIntegerFromEnd) { + set.erase(3); + EXPECT_EQ(set.size(), 3u); + EXPECT_EQ(set[0].getDecl(), &n0); + EXPECT_EQ(set[1].getDecl(), &n1); + EXPECT_EQ(set[2].getDecl(), &n2); + + set.erase(2); + EXPECT_EQ(set.size(), 2u); + EXPECT_EQ(set[0].getDecl(), &n0); + EXPECT_EQ(set[1].getDecl(), &n1); + + set.erase(1); + EXPECT_EQ(set.size(), 1u); + EXPECT_EQ(set[0].getDecl(), &n0); + + set.erase(0); + EXPECT_EQ(set.size(), 0u); +} + +TEST_F(UnresolvedSetTest, EraseIteratorFromStart) { + set.erase(set.begin()); + EXPECT_EQ(set.size(), 3u); + EXPECT_EQ(set[0].getDecl(), &n3); + EXPECT_EQ(set[1].getDecl(), &n1); + EXPECT_EQ(set[2].getDecl(), &n2); + + set.erase(set.begin()); + EXPECT_EQ(set.size(), 2u); + EXPECT_EQ(set[0].getDecl(), &n2); + EXPECT_EQ(set[1].getDecl(), &n1); + + set.erase(set.begin()); + EXPECT_EQ(set.size(), 1u); + EXPECT_EQ(set[0].getDecl(), &n1); + + set.erase(set.begin()); + EXPECT_EQ(set.size(), 0u); +} + +TEST_F(UnresolvedSetTest, EraseIteratorFromEnd) { + set.erase(--set.end()); + EXPECT_EQ(set.size(), 3u); + EXPECT_EQ(set[0].getDecl(), &n0); + EXPECT_EQ(set[1].getDecl(), &n1); + EXPECT_EQ(set[2].getDecl(), &n2); + + set.erase(--set.end()); + EXPECT_EQ(set.size(), 2u); + EXPECT_EQ(set[0].getDecl(), &n0); + EXPECT_EQ(set[1].getDecl(), &n1); + + set.erase(--set.end()); + EXPECT_EQ(set.size(), 1u); + EXPECT_EQ(set[0].getDecl(), &n0); + + set.erase(--set.end()); + EXPECT_EQ(set.size(), 0u); +}