@@ -6226,13 +6226,11 @@ swift::extractNearestSourceLoc(const ClangCategoryLookupDescriptor &desc) {
62266226
62276227TinyPtrVector<ValueDecl *>
62286228ClangImporter::Implementation::loadNamedMembers (
6229- const IterableDeclContext *IDC, DeclBaseName N, uint64_t contextData) {
6230-
6229+ const IterableDeclContext *IDC, DeclBaseName N, uint64_t extra) {
62316230 auto *D = IDC->getDecl ();
62326231 auto *DC = D->getInnermostDeclContext ();
62336232 auto *CD = D->getClangDecl ();
6234- auto *CDC = cast<clang::DeclContext>(CD);
6235- assert (CD && " loadNamedMembers on a Decl without a clangDecl" );
6233+ auto *CDC = cast_or_null<clang::DeclContext>(CD);
62366234
62376235 auto *nominal = DC->getSelfNominalTypeDecl ();
62386236 auto effectiveClangContext = getEffectiveClangContext (nominal);
@@ -6252,15 +6250,22 @@ ClangImporter::Implementation::loadNamedMembers(
62526250 // findLookupTable, below, handles the first two cases; we assert on the
62536251 // third.
62546252
6255- auto CMO = getClangSubmoduleForDecl (CD);
6253+ llvm::Optional<clang::Module *> CMO;
6254+ if (CD)
6255+ CMO = getClangSubmoduleForDecl (CD);
6256+ else {
6257+ // IDC is an extension containing globals imported as members, so it doesn't
6258+ // have a clang node but the submodule pointer has been stashed in `extra`.
6259+ CMO = reinterpret_cast <clang::Module *>(static_cast <uintptr_t >(extra));
6260+ }
62566261 assert (CMO && " loadNamedMembers on a forward-declared Decl" );
62576262
62586263 auto table = findLookupTable (*CMO);
62596264 assert (table && " clang module without lookup table" );
62606265
6261- assert (!isa <clang::NamespaceDecl>(CD) && " Namespace members should be loaded "
6262- " via a request." );
6263- assert (isa<clang::ObjCContainerDecl>(CD));
6266+ assert (!isa_and_nonnull <clang::NamespaceDecl>(CD)
6267+ && " Namespace members should be loaded via a request." );
6268+ assert (!CD || isa<clang::ObjCContainerDecl>(CD));
62646269
62656270 // Force the members of the entire inheritance hierarchy to be loaded and
62666271 // deserialized before loading the named member of a class. This warms up
@@ -6275,32 +6280,37 @@ ClangImporter::Implementation::loadNamedMembers(
62756280
62766281 // TODO: update this to use the requestified lookup.
62776282 TinyPtrVector<ValueDecl *> Members;
6278- for (auto entry : table->lookup (SerializedSwiftName (N),
6279- effectiveClangContext)) {
6280- if (!entry.is <clang::NamedDecl *>()) continue ;
6281- auto member = entry.get <clang::NamedDecl *>();
6282- if (!isVisibleClangEntry (member)) continue ;
62836283
6284- // Skip Decls from different clang::DeclContexts
6285- if (member->getDeclContext () != CDC) continue ;
6286-
6287- SmallVector<Decl*, 4 > tmp;
6288- insertMembersAndAlternates (member, tmp);
6289- for (auto *TD : tmp) {
6290- if (auto *V = dyn_cast<ValueDecl>(TD)) {
6291- // Skip ValueDecls if they import under different names.
6292- if (V->getBaseName () == N) {
6293- Members.push_back (V);
6284+ // Lookup actual, factual clang-side members of the context. No need to do
6285+ // this if we're handling an import-as-member extension.
6286+ if (CD) {
6287+ for (auto entry : table->lookup (SerializedSwiftName (N),
6288+ effectiveClangContext)) {
6289+ if (!entry.is <clang::NamedDecl *>()) continue ;
6290+ auto member = entry.get <clang::NamedDecl *>();
6291+ if (!isVisibleClangEntry (member)) continue ;
6292+
6293+ // Skip Decls from different clang::DeclContexts
6294+ if (member->getDeclContext () != CDC) continue ;
6295+
6296+ SmallVector<Decl*, 4 > tmp;
6297+ insertMembersAndAlternates (member, tmp, DC);
6298+ for (auto *TD : tmp) {
6299+ if (auto *V = dyn_cast<ValueDecl>(TD)) {
6300+ // Skip ValueDecls if they import under different names.
6301+ if (V->getBaseName () == N) {
6302+ Members.push_back (V);
6303+ }
62946304 }
6295- }
62966305
6297- // If the property's accessors have alternate decls, we might have
6298- // to import those too.
6299- if (auto *ASD = dyn_cast<AbstractStorageDecl>(TD)) {
6300- for (auto *AD : ASD->getAllAccessors ()) {
6301- for (auto *D : getAlternateDecls (AD)) {
6302- if (D->getBaseName () == N)
6303- Members.push_back (D);
6306+ // If the property's accessors have alternate decls, we might have
6307+ // to import those too.
6308+ if (auto *ASD = dyn_cast<AbstractStorageDecl>(TD)) {
6309+ for (auto *AD : ASD->getAllAccessors ()) {
6310+ for (auto *D : getAlternateDecls (AD)) {
6311+ if (D->getBaseName () == N)
6312+ Members.push_back (D);
6313+ }
63046314 }
63056315 }
63066316 }
@@ -6313,11 +6323,14 @@ ClangImporter::Implementation::loadNamedMembers(
63136323 auto member = entry.get <clang::NamedDecl *>();
63146324 if (!isVisibleClangEntry (member)) continue ;
63156325
6316- // Skip Decls from different clang::DeclContexts
6317- if (member->getDeclContext () != CDC) continue ;
6326+ // Skip Decls from different clang::DeclContexts. We don't do this for
6327+ // import-as-member extensions because we don't know what decl context to
6328+ // expect; for instance, an enum constant is inside the enum decl, not in
6329+ // the translation unit.
6330+ if (CDC && member->getDeclContext () != CDC) continue ;
63186331
63196332 SmallVector<Decl*, 4 > tmp;
6320- insertMembersAndAlternates (member, tmp);
6333+ insertMembersAndAlternates (member, tmp, DC );
63216334 for (auto *TD : tmp) {
63226335 if (auto *V = dyn_cast<ValueDecl>(TD)) {
63236336 // Skip ValueDecls if they import under different names.
@@ -6328,7 +6341,7 @@ ClangImporter::Implementation::loadNamedMembers(
63286341 }
63296342 }
63306343
6331- if (N.isConstructor ()) {
6344+ if (CD && N.isConstructor ()) {
63326345 if (auto *classDecl = dyn_cast<ClassDecl>(D)) {
63336346 SmallVector<Decl *, 4 > ctors;
63346347 importInheritedConstructors (cast<clang::ObjCInterfaceDecl>(CD),
@@ -6338,7 +6351,7 @@ ClangImporter::Implementation::loadNamedMembers(
63386351 }
63396352 }
63406353
6341- if (!isa<ProtocolDecl>(D)) {
6354+ if (CD && !isa<ProtocolDecl>(D)) {
63426355 if (auto *OCD = dyn_cast<clang::ObjCContainerDecl>(CD)) {
63436356 SmallVector<Decl *, 1 > newMembers;
63446357 importMirroredProtocolMembers (OCD, DC, N, newMembers);
0 commit comments