From 1e6377ab554f06c533a0e2b30d29794e5d0100f6 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Tue, 21 Oct 2025 17:55:10 -0700 Subject: [PATCH 01/22] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20?= =?UTF-8?q?changes=20to=20main=20this=20commit=20is=20based=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.7 [skip ci] --- llvm/include/llvm/Support/GlobPattern.h | 22 ++++--- llvm/lib/Support/GlobPattern.cpp | 67 +++++++++++++++++++--- llvm/unittests/Support/GlobPatternTest.cpp | 66 +++++++++++++++++++++ 3 files changed, 140 insertions(+), 15 deletions(-) diff --git a/llvm/include/llvm/Support/GlobPattern.h b/llvm/include/llvm/Support/GlobPattern.h index c1b44849b9794..8b8ac89304e31 100644 --- a/llvm/include/llvm/Support/GlobPattern.h +++ b/llvm/include/llvm/Support/GlobPattern.h @@ -63,22 +63,30 @@ class GlobPattern { // Returns true for glob pattern "*". Can be used to avoid expensive // preparation/acquisition of the input for match(). bool isTrivialMatchAll() const { - if (!Prefix.empty()) + if (PrefixSize) return false; - if (!Suffix.empty()) + if (SuffixSize) return false; if (SubGlobs.size() != 1) return false; return SubGlobs[0].getPat() == "*"; } - StringRef prefix() const { return Prefix; } - StringRef suffix() const { return Suffix; } + // The following functions are just shortcuts for faster matching. They are + // conservative to simplify implementations. -private: - StringRef Prefix; - StringRef Suffix; + // Returns plain prefix of the pattern. + StringRef prefix() const { return Pattern.take_front(PrefixSize); } + // Returns plain suffix of the pattern. + StringRef suffix() const { return Pattern.take_back(SuffixSize); } + // Returns the longest plain substring of the pattern between prefix and + // suffix. + StringRef longest_substr() const; +private: + StringRef Pattern; + size_t PrefixSize = 0; + size_t SuffixSize = 0; struct SubGlobPattern { /// \param Pat the pattern to match against LLVM_ABI static Expected create(StringRef Pat); diff --git a/llvm/lib/Support/GlobPattern.cpp b/llvm/lib/Support/GlobPattern.cpp index 0ecf47dc1d3d1..2715229c65be1 100644 --- a/llvm/lib/Support/GlobPattern.cpp +++ b/llvm/lib/Support/GlobPattern.cpp @@ -132,24 +132,70 @@ parseBraceExpansions(StringRef S, std::optional MaxSubPatterns) { return std::move(SubPatterns); } +static StringRef maxPlainSubstring(StringRef S) { + StringRef Best; + while (!S.empty()) { + size_t PrefixSize = S.find_first_of("?*[{\\"); + if (PrefixSize == std::string::npos) + PrefixSize = S.size(); + + if (Best.size() < PrefixSize) + Best = S.take_front(PrefixSize); + + S = S.drop_front(PrefixSize); + + // It's impossible, as the first and last characters of the input string + // must be Glob special characters, otherwise they would be parts of + // the prefix or the suffix. + assert(!S.empty()); + + switch (S.front()) { + case '\\': + S = S.drop_front(2); + break; + case '[': { + // Drop '[' and the first character which can be ']'. + S = S.drop_front(2); + size_t EndBracket = S.find_first_of("]"); + // Should not be possible, SubGlobPattern::create should fail on invalid + // pattern before we get here. + assert(EndBracket != std::string::npos); + S = S.drop_front(EndBracket + 1); + break; + } + case '{': + // TODO: implement. + // Fallback to whatever is best for now. + return Best; + default: + S = S.drop_front(1); + } + } + + return Best; +} + Expected GlobPattern::create(StringRef S, std::optional MaxSubPatterns) { GlobPattern Pat; + Pat.Pattern = S; // Store the prefix that does not contain any metacharacter. - size_t PrefixSize = S.find_first_of("?*[{\\"); - Pat.Prefix = S.substr(0, PrefixSize); - if (PrefixSize == std::string::npos) + Pat.PrefixSize = S.find_first_of("?*[{\\"); + if (Pat.PrefixSize == std::string::npos) { + Pat.PrefixSize = S.size(); return Pat; - S = S.substr(PrefixSize); + } + S = S.substr(Pat.PrefixSize); // Just in case we stop on unmatched opening brackets. size_t SuffixStart = S.find_last_of("?*[]{}\\"); assert(SuffixStart != std::string::npos); if (S[SuffixStart] == '\\') ++SuffixStart; - ++SuffixStart; - Pat.Suffix = S.substr(SuffixStart); + if (SuffixStart < S.size()) + ++SuffixStart; + Pat.SuffixSize = S.size() - SuffixStart; S = S.substr(0, SuffixStart); SmallVector SubPats; @@ -199,10 +245,15 @@ GlobPattern::SubGlobPattern::create(StringRef S) { return Pat; } +StringRef GlobPattern::longest_substr() const { + return maxPlainSubstring( + Pattern.drop_front(PrefixSize).drop_back(SuffixSize)); +} + bool GlobPattern::match(StringRef S) const { - if (!S.consume_front(Prefix)) + if (!S.consume_front(prefix())) return false; - if (!S.consume_back(Suffix)) + if (!S.consume_back(suffix())) return false; if (SubGlobs.empty() && S.empty()) return true; diff --git a/llvm/unittests/Support/GlobPatternTest.cpp b/llvm/unittests/Support/GlobPatternTest.cpp index 58fd7678131c6..872a21e948d7a 100644 --- a/llvm/unittests/Support/GlobPatternTest.cpp +++ b/llvm/unittests/Support/GlobPatternTest.cpp @@ -329,6 +329,72 @@ TEST_F(GlobPatternTest, PrefixSuffix) { EXPECT_EQ("cd", Pat->suffix()); } +TEST_F(GlobPatternTest, Substr) { + auto Pat = GlobPattern::create(""); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("", Pat->longest_substr()); + + Pat = GlobPattern::create("abcd"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcd"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("", Pat->longest_substr()); + + Pat = GlobPattern::create("*abcd"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("", Pat->longest_substr()); + + Pat = GlobPattern::create("abcd*"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bc*d"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bc", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bc*def*g"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("def", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcd*ef*g"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcd", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcd*efg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcd", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcd[ef]g*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcd", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bc[d]efg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("efg", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bc[]]efg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("efg", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcde\\fg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcde", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcde\\[fg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcde", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcde?fg*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcde", Pat->longest_substr()); + + Pat = GlobPattern::create("a*bcdef{g}*h"); + ASSERT_TRUE((bool)Pat); + EXPECT_EQ("bcdef", Pat->longest_substr()); +} + TEST_F(GlobPatternTest, Pathological) { std::string P, S(40, 'a'); StringRef Pieces[] = {"a*", "[ba]*", "{b*,a*}*"}; From 40ba10a6096b7183ab90cee58486ef41de096e85 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Tue, 21 Oct 2025 18:03:03 -0700 Subject: [PATCH 02/22] spelling Created using spr 1.3.7 --- llvm/include/llvm/Support/RadixTree.h | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/llvm/include/llvm/Support/RadixTree.h b/llvm/include/llvm/Support/RadixTree.h index c9bed5ca6ba1b..05697fc267628 100644 --- a/llvm/include/llvm/Support/RadixTree.h +++ b/llvm/include/llvm/Support/RadixTree.h @@ -65,8 +65,8 @@ namespace llvm { /// The `RadixTree` takes ownership of the `KeyType` and `T` objects /// inserted into it. When an element is removed or the tree is destroyed, /// these objects will be destructed. -/// However, if `KeyType` is a reference-like type, e.g. StrignRef or range, -/// User must guaranty that destination has lifetime longer than the tree. +/// However, if `KeyType` is a reference-like type, e.g. StringRef or range, +/// User must guarantee that destination has lifetime longer than the tree. template class RadixTree { public: using key_type = KeyType; @@ -81,7 +81,7 @@ template class RadixTree { remove_cvref_t()))>; using ContainerType = std::list; - /// Represents a internal node in the Radix Tree. + /// Represents an internal node in the Radix Tree. struct Node { KeyConstIteratorRangeType Key = {KeyConstIteratorType{}, KeyConstIteratorType{}}; @@ -110,12 +110,12 @@ template class RadixTree { Node &operator=(const Node &) = delete; const Node *findChild(const KeyConstIteratorRangeType &Key) const { - if (!Key.empty()) { - for (const auto &Child : Children) { - assert(!Child.Key.empty()); // Only root can be empty. - if (Child.KeyFront == *Key.begin()) - return &Child; - } + if (Key.empty()) + return nullptr; + for (const auto &Child : Children) { + assert(!Child.Key.empty()); // Only root can be empty. + if (Child.KeyFront == *Key.begin()) + return &Child; } return nullptr; } @@ -167,12 +167,12 @@ template class RadixTree { Key = make_range(I1, Key.end()); if (I2 != Curr->Key.end()) { - // Match is partial. Either query is too short, or there is missmatching + // Match is partial. Either query is too short, or there is mismatching // character. Split either way, and put new node in between of the // current and its children. Curr->split(I2); - // Split was caused by mismatch, we can't 'findChild' will fail. + // Split was caused by mismatch, so `findChild` will fail. break; } @@ -196,7 +196,7 @@ template class RadixTree { } /// - /// An iterator for traversing prefixes searche results. + /// An iterator for traversing prefixes search results. /// /// This iterator is used by `find_prefixes` to traverse the tree and find /// elements that are prefixes to the given key. It's a forward iterator. @@ -278,7 +278,7 @@ template class RadixTree { /// Returns the number of nodes in the tree. /// - /// This function counts all internal in the tree. It can be useful for + /// This function counts all internal nodes in the tree. It can be useful for /// understanding the memory footprint or complexity of the tree structure. size_t countNodes() const { return Root.countNodes(); } @@ -322,7 +322,7 @@ template class RadixTree { /// /// This function returns an iterator range over all elements in the tree /// whose keys are prefixes of the provided `Key`. For example, if the tree - /// contains "abcde", "abc", "abcdefgh, and `Key` is "abcde", this function + /// contains "abcde", "abc", "abcdefgh", and `Key` is "abcde", this function /// would return iterators to "abcde" and "abc". /// /// \param Key The key to search for prefixes of. From 5d58018daf347ca9496a29bc236e63e15f904a44 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 00:32:32 -0700 Subject: [PATCH 03/22] rebase Created using spr 1.3.7 --- llvm/docs/ProgrammersManual.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/llvm/docs/ProgrammersManual.rst b/llvm/docs/ProgrammersManual.rst index 9cdac9c59fa9b..26865e4f671d7 100644 --- a/llvm/docs/ProgrammersManual.rst +++ b/llvm/docs/ProgrammersManual.rst @@ -2161,6 +2161,16 @@ that are not simple pointers (use :ref:`SmallPtrSet ` for pointers). Note that ``DenseSet`` has the same requirements for the value type that :ref:`DenseMap ` has. +.. _dss_radixtree: + +llvm/ADT/RadixTree.h +^^^^^^^^^^^^^^^^^^^^ + +``RadixTree`` is a trie-based data structure that stores range like keys and +their associated values. It is particularly efficient for storing keys that +share common prefixes, as it can compress these prefixes to save memory. It +supports efficient search of matching prefixes. + .. _dss_sparseset: llvm/ADT/SparseSet.h From 1840fe0b4c3569907b020cad55a67b299e0e9bf4 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 21:03:44 -0700 Subject: [PATCH 04/22] Update llvm/docs/ProgrammersManual.rst Co-authored-by: Kazu Hirata --- llvm/docs/ProgrammersManual.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/docs/ProgrammersManual.rst b/llvm/docs/ProgrammersManual.rst index 26865e4f671d7..d99b5843c2133 100644 --- a/llvm/docs/ProgrammersManual.rst +++ b/llvm/docs/ProgrammersManual.rst @@ -2166,7 +2166,7 @@ pointers). Note that ``DenseSet`` has the same requirements for the value type llvm/ADT/RadixTree.h ^^^^^^^^^^^^^^^^^^^^ -``RadixTree`` is a trie-based data structure that stores range like keys and +``RadixTree`` is a trie-based data structure that stores range-like keys and their associated values. It is particularly efficient for storing keys that share common prefixes, as it can compress these prefixes to save memory. It supports efficient search of matching prefixes. From b24b6ddc6d1811d31b006fb14e8c872c2060a0b7 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 21:03:58 -0700 Subject: [PATCH 05/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 5dd3f0c4d1b4e..8e8506d095383 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -172,7 +172,7 @@ template class RadixTree { // current and its children. Curr->split(I2); - // Split was caused by mismatch, so `findChild` will fail. + // Split was caused by mismatch, so `findChild` would fail. break; } From f97c94ba9e83616cd25400efaa137ff7fc946688 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 21:04:14 -0700 Subject: [PATCH 06/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 8e8506d095383..dd8655244c44d 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -189,7 +189,7 @@ template class RadixTree { return *Curr; } - // `Key` a suffix of original `Key` unmatched by path from the `Root` to the + // `Key` is a suffix of original `Key` unmatched by path from the `Root` to the // `Curr`, and we have no candidate in the children to match more. Create a // new one. return Curr->Children.emplace_back(Key); From 2a13ceacd91203a133783a8336261e89046b606b Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 21:05:22 -0700 Subject: [PATCH 07/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index dd8655244c44d..b80633e419d74 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -85,7 +85,7 @@ template class RadixTree { struct Node { KeyConstIteratorRangeType Key = {KeyConstIteratorType{}, KeyConstIteratorType{}}; - std::vector Children; + SmallVector Children; /// An iterator to the value associated with this node. /// From 8e62249c96a64ba14f9a7a9b9913745230236f70 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 21:05:36 -0700 Subject: [PATCH 08/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index b80633e419d74..87a353609399a 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -112,7 +112,7 @@ template class RadixTree { const Node *findChild(const KeyConstIteratorRangeType &Key) const { if (Key.empty()) return nullptr; - for (const auto &Child : Children) { + for (const Node &Child : Children) { assert(!Child.Key.empty()); // Only root can be empty. if (Child.KeyFront == *Key.begin()) return &Child; From c1dafd2bf242c2cb02337ac34536e64bf8d9e762 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 21:06:10 -0700 Subject: [PATCH 09/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 87a353609399a..8014ea9de868a 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -209,7 +209,7 @@ template class RadixTree { : public iterator_facade_base, std::forward_iterator_tag, MappedType> { const Node *Curr = nullptr; - KeyConstIteratorRangeType Query; + KeyConstIteratorRangeType Query{}; void findNextValid() { while (Curr && Curr->Value == typename ContainerType::iterator()) From 058bd72c546958c9be8fc84317cd6bd082e0f85b Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 21:06:27 -0700 Subject: [PATCH 10/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 8014ea9de868a..64b9fa18a0d02 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -154,7 +154,7 @@ template class RadixTree { }; Node Root; // Root is always for empty range. - ContainerType Values; + ContainerType KeyValuePairs; /// Finds or creates a new tail or leaf node corresponding to the `Key`. Node &findOrCreate(KeyConstIteratorRangeType Key) { From f80e076b745812c1bb3c5e9f69c1793b724a7bc6 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 21:06:42 -0700 Subject: [PATCH 11/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 64b9fa18a0d02..00a76302f814a 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -292,7 +292,7 @@ template class RadixTree { /// Constructs and inserts a new element into the tree. /// - /// This function constructs an element in-place within the tree. If an + /// This function constructs an element in place within the tree. If an /// element with the same key already exists, the insertion fails and the /// function returns an iterator to the existing element along with `false`. /// Otherwise, the new element is inserted and the function returns an From 560207870e9b3e9daee8c4769540c0cb6c64831d Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 21:07:09 -0700 Subject: [PATCH 12/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 00a76302f814a..674f40f9f16ee 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -49,10 +49,10 @@ namespace llvm { /// Tree.emplace("grape", 3); /// /// // Find prefixes -/// for (const auto &pair : Tree.find_prefixes("grapefruit juice")) { +/// for (const auto &[Key, Value] : Tree.find_prefixes("grapefruit juice")) { /// // pair will be {"grape", 3} /// // pair will be {"grapefruit", 2} -/// llvm::outs() << pair.first << ": " << pair.second << "\n"; +/// llvm::outs() << Key << ": " << Value << "\n"; /// } /// /// // Iterate over all elements From 885ae93fead945d444fd1656da800ba1666e3097 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 21:07:27 -0700 Subject: [PATCH 13/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 674f40f9f16ee..e710b00976824 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -56,9 +56,8 @@ namespace llvm { /// } /// /// // Iterate over all elements -/// for (const auto &pair : Tree) { -/// llvm::outs() << pair.first << ": " << pair.second << "\n"; -/// } +/// for (const auto &[Key, Value] : Tree) +/// llvm::outs() << Key << ": " << Value << "\n"; /// \endcode /// /// \note From 07dfaf1d8fdbbd44a282fd696488796cdccfa84b Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 21:07:43 -0700 Subject: [PATCH 14/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index e710b00976824..23ae44b8f4a62 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -334,7 +334,7 @@ template class RadixTree { find_prefixes(const key_type &Key) const { return iterator_range{ const_prefix_iterator( - &Root, KeyConstIteratorRangeType{adl_begin(Key), adl_end(Key)}), + &Root, KeyConstIteratorRangeType(Key)), const_prefix_iterator{}}; } }; From 52c6a62ae23bf0d7db87842bc4e8b4b032cbac10 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 23:18:39 -0700 Subject: [PATCH 15/22] Update llvm/unittests/ADT/RadixTreeTest.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- llvm/unittests/ADT/RadixTreeTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/unittests/ADT/RadixTreeTest.cpp b/llvm/unittests/ADT/RadixTreeTest.cpp index c9fd44e3497ff..4a1d0b375b0d0 100644 --- a/llvm/unittests/ADT/RadixTreeTest.cpp +++ b/llvm/unittests/ADT/RadixTreeTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/ADT/RadixTreeTypeTest.cpp ------------------------===// +//===- llvm/unittest/ADT/RadixTreeTest.cpp ----------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. From 4d1c890920b24c984229ac9722953deefdfe323c Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Thu, 23 Oct 2025 23:20:04 -0700 Subject: [PATCH 16/22] comment Created using spr 1.3.7 --- llvm/unittests/ADT/RadixTreeTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/unittests/ADT/RadixTreeTest.cpp b/llvm/unittests/ADT/RadixTreeTest.cpp index 4a1d0b375b0d0..2c92e9d939852 100644 --- a/llvm/unittests/ADT/RadixTreeTest.cpp +++ b/llvm/unittests/ADT/RadixTreeTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/ADT/RadixTreeTest.cpp ----------------------------===// +//===- llvm/unittest/ADT/RadixTreeTest.cpp --------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. From 1ee09090130ade802914998fcaec7c8fe393f4dd Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 24 Oct 2025 16:17:03 -0700 Subject: [PATCH 17/22] Apply suggestion from @kazutakahirata Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 2d3a8d29491f1..bc6659983fda4 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -64,8 +64,8 @@ namespace llvm { /// The `RadixTree` takes ownership of the `KeyType` and `T` objects /// inserted into it. When an element is removed or the tree is destroyed, /// these objects will be destructed. -/// However, if `KeyType` is a reference-like type, e.g. StringRef or range, -/// User must guarantee that destination has lifetime longer than the tree. +/// However, if `KeyType` is a reference-like type, e.g., StringRef or range, +/// the user must guarantee that destination has lifetime longer than the tree. template class RadixTree { public: using key_type = KeyType; From ecd9566be4a37912bbeeff6a320517d337b2aef2 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 24 Oct 2025 16:23:35 -0700 Subject: [PATCH 18/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index bc6659983fda4..137991d941f4b 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -82,8 +82,7 @@ template class RadixTree { /// Represents an internal node in the Radix Tree. struct Node { - KeyConstIteratorRangeType Key = {KeyConstIteratorType{}, - KeyConstIteratorType{}}; + KeyConstIteratorRangeType Key{}; std::vector Children; /// An iterator to the value associated with this node. From 067b34fc0df3d078875b3124679fadfa4427c94e Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 24 Oct 2025 16:24:03 -0700 Subject: [PATCH 19/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 137991d941f4b..53474845fe40b 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -317,7 +317,7 @@ template class RadixTree { Node.Value = KeyValuePairs.begin(); else KeyValuePairs.pop_front(); - return std::make_pair(Node.Value, !HasValue); + return {Node.Value, !HasValue}; } /// From a2a8d9de4e5d6eda1e9060bbfa4bbbbf1cc6ff20 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 24 Oct 2025 16:24:20 -0700 Subject: [PATCH 20/22] Update llvm/include/llvm/ADT/RadixTree.h Co-authored-by: Kazu Hirata --- llvm/include/llvm/ADT/RadixTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 53474845fe40b..2585913581b3d 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -244,7 +244,7 @@ template class RadixTree { } public: - IteratorImpl() : Query{{}, {}} {} + IteratorImpl() = default; MappedType &operator*() const { return *Curr->Value; } From a88a2048ea97bd69e4c4553a4e8d12cd199e03b9 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 24 Oct 2025 16:41:20 -0700 Subject: [PATCH 21/22] update Created using spr 1.3.7 --- llvm/include/llvm/ADT/RadixTree.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 2585913581b3d..6d0f69dc5f957 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -82,7 +82,8 @@ template class RadixTree { /// Represents an internal node in the Radix Tree. struct Node { - KeyConstIteratorRangeType Key{}; + KeyConstIteratorRangeType Key{KeyConstIteratorType{}, + KeyConstIteratorType{}}; std::vector Children; /// An iterator to the value associated with this node. @@ -209,7 +210,8 @@ template class RadixTree { : public iterator_facade_base, std::forward_iterator_tag, MappedType> { const Node *Curr = nullptr; - KeyConstIteratorRangeType Query{}; + KeyConstIteratorRangeType Query{KeyConstIteratorType{}, + KeyConstIteratorType{}}; void findNextValid() { while (Curr && Curr->Value == typename ContainerType::iterator()) From 7bb9a6a71041b5af460bcb0db1b0c7d9a5e0d24d Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 24 Oct 2025 16:50:58 -0700 Subject: [PATCH 22/22] copilot Created using spr 1.3.7 --- llvm/include/llvm/ADT/RadixTree.h | 7 ++++--- llvm/unittests/ADT/RadixTreeTest.cpp | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/ADT/RadixTree.h b/llvm/include/llvm/ADT/RadixTree.h index 6d0f69dc5f957..d3c44e4e6345c 100644 --- a/llvm/include/llvm/ADT/RadixTree.h +++ b/llvm/include/llvm/ADT/RadixTree.h @@ -65,7 +65,8 @@ namespace llvm { /// inserted into it. When an element is removed or the tree is destroyed, /// these objects will be destructed. /// However, if `KeyType` is a reference-like type, e.g., StringRef or range, -/// the user must guarantee that destination has lifetime longer than the tree. +/// the user must guarantee that the referenced data has a lifetime longer than +/// the tree. template class RadixTree { public: using key_type = KeyType; @@ -311,8 +312,8 @@ template class RadixTree { // from the argument. // FIXME: Determine that we need a new node, before expanding // `KeyValuePairs`. - const value_type &NewValue = - KeyValuePairs.emplace_front(std::move(Key), T(std::move(Args)...)); + const value_type &NewValue = KeyValuePairs.emplace_front( + std::move(Key), T(std::forward(Args)...)); Node &Node = findOrCreate(NewValue.first); bool HasValue = Node.Value != typename ContainerType::iterator(); if (!HasValue) diff --git a/llvm/unittests/ADT/RadixTreeTest.cpp b/llvm/unittests/ADT/RadixTreeTest.cpp index 2c92e9d939852..b2dd67c13a713 100644 --- a/llvm/unittests/ADT/RadixTreeTest.cpp +++ b/llvm/unittests/ADT/RadixTreeTest.cpp @@ -93,6 +93,13 @@ TEST(RadixTreeTest, Complex) { EXPECT_EQ(T.countNodes(), 9u); } +TEST(RadixTreeTest, ValueWith2Parameters) { + RadixTree> T; + T.emplace("abcd", "a", 3); + + EXPECT_THAT(T, UnorderedElementsAre(Pair("abcd", Pair("a", 3)))); +} + // Test different types, less readable. template struct TestData {