Skip to content

Commit 19cdab4

Browse files
committed
[Clang importer] Eliminate redundant imports of C++ fields as properties
A recent refactoring uncovered two places where we could end up importing a C++ field declaration as a property more than once: 1. Importing the declaration context of a field in C++ mode can then go import all of the fields. In such a case, check that the field we're importing didn't happen already, and bail out early if it did. This is common practice in the Clang importer but wasn't happening here. 2. One caller to the function that imported a field from a C++ base class into its inheriting class (as a computed property) wasn't checking the cache, and therefore created a redundant version. Fix both issues. (cherry picked from commit b374c09)
1 parent cf7b7c7 commit 19cdab4

File tree

3 files changed

+25
-9
lines changed

3 files changed

+25
-9
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4992,7 +4992,8 @@ DeclAttributes cloneImportedAttributes(ValueDecl *decl, ASTContext &context) {
49924992
return attrs;
49934993
}
49944994

4995-
ValueDecl *cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
4995+
static ValueDecl *
4996+
cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
49964997
if (auto fn = dyn_cast<FuncDecl>(decl)) {
49974998
// TODO: function templates are specialized during type checking so to
49984999
// support these we need to tell Swift to type check the synthesized bodies.
@@ -6282,16 +6283,23 @@ Decl *ClangImporter::importDeclDirectly(const clang::NamedDecl *decl) {
62826283
return Impl.importDecl(decl, Impl.CurrentVersion);
62836284
}
62846285

6285-
ValueDecl *ClangImporter::importBaseMemberDecl(ValueDecl *decl,
6286-
DeclContext *newContext) {
6286+
ValueDecl *ClangImporter::Implementation::importBaseMemberDecl(
6287+
ValueDecl *decl, DeclContext *newContext) {
62876288
// Make sure we don't clone the decl again for this class, as that would
62886289
// result in multiple definitions of the same symbol.
62896290
std::pair<ValueDecl *, DeclContext *> key = {decl, newContext};
6290-
if (!Impl.clonedBaseMembers.count(key)) {
6291+
auto known = clonedBaseMembers.find(key);
6292+
if (known == clonedBaseMembers.end()) {
62916293
ValueDecl *cloned = cloneBaseMemberDecl(decl, newContext);
6292-
Impl.clonedBaseMembers[key] = cloned;
6294+
known = clonedBaseMembers.insert({key, cloned}).first;
62936295
}
6294-
return Impl.clonedBaseMembers[key];
6296+
6297+
return known->second;
6298+
}
6299+
6300+
ValueDecl *ClangImporter::importBaseMemberDecl(ValueDecl *decl,
6301+
DeclContext *newContext) {
6302+
return Impl.importBaseMemberDecl(decl, newContext);
62956303
}
62966304

62976305
void ClangImporter::diagnoseTopLevelValue(const DeclName &name) {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3570,6 +3570,12 @@ namespace {
35703570
if (!dc)
35713571
return nullptr;
35723572

3573+
// While importing the DeclContext, we might have imported the decl
3574+
// itself.
3575+
auto known = Impl.importDeclCached(decl, getVersion());
3576+
if (known.has_value())
3577+
return known.value();
3578+
35733579
// TODO: do we want to emit a diagnostic here?
35743580
// Types that are marked as foreign references cannot be stored by value.
35753581
if (auto recordType =
@@ -8750,8 +8756,6 @@ static void loadAllMembersOfSuperclassIfNeeded(ClassDecl *CD) {
87508756
E->loadAllMembers();
87518757
}
87528758

8753-
ValueDecl *cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext);
8754-
87558759
void ClangImporter::Implementation::loadAllMembersOfRecordDecl(
87568760
NominalTypeDecl *swiftDecl, const clang::RecordDecl *clangRecord) {
87578761
// Import all of the members.
@@ -8782,7 +8786,7 @@ void ClangImporter::Implementation::loadAllMembersOfRecordDecl(
87828786
// This means we found a member in a C++ record's base class.
87838787
if (swiftDecl->getClangDecl() != clangRecord) {
87848788
// So we need to clone the member into the derived class.
8785-
if (auto newDecl = cloneBaseMemberDecl(cast<ValueDecl>(member), swiftDecl)) {
8789+
if (auto newDecl = importBaseMemberDecl(cast<ValueDecl>(member), swiftDecl)) {
87868790
swiftDecl->addMember(newDecl);
87878791
}
87888792
continue;

lib/ClangImporter/ImporterImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,10 +642,14 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
642642
llvm::MapVector<std::pair<NominalTypeDecl *, Type>,
643643
std::pair<FuncDecl *, FuncDecl *>> cxxSubscripts;
644644

645+
private:
645646
// Keep track of the decls that were already cloned for this specific class.
646647
llvm::DenseMap<std::pair<ValueDecl *, DeclContext *>, ValueDecl *>
647648
clonedBaseMembers;
648649

650+
ValueDecl *importBaseMemberDecl(ValueDecl *decl, DeclContext *newContext);
651+
652+
public:
649653
// Cache for already-specialized function templates and any thunks they may
650654
// have.
651655
llvm::DenseMap<clang::FunctionDecl *, ValueDecl *>

0 commit comments

Comments
 (0)