Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
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


  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