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

Reply via email to