Index: include/lldb/API/SBValue.h =================================================================== --- include/lldb/API/SBValue.h +++ include/lldb/API/SBValue.h @@ -129,6 +129,9 @@ const char * GetLocation (); + bool + PrintValueSummary (std::string& valsum); + // Deprecated - use the one that takes SBError& bool SetValueFromCString (const char *value_str); Index: source/API/SBValue.cpp =================================================================== --- source/API/SBValue.cpp +++ source/API/SBValue.cpp @@ -706,6 +706,32 @@ return cstr; } +// Used by LLDB-MI to print characters and strings +bool +SBValue::PrintValueSummary (std::string& valsum) +{ + std::string val; + ValueLocker locker; + lldb_private::TypeSummaryOptions options; + + lldb::ValueObjectSP value_sp(GetSP(locker)); + if (value_sp && value_sp->UpdateValueIfNeeded(true)) + { + lldb::TypeSummaryImplSP summary = value_sp->GetSummaryFormat(); + if (summary && summary->FormatObject(value_sp.get(), valsum, options)) + { + if (summary->DoesPrintValue(value_sp.get()) && + value_sp->GetValueAsCString(lldb::eFormatDefault, val) && + !val.empty()) + { + valsum = val + " " + valsum; + } + return true; + } + } + return false; +} + // Deprecated - use the one that takes an lldb::SBError bool SBValue::SetValueFromCString (const char *value_str) Index: test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py =================================================================== --- test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py +++ test/tools/lldb-mi/variable/TestMiGdbSetShowPrint.py @@ -1,3 +1,4 @@ +# coding=utf8 """ Test lldb-mi -gdb-set and -gdb-show commands for 'print option-name'. """ @@ -9,6 +10,22 @@ class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase): mydir = TestBase.compute_mydir(__file__) + # evaluates array when char-array-as-string is off + def eval_array(self, name, length, typ): + self.runCmd("-var-create - * " + name) + self.expect("\^done,name=\"var\d+\",numchild=\"" + + str(length) + + "\",value=\"\[" + str(length) + "\]\",type=\"" + + typ + " \[" + str(length) + "\]\",thread-id=\"1\",has_more=\"0\"") + + # evaluates array or pointer when char-array-as-string is on + def eval_ap(self, name, value, sum_part, typ): + self.runCmd("-var-create - * " + name) + self.expect("\^done,name=\"var\d+\",numchild=\"[0-9]+\",value=\"" + + value + + "\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\""+ sum_part +"\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"" + + typ + + "\",thread-id=\"1\",has_more=\"0\"") @lldbmi_test @skipIfWindows #llvm.org/pr24452: Get lldb-mi working on Windows @@ -36,28 +53,22 @@ self.expect("\^done,value=\"off\"") # Test that an char* is expanded to string when print char-array-as-string is "off" - self.runCmd("-var-create - * cp") - self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ \\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char \*\",thread-id=\"1\",has_more=\"0\"") + self.eval_ap("cp", "0x[0-9a-f]+ ", "hello", "const char \\*") # Test that an char[] isn't expanded to string when print char-array-as-string is "off" - self.runCmd("-var-create - * ca") - self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"\[10\]\",type=\"const char \[10\]\",thread-id=\"1\",has_more=\"0\"") + self.eval_array("ca", 10, "const char"); # Test that an char16_t* is expanded to string when print char-array-as-string is "off" - self.runCmd("-var-create - * u16p") - self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ u\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char16_t \*\",thread-id=\"1\",has_more=\"0\"") + self.eval_ap("u16p", "0x[0-9a-f]+ u", "hello", "const char16_t \\*") # Test that an char16_t[] isn't expanded to string when print char-array-as-string is "off" - self.runCmd("-var-create - * u16a") - self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"\[10\]\",type=\"const char16_t \[10\]\",thread-id=\"1\",has_more=\"0\"") + self.eval_array("u16a", 10, "const char16_t"); # Test that an char32_t* is expanded to string when print char-array-as-string is "off" - self.runCmd("-var-create - * u32p") - self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ U\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char32_t \*\",thread-id=\"1\",has_more=\"0\"") + self.eval_ap("u32p", "0x[0-9a-f]+ U", "hello", "const char32_t \\*") # Test that an char32_t[] isn't expanded to string when print char-array-as-string is "off" - self.runCmd("-var-create - * u32a") - self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"\[10\]\",type=\"const char32_t \[10\]\",thread-id=\"1\",has_more=\"0\"") + self.eval_array("u32a", 10, "const char32_t"); # Test that -gdb-set can set print char-array-as-string flag self.runCmd("-gdb-set print char-array-as-string on") @@ -68,28 +79,36 @@ self.expect("\^done,value=\"on\"") # Test that an char* with escape chars is expanded to string when print char-array-as-string is "on" - self.runCmd("-var-create - * cp") - self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ \\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char \*\",thread-id=\"1\",has_more=\"0\"") + self.eval_ap("cp", "0x[0-9a-f]+ ", "hello", "const char \\*") # Test that an char[] with escape chars is expanded to string when print char-array-as-string is "on" - self.runCmd("-var-create - * ca") - self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char \[10\]\",thread-id=\"1\",has_more=\"0\"") + self.eval_ap("ca", "", "hello", "const char \\[[0-9]+\\]") # Test that an char16_t* with esc1ape chars is expanded to string when print char-array-as-string is "on" - self.runCmd("-var-create - * u16p") - self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ u\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char16_t \*\",thread-id=\"1\",has_more=\"0\"") + self.eval_ap("u16p", "0x[0-9a-f]+ u", "hello", "const char16_t \\*") # Test that an char16_t[] with escape chars is expanded to string when print char-array-as-string is "on" - self.runCmd("-var-create - * u16a") - self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"u\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char16_t \[10\]\",thread-id=\"1\",has_more=\"0\"") + self.eval_ap("u16a", "u", "hello", "const char16_t \\[[0-9]+\\]") # Test that an char32_t* with escape chars is expanded to string when print char-array-as-string is "on" - self.runCmd("-var-create - * u32p") - self.expect("\^done,name=\"var\d+\",numchild=\"1\",value=\"0x[0-9a-f]+ U\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char32_t \*\",thread-id=\"1\",has_more=\"0\"") + self.eval_ap("u32p", "0x[0-9a-f]+ U", "hello", "const char32_t \\*") # Test that an char32_t[] with escape chars is expanded to string when print char-array-as-string is "on" - self.runCmd("-var-create - * u32a") - self.expect("\^done,name=\"var\d+\",numchild=\"10\",value=\"U\\\\\\\"\\\\\\\\t\\\\\\\\\\\\\"hello\\\\\\\\\\\\\"\\\\\\\\n\\\\\\\"\",type=\"const char32_t \[10\]\",thread-id=\"1\",has_more=\"0\"") + self.eval_ap("u32a", "U", "hello", "const char32_t \\[[0-9]+\\]") + + # Test russian unicode strings + rval = "Эмбаркадеро" + self.eval_ap("u16p_rus", "0x[0-9a-f]+ u", rval, "const char16_t \\*") + self.eval_ap("u16a_rus", "u", rval, "const char16_t \\[[0-9]+\\]") + self.eval_ap("u32p_rus", "0x[0-9a-f]+ U", rval, "const char32_t \\*") + self.eval_ap("u32a_rus", "U", rval, "const char32_t \\[[0-9]+\\]") + + # Additional test for escaping + # \\\\\\\" \\n -> \\\" \n + # in python regex \\\\ -> \ + rval = '\\\\' * 7 + '" ' + '\\\\' * 2 + 'n' + self.eval_ap("u16p_esc", "0x[0-9a-f]+ u", rval, "const char16_t \\*") + self.eval_ap("u16a_esc", "u", rval, "const char16_t \\[[0-9]+\\]") # Test that -gdb-set print char-array-as-string fails if "on"/"off" isn't specified self.runCmd("-gdb-set print char-array-as-string") @@ -101,6 +120,30 @@ @lldbmi_test @skipIfWindows #llvm.org/pr24452: Get lldb-mi working on Windows + @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races + @skipIfLinux # llvm.org/pr22841: lldb-mi tests fail on all Linux buildbots + def test_lldbmi_stl_types(self): + """Test that 'lldb-mi --interpreter' print summary for STL types.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to BP_gdb_set_show_print_char_array_as_string_test + line = line_number('main.cpp', '// BP_cpp_stl_types_test') + self.runCmd("-break-insert main.cpp:%d" % line) + self.expect("\^done,bkpt={number=\"1\"") + self.runCmd("-exec-run") + self.expect("\^running") + self.expect("\*stopped,reason=\"breakpoint-hit\"") + + # Test for std::string + self.eval_ap("mi_string", "", "hello", "std::__1::string") + + @lldbmi_test + @skipIfWindows #llvm.org/pr24452: Get lldb-mi working on Windows @expectedFailureGcc("https://llvm.org/bugs/show_bug.cgi?id=23357") @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races def test_lldbmi_gdb_set_show_print_expand_aggregates(self): @@ -129,8 +172,7 @@ self.expect("\^done,name=\"var1\",numchild=\"3\",value=\"{\.\.\.}\",type=\"complex_type\",thread-id=\"1\",has_more=\"0\"") # Test that composite type[] isn't expanded when print expand-aggregates is "off" - self.runCmd("-var-create var2 * complx_array") - self.expect("\^done,name=\"var2\",numchild=\"2\",value=\"\[2\]\",type=\"complex_type \[2\]\",thread-id=\"1\",has_more=\"0\"") + self.eval_array("complx_array", 2, "complex_type") # Test that a struct with a char first element is not formatted as a string self.runCmd("-var-create - * &nstr") Index: test/tools/lldb-mi/variable/main.cpp =================================================================== --- test/tools/lldb-mi/variable/main.cpp +++ test/tools/lldb-mi/variable/main.cpp @@ -8,6 +8,9 @@ //===----------------------------------------------------------------------===// #include +#include + +using namespace std; struct complex_type { @@ -64,9 +67,23 @@ const char32_t *u32p = U"\t\"hello\"\n"; const char32_t u32a[] = U"\t\"hello\"\n"; + const char16_t* u16p_rus = u"\t\"Эмбаркадеро\"\n"; + const char16_t u16a_rus[] = u"\t\"Эмбаркадеро\"\n"; + const char32_t* u32p_rus = U"\t\"Эмбаркадеро\"\n"; + const char32_t u32a_rus[] = U"\t\"Эмбаркадеро\"\n"; + + const char16_t* u16p_esc = u"\t\"\\\" \n\"\n"; + const char16_t u16a_esc[] = u"\t\"\\\" \n\"\n"; // BP_gdb_set_show_print_char_array_as_string_test } +void +cpp_stl_types_test(void) +{ + string mi_string = "\t\"hello\"\n"; + // BP_cpp_stl_types_test +} + struct not_str { not_str(char _c, int _f) @@ -105,6 +122,7 @@ var_update_test(); var_list_children_test(); gdb_set_show_print_char_array_as_string_test(); + cpp_stl_types_test(); gdb_set_show_print_expand_aggregates(); gdb_set_show_print_aggregate_field_names(); return 0; // BP_return Index: tools/lldb-mi/MICmnLLDBUtilSBValue.cpp =================================================================== --- tools/lldb-mi/MICmnLLDBUtilSBValue.cpp +++ tools/lldb-mi/MICmnLLDBUtilSBValue.cpp @@ -17,6 +17,11 @@ #include "MICmnMIValueTuple.h" #include "MIUtilString.h" +#if 0 +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/TypeSummary.h" +#endif + //++ ------------------------------------------------------------------------------------ // Details: CMICmnLLDBUtilSBValue constructor. // Type: Method. @@ -165,6 +170,17 @@ return MIstatus::success; } } + else + { + // Treat composite value which has registered summary + // (for example with AddCXXSummary) as simple value + std::string result; + if (m_rValue.PrintValueSummary(result)) + { + vwrValue = result.c_str(); + return MIstatus::success; + } + } // Composite variable type i.e. struct return MIstatus::failure; @@ -180,6 +196,10 @@ CMIUtilString CMICmnLLDBUtilSBValue::GetSimpleValueChar() const { + std::string result; + if (m_rValue.PrintValueSummary(result)) + return result.c_str(); + const uint64_t value = m_rValue.GetValueAsUnsigned(); if (value == 0) { @@ -223,10 +243,14 @@ CMIUtilString CMICmnLLDBUtilSBValue::GetSimpleValueCStringPointer() const { + std::string result; const char *value = m_rValue.GetValue(); if (value == nullptr) return m_pUnkwn; + if (m_rValue.PrintValueSummary(result)) + return result.c_str(); + lldb::SBValue child = m_rValue.GetChildAtIndex(0); const lldb::BasicType eType = child.GetType().GetBasicType(); switch (eType) @@ -266,6 +290,10 @@ CMIUtilString CMICmnLLDBUtilSBValue::GetSimpleValueCStringArray() const { + std::string result; + if (m_rValue.PrintValueSummary(result)) + return result.c_str(); + const MIuint nChildren = m_rValue.GetNumChildren(); lldb::SBValue child = m_rValue.GetChildAtIndex(0); const lldb::BasicType eType = child.GetType().GetBasicType();