diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -1112,7 +1112,7 @@ CompilerType class_opaque_type = class_type->GetForwardCompilerType(); if (TypeSystemClang::IsCXXClassType(class_opaque_type)) { - if (class_opaque_type.IsBeingDefined() || alternate_defn) { + if (class_opaque_type.IsBeingDefined()) { if (!is_static && !die.HasChildren()) { // We have a C++ member function with no children (this // pointer!) and clang will get mad if we try and make diff --git a/lldb/test/API/lang/cpp/incomplete-types/members/Makefile b/lldb/test/API/lang/cpp/incomplete-types/members/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/incomplete-types/members/Makefile @@ -0,0 +1,10 @@ +CXX_SOURCES := main.cpp f.cpp g.cpp + +include Makefile.rules + +# Force main.cpp to be built with no debug information +main.o: CFLAGS = $(CFLAGS_NO_DEBUG) + +# And force -flimit-debug-info on the rest. +f.o: CFLAGS_EXTRAS += $(LIMIT_DEBUG_INFO_FLAGS) +g.o: CFLAGS_EXTRAS += $(LIMIT_DEBUG_INFO_FLAGS) diff --git a/lldb/test/API/lang/cpp/incomplete-types/members/TestCppIncompleteTypeMembers.py b/lldb/test/API/lang/cpp/incomplete-types/members/TestCppIncompleteTypeMembers.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/incomplete-types/members/TestCppIncompleteTypeMembers.py @@ -0,0 +1,32 @@ +""" +Test situations where we don't have a definition for a type, but we have (some) +of its member functions. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCppIncompleteTypeMembers(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "// break here", + lldb.SBFileSpec("f.cpp")) + + # Sanity check that we really have to debug info for this type. + this = self.expect_var_path("this", type="A *") + self.assertEquals(this.GetType().GetPointeeType().GetNumberOfFields(), + 0, str(this)) + + self.expect_var_path("af.x", value='42') + + lldbutil.run_break_set_by_source_regexp(self, "// break here", + extra_options="-f g.cpp") + self.runCmd("continue") + + self.expect_var_path("ag.a", value='47') diff --git a/lldb/test/API/lang/cpp/incomplete-types/members/a.h b/lldb/test/API/lang/cpp/incomplete-types/members/a.h new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/incomplete-types/members/a.h @@ -0,0 +1,14 @@ +#ifndef A_H +#define A_H + +class A { +public: + A(); + virtual void anchor(); + int f(); + int g(); + + int member = 47; +}; + +#endif diff --git a/lldb/test/API/lang/cpp/incomplete-types/members/f.cpp b/lldb/test/API/lang/cpp/incomplete-types/members/f.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/incomplete-types/members/f.cpp @@ -0,0 +1,8 @@ +#include "a.h" + +int A::f() { + struct Af { + int x, y; + } af{42, 47}; + return af.x + af.y; // break here +} diff --git a/lldb/test/API/lang/cpp/incomplete-types/members/g.cpp b/lldb/test/API/lang/cpp/incomplete-types/members/g.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/incomplete-types/members/g.cpp @@ -0,0 +1,8 @@ +#include "a.h" + +int A::g() { + struct Ag { + int a, b; + } ag{47, 42}; + return ag.a + ag.b; // break here +} diff --git a/lldb/test/API/lang/cpp/incomplete-types/members/main.cpp b/lldb/test/API/lang/cpp/incomplete-types/members/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/incomplete-types/members/main.cpp @@ -0,0 +1,9 @@ +#include "a.h" + +A::A() = default; +void A::anchor() {} + +int main() { + A().f(); + A().g(); +}