Index: test/tools/lldb-mi/variable/TestMiVar.py =================================================================== --- test/tools/lldb-mi/variable/TestMiVar.py +++ test/tools/lldb-mi/variable/TestMiVar.py @@ -354,5 +354,46 @@ self.runCmd("-var-create - * std_string") self.expect('\^done,name="var\d+",numchild="[0-9]+",value="\\\\"hello\\\\"",type="std::[\S]*?string",thread-id="1",has_more="0"') + @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_var_create_for_unnamed_objects(self): + """Test that 'lldb-mi --interpreter' can expand unnamed structures and unions.""" + + self.spawnLldbMi(args = None) + + # Load executable + self.runCmd("-file-exec-and-symbols %s" % self.myexe) + self.expect("\^done") + + # Run to breakpoint + line = line_number('main.cpp', '// BP_unnamed_objects_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\"") + + # Evaluate struct_with_unions type and its children + self.runCmd("-var-create v0 * swu") + self.expect('\^done,name="v0",numchild="2",value="\{\.\.\.\}",type="struct_with_unions",thread-id="1",has_more="0"') + + self.runCmd("-var-list-children v0") + + # inspect the first unnamed union + self.runCmd("-var-list-children v0.$0") + self.runCmd("-var-evaluate-expression v0.$0.u_i") + self.expect('\^done,value="1"') + + # inspect the second unnamed union + self.runCmd("-var-list-children v0.$1") + self.runCmd("-var-evaluate-expression v0.$1.u1") + self.expect('\^done,value="-1"') + # inspect unnamed structure + self.runCmd("-var-list-children v0.$1.$1") + self.runCmd("-var-evaluate-expression v0.$1.$1.s1") + self.expect('\^done,value="-1"') + if __name__ == '__main__': unittest2.main() Index: test/tools/lldb-mi/variable/main.cpp =================================================================== --- test/tools/lldb-mi/variable/main.cpp +++ test/tools/lldb-mi/variable/main.cpp @@ -27,6 +27,25 @@ int pcomplex_type::si; +struct struct_with_unions +{ + struct_with_unions(): u_i(1), u1(-1) {} + union + { + int u_i; + int u_j; + }; + union + { + int u1; + struct + { + short s1; + short s2; + }; + }; +}; + void var_update_test(void) { @@ -80,6 +99,13 @@ // BP_cpp_stl_types_test } +void +unnamed_objects_test(void) +{ + struct_with_unions swu; + // BP_unnamed_objects_test +} + struct not_str { not_str(char _c, int _f) @@ -119,6 +145,7 @@ var_list_children_test(); gdb_set_show_print_char_array_as_string_test(); cpp_stl_types_test(); + unnamed_objects_test(); gdb_set_show_print_expand_aggregates(); gdb_set_show_print_aggregate_field_names(); return 0; // BP_return Index: tools/lldb-mi/MICmdCmdVar.cpp =================================================================== --- tools/lldb-mi/MICmdCmdVar.cpp +++ tools/lldb-mi/MICmdCmdVar.cpp @@ -1015,7 +1015,9 @@ lldb::SBValue member = rValue.GetChildAtIndex(i); const CMICmnLLDBUtilSBValue utilValue(member); const CMIUtilString strExp = utilValue.GetName(); - const CMIUtilString name(CMIUtilString::Format("%s.%s", rVarObjName.c_str(), strExp.c_str())); + const CMIUtilString name(strExp.empty() ? + CMIUtilString::Format("%s.$%u", rVarObjName.c_str(), i) : + CMIUtilString::Format("%s.%s", rVarObjName.c_str(), strExp.c_str())); const MIuint nChildren = member.GetNumChildren(); const CMIUtilString strThreadId(CMIUtilString::Format("%u", member.GetThread().GetIndexID())); Index: tools/lldb-mi/MICmnLLDBUtilSBValue.cpp =================================================================== --- tools/lldb-mi/MICmnLLDBUtilSBValue.cpp +++ tools/lldb-mi/MICmnLLDBUtilSBValue.cpp @@ -61,7 +61,7 @@ CMICmnLLDBUtilSBValue::GetName() const { const char *pName = m_bValidSBValue ? m_rValue.GetName() : nullptr; - const CMIUtilString text((pName != nullptr) ? pName : m_pUnkwn); + const CMIUtilString text((pName != nullptr) ? pName : CMIUtilString()); return text; }