Skip to content

Commit e30ba5f

Browse files
authored
Merge pull request #39349 from zoecarver/import-base-class-members
2 parents 7f02653 + d067f07 commit e30ba5f

17 files changed

+1160
-75
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ class ClangModuleLoader : public ModuleLoader {
268268
clang::DeclarationName givenName = clang::DeclarationName()) = 0;
269269

270270
/// Determine the effective Clang context for the given Swift nominal type.
271-
EffectiveClangContext virtual getEffectiveClangContext(
271+
virtual EffectiveClangContext getEffectiveClangContext(
272272
const NominalTypeDecl *nominal) = 0;
273273
};
274274

lib/ClangImporter/ClangImporter.cpp

Lines changed: 439 additions & 0 deletions
Large diffs are not rendered by default.

lib/ClangImporter/ImportDecl.cpp

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,7 @@ static AccessorDecl *makeStructRawValueGetter(
692692
assert(storedVar->hasStorage());
693693

694694
ASTContext &C = Impl.SwiftContext;
695-
695+
696696
auto *params = ParameterList::createEmpty(C);
697697

698698
auto computedType = computedVar->getInterfaceType();
@@ -726,7 +726,7 @@ static AccessorDecl *makeFieldGetterDecl(ClangImporter::Implementation &Impl,
726726
auto &C = Impl.SwiftContext;
727727

728728
auto *params = ParameterList::createEmpty(C);
729-
729+
730730
auto getterType = importedFieldDecl->getInterfaceType();
731731
auto getterDecl = AccessorDecl::create(C,
732732
/*FuncLoc=*/importedFieldDecl->getLoc(),
@@ -1152,7 +1152,7 @@ makeBitFieldAccessors(ClangImporter::Implementation &Impl,
11521152
cSetterParamTypes,
11531153
clang::FunctionProtoType::ExtProtoInfo());
11541154
auto cSetterTypeInfo = Ctx.getTrivialTypeSourceInfo(cSetterType);
1155-
1155+
11561156
auto cSetterDecl = clang::FunctionDecl::Create(Ctx,
11571157
structDecl->getDeclContext(),
11581158
clang::SourceLocation(),
@@ -1184,7 +1184,7 @@ makeBitFieldAccessors(ClangImporter::Implementation &Impl,
11841184
clang::SC_None,
11851185
nullptr);
11861186
cGetterDecl->setParams(cGetterSelf);
1187-
1187+
11881188
auto cGetterSelfExpr = new (Ctx) clang::DeclRefExpr(Ctx, cGetterSelf, false,
11891189
recordType,
11901190
clang::VK_PRValue,
@@ -1197,7 +1197,7 @@ makeBitFieldAccessors(ClangImporter::Implementation &Impl,
11971197
clang::VK_PRValue,
11981198
clang::OK_BitField);
11991199

1200-
1200+
12011201
auto cGetterBody = clang::ReturnStmt::Create(Ctx, clang::SourceLocation(),
12021202
cGetterExpr,
12031203
nullptr);
@@ -1228,20 +1228,20 @@ makeBitFieldAccessors(ClangImporter::Implementation &Impl,
12281228
nullptr);
12291229
cSetterParams.push_back(cSetterSelf);
12301230
cSetterDecl->setParams(cSetterParams);
1231-
1231+
12321232
auto cSetterSelfExpr = new (Ctx) clang::DeclRefExpr(Ctx, cSetterSelf, false,
12331233
recordPointerType,
12341234
clang::VK_PRValue,
12351235
clang::SourceLocation());
1236-
1236+
12371237
auto cSetterMemberExpr = clang::MemberExpr::CreateImplicit(Ctx,
12381238
cSetterSelfExpr,
12391239
/*isarrow=*/true,
12401240
fieldDecl,
12411241
fieldType,
12421242
clang::VK_LValue,
12431243
clang::OK_BitField);
1244-
1244+
12451245
auto cSetterValueExpr = new (Ctx) clang::DeclRefExpr(Ctx, cSetterValue, false,
12461246
fieldType,
12471247
clang::VK_PRValue,
@@ -1256,7 +1256,7 @@ makeBitFieldAccessors(ClangImporter::Implementation &Impl,
12561256
clang::OK_Ordinary,
12571257
clang::SourceLocation(),
12581258
clang::FPOptionsOverride());
1259-
1259+
12601260
cSetterDecl->setBody(cSetterExpr);
12611261
}
12621262

@@ -2419,7 +2419,7 @@ namespace {
24192419
if (auto *typedefForAnon = decl->getTypedefNameForAnonDecl())
24202420
return importFullName(typedefForAnon);
24212421
}
2422-
2422+
24232423
return {ImportedName(), None};
24242424
}
24252425

@@ -2806,7 +2806,7 @@ namespace {
28062806
});
28072807

28082808
Result->setUnderlyingType(SwiftType);
2809-
2809+
28102810
// Make Objective-C's 'id' unavailable.
28112811
if (Impl.SwiftContext.LangOpts.EnableObjCInterop && isObjCId(Decl)) {
28122812
auto attr = AvailableAttr::createPlatformAgnostic(
@@ -2882,7 +2882,7 @@ namespace {
28822882
Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
28832883
if (!dc)
28842884
return nullptr;
2885-
2885+
28862886
auto name = importedName.getDeclName().getBaseIdentifier();
28872887

28882888
// Create the enum declaration and record it.
@@ -2948,7 +2948,7 @@ namespace {
29482948
ProtocolDecl *bridgedNSError = nullptr;
29492949
ClassDecl *nsErrorDecl = nullptr;
29502950
ProtocolDecl *errorCodeProto = nullptr;
2951-
if (enumInfo.isErrorEnum() &&
2951+
if (enumInfo.isErrorEnum() &&
29522952
(bridgedNSError =
29532953
C.getProtocol(KnownProtocolKind::BridgedStoredNSError)) &&
29542954
(nsErrorDecl = C.getNSErrorDecl()) &&
@@ -3124,7 +3124,7 @@ namespace {
31243124
Impl.ImportedDecls[{canonicalClangDecl, getVersion()}] = result;
31253125

31263126
// Import each of the enumerators.
3127-
3127+
31283128
bool addEnumeratorsAsMembers;
31293129
switch (enumKind) {
31303130
case EnumKind::Constants:
@@ -3282,7 +3282,7 @@ namespace {
32823282
addDecl(result, enumeratorDecl);
32833283
for (auto *variant : variantDecls)
32843284
addDecl(result, variant);
3285-
3285+
32863286
// If there is an error wrapper, add an alias within the
32873287
// wrapper to the corresponding value within the enumerator
32883288
// context.
@@ -3334,7 +3334,7 @@ namespace {
33343334
// Track whether this record contains fields we can't reference in Swift
33353335
// as stored properties.
33363336
bool hasUnreferenceableStorage = false;
3337-
3337+
33383338
// Track whether this record contains fields that can't be zero-
33393339
// initialized.
33403340
bool hasZeroInitializableStorage = true;
@@ -3576,6 +3576,12 @@ namespace {
35763576

35773577
const clang::CXXRecordDecl *cxxRecordDecl =
35783578
dyn_cast<clang::CXXRecordDecl>(decl);
3579+
bool hasBaseClasses = cxxRecordDecl && !cxxRecordDecl->bases().empty();
3580+
if (hasBaseClasses) {
3581+
hasUnreferenceableStorage = true;
3582+
hasMemberwiseInitializer = false;
3583+
}
3584+
35793585
if (hasZeroInitializableStorage && !cxxRecordDecl) {
35803586
// Add default constructor for the struct if compiling in C mode.
35813587
// If we're compiling for C++, we'll import the C++ default constructor
@@ -4212,10 +4218,10 @@ namespace {
42124218
DeclName ctorName(Impl.SwiftContext, DeclBaseName::createConstructor(),
42134219
bodyParams);
42144220
result = Impl.createDeclWithClangNode<ConstructorDecl>(
4215-
clangNode, AccessLevel::Public, ctorName, loc,
4221+
clangNode, AccessLevel::Public, ctorName, loc,
42164222
/*failable=*/false, /*FailabilityLoc=*/SourceLoc(),
42174223
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
4218-
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
4224+
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
42194225
bodyParams, genericParams, dc);
42204226
} else {
42214227
auto resultTy = importedType.getType();
@@ -4592,33 +4598,33 @@ namespace {
45924598
// Only import types for now.
45934599
if (!isa<clang::TypeDecl>(decl->getUnderlyingDecl()))
45944600
return nullptr;
4595-
4601+
45964602
ImportedName importedName;
45974603
Optional<ImportedName> correctSwiftName;
45984604
std::tie(importedName, correctSwiftName) = importFullName(decl);
45994605
auto Name = importedName.getDeclName().getBaseIdentifier();
46004606
if (Name.empty())
46014607
return nullptr;
4602-
4608+
46034609
// If we've been asked to produce a compatibility stub, handle it via a
46044610
// typealias.
46054611
if (correctSwiftName)
46064612
return importCompatibilityTypeAlias(decl, importedName,
46074613
*correctSwiftName);
4608-
4614+
46094615
auto DC =
46104616
Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
46114617
if (!DC)
46124618
return nullptr;
4613-
4619+
46144620
Decl *SwiftDecl = Impl.importDecl(decl->getUnderlyingDecl(), getActiveSwiftVersion());
46154621
if (!SwiftDecl)
46164622
return nullptr;
46174623

46184624
const TypeDecl *SwiftTypeDecl = dyn_cast<TypeDecl>(SwiftDecl);
46194625
if (!SwiftTypeDecl)
46204626
return nullptr;
4621-
4627+
46224628
auto Loc = Impl.importSourceLoc(decl->getLocation());
46234629
auto Result = Impl.createDeclWithClangNode<TypeAliasDecl>(
46244630
decl,
@@ -5286,7 +5292,7 @@ namespace {
52865292
objcClass->getDeclaredType());
52875293
Impl.SwiftContext.evaluator.cacheOutput(ExtendedNominalRequest{result},
52885294
std::move(objcClass));
5289-
5295+
52905296
// Determine the type and generic args of the extension.
52915297
if (objcClass->getGenericParams()) {
52925298
result->setGenericSignature(objcClass->getGenericSignature());
@@ -5305,7 +5311,7 @@ namespace {
53055311
}
53065312

53075313
template <typename T, typename U>
5308-
T *resolveSwiftDeclImpl(const U *decl, Identifier name,
5314+
T *resolveSwiftDeclImpl(const U *decl, Identifier name,
53095315
bool hasKnownSwiftName, ModuleDecl *overlay) {
53105316
const auto &languageVersion =
53115317
Impl.SwiftContext.LangOpts.EffectiveLanguageVersion;
@@ -6178,7 +6184,7 @@ Decl *SwiftDeclConverter::importCompatibilityTypeAlias(
61786184
}
61796185

61806186
alias->setUnderlyingType(typeDecl->getDeclaredInterfaceType());
6181-
6187+
61826188
// Record that this is the official version of this declaration.
61836189
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = alias;
61846190
markAsVariant(alias, correctSwiftName);
@@ -9335,7 +9341,7 @@ ClangImporter::Implementation::importMirroredDecl(const clang::NamedDecl *decl,
93359341

93369342
auto updateMirroredDecl = [&](Decl *result) {
93379343
result->setImplicit();
9338-
9344+
93399345
// Map the Clang attributes onto Swift attributes.
93409346
importAttributes(decl, result);
93419347

@@ -9926,10 +9932,10 @@ static void loadAllMembersOfSuperclassIfNeeded(ClassDecl *CD) {
99269932
E->loadAllMembers();
99279933
}
99289934

9929-
void ClangImporter::Implementation::loadAllMembersOfRecordDecl(
9930-
NominalTypeDecl *recordDecl) {
9931-
auto clangRecord = cast<clang::RecordDecl>(recordDecl->getClangDecl());
9935+
ValueDecl *cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext);
99329936

9937+
void ClangImporter::Implementation::loadAllMembersOfRecordDecl(
9938+
NominalTypeDecl *swiftDecl, const clang::RecordDecl *clangRecord) {
99339939
// Import all of the members.
99349940
llvm::SmallVector<Decl *, 16> members;
99359941
for (const clang::Decl *m : clangRecord->decls()) {
@@ -9955,12 +9961,36 @@ void ClangImporter::Implementation::loadAllMembersOfRecordDecl(
99559961

99569962
// Add the members here.
99579963
for (auto member: members) {
9964+
// This means we found a member in a C++ record's base class.
9965+
if (swiftDecl->getClangDecl() != clangRecord) {
9966+
// So we need to clone the member into the derived class.
9967+
if (auto newDecl = cloneBaseMemberDecl(cast<ValueDecl>(member), swiftDecl)) {
9968+
swiftDecl->addMember(newDecl);
9969+
}
9970+
continue;
9971+
}
9972+
99589973
// FIXME: constructors are added eagerly, but shouldn't be
99599974
// FIXME: subscripts are added eagerly, but shouldn't be
99609975
if (!isa<AccessorDecl>(member) &&
99619976
!isa<SubscriptDecl>(member) &&
9962-
!isa<ConstructorDecl>(member))
9963-
recordDecl->addMember(member);
9977+
!isa<ConstructorDecl>(member)) {
9978+
swiftDecl->addMember(member);
9979+
}
9980+
}
9981+
9982+
// If this is a C++ record, look through the base classes too.
9983+
if (auto cxxRecord = dyn_cast<clang::CXXRecordDecl>(clangRecord)) {
9984+
for (auto base : cxxRecord->bases()) {
9985+
clang::QualType baseType = base.getType();
9986+
if (auto spectType = dyn_cast<clang::TemplateSpecializationType>(baseType))
9987+
baseType = spectType->desugar();
9988+
if (!isa<clang::RecordType>(baseType))
9989+
continue;
9990+
9991+
auto *baseRecord = cast<clang::RecordType>(baseType)->getDecl();
9992+
loadAllMembersOfRecordDecl(swiftDecl, baseRecord);
9993+
}
99649994
}
99659995
}
99669996

@@ -9996,7 +10026,8 @@ ClangImporter::Implementation::loadAllMembers(Decl *D, uint64_t extra) {
999610026
}
999710027

999810028
if (isa_and_nonnull<clang::RecordDecl>(D->getClangDecl())) {
9999-
loadAllMembersOfRecordDecl(cast<NominalTypeDecl>(D));
10029+
loadAllMembersOfRecordDecl(cast<NominalTypeDecl>(D),
10030+
cast<clang::RecordDecl>(D->getClangDecl()));
1000010031
return;
1000110032
}
1000210033

lib/ClangImporter/ImporterImpl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1460,7 +1460,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
14601460
void
14611461
loadAllMembersOfObjcContainer(Decl *D,
14621462
const clang::ObjCContainerDecl *objcContainer);
1463-
void loadAllMembersOfRecordDecl(NominalTypeDecl *recordDecl);
1463+
void loadAllMembersOfRecordDecl(NominalTypeDecl *swiftDecl,
1464+
const clang::RecordDecl *clangRecord);
14641465

14651466
void collectMembersToAdd(const clang::ObjCContainerDecl *objcContainer,
14661467
Decl *D, DeclContext *DC,

lib/IRGen/GenDecl.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,10 +469,14 @@ void IRGenModule::emitSourceFile(SourceFile &SF) {
469469
if (ObjCInterop)
470470
this->addLinkLibrary(LinkLibrary("objc", LibraryKind::Library));
471471

472-
// Automatically with libc++ when possible.
473-
if (Context.LangOpts.EnableCXXInterop && Context.LangOpts.Target.isOSDarwin())
474-
this->addLinkLibrary(LinkLibrary("c++", LibraryKind::Library));
475-
472+
// If C++ interop is enabled, add -lc++ on Darwin and -lstdc++ on linux.
473+
if (Context.LangOpts.EnableCXXInterop) {
474+
if (Context.LangOpts.Target.isOSDarwin())
475+
this->addLinkLibrary(LinkLibrary("c++", LibraryKind::Library));
476+
else if (Context.LangOpts.Target.isOSLinux())
477+
this->addLinkLibrary(LinkLibrary("stdc++", LibraryKind::Library));
478+
}
479+
476480
// FIXME: It'd be better to have the driver invocation or build system that
477481
// executes the linker introduce these compatibility libraries, since at
478482
// that point we know whether we're building an executable, which is the only

0 commit comments

Comments
 (0)