https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/156370
>From 967d3453e997ed25c3548898d69a40d079d307b1 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Mon, 1 Sep 2025 21:02:33 +0200 Subject: [PATCH 1/3] [LLDB] Complete constant array member types in class members --- .../TypeSystem/Clang/TypeSystemClang.cpp | 15 ++- .../NativePDB/Inputs/incomplete-tag-type.cpp | 5 + .../NativePDB/incomplete-tag-type.cpp | 45 -------- .../NativePDB/incomplete-tag-type.test | 109 ++++++++++++++++++ 4 files changed, 126 insertions(+), 48 deletions(-) delete mode 100644 lldb/test/Shell/SymbolFile/NativePDB/incomplete-tag-type.cpp create mode 100644 lldb/test/Shell/SymbolFile/NativePDB/incomplete-tag-type.test diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 39aacdb58e694..038677f68b991 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -9577,12 +9577,21 @@ TypeSystemClang::DeclContextGetTypeSystemClang(const CompilerDeclContext &dc) { } void TypeSystemClang::RequireCompleteType(CompilerType type) { + if (!type) + return; + + clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); + if (qual_type.isNull()) + return; + // 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; + bool is_constant_array = qual_type->isConstantArrayType(); + bool is_cxx_record = qual_type->getAsCXXRecordDecl() != nullptr; + if (is_constant_array || is_cxx_record) + type.GetCompleteType(); - if (type.GetCompleteType()) + if (!is_cxx_record) return; // No complete definition in this module. Mark the class as complete to diff --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/incomplete-tag-type.cpp b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/incomplete-tag-type.cpp index c930338905445..d08f49d1014ba 100644 --- a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/incomplete-tag-type.cpp +++ b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/incomplete-tag-type.cpp @@ -13,3 +13,8 @@ struct E { E(); }; E::E() = default; + +struct I { + I(); +}; +I::I() = default; diff --git a/lldb/test/Shell/SymbolFile/NativePDB/incomplete-tag-type.cpp b/lldb/test/Shell/SymbolFile/NativePDB/incomplete-tag-type.cpp deleted file mode 100644 index 7bc7e618667f7..0000000000000 --- a/lldb/test/Shell/SymbolFile/NativePDB/incomplete-tag-type.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// 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: %lldb -f %t.exe -o \ -// RUN: "settings set interpreter.stop-command-source-on-error false" \ -// RUN: -o "expression b" -o "expression d" -o "expression static_e_ref" -o "exit" 2>&1 | FileCheck %s - -// CHECK: (lldb) expression b -// CHECK: (B) $0 = {} -// CHECK: (lldb) expression d -// CHECK: (D) $1 = {} -// CHECK: (lldb) expression static_e_ref -// CHECK: error:{{.*}}incomplete type 'E' where a complete type is required - -// Complete base class. -struct A { int x; A(); }; -struct B : A {}; -B b; - -// Complete data member. -struct C { - C(); -}; - -struct D { - C c; -}; -D d; - -// Incomplete static data member should return error. -struct E { - E(); -}; - -struct F { - static E static_e; -}; - -E F::static_e = E(); -E& static_e_ref = F::static_e; - -int main(){} diff --git a/lldb/test/Shell/SymbolFile/NativePDB/incomplete-tag-type.test b/lldb/test/Shell/SymbolFile/NativePDB/incomplete-tag-type.test new file mode 100644 index 0000000000000..f30866ccdd6f0 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/incomplete-tag-type.test @@ -0,0 +1,109 @@ +# REQUIRES: lld, x86 + +# RUN: split-file %s %t + +# 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 -- %t/main.cpp +# RUN: lld-link /debug:full /nodefaultlib /entry:main %t1.obj %t2.obj /out:%t.exe /pdb:%t.pdb + +# RUN: %lldb -f %t.exe -s %t/target-var.input 2>&1 | FileCheck %s --check-prefix=TARGET-VAR +# RUN: %lldb -f %t.exe -s %t/expr.input 2>&1 | FileCheck %s --check-prefix=EXPR + +#--- main.cpp + +// Complete base class. +struct A { int x; A(); }; +struct B : A {}; +B b; + +// Complete data member. +struct C { + C(); +}; + +struct D { + C c; +}; +D d; + +// Incomplete static data member should return error. +struct E { + E(); +}; + +struct F { + static E static_e; +}; + +E F::static_e = E(); +E& static_e_ref = F::static_e; + +struct G { + int foo = 1; +}; +struct H { + G g[2]; +}; +H h; + +struct I { + I(); +}; +struct J { + I i[2]; +}; +J j; + + +int main(){} + +#--- target-var.input + +target variable b +target variable d +target variable h +target variable j +target variable static_e_ref +exit + +#--- expr.input + +settings set interpreter.stop-command-source-on-error false +expression b +expression d +expression h +expression j +expression static_e_ref +exit + +# TARGET-VAR: (lldb) target variable b +# TARGET-VAR-NEXT: (B) b = (A = <incomplete type>) +# TARGET-VAR-NEXT: (lldb) target variable d +# TARGET-VAR-NEXT: (D) d = {} +# TARGET-VAR-NEXT: (lldb) target variable h +# TARGET-VAR-NEXT: (H) h = { +# TARGET-VAR-NEXT: g = { +# TARGET-VAR-NEXT: [0] = (foo = 1) +# TARGET-VAR-NEXT: [1] = (foo = 1) +# TARGET-VAR-NEXT: } +# TARGET-VAR-NEXT: } +# TARGET-VAR-NEXT: (lldb) target variable j +# TARGET-VAR-NEXT: (J) j = {} +# TARGET-VAR-NEXT: (lldb) target variable static_e_ref +# TARGET-VAR-NEXT: (E &) static_e_ref = 0x{{.*}} <incomplete type "E"> + +# EXPR: (lldb) expression b +# EXPR-NEXT: (B) $0 = {} +# EXPR-NEXT: (lldb) expression d +# EXPR-NEXT: (D) $1 = {} +# EXPR-NEXT: (lldb) expression h +# EXPR-NEXT: (H) $2 = { +# EXPR-NEXT: g = { +# EXPR-NEXT: [0] = (foo = 1) +# EXPR-NEXT: [1] = (foo = 1) +# EXPR-NEXT: } +# EXPR-NEXT: } +# EXPR-NEXT: (lldb) expression j +# EXPR-NEXT: (J) $3 = {} +# EXPR-NEXT: (lldb) expression static_e_ref +# EXPR: error:{{.*}}incomplete type 'E' where a complete type is required >From 4a08289d9b435e08cd8a7fac1ab9fcbbfdaa88f4 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Mon, 1 Sep 2025 21:54:49 +0200 Subject: [PATCH 2/3] fix: return if complete --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 038677f68b991..218ea74bc74c2 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -9589,7 +9589,8 @@ void TypeSystemClang::RequireCompleteType(CompilerType type) { bool is_constant_array = qual_type->isConstantArrayType(); bool is_cxx_record = qual_type->getAsCXXRecordDecl() != nullptr; if (is_constant_array || is_cxx_record) - type.GetCompleteType(); + if (type.GetCompleteType()) + return; if (!is_cxx_record) return; >From d978d598006163b1c5738fa0d17d60be7508fd75 Mon Sep 17 00:00:00 2001 From: Nerixyz <nerix...@outlook.de> Date: Tue, 2 Sep 2025 16:05:49 +0200 Subject: [PATCH 3/3] fix: require element type when creating array type --- .../SymbolFile/NativePDB/PdbAstBuilder.cpp | 1 + .../Plugins/TypeSystem/Clang/TypeSystemClang.cpp | 16 +++------------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 709281cb32709..933c4361d93da 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -1169,6 +1169,7 @@ clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id, clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) { clang::QualType element_type = GetOrCreateType(ar.ElementType); + TypeSystemClang::RequireCompleteType(ToCompilerType(element_type)); SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( m_clang.GetSymbolFile()->GetBackingSymbolFile()); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 218ea74bc74c2..39aacdb58e694 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -9577,22 +9577,12 @@ TypeSystemClang::DeclContextGetTypeSystemClang(const CompilerDeclContext &dc) { } void TypeSystemClang::RequireCompleteType(CompilerType type) { - if (!type) - return; - - clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type)); - if (qual_type.isNull()) - return; - // Technically, enums can be incomplete too, but we don't handle those as they // are emitted even under -flimit-debug-info. - bool is_constant_array = qual_type->isConstantArrayType(); - bool is_cxx_record = qual_type->getAsCXXRecordDecl() != nullptr; - if (is_constant_array || is_cxx_record) - if (type.GetCompleteType()) - return; + if (!TypeSystemClang::IsCXXClassType(type)) + return; - if (!is_cxx_record) + if (type.GetCompleteType()) return; // No complete definition in this module. Mark the class as complete to _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits