zequanwu updated this revision to Diff 473077.
zequanwu added a comment.

Update to forcefully complete a record type only if it has empty debug info and 
is required to have complete type.

I basically copied RequireCompleteType 
<https://github.com/llvm/llvm-project/blob/main/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp#L230-L250>
 from dwarf plugin. Calling it when the tag type is one of 1. an element type 
2. an base class 3. a class member. This is the same way that dwarf plugin is 
doing.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134066/new/

https://reviews.llvm.org/D134066

Files:
  lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
  lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
  lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
  lldb/test/Shell/SymbolFile/NativePDB/Inputs/incomplete-tag-type.cpp
  lldb/test/Shell/SymbolFile/NativePDB/incomplete-tag-type.cpp

Index: lldb/test/Shell/SymbolFile/NativePDB/incomplete-tag-type.cpp
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/NativePDB/incomplete-tag-type.cpp
@@ -0,0 +1,28 @@
+// clang-format off
+// REQUIRES: lld, x86
+
+// RUN: %clang_cl --target=x86_64-windows-msvc -c /Fo%t1.obj -- %p/Inputs/incomplete-tag-type.cpp
+// RUN: %clang_cl --target=x86_64-windows-msvc /O1 /Z7 -c /Fo%t2.obj -- %s
+// RUN: lld-link /debug:full /nodefaultlib /entry:main %t1.obj %t2.obj /out:%t.exe /pdb:%t.pdb
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe \
+// RUN:   -o "p b" -o "p b_array" -o "p c" -o "exit" | FileCheck %s
+
+// CHECK: (lldb) p b
+// CHECK: (B) $0 = {}
+// CHECK: (lldb) p b_array
+// CHECK: (B[3]) $1 = ([0] = B @ {{.*}}, [1] = B @ {{.*}}, [2] = B @ {{.*}})
+// CHECK: (lldb) p c
+// CHECK: (C) $2 = {}
+
+struct A { int x; A(); };
+struct B : A {};
+struct C {
+  static A static_a;
+  A getA() {}
+};
+
+B b;
+B b_array[3] = {};
+A C::static_a = A();
+C c;
+int main(){}
Index: lldb/test/Shell/SymbolFile/NativePDB/Inputs/incomplete-tag-type.cpp
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/NativePDB/Inputs/incomplete-tag-type.cpp
@@ -0,0 +1,5 @@
+struct A {
+  int x;
+  A();
+};
+A::A() : x(47) {}
Index: lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -92,9 +92,10 @@
       m_ast_builder.GetOrCreateType(PdbTypeSymId(type_idx));
   if (method_qt.isNull())
     return;
-  m_ast_builder.CompleteType(method_qt);
   CompilerType method_ct = m_ast_builder.ToCompilerType(method_qt);
-  lldb::opaque_compiler_type_t derived_opaque_ty = m_derived_ct.GetOpaqueQualType();
+  PdbAstBuilder::RequireCompleteType(method_ct);
+  lldb::opaque_compiler_type_t derived_opaque_ty =
+      m_derived_ct.GetOpaqueQualType();
   auto iter = m_cxx_record_map.find(derived_opaque_ty);
   if (iter != m_cxx_record_map.end()) {
     if (iter->getSecond().contains({name, method_ct})) {
@@ -155,6 +156,7 @@
     return llvm::Error::success();
 
   CompilerType member_ct = m_ast_builder.ToCompilerType(member_type);
+  PdbAstBuilder::RequireCompleteType(member_ct);
 
   lldb::AccessType access =
       TranslateMemberAccess(static_data_member.getAccess());
@@ -253,7 +255,7 @@
   clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti));
   if (member_qt.isNull())
     return Error::success();
-  m_ast_builder.CompleteType(member_qt);
+  PdbAstBuilder::RequireCompleteType(m_ast_builder.ToCompilerType(member_qt));
   lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
   size_t field_size =
       bitfield_width ? bitfield_width : GetSizeOfType(ti, m_index.tpi()) * 8;
@@ -310,6 +312,18 @@
     bases.push_back(std::move(ib.second));
 
   TypeSystemClang &clang = m_ast_builder.clang();
+  // Make sure all base classes refer to complete types and not forward
+  // declarations. If we don't do this, clang will crash with an
+  // assertion in the call to clang_type.TransferBaseClasses()
+  for (const auto &base_class : bases) {
+    clang::TypeSourceInfo *type_source_info =
+        base_class->getTypeSourceInfo();
+    if (type_source_info) {
+      PdbAstBuilder::RequireCompleteType(
+          clang.GetType(type_source_info->getType()));
+    }
+  }
+
   clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(), std::move(bases));
 
   clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType());
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
@@ -87,6 +87,7 @@
   ClangASTImporter &GetClangASTImporter() { return m_importer; }
 
   void Dump(Stream &stream);
+  static void RequireCompleteType(CompilerType type);
 
 private:
   clang::Decl *TryGetDecl(PdbSymUid uid) const;
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -1,3 +1,4 @@
+#include "/tmp/debug.h"
 #include "PdbAstBuilder.h"
 
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
@@ -1170,7 +1171,9 @@
     return {};
   uint64_t element_count = ar.Size / element_size;
 
-  CompilerType array_ct = m_clang.CreateArrayType(ToCompilerType(element_type),
+  CompilerType element_ct = ToCompilerType(element_type);
+  RequireCompleteType(element_ct);
+  CompilerType array_ct = m_clang.CreateArrayType(element_ct,
                                                   element_count, false);
   return clang::QualType::getFromOpaquePtr(array_ct.GetOpaqueQualType());
 }
@@ -1448,3 +1451,30 @@
 void PdbAstBuilder::Dump(Stream &stream) {
   m_clang.Dump(stream.AsRawOstream());
 }
+
+/// Complete a type from debug info, or mark it as forcefully completed if
+/// there is no definition of the type in the current Module. Call this function
+/// in contexts where the usual C++ rules require a type to be complete (base
+/// class, member, etc.).
+void PdbAstBuilder::RequireCompleteType(CompilerType type) {
+  // Technically, enums can be incomplete too, but we don't handle those as they
+  // are emitted even under -flimit-debug-info.
+  if (!TypeSystemClang::IsCXXClassType(type))
+    return;
+
+  if (type.GetCompleteType())
+    return;
+
+  // No complete definition in this module.  Mark the class as complete to
+  // satisfy local ast invariants, but make a note of the fact that
+  // it is not _really_ complete so we can later search for a definition in a
+  // different module.
+  // Since we provide layout assistance, layouts of types containing this class
+  // will be correct even if we  are not able to find the definition elsewhere.
+  bool started = TypeSystemClang::StartTagDeclarationDefinition(type);
+  lldbassert(started && "Unable to start a class type definition.");
+  TypeSystemClang::CompleteTagDeclarationDefinition(type);
+  const clang::TagDecl *td = ClangUtil::GetAsTagDecl(type);
+  auto &ts = llvm::cast<TypeSystemClang>(*type.GetTypeSystem());
+  ts.GetMetadata(td)->SetIsForcefullyCompleted();
+}
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to