Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp @@ -50,14 +50,13 @@ bool ClangExternalASTSourceCallbacks::FindExternalVisibleDeclsByName( const clang::DeclContext *DC, clang::DeclarationName Name) { llvm::SmallVector decls; - // Objective-C methods are not added into the LookupPtr when they originate - // from an external source. SetExternalVisibleDeclsForName() adds them. - if (auto *oid = llvm::dyn_cast(DC)) { - clang::ObjCContainerDecl::method_range noload_methods(oid->noload_decls()); - for (auto *omd : noload_methods) - if (omd->getDeclName() == Name) - decls.push_back(omd); - } + // SetExternalVisibleDeclsForName() should make all declarations visible + // that are from an AST file. + for (auto *d : DC->noload_decls()) + if (clang::NamedDecl *nd = llvm::dyn_cast(d)) { + if (nd->isFromASTFile() && nd->getDeclName() == Name) + decls.push_back(nd); + } return !SetExternalVisibleDeclsForName(DC, Name, decls).empty(); } Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp =================================================================== --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -1240,6 +1240,11 @@ decl->setFromASTFile(); decl->setOwningModuleID(owning_module.GetValue()); decl->setModuleOwnershipKind(clang::Decl::ModuleOwnershipKind::Visible); + + // Declarations that are marked as setFromASTFile are expected to be added to + // the lookup by the ExternalASTSource. See DeclContext::buildLookupImpl. + if (DeclContext *dc = dyn_cast(decl)) + dc->setHasExternalVisibleStorage(true); } OptionalClangModuleID @@ -8068,7 +8073,6 @@ cxx_record_decl->completeDefinition(); cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true); cxx_record_decl->setHasExternalLexicalStorage(false); - cxx_record_decl->setHasExternalVisibleStorage(false); return true; } } Index: lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/Makefile =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES = main.cpp +CFLAGS_EXTRAS := $(MODULE_DEBUG_INFO_FLAGS) + +include Makefile.rules Index: lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/TestGModulesFieldTypesFromDifferentModules.py =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/TestGModulesFieldTypesFromDifferentModules.py @@ -0,0 +1,17 @@ +""" +Tests that a record with types from two modules works with -gmodules. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + self.build() + self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.expect_expr("mix_modules.u1.c.i", result_type="int", result_value="0") Index: lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/categories =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/categories @@ -0,0 +1 @@ +gmodules Index: lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/common.h =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/common.h @@ -0,0 +1,6 @@ +#ifndef COMMON_H +#define COMMON_H +struct Common { + int i; +}; +#endif // COMMON_H Index: lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/main.cpp =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/main.cpp @@ -0,0 +1,12 @@ +#include "mod1.h" +#include "mod2.h" + +struct Mix { + Use1 u1; + Use2 u2; +}; + +// A record that has FieldDecls with types from two different modules. +Mix mix_modules; + +int main(int argc, const char *argv[]) { return mix_modules.u1.c.i; } Index: lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/mod1.h =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/mod1.h @@ -0,0 +1,5 @@ +#include "common.h" + +struct Use1 { + Common c; +}; Index: lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/mod2.h =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/mod2.h @@ -0,0 +1,5 @@ +#include "common.h" + +struct Use2 { + Common y; +}; Index: lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/mod3.h =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/mod3.h @@ -0,0 +1,7 @@ +#include "mod1.h" +#include "mod2.h" + +struct Mix { + Foo f; + Bar b; +}; Index: lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/module.modulemap =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/gmodules-field-types-from-different-modules/module.modulemap @@ -0,0 +1,2 @@ +module M1 { header "mod1.h" export * } +module M2 { header "mod2.h" export * } Index: lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm =================================================================== --- lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm +++ lldb/test/Shell/SymbolFile/DWARF/module-ownership.mm @@ -25,7 +25,7 @@ // CHECK-ANON-S1: CXXRecordDecl {{.*}} imported in A struct StructB s3; -// CHECK-ANON-S2: CXXRecordDecl {{.*}} imported in A.B {{.*}} struct +// CHECK-ANON-S2: CXXRecordDecl {{.*}} imported in A.B struct // CHECK-ANON-S2: -FieldDecl {{.*}} in A.B anon_field_b 'int' Nested s4;