llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: Michael Buch (Michael137) <details> <summary>Changes</summary> This patch addresses an infinite recursion that happens when we try to check `HasSyntheticValue` for incomplete C++ types. We're inside of `ValueObject::Dereference` but `TypeSystemClang::GetDereferencedType` failed. When `GetPreferredDisplayLanguage` is `C++` we bail (according to a comment just above the language check this is a workaround). But for Objective-C we continue and create a `ValueObjectSyntheticFilter`, which internally will call back into `ValueObject::Dereference`. Hence the infinite recursion. The reason this happens for `std::vector` in the test-case is that the target was compiled with `Objective-C++`, so we treat it the same that we do Objective-C. This patch works around this issue by skipping this if we're dealing with a pointer to a C++ type. It's one of those cases where it's awkward for LLDB to know what to do because ObjC++ really does mean ObjC *or* C++. rdar://158058556 --- Full diff: https://github.com/llvm/llvm-project/pull/153454.diff 7 Files Affected: - (modified) lldb/include/lldb/Symbol/CompilerType.h (+2) - (modified) lldb/include/lldb/Symbol/TypeSystem.h (+3) - (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+20-1) - (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h (+3) - (modified) lldb/source/Symbol/CompilerType.cpp (+7) - (modified) lldb/source/ValueObject/ValueObject.cpp (+2) - (added) lldb/test/Shell/Expr/TestPrintCXXTypeAsObjCXX.test (+34) ``````````diff diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index df8489a7fe582..f91753afa684c 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -136,6 +136,8 @@ class CompilerType { bool IsBeingDefined() const; + bool IsClassTypeForLanguage(lldb::LanguageType language) const; + bool IsCharType() const; bool IsCompleteType() const; diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index 16a2e0b5a52fb..486aa722992dc 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -160,6 +160,9 @@ class TypeSystem : public PluginInterface, virtual bool IsCompleteType(lldb::opaque_compiler_type_t type) = 0; + virtual bool IsClassTypeForLanguage(lldb::opaque_compiler_type_t type, + lldb::LanguageType language) = 0; + virtual bool IsDefined(lldb::opaque_compiler_type_t type) = 0; virtual bool IsFloatingPointType(lldb::opaque_compiler_type_t type, diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index c4a917f59fb88..9ab816d3f27e0 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -80,8 +80,9 @@ #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h" #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h" -#include "Plugins/SymbolFile/PDB/PDBASTParser.h" #include "Plugins/SymbolFile/NativePDB/PdbAstBuilder.h" +#include "Plugins/SymbolFile/PDB/PDBASTParser.h" +#include "lldb/lldb-types.h" #include <cstdio> @@ -3747,6 +3748,24 @@ TypeSystemClang::GetCXXClassName(const CompilerType &type) { return std::string(cxx_record_decl->getIdentifier()->getNameStart()); } +bool TypeSystemClang::IsClassTypeForLanguage(lldb::opaque_compiler_type_t type, + lldb::LanguageType language) { + CompilerType ct(GetType(GetCanonicalQualType(type))); + if (!ct) + return false; + + if (language == lldb::eLanguageTypeObjC) + return IsObjCClassType(ct); + + if (language == lldb::eLanguageTypeObjC_plus_plus) + return IsObjCClassType(ct) || IsCXXClassType(ct); + + if (Language::LanguageIsCPlusPlus(language)) + return IsCXXClassType(ct); + + return false; +} + bool TypeSystemClang::IsCXXClassType(const CompilerType &type) { if (!type) return false; diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 709f89590ba3b..7a6123b1737a4 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -649,6 +649,9 @@ class TypeSystemClang : public TypeSystem { static bool IsCXXClassType(const CompilerType &type); + bool IsClassTypeForLanguage(lldb::opaque_compiler_type_t type, + lldb::LanguageType language) override; + bool IsDefined(lldb::opaque_compiler_type_t type) override; bool IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count, diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index 62c0ddf51c012..0e3f9229bfd6a 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -318,6 +318,13 @@ bool CompilerType::IsArrayOfScalarType() const { return false; } +bool CompilerType::IsClassTypeForLanguage(lldb::LanguageType language) const { + if (IsValid()) + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->IsClassTypeForLanguage(m_type, language); + return false; +} + bool CompilerType::IsBeingDefined() const { if (IsValid()) if (auto type_system_sp = GetTypeSystem()) diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp index 38b9f77e6ddda..8a6f0d8df325e 100644 --- a/lldb/source/ValueObject/ValueObject.cpp +++ b/lldb/source/ValueObject/ValueObject.cpp @@ -2816,6 +2816,8 @@ ValueObjectSP ValueObject::Dereference(Status &error) { // 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()) && + !compiler_type.GetPointeeType().IsClassTypeForLanguage( + lldb::eLanguageTypeC_plus_plus) && HasSyntheticValue()) { deref_compiler_type = compiler_type.GetPointeeType(); diff --git a/lldb/test/Shell/Expr/TestPrintCXXTypeAsObjCXX.test b/lldb/test/Shell/Expr/TestPrintCXXTypeAsObjCXX.test new file mode 100644 index 0000000000000..f304d94902b0b --- /dev/null +++ b/lldb/test/Shell/Expr/TestPrintCXXTypeAsObjCXX.test @@ -0,0 +1,34 @@ +# UNSUPPORTED: system-windows +# +# Tests that we don't crash when trying to `po` an incomplete +# C++ type with synthetic children in an ObjC++ target. +# +# RUN: split-file %s %t +# RUN: %clang_host -x objective-c++ -g %t/main.mm -o %t.out +# RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \ +# RUN: | FileCheck %s + +#--- main.mm + +#include <vector> + +int main() { + std::vector<int> * vec; + __builtin_debugtrap(); +} + +#--- commands.input + +run + +frame variable -O -- vec +# CHECK: frame variable +# CHECK-NEXT: warning: no object description available + +expression -O -- vec +# CHECK: expression +# CHECK-NEXT: size=error: incomplete type + +dwim-print -O -- vec +# CHECK: dwim-print +# CHECK-NEXT: size=error: incomplete type `````````` </details> https://github.com/llvm/llvm-project/pull/153454 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits