Skip to content

Commit d50faa8

Browse files
committed
Restructure ClangRecordMemberLookup to eagerly import inherited members
Doing so avoids some annoyingly obscure false-positive errors
1 parent 9eb4057 commit d50faa8

File tree

1 file changed

+39
-37
lines changed

1 file changed

+39
-37
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "swift/AST/DiagnosticEngine.h"
2828
#include "swift/AST/DiagnosticsClangImporter.h"
2929
#include "swift/AST/DiagnosticsSema.h"
30+
#include "swift/AST/Evaluator.h"
3031
#include "swift/AST/IRGenOptions.h"
3132
#include "swift/AST/ImportCache.h"
3233
#include "swift/AST/LinkLibrary.h"
@@ -41,6 +42,7 @@
4142
#include "swift/AST/Types.h"
4243
#include "swift/Basic/Assertions.h"
4344
#include "swift/Basic/Defer.h"
45+
#include "swift/Basic/LLVM.h"
4446
#include "swift/Basic/Platform.h"
4547
#include "swift/Basic/Range.h"
4648
#include "swift/Basic/SourceLoc.h"
@@ -6163,14 +6165,43 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
61636165
ClangModuleLoader *clangModuleLoader = ctx.getClangModuleLoader();
61646166
for (auto found : directResults) {
61656167
auto named = found.get<clang::NamedDecl *>();
6166-
if (dyn_cast<clang::Decl>(named->getDeclContext()) ==
6167-
recordDecl->getClangDecl()) {
6168-
// Don't import constructors on foreign reference types.
6169-
if (isa<clang::CXXConstructorDecl>(named) && isa<ClassDecl>(recordDecl))
6168+
if (dyn_cast<clang::Decl>(named->getDeclContext()) !=
6169+
recordDecl->getClangDecl())
6170+
continue;
6171+
6172+
// Don't import constructors on foreign reference types.
6173+
if (isa<clang::CXXConstructorDecl>(named) && isa<ClassDecl>(recordDecl))
6174+
continue;
6175+
6176+
auto imported = clangModuleLoader->importDeclDirectly(named);
6177+
if (!imported)
6178+
continue;
6179+
6180+
// If this member is found due to inheritance, clone it from the base class
6181+
// by synthesizing getters and setters.
6182+
if (inheritingDecl != recordDecl) {
6183+
imported = clangModuleLoader->importBaseMemberDecl(
6184+
cast<ValueDecl>(imported), inheritingDecl);
6185+
if (!imported)
61706186
continue;
6187+
}
6188+
result.push_back(cast<ValueDecl>(imported));
6189+
}
61716190

6172-
if (auto import = clangModuleLoader->importDeclDirectly(named))
6173-
result.push_back(cast<ValueDecl>(import));
6191+
if (inheritingDecl != recordDecl) {
6192+
// For inheritied members, add members that are synthesized eagerly, such as
6193+
// subscripts. This is not necessary for non-inherited members because those
6194+
// should already be in the lookup table.
6195+
for (auto member :
6196+
cast<NominalTypeDecl>(recordDecl)->getCurrentMembersWithoutLoading()) {
6197+
auto namedMember = dyn_cast<ValueDecl>(member);
6198+
if (!namedMember || !namedMember->hasName() ||
6199+
namedMember->getName().getBaseName() != name)
6200+
continue;
6201+
6202+
if (auto imported = clangModuleLoader->importBaseMemberDecl(
6203+
namedMember, inheritingDecl))
6204+
result.push_back(cast<ValueDecl>(imported));
61746205
}
61756206
}
61766207

@@ -6209,43 +6240,14 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
62096240
ClangRecordMemberLookup(
62106241
{cast<NominalTypeDecl>(import), name, inheritingDecl}),
62116242
{});
6212-
// Add members that are synthesized eagerly, such as subscripts.
6213-
for (auto member :
6214-
cast<NominalTypeDecl>(import)->getCurrentMembersWithoutLoading()) {
6215-
if (auto namedMember = dyn_cast<ValueDecl>(member)) {
6216-
if (namedMember->hasName() &&
6217-
namedMember->getName().getBaseName() == name &&
6218-
// Make sure we don't add duplicate entries, as that would
6219-
// wrongly imply that lookup is ambiguous.
6220-
!llvm::is_contained(baseResults, namedMember)) {
6221-
baseResults.push_back(namedMember);
6222-
}
6223-
}
6224-
}
6243+
62256244
for (auto foundInBase : baseResults) {
62266245
// Do not add duplicate entry with the same arity,
62276246
// as that would cause an ambiguous lookup.
62286247
if (foundNameArities.count(getArity(foundInBase)))
62296248
continue;
62306249

6231-
// Do not importBaseMemberDecl() if this is a recursive lookup into
6232-
// some class's superclass. importBaseMemberDecl() caches synthesized
6233-
// members, which does not work if we call it on its result, e.g.:
6234-
//
6235-
// importBaseMemberDecl(importBaseMemberDecl(foundInBase,
6236-
// recorDecl), recordDecl)
6237-
//
6238-
// Instead, we simply pass on the imported decl (foundInBase) as is,
6239-
// so that only the top-most request calls importBaseMemberDecl().
6240-
if (inheritingDecl != recordDecl) {
6241-
result.push_back(foundInBase);
6242-
continue;
6243-
}
6244-
6245-
if (auto newDecl = clangModuleLoader->importBaseMemberDecl(
6246-
foundInBase, recordDecl)) {
6247-
result.push_back(newDecl);
6248-
}
6250+
result.push_back(foundInBase);
62496251
}
62506252
}
62516253
}

0 commit comments

Comments
 (0)