forked from OSchip/llvm-project
[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).
This commit is contained in:
parent
8756869170
commit
ea2af727a5
|
@ -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.
|
||||
<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")
|
|
@ -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
|
||||
}
|
|
@ -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")
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue