forked from OSchip/llvm-project
Fix the libcxx set, multiset, vector and bitset formatters to work on references.
The synthetic child providers for these classes had a type expression that matched pointers & references to the type, but the Front End only worked on the actual object. I fixed this by adding a way for the Synthetic Child FrontEnd provider to request dereference, and then had these formatters use that mode. <rdar://problem/40849836> Differential Revision: https://reviews.llvm.org/D49279 llvm-svn: 337035
This commit is contained in:
parent
0925c1fdff
commit
393fe62e33
|
@ -207,6 +207,19 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GetFrontEndWantsDereference() const {
|
||||||
|
return (m_flags & lldb::eTypeOptionFrontEndWantsDereference) ==
|
||||||
|
lldb::eTypeOptionFrontEndWantsDereference;
|
||||||
|
}
|
||||||
|
|
||||||
|
Flags &SetFrontEndWantsDereference(bool value = true) {
|
||||||
|
if (value)
|
||||||
|
m_flags |= lldb::eTypeOptionFrontEndWantsDereference;
|
||||||
|
else
|
||||||
|
m_flags &= ~lldb::eTypeOptionFrontEndWantsDereference;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t GetValue() { return m_flags; }
|
uint32_t GetValue() { return m_flags; }
|
||||||
|
|
||||||
void SetValue(uint32_t value) { m_flags = value; }
|
void SetValue(uint32_t value) { m_flags = value; }
|
||||||
|
@ -226,6 +239,8 @@ public:
|
||||||
bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
|
bool SkipsReferences() const { return m_flags.GetSkipReferences(); }
|
||||||
|
|
||||||
bool NonCacheable() const { return m_flags.GetNonCacheable(); }
|
bool NonCacheable() const { return m_flags.GetNonCacheable(); }
|
||||||
|
|
||||||
|
bool WantsDereference() const { return m_flags.GetFrontEndWantsDereference();}
|
||||||
|
|
||||||
void SetCascades(bool value) { m_flags.SetCascades(value); }
|
void SetCascades(bool value) { m_flags.SetCascades(value); }
|
||||||
|
|
||||||
|
|
|
@ -789,7 +789,9 @@ FLAGS_ENUM(TypeOptions){eTypeOptionNone = (0u),
|
||||||
eTypeOptionShowOneLiner = (1u << 5),
|
eTypeOptionShowOneLiner = (1u << 5),
|
||||||
eTypeOptionHideNames = (1u << 6),
|
eTypeOptionHideNames = (1u << 6),
|
||||||
eTypeOptionNonCacheable = (1u << 7),
|
eTypeOptionNonCacheable = (1u << 7),
|
||||||
eTypeOptionHideEmptyAggregates = (1u << 8)};
|
eTypeOptionHideEmptyAggregates = (1u << 8),
|
||||||
|
eTypeOptionFrontEndWantsDereference = (1u << 9)
|
||||||
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// This is the return value for frame comparisons. If you are comparing frame
|
// This is the return value for frame comparisons. If you are comparing frame
|
||||||
|
|
|
@ -35,7 +35,7 @@ class TestDataFormatterLibcxxBitset(TestBase):
|
||||||
"variable: %s, index: %d"%(name, size))
|
"variable: %s, index: %d"%(name, size))
|
||||||
|
|
||||||
@add_test_categories(["libc++"])
|
@add_test_categories(["libc++"])
|
||||||
def test(self):
|
def test_value(self):
|
||||||
"""Test that std::bitset is displayed correctly"""
|
"""Test that std::bitset is displayed correctly"""
|
||||||
self.build()
|
self.build()
|
||||||
lldbutil.run_to_source_breakpoint(self, '// break here',
|
lldbutil.run_to_source_breakpoint(self, '// break here',
|
||||||
|
@ -44,3 +44,18 @@ class TestDataFormatterLibcxxBitset(TestBase):
|
||||||
self.check("empty", 0)
|
self.check("empty", 0)
|
||||||
self.check("small", 13)
|
self.check("small", 13)
|
||||||
self.check("large", 200)
|
self.check("large", 200)
|
||||||
|
|
||||||
|
def test_ptr_and_ref(self):
|
||||||
|
"""Test that ref and ptr to std::bitset is displayed correctly"""
|
||||||
|
self.build()
|
||||||
|
(_, process, _, bkpt) = lldbutil.run_to_source_breakpoint(self,
|
||||||
|
'Check ref and ptr',
|
||||||
|
lldb.SBFileSpec("main.cpp", False))
|
||||||
|
|
||||||
|
self.check("ref", 13)
|
||||||
|
self.check("ptr", 13)
|
||||||
|
|
||||||
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
|
|
||||||
|
self.check("ref", 200)
|
||||||
|
self.check("ptr", 200)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
template<std::size_t N>
|
template<std::size_t N>
|
||||||
void fill(std::bitset<N> &b) {
|
void fill(std::bitset<N> &b) {
|
||||||
|
@ -10,11 +11,19 @@ void fill(std::bitset<N> &b) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<std::size_t N>
|
||||||
|
void by_ref_and_ptr(std::bitset<N> &ref, std::bitset<N> *ptr) {
|
||||||
|
// Check ref and ptr
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
std::bitset<0> empty;
|
std::bitset<0> empty;
|
||||||
std::bitset<13> small;
|
std::bitset<13> small;
|
||||||
fill(small);
|
fill(small);
|
||||||
std::bitset<200> large;
|
std::bitset<200> large;
|
||||||
fill(large);
|
fill(large);
|
||||||
return 0; // break here
|
by_ref_and_ptr(small, &small); // break here
|
||||||
|
by_ref_and_ptr(large, &large);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,22 +27,31 @@ class LibcxxMultiSetDataFormatterTestCase(TestBase):
|
||||||
self.assertTrue(var.IsValid())
|
self.assertTrue(var.IsValid())
|
||||||
return var.GetType().GetCanonicalType().GetName()
|
return var.GetType().GetCanonicalType().GetName()
|
||||||
|
|
||||||
|
def check_ii(self, var_name):
|
||||||
|
""" This checks the value of the bitset stored in ii at the call to by_ref_and_ptr.
|
||||||
|
We use this to make sure we get the same values for ii when we look at the object
|
||||||
|
directly, and when we look at a reference to the object. """
|
||||||
|
self.expect(
|
||||||
|
"frame variable " + var_name,
|
||||||
|
substrs=["size=7",
|
||||||
|
"[2] = 2",
|
||||||
|
"[3] = 3",
|
||||||
|
"[6] = 6"])
|
||||||
|
self.expect("frame variable " + var_name + "[2]", substrs=[" = 2"])
|
||||||
|
self.expect(
|
||||||
|
"p " + var_name,
|
||||||
|
substrs=[
|
||||||
|
"size=7",
|
||||||
|
"[2] = 2",
|
||||||
|
"[3] = 3",
|
||||||
|
"[6] = 6"])
|
||||||
|
|
||||||
@add_test_categories(["libc++"])
|
@add_test_categories(["libc++"])
|
||||||
def test_with_run_command(self):
|
def test_with_run_command(self):
|
||||||
"""Test that that file and class static variables display correctly."""
|
"""Test that that file and class static variables display correctly."""
|
||||||
self.build()
|
self.build()
|
||||||
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
|
(self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
|
||||||
|
self, "Set break point at this line.", lldb.SBFileSpec("main.cpp", False))
|
||||||
bkpt = self.target().FindBreakpointByID(
|
|
||||||
lldbutil.run_break_set_by_source_regexp(
|
|
||||||
self, "Set break point at this line."))
|
|
||||||
|
|
||||||
self.runCmd("run", RUN_SUCCEEDED)
|
|
||||||
|
|
||||||
# The stop reason of the thread should be breakpoint.
|
|
||||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
|
||||||
substrs=['stopped',
|
|
||||||
'stop reason = breakpoint'])
|
|
||||||
|
|
||||||
# This is the function to remove the custom formats in order to have a
|
# This is the function to remove the custom formats in order to have a
|
||||||
# clean slate for the next test case.
|
# clean slate for the next test case.
|
||||||
|
@ -63,7 +72,7 @@ class LibcxxMultiSetDataFormatterTestCase(TestBase):
|
||||||
"Type: " + ii_type)
|
"Type: " + ii_type)
|
||||||
|
|
||||||
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect(
|
self.expect(
|
||||||
"frame variable ii",
|
"frame variable ii",
|
||||||
substrs=[
|
substrs=[
|
||||||
|
@ -74,38 +83,26 @@ class LibcxxMultiSetDataFormatterTestCase(TestBase):
|
||||||
"[3] = 3",
|
"[3] = 3",
|
||||||
"[4] = 4",
|
"[4] = 4",
|
||||||
"[5] = 5"])
|
"[5] = 5"])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect(
|
|
||||||
"frame variable ii",
|
self.check_ii("ii")
|
||||||
substrs=[
|
|
||||||
"size=7",
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
"[2] = 2",
|
|
||||||
"[3] = 3",
|
|
||||||
"[6] = 6"])
|
|
||||||
self.expect(
|
|
||||||
"p ii",
|
|
||||||
substrs=[
|
|
||||||
"size=7",
|
|
||||||
"[2] = 2",
|
|
||||||
"[3] = 3",
|
|
||||||
"[6] = 6"])
|
|
||||||
self.expect("frame variable ii[2]", substrs=[" = 2"])
|
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
|
||||||
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
||||||
ss_type = self.getVariableType("ss")
|
ss_type = self.getVariableType("ss")
|
||||||
self.assertTrue(ss_type.startswith(self.namespace + "::multiset"),
|
self.assertTrue(ss_type.startswith(self.namespace + "::multiset"),
|
||||||
"Type: " + ss_type)
|
"Type: " + ss_type)
|
||||||
self.expect("frame variable ss", substrs=["size=0", "{}"])
|
self.expect("frame variable ss", substrs=["size=0", "{}"])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect(
|
self.expect(
|
||||||
"frame variable ss",
|
"frame variable ss",
|
||||||
substrs=[
|
substrs=[
|
||||||
"size=2",
|
"size=2",
|
||||||
'[0] = "a"',
|
'[0] = "a"',
|
||||||
'[1] = "a very long string is right here"'])
|
'[1] = "a very long string is right here"'])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect(
|
self.expect(
|
||||||
"frame variable ss",
|
"frame variable ss",
|
||||||
substrs=[
|
substrs=[
|
||||||
|
@ -123,7 +120,7 @@ class LibcxxMultiSetDataFormatterTestCase(TestBase):
|
||||||
'[0] = "a"',
|
'[0] = "a"',
|
||||||
'[1] = "a very long string is right here"'])
|
'[1] = "a very long string is right here"'])
|
||||||
self.expect("frame variable ss[2]", substrs=[' = "b"'])
|
self.expect("frame variable ss[2]", substrs=[' = "b"'])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect(
|
self.expect(
|
||||||
"frame variable ss",
|
"frame variable ss",
|
||||||
substrs=[
|
substrs=[
|
||||||
|
@ -131,3 +128,18 @@ class LibcxxMultiSetDataFormatterTestCase(TestBase):
|
||||||
'[0] = "a"',
|
'[0] = "a"',
|
||||||
'[1] = "a very long string is right here"',
|
'[1] = "a very long string is right here"',
|
||||||
'[2] = "c"'])
|
'[2] = "c"'])
|
||||||
|
|
||||||
|
@add_test_categories(["libc++"])
|
||||||
|
def test_ref_and_ptr(self):
|
||||||
|
"""Test that the data formatters work on ref and ptr."""
|
||||||
|
self.build()
|
||||||
|
(self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
|
||||||
|
self, "Stop here to check by ref and ptr.",
|
||||||
|
lldb.SBFileSpec("main.cpp", False))
|
||||||
|
# The reference should print just like the value:
|
||||||
|
self.check_ii("ref")
|
||||||
|
|
||||||
|
self.expect("frame variable ptr",
|
||||||
|
substrs=["ptr =", "size=7"])
|
||||||
|
self.expect("expr ptr",
|
||||||
|
substrs=["size=7"])
|
||||||
|
|
|
@ -16,6 +16,12 @@ int thefoo_rw(int arg = 1)
|
||||||
return g_the_foo;
|
return g_the_foo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void by_ref_and_ptr(intset &ref, intset *ptr)
|
||||||
|
{
|
||||||
|
// Stop here to check by ref and ptr
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
intset ii;
|
intset ii;
|
||||||
|
@ -31,7 +37,9 @@ int main()
|
||||||
|
|
||||||
ii.insert(6);
|
ii.insert(6);
|
||||||
thefoo_rw(1); // Set break point at this line.
|
thefoo_rw(1); // Set break point at this line.
|
||||||
|
|
||||||
|
by_ref_and_ptr(ii, &ii);
|
||||||
|
|
||||||
ii.clear();
|
ii.clear();
|
||||||
thefoo_rw(1); // Set break point at this line.
|
thefoo_rw(1); // Set break point at this line.
|
||||||
|
|
||||||
|
|
|
@ -27,21 +27,31 @@ class LibcxxSetDataFormatterTestCase(TestBase):
|
||||||
self.assertTrue(var.IsValid())
|
self.assertTrue(var.IsValid())
|
||||||
return var.GetType().GetCanonicalType().GetName()
|
return var.GetType().GetCanonicalType().GetName()
|
||||||
|
|
||||||
|
def check_ii(self, var_name):
|
||||||
|
""" This checks the value of the bitset stored in ii at the call to by_ref_and_ptr.
|
||||||
|
We use this to make sure we get the same values for ii when we look at the object
|
||||||
|
directly, and when we look at a reference to the object. """
|
||||||
|
self.expect(
|
||||||
|
"frame variable " + var_name,
|
||||||
|
substrs=["size=7",
|
||||||
|
"[2] = 2",
|
||||||
|
"[3] = 3",
|
||||||
|
"[6] = 6"])
|
||||||
|
self.expect("frame variable " + var_name + "[2]", substrs=[" = 2"])
|
||||||
|
self.expect(
|
||||||
|
"p " + var_name,
|
||||||
|
substrs=[
|
||||||
|
"size=7",
|
||||||
|
"[2] = 2",
|
||||||
|
"[3] = 3",
|
||||||
|
"[6] = 6"])
|
||||||
|
|
||||||
@add_test_categories(["libc++"])
|
@add_test_categories(["libc++"])
|
||||||
def test_with_run_command(self):
|
def test_with_run_command(self):
|
||||||
"""Test that that file and class static variables display correctly."""
|
"""Test that that file and class static variables display correctly."""
|
||||||
self.build()
|
self.build()
|
||||||
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
|
(self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
|
||||||
|
self, "Set break point at this line.", lldb.SBFileSpec("main.cpp", False))
|
||||||
bkpt = self.target().FindBreakpointByID(
|
|
||||||
lldbutil.run_break_set_by_source_regexp(self, "Set break point at this line."))
|
|
||||||
|
|
||||||
self.runCmd("run", RUN_SUCCEEDED)
|
|
||||||
|
|
||||||
# The stop reason of the thread should be breakpoint.
|
|
||||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
|
||||||
substrs=['stopped',
|
|
||||||
'stop reason = breakpoint'])
|
|
||||||
|
|
||||||
# This is the function to remove the custom formats in order to have a
|
# This is the function to remove the custom formats in order to have a
|
||||||
# clean slate for the next test case.
|
# clean slate for the next test case.
|
||||||
|
@ -62,7 +72,7 @@ class LibcxxSetDataFormatterTestCase(TestBase):
|
||||||
"Type: " + ii_type)
|
"Type: " + ii_type)
|
||||||
|
|
||||||
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect(
|
self.expect(
|
||||||
"frame variable ii",
|
"frame variable ii",
|
||||||
substrs=["size=6",
|
substrs=["size=6",
|
||||||
|
@ -72,24 +82,12 @@ class LibcxxSetDataFormatterTestCase(TestBase):
|
||||||
"[3] = 3",
|
"[3] = 3",
|
||||||
"[4] = 4",
|
"[4] = 4",
|
||||||
"[5] = 5"])
|
"[5] = 5"])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect(
|
self.check_ii("ii")
|
||||||
"frame variable ii",
|
|
||||||
substrs=["size=7",
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
"[2] = 2",
|
|
||||||
"[3] = 3",
|
|
||||||
"[6] = 6"])
|
|
||||||
self.expect("frame variable ii[2]", substrs=[" = 2"])
|
|
||||||
self.expect(
|
|
||||||
"p ii",
|
|
||||||
substrs=[
|
|
||||||
"size=7",
|
|
||||||
"[2] = 2",
|
|
||||||
"[3] = 3",
|
|
||||||
"[6] = 6"])
|
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
|
||||||
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
self.expect("frame variable ii", substrs=["size=0", "{}"])
|
||||||
|
|
||||||
ss_type = self.getVariableType("ss")
|
ss_type = self.getVariableType("ss")
|
||||||
|
@ -97,13 +95,13 @@ class LibcxxSetDataFormatterTestCase(TestBase):
|
||||||
"Type: " + ss_type)
|
"Type: " + ss_type)
|
||||||
|
|
||||||
self.expect("frame variable ss", substrs=["size=0", "{}"])
|
self.expect("frame variable ss", substrs=["size=0", "{}"])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect(
|
self.expect(
|
||||||
"frame variable ss",
|
"frame variable ss",
|
||||||
substrs=["size=2",
|
substrs=["size=2",
|
||||||
'[0] = "a"',
|
'[0] = "a"',
|
||||||
'[1] = "a very long string is right here"'])
|
'[1] = "a very long string is right here"'])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect(
|
self.expect(
|
||||||
"frame variable ss",
|
"frame variable ss",
|
||||||
substrs=["size=4",
|
substrs=["size=4",
|
||||||
|
@ -119,10 +117,26 @@ class LibcxxSetDataFormatterTestCase(TestBase):
|
||||||
'[0] = "a"',
|
'[0] = "a"',
|
||||||
'[1] = "a very long string is right here"'])
|
'[1] = "a very long string is right here"'])
|
||||||
self.expect("frame variable ss[2]", substrs=[' = "b"'])
|
self.expect("frame variable ss[2]", substrs=[' = "b"'])
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
self.expect(
|
self.expect(
|
||||||
"frame variable ss",
|
"frame variable ss",
|
||||||
substrs=["size=3",
|
substrs=["size=3",
|
||||||
'[0] = "a"',
|
'[0] = "a"',
|
||||||
'[1] = "a very long string is right here"',
|
'[1] = "a very long string is right here"',
|
||||||
'[2] = "c"'])
|
'[2] = "c"'])
|
||||||
|
|
||||||
|
@add_test_categories(["libc++"])
|
||||||
|
def test_ref_and_ptr(self):
|
||||||
|
"""Test that the data formatters work on ref and ptr."""
|
||||||
|
self.build()
|
||||||
|
(self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
|
||||||
|
self, "Stop here to check by ref and ptr.",
|
||||||
|
lldb.SBFileSpec("main.cpp", False))
|
||||||
|
# The reference should print just like the value:
|
||||||
|
self.check_ii("ref")
|
||||||
|
|
||||||
|
self.expect("frame variable ptr",
|
||||||
|
substrs=["ptr =", "size=7"])
|
||||||
|
self.expect("expr ptr",
|
||||||
|
substrs=["size=7"])
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,12 @@ int thefoo_rw(int arg = 1)
|
||||||
return g_the_foo;
|
return g_the_foo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void by_ref_and_ptr(intset &ref, intset *ptr)
|
||||||
|
{
|
||||||
|
// Stop here to check by ref and ptr
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
intset ii;
|
intset ii;
|
||||||
|
@ -31,7 +37,9 @@ int main()
|
||||||
|
|
||||||
ii.insert(6);
|
ii.insert(6);
|
||||||
thefoo_rw(1); // Set break point at this line.
|
thefoo_rw(1); // Set break point at this line.
|
||||||
|
|
||||||
|
by_ref_and_ptr(ii, &ii);
|
||||||
|
|
||||||
ii.clear();
|
ii.clear();
|
||||||
thefoo_rw(1); // Set break point at this line.
|
thefoo_rw(1); // Set break point at this line.
|
||||||
|
|
||||||
|
|
|
@ -20,21 +20,45 @@ class LibcxxVectorDataFormatterTestCase(TestBase):
|
||||||
@add_test_categories(["libc++"])
|
@add_test_categories(["libc++"])
|
||||||
@skipIf(debug_info="gmodules",
|
@skipIf(debug_info="gmodules",
|
||||||
bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048")
|
bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048")
|
||||||
|
|
||||||
|
def check_numbers(self, var_name):
|
||||||
|
self.expect("frame variable " + var_name,
|
||||||
|
substrs=[var_name + ' = size=7',
|
||||||
|
'[0] = 1',
|
||||||
|
'[1] = 12',
|
||||||
|
'[2] = 123',
|
||||||
|
'[3] = 1234',
|
||||||
|
'[4] = 12345',
|
||||||
|
'[5] = 123456',
|
||||||
|
'[6] = 1234567',
|
||||||
|
'}'])
|
||||||
|
|
||||||
|
self.expect("p " + var_name,
|
||||||
|
substrs=['$', 'size=7',
|
||||||
|
'[0] = 1',
|
||||||
|
'[1] = 12',
|
||||||
|
'[2] = 123',
|
||||||
|
'[3] = 1234',
|
||||||
|
'[4] = 12345',
|
||||||
|
'[5] = 123456',
|
||||||
|
'[6] = 1234567',
|
||||||
|
'}'])
|
||||||
|
|
||||||
|
# check access-by-index
|
||||||
|
self.expect("frame variable " + var_name + "[0]",
|
||||||
|
substrs=['1'])
|
||||||
|
self.expect("frame variable " + var_name + "[1]",
|
||||||
|
substrs=['12'])
|
||||||
|
self.expect("frame variable " + var_name + "[2]",
|
||||||
|
substrs=['123'])
|
||||||
|
self.expect("frame variable " + var_name + "[3]",
|
||||||
|
substrs=['1234'])
|
||||||
|
|
||||||
def test_with_run_command(self):
|
def test_with_run_command(self):
|
||||||
"""Test that that file and class static variables display correctly."""
|
"""Test that that file and class static variables display correctly."""
|
||||||
self.build()
|
self.build()
|
||||||
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
|
(self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
|
||||||
|
self, "break here", lldb.SBFileSpec("main.cpp", False))
|
||||||
bkpt = self.target().FindBreakpointByID(
|
|
||||||
lldbutil.run_break_set_by_source_regexp(
|
|
||||||
self, "break here"))
|
|
||||||
|
|
||||||
self.runCmd("run", RUN_SUCCEEDED)
|
|
||||||
|
|
||||||
# The stop reason of the thread should be breakpoint.
|
|
||||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
|
||||||
substrs=['stopped',
|
|
||||||
'stop reason = breakpoint'])
|
|
||||||
|
|
||||||
# This is the function to remove the custom formats in order to have a
|
# This is the function to remove the custom formats in order to have a
|
||||||
# clean slate for the next test case.
|
# clean slate for the next test case.
|
||||||
|
@ -54,7 +78,7 @@ class LibcxxVectorDataFormatterTestCase(TestBase):
|
||||||
self.expect("frame variable numbers",
|
self.expect("frame variable numbers",
|
||||||
substrs=['numbers = size=0'])
|
substrs=['numbers = size=0'])
|
||||||
|
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
|
|
||||||
# first value added
|
# first value added
|
||||||
self.expect("frame variable numbers",
|
self.expect("frame variable numbers",
|
||||||
|
@ -63,7 +87,7 @@ class LibcxxVectorDataFormatterTestCase(TestBase):
|
||||||
'}'])
|
'}'])
|
||||||
|
|
||||||
# add some more data
|
# add some more data
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
|
|
||||||
self.expect("frame variable numbers",
|
self.expect("frame variable numbers",
|
||||||
substrs=['numbers = size=4',
|
substrs=['numbers = size=4',
|
||||||
|
@ -96,47 +120,17 @@ class LibcxxVectorDataFormatterTestCase(TestBase):
|
||||||
self.runCmd("type summary delete int_vect")
|
self.runCmd("type summary delete int_vect")
|
||||||
|
|
||||||
# add some more data
|
# add some more data
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
|
|
||||||
self.expect("frame variable numbers",
|
self.check_numbers("numbers")
|
||||||
substrs=['numbers = size=7',
|
|
||||||
'[0] = 1',
|
|
||||||
'[1] = 12',
|
|
||||||
'[2] = 123',
|
|
||||||
'[3] = 1234',
|
|
||||||
'[4] = 12345',
|
|
||||||
'[5] = 123456',
|
|
||||||
'[6] = 1234567',
|
|
||||||
'}'])
|
|
||||||
|
|
||||||
self.expect("p numbers",
|
|
||||||
substrs=['$', 'size=7',
|
|
||||||
'[0] = 1',
|
|
||||||
'[1] = 12',
|
|
||||||
'[2] = 123',
|
|
||||||
'[3] = 1234',
|
|
||||||
'[4] = 12345',
|
|
||||||
'[5] = 123456',
|
|
||||||
'[6] = 1234567',
|
|
||||||
'}'])
|
|
||||||
|
|
||||||
# check access-by-index
|
|
||||||
self.expect("frame variable numbers[0]",
|
|
||||||
substrs=['1'])
|
|
||||||
self.expect("frame variable numbers[1]",
|
|
||||||
substrs=['12'])
|
|
||||||
self.expect("frame variable numbers[2]",
|
|
||||||
substrs=['123'])
|
|
||||||
self.expect("frame variable numbers[3]",
|
|
||||||
substrs=['1234'])
|
|
||||||
|
|
||||||
# clear out the vector and see that we do the right thing once again
|
# clear out the vector and see that we do the right thing once again
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
|
|
||||||
self.expect("frame variable numbers",
|
self.expect("frame variable numbers",
|
||||||
substrs=['numbers = size=0'])
|
substrs=['numbers = size=0'])
|
||||||
|
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
|
|
||||||
# first value added
|
# first value added
|
||||||
self.expect("frame variable numbers",
|
self.expect("frame variable numbers",
|
||||||
|
@ -170,7 +164,7 @@ class LibcxxVectorDataFormatterTestCase(TestBase):
|
||||||
'is',
|
'is',
|
||||||
'smart'])
|
'smart'])
|
||||||
|
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
|
|
||||||
self.expect("frame variable strings",
|
self.expect("frame variable strings",
|
||||||
substrs=['vector has 4 items'])
|
substrs=['vector has 4 items'])
|
||||||
|
@ -181,7 +175,22 @@ class LibcxxVectorDataFormatterTestCase(TestBase):
|
||||||
self.expect("frame variable strings[1]",
|
self.expect("frame variable strings[1]",
|
||||||
substrs=['is'])
|
substrs=['is'])
|
||||||
|
|
||||||
lldbutil.continue_to_breakpoint(self.process(), bkpt)
|
lldbutil.continue_to_breakpoint(process, bkpt)
|
||||||
|
|
||||||
self.expect("frame variable strings",
|
self.expect("frame variable strings",
|
||||||
substrs=['vector has 0 items'])
|
substrs=['vector has 0 items'])
|
||||||
|
|
||||||
|
def test_ref_and_ptr(self):
|
||||||
|
"""Test that that file and class static variables display correctly."""
|
||||||
|
self.build()
|
||||||
|
(self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
|
||||||
|
self, "Stop here to check by ref", lldb.SBFileSpec("main.cpp", False))
|
||||||
|
|
||||||
|
# The reference should display the same was as the value did
|
||||||
|
self.check_numbers("ref")
|
||||||
|
|
||||||
|
# The pointer should just show the right number of elements:
|
||||||
|
|
||||||
|
self.expect("frame variable ptr", substrs=['ptr =', ' size=7'])
|
||||||
|
|
||||||
|
self.expect("p ptr", substrs=['$', 'size=7'])
|
||||||
|
|
|
@ -4,6 +4,12 @@
|
||||||
typedef std::vector<int> int_vect;
|
typedef std::vector<int> int_vect;
|
||||||
typedef std::vector<std::string> string_vect;
|
typedef std::vector<std::string> string_vect;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void by_ref_and_ptr(std::vector<T> &ref, std::vector<T> *ptr) {
|
||||||
|
// Stop here to check by ref
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
int_vect numbers;
|
int_vect numbers;
|
||||||
|
@ -14,6 +20,7 @@ int main()
|
||||||
(numbers.push_back(12345)); // break here
|
(numbers.push_back(12345)); // break here
|
||||||
(numbers.push_back(123456));
|
(numbers.push_back(123456));
|
||||||
(numbers.push_back(1234567));
|
(numbers.push_back(1234567));
|
||||||
|
by_ref_and_ptr(numbers, &numbers);
|
||||||
|
|
||||||
printf("break here");
|
printf("break here");
|
||||||
numbers.clear();
|
numbers.clear();
|
||||||
|
|
|
@ -129,7 +129,19 @@ lldb::ValueType ValueObjectSynthetic::GetValueType() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValueObjectSynthetic::CreateSynthFilter() {
|
void ValueObjectSynthetic::CreateSynthFilter() {
|
||||||
m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*m_parent));
|
ValueObject *valobj_for_frontend = m_parent;
|
||||||
|
if (m_synth_sp->WantsDereference())
|
||||||
|
{
|
||||||
|
CompilerType type = m_parent->GetCompilerType();
|
||||||
|
if (type.IsValid() && type.IsPointerOrReferenceType())
|
||||||
|
{
|
||||||
|
Status error;
|
||||||
|
lldb::ValueObjectSP deref_sp = m_parent->Dereference(error);
|
||||||
|
if (error.Success())
|
||||||
|
valobj_for_frontend = deref_sp.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*valobj_for_frontend));
|
||||||
if (!m_synth_filter_ap.get())
|
if (!m_synth_filter_ap.get())
|
||||||
m_synth_filter_ap = llvm::make_unique<DummySyntheticFrontEnd>(*m_parent);
|
m_synth_filter_ap = llvm::make_unique<DummySyntheticFrontEnd>(*m_parent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -423,18 +423,20 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
||||||
SyntheticChildren::Flags stl_synth_flags;
|
SyntheticChildren::Flags stl_synth_flags;
|
||||||
stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
|
stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(
|
||||||
false);
|
false);
|
||||||
|
SyntheticChildren::Flags stl_deref_flags = stl_synth_flags;
|
||||||
|
stl_deref_flags.SetFrontEndWantsDereference();
|
||||||
|
|
||||||
AddCXXSynthetic(
|
AddCXXSynthetic(
|
||||||
cpp_category_sp,
|
cpp_category_sp,
|
||||||
lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator,
|
lldb_private::formatters::LibcxxBitsetSyntheticFrontEndCreator,
|
||||||
"libc++ std::bitset synthetic children",
|
"libc++ std::bitset synthetic children",
|
||||||
ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), stl_synth_flags,
|
ConstString("^std::__(ndk)?1::bitset<.+>(( )?&)?$"), stl_deref_flags,
|
||||||
true);
|
true);
|
||||||
AddCXXSynthetic(
|
AddCXXSynthetic(
|
||||||
cpp_category_sp,
|
cpp_category_sp,
|
||||||
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
|
lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator,
|
||||||
"libc++ std::vector synthetic children",
|
"libc++ std::vector synthetic children",
|
||||||
ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_synth_flags,
|
ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_deref_flags,
|
||||||
true);
|
true);
|
||||||
AddCXXSynthetic(
|
AddCXXSynthetic(
|
||||||
cpp_category_sp,
|
cpp_category_sp,
|
||||||
|
@ -457,13 +459,13 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
||||||
cpp_category_sp,
|
cpp_category_sp,
|
||||||
lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
|
lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
|
||||||
"libc++ std::set synthetic children",
|
"libc++ std::set synthetic children",
|
||||||
ConstString("^std::__(ndk)?1::set<.+> >(( )?&)?$"), stl_synth_flags,
|
ConstString("^std::__(ndk)?1::set<.+> >(( )?&)?$"), stl_deref_flags,
|
||||||
true);
|
true);
|
||||||
AddCXXSynthetic(
|
AddCXXSynthetic(
|
||||||
cpp_category_sp,
|
cpp_category_sp,
|
||||||
lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
|
lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator,
|
||||||
"libc++ std::multiset synthetic children",
|
"libc++ std::multiset synthetic children",
|
||||||
ConstString("^std::__(ndk)?1::multiset<.+> >(( )?&)?$"), stl_synth_flags,
|
ConstString("^std::__(ndk)?1::multiset<.+> >(( )?&)?$"), stl_deref_flags,
|
||||||
true);
|
true);
|
||||||
AddCXXSynthetic(
|
AddCXXSynthetic(
|
||||||
cpp_category_sp,
|
cpp_category_sp,
|
||||||
|
|
Loading…
Reference in New Issue