diff options
Diffstat (limited to 'lldb/test/API/lang/cpp')
8 files changed, 278 insertions, 14 deletions
diff --git a/lldb/test/API/lang/cpp/abi_tag_structors/Makefile b/lldb/test/API/lang/cpp/abi_tag_structors/Makefile new file mode 100644 index 000000000000..99998b20bcb0 --- /dev/null +++ b/lldb/test/API/lang/cpp/abi_tag_structors/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/abi_tag_structors/TestAbiTagStructors.py b/lldb/test/API/lang/cpp/abi_tag_structors/TestAbiTagStructors.py new file mode 100644 index 000000000000..87d8adb42b82 --- /dev/null +++ b/lldb/test/API/lang/cpp/abi_tag_structors/TestAbiTagStructors.py @@ -0,0 +1,116 @@ +""" +Test that we can call structors/destructors +annotated (and thus mangled) with ABI tags. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AbiTagStructorsTestCase(TestBase): + @expectedFailureAll(oslist=["windows"]) + def test_with_structor_linkage_names(self): + self.build(dictionary={"CXXFLAGS_EXTRAS": "-gstructor-decl-linkage-names"}) + + lldbutil.run_to_source_breakpoint( + self, "Break here", lldb.SBFileSpec("main.cpp", False) + ) + + self.expect_expr( + "Tagged()", + result_type="Tagged", + result_children=[ValueCheck(name="x", value="15")], + ) + self.expect_expr( + "Tagged(-17)", + result_type="Tagged", + result_children=[ValueCheck(name="x", value="-17")], + ) + self.expect_expr("t1 = t2", result_type="Tagged") + + self.expect("expr Tagged t3(t1)", error=False) + self.expect("expr t1.~Tagged()", error=False) + + self.expect("expr t1.~Tagged()", error=False) + + self.expect( + "expression -- struct $Derived : virtual public Tagged { int y; $Derived(int val) : Tagged(val) { y = x; } };", + error=False, + ) + self.expect( + "expression -- struct $Derived2 : virtual public $Derived { int z; $Derived2() : $Derived(10) { z = y; } };", + error=False, + ) + self.expect_expr( + "$Derived2 d; d", + result_type="$Derived2", + result_children=[ + ValueCheck( + name="$Derived", + children=[ + ValueCheck( + name="Tagged", children=[ValueCheck(name="x", value="15")] + ), + ValueCheck(name="y", value="15"), + ], + ), + ValueCheck(name="z", value="15"), + ], + ) + + # Calls to deleting and base object destructor variants (D0 and D2 in Itanium ABI) + self.expect_expr( + "struct D : public HasVirtualDtor {}; D d; d.func()", + result_type="int", + result_value="10", + ) + + @expectedFailureAll(oslist=["windows"]) + def test_no_structor_linkage_names(self): + """ + Test that without linkage names on structor declarations we can't call + ABI-tagged structors. + """ + self.build(dictionary={"CXXFLAGS_EXTRAS": "-gno-structor-decl-linkage-names"}) + + lldbutil.run_to_source_breakpoint( + self, "Break here", lldb.SBFileSpec("main.cpp", False) + ) + + self.expect("expression Tagged(17)", error=True) + self.expect("expr Tagged t3(t1)", error=True) + self.expect("expr t1.~Tagged()", error=True) + + ## Calls to deleting and base object destructor variants (D0 and D2 in Itanium ABI) + self.expect( + "expression -- struct D : public HasVirtualDtor {}; D d; d.func()", + error=True, + ) + + self.expect("expression -- Derived d(16); d", error=True) + + def do_nested_structor_test(self): + """ + Test that calling ABI-tagged ctors of function local classes is not supported, + but calling un-tagged functions is. + """ + lldbutil.run_to_source_breakpoint( + self, "Break nested", lldb.SBFileSpec("main.cpp", False) + ) + + self.expect("expression Local()", error=False) + self.expect( + "expression TaggedLocal()", error=True, substrs=["Couldn't look up symbols"] + ) + + @expectedFailureAll(oslist=["windows"]) + def test_nested_no_structor_linkage_names(self): + self.build(dictionary={"CXXFLAGS_EXTRAS": "-gstructor-decl-linkage-names"}) + self.do_nested_structor_test() + + @expectedFailureAll(oslist=["windows"]) + def test_nested_with_structor_linkage_names(self): + self.build(dictionary={"CXXFLAGS_EXTRAS": "-gno-structor-decl-linkage-names"}) + self.do_nested_structor_test() diff --git a/lldb/test/API/lang/cpp/abi_tag_structors/main.cpp b/lldb/test/API/lang/cpp/abi_tag_structors/main.cpp new file mode 100644 index 000000000000..ddf237491b83 --- /dev/null +++ b/lldb/test/API/lang/cpp/abi_tag_structors/main.cpp @@ -0,0 +1,62 @@ +#include <cstdio> + +struct Tagged { + [[gnu::abi_tag("Default")]] Tagged() : x(15) { std::puts(__func__); } + [[gnu::abi_tag("Value")]] Tagged(int val) : x(val) { std::puts(__func__); } + [[gnu::abi_tag("Copy")]] Tagged(const Tagged &lhs) : x(lhs.x) { + std::puts(__func__); + } + [[gnu::abi_tag("CopyAssign")]] Tagged &operator=(const Tagged &) { + std::puts(__func__); + return *this; + } + [[gnu::abi_tag("Dtor")]] ~Tagged() { std::puts(__func__); } + + int x; +}; + +struct Base { + virtual ~Base() { std::puts(__func__); } + virtual int func() { return 5; } +}; + +struct HasVirtualDtor : public Base { + int func() override { return 10; } + + [[gnu::abi_tag("VirtualDtor")]] ~HasVirtualDtor() override { + std::puts(__func__); + } +}; + +struct HasNestedCtor { + HasNestedCtor() { + struct TaggedLocal { + [[gnu::abi_tag("Local")]] TaggedLocal() { std::puts(__func__); } + }; + + struct Local { + Local() { std::puts(__func__); } + }; + + TaggedLocal l1; + Local l2; + std::puts("Break nested"); + } +}; + +int main() { + Tagged t; + Tagged t1(10); + Tagged t2(t1); + t1 = t2; + + Base b; + HasVirtualDtor vdtor; + vdtor.func(); + + std::puts("Break here"); + + HasNestedCtor nested; + + return 0; +} diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py index 70d7fd096c7c..c0545c70c84e 100644 --- a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py @@ -5,15 +5,14 @@ from lldbsuite.test import lldbutil class ExprDefinitionInDylibTestCase(TestBase): - NO_DEBUG_INFO_TESTCASE = True @skipIfWindows - def test(self): + def test_with_structor_linkage_names(self): """ Tests that we can call functions whose definition is in a different LLDB module than it's declaration. """ - self.build() + self.build(dictionary={"CXXFLAGS_EXTRAS": "-gstructor-decl-linkage-names"}) target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) self.assertTrue(target, VALID_TARGET) @@ -31,10 +30,71 @@ class ExprDefinitionInDylibTestCase(TestBase): ) self.expect_expr("f.method()", result_value="-72", result_type="int") - self.expect_expr("Foo()", result_type="Foo") - # FIXME: mangled name lookup for ABI-tagged ctors fails because - # the debug-info AST doesn't have ABI-tag information. - self.expect( - "expr Bar()", error=True, substrs=["error: Couldn't look up symbols"] + self.expect_expr("Foo(10)", result_type="Foo") + + self.expect_expr("Base()", result_type="Base") + + self.expect_expr("Bar()", result_type="Bar") + + # Test a more complex setup: expression that has a three bases: + # 1. definition is in local module + # 2. definition is in different module + # 3. definition is in expression context (and has it's own virtual base) + self.expect_expr( + "struct ExprBase : virtual Foo { int z; ExprBase() : Foo(11) { z = x; } }; struct Expr : virtual Local, virtual Foo, virtual ExprBase { int w; Expr() : Local(), Foo(12), ExprBase() { w = y; } }; Expr tmp; tmp", + result_type="Expr", + result_children=[ + ValueCheck( + name="Local", + children=[ + ValueCheck( + name="Foo", children=[ValueCheck(name="x", value="12")] + ), + ValueCheck(name="y", value="12"), + ], + ), + ValueCheck(name="Foo", children=[ValueCheck(name="x", value="12")]), + ValueCheck( + name="ExprBase", + children=[ + ValueCheck( + name="Foo", children=[ValueCheck(name="x", value="12")] + ), + ValueCheck(name="z", value="12"), + ], + ), + ValueCheck(name="w", value="12"), + ], ) + + @skipIfWindows + def test_no_structor_linkage_names(self): + """ + Tests that if structor declarations don't have linkage names, we can't + call ABI-tagged constructors. But non-tagged ones are fine. + """ + self.build(dictionary={"CXXFLAGS_EXTRAS": "-gno-structor-decl-linkage-names"}) + + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + env = self.registerSharedLibrariesWithTarget(target, ["lib"]) + + breakpoint = lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", line_number("main.cpp", "return") + ) + + process = target.LaunchSimple(None, env, self.get_process_working_directory()) + + self.assertIsNotNone( + lldbutil.get_one_thread_stopped_at_breakpoint_id(self.process(), breakpoint) + ) + + self.expect_expr("f.method()", result_value="-72", result_type="int") + + self.expect_expr("Foo(10)", result_type="Foo") + + self.expect("Base()", error=True) + + self.expect("Bar()", error=True) diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp index 1a08817f5cda..aa3921ffe0b1 100644 --- a/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp @@ -4,10 +4,14 @@ int Foo::method() { return -72; } -Foo::Foo() { std::puts(__func__); } +Foo::Foo(int val) : x(val) { std::puts(__func__); } Foo::~Foo() { std::puts(__func__); } Bar::Bar() { std::puts(__func__); } Bar::~Bar() { std::puts(__func__); } + +Base::Base() { std::puts(__func__); } + +Base::~Base() { std::puts(__func__); } diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h index 5ec227946cba..513c9a0f9c87 100644 --- a/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h @@ -3,11 +3,18 @@ struct Foo { int method(); - Foo(); + Foo(int val); ~Foo(); + + int x; +}; + +struct Base { + [[gnu::abi_tag("BaseCtor")]] Base(); + [[gnu::abi_tag("BaseDtor")]] ~Base(); }; -struct Bar { +struct Bar : public Base { [[gnu::abi_tag("Ctor")]] Bar(); [[gnu::abi_tag("Dtor")]] ~Bar(); }; diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp b/lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp index 4d6bece21eca..ff43190b991c 100644 --- a/lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp @@ -1,7 +1,18 @@ #include "lib.h" +struct Local : public virtual Foo { + Local(); + ~Local(); + int y; +}; + +Local::Local() : Foo(5) { y = x; } +Local::~Local() {} + int main() { - Foo f; - Bar b; + Foo f(5); + Base b1; + Bar b2; + Local l1; return f.method(); } diff --git a/lldb/test/API/lang/cpp/libcxx-internals-recognizer/TestLibcxxInternalsRecognizer.py b/lldb/test/API/lang/cpp/libcxx-internals-recognizer/TestLibcxxInternalsRecognizer.py index 8efa53bdbf72..d8a729b322fe 100644 --- a/lldb/test/API/lang/cpp/libcxx-internals-recognizer/TestLibcxxInternalsRecognizer.py +++ b/lldb/test/API/lang/cpp/libcxx-internals-recognizer/TestLibcxxInternalsRecognizer.py @@ -9,7 +9,7 @@ class LibCxxInternalsRecognizerTestCase(TestBase): NO_DEBUG_INFO_TESTCASE = True @add_test_categories(["libc++"]) - @skipIf(compiler="clang", compiler_version=["<", "16.0"]) + @skipIf(compiler="clang", compiler_version=["<", "19.0"]) def test_frame_recognizer(self): """Test that implementation details of libc++ are hidden""" self.build() @@ -40,6 +40,7 @@ class LibCxxInternalsRecognizerTestCase(TestBase): "Callable::operator()(int) const": ["::invoke", "test_invoke"], # Containers "MyKey::operator<(MyKey const&) const": [ + "::operator()", "less", "::emplace", "test_containers", |
