From 143d507c9ff90db93e547f0e1131e92db06e2675 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Wed, 4 Mar 2020 09:30:12 -0800 Subject: [PATCH] Preserve the owning module information from DWARF in the synthesized AST Types that came from a Clang module are nested in DW_TAG_module tags in DWARF. This patch recreates the Clang module hierarchy in LLDB and 1;95;0csets the owning module information accordingly. My primary motivation is to facilitate looking up per-module APINotes for individual declarations, but this likely also has other applications. This reapplies the previously reverted commit, but without support for ClassTemplateSpecializations, which I'm going to look into separately. rdar://problem/59634380 Differential Revision: https://reviews.llvm.org/D75488 --- lldb/include/lldb/Symbol/CompilerType.h | 4 +- lldb/include/lldb/Symbol/TypeSystem.h | 5 +- .../ExpressionParser/Clang/ClangASTImporter.cpp | 30 +++ .../Clang/ClangExpressionDeclMap.cpp | 2 +- .../Clang/ClangExternalASTSourceCallbacks.cpp | 28 +++ .../Clang/ClangExternalASTSourceCallbacks.h | 23 +- lldb/source/Plugins/Language/ObjC/NSDictionary.cpp | 5 +- .../AppleObjCTypeEncodingParser.cpp | 3 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 92 +++++--- .../Plugins/SymbolFile/DWARF/DWARFASTParserClang.h | 5 + .../Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp | 26 ++- .../source/Plugins/SymbolFile/PDB/PDBASTParser.cpp | 25 +-- .../SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp | 5 +- .../Plugins/TypeSystem/Clang/TypeSystemClang.cpp | 231 ++++++++++++++++----- .../Plugins/TypeSystem/Clang/TypeSystemClang.h | 95 +++++++-- lldb/source/Symbol/CompilerType.cpp | 8 +- lldb/source/Symbol/Type.cpp | 4 +- lldb/source/Symbol/TypeSystem.cpp | 3 +- .../SymbolFile/DWARF/Inputs/ModuleOwnership/A.h | 29 +++ .../SymbolFile/DWARF/Inputs/ModuleOwnership/B.h | 8 + .../DWARF/Inputs/ModuleOwnership/module.modulemap | 6 + lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg | 2 +- .../Shell/SymbolFile/DWARF/module-ownership.mm | 42 ++++ lldb/unittests/Symbol/TestTypeSystemClang.cpp | 80 ++++--- .../TestingSupport/Symbol/ClangTestUtils.h | 1 + 25 files changed, 594 insertions(+), 168 deletions(-) create mode 100644 lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h create mode 100644 lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/B.h create mode 100644 lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/module.modulemap create mode 100644 lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index 0d1b00a..b0a7953 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -242,8 +242,10 @@ public: /// Create a typedef to this type using "name" as the name of the typedef this /// type is valid and the type system supports typedefs, else return an /// invalid type. + /// \param payload The typesystem-specific \p lldb::Type payload. CompilerType CreateTypedef(const char *name, - const CompilerDeclContext &decl_ctx) const; + const CompilerDeclContext &decl_ctx, + uint32_t payload) const; /// If the current object represents a typedef type, get the underlying type CompilerType GetTypedefedType() const; diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index a84b9a1..ba2bbfa 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -259,9 +259,12 @@ public: virtual CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type); + /// \param opaque_payload The m_payload field of Type, which may + /// carry TypeSystem-specific extra information. virtual CompilerType CreateTypedef(lldb::opaque_compiler_type_t type, const char *name, - const CompilerDeclContext &decl_ctx); + const CompilerDeclContext &decl_ctx, + uint32_t opaque_payload); // Exploring the type diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp index 4b3e237..2a21e5e 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp @@ -18,6 +18,7 @@ #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h" +#include "Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h" #include "Plugins/ExpressionParser/Clang/ClangUtil.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" @@ -1003,6 +1004,21 @@ static void MaybeCompleteReturnType(ClangASTImporter &importer, importer.CompleteTagDecl(rd); } +/// Recreate a module with its parents in \p to_source and return its id. +static OptionalClangModuleID +RemapModule(OptionalClangModuleID from_id, + ClangExternalASTSourceCallbacks &from_source, + ClangExternalASTSourceCallbacks &to_source) { + if (!from_id.HasValue()) + return {}; + clang::Module *module = from_source.getModule(from_id.GetValue()); + OptionalClangModuleID parent = RemapModule( + from_source.GetIDForModule(module->Parent), from_source, to_source); + TypeSystemClang &to_ts = to_source.GetTypeSystem(); + return to_ts.GetOrCreateClangModule(module->Name, parent, module->IsFramework, + module->IsExplicit); +} + void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, clang::Decl *to) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); @@ -1012,6 +1028,20 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, if (m_decls_to_ignore.find(to) != m_decls_to_ignore.end()) return clang::ASTImporter::Imported(from, to); + // Transfer module ownership information. + auto *from_source = llvm::dyn_cast_or_null( + getFromContext().getExternalSource()); + // Can also be a ClangASTSourceProxy. + auto *to_source = llvm::dyn_cast_or_null( + getToContext().getExternalSource()); + if (from_source && to_source) { + OptionalClangModuleID from_id(from->getOwningModuleID()); + OptionalClangModuleID to_id = + RemapModule(from_id, *from_source, *to_source); + TypeSystemClang &to_ts = to_source->GetTypeSystem(); + to_ts.SetOwningModule(to, to_id); + } + lldb::user_id_t user_id = LLDB_INVALID_UID; ClangASTMetadata *metadata = m_master.GetDeclMetadata(from); if (metadata) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 9eca2d0..7d66cc0 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -993,7 +993,7 @@ void ClangExpressionDeclMap::LookupLocalVarNamespace( clang::NamespaceDecl *namespace_decl = m_clang_ast_context->GetUniqueNamespaceDeclaration( - g_lldb_local_vars_namespace_cstr, nullptr); + g_lldb_local_vars_namespace_cstr, nullptr, OptionalClangModuleID()); if (!namespace_decl) return; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp index 26dc4d6..943058f 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp @@ -13,6 +13,8 @@ using namespace lldb_private; +char ClangExternalASTSourceCallbacks::ID; + void ClangExternalASTSourceCallbacks::CompleteType(clang::TagDecl *tag_decl) { m_ast.CompleteTagDecl(tag_decl); } @@ -43,3 +45,29 @@ void ClangExternalASTSourceCallbacks::FindExternalLexicalDecls( CompleteType(tag_decl); } } + +OptionalClangModuleID +ClangExternalASTSourceCallbacks::RegisterModule(clang::Module *module) { + m_modules.push_back(module); + unsigned id = m_modules.size(); + m_ids.insert({module, id}); + return OptionalClangModuleID(id); +} + +llvm::Optional +ClangExternalASTSourceCallbacks::getSourceDescriptor(unsigned id) { + if (clang::Module *module = getModule(id)) + return {*module}; + return {}; +} + +clang::Module *ClangExternalASTSourceCallbacks::getModule(unsigned id) { + if (id && id <= m_modules.size()) + return m_modules[id - 1]; + return nullptr; +} + +OptionalClangModuleID +ClangExternalASTSourceCallbacks::GetIDForModule(clang::Module *module) { + return OptionalClangModuleID(m_ids[module]); +} diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h index 4bbf556..fc6ba0d 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h @@ -10,14 +10,19 @@ #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXTERNALASTSOURCECALLBACKS_H #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" -#include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/Module.h" namespace lldb_private { -class TypeSystemClang; - class ClangExternalASTSourceCallbacks : public clang::ExternalASTSource { + /// LLVM RTTI support. + static char ID; + public: + /// LLVM RTTI support. + bool isA(const void *ClassID) const override { return ClassID == &ID; } + static bool classof(const clang::ExternalASTSource *s) { return s->isA(&ID); } + ClangExternalASTSourceCallbacks(TypeSystemClang &ast) : m_ast(ast) {} void FindExternalLexicalDecls( @@ -37,8 +42,20 @@ public: llvm::DenseMap &VirtualBaseOffsets) override; + TypeSystemClang &GetTypeSystem() const { return m_ast; } + + /// Module-related methods. + /// \{ + llvm::Optional + getSourceDescriptor(unsigned ID) override; + clang::Module *getModule(unsigned ID) override; + OptionalClangModuleID RegisterModule(clang::Module *module); + OptionalClangModuleID GetIDForModule(clang::Module *module); + /// \} private: TypeSystemClang &m_ast; + std::vector m_modules; + llvm::DenseMap m_ids; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp index 2b22885..e76096b 100644 --- a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -76,8 +76,9 @@ static CompilerType GetLLDBNSPairType(TargetSP target_sp) { if (!compiler_type) { compiler_type = target_ast_context->CreateRecordType( - nullptr, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), - clang::TTK_Struct, lldb::eLanguageTypeC); + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, + g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, + lldb::eLanguageTypeC); if (compiler_type) { TypeSystemClang::StartTagDeclarationDefinition(compiler_type); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index 8484318..ba76f68 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -124,7 +124,8 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate( return clang::QualType(); // This is where we bail out. Sorry! CompilerType union_type(ast_ctx.CreateRecordType( - nullptr, lldb::eAccessPublic, name, kind, lldb::eLanguageTypeC)); + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, name, kind, + lldb::eLanguageTypeC)); if (union_type) { TypeSystemClang::StartTagDeclarationDefinition(union_type); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 96500da..62aba37 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -212,14 +212,15 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, TypeSP type_sp(new Type( 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)); + &pcm_type_sp->GetDeclaration(), type, Type::ResolveState::Forward, + TypePayloadClang(GetOwningClangModule(die)))); dwarf->GetTypeList().Insert(type_sp); dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); clang::TagDecl *tag_decl = TypeSystemClang::GetAsTagDecl(type); - if (tag_decl) + if (tag_decl) { LinkDeclContextToDIE(tag_decl, die); - else { + } else { clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die); if (defn_decl_ctx) LinkDeclContextToDIE(defn_decl_ctx, die); @@ -708,7 +709,7 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc, type_sp = std::make_shared( die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, dwarf->GetUID(attrs.type.Reference()), encoding_data_type, &attrs.decl, - clang_type, resolve_state); + clang_type, resolve_state, TypePayloadClang(GetOwningClangModule(die))); dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); return type_sp; @@ -790,7 +791,8 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, clang_type = m_ast.CreateEnumerationType( attrs.name.GetCString(), GetClangDeclContextContainingDIE(die, nullptr), - attrs.decl, enumerator_clang_type, attrs.is_scoped_enum); + GetOwningClangModule(die), attrs.decl, enumerator_clang_type, + attrs.is_scoped_enum); } else { enumerator_clang_type = m_ast.GetEnumerationIntegerType(clang_type); } @@ -800,7 +802,8 @@ TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc, type_sp = std::make_shared( die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, dwarf->GetUID(attrs.type.Reference()), Type::eEncodingIsUID, &attrs.decl, - clang_type, Type::ResolveState::Forward); + clang_type, Type::ResolveState::Forward, + TypePayloadClang(GetOwningClangModule(die))); if (TypeSystemClang::StartTagDeclarationDefinition(clang_type)) { if (die.HasChildren()) { @@ -1184,7 +1187,8 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, function_decl = m_ast.CreateFunctionDeclaration( ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, - name, clang_type, attrs.storage, attrs.is_inline); + GetOwningClangModule(die), name, clang_type, attrs.storage, + attrs.is_inline); if (has_template_params) { TypeSystemClang::TemplateParameterInfos template_param_infos; @@ -1192,12 +1196,12 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, template_function_decl = m_ast.CreateFunctionDeclaration( ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, - name, clang_type, attrs.storage, attrs.is_inline); - + GetOwningClangModule(die), attrs.name.GetCString(), clang_type, + attrs.storage, attrs.is_inline); clang::FunctionTemplateDecl *func_template_decl = - m_ast.CreateFunctionTemplateDecl(containing_decl_ctx, - template_function_decl, name, - template_param_infos); + m_ast.CreateFunctionTemplateDecl( + containing_decl_ctx, GetOwningClangModule(die), + template_function_decl, name, template_param_infos); m_ast.CreateFunctionTemplateSpecializationInfo( template_function_decl, func_template_decl, template_param_infos); } @@ -1594,9 +1598,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, TypeSystemClang::TemplateParameterInfos template_param_infos; if (ParseTemplateParameterInfos(die, template_param_infos)) { clang::ClassTemplateDecl *class_template_decl = - m_ast.ParseClassTemplateDecl(decl_ctx, attrs.accessibility, - attrs.name.GetCString(), tag_decl_kind, - template_param_infos); + m_ast.ParseClassTemplateDecl( + decl_ctx, GetOwningClangModule(die), attrs.accessibility, + attrs.name.GetCString(), tag_decl_kind, template_param_infos); if (!class_template_decl) { if (log) { dwarf->GetObjectFile()->GetModule()->LogMessage( @@ -1611,8 +1615,8 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, clang::ClassTemplateSpecializationDecl *class_specialization_decl = m_ast.CreateClassTemplateSpecializationDecl( - decl_ctx, class_template_decl, tag_decl_kind, - template_param_infos); + decl_ctx, GetOwningClangModule(die), class_template_decl, + tag_decl_kind, template_param_infos); clang_type = m_ast.CreateClassTemplateSpecializationType( class_specialization_decl); clang_type_was_created = true; @@ -1625,8 +1629,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, if (!clang_type_was_created) { clang_type_was_created = true; clang_type = m_ast.CreateRecordType( - decl_ctx, attrs.accessibility, attrs.name.GetCString(), tag_decl_kind, - attrs.class_language, &metadata, attrs.exports_symbols); + decl_ctx, GetOwningClangModule(die), attrs.accessibility, + attrs.name.GetCString(), tag_decl_kind, attrs.class_language, + &metadata, attrs.exports_symbols); } } @@ -1638,7 +1643,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Forward, - TypePayloadClang(attrs.is_complete_objc_class)); + TypePayloadClang(OptionalClangModuleID(), attrs.is_complete_objc_class)); // Add our type to the unique type map so we don't end up creating many // copies of the same type over and over in the ASTContext for our @@ -3082,9 +3087,9 @@ size_t DWARFASTParserClang::ParseChildParameters( function_param_types.push_back(type->GetForwardCompilerType()); clang::ParmVarDecl *param_var_decl = - m_ast.CreateParameterDeclaration(containing_decl_ctx, name, - type->GetForwardCompilerType(), - storage); + m_ast.CreateParameterDeclaration( + containing_decl_ctx, GetOwningClangModule(die), name, + type->GetForwardCompilerType(), storage); assert(param_var_decl); function_param_decls.push_back(param_var_decl); @@ -3282,7 +3287,7 @@ clang::Decl *DWARFASTParserClang::GetClangDeclForDIE(const DWARFDIE &die) { TypeSystemClang::DeclContextGetAsDeclContext( dwarf->GetDeclContextContainingUID(die.GetID())); decl = m_ast.CreateVariableDeclaration( - decl_context, name, + decl_context, GetOwningClangModule(die), name, ClangUtil::GetQualType(type->GetForwardCompilerType())); } break; @@ -3299,8 +3304,8 @@ clang::Decl *DWARFASTParserClang::GetClangDeclForDIE(const DWARFDIE &die) { if (clang::NamedDecl *clang_imported_decl = llvm::dyn_cast( (clang::Decl *)imported_decl.GetOpaqueDecl())) - decl = - m_ast.CreateUsingDeclaration(decl_context, clang_imported_decl); + decl = m_ast.CreateUsingDeclaration( + decl_context, OptionalClangModuleID(), clang_imported_decl); } } break; @@ -3319,7 +3324,8 @@ clang::Decl *DWARFASTParserClang::GetClangDeclForDIE(const DWARFDIE &die) { if (clang::NamespaceDecl *ns_decl = TypeSystemClang::DeclContextGetAsNamespaceDecl( imported_decl_ctx)) - decl = m_ast.CreateUsingDirectiveDeclaration(decl_context, ns_decl); + decl = m_ast.CreateUsingDirectiveDeclaration( + decl_context, OptionalClangModuleID(), ns_decl); } } break; @@ -3377,6 +3383,32 @@ DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) { return nullptr; } +OptionalClangModuleID +DWARFASTParserClang::GetOwningClangModule(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 {}; + + OptionalClangModuleID id = + m_ast.GetOrCreateClangModule(name, GetOwningClangModule(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: @@ -3449,7 +3481,8 @@ clang::BlockDecl *DWARFASTParserClang::ResolveBlockDIE(const DWARFDIE &die) { DWARFDIE decl_context_die; clang::DeclContext *decl_context = GetClangDeclContextContainingDIE(die, &decl_context_die); - decl = m_ast.CreateBlockDeclaration(decl_context); + decl = + m_ast.CreateBlockDeclaration(decl_context, GetOwningClangModule(die)); if (decl) LinkDeclContextToDIE((clang::DeclContext *)decl, die); @@ -3477,7 +3510,8 @@ DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) { die.GetAttributeValueAsUnsigned(DW_AT_export_symbols, 0) != 0; namespace_decl = m_ast.GetUniqueNamespaceDeclaration( - namespace_name, containing_decl_ctx, is_inline); + namespace_name, containing_decl_ctx, GetOwningClangModule(die), + is_inline); Log *log = nullptr; // (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); if (log) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 40d97ac..020d29d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -78,6 +78,9 @@ protected: DIEToDeclContextMap; typedef std::multimap DeclContextToDIEMap; + typedef llvm::DenseMap + DIEToModuleMap; typedef llvm::DenseMap DIEToDeclMap; typedef llvm::DenseMap DeclToDIEMap; @@ -87,6 +90,7 @@ protected: 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 +144,7 @@ protected: clang::DeclContext *GetClangDeclContextContainingDIE(const DWARFDIE &die, DWARFDIE *decl_ctx_die); + lldb_private::OptionalClangModuleID GetOwningClangModule(const DWARFDIE &die); bool CopyUniqueClassMethodTypes(const DWARFDIE &src_class_die, const DWARFDIE &dst_class_die, diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 1e9c24e..b88f875 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -776,8 +776,9 @@ clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id, metadata.SetUserID(toOpaqueUid(id)); metadata.SetIsDynamicCXXType(false); - CompilerType ct = m_clang.CreateRecordType( - context, access, uname, ttk, lldb::eLanguageTypeC_plus_plus, &metadata); + CompilerType ct = + m_clang.CreateRecordType(context, OptionalClangModuleID(), access, uname, + ttk, lldb::eLanguageTypeC_plus_plus, &metadata); lldbassert(ct.IsValid()); @@ -804,7 +805,8 @@ clang::NamespaceDecl * PdbAstBuilder::GetOrCreateNamespaceDecl(const char *name, clang::DeclContext &context) { return m_clang.GetUniqueNamespaceDeclaration( - IsAnonymousNamespaceName(name) ? nullptr : name, &context); + IsAnonymousNamespaceName(name) ? nullptr : name, &context, + OptionalClangModuleID()); } clang::BlockDecl * @@ -814,7 +816,8 @@ PdbAstBuilder::GetOrCreateBlockDecl(PdbCompilandSymId block_id) { clang::DeclContext *scope = GetParentDeclContext(block_id); - clang::BlockDecl *block_decl = m_clang.CreateBlockDeclaration(scope); + clang::BlockDecl *block_decl = + m_clang.CreateBlockDeclaration(scope, OptionalClangModuleID()); m_uid_to_decl.insert({toOpaqueUid(block_id), block_decl}); DeclStatus status; @@ -831,7 +834,7 @@ clang::VarDecl *PdbAstBuilder::CreateVariableDecl(PdbSymUid uid, CVSymbol sym, clang::QualType qt = GetOrCreateType(var_info.type); clang::VarDecl *var_decl = m_clang.CreateVariableDeclaration( - &scope, var_info.name.str().c_str(), qt); + &scope, OptionalClangModuleID(), var_info.name.str().c_str(), qt); m_uid_to_decl[toOpaqueUid(uid)] = var_decl; DeclStatus status; @@ -879,7 +882,7 @@ PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) { std::string uname = std::string(DropNameScope(udt.Name)); CompilerType ct = m_clang.CreateTypedefType(ToCompilerType(qt), uname.c_str(), - ToCompilerDeclContext(*scope)); + ToCompilerDeclContext(*scope), 0); clang::TypedefNameDecl *tnd = m_clang.GetAsTypedefDecl(ct); DeclStatus status; status.resolved = true; @@ -1012,7 +1015,8 @@ PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) { proc_name.consume_front("::"); clang::FunctionDecl *function_decl = m_clang.CreateFunctionDeclaration( - parent, proc_name.str().c_str(), func_ct, storage, false); + parent, OptionalClangModuleID(), proc_name.str().c_str(), func_ct, + storage, false); lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0); m_uid_to_decl[toOpaqueUid(func_id)] = function_decl; @@ -1080,8 +1084,8 @@ void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id, CompilerType param_type_ct = m_clang.GetType(qt); clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration( - &function_decl, param_name.str().c_str(), param_type_ct, - clang::SC_None, true); + &function_decl, OptionalClangModuleID(), param_name.str().c_str(), + param_type_ct, clang::SC_None, true); lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0); m_uid_to_decl[toOpaqueUid(param_uid)] = param; @@ -1102,8 +1106,8 @@ clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id, Declaration declaration; CompilerType enum_ct = m_clang.CreateEnumerationType( - uname.c_str(), decl_context, declaration, ToCompilerType(underlying_type), - er.isScoped()); + uname.c_str(), decl_context, OptionalClangModuleID(), declaration, + ToCompilerType(underlying_type), er.isScoped()); TypeSystemClang::StartTagDeclarationDefinition(enum_ct); TypeSystemClang::SetHasExternalStorage(enum_ct.GetOpaqueQualType(), true); diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index a038788..112bec4 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -409,9 +409,9 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { metadata.SetUserID(type.getSymIndexId()); metadata.SetIsDynamicCXXType(false); - clang_type = - m_ast.CreateRecordType(decl_context, access, name, tag_type_kind, - lldb::eLanguageTypeC_plus_plus, &metadata); + clang_type = m_ast.CreateRecordType( + decl_context, OptionalClangModuleID(), access, name, tag_type_kind, + lldb::eLanguageTypeC_plus_plus, &metadata); assert(clang_type.IsValid()); auto record_decl = @@ -497,7 +497,8 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { // Class). Set it false for now. bool isScoped = false; - ast_enum = m_ast.CreateEnumerationType(name.c_str(), decl_context, decl, + ast_enum = m_ast.CreateEnumerationType(name.c_str(), decl_context, + OptionalClangModuleID(), decl, builtin_type, isScoped); auto enum_decl = TypeSystemClang::GetAsEnumDecl(ast_enum); @@ -550,7 +551,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) { CompilerType target_ast_type = target_type->GetFullCompilerType(); ast_typedef = m_ast.CreateTypedefType( - target_ast_type, name.c_str(), m_ast.CreateDeclContext(decl_ctx)); + target_ast_type, name.c_str(), m_ast.CreateDeclContext(decl_ctx), 0); if (!ast_typedef) return nullptr; @@ -901,7 +902,7 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { return nullptr; decl = m_ast.CreateVariableDeclaration( - decl_context, name.c_str(), + decl_context, OptionalClangModuleID(), name.c_str(), ClangUtil::GetQualType(type->GetLayoutCompilerType())); } @@ -927,8 +928,8 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { : clang::StorageClass::SC_None; auto decl = m_ast.CreateFunctionDeclaration( - decl_context, name.c_str(), type->GetForwardCompilerType(), storage, - func->hasInlineAttribute()); + decl_context, OptionalClangModuleID(), name.c_str(), + type->GetForwardCompilerType(), storage, func->hasInlineAttribute()); std::vector params; if (std::unique_ptr sig = func->getSignature()) { @@ -941,8 +942,8 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { continue; clang::ParmVarDecl *param = m_ast.CreateParameterDeclaration( - decl, nullptr, arg_type->GetForwardCompilerType(), - clang::SC_None, true); + decl, OptionalClangModuleID(), nullptr, + arg_type->GetForwardCompilerType(), clang::SC_None, true); if (param) params.push_back(param); } @@ -1056,8 +1057,8 @@ clang::DeclContext *PDBASTParser::GetDeclContextContainingSymbol( IsAnonymousNamespaceName(namespace_name) ? nullptr : namespace_name.data(); clang::NamespaceDecl *namespace_decl = - m_ast.GetUniqueNamespaceDeclaration(namespace_name_c_str, - curr_context); + m_ast.GetUniqueNamespaceDeclaration( + namespace_name_c_str, curr_context, OptionalClangModuleID()); m_parent_to_namespaces[curr_context].insert(namespace_decl); m_namespaces.insert(namespace_decl); diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp index 50f53e5..33b1ed1 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp @@ -419,8 +419,9 @@ void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexes() { CompilerType uint16 = ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 16); CompilerType dispatch_tsd_indexes_s = ast_ctx->CreateRecordType( - nullptr, lldb::eAccessPublic, "__lldb_dispatch_tsd_indexes_s", - clang::TTK_Struct, lldb::eLanguageTypeC); + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, + "__lldb_dispatch_tsd_indexes_s", clang::TTK_Struct, + lldb::eLanguageTypeC); TypeSystemClang::StartTagDeclarationDefinition(dispatch_tsd_indexes_s); TypeSystemClang::AddFieldToRecordType(dispatch_tsd_indexes_s, diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index ecb1520..8598e41 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -34,6 +34,9 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/Frontend/FrontendOptions.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/ModuleMap.h" #include "clang/Sema/Sema.h" #include "llvm/Support/Signals.h" @@ -316,10 +319,33 @@ static ClangASTMap &GetASTMap() { return *g_map_ptr; } -TypePayloadClang::TypePayloadClang(bool is_complete_objc_class) { +TypePayloadClang::TypePayloadClang(OptionalClangModuleID owning_module, + bool is_complete_objc_class) + : m_payload(owning_module.GetValue()) { SetIsCompleteObjCClass(is_complete_objc_class); } +void TypePayloadClang::SetOwningModule(OptionalClangModuleID id) { + assert(id.GetValue() < ObjCClassBit); + bool is_complete = IsCompleteObjCClass(); + m_payload = id.GetValue(); + SetIsCompleteObjCClass(is_complete); +} + +static void SetMemberOwningModule(clang::Decl *member, + const clang::Decl *parent) { + if (!member || !parent) + return; + + OptionalClangModuleID id(parent->getOwningModuleID()); + if (!id.HasValue()) + return; + + member->setFromASTFile(); + member->setOwningModuleID(id.GetValue()); + member->setModuleOwnershipKind(clang::Decl::ModuleOwnershipKind::Visible); +} + char TypeSystemClang::ID; bool TypeSystemClang::IsOperator(llvm::StringRef name, @@ -505,6 +531,10 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) { // // FIXME: This is affected by other options (-fno-inline). Opts.NoInlineDefine = !Opt; + + // This is needed to allocate the extra space for the owning module + // on each decl. + Opts.ModulesLocalVisibility = 1; } TypeSystemClang::TypeSystemClang(llvm::StringRef name, @@ -1186,12 +1216,60 @@ CompilerType TypeSystemClang::GetTypeForDecl(ObjCInterfaceDecl *decl) { #pragma mark Structure, Unions, Classes -CompilerType TypeSystemClang::CreateRecordType(DeclContext *decl_ctx, - AccessType access_type, - llvm::StringRef name, int kind, - LanguageType language, - ClangASTMetadata *metadata, - bool exports_symbols) { +void TypeSystemClang::SetOwningModule(clang::Decl *decl, + OptionalClangModuleID owning_module) { + if (!decl || !owning_module.HasValue()) + return; + + decl->setFromASTFile(); + decl->setOwningModuleID(owning_module.GetValue()); + decl->setModuleOwnershipKind(clang::Decl::ModuleOwnershipKind::Visible); + if (auto *decl_ctx = llvm::dyn_cast(decl)) { + decl_ctx->setHasExternalVisibleStorage(); + if (auto *ns = llvm::dyn_cast(decl_ctx)) + ns->getPrimaryContext()->setMustBuildLookupTable(); + } +} + +OptionalClangModuleID +TypeSystemClang::GetOrCreateClangModule(llvm::StringRef name, + OptionalClangModuleID parent, + bool is_framework, bool is_explicit) { + // Get the external AST source which holds the modules. + auto *ast_source = llvm::dyn_cast_or_null( + getASTContext().getExternalSource()); + assert(ast_source && "external ast source was lost"); + if (!ast_source) + return {}; + + // Lazily initialize the module map. + if (!m_header_search_up) { + auto HSOpts = std::make_shared(); + m_header_search_up = std::make_unique( + HSOpts, *m_source_manager_up, *m_diagnostics_engine_up, + *m_language_options_up, m_target_info_up.get()); + m_module_map_up = std::make_unique( + *m_source_manager_up, *m_diagnostics_engine_up, *m_language_options_up, + m_target_info_up.get(), *m_header_search_up); + } + + // Get or create the module context. + bool created; + clang::Module *module; + auto parent_desc = ast_source->getSourceDescriptor(parent.GetValue()); + std::tie(module, created) = m_module_map_up->findOrCreateModule( + name, parent_desc ? parent_desc->getModuleOrNull() : nullptr, + is_framework, is_explicit); + if (!created) + return ast_source->GetIDForModule(module); + + return ast_source->RegisterModule(module); +} + +CompilerType TypeSystemClang::CreateRecordType( + clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, + AccessType access_type, llvm::StringRef name, int kind, + LanguageType language, ClangASTMetadata *metadata, bool exports_symbols) { ASTContext &ast = getASTContext(); if (decl_ctx == nullptr) @@ -1201,7 +1279,8 @@ CompilerType TypeSystemClang::CreateRecordType(DeclContext *decl_ctx, language == eLanguageTypeObjC_plus_plus) { bool isForwardDecl = true; bool isInternal = false; - return CreateObjCClass(name, decl_ctx, isForwardDecl, isInternal, metadata); + return CreateObjCClass(name, decl_ctx, owning_module, isForwardDecl, + isInternal, metadata); } // NOTE: Eventually CXXRecordDecl will be merged back into RecordDecl and @@ -1216,6 +1295,7 @@ CompilerType TypeSystemClang::CreateRecordType(DeclContext *decl_ctx, decl->setDeclContext(decl_ctx); if (has_name) decl->setDeclName(&ast.Idents.get(name)); + SetOwningModule(decl, owning_module); if (!has_name) { // In C++ a lambda is also represented as an unnamed class. This is @@ -1327,13 +1407,13 @@ static TemplateParameterList *CreateTemplateParameterList( } clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl( - clang::DeclContext *decl_ctx, clang::FunctionDecl *func_decl, - const char *name, const TemplateParameterInfos &template_param_infos) { + clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, + clang::FunctionDecl *func_decl, const char *name, + const TemplateParameterInfos &template_param_infos) { // /// Create a function template node. ASTContext &ast = getASTContext(); llvm::SmallVector template_param_decls; - TemplateParameterList *template_param_list = CreateTemplateParameterList( ast, template_param_infos, template_param_decls); FunctionTemplateDecl *func_tmpl_decl = @@ -1342,6 +1422,7 @@ clang::FunctionTemplateDecl *TypeSystemClang::CreateFunctionTemplateDecl( func_tmpl_decl->setLocation(func_decl->getLocation()); func_tmpl_decl->setDeclName(func_decl->getDeclName()); func_tmpl_decl->init(func_decl, template_param_list); + SetOwningModule(func_tmpl_decl, owning_module); for (size_t i = 0, template_param_decl_count = template_param_decls.size(); i < template_param_decl_count; ++i) { @@ -1368,8 +1449,9 @@ void TypeSystemClang::CreateFunctionTemplateSpecializationInfo( } ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl( - DeclContext *decl_ctx, lldb::AccessType access_type, const char *class_name, - int kind, const TemplateParameterInfos &template_param_infos) { + DeclContext *decl_ctx, OptionalClangModuleID owning_module, + lldb::AccessType access_type, const char *class_name, int kind, + const TemplateParameterInfos &template_param_infos) { ASTContext &ast = getASTContext(); ClassTemplateDecl *class_template_decl = nullptr; @@ -1397,6 +1479,7 @@ ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl( // What decl context do we use here? TU? The actual decl context? template_cxx_decl->setDeclContext(decl_ctx); template_cxx_decl->setDeclName(decl_name); + SetOwningModule(template_cxx_decl, owning_module); for (size_t i = 0, template_param_decl_count = template_param_decls.size(); i < template_param_decl_count; ++i) { @@ -1414,6 +1497,7 @@ ClassTemplateDecl *TypeSystemClang::CreateClassTemplateDecl( class_template_decl->setDeclName(decl_name); class_template_decl->init(template_cxx_decl, template_param_list); template_cxx_decl->setDescribedClassTemplate(class_template_decl); + SetOwningModule(class_template_decl, owning_module); if (class_template_decl) { if (access_type != eAccessNone) @@ -1453,7 +1537,8 @@ TypeSystemClang::CreateTemplateTemplateParmDecl(const char *template_name) { ClassTemplateSpecializationDecl * TypeSystemClang::CreateClassTemplateSpecializationDecl( - DeclContext *decl_ctx, ClassTemplateDecl *class_template_decl, int kind, + DeclContext *decl_ctx, OptionalClangModuleID owning_module, + ClassTemplateDecl *class_template_decl, int kind, const TemplateParameterInfos &template_param_infos) { ASTContext &ast = getASTContext(); llvm::SmallVector args( @@ -1476,6 +1561,16 @@ TypeSystemClang::CreateClassTemplateSpecializationDecl( ast.getTypeDeclType(class_template_specialization_decl, nullptr); class_template_specialization_decl->setDeclName( class_template_decl->getDeclName()); + // FIXME: Turning this on breaks the libcxx data formatter tests. + // SetOwningModule marks the Decl as external, which prevents a + // LookupPtr from being built. Template instantiations can also not + // be found by ExternalASTSource::FindExternalVisibleDeclsByName(), + // nor can we lazily build a LookupPtr later, because template + // specializations are supposed to be hidden so + // makeDeclVisibleInContextWithFlags() is a noop, as well. + // + // SetOwningModule(class_template_specialization_decl, owning_module); + decl_ctx->addDecl(class_template_specialization_decl); class_template_specialization_decl->setSpecializationKind( TSK_ExplicitSpecialization); @@ -1594,14 +1689,13 @@ bool TypeSystemClang::RecordHasFields(const RecordDecl *record_decl) { #pragma mark Objective-C Classes -CompilerType TypeSystemClang::CreateObjCClass(llvm::StringRef name, - DeclContext *decl_ctx, - bool isForwardDecl, - bool isInternal, - ClangASTMetadata *metadata) { +CompilerType TypeSystemClang::CreateObjCClass( + llvm::StringRef name, clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, bool isForwardDecl, bool isInternal, + ClangASTMetadata *metadata) { ASTContext &ast = getASTContext(); assert(!name.empty()); - if (decl_ctx == nullptr) + if (!decl_ctx) decl_ctx = ast.getTranslationUnitDecl(); ObjCInterfaceDecl *decl = ObjCInterfaceDecl::CreateDeserialized(ast, 0); @@ -1609,6 +1703,7 @@ CompilerType TypeSystemClang::CreateObjCClass(llvm::StringRef name, decl->setDeclName(&ast.Idents.get(name)); /*isForwardDecl,*/ decl->setImplicit(isInternal); + SetOwningModule(decl, owning_module); if (decl && metadata) SetMetadata(decl, *metadata); @@ -1646,11 +1741,12 @@ TypeSystemClang::GetNumBaseClasses(const CXXRecordDecl *cxx_record_decl, #pragma mark Namespace Declarations NamespaceDecl *TypeSystemClang::GetUniqueNamespaceDeclaration( - const char *name, clang::DeclContext *decl_ctx, bool is_inline) { + const char *name, clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, bool is_inline) { NamespaceDecl *namespace_decl = nullptr; ASTContext &ast = getASTContext(); TranslationUnitDecl *translation_unit_decl = ast.getTranslationUnitDecl(); - if (decl_ctx == nullptr) + if (!decl_ctx) decl_ctx = translation_unit_decl; if (name) { @@ -1699,17 +1795,23 @@ NamespaceDecl *TypeSystemClang::GetUniqueNamespaceDeclaration( } } } + // Note: namespaces can span multiple modules, so perhaps this isn't a good + // idea. + SetOwningModule(namespace_decl, owning_module); + VerifyDecl(namespace_decl); return namespace_decl; } clang::BlockDecl * -TypeSystemClang::CreateBlockDeclaration(clang::DeclContext *ctx) { +TypeSystemClang::CreateBlockDeclaration(clang::DeclContext *ctx, + OptionalClangModuleID owning_module) { if (ctx) { clang::BlockDecl *decl = clang::BlockDecl::CreateDeserialized(getASTContext(), 0); decl->setDeclContext(ctx); ctx->addDecl(decl); + SetOwningModule(decl, owning_module); return decl; } return nullptr; @@ -1733,7 +1835,8 @@ clang::DeclContext *FindLCABetweenDecls(clang::DeclContext *left, } clang::UsingDirectiveDecl *TypeSystemClang::CreateUsingDirectiveDeclaration( - clang::DeclContext *decl_ctx, clang::NamespaceDecl *ns_decl) { + clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, + clang::NamespaceDecl *ns_decl) { if (decl_ctx && ns_decl) { auto *translation_unit = getASTContext().getTranslationUnitDecl(); clang::UsingDirectiveDecl *using_decl = clang::UsingDirectiveDecl::Create( @@ -1743,6 +1846,7 @@ clang::UsingDirectiveDecl *TypeSystemClang::CreateUsingDirectiveDeclaration( FindLCABetweenDecls(decl_ctx, ns_decl, translation_unit)); decl_ctx->addDecl(using_decl); + SetOwningModule(using_decl, owning_module); return using_decl; } return nullptr; @@ -1750,14 +1854,17 @@ clang::UsingDirectiveDecl *TypeSystemClang::CreateUsingDirectiveDeclaration( clang::UsingDecl * TypeSystemClang::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx, + OptionalClangModuleID owning_module, clang::NamedDecl *target) { - if (current_decl_ctx != nullptr && target != nullptr) { + if (current_decl_ctx && target) { clang::UsingDecl *using_decl = clang::UsingDecl::Create( getASTContext(), current_decl_ctx, clang::SourceLocation(), clang::NestedNameSpecifierLoc(), clang::DeclarationNameInfo(), false); + SetOwningModule(using_decl, owning_module); clang::UsingShadowDecl *shadow_decl = clang::UsingShadowDecl::Create( getASTContext(), current_decl_ctx, clang::SourceLocation(), using_decl, target); + SetOwningModule(shadow_decl, owning_module); using_decl->addShadowDecl(shadow_decl); current_decl_ctx->addDecl(using_decl); return using_decl; @@ -1766,7 +1873,8 @@ TypeSystemClang::CreateUsingDeclaration(clang::DeclContext *current_decl_ctx, } clang::VarDecl *TypeSystemClang::CreateVariableDeclaration( - clang::DeclContext *decl_context, const char *name, clang::QualType type) { + clang::DeclContext *decl_context, OptionalClangModuleID owning_module, + const char *name, clang::QualType type) { if (decl_context) { clang::VarDecl *var_decl = clang::VarDecl::CreateDeserialized(getASTContext(), 0); @@ -1774,6 +1882,7 @@ clang::VarDecl *TypeSystemClang::CreateVariableDeclaration( if (name && name[0]) var_decl->setDeclName(&getASTContext().Idents.getOwn(name)); var_decl->setType(type); + SetOwningModule(var_decl, owning_module); var_decl->setAccess(clang::AS_public); decl_context->addDecl(var_decl); return var_decl; @@ -1885,11 +1994,12 @@ TypeSystemClang::GetDeclarationName(const char *name, } FunctionDecl *TypeSystemClang::CreateFunctionDeclaration( - DeclContext *decl_ctx, const char *name, - const CompilerType &function_clang_type, int storage, bool is_inline) { + clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, + const char *name, const CompilerType &function_clang_type, int storage, + bool is_inline) { FunctionDecl *func_decl = nullptr; ASTContext &ast = getASTContext(); - if (decl_ctx == nullptr) + if (!decl_ctx) decl_ctx = ast.getTranslationUnitDecl(); const bool hasWrittenPrototype = true; @@ -1906,6 +2016,7 @@ FunctionDecl *TypeSystemClang::CreateFunctionDeclaration( func_decl->setHasWrittenPrototype(hasWrittenPrototype); func_decl->setConstexprKind(isConstexprSpecified ? CSK_constexpr : CSK_unspecified); + SetOwningModule(func_decl, owning_module); if (func_decl) decl_ctx->addDecl(func_decl); @@ -1954,8 +2065,9 @@ TypeSystemClang::CreateFunctionType(const CompilerType &result_type, } ParmVarDecl *TypeSystemClang::CreateParameterDeclaration( - clang::DeclContext *decl_ctx, const char *name, - const CompilerType ¶m_type, int storage, bool add_decl) { + clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, + const char *name, const CompilerType ¶m_type, int storage, + bool add_decl) { ASTContext &ast = getASTContext(); auto *decl = ParmVarDecl::CreateDeserialized(ast, 0); decl->setDeclContext(decl_ctx); @@ -1963,6 +2075,7 @@ ParmVarDecl *TypeSystemClang::CreateParameterDeclaration( decl->setDeclName(&ast.Idents.get(name)); decl->setType(ClangUtil::GetQualType(param_type)); decl->setStorageClass(static_cast(storage)); + SetOwningModule(decl, owning_module); if (add_decl) decl_ctx->addDecl(decl); @@ -2024,8 +2137,9 @@ CompilerType TypeSystemClang::CreateStructForIdentifier( return type; } - type = CreateRecordType(nullptr, lldb::eAccessPublic, type_name.GetCString(), - clang::TTK_Struct, lldb::eLanguageTypeC); + type = CreateRecordType(nullptr, OptionalClangModuleID(), lldb::eAccessPublic, + type_name.GetCString(), clang::TTK_Struct, + lldb::eLanguageTypeC); StartTagDeclarationDefinition(type); for (const auto &field : type_fields) AddFieldToRecordType(type, field.first, field.second, lldb::eAccessPublic, @@ -2050,11 +2164,10 @@ CompilerType TypeSystemClang::GetOrCreateStructForIdentifier( #pragma mark Enumeration Types -CompilerType -TypeSystemClang::CreateEnumerationType(const char *name, DeclContext *decl_ctx, - const Declaration &decl, - const CompilerType &integer_clang_type, - bool is_scoped) { +CompilerType TypeSystemClang::CreateEnumerationType( + const char *name, clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, const Declaration &decl, + const CompilerType &integer_clang_type, bool is_scoped) { // TODO: Do something intelligent with the Declaration object passed in // like maybe filling in the SourceLocation with it... ASTContext &ast = getASTContext(); @@ -2068,6 +2181,7 @@ TypeSystemClang::CreateEnumerationType(const char *name, DeclContext *decl_ctx, enum_decl->setScoped(is_scoped); enum_decl->setScopedUsingClassTag(is_scoped); enum_decl->setFixed(false); + SetOwningModule(enum_decl, owning_module); if (enum_decl) { if (decl_ctx) decl_ctx->addDecl(enum_decl); @@ -4254,7 +4368,7 @@ TypeSystemClang::GetNonReferenceType(lldb::opaque_compiler_type_t type) { CompilerType TypeSystemClang::CreateTypedefType( const CompilerType &type, const char *typedef_name, - const CompilerDeclContext &compiler_decl_ctx) { + const CompilerDeclContext &compiler_decl_ctx, uint32_t payload) { if (type && typedef_name && typedef_name[0]) { TypeSystemClang *ast = llvm::dyn_cast(type.GetTypeSystem()); @@ -4265,7 +4379,7 @@ CompilerType TypeSystemClang::CreateTypedefType( clang::DeclContext *decl_ctx = TypeSystemClang::DeclContextGetAsDeclContext(compiler_decl_ctx); - if (decl_ctx == nullptr) + if (!decl_ctx) decl_ctx = ast->getASTContext().getTranslationUnitDecl(); clang::TypedefDecl *decl = @@ -4274,6 +4388,7 @@ CompilerType TypeSystemClang::CreateTypedefType( decl->setDeclName(&clang_ast.Idents.get(typedef_name)); decl->setTypeSourceInfo(clang_ast.getTrivialTypeSourceInfo(qual_type)); + SetOwningModule(decl, TypePayloadClang(payload).GetOwningModule()); decl->setAccess(clang::AS_public); // TODO respect proper access specifier decl_ctx->addDecl(decl); @@ -4362,24 +4477,23 @@ TypeSystemClang::AddRestrictModifier(lldb::opaque_compiler_type_t type) { return CompilerType(); } -CompilerType -TypeSystemClang::CreateTypedef(lldb::opaque_compiler_type_t type, - const char *typedef_name, - const CompilerDeclContext &compiler_decl_ctx) { +CompilerType TypeSystemClang::CreateTypedef( + lldb::opaque_compiler_type_t type, const char *typedef_name, + const CompilerDeclContext &compiler_decl_ctx, uint32_t payload) { if (type) { clang::ASTContext &clang_ast = getASTContext(); clang::QualType qual_type(GetQualType(type)); clang::DeclContext *decl_ctx = TypeSystemClang::DeclContextGetAsDeclContext(compiler_decl_ctx); - if (decl_ctx == nullptr) + if (!decl_ctx) decl_ctx = getASTContext().getTranslationUnitDecl(); - clang::TypedefDecl *decl = - clang::TypedefDecl::CreateDeserialized(clang_ast, 0); - decl->setDeclContext(decl_ctx); - decl->setDeclName(&clang_ast.Idents.get(typedef_name)); - decl->setTypeSourceInfo(clang_ast.getTrivialTypeSourceInfo(qual_type)); + clang::TypedefDecl *decl = clang::TypedefDecl::Create( + clang_ast, decl_ctx, clang::SourceLocation(), clang::SourceLocation(), + &clang_ast.Idents.get(typedef_name), + clang_ast.getTrivialTypeSourceInfo(qual_type)); + SetOwningModule(decl, TypePayloadClang(payload).GetOwningModule()); clang::TagDecl *tdecl = nullptr; if (!qual_type.isNull()) { @@ -6923,6 +7037,7 @@ clang::FieldDecl *TypeSystemClang::AddFieldToRecordType( field->setType(ClangUtil::GetQualType(field_clang_type)); if (bit_width) field->setBitWidth(bit_width); + SetMemberOwningModule(field, record_decl); if (name.empty()) { // Determine whether this field corresponds to an anonymous struct or @@ -6964,6 +7079,7 @@ clang::FieldDecl *TypeSystemClang::AddFieldToRecordType( ivar->setBitWidth(bit_width); ivar->setSynthesize(is_synthesized); field = ivar; + SetMemberOwningModule(field, class_interface_decl); if (field) { class_interface_decl->addDecl(field); @@ -7025,6 +7141,7 @@ void TypeSystemClang::BuildIndirectFields(const CompilerType &type) { ast->getASTContext(), record_decl, clang::SourceLocation(), nested_field_decl->getIdentifier(), nested_field_decl->getType(), {chain, 2}); + SetMemberOwningModule(indirect_field, record_decl); indirect_field->setImplicit(); @@ -7055,6 +7172,7 @@ void TypeSystemClang::BuildIndirectFields(const CompilerType &type) { nested_indirect_field_decl->getIdentifier(), nested_indirect_field_decl->getType(), {chain, nested_chain_size + 1}); + SetMemberOwningModule(indirect_field, record_decl); indirect_field->setImplicit(); @@ -7121,6 +7239,7 @@ clang::VarDecl *TypeSystemClang::AddVariableToRecordType( var_decl->setDeclName(ident); var_decl->setType(ClangUtil::GetQualType(var_type)); var_decl->setStorageClass(clang::SC_Static); + SetMemberOwningModule(var_decl, record_decl); if (!var_decl) return nullptr; @@ -7256,6 +7375,7 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType( cxx_method_decl->setConstexprKind(CSK_unspecified); } } + SetMemberOwningModule(cxx_method_decl, cxx_record_decl); clang::AccessSpecifier access_specifier = TypeSystemClang::ConvertAccessTypeToAccessSpecifier(access); @@ -7430,6 +7550,7 @@ bool TypeSystemClang::AddObjCClassProperty( ? ivar_decl->getType() : ClangUtil::GetQualType(property_clang_type), prop_type_source); + SetMemberOwningModule(property_decl, class_interface_decl); if (!property_decl) return false; @@ -7521,6 +7642,7 @@ bool TypeSystemClang::AddObjCClassProperty( getter->setDefined(isDefined); getter->setDeclImplementation(impControl); getter->setRelatedResultType(HasRelatedResultType); + SetMemberOwningModule(getter, class_interface_decl); if (getter) { if (metadata) @@ -7562,6 +7684,7 @@ bool TypeSystemClang::AddObjCClassProperty( setter->setDefined(isDefined); setter->setDeclImplementation(impControl); setter->setRelatedResultType(HasRelatedResultType); + SetMemberOwningModule(setter, class_interface_decl); if (setter) { if (metadata) @@ -7690,6 +7813,7 @@ clang::ObjCMethodDecl *TypeSystemClang::AddMethodToObjCObjectType( objc_method_decl->setDefined(isDefined); objc_method_decl->setDeclImplementation(impControl); objc_method_decl->setRelatedResultType(HasRelatedResultType); + SetMemberOwningModule(objc_method_decl, class_interface_decl); if (objc_method_decl == nullptr) return nullptr; @@ -7920,6 +8044,7 @@ clang::EnumConstantDecl *TypeSystemClang::AddEnumerationValueToEnumerationType( enumerator_decl->setDeclName(&getASTContext().Idents.get(name)); enumerator_decl->setType(clang::QualType(enutype, 0)); enumerator_decl->setInitVal(value); + SetMemberOwningModule(enumerator_decl, enutype->getDecl()); if (!enumerator_decl) return nullptr; @@ -8814,14 +8939,14 @@ void TypeSystemClang::DumpTypeName(const CompilerType &type) { } clang::ClassTemplateDecl *TypeSystemClang::ParseClassTemplateDecl( - clang::DeclContext *decl_ctx, lldb::AccessType access_type, - const char *parent_name, int tag_decl_kind, + clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, + lldb::AccessType access_type, const char *parent_name, int tag_decl_kind, const TypeSystemClang::TemplateParameterInfos &template_param_infos) { if (template_param_infos.IsValid()) { std::string template_basename(parent_name); template_basename.erase(template_basename.find('<')); - return CreateClassTemplateDecl(decl_ctx, access_type, + return CreateClassTemplateDecl(decl_ctx, owning_module, access_type, template_basename.c_str(), tag_decl_kind, template_param_infos); } diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index f355681..b326ee5 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -53,13 +53,30 @@ class ClangASTMetadata; class ClangASTSource; class Declaration; +/// A Clang module ID. +class OptionalClangModuleID { + unsigned m_id = 0; + +public: + OptionalClangModuleID() = default; + explicit OptionalClangModuleID(unsigned id) : m_id(id) {} + bool HasValue() const { return m_id != 0; } + unsigned GetValue() const { return m_id; } +}; + /// The implementation of lldb::Type's m_payload field for TypeSystemClang. class TypePayloadClang { - /// Layout: bit 31 ... IsCompleteObjCClass. + /// The Layout is as follows: + /// \verbatim + /// bit 0..30 ... Owning Module ID. + /// bit 31 ...... IsCompleteObjCClass. + /// \endverbatim Type::Payload m_payload = 0; + public: TypePayloadClang() = default; - explicit TypePayloadClang(bool is_complete_objc_class); + explicit TypePayloadClang(OptionalClangModuleID owning_module, + bool is_complete_objc_class = false); explicit TypePayloadClang(uint32_t opaque_payload) : m_payload(opaque_payload) {} operator Type::Payload() { return m_payload; } @@ -69,6 +86,11 @@ public: m_payload = is_complete_objc_class ? Flags(m_payload).Set(ObjCClassBit) : Flags(m_payload).Clear(ObjCClassBit); } + OptionalClangModuleID GetOwningModule() { + return OptionalClangModuleID(Flags(m_payload).Clear(ObjCClassBit)); + } + void SetOwningModule(OptionalClangModuleID id); + /// \} }; /// A TypeSystem implementation based on Clang. @@ -293,7 +315,14 @@ public: static uint32_t GetNumBaseClasses(const clang::CXXRecordDecl *cxx_record_decl, bool omit_empty_base_classes); + /// Synthesize a clang::Module and return its ID or a default-constructed ID. + OptionalClangModuleID GetOrCreateClangModule(llvm::StringRef name, + OptionalClangModuleID parent, + bool is_framework = false, + bool is_explicit = false); + CompilerType CreateRecordType(clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, lldb::AccessType access_type, llvm::StringRef name, int kind, lldb::LanguageType language, @@ -319,6 +348,7 @@ public: clang::FunctionTemplateDecl * CreateFunctionTemplateDecl(clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, clang::FunctionDecl *func_decl, const char *name, const TemplateParameterInfos &infos); @@ -328,6 +358,7 @@ public: clang::ClassTemplateDecl * CreateClassTemplateDecl(clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, lldb::AccessType access_type, const char *class_name, int kind, const TemplateParameterInfos &infos); @@ -335,7 +366,7 @@ public: CreateTemplateTemplateParmDecl(const char *template_name); clang::ClassTemplateSpecializationDecl *CreateClassTemplateSpecializationDecl( - clang::DeclContext *decl_ctx, + clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, clang::ClassTemplateDecl *class_template_decl, int kind, const TemplateParameterInfos &infos); @@ -355,8 +386,9 @@ public: static bool RecordHasFields(const clang::RecordDecl *record_decl); CompilerType CreateObjCClass(llvm::StringRef name, - clang::DeclContext *decl_ctx, bool isForwardDecl, - bool isInternal, + clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, + bool isForwardDecl, bool isInternal, ClangASTMetadata *metadata = nullptr); bool SetTagTypeKind(clang::QualType type, int kind) const; @@ -373,14 +405,16 @@ public: clang::NamespaceDecl * GetUniqueNamespaceDeclaration(const char *name, clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, bool is_inline = false); // Function Types clang::FunctionDecl * - CreateFunctionDeclaration(clang::DeclContext *decl_ctx, const char *name, - const CompilerType &function_Type, int storage, - bool is_inline); + CreateFunctionDeclaration(clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, + const char *name, const CompilerType &function_Type, + int storage, bool is_inline); CompilerType CreateFunctionType(const CompilerType &result_type, const CompilerType *args, unsigned num_args, @@ -394,11 +428,11 @@ public: type_quals, clang::CC_C); } - clang::ParmVarDecl *CreateParameterDeclaration(clang::DeclContext *decl_ctx, - const char *name, - const CompilerType ¶m_type, - int storage, - bool add_decl=false); + clang::ParmVarDecl * + CreateParameterDeclaration(clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, + const char *name, const CompilerType ¶m_type, + int storage, bool add_decl = false); void SetFunctionParameters(clang::FunctionDecl *function_decl, clang::ParmVarDecl **params, unsigned num_params); @@ -413,6 +447,7 @@ public: // Enumeration Types CompilerType CreateEnumerationType(const char *name, clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, const Declaration &decl, const CompilerType &integer_qual_type, bool is_scoped); @@ -479,6 +514,10 @@ public: /// TypeSystemClang. CompilerDeclContext CreateDeclContext(clang::DeclContext *ctx); + /// Set the owning module for \p decl. + static void SetOwningModule(clang::Decl *decl, + OptionalClangModuleID owning_module); + std::vector DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, const bool ignore_using_decls) override; @@ -641,11 +680,13 @@ public: // Creating related types - // Using the current type, create a new typedef to that type using - // "typedef_name" as the name and "decl_ctx" as the decl context. + /// Using the current type, create a new typedef to that type using + /// "typedef_name" as the name and "decl_ctx" as the decl context. + /// \param payload is an opaque TypePayloadClang. static CompilerType CreateTypedefType(const CompilerType &type, const char *typedef_name, - const CompilerDeclContext &compiler_decl_ctx); + const CompilerDeclContext &compiler_decl_ctx, + uint32_t opaque_payload); CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type, uint64_t *stride) override; @@ -696,7 +737,8 @@ public: CompilerType CreateTypedef(lldb::opaque_compiler_type_t type, const char *name, - const CompilerDeclContext &decl_ctx) override; + const CompilerDeclContext &decl_ctx, + uint32_t opaque_payload) override; // If the current object represents a typedef type, get the underlying type CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) override; @@ -955,20 +997,24 @@ public: GetAsObjCInterfaceDecl(const CompilerType &type); clang::ClassTemplateDecl *ParseClassTemplateDecl( - clang::DeclContext *decl_ctx, lldb::AccessType access_type, - const char *parent_name, int tag_decl_kind, + clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, + lldb::AccessType access_type, const char *parent_name, int tag_decl_kind, const TypeSystemClang::TemplateParameterInfos &template_param_infos); - clang::BlockDecl *CreateBlockDeclaration(clang::DeclContext *ctx); + clang::BlockDecl *CreateBlockDeclaration(clang::DeclContext *ctx, + OptionalClangModuleID owning_module); clang::UsingDirectiveDecl * CreateUsingDirectiveDeclaration(clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, clang::NamespaceDecl *ns_decl); clang::UsingDecl *CreateUsingDeclaration(clang::DeclContext *current_decl_ctx, + OptionalClangModuleID owning_module, clang::NamedDecl *target); clang::VarDecl *CreateVariableDeclaration(clang::DeclContext *decl_context, + OptionalClangModuleID owning_module, const char *name, clang::QualType type); @@ -991,6 +1037,13 @@ public: clang::DeclarationName GetDeclarationName(const char *name, const CompilerType &function_clang_type); + clang::LangOptions *GetLangOpts() const { + return m_language_options_up.get(); + } + clang::SourceManager *GetSourceMgr() const { + return m_source_manager_up.get(); + } + private: const clang::ClassTemplateSpecializationDecl * GetAsTemplateSpecialization(lldb::opaque_compiler_type_t type); @@ -1008,6 +1061,8 @@ private: std::unique_ptr m_identifier_table_up; std::unique_ptr m_selector_table_up; std::unique_ptr m_builtins_up; + std::unique_ptr m_header_search_up; + std::unique_ptr m_module_map_up; std::unique_ptr m_dwarf_ast_parser_up; std::unique_ptr m_pdb_ast_parser_up; std::unique_ptr m_mangle_ctx_up; diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index 6c15098..f24d993 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -439,11 +439,11 @@ CompilerType CompilerType::AddRestrictModifier() const { return CompilerType(); } -CompilerType -CompilerType::CreateTypedef(const char *name, - const CompilerDeclContext &decl_ctx) const { +CompilerType CompilerType::CreateTypedef(const char *name, + const CompilerDeclContext &decl_ctx, + uint32_t payload) const { if (IsValid()) - return m_type_system->CreateTypedef(m_type, name, decl_ctx); + return m_type_system->CreateTypedef(m_type, name, decl_ctx, payload); else return CompilerType(); } diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 804f7e0..058d4c7 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -505,7 +505,7 @@ bool Type::ResolveCompilerType(ResolveState compiler_type_resolve_state) { case eEncodingIsTypedefUID: m_compiler_type = encoding_type->GetForwardCompilerType().CreateTypedef( m_name.AsCString("__lldb_invalid_typedef_name"), - GetSymbolFile()->GetDeclContextContainingUID(GetID())); + GetSymbolFile()->GetDeclContextContainingUID(GetID()), m_payload); m_name.Clear(); break; @@ -563,7 +563,7 @@ bool Type::ResolveCompilerType(ResolveState compiler_type_resolve_state) { case eEncodingIsTypedefUID: m_compiler_type = void_compiler_type.CreateTypedef( m_name.AsCString("__lldb_invalid_typedef_name"), - GetSymbolFile()->GetDeclContextContainingUID(GetID())); + GetSymbolFile()->GetDeclContextContainingUID(GetID()), m_payload); break; case eEncodingIsPointerUID: diff --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp index fd5b961..5e57813 100644 --- a/lldb/source/Symbol/TypeSystem.cpp +++ b/lldb/source/Symbol/TypeSystem.cpp @@ -113,7 +113,8 @@ TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) { CompilerType TypeSystem::CreateTypedef(lldb::opaque_compiler_type_t type, const char *name, - const CompilerDeclContext &decl_ctx) { + const CompilerDeclContext &decl_ctx, + uint32_t opaque_payload) { return CompilerType(); } diff --git a/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h b/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h new file mode 100644 index 0000000..4b223ca --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/A.h @@ -0,0 +1,29 @@ +#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; +} diff --git a/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/B.h b/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/B.h new file mode 100644 index 0000000..23d8347 --- /dev/null +++ b/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; +} // namespace Namespace diff --git a/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/module.modulemap b/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/module.modulemap new file mode 100644 index 0000000..b9940a8 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/Inputs/ModuleOwnership/module.modulemap @@ -0,0 +1,6 @@ +module A { + header "A.h" + module B { + header "B.h" + } +} diff --git a/lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg b/lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg index 8c4600c..84376e6 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/lit.local.cfg +++ b/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'] diff --git a/lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm b/lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm new file mode 100644 index 0000000..6a876d1 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm @@ -0,0 +1,42 @@ +// 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 +// FIXME: -EnumConstantDecl {{.*}} imported in A a + +SomeClass *obj1; +// CHECK-DAG: ObjCInterfaceDecl {{.*}} imported in A {{.*}} SomeClass + +// Template specializations are not yet supported, so they lack the ownership info: +Template t2; +// CHECK-DAG: ClassTemplateSpecializationDecl {{.*}} struct Template + +Namespace::InNamespace t3; +// CHECK-DAG: ClassTemplateSpecializationDecl {{.*}} struct InNamespace + +Namespace::AlsoInNamespace t4; +// CHECK-DAG: ClassTemplateSpecializationDecl {{.*}} struct AlsoInNamespace diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/lldb/unittests/Symbol/TestTypeSystemClang.cpp index a3345e81..c67168b 100644 --- a/lldb/unittests/Symbol/TestTypeSystemClang.cpp +++ b/lldb/unittests/Symbol/TestTypeSystemClang.cpp @@ -14,6 +14,7 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/Declaration.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" #include "gtest/gtest.h" @@ -257,9 +258,10 @@ TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeBasicTypes) { CompilerType basic_compiler_type = ast.GetBasicType(basic_type); EXPECT_TRUE(basic_compiler_type.IsValid()); - CompilerType enum_type = - ast.CreateEnumerationType("my_enum", ast.GetTranslationUnitDecl(), - Declaration(), basic_compiler_type, scoped); + CompilerType enum_type = ast.CreateEnumerationType( + "my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(), + Declaration(), basic_compiler_type, scoped); + CompilerType t = ast.GetEnumerationIntegerType(enum_type); // Check that the type we put in at the start is found again. EXPECT_EQ(basic_compiler_type.GetTypeName(), t.GetTypeName()); @@ -267,14 +269,39 @@ TEST_F(TestTypeSystemClang, TestGetEnumIntegerTypeBasicTypes) { } } +TEST_F(TestTypeSystemClang, TestOwningModule) { + TypeSystemClang ast("module_ast", HostInfo::GetTargetTriple()); + CompilerType basic_compiler_type = ast.GetBasicType(BasicType::eBasicTypeInt); + CompilerType enum_type = ast.CreateEnumerationType( + "my_enum", ast.GetTranslationUnitDecl(), OptionalClangModuleID(100), + Declaration(), basic_compiler_type, false); + auto *ed = TypeSystemClang::GetAsEnumDecl(enum_type); + EXPECT_FALSE(!ed); + EXPECT_EQ(ed->getOwningModuleID(), 100u); + + CompilerType record_type = ast.CreateRecordType( + nullptr, OptionalClangModuleID(200), lldb::eAccessPublic, "FooRecord", + clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr); + auto *rd = TypeSystemClang::GetAsRecordDecl(record_type); + EXPECT_FALSE(!rd); + EXPECT_EQ(rd->getOwningModuleID(), 200u); + + CompilerType class_type = + ast.CreateObjCClass("objc_class", ast.GetTranslationUnitDecl(), + OptionalClangModuleID(300), false, false); + auto *cd = TypeSystemClang::GetAsObjCInterfaceDecl(class_type); + EXPECT_FALSE(!cd); + EXPECT_EQ(cd->getOwningModuleID(), 300u); +} + TEST_F(TestTypeSystemClang, TestIsClangType) { clang::ASTContext &context = m_ast->getASTContext(); lldb::opaque_compiler_type_t bool_ctype = TypeSystemClang::GetOpaqueCompilerType(&context, lldb::eBasicTypeBool); CompilerType bool_type(m_ast.get(), bool_ctype); CompilerType record_type = m_ast->CreateRecordType( - nullptr, lldb::eAccessPublic, "FooRecord", clang::TTK_Struct, - lldb::eLanguageTypeC_plus_plus, nullptr); + nullptr, OptionalClangModuleID(100), lldb::eAccessPublic, "FooRecord", + clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr); // Clang builtin type and record type should pass EXPECT_TRUE(ClangUtil::IsClangType(bool_type)); EXPECT_TRUE(ClangUtil::IsClangType(record_type)); @@ -285,8 +312,8 @@ TEST_F(TestTypeSystemClang, TestIsClangType) { TEST_F(TestTypeSystemClang, TestRemoveFastQualifiers) { CompilerType record_type = m_ast->CreateRecordType( - nullptr, lldb::eAccessPublic, "FooRecord", clang::TTK_Struct, - lldb::eLanguageTypeC_plus_plus, nullptr); + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "FooRecord", + clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr); QualType qt; qt = ClangUtil::GetQualType(record_type); @@ -357,8 +384,8 @@ TEST_F(TestTypeSystemClang, TestRecordHasFields) { // Test that a record with no fields returns false CompilerType empty_base = m_ast->CreateRecordType( - nullptr, lldb::eAccessPublic, "EmptyBase", clang::TTK_Struct, - lldb::eLanguageTypeC_plus_plus, nullptr); + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyBase", + clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr); TypeSystemClang::StartTagDeclarationDefinition(empty_base); TypeSystemClang::CompleteTagDeclarationDefinition(empty_base); @@ -368,8 +395,8 @@ TEST_F(TestTypeSystemClang, TestRecordHasFields) { // Test that a record with direct fields returns true CompilerType non_empty_base = m_ast->CreateRecordType( - nullptr, lldb::eAccessPublic, "NonEmptyBase", clang::TTK_Struct, - lldb::eLanguageTypeC_plus_plus, nullptr); + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "NonEmptyBase", + clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr); TypeSystemClang::StartTagDeclarationDefinition(non_empty_base); FieldDecl *non_empty_base_field_decl = m_ast->AddFieldToRecordType( non_empty_base, "MyField", int_type, eAccessPublic, 0); @@ -384,8 +411,8 @@ TEST_F(TestTypeSystemClang, TestRecordHasFields) { // Test that a record with no direct fields, but fields in a base returns true CompilerType empty_derived = m_ast->CreateRecordType( - nullptr, lldb::eAccessPublic, "EmptyDerived", clang::TTK_Struct, - lldb::eLanguageTypeC_plus_plus, nullptr); + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyDerived", + clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr); TypeSystemClang::StartTagDeclarationDefinition(empty_derived); std::unique_ptr non_empty_base_spec = m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(), @@ -407,8 +434,8 @@ TEST_F(TestTypeSystemClang, TestRecordHasFields) { // Test that a record with no direct fields, but fields in a virtual base // returns true CompilerType empty_derived2 = m_ast->CreateRecordType( - nullptr, lldb::eAccessPublic, "EmptyDerived2", clang::TTK_Struct, - lldb::eLanguageTypeC_plus_plus, nullptr); + nullptr, OptionalClangModuleID(), lldb::eAccessPublic, "EmptyDerived2", + clang::TTK_Struct, lldb::eLanguageTypeC_plus_plus, nullptr); TypeSystemClang::StartTagDeclarationDefinition(empty_derived2); std::unique_ptr non_empty_vbase_spec = m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(), @@ -439,13 +466,15 @@ TEST_F(TestTypeSystemClang, TemplateArguments) { // template struct foo; ClassTemplateDecl *decl = m_ast->CreateClassTemplateDecl( - m_ast->GetTranslationUnitDecl(), eAccessPublic, "foo", TTK_Struct, infos); + m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), eAccessPublic, + "foo", TTK_Struct, infos); ASSERT_NE(decl, nullptr); // foo ClassTemplateSpecializationDecl *spec_decl = m_ast->CreateClassTemplateSpecializationDecl( - m_ast->GetTranslationUnitDecl(), decl, TTK_Struct, infos); + m_ast->GetTranslationUnitDecl(), OptionalClangModuleID(), decl, + TTK_Struct, infos); ASSERT_NE(spec_decl, nullptr); CompilerType type = m_ast->CreateClassTemplateSpecializationType(spec_decl); ASSERT_TRUE(type); @@ -454,7 +483,8 @@ TEST_F(TestTypeSystemClang, TemplateArguments) { // typedef foo foo_def; CompilerType typedef_type = m_ast->CreateTypedefType( - type, "foo_def", m_ast->CreateDeclContext(m_ast->GetTranslationUnitDecl())); + type, "foo_def", + m_ast->CreateDeclContext(m_ast->GetTranslationUnitDecl()), 0); CompilerType auto_type( m_ast.get(), @@ -528,13 +558,14 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) { // Prepare the declarations/types we need for the template. CompilerType clang_type = m_ast->CreateFunctionType(int_type, nullptr, 0U, false, 0U); - FunctionDecl *func = - m_ast->CreateFunctionDeclaration(TU, "foo", clang_type, 0, false); + FunctionDecl *func = m_ast->CreateFunctionDeclaration( + TU, OptionalClangModuleID(), "foo", clang_type, 0, false); TypeSystemClang::TemplateParameterInfos empty_params; // Create the actual function template. clang::FunctionTemplateDecl *func_template = - m_ast->CreateFunctionTemplateDecl(TU, func, "foo", empty_params); + m_ast->CreateFunctionTemplateDecl(TU, OptionalClangModuleID(), func, + "foo", empty_params); EXPECT_EQ(TU, func_template->getDeclContext()); EXPECT_EQ("foo", func_template->getName()); @@ -558,13 +589,14 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) { // We create the FunctionDecl for the template in the TU DeclContext because: // 1. FunctionDecls can't be in a Record (only CXXMethodDecls can). // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine. - FunctionDecl *func = - m_ast->CreateFunctionDeclaration(TU, "foo", clang_type, 0, false); + FunctionDecl *func = m_ast->CreateFunctionDeclaration( + TU, OptionalClangModuleID(), "foo", clang_type, 0, false); TypeSystemClang::TemplateParameterInfos empty_params; // Create the actual function template. clang::FunctionTemplateDecl *func_template = - m_ast->CreateFunctionTemplateDecl(record, func, "foo", empty_params); + m_ast->CreateFunctionTemplateDecl(record, OptionalClangModuleID(), func, + "foo", empty_params); EXPECT_EQ(record, func_template->getDeclContext()); EXPECT_EQ("foo", func_template->getName()); diff --git a/lldb/unittests/TestingSupport/Symbol/ClangTestUtils.h b/lldb/unittests/TestingSupport/Symbol/ClangTestUtils.h index c6954af..6524f09 100644 --- a/lldb/unittests/TestingSupport/Symbol/ClangTestUtils.h +++ b/lldb/unittests/TestingSupport/Symbol/ClangTestUtils.h @@ -28,6 +28,7 @@ inline std::unique_ptr createAST() { inline CompilerType createRecord(TypeSystemClang &ast, llvm::StringRef name) { return ast.CreateRecordType(ast.getASTContext().getTranslationUnitDecl(), + OptionalClangModuleID(), lldb::AccessType::eAccessPublic, name, 0, lldb::LanguageType::eLanguageTypeC); } -- 2.7.4