Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -104,7 +104,7 @@ ParseTemplateParameterInfos (const DWARFDIE &parent_die, lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); - size_t + bool ParseChildMembers (const lldb_private::SymbolContext& sc, const DWARFDIE &die, lldb_private::CompilerType &class_clang_type, Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1770,7 +1770,6 @@ type->GetName().AsCString()); assert (clang_type); DWARFAttributes attributes; - switch (tag) { case DW_TAG_structure_type: @@ -1817,17 +1816,18 @@ DWARFDIECollection member_function_dies; DelayedPropertyList delayed_properties; - ParseChildMembers (sc, - die, - clang_type, - class_language, - base_classes, - member_accessibilities, - member_function_dies, - delayed_properties, - default_accessibility, - is_a_class, - layout_info); + if (!ParseChildMembers (sc, + die, + clang_type, + class_language, + base_classes, + member_accessibilities, + member_function_dies, + delayed_properties, + default_accessibility, + is_a_class, + layout_info)) + return false; // Now parse any methods if there were any... size_t num_functions = member_function_dies.Size(); @@ -2354,7 +2354,7 @@ } -size_t +bool DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, const DWARFDIE &parent_die, CompilerType &class_clang_type, @@ -2370,7 +2370,7 @@ if (!parent_die) return 0; - size_t count = 0; + uint32_t incomplete_member_info_count = 0; uint32_t member_idx = 0; BitfieldInfo last_field_info; @@ -2704,6 +2704,8 @@ } CompilerType member_clang_type = member_type->GetLayoutCompilerType (); + if (!member_clang_type.IsCompleteType() && !member_clang_type.GetCompleteType()) + incomplete_member_info_count += 1; { // Older versions of clang emit array[0] and array[1] in the same way (). @@ -2926,7 +2928,7 @@ } } - return count; + return incomplete_member_info_count == 0; } Index: test/lang/cpp/incomplete-types/Makefile =================================================================== --- /dev/null +++ test/lang/cpp/incomplete-types/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules Index: test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py =================================================================== --- /dev/null +++ test/lang/cpp/incomplete-types/TestCppIncompleteTypes.py @@ -0,0 +1,59 @@ +import lldb +from lldbtest import * +import lldbutil + +class TestCppIncompleteTypes(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @dwarf_test + @skipIfDarwin + @skipIfGcc + def test_with_dwarf_and_run_command(self): + self.buildDwarf() + self.check() + + def setUp(self): + TestBase.setUp(self) + + def check(self): + # Get main source file + src_file = "main.cpp" + src_file_spec = lldb.SBFileSpec(src_file) + self.assertTrue(src_file_spec.IsValid(), "Main source file") + + # Get the path of the executable + cwd = os.getcwd() + exe_file = "a.out" + exe_path = os.path.join(cwd, exe_file) + + # Load the executable + target = self.dbg.CreateTarget(exe_path) + self.assertTrue(target.IsValid(), VALID_TARGET) + + # Break on main function + main_breakpoint = target.BreakpointCreateBySourceRegex("break here", src_file_spec) + self.assertTrue(main_breakpoint.IsValid() and main_breakpoint.GetNumLocations() >= 1, VALID_BREAKPOINT) + + # Launch the process + args = None + env = None + process = target.LaunchSimple(args, env, self.get_process_working_directory()) + self.assertTrue(process.IsValid(), PROCESS_IS_VALID) + + # Get the thread of the process + self.assertTrue(process.GetState() == lldb.eStateStopped, PROCESS_STOPPED) + thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint) + + # Get frame for current thread + frame = thread.GetSelectedFrame() + + value_f = frame.EvaluateExpression("f") + self.assertTrue(value_f.IsValid(), "'expr f' results in a valid SBValue object") + self.assertFalse(value_f.GetError().Success(), "'expr f' results in an error, but LLDB does not crash") + +if __name__ == '__main__': + import atexit + lldb.SBDebugger.Initialize() + atexit.register(lambda: lldb.SBDebugger.Terminate()) + unittest2.main() Index: test/lang/cpp/incomplete-types/main.cpp =================================================================== --- /dev/null +++ test/lang/cpp/incomplete-types/main.cpp @@ -0,0 +1,15 @@ +#include + +class Foo { +public: + Foo(std::string x) : s(x) {} + +private: + std::string s; +}; + +int main() +{ + Foo f("qwerty"); + return 0; // break here +}