+++ /dev/null
-"""
-Test calling an overriden method.
-
-Note:
- This verifies that LLDB is correctly building the method overrides table.
- If this table is not built correctly then calls to overridden methods in
- derived classes may generate references to non-existant vtable entries,
- as the compiler treats the overridden method as a totally new virtual
- method definition.
- <rdar://problem/14205774>
-
-"""
-
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-class ExprCommandCallOverriddenMethod(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Find the line number to break for main.c.
- self.line = line_number('main.cpp', '// Set breakpoint here')
-
- def test_call_on_base(self):
- """Test calls to overridden methods in derived classes."""
- self.build()
-
- # Set breakpoint in main and run exe
- self.runCmd("file " + self.getBuildArtifact("a.out"),
- CURRENT_EXECUTABLE_SET)
- lldbutil.run_break_set_by_file_and_line(
- self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True)
-
- self.runCmd("run", RUN_SUCCEEDED)
-
- # Test call to method in base class (this should always work as the base
- # class method is never an override).
- self.expect_expr("b->foo()", result_type="int", result_value="2")
-
- # Test calling the base class.
- self.expect_expr("realbase.foo()", result_type="int", result_value="1")
-
- @skipIfLinux # Returns wrong result code on some platforms.
- def test_call_on_derived(self):
- """Test calls to overridden methods in derived classes."""
- self.build()
-
- # Set breakpoint in main and run exe
- self.runCmd("file " + self.getBuildArtifact("a.out"),
- CURRENT_EXECUTABLE_SET)
- lldbutil.run_break_set_by_file_and_line(
- self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True)
-
- self.runCmd("run", RUN_SUCCEEDED)
-
- # Test call to overridden method in derived class (this will fail if the
- # overrides table is not correctly set up, as Derived::foo will be assigned
- # a vtable entry that does not exist in the compiled program).
- self.expect_expr("d.foo()", result_type="int", result_value="2")
-
- @skipIf(oslist=["linux"], archs=["aarch64"])
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr43707")
- def test_call_on_temporary(self):
- """Test calls to overridden methods in derived classes."""
- self.build()
-
- # Set breakpoint in main and run exe
- self.runCmd("file " + self.getBuildArtifact("a.out"),
- CURRENT_EXECUTABLE_SET)
- lldbutil.run_break_set_by_file_and_line(
- self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True)
-
- self.runCmd("run", RUN_SUCCEEDED)
-
- # Test with locally constructed instances.
- self.expect_expr("Base().foo()", result_type="int", result_value="1")
- self.expect_expr("Derived().foo()", result_type="int", result_value="2")
+++ /dev/null
-class Base {
-public:
- virtual ~Base() {}
- virtual int foo() { return 1; }
-};
-
-class Derived : public Base {
-public:
- virtual int foo() { return 2; }
-};
-
-int main() {
- Base realbase;
- realbase.foo();
- Derived d;
- Base *b = &d;
- return 0; // Set breakpoint here
-}
--- /dev/null
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def common_setup(self):
+ self.build()
+ lldbutil.run_to_source_breakpoint(self,"// break here", lldb.SBFileSpec("main.cpp"))
+
+ def test_call_on_base(self):
+ self.common_setup()
+ self.expect_expr("base_with_dtor.foo()", result_type="int", result_value="1")
+ self.expect_expr("base_without_dtor.foo()", result_type="int", result_value="2")
+
+ def test_call_on_derived(self):
+ self.common_setup()
+ self.expect_expr("derived_with_dtor.foo()", result_type="int", result_value="3")
+ self.expect_expr("derived_without_dtor.foo()", result_type="int", result_value="4")
+ self.expect_expr("derived_with_base_dtor.foo()", result_type="int", result_value="5")
+ self.expect_expr("derived_with_dtor_but_no_base_dtor.foo()", result_type="int", result_value="6")
+
+ def test_call_on_derived_as_base(self):
+ self.common_setup()
+ self.expect_expr("derived_with_dtor_as_base.foo()", result_type="int", result_value="3")
+ self.expect_expr("derived_without_as_base.foo()", result_type="int", result_value="4")
+ self.expect_expr("derived_with_base_dtor_as_base.foo()", result_type="int", result_value="5")
+ self.expect_expr("derived_with_dtor_but_no_base_dtor_as_base.foo()", result_type="int", result_value="6")
--- /dev/null
+// Tests virtual function calls. As virtual destructors influence
+// vtables this tests also needs to cover all combinations of
+// virtual destructors in the derived/base class.
+
+struct BaseWithVirtDtor {
+ virtual ~BaseWithVirtDtor() {}
+ virtual int foo() { return 1; }
+};
+
+struct BaseWithoutVirtDtor {
+ virtual int foo() { return 2; }
+};
+
+struct DerivedWithVirtDtor : BaseWithVirtDtor {
+ virtual ~DerivedWithVirtDtor() {}
+ virtual int foo() { return 3; }
+};
+
+struct DerivedWithoutVirtDtor : BaseWithoutVirtDtor {
+ virtual int foo() { return 4; }
+};
+
+struct DerivedWithBaseVirtDtor : BaseWithVirtDtor {
+ virtual int foo() { return 5; }
+};
+
+struct DerivedWithVirtDtorButNoBaseDtor : BaseWithoutVirtDtor {
+ virtual ~DerivedWithVirtDtorButNoBaseDtor() {}
+ virtual int foo() { return 6; }
+};
+
+int main() {
+ // Declare base classes.
+ BaseWithVirtDtor base_with_dtor;
+ BaseWithoutVirtDtor base_without_dtor;
+
+ // Declare all the derived classes.
+ DerivedWithVirtDtor derived_with_dtor;
+ DerivedWithoutVirtDtor derived_without_dtor;
+ DerivedWithBaseVirtDtor derived_with_base_dtor;
+ DerivedWithVirtDtorButNoBaseDtor derived_with_dtor_but_no_base_dtor;
+
+ // The previous classes as their base class type.
+ BaseWithVirtDtor &derived_with_dtor_as_base = derived_with_dtor;
+ BaseWithoutVirtDtor &derived_without_as_base = derived_without_dtor;
+ BaseWithVirtDtor &derived_with_base_dtor_as_base = derived_with_base_dtor;
+ BaseWithoutVirtDtor &derived_with_dtor_but_no_base_dtor_as_base = derived_with_dtor_but_no_base_dtor;
+
+ // Call functions so that they are compiled.
+ int i = base_with_dtor.foo() + base_without_dtor.foo() +
+ derived_with_dtor.foo() + derived_without_dtor.foo() +
+ derived_with_base_dtor.foo();
+
+ return i; // break here
+}