Author: Yao Qi Date: 2026-08-27T13:02:27+01:00 New Revision: af5aa17f44bf385e3cc9e2d9ffc2156e49f1071e
URL: https://github.com/llvm/llvm-project/commit/af5aa17f44bf385e3cc9e2d9ffc2156e49f1071e DIFF: https://github.com/llvm/llvm-project/commit/af5aa17f44bf385e3cc9e2d9ffc2156e49f1071e.diff LOG: [lldb][test] Avoid namespace name colliding with dyld symbols in TestAbiTagLookup (#203984) TestAbiTagLookup.py used `v1` as the inline namespace name. On macOS the dyld shared cache contains two unrelated internal data symbols named `v1` (one in dyld, one in libdyld.dylib). When evaluating `v1::withImplicitTag(...)`, `ClangExpressionDeclMap` resolves `v1` as a namespace correctly, but then still falls through to `SymbolContext::FindBestGlobalDataSymbol`, which finds the two dyld symbols and raises "Multiple internal symbols found for 'v1'", failing the test. Rename the inline namespace to `lldb_test_abi_tag_lookup_inline_ns` so the test no longer collides with anything in dyld. Add a new XFAIL test, namespace_data_symbol_collision, that reproduces the underlying bug deterministically (without depending on `dyld`) by linking two non-debug-info objects that each define a static data symbol whose name matches a real namespace in main.cpp. Added: lldb/test/API/lang/cpp/namespace_data_symbol_collision/Makefile lldb/test/API/lang/cpp/namespace_data_symbol_collision/TestNamespaceDataSymbolCollision.py lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_a.c lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_b.c lldb/test/API/lang/cpp/namespace_data_symbol_collision/main.cpp Modified: lldb/test/API/lang/cpp/abi_tag_lookup/TestAbiTagLookup.py lldb/test/API/lang/cpp/abi_tag_lookup/main.cpp Removed: ################################################################################ diff --git a/lldb/test/API/lang/cpp/abi_tag_lookup/TestAbiTagLookup.py b/lldb/test/API/lang/cpp/abi_tag_lookup/TestAbiTagLookup.py index 19f4a4e14ed22..76d89cfff8e48 100644 --- a/lldb/test/API/lang/cpp/abi_tag_lookup/TestAbiTagLookup.py +++ b/lldb/test/API/lang/cpp/abi_tag_lookup/TestAbiTagLookup.py @@ -60,14 +60,18 @@ def test_abi_tag_lookup(self): # Inline namespaces with ABI tags self.expect_expr( - "v1::withImplicitTag(Simple{.mem = 6})", result_type="int", result_value="6" + "lldb_test_abi_tag_lookup_inline_ns::withImplicitTag(Simple{.mem = 6})", + result_type="int", + result_value="6", ) self.expect_expr( "withImplicitTag(Simple{.mem = 6})", result_type="int", result_value="6" ) self.expect_expr( - "v1::withImplicitTag(Tagged{.mem = 6})", result_type="int", result_value="6" + "lldb_test_abi_tag_lookup_inline_ns::withImplicitTag(Tagged{.mem = 6})", + result_type="int", + result_value="6", ) self.expect_expr( "withImplicitTag(Tagged{.mem = 6})", result_type="int", result_value="6" diff --git a/lldb/test/API/lang/cpp/abi_tag_lookup/main.cpp b/lldb/test/API/lang/cpp/abi_tag_lookup/main.cpp index 4c1ff688df0cd..ab5aabaddd2c8 100644 --- a/lldb/test/API/lang/cpp/abi_tag_lookup/main.cpp +++ b/lldb/test/API/lang/cpp/abi_tag_lookup/main.cpp @@ -49,7 +49,7 @@ template <typename T> struct [[gnu::abi_tag("Quux", "Quuux")]] TaggedTemplate { }; // clang-format off -inline namespace [[gnu::abi_tag("Inline", "NS")]] v1 { +inline namespace [[gnu::abi_tag("Inline", "NS")]] lldb_test_abi_tag_lookup_inline_ns { template <typename T> int withImplicitTag(T const &t) { return t.mem; } } // namespace // clang-format on diff --git a/lldb/test/API/lang/cpp/namespace_data_symbol_collision/Makefile b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/Makefile new file mode 100644 index 0000000000000..1573282719a1f --- /dev/null +++ b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/Makefile @@ -0,0 +1,10 @@ +CXX_SOURCES := main.cpp +C_SOURCES := colliding_a.c colliding_b.c + +include Makefile.rules + +# The colliding_*.c files must be built WITHOUT debug info so that lldb sees +# them only as bare symtab entries (eSymbolTypeData), the same situation as +# the dyld globals that triggered the original failure. +colliding_a.o: CFLAGS = $(CFLAGS_NO_DEBUG) +colliding_b.o: CFLAGS = $(CFLAGS_NO_DEBUG) diff --git a/lldb/test/API/lang/cpp/namespace_data_symbol_collision/TestNamespaceDataSymbolCollision.py b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/TestNamespaceDataSymbolCollision.py new file mode 100644 index 0000000000000..096cf76db1742 --- /dev/null +++ b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/TestNamespaceDataSymbolCollision.py @@ -0,0 +1,32 @@ +""" +This test plants two unrelated internal data symbols named +`colliding_ns` in non-debug-info objects, then evaluates a qualified-id +expression that uses `colliding_ns` as a (real) namespace prefix. + +Expected eventual behavior: the namespace resolution succeeds and the +function call returns 6. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCase(TestBase): + @skipIfWindows + @expectedFailureAll + def test(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "Break here", lldb.SBFileSpec("main.cpp", False) + ) + + # The bug: even though `colliding_ns` is a namespace in the program, + # lldb's expression evaluator still runs FindBestGlobalDataSymbol on + # the bare name, finds the two internal data symbols, and errors out. + self.expect_expr( + "colliding_ns::do_thing(5)", + result_type="int", + result_value="6", + ) diff --git a/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_a.c b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_a.c new file mode 100644 index 0000000000000..2c1209cebe96d --- /dev/null +++ b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_a.c @@ -0,0 +1,6 @@ +// Internal (file-static) data symbol named `colliding_ns`. Built without +// debug info, so lldb sees only the symtab entry, not a DWARF VarDecl. +static const int colliding_ns __attribute__((used)) = 1; + +// Anchor referenced from main so the linker keeps the object alive. +const int *colliding_a_anchor(void) { return &colliding_ns; } diff --git a/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_b.c b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_b.c new file mode 100644 index 0000000000000..535bcf72b5e0b --- /dev/null +++ b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/colliding_b.c @@ -0,0 +1,7 @@ +// Second internal data symbol with the SAME name as the one in +// colliding_a.c. Two such symbols in the target's symtab is what trips +// SymbolContext::FindBestGlobalDataSymbol -> "Multiple internal symbols +// found". +static const int colliding_ns __attribute__((used)) = 2; + +const int *colliding_b_anchor(void) { return &colliding_ns; } diff --git a/lldb/test/API/lang/cpp/namespace_data_symbol_collision/main.cpp b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/main.cpp new file mode 100644 index 0000000000000..8ac25477df526 --- /dev/null +++ b/lldb/test/API/lang/cpp/namespace_data_symbol_collision/main.cpp @@ -0,0 +1,18 @@ +// `colliding_ns` is a real (inline) namespace in this translation unit. +// Two unrelated internal data symbols of the same name live in +// colliding_a.o / colliding_b.o (built without debug info). +inline namespace colliding_ns { +int do_thing(int t) { return t + 1; } +} // namespace colliding_ns + +extern "C" const int *colliding_a_anchor(void); +extern "C" const int *colliding_b_anchor(void); + +int main() { + // Force the linker to keep both internal `colliding_ns` data symbols. + (void)colliding_a_anchor(); + (void)colliding_b_anchor(); + + int r = do_thing(5); + return r; // Break here +} _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
