https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/155853
>From 548098e932eeedff5a0ae26a211a1b7b1cbbe145 Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Thu, 28 Aug 2025 16:33:57 +0200 Subject: [PATCH] [LLDB][NativePDB] Set IsDynmaicCXXType metadata for records --- .../Clang/ClangASTMetadata.cpp | 10 +- .../NativePDB/PdbAstBuilderClang.cpp | 19 ++- .../SymbolFile/NativePDB/PdbAstBuilderClang.h | 5 +- .../NativePDB/UdtRecordCompleter.cpp | 7 + .../SymbolFile/NativePDB/UdtRecordCompleter.h | 1 + .../TypeSystem/Clang/TypeSystemClang.cpp | 127 ++++++++++-------- .../SymbolFile/NativePDB/dynamic-types.cpp | 43 ++++++ .../SymbolFile/NativePDB/CMakeLists.txt | 11 ++ .../NativePDB/Inputs/DynamicTypes.cpp | 29 ++++ .../NativePDB/Inputs/DynamicTypes.exe | Bin 0 -> 3584 bytes .../NativePDB/Inputs/DynamicTypes.pdb | Bin 0 -> 73728 bytes .../NativePDB/SymbolFilePDBTests.cpp | 123 +++++++++++++++++ 12 files changed, 303 insertions(+), 72 deletions(-) create mode 100644 lldb/test/Shell/SymbolFile/NativePDB/dynamic-types.cpp create mode 100644 lldb/unittests/SymbolFile/NativePDB/Inputs/DynamicTypes.cpp create mode 100644 lldb/unittests/SymbolFile/NativePDB/Inputs/DynamicTypes.exe create mode 100644 lldb/unittests/SymbolFile/NativePDB/Inputs/DynamicTypes.pdb create mode 100644 lldb/unittests/SymbolFile/NativePDB/SymbolFilePDBTests.cpp diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.cpp index 2c5dacb60a9b8..d77509ef248d4 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.cpp @@ -31,12 +31,12 @@ void ClangASTMetadata::Dump(Stream *s) { lldb::user_id_t uid = GetUserID(); if (uid != LLDB_INVALID_UID) { - s->Printf("uid=0x%" PRIx64, uid); + s->Printf("uid=0x%" PRIx64 " ", uid); } uint64_t isa_ptr = GetISAPtr(); if (isa_ptr != 0) { - s->Printf("isa_ptr=0x%" PRIx64, isa_ptr); + s->Printf("isa_ptr=0x%" PRIx64 " ", isa_ptr); } const char *obj_ptr_name = GetObjectPtrName(); @@ -44,8 +44,8 @@ void ClangASTMetadata::Dump(Stream *s) { s->Printf("obj_ptr_name=\"%s\" ", obj_ptr_name); } - if (m_is_dynamic_cxx) { - s->Printf("is_dynamic_cxx=%i ", m_is_dynamic_cxx); - } + if (m_is_dynamic_cxx) + *s << "is_dynamic_cxx=" << (m_is_dynamic_cxx == 2) << ' '; + s->EOL(); } diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp index 673bd2826b455..ca02b298f9f4d 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp @@ -695,17 +695,24 @@ PdbAstBuilderClang::CreateModifierType(const ModifierRecord &modifier) { } clang::QualType PdbAstBuilderClang::CreateRecordType(PdbTypeSymId id, - const TagRecord &record) { + const CVTagRecord &record) { clang::DeclContext *context = nullptr; std::string uname; - std::tie(context, uname) = CreateDeclInfoForType(record, id.index); + std::tie(context, uname) = CreateDeclInfoForType(record.asTag(), id.index); if (!context) return {}; - clang::TagTypeKind ttk = TranslateUdtKind(record); + clang::TagTypeKind ttk = TranslateUdtKind(record.asTag()); ClangASTMetadata metadata; metadata.SetUserID(toOpaqueUid(id)); - metadata.SetIsDynamicCXXType(false); + // unions can't be dynamic + if (record.contextKind() != CompilerContextKind::ClassOrStruct) + metadata.SetIsDynamicCXXType(false); + // If a class has a vtable, it is dynamic. + else if (!record.asClass().getVTableShape().isNoneType()) + metadata.SetIsDynamicCXXType(true); + // else + // wait until the record is completed as it might have virtual bases CompilerType ct = m_clang.CreateRecordType( context, OptionalClangModuleID(), uname, llvm::to_underlying(ttk), @@ -888,11 +895,9 @@ clang::QualType PdbAstBuilderClang::CreateType(PdbTypeSymId type) { if (IsTagRecord(cvt)) { CVTagRecord tag = CVTagRecord::create(cvt); - if (tag.kind() == CVTagRecord::Union) - return CreateRecordType(type.index, tag.asUnion()); if (tag.kind() == CVTagRecord::Enum) return CreateEnumType(type.index, tag.asEnum()); - return CreateRecordType(type.index, tag.asClass()); + return CreateRecordType(type.index, tag); } if (cvt.kind() == LF_ARRAY) { diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h index 0d214cb57f820..2abf1eb58f3ac 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h @@ -50,6 +50,8 @@ struct DeclStatus { bool resolved = false; }; +struct CVTagRecord; + class PdbAstBuilderClang : public PdbAstBuilder { public: PdbAstBuilderClang(TypeSystemClang &clang); @@ -114,8 +116,7 @@ class PdbAstBuilderClang : public PdbAstBuilder { clang::QualType CreateModifierType(const llvm::codeview::ModifierRecord &modifier); clang::QualType CreateArrayType(const llvm::codeview::ArrayRecord &array); - clang::QualType CreateRecordType(PdbTypeSymId id, - const llvm::codeview::TagRecord &record); + clang::QualType CreateRecordType(PdbTypeSymId id, const CVTagRecord &record); clang::QualType CreateEnumType(PdbTypeSymId id, const llvm::codeview::EnumRecord &record); clang::QualType diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index 871b053151c61..2476928eb5a3e 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -133,6 +133,7 @@ Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, // LF_VBCLASS. if (cvr.Kind == LF_VBCLASS) AddBaseClassForTypeIndex(base.BaseType, base.getAccess(), base.VTableIndex); + m_any_virtual_base = true; return Error::success(); } @@ -384,6 +385,12 @@ void UdtRecordCompleter::complete() { if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) { m_ast_builder.GetClangASTImporter().SetRecordLayout(record_decl, m_layout); } + + if (auto meta = m_ast_builder.clang().GetMetadata(&m_tag_decl)) { + meta->SetIsDynamicCXXType(meta->GetIsDynamicCXXType().value_or(false) || + m_any_virtual_base); + m_ast_builder.clang().SetMetadata(&m_tag_decl, *meta); + } } uint64_t diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h index 0a6aedefa69e8..54029e1e4d28a 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h @@ -53,6 +53,7 @@ class UdtRecordCompleter : public llvm::codeview::TypeVisitorCallbacks { llvm::DenseMap<lldb::opaque_compiler_type_t, llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>> &m_cxx_record_map; + bool m_any_virtual_base = false; public: UdtRecordCompleter( diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 4a637f0817759..8431c2981ebf9 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -17,8 +17,8 @@ #include "llvm/Support/FormatAdapters.h" #include "llvm/Support/FormatVariadic.h" -#include <mutex> #include <memory> +#include <mutex> #include <string> #include <vector> @@ -200,7 +200,7 @@ void addOverridesForMethod(clang::CXXMethodDecl *decl) { llvm::cast<clang::CXXMethodDecl>(overridden_decl)); } } -} +} // namespace static lldb::addr_t GetVTableAddress(Process &process, VTableContextBase &vtable_ctx, @@ -1197,7 +1197,7 @@ CompilerDeclContext TypeSystemClang::CreateDeclContext(DeclContext *ctx) { CompilerType TypeSystemClang::GetTypeForDecl(clang::NamedDecl *decl) { if (clang::ObjCInterfaceDecl *interface_decl = - llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) + llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl)) return GetTypeForDecl(interface_decl); if (clang::TagDecl *tag_decl = llvm::dyn_cast<clang::TagDecl>(decl)) return GetTypeForDecl(tag_decl); @@ -1952,14 +1952,13 @@ clang::UsingDirectiveDecl *TypeSystemClang::CreateUsingDirectiveDeclaration( if (decl_ctx && ns_decl) { auto *translation_unit = getASTContext().getTranslationUnitDecl(); clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create( - getASTContext(), decl_ctx, clang::SourceLocation(), - clang::SourceLocation(), clang::NestedNameSpecifierLoc(), - clang::SourceLocation(), ns_decl, - FindLCABetweenDecls(decl_ctx, ns_decl, - translation_unit)); - decl_ctx->addDecl(using_decl); - SetOwningModule(using_decl, owning_module); - return using_decl; + getASTContext(), decl_ctx, clang::SourceLocation(), + clang::SourceLocation(), clang::NestedNameSpecifierLoc(), + clang::SourceLocation(), ns_decl, + FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit)); + decl_ctx->addDecl(using_decl); + SetOwningModule(using_decl, owning_module); + return using_decl; } return nullptr; } @@ -3131,7 +3130,8 @@ TypeSystemClang::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, llvm::dyn_cast<clang::FunctionProtoType>(qual_type.getTypePtr()); if (func) { if (index < func->getNumParams()) - return CompilerType(weak_from_this(), func->getParamType(index).getAsOpaquePtr()); + return CompilerType(weak_from_this(), + func->getParamType(index).getAsOpaquePtr()); } } return CompilerType(); @@ -3156,7 +3156,8 @@ bool TypeSystemClang::IsTypeImpl( const clang::ReferenceType *reference_type = llvm::cast<clang::ReferenceType>(qual_type.getTypePtr()); if (reference_type) - return IsTypeImpl(reference_type->getPointeeType().getAsOpaquePtr(), predicate); + return IsTypeImpl(reference_type->getPointeeType().getAsOpaquePtr(), + predicate); } break; } } @@ -3654,8 +3655,7 @@ bool TypeSystemClang::HasPointerAuthQualifier( } bool TypeSystemClang::CanPassInRegisters(const CompilerType &type) { - if (auto *record_decl = - TypeSystemClang::GetAsRecordDecl(type)) { + if (auto *record_decl = TypeSystemClang::GetAsRecordDecl(type)) { return record_decl->canPassInRegisters(); } return false; @@ -4674,14 +4674,13 @@ CompilerType TypeSystemClang::GetBasicTypeFromAST(lldb::BasicType basic_type) { CompilerType TypeSystemClang::CreateGenericFunctionPrototype() { clang::ASTContext &ast = getASTContext(); const FunctionType::ExtInfo generic_ext_info( - /*noReturn=*/false, - /*hasRegParm=*/false, - /*regParm=*/0, - CallingConv::CC_C, - /*producesResult=*/false, - /*noCallerSavedRegs=*/false, - /*NoCfCheck=*/false, - /*cmseNSCall=*/false); + /*noReturn=*/false, + /*hasRegParm=*/false, + /*regParm=*/0, CallingConv::CC_C, + /*producesResult=*/false, + /*noCallerSavedRegs=*/false, + /*NoCfCheck=*/false, + /*cmseNSCall=*/false); QualType func_type = ast.getFunctionNoProtoType(ast.VoidTy, generic_ext_info); return GetType(func_type); } @@ -4972,7 +4971,8 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type) { case clang::BuiltinType::OCLIntelSubgroupAVCImeResult: case clang::BuiltinType::OCLIntelSubgroupAVCRefResult: case clang::BuiltinType::OCLIntelSubgroupAVCSicResult: - case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleReferenceStreamout: + case clang::BuiltinType:: + OCLIntelSubgroupAVCImeResultSingleReferenceStreamout: case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualReferenceStreamout: case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleReferenceStreamin: case clang::BuiltinType::OCLIntelSubgroupAVCImeDualReferenceStreamin: @@ -4985,12 +4985,12 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type) { case clang::BuiltinType::DMR2048: break; - // ARM -- Scalable Vector Extension + // ARM -- Scalable Vector Extension #define SVE_TYPE(Name, Id, SingletonId) case clang::BuiltinType::Id: #include "clang/Basic/AArch64ACLETypes.def" break; - // RISC-V V builtin types. + // RISC-V V builtin types. #define RVV_TYPE(Name, Id, SingletonId) case clang::BuiltinType::Id: #include "clang/Basic/RISCVVTypes.def" break; @@ -5005,7 +5005,7 @@ lldb::Encoding TypeSystemClang::GetEncoding(lldb::opaque_compiler_type_t type) { case clang::BuiltinType::UnresolvedTemplate: break; - // AMD GPU builtin types. + // AMD GPU builtin types. #define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) \ case clang::BuiltinType::Id: #include "clang/Basic/AMDGPUTypes.def" @@ -5329,8 +5329,8 @@ TypeSystemClang::GetNumChildren(lldb::opaque_compiler_type_t type, num_children += GetNumBaseClasses(cxx_record_decl, omit_empty_base_classes); - num_children += std::distance(record_decl->field_begin(), - record_decl->field_end()); + num_children += + std::distance(record_decl->field_begin(), record_decl->field_end()); } else return llvm::createStringError( "incomplete type \"" + GetDisplayTypeName(type).GetString() + "\""); @@ -5528,8 +5528,7 @@ TypeSystemClang::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) { void TypeSystemClang::ForEachEnumerator( lldb::opaque_compiler_type_t type, - std::function<bool(const CompilerType &integer_type, - ConstString name, + std::function<bool(const CompilerType &integer_type, ConstString name, const llvm::APSInt &value)> const &callback) { const clang::EnumType *enum_type = llvm::dyn_cast<clang::EnumType>(GetCanonicalQualType(type)); @@ -6624,10 +6623,10 @@ llvm::Expected<CompilerType> TypeSystemClang::GetChildCompilerTypeAtIndex( return llvm::createStringError("cannot enumerate children"); } -uint32_t TypeSystemClang::GetIndexForRecordBase( - const clang::RecordDecl *record_decl, - const clang::CXXBaseSpecifier *base_spec, - bool omit_empty_base_classes) { +uint32_t +TypeSystemClang::GetIndexForRecordBase(const clang::RecordDecl *record_decl, + const clang::CXXBaseSpecifier *base_spec, + bool omit_empty_base_classes) { uint32_t child_idx = 0; const clang::CXXRecordDecl *cxx_record_decl = @@ -6652,9 +6651,10 @@ uint32_t TypeSystemClang::GetIndexForRecordBase( return UINT32_MAX; } -uint32_t TypeSystemClang::GetIndexForRecordChild( - const clang::RecordDecl *record_decl, clang::NamedDecl *canonical_decl, - bool omit_empty_base_classes) { +uint32_t +TypeSystemClang::GetIndexForRecordChild(const clang::RecordDecl *record_decl, + clang::NamedDecl *canonical_decl, + bool omit_empty_base_classes) { uint32_t child_idx = TypeSystemClang::GetNumBaseClasses( llvm::dyn_cast<clang::CXXRecordDecl>(record_decl), omit_empty_base_classes); @@ -6759,7 +6759,7 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName( [decl_name](const clang::CXXBaseSpecifier *specifier, clang::CXXBasePath &path) { CXXRecordDecl *record = - specifier->getType()->getAsCXXRecordDecl(); + specifier->getType()->getAsCXXRecordDecl(); auto r = record->lookup(decl_name); path.Decls = r.begin(); return !r.empty(); @@ -6787,8 +6787,8 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName( } for (clang::DeclContext::lookup_iterator I = path->Decls, E; I != E; ++I) { - child_idx = GetIndexForRecordChild( - parent_record_decl, *I, omit_empty_base_classes); + child_idx = GetIndexForRecordChild(parent_record_decl, *I, + omit_empty_base_classes); if (child_idx == UINT32_MAX) { child_indexes.clear(); return 0; @@ -7135,7 +7135,7 @@ TypeSystemClang::GetAsTemplateSpecialization( const clang::Type::TypeClass type_class = qual_type->getTypeClass(); switch (type_class) { case clang::Type::Record: { - if (! GetCompleteType(type)) + if (!GetCompleteType(type)) return nullptr; const clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); @@ -7277,7 +7277,8 @@ TypeSystemClang::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, CompilerType TypeSystemClang::GetTypeForFormatters(void *type) { if (type) - return ClangUtil::RemoveFastQualifiers(CompilerType(weak_from_this(), type)); + return ClangUtil::RemoveFastQualifiers( + CompilerType(weak_from_this(), type)); return CompilerType(); } @@ -8023,7 +8024,8 @@ bool TypeSystemClang::AddObjCClassProperty( getter = clang::ObjCMethodDecl::CreateDeserialized(clang_ast, GlobalDeclID()); getter->setDeclName(getter_sel); - getter->setReturnType(ClangUtil::GetQualType(property_clang_type_to_access)); + getter->setReturnType( + ClangUtil::GetQualType(property_clang_type_to_access)); getter->setDeclContext(class_interface_decl); getter->setInstanceMethod(isInstance); getter->setVariadic(isVariadic); @@ -8049,8 +8051,8 @@ bool TypeSystemClang::AddObjCClassProperty( } clang::ObjCMethodDecl *setter = nullptr; - setter = isInstance ? class_interface_decl->lookupInstanceMethod(setter_sel) - : class_interface_decl->lookupClassMethod(setter_sel); + setter = isInstance ? class_interface_decl->lookupInstanceMethod(setter_sel) + : class_interface_decl->lookupClassMethod(setter_sel); if (!setter_sel.isNull() && !setter) { clang::QualType result_type = clang_ast.VoidTy; const bool isVariadic = false; @@ -8784,12 +8786,6 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, lldb::DescriptionLevel level) { StreamFile s(stdout, false); DumpTypeDescription(type, s, level); - - CompilerType ct(weak_from_this(), type); - const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr(); - if (std::optional<ClangASTMetadata> metadata = GetMetadata(clang_type)) { - metadata->Dump(&s); - } } void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, @@ -8814,7 +8810,7 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, if (!objc_class_type) break; clang::ObjCInterfaceDecl *class_interface_decl = - objc_class_type->getInterface(); + objc_class_type->getInterface(); if (!class_interface_decl) break; if (level == eDescriptionLevelVerbose) @@ -8878,7 +8874,24 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, if (buf.size() > 0) { s.Write(buf.data(), buf.size()); } -} + + if (level == eDescriptionLevelVerbose) { + std::optional<ClangASTMetadata> metadata = + GetMetadata(qual_type.getTypePtr()); + if (metadata) { + s << "type-metadata = "; + metadata->Dump(&s); + } + + if (const clang::TagDecl *tag = qual_type->getAsTagDecl()) + metadata = GetMetadata(tag); + + if (metadata) { + s << "decl-metadata = "; + metadata->Dump(&s); + } + } + } } void TypeSystemClang::DumpTypeName(const CompilerType &type) { @@ -9229,8 +9242,7 @@ std::vector<CompilerDecl> TypeSystemClang::DeclContextFindDeclByName( it++) { if (!searched.insert(it->second).second) continue; - symbol_file->ParseDeclsForContext( - CreateDeclContext(it->second)); + symbol_file->ParseDeclsForContext(CreateDeclContext(it->second)); for (clang::Decl *child : it->second->decls()) { if (clang::UsingDirectiveDecl *ud = @@ -9343,8 +9355,7 @@ uint32_t TypeSystemClang::CountDeclLevels(clang::DeclContext *frame_decl_ctx, continue; searched.insert(it->second); - symbol_file->ParseDeclsForContext( - CreateDeclContext(it->second)); + symbol_file->ParseDeclsForContext(CreateDeclContext(it->second)); for (clang::Decl *child : it->second->decls()) { if (clang::UsingDirectiveDecl *ud = diff --git a/lldb/test/Shell/SymbolFile/NativePDB/dynamic-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/dynamic-types.cpp new file mode 100644 index 0000000000000..576a601c7190e --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/dynamic-types.cpp @@ -0,0 +1,43 @@ +// clang-format off +// REQUIRES: lld, x86 + +// RUN: %clang_cl --target=x86_64-windows-msvc -Od -GS- -GR- -std:c++20 -Z7 -c /Fo%t.obj -- %s +// RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb + +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=Base %t.exe | FileCheck %s --check-prefix=DYNAMIC +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=UsingBase %t.exe | FileCheck %s --check-prefix=DYNAMIC +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=UsingVBase %t.exe | FileCheck %s --check-prefix=DYNAMIC +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=UsingUsingVBase %t.exe | FileCheck %s --check-prefix=DYNAMIC + +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=VBase %t.exe | FileCheck %s --check-prefix=NOT-DYNAMIC +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=NotDynamic %t.exe | FileCheck %s --check-prefix=NOT-DYNAMIC + +// DYNAMIC: Found 1 types: +// DYNAMIC: decl-metadata = uid={{.*}} is_dynamic_cxx=true + +// NOT-DYNAMIC: Found 1 types: +// NOT-DYNAMIC: decl-metadata = uid={{.*}} is_dynamic_cxx=false + +struct Base { + virtual ~Base() = default; +}; + +struct UsingBase : public Base {}; + +struct VBase {}; + +struct UsingVBase : public virtual VBase {}; + +struct UsingUsingVBase : public UsingVBase {}; + +struct NotDynamic : public VBase {}; + +void operator delete(void *, unsigned __int64 i) throw() {} + +int main() { + UsingBase ub; + UsingVBase uvb; + UsingUsingVBase uuvb; + NotDynamic nd; + return 0; +} diff --git a/lldb/unittests/SymbolFile/NativePDB/CMakeLists.txt b/lldb/unittests/SymbolFile/NativePDB/CMakeLists.txt index bfd74dd5050b4..6ee198bd85aa1 100644 --- a/lldb/unittests/SymbolFile/NativePDB/CMakeLists.txt +++ b/lldb/unittests/SymbolFile/NativePDB/CMakeLists.txt @@ -1,5 +1,6 @@ add_lldb_unittest(SymbolFileNativePDBTests PdbFPOProgramToDWARFExpressionTests.cpp + SymbolFilePDBTests.cpp UdtRecordCompleterTests.cpp LINK_COMPONENTS @@ -9,6 +10,16 @@ add_lldb_unittest(SymbolFileNativePDBTests lldbCore lldbHost lldbSymbol + lldbPluginObjectFilePECOFF + lldbPluginPlatformWindows lldbPluginSymbolFileNativePDB + lldbPluginSymbolFilePDB # for the pdb reader setting lldbUtilityHelpers ) + +set(test_inputs + DynamicTypes.cpp + DynamicTypes.exe + DynamicTypes.pdb) + +add_unittest_inputs(SymbolFileNativePDBTests "${test_inputs}") diff --git a/lldb/unittests/SymbolFile/NativePDB/Inputs/DynamicTypes.cpp b/lldb/unittests/SymbolFile/NativePDB/Inputs/DynamicTypes.cpp new file mode 100644 index 0000000000000..bbd2dfa5bbaa6 --- /dev/null +++ b/lldb/unittests/SymbolFile/NativePDB/Inputs/DynamicTypes.cpp @@ -0,0 +1,29 @@ +// This was used to generate `DynamicTypes.pdb`. + +// clang-cl /Z7 /GR- /GS- DynamicTypes.cpp -c +// lld-link /NODEFAULTLIB /entry:main /DEBUG DynamicTypes.obj +// rm DynamicTypes.obj + +struct Base { + virtual ~Base() = default; +}; + +struct UsingBase : public Base {}; + +struct VBase {}; + +struct UsingVBase : public virtual VBase {}; + +struct UsingUsingVBase : public UsingVBase {}; + +struct NotDynamic : public VBase {}; + +void operator delete(void *, unsigned __int64 i) throw() {} + +int main() { + UsingBase ub; + UsingVBase uvb; + UsingUsingVBase uuvb; + NotDynamic nd; + return 0; +} diff --git a/lldb/unittests/SymbolFile/NativePDB/Inputs/DynamicTypes.exe b/lldb/unittests/SymbolFile/NativePDB/Inputs/DynamicTypes.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1901dc70cba0640e05b23164283b2876ce6c4c5 GIT binary patch literal 3584 zcmeHJKWGzC82_#YNo|{^rO*ySU**6IHAJUUG92|RSBN&44*to|{5fqTxrF3eT5z!u zA=HAKi$e#84ptC4NOcfeP)a%|x`=~=!wnrA99%U1-rc+OY;_W(lzi~r_xs-azVH3M z_bz#N@!C8|MC5~dMe#a+!Sfgo3~mHyy?tlsxfI(OnwrT~SgBmRSxyyLCS@2!lcjZ5 zo;6s`VCrOo6^dCsEEB~q5M}TA=;?=NGj92>bc#CK0uGtu&L|7QawSqYPaC%piRq@L zIOaqX$7uSFn<R2Y;+_H8o8r!Xi4gJrnxYVO!eNZ)WOMM}LD<yiO_b?JPc|Xm!@k2{ zMAPANHf5%WzG0d$Ks??L^@xH!3YVNXn>%{2<4$;j0PVQ4o-bycp7?+r#~bvBLNw-a zTkr_(fL7fNYPBiZuhlwbt-2N5yul^hJ$Tpd7W3L`RaUv9Eyv^$YgC}fh6H3?7jDRL z@5B8)ej6i8sDR?yW*zlLv|3D#XiNM76tdp%5(o)t%U$_y;F=%7Bb#*y;u+}m@kl=p z0#To=)l_+)dRy)zGoUTOU+y|D5)m?hY-VTM`MkZTSX1R|@|EyVP#{WXx4U$^TLGNT zzOxn^jRv1m9O9e|1bmPjlNsmFtQ}B)fPj!#t{%7d(V?`8zcTc4)twXhUOr+E7%!<{ zu_$;ATMw}`oZ;$sn;sV0;6HV1^5+3c{Cqt9{kh(0=LineYy3D+&*p!{%h+za^*EwC zQ0j5+)mOseO=(^$?)Bo{(frDpfkqh=la~`};%(3NYIJR_Ef!N*TpbJZ|Ag_;q^i#) z^ZB{L8GH=f(laKUY&tn><V;hqn3ZH=p^z@-$8&i-c`0S)=5*vHCydf8=F|lvRmf$g z7D{>r*IAk*pG3Z1a_pk8X<^Up8^?_$NfJpQYv;M~+=_8fY>B%A__peWK4$o=fGt9w z0GD7NLDzv-U_U}%0)K`L^$=|VM_?zQb>KLx4t)=dcZyy>KLO*tq7Izh7vLalKXezk XC5L1OnD_=<@vj^bMlBluaR+_@r+BwJ literal 0 HcmV?d00001 diff --git a/lldb/unittests/SymbolFile/NativePDB/Inputs/DynamicTypes.pdb b/lldb/unittests/SymbolFile/NativePDB/Inputs/DynamicTypes.pdb new file mode 100644 index 0000000000000000000000000000000000000000..28bb3d6f5a9d10af26850975a2cf17bdf6cb4bd5 GIT binary patch literal 73728 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 OKnMr{A@Ki1;Qs*08MKT5 literal 0 HcmV?d00001 diff --git a/lldb/unittests/SymbolFile/NativePDB/SymbolFilePDBTests.cpp b/lldb/unittests/SymbolFile/NativePDB/SymbolFilePDBTests.cpp new file mode 100644 index 0000000000000..b8b67b46c1339 --- /dev/null +++ b/lldb/unittests/SymbolFile/NativePDB/SymbolFilePDBTests.cpp @@ -0,0 +1,123 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h" +#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h" +#include "Plugins/Platform/Windows/PlatformWindows.h" +#include "Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h" +#include "Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h" +#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h" +#include "Plugins/TypeSystem/Clang/TypeSystemClang.h" + +#include "TestingSupport/SubsystemRAII.h" +#include "TestingSupport/TestUtilities.h" + +#include "lldb/Core/Debugger.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Target/Platform.h" +#include "lldb/Utility/ArchSpec.h" + +#include "gtest/gtest.h" + +#include <optional> + +using namespace lldb_private; +using namespace lldb_private::npdb; +using namespace llvm; + +class SymbolFilePDBTests : public testing::Test { +public: + void SetUp() override { + m_test_exe = GetInputFilePath("DynamicTypes.exe"); + + ArchSpec arch("x86_64-pc-windows-msvc"); + Platform::SetHostPlatform(PlatformWindows::CreateInstance(true, &arch)); + m_debugger_sp = Debugger::CreateInstance(); + m_debugger_sp->SetPropertyValue(nullptr, + lldb_private::eVarSetOperationAssign, + "plugin.symbol-file.pdb.reader", "native"); + } + + std::optional<ClangASTMetadata> GetMetadataFor(SymbolFile *symfile, + llvm::StringRef query, + TypeSystemClang *clang) { + TypeResults results; + symfile->FindTypes(TypeQuery(query), results); + lldb::TypeSP type_sp = results.GetFirstType(); + if (!type_sp) + return std::nullopt; + + CompilerType ct = type_sp->GetFullCompilerType(); + ct.GetCompleteType(); + if (!ct.IsValid()) + return std::nullopt; + + ct.IsPossibleDynamicType(nullptr, true, false); + + clang::TagDecl *tag_decl = clang->GetAsTagDecl(ct); + if (!tag_decl) + return std::nullopt; + + return clang->GetMetadata(tag_decl); + } + +protected: + std::string m_test_exe; + + SubsystemRAII<FileSystem, HostInfo, ObjectFilePECOFF, SymbolFileNativePDB, + SymbolFilePDB, TypeSystemClang> + m_subsystems; + lldb::DebuggerSP m_debugger_sp; +}; + +TEST_F(SymbolFilePDBTests, TestDynamicCxxType) { + FileSpec fspec(m_test_exe); + ArchSpec aspec("x86_64-pc-windows"); + lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec); + + SymbolFile *symfile = module->GetSymbolFile(); + ASSERT_TRUE(symfile); + ASSERT_TRUE(llvm::isa<SymbolFileNativePDB>(symfile)); + + auto ts = symfile->GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + ASSERT_TRUE(bool(ts)); + TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts->get()); + ASSERT_NE(clang, nullptr); + + auto using_base_meta = GetMetadataFor(symfile, "UsingBase", clang); + ASSERT_TRUE(using_base_meta.has_value()); + ASSERT_TRUE(using_base_meta->GetIsDynamicCXXType().has_value()); + ASSERT_EQ(using_base_meta->GetIsDynamicCXXType(), true); // has vtable + + auto base_meta = GetMetadataFor(symfile, "Base", clang); + ASSERT_TRUE(base_meta.has_value()); + ASSERT_TRUE(base_meta->GetIsDynamicCXXType().has_value()); + ASSERT_EQ(base_meta->GetIsDynamicCXXType(), true); // has vtable + + auto vbase_meta = GetMetadataFor(symfile, "VBase", clang); + ASSERT_TRUE(vbase_meta.has_value()); + ASSERT_TRUE(vbase_meta->GetIsDynamicCXXType().has_value()); + ASSERT_EQ(vbase_meta->GetIsDynamicCXXType(), false); // empty struct + + auto using_vbase_meta = GetMetadataFor(symfile, "UsingVBase", clang); + ASSERT_TRUE(using_vbase_meta.has_value()); + ASSERT_TRUE(using_vbase_meta->GetIsDynamicCXXType().has_value()); + ASSERT_EQ(using_vbase_meta->GetIsDynamicCXXType(), true); // has virtual base + + auto uu_vbase_meta = GetMetadataFor(symfile, "UsingUsingVBase", clang); + ASSERT_TRUE(uu_vbase_meta.has_value()); + ASSERT_TRUE(uu_vbase_meta->GetIsDynamicCXXType().has_value()); + ASSERT_EQ(uu_vbase_meta->GetIsDynamicCXXType(), + true); // has 'UsingVBase' as non-virtual base + + auto not_dynamic_meta = GetMetadataFor(symfile, "NotDynamic", clang); + ASSERT_TRUE(not_dynamic_meta.has_value()); + ASSERT_TRUE(not_dynamic_meta->GetIsDynamicCXXType().has_value()); + ASSERT_EQ(not_dynamic_meta->GetIsDynamicCXXType(), + false); // has 'VBase' as non-virtual base +} _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
