From ea2af727a5c38906e3d1321de51aaa126b4efc69 Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Thu, 6 Feb 2020 15:11:06 +0100 Subject: [PATCH] [lldb] Refactored TestCallOverriddenMethod.py to general virtual function test This actually tests all the different situations in which we can call virtual functions. This removes also all skipIfs as the first skipIf for Linux is apparently fixed and the second skipIf was just failing due to the constructor call (which should be its own test and not be tested here). --- .../overriden-methods/TestCallOverriddenMethod.py | 82 ---------------------- .../test/lang/cpp/overriden-methods/main.cpp | 18 ----- .../Makefile | 0 .../virtual-functions/TestCppVirtualFunctions.py | 31 ++++++++ .../test/lang/cpp/virtual-functions/main.cpp | 55 +++++++++++++++ 5 files changed, 86 insertions(+), 100 deletions(-) delete mode 100644 lldb/packages/Python/lldbsuite/test/lang/cpp/overriden-methods/TestCallOverriddenMethod.py delete mode 100644 lldb/packages/Python/lldbsuite/test/lang/cpp/overriden-methods/main.cpp rename lldb/packages/Python/lldbsuite/test/lang/cpp/{overriden-methods => virtual-functions}/Makefile (100%) create mode 100644 lldb/packages/Python/lldbsuite/test/lang/cpp/virtual-functions/TestCppVirtualFunctions.py create mode 100644 lldb/packages/Python/lldbsuite/test/lang/cpp/virtual-functions/main.cpp diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/overriden-methods/TestCallOverriddenMethod.py b/lldb/packages/Python/lldbsuite/test/lang/cpp/overriden-methods/TestCallOverriddenMethod.py deleted file mode 100644 index 05287f4..0000000 --- a/lldb/packages/Python/lldbsuite/test/lang/cpp/overriden-methods/TestCallOverriddenMethod.py +++ /dev/null @@ -1,82 +0,0 @@ -""" -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. - - -""" - -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") diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/overriden-methods/main.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/overriden-methods/main.cpp deleted file mode 100644 index 87997fa..0000000 --- a/lldb/packages/Python/lldbsuite/test/lang/cpp/overriden-methods/main.cpp +++ /dev/null @@ -1,18 +0,0 @@ -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 -} diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/overriden-methods/Makefile b/lldb/packages/Python/lldbsuite/test/lang/cpp/virtual-functions/Makefile similarity index 100% rename from lldb/packages/Python/lldbsuite/test/lang/cpp/overriden-methods/Makefile rename to lldb/packages/Python/lldbsuite/test/lang/cpp/virtual-functions/Makefile diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/virtual-functions/TestCppVirtualFunctions.py b/lldb/packages/Python/lldbsuite/test/lang/cpp/virtual-functions/TestCppVirtualFunctions.py new file mode 100644 index 0000000..d814354 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/virtual-functions/TestCppVirtualFunctions.py @@ -0,0 +1,31 @@ +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") diff --git a/lldb/packages/Python/lldbsuite/test/lang/cpp/virtual-functions/main.cpp b/lldb/packages/Python/lldbsuite/test/lang/cpp/virtual-functions/main.cpp new file mode 100644 index 0000000..3689828 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/lang/cpp/virtual-functions/main.cpp @@ -0,0 +1,55 @@ +// 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 +} -- 2.7.4