forked from OSchip/llvm-project
[lldb][NFC] Add some tests for function-local classes and document some bugs
This feature doesn't seem to have any dedicated test. Instead some random tests (e.g. the bitfield tests) are declaring function-local classes for some reason. This adds a dedicated test so we can clean up those other tests. Also add FIXME's for some basic stuff that doesn't work. The first FIXME is a good beginner bug which just requires prepending the function name (in case we decide to fix it instead of documenting this behaviour). The second FIXME is caused by LLDB searching for definitions by name (which also seems to miss the function name so there is a conflict with the outer type). Some more things that should be tested (and might not work): * Local classes with member functions with local classes. * Classes in different functions with same name. * Classes with the same name in different TUs with internal linkage functions of the same name. * Empty classes are parsed by the DWARF parser in a fast path, so that requires dedicated tests. * Repeat some of the tested logic for C.
This commit is contained in:
parent
6c8ff4032e
commit
cda1450f1c
|
@ -0,0 +1,3 @@
|
|||
CXX_SOURCES := main.cpp
|
||||
|
||||
include Makefile.rules
|
|
@ -0,0 +1,58 @@
|
|||
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__)
|
||||
|
||||
@no_debug_info_test
|
||||
def test(self):
|
||||
self.build()
|
||||
lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.cpp"))
|
||||
|
||||
m_val = self.expect_expr("m", result_type="WithMember", result_children=[
|
||||
ValueCheck(name="i", value="1")
|
||||
])
|
||||
# FIXME: The non-display name doesn't include the function, so users
|
||||
# can't actually match specific classes by their name. Either document
|
||||
# or fix this.
|
||||
self.assertEqual(m_val.GetType().GetName(), "WithMember")
|
||||
# Try accessing the type in the expression evaluator.
|
||||
self.expect_expr("m.i", result_type="int", result_value="1")
|
||||
|
||||
self.expect_expr("typedef_unnamed", result_type="TypedefUnnamed", result_children=[
|
||||
ValueCheck(name="a", value="2")
|
||||
])
|
||||
self.expect_expr("typedef_unnamed2", result_type="TypedefUnnamed2", result_children=[
|
||||
ValueCheck(name="b", value="3")
|
||||
])
|
||||
self.expect_expr("unnamed", result_type="(unnamed struct)", result_children=[
|
||||
ValueCheck(name="i", value="4")
|
||||
])
|
||||
self.expect_expr("unnamed2", result_type="(unnamed struct)", result_children=[
|
||||
ValueCheck(name="j", value="5")
|
||||
])
|
||||
|
||||
# Try a class that is only forward declared.
|
||||
self.expect_expr("fwd", result_type="Forward *")
|
||||
self.expect("expression -- fwd->i", error=True, substrs=[
|
||||
"member access into incomplete type 'Forward'"
|
||||
])
|
||||
self.expect("expression -- *fwd", error=True, substrs=[
|
||||
"incomplete type 'Forward' where a complete type is required"
|
||||
])
|
||||
|
||||
# Try a class that has a name that matches a class in the global scope.
|
||||
self.expect_expr("fwd_conflict", result_type="ForwardConflict *")
|
||||
# FIXME: This pulls in the unrelated type with the same name from the
|
||||
# global scope.
|
||||
self.expect("expression -- fwd_conflict->i", error=True, substrs=[
|
||||
# This should point out that ForwardConflict is incomplete.
|
||||
"no member named 'i' in 'ForwardConflict'"
|
||||
])
|
||||
self.expect("expression -- *fwd_conflict", error=True, substrs=[
|
||||
# This should fail to parse instead.
|
||||
"couldn't read its memory"
|
||||
])
|
|
@ -0,0 +1,44 @@
|
|||
// These declarations have intentionally the same name as the function-local
|
||||
// class. LLDB should never pull in these definitions as this test only inspects
|
||||
// the classes defined in the function below.
|
||||
struct WithMember {
|
||||
float false_def;
|
||||
};
|
||||
typedef struct {
|
||||
float false_def;
|
||||
} TypedefUnnamed;
|
||||
struct ForwardConflict {
|
||||
float false_def;
|
||||
};
|
||||
ForwardConflict conflict1;
|
||||
WithMember conflict2;
|
||||
struct {
|
||||
float false_def;
|
||||
} unnamed;
|
||||
|
||||
int main() {
|
||||
struct WithMember {
|
||||
int i;
|
||||
};
|
||||
typedef struct {
|
||||
int a;
|
||||
} TypedefUnnamed;
|
||||
typedef struct {
|
||||
int b;
|
||||
} TypedefUnnamed2;
|
||||
struct Forward;
|
||||
struct ForwardConflict;
|
||||
|
||||
WithMember m = {1};
|
||||
TypedefUnnamed typedef_unnamed = {2};
|
||||
TypedefUnnamed2 typedef_unnamed2 = {3};
|
||||
struct {
|
||||
int i;
|
||||
} unnamed = {4};
|
||||
struct {
|
||||
int j;
|
||||
} unnamed2 = {5};
|
||||
Forward *fwd = nullptr;
|
||||
ForwardConflict *fwd_conflict = nullptr;
|
||||
return 0; // break here
|
||||
}
|
Loading…
Reference in New Issue