Skip to content

Commit 011dc46

Browse files
committed
Restructure ClangRecordMemberLookup to eagerly import inherited members
Doing so avoids some annoyingly obscure false-positive errors
1 parent d5ac170 commit 011dc46

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"
@@ -6161,14 +6163,43 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
61616163
ClangModuleLoader *clangModuleLoader = ctx.getClangModuleLoader();
61626164
for (auto found : directResults) {
61636165
auto named = found.get<clang::NamedDecl *>();
6164-
if (dyn_cast<clang::Decl>(named->getDeclContext()) ==
6165-
recordDecl->getClangDecl()) {
6166-
// Don't import constructors on foreign reference types.
6167-
if (isa<clang::CXXConstructorDecl>(named) && isa<ClassDecl>(recordDecl))
6166+
if (dyn_cast<clang::Decl>(named->getDeclContext()) !=
6167+
recordDecl->getClangDecl())
6168+
continue;
6169+
6170+
// Don't import constructors on foreign reference types.
6171+
if (isa<clang::CXXConstructorDecl>(named) && isa<ClassDecl>(recordDecl))
6172+
continue;
6173+
6174+
auto imported = clangModuleLoader->importDeclDirectly(named);
6175+
if (!imported)
6176+
continue;
6177+
6178+
// If this member is found due to inheritance, clone it from the base class
6179+
// by synthesizing getters and setters.
6180+
if (inheritingDecl != recordDecl) {
6181+
imported = clangModuleLoader->importBaseMemberDecl(
6182+
cast<ValueDecl>(imported), inheritingDecl);
6183+
if (!imported)
61686184
continue;
6185+
}
6186+
result.push_back(cast<ValueDecl>(imported));
6187+
}
61696188

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

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

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

0 commit comments

Comments
 (0)