From: Simon Marchi <simon.marchi@efficios.com>
To: gcc-patches@sourceware.org, gdb-patches@sourceware.org
Cc: Simon Marchi <simon.marchi@efficios.com>
Subject: [PATCH v2 1/2] gdb: add selftests for split_name
Date: Wed, 14 Oct 2026 12:46:58 -0400 [thread overview]
Message-ID: <20261014164830.358677-2-simon.marchi@efficios.com> (raw)
In-Reply-To: <20261005052602.1288766-3-simon.marchi@polymtl.ca>
Add selftests for split_name, covering all splitting styles. Some
output is questionable, but the goal is to document the current
behavior.
Change-Id: Ib31a6f01762e84eefff647e0c141975ea23d469f
---
gdb/split-name.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 189 insertions(+)
diff --git a/gdb/split-name.c b/gdb/split-name.c
index bc145909c2e8..cb740a968d49 100644
--- a/gdb/split-name.c
+++ b/gdb/split-name.c
@@ -19,6 +19,8 @@
#include "split-name.h"
#include "cp-support.h"
+#include "gdbsupport/enumerate.h"
+#include "gdbsupport/selftest.h"
/* See split-name.h. */
@@ -64,3 +66,190 @@ split_name (const char *name, split_style style)
result.emplace_back (&name[previous_len]);
return result;
}
+
+#if GDB_SELF_TEST
+
+namespace selftests {
+
+/* Return a string representation of COMPONENTS, for debugging. */
+
+static std::string
+components_to_string (const std::vector<std::string_view> &components)
+{
+ std::string str = "{";
+
+ for (auto [i, component] : gdb::ranges::views::enumerate (components))
+ {
+ if (i > 0)
+ str += ",";
+
+ str += " \"";
+ str += component;
+ str += "\"";
+ }
+
+ str += " }";
+ return str;
+}
+
+/* Check that splitting NAME using STYLE gives EXPECTED. */
+
+static void
+check_split_name (const char *name, split_style style,
+ const std::vector<std::string_view> &expected)
+{
+ std::vector<std::string_view> result = split_name (name, style);
+
+ if (result != expected)
+ debug_printf ("split_name (\"%s\"): got %s, expected %s\n", name,
+ components_to_string (result).c_str (),
+ components_to_string (expected).c_str ());
+
+ SELF_CHECK (result == expected);
+}
+
+static void
+test_split_name_none ()
+{
+ /* No splitting is ever done. */
+ check_split_name ("", split_style::NONE, { "" });
+ check_split_name ("foo", split_style::NONE, { "foo" });
+ check_split_name ("a::b", split_style::NONE, { "a::b" });
+ check_split_name ("a.b", split_style::NONE, { "a.b" });
+ check_split_name ("a..b", split_style::NONE, { "a..b" });
+ check_split_name ("::", split_style::NONE, { "::" });
+ check_split_name (".", split_style::NONE, { "." });
+}
+
+static void
+test_split_name_cxx ()
+{
+ /* Simple names. */
+ check_split_name ("", split_style::CXX, { "" });
+ check_split_name ("foo", split_style::CXX, { "foo" });
+ check_split_name ("a::b", split_style::CXX, { "a", "b" });
+ check_split_name ("a::b::c", split_style::CXX, { "a", "b", "c" });
+
+ /* Dots are not separators. */
+ check_split_name ("a.b", split_style::CXX, { "a.b" });
+ check_split_name ("a..b::c", split_style::CXX, { "a..b", "c" });
+
+ /* A single colon is not a separator. */
+ check_split_name ("a:b", split_style::CXX, { "a:b" });
+ check_split_name ("a:::b", split_style::CXX, { "a", ":b" });
+
+ /* Templates. */
+ check_split_name ("a<b::c>", split_style::CXX, { "a<b::c>" });
+ check_split_name ("a<b::c>::d", split_style::CXX, { "a<b::c>", "d" });
+ check_split_name ("a::b<c::d, e::f>::g", split_style::CXX,
+ { "a", "b<c::d, e::f>", "g" });
+ check_split_name ("a<b::c<d::e>>::f", split_style::CXX,
+ { "a<b::c<d::e>>", "f" });
+ check_split_name ("std::vector<int, std::allocator<int> >::size",
+ split_style::CXX,
+ { "std", "vector<int, std::allocator<int> >", "size" });
+
+ /* Parentheses: function parameters, function-local names,
+ anonymous namespaces. */
+ check_split_name ("a::b(c::d)", split_style::CXX, { "a", "b(c::d)" });
+ check_split_name ("a::b(c::d) const", split_style::CXX,
+ { "a", "b(c::d) const" });
+ check_split_name ("foo(int)::bar", split_style::CXX,
+ { "foo(int)", "bar" });
+ check_split_name ("(anonymous namespace)::foo", split_style::CXX,
+ { "(anonymous namespace)", "foo" });
+ check_split_name ("a::(anonymous namespace)::foo", split_style::CXX,
+ { "a", "(anonymous namespace)", "foo" });
+
+ /* Operators, which can contain characters that would otherwise
+ be treated specially. */
+ check_split_name ("A::operator<", split_style::CXX,
+ { "A", "operator<" });
+ check_split_name ("A::operator<<", split_style::CXX,
+ { "A", "operator<<" });
+ check_split_name ("A::operator>", split_style::CXX,
+ { "A", "operator>" });
+ check_split_name ("A::operator>>", split_style::CXX,
+ { "A", "operator>>" });
+ check_split_name ("A::operator->", split_style::CXX,
+ { "A", "operator->" });
+ check_split_name ("A::operator()", split_style::CXX,
+ { "A", "operator()" });
+ check_split_name ("A::operator< <int>", split_style::CXX,
+ { "A", "operator< <int>" });
+ check_split_name ("A::operator<(A const&, A const&)", split_style::CXX,
+ { "A", "operator<(A const&, A const&)" });
+
+ /* "operator" as part of an identifier is not an operator. */
+ check_split_name ("cooperator::x", split_style::CXX,
+ { "cooperator", "x" });
+ check_split_name ("operator_foo::x", split_style::CXX,
+ { "operator_foo", "x" });
+
+ /* Malformed names are returned as a single component. */
+ check_split_name ("a<b::c", split_style::CXX, { "a<b::c" });
+ check_split_name ("a(b::c", split_style::CXX, { "a(b::c" });
+ check_split_name ("a>b::c", split_style::CXX, { "a>b::c" });
+ check_split_name ("a)b::c", split_style::CXX, { "a)b::c" });
+
+ /* Leading, trailing or consecutive separators produce empty
+ components. */
+ check_split_name ("::", split_style::CXX, { "", "" });
+ check_split_name ("::a", split_style::CXX, { "", "a" });
+ check_split_name ("a::", split_style::CXX, { "a", "" });
+ check_split_name ("a::::b", split_style::CXX, { "a", "", "b" });
+}
+
+static void
+test_split_name_dot_style ()
+{
+ /* Simple names. */
+ check_split_name ("", split_style::DOT_STYLE, { "" });
+ check_split_name ("foo", split_style::DOT_STYLE, { "foo" });
+ check_split_name ("a.b", split_style::DOT_STYLE, { "a", "b" });
+ check_split_name ("a.b.c", split_style::DOT_STYLE, { "a", "b", "c" });
+ check_split_name ("pkg.sub.func", split_style::DOT_STYLE,
+ { "pkg", "sub", "func" });
+
+ /* "::" is not a separator. */
+ check_split_name ("a::b", split_style::DOT_STYLE, { "a::b" });
+ check_split_name ("a::b.c", split_style::DOT_STYLE, { "a::b", "c" });
+
+ /* Go method names. */
+ check_split_name ("main.(*T).Method", split_style::DOT_STYLE,
+ { "main", "(*T)", "Method" });
+
+ /* Ada operator names. */
+ check_split_name ("pkg.\"+\"", split_style::DOT_STYLE,
+ { "pkg", "\"+\"" });
+
+ /* Leading, trailing or consecutive dots produce empty components. */
+ check_split_name (".", split_style::DOT_STYLE, { "", "" });
+ check_split_name ("..", split_style::DOT_STYLE, { "", "", "" });
+ check_split_name (".a", split_style::DOT_STYLE, { "", "a" });
+ check_split_name ("a.", split_style::DOT_STYLE, { "a", "" });
+ check_split_name ("a..b", split_style::DOT_STYLE, { "a", "", "b" });
+ check_split_name (".a.b", split_style::DOT_STYLE, { "", "a", "b" });
+ check_split_name ("a.b.", split_style::DOT_STYLE, { "a", "b", "" });
+ check_split_name ("a.b..c", split_style::DOT_STYLE,
+ { "a", "b", "", "c" });
+ check_split_name ("a..b.c", split_style::DOT_STYLE,
+ { "a", "", "b", "c" });
+ check_split_name ("a...b", split_style::DOT_STYLE, { "a", "", "", "b" });
+}
+
+} /* namespace selftests */
+
+#endif /* GDB_SELF_TEST */
+
+INIT_GDB_FILE (split_name)
+{
+#if GDB_SELF_TEST
+ selftests::register_test ("split_name_none",
+ selftests::test_split_name_none);
+ selftests::register_test ("split_name_cxx",
+ selftests::test_split_name_cxx);
+ selftests::register_test ("split_name_dot_style",
+ selftests::test_split_name_dot_style);
+#endif
+}
--
2.56.0
next prev parent reply other threads:[~2026-10-14 16:50 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-05 5:25 [PATCH 1/3] gdb/testsuite: fix rust compiler selection in gdb_default_target_compile simon.marchi
2026-10-05 5:25 ` [PATCH 2/3] gdb/testsuite: wrap rustc in cc-with-tweaks.exp simon.marchi
2026-10-06 10:56 ` Andrew Burgess
2026-10-05 5:25 ` [PATCH 3/3] gdb/dwarf: fix crash when .gdb_index contains Rust legacy mangled names simon.marchi
2026-10-06 11:01 ` Andrew Burgess
2026-10-06 13:39 ` Simon Marchi
2026-10-14 13:01 ` Tom Tromey
2026-10-14 13:22 ` Simon Marchi
2026-10-14 14:59 ` Tom Tromey
2026-10-14 16:13 ` Tom Tromey
2026-10-14 16:26 ` Simon Marchi
2026-10-14 16:46 ` [PATCH v2 0/2] Fix " Simon Marchi
2026-10-15 15:47 ` Tom Tromey
2026-10-18 3:45 ` Simon Marchi
2026-10-14 16:46 ` Simon Marchi [this message]
2026-10-15 15:48 ` [PATCH v2 1/2] gdb: add selftests for split_name Tom Tromey
2026-10-15 18:33 ` Simon Marchi
2026-10-16 3:15 ` Tom Tromey
2026-10-14 16:46 ` [PATCH v2 2/2] gdb/dwarf: fix crash when .gdb_index contains Rust legacy mangled names Simon Marchi
2026-10-06 10:56 ` [PATCH 1/3] gdb/testsuite: fix rust compiler selection in gdb_default_target_compile Andrew Burgess
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261014164830.358677-2-simon.marchi@efficios.com \
--to=simon.marchi@efficios.com \
--cc=gcc-patches@sourceware.org \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox