Skip to content

Commit 01cd1cd

Browse files
authored
Merge pull request #11614 from swiftlang/egorzhdan/21.x-default-ctor-fix
🍒[Clang][Modules] Add added implicit members to record upon deserialization
2 parents d4daf71 + e4c7732 commit 01cd1cd

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

clang/lib/Serialization/ASTReader.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10671,6 +10671,70 @@ void ASTReader::finishPendingActions() {
1067110671

1067210672
// Inform any classes that had members added that they now have more members.
1067310673
for (auto [RD, MD] : PendingAddedClassMembers) {
10674+
// The module we just imported added MD to RD so we should do the same, but
10675+
// only RD doesn't already contain the same member. This can happen when two
10676+
// modules independent add and serialize the same implicit member.
10677+
10678+
// Fast path: we can check for the presence of implicit special members
10679+
// (default/copy/move constructors + copy/move assignments + destructors)
10680+
// with RD's needsImplicit*() methods (which are constant time).
10681+
if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(MD)) {
10682+
if (!Ctor->isInheritingConstructor()) {
10683+
if (Ctor->isDefaultConstructor()) {
10684+
if (RD->needsImplicitDefaultConstructor())
10685+
RD->addHiddenDecl(MD);
10686+
continue;
10687+
}
10688+
if (Ctor->isCopyConstructor()) {
10689+
if (RD->needsImplicitCopyConstructor())
10690+
RD->addHiddenDecl(MD);
10691+
continue;
10692+
}
10693+
if (Ctor->isMoveConstructor()) {
10694+
if (RD->needsImplicitMoveConstructor())
10695+
RD->addHiddenDecl(MD);
10696+
continue;
10697+
}
10698+
}
10699+
} else if (const auto *Mthd = dyn_cast<CXXMethodDecl>(MD)) {
10700+
if (isa<CXXDestructorDecl>(Mthd)) {
10701+
if (RD->needsImplicitDestructor())
10702+
RD->addHiddenDecl(MD);
10703+
continue;
10704+
}
10705+
if (Mthd->isCopyAssignmentOperator()) {
10706+
if (RD->needsImplicitCopyAssignment())
10707+
RD->addHiddenDecl(MD);
10708+
continue;
10709+
}
10710+
if (Mthd->isMoveAssignmentOperator()) {
10711+
if (RD->needsImplicitMoveAssignment())
10712+
RD->addHiddenDecl(MD);
10713+
continue;
10714+
}
10715+
}
10716+
10717+
if (auto *FD = dyn_cast<FunctionDecl>(MD)) {
10718+
// Slow path: this is some other implicit added member (e.g., inherited
10719+
// constructor). We need iterate through all of RD's members and compare
10720+
// their ODR hash against MD's.
10721+
auto needToAddMD = true;
10722+
for (auto *RDD : RD->noload_decls()) {
10723+
if (auto *RDFD = dyn_cast<FunctionDecl>(RDD)) {
10724+
if (FD->getODRHash() == RDFD->getODRHash()) {
10725+
needToAddMD = false;
10726+
break;
10727+
}
10728+
}
10729+
}
10730+
if (needToAddMD)
10731+
RD->addHiddenDecl(MD);
10732+
continue;
10733+
}
10734+
10735+
// This branch is only reachable if MD is not a function decl (which means
10736+
// it doesn't have an ODR hash to compare). Call addedMember() to preserve
10737+
// historical behavior.
1067410738
RD->addedMember(MD);
1067510739
}
1067610740
PendingAddedClassMembers.clear();

0 commit comments

Comments
 (0)