Author: Arthur Eubanks Date: 2022-11-21T09:30:29-08:00 New Revision: 8b80e8ee1fca660a5ea58cf701c2af8bba0dd89b
URL: https://github.com/llvm/llvm-project/commit/8b80e8ee1fca660a5ea58cf701c2af8bba0dd89b DIFF: https://github.com/llvm/llvm-project/commit/8b80e8ee1fca660a5ea58cf701c2af8bba0dd89b.diff LOG: [lldb] Disable looking at pointee types to find synthetic value for non-ObjC After D134378, we started seeing crashes with incomplete types (in the context of shared libraries). When trying to print a `std::vector<int> &` with only debug info for a declaration, we now try to use the formatter after D134378. With an incomplete type, this somehow goes into infinite recursion with the frames ``` lldb_private::ValueObject::Dereference lldb_private::ValueObjectSynthetic::CreateSynthFilter lldb_private::ValueObjectSynthetic::ValueObjectSynthetic lldb_private::ValueObject::CalculateSyntheticValue lldb_private::ValueObject::HasSyntheticValue ``` This has to do with `FrontEndWantsDereference` that some STL formatters set, causing recursion between the formatter (which tries to dereference), and dereferencing (which wants to know if there's a formatter to avoid dereferencing). The reason this only started appearing after D134378 was because previously with incomplete types, for names with `<`, lldb would attempt to parse template parameter DIEs, which were empty, then create an empty `ClassTemplateSpecializationDecl` which overrode the name used to lookup a formatter in `FormattersMatchData()` to not include template parameters (e.g. `std::vector<> &`). After D134378 we don't create a `ClassTemplateSpecializationDecl` when there are no template parameters and the name to lookup a formatter is the original name (e.g. `std::vector<int> &`). The code to try harder with incomplete child compiler types was added in D79554 for ObjC purposes. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D137983 Added: lldb/test/API/lang/cpp/incomplete-stl-types/Makefile lldb/test/API/lang/cpp/incomplete-stl-types/TestStlIncompleteTypes.py lldb/test/API/lang/cpp/incomplete-stl-types/f.cpp lldb/test/API/lang/cpp/incomplete-stl-types/main.cpp Modified: lldb/source/Core/ValueObject.cpp Removed: ################################################################################ diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 19d86bee40e1f..081f9c2cf5dcf 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -2673,7 +2673,10 @@ ValueObjectSP ValueObject::Dereference(Status &error) { // In case of incomplete child compiler type, use the pointee type and try // to recreate a new ValueObjectChild using it. if (!m_deref_valobj) { - if (HasSyntheticValue()) { + // FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g. + // `std::vector<int> &`). Remove ObjC restriction once that's resolved. + if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) && + HasSyntheticValue()) { child_compiler_type = compiler_type.GetPointeeType(); if (child_compiler_type) { diff --git a/lldb/test/API/lang/cpp/incomplete-stl-types/Makefile b/lldb/test/API/lang/cpp/incomplete-stl-types/Makefile new file mode 100644 index 0000000000000..2fd1763a62bb6 --- /dev/null +++ b/lldb/test/API/lang/cpp/incomplete-stl-types/Makefile @@ -0,0 +1,9 @@ +CXX_SOURCES := main.cpp f.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) diff --git a/lldb/test/API/lang/cpp/incomplete-stl-types/TestStlIncompleteTypes.py b/lldb/test/API/lang/cpp/incomplete-stl-types/TestStlIncompleteTypes.py new file mode 100644 index 0000000000000..06d960cd5c9f3 --- /dev/null +++ b/lldb/test/API/lang/cpp/incomplete-stl-types/TestStlIncompleteTypes.py @@ -0,0 +1,18 @@ +""" +Test situations where the debug info only has a declaration, no definition, for +an STL container with a formatter. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestStlIncompleteTypes(TestBase): + def test(self): + self.build() + lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("f.cpp")) + + var = self.frame().GetValueForVariablePath("v") + self.assertIn("set", var.GetDisplayTypeName()) diff --git a/lldb/test/API/lang/cpp/incomplete-stl-types/f.cpp b/lldb/test/API/lang/cpp/incomplete-stl-types/f.cpp new file mode 100644 index 0000000000000..af330d7db7709 --- /dev/null +++ b/lldb/test/API/lang/cpp/incomplete-stl-types/f.cpp @@ -0,0 +1,5 @@ +#include <set> + +void f(std::set<int> &v) { + // break here +} diff --git a/lldb/test/API/lang/cpp/incomplete-stl-types/main.cpp b/lldb/test/API/lang/cpp/incomplete-stl-types/main.cpp new file mode 100644 index 0000000000000..22409c87a0f69 --- /dev/null +++ b/lldb/test/API/lang/cpp/incomplete-stl-types/main.cpp @@ -0,0 +1,8 @@ +#include <set> + +void f(std::set<int> &v); + +int main() { + std::set<int> v; + f(v); +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits