Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h +++ lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h @@ -14,8 +14,6 @@ namespace lldb_private { -class TypeSystemClang; - class ClangExternalASTSourceCallbacks : public clang::ExternalASTSource { /// LLVM RTTI support. static char ID; @@ -51,8 +49,8 @@ llvm::Optional getSourceDescriptor(unsigned ID) override; clang::Module *getModule(unsigned ID) override; - unsigned RegisterModule(clang::Module *module); - unsigned GetIDForModule(clang::Module *module); + ModuleID RegisterModule(clang::Module *module); + ModuleID GetIDForModule(clang::Module *module); /// \} private: TypeSystemClang &m_ast; Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp @@ -46,11 +46,11 @@ } } -unsigned ClangExternalASTSourceCallbacks::RegisterModule(clang::Module *module) { +ModuleID ClangExternalASTSourceCallbacks::RegisterModule(clang::Module *module) { m_modules.push_back(module); unsigned id = m_modules.size(); m_ids.insert({module, id}); - return id; + return ModuleID(id); } llvm::Optional @@ -66,6 +66,6 @@ return nullptr; } -unsigned ClangExternalASTSourceCallbacks::GetIDForModule(clang::Module *module) { - return m_ids[module]; +ModuleID ClangExternalASTSourceCallbacks::GetIDForModule(clang::Module *module) { + return ModuleID(m_ids[module]); } Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -78,6 +78,8 @@ DIEToDeclContextMap; typedef std::multimap DeclContextToDIEMap; + typedef llvm::DenseMap + DIEToModuleMap; typedef llvm::DenseMap DIEToDeclMap; typedef llvm::DenseMap DeclToDIEMap; @@ -87,6 +89,7 @@ DeclToDIEMap m_decl_to_die; DIEToDeclContextMap m_die_to_decl_ctx; DeclContextToDIEMap m_decl_ctx_to_die; + DIEToModuleMap m_die_to_module; std::unique_ptr m_clang_ast_importer_up; /// @} @@ -140,6 +143,7 @@ clang::DeclContext *GetClangDeclContextContainingDIE(const DWARFDIE &die, DWARFDIE *decl_ctx_die); + lldb_private::ModuleID GetOwningModuleID(const DWARFDIE &die); bool CopyUniqueClassMethodTypes(const DWARFDIE &src_class_die, const DWARFDIE &dst_class_die, Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -211,13 +211,30 @@ die.GetID(), dwarf, pcm_type_sp->GetName(), pcm_type_sp->GetByteSize(), nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid, &pcm_type_sp->GetDeclaration(), type, Type::ResolveState::Forward)); + TypePayloadClang(type_sp->GetPayload()) + .SetOwningModuleID(GetOwningModuleID(die)); dwarf->GetTypeList().Insert(type_sp); dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); clang::TagDecl *tag_decl = TypeSystemClang::GetAsTagDecl(type); - if (tag_decl) + ModuleID owning_module = GetOwningModuleID(die); + if (tag_decl) { + TypeSystemClang::SetOwningModule(tag_decl, owning_module); + if (auto *rd = llvm::dyn_cast(tag_decl)) + for (clang::FieldDecl *fd : rd->fields()) + TypeSystemClang::SetOwningModule(fd, owning_module); + if (auto *ed = llvm::dyn_cast(tag_decl)) + for (clang::EnumConstantDecl *ecd : ed->enumerators()) + TypeSystemClang::SetOwningModule(ecd, owning_module); LinkDeclContextToDIE(tag_decl, die); - else { + } else { + if (auto *oid = TypeSystemClang::GetAsObjCInterfaceDecl(type)) { + TypeSystemClang::SetOwningModule(oid, owning_module); + for (clang::ObjCMethodDecl *omd : oid->methods()) + TypeSystemClang::SetOwningModule(omd, owning_module); + for (clang::ObjCPropertyDecl *opd : oid->properties()) + TypeSystemClang::SetOwningModule(opd, owning_module); + } clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die); if (defn_decl_ctx) LinkDeclContextToDIE(defn_decl_ctx, die); @@ -707,6 +724,7 @@ die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, dwarf->GetUID(attrs.type.Reference()), encoding_data_type, &attrs.decl, clang_type, resolve_state); + TypePayloadClang(type_sp->GetPayload()).SetOwningModuleID(GetOwningModuleID(die)); dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); return type_sp; @@ -788,7 +806,8 @@ clang_type = m_ast.CreateEnumerationType( attrs.name.GetCString(), GetClangDeclContextContainingDIE(die, nullptr), - ModuleID(), attrs.decl, enumerator_clang_type, attrs.is_scoped_enum); + GetOwningModuleID(die), attrs.decl, enumerator_clang_type, + attrs.is_scoped_enum); } else { enumerator_clang_type = m_ast.GetEnumerationIntegerType(clang_type); } @@ -799,6 +818,7 @@ die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, dwarf->GetUID(attrs.type.Reference()), Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Forward); + TypePayloadClang(type_sp->GetPayload()).SetOwningModuleID(GetOwningModuleID(die)); if (TypeSystemClang::StartTagDeclarationDefinition(clang_type)) { if (die.HasChildren()) { @@ -1171,7 +1191,8 @@ function_decl = m_ast.CreateFunctionDeclaration( ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, - ModuleID(), attrs.name.GetCString(), clang_type, attrs.storage, + GetOwningModuleID(die), + attrs.name.GetCString(), clang_type, attrs.storage, attrs.is_inline); if (has_template_params) { @@ -1180,12 +1201,13 @@ template_function_decl = m_ast.CreateFunctionDeclaration( ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, - ModuleID(), attrs.name.GetCString(), clang_type, attrs.storage, - attrs.is_inline); + GetOwningModuleID(die), attrs.name.GetCString(), clang_type, + attrs.storage, attrs.is_inline); clang::FunctionTemplateDecl *func_template_decl = m_ast.CreateFunctionTemplateDecl( - containing_decl_ctx, ModuleID(), template_function_decl, - attrs.name.GetCString(), template_param_infos); + containing_decl_ctx, GetOwningModuleID(die), + template_function_decl, attrs.name.GetCString(), + template_param_infos); m_ast.CreateFunctionTemplateSpecializationInfo( function_decl, func_template_decl, template_param_infos); } @@ -1583,7 +1605,7 @@ if (ParseTemplateParameterInfos(die, template_param_infos)) { clang::ClassTemplateDecl *class_template_decl = m_ast.ParseClassTemplateDecl( - decl_ctx, ModuleID(), attrs.accessibility, + decl_ctx, GetOwningModuleID(die), attrs.accessibility, attrs.name.GetCString(), tag_decl_kind, template_param_infos); if (!class_template_decl) { if (log) { @@ -1599,8 +1621,8 @@ clang::ClassTemplateSpecializationDecl *class_specialization_decl = m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, ModuleID(), class_template_decl, tag_decl_kind, - template_param_infos); + decl_ctx, GetOwningModuleID(die), class_template_decl, + tag_decl_kind, template_param_infos); clang_type = m_ast.CreateClassTemplateSpecializationType( class_specialization_decl); clang_type_was_created = true; @@ -1613,9 +1635,9 @@ if (!clang_type_was_created) { clang_type_was_created = true; clang_type = m_ast.CreateRecordType( - decl_ctx, ModuleID(), attrs.accessibility, attrs.name.GetCString(), - tag_decl_kind, attrs.class_language, &metadata, - attrs.exports_symbols); + decl_ctx, GetOwningModuleID(die), attrs.accessibility, + attrs.name.GetCString(), tag_decl_kind, attrs.class_language, + &metadata, attrs.exports_symbols); } } @@ -3062,7 +3084,7 @@ clang::ParmVarDecl *param_var_decl = m_ast.CreateParameterDeclaration( - containing_decl_ctx, ModuleID(), name, + containing_decl_ctx, GetOwningModuleID(die), name, type->GetForwardCompilerType(), storage); assert(param_var_decl); function_param_decls.push_back(param_var_decl); @@ -3261,7 +3283,7 @@ TypeSystemClang::DeclContextGetAsDeclContext( dwarf->GetDeclContextContainingUID(die.GetID())); decl = m_ast.CreateVariableDeclaration( - decl_context, ModuleID(), name, + decl_context, GetOwningModuleID(die), name, ClangUtil::GetQualType(type->GetForwardCompilerType())); } break; @@ -3357,6 +3379,31 @@ return nullptr; } +ModuleID DWARFASTParserClang::GetOwningModuleID(const DWARFDIE &die) { + if (!die.IsValid()) + return {}; + + for (DWARFDIE parent = die.GetParent(); parent.IsValid(); + parent = parent.GetParent()) { + const dw_tag_t tag = parent.Tag(); + if (tag == DW_TAG_module) { + DWARFDIE module_die = parent; + auto it = m_die_to_module.find(module_die.GetDIE()); + if (it != m_die_to_module.end()) + return it->second; + const char *name = module_die.GetAttributeValueAsString(DW_AT_name, 0); + if (!name) + return {}; + + ModuleID id = + m_ast.GetOrCreateClangModule(name, GetOwningModuleID(module_die)); + m_die_to_module.insert({module_die.GetDIE(), id}); + return id; + } + } + return {}; +} + static bool IsSubroutine(const DWARFDIE &die) { switch (die.Tag()) { case DW_TAG_subprogram: @@ -3429,7 +3476,7 @@ DWARFDIE decl_context_die; clang::DeclContext *decl_context = GetClangDeclContextContainingDIE(die, &decl_context_die); - decl = m_ast.CreateBlockDeclaration(decl_context, ModuleID()); + decl = m_ast.CreateBlockDeclaration(decl_context, GetOwningModuleID(die)); if (decl) LinkDeclContextToDIE((clang::DeclContext *)decl, die); Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h =================================================================== --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -314,8 +314,8 @@ static uint32_t GetNumBaseClasses(const clang::CXXRecordDecl *cxx_record_decl, bool omit_empty_base_classes); - /// Synthesize a clang::Module and return its ID or 0. - unsigned GetOrCreateClangModule(llvm::StringRef name, unsigned parent, + /// Synthesize a clang::Module and return its ID or a default-constructed ID. + ModuleID GetOrCreateClangModule(llvm::StringRef name, ModuleID parent, bool is_framework = false, bool is_explicit = false); Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp =================================================================== --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -1225,8 +1225,8 @@ decl->setModuleOwnershipKind(clang::Decl::ModuleOwnershipKind::Visible); } -unsigned TypeSystemClang::GetOrCreateClangModule(llvm::StringRef name, - unsigned parent, +ModuleID TypeSystemClang::GetOrCreateClangModule(llvm::StringRef name, + ModuleID parent, bool is_framework, bool is_explicit) { // Get the external AST source which holds the modules. @@ -1234,7 +1234,7 @@ getASTContext().getExternalSource()); assert(ast_source && "external ast source was lost"); if (!ast_source) - return 0; + return {}; // Lazily initialize the module map. if (!m_header_search_up) { @@ -1250,7 +1250,7 @@ // Get or create the module context. bool created; clang::Module *module; - auto parent_desc = ast_source->getSourceDescriptor(parent); + auto parent_desc = ast_source->getSourceDescriptor(parent.id); std::tie(module, created) = m_module_map_up->findOrCreateModule( name, parent_desc ? parent_desc->getModuleOrNull() : nullptr, is_framework, is_explicit); Index: lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h =================================================================== --- /dev/null +++ lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h @@ -0,0 +1,30 @@ +#include "B.h" // -*- ObjC -*- + +typedef int Typedef; + +struct TopLevelStruct { + int a; +}; + +typedef struct Struct_s { + int a; +} Struct; + +struct Nested { + StructB fromb; +}; + +typedef enum Enum_e { + a = 0 +} Enum; + +@interface SomeClass {} +@end + +template struct Template { T field; }; +extern template struct Template; + +namespace Namespace { +template struct InNamespace { T field; }; +extern template struct InNamespace; +} Index: lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/B.h =================================================================== --- /dev/null +++ lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/B.h @@ -0,0 +1,8 @@ +typedef struct { + int b; +} StructB; + +namespace Namespace { +template struct AlsoInNamespace { T field; }; + extern template struct AlsoInNamespace; +} Index: lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/module.modulemap =================================================================== --- /dev/null +++ lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/module.modulemap @@ -0,0 +1,6 @@ +module A { + header "A.h" + module B { + header "B.h" + } +} Index: lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg =================================================================== --- lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg +++ lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg @@ -1 +1 @@ -config.suffixes = ['.cpp', '.m', '.s', '.test', '.ll'] +config.suffixes = ['.cpp', '.m', '.mm', '.s', '.test', '.ll'] Index: lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm =================================================================== --- /dev/null +++ lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm @@ -0,0 +1,41 @@ +// RUN: %clang --target=x86_64-apple-macosx -g -gmodules \ +// RUN: -fmodules -fmodules-cache-path=%t.cache \ +// RUN: -c -o %t.o %s -I%S/Inputs +// RUN: lldb-test symbols -dump-clang-ast %t.o | FileCheck %s +// Verify that the owning module information from DWARF is preserved in the AST. + +@import A; + +Typedef t1; +// CHECK-DAG: TypedefDecl {{.*}} imported in A Typedef + +TopLevelStruct s1; +// CHECK-DAG: CXXRecordDecl {{.*}} imported in A struct TopLevelStruct +// CHECK-DAG: -FieldDecl {{.*}} in A a 'int' + +Struct s2; +// CHECK-DAG: CXXRecordDecl {{.*}} imported in A struct + +StructB s3; +// CHECK-DAG: CXXRecordDecl {{.*}} imported in A.B struct +// CHECK-DAG: -FieldDecl {{.*}} in A.B b 'int' + +Nested s4; +// CHECK-DAG: CXXRecordDecl {{.*}} imported in A struct Nested +// CHECK-DAG: -FieldDecl {{.*}} in A fromb 'StructB' + +Enum e1; +// CHECK-DAG: EnumDecl {{.*}} imported in A Enum_e +// CHECK-DAG: -EnumConstantDecl {{.*}} imported in A a + +SomeClass *obj1; +// CHECK-DAG: ObjCInterfaceDecl {{.*}} imported in A SomeClass + +Template t2; +// CHECK-DAG: ClassTemplateSpecializationDecl {{.*}} imported in A struct Template + +Namespace::InNamespace t3; +// CHECK-DAG: ClassTemplateSpecializationDecl {{.*}} imported in A struct InNamespace + +Namespace::AlsoInNamespace t4; +// CHECK-DAG: ClassTemplateSpecializationDecl {{.*}} imported in A.B struct AlsoInNamespace