Skip to content

Commit 0134baf

Browse files
authored
Merge pull request #86124 from Xazax-hun/fix-multiple-inheritance-refcounts
[cxx-interop] Fix miscompilation for inferred shared references
2 parents cd3ebfb + 35bcc99 commit 0134baf

File tree

13 files changed

+271
-46
lines changed

13 files changed

+271
-46
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,13 @@ class ClangModuleLoader : public ModuleLoader {
216216
DeclContext *newContext,
217217
ClangInheritanceInfo inheritance) = 0;
218218

219-
/// Returnes the original method if \param decl is a clone from a base class
219+
/// Returns the original method if \param decl is a clone from a base class
220220
virtual ValueDecl *getOriginalForClonedMember(const ValueDecl *decl) = 0;
221221

222+
/// Returns true if we synthesize this member for every type so no need to
223+
/// clone it for the derived classes.
224+
virtual bool isMemberSynthesizedPerType(const ValueDecl *decl) = 0;
225+
222226
/// Emits diagnostics for any declarations named name
223227
/// whose direct declaration context is a TU.
224228
virtual void diagnoseTopLevelValue(const DeclName &name) = 0;

include/swift/ClangImporter/ClangImporter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ class ClangImporter final : public ClangModuleLoader {
650650
ClangInheritanceInfo inheritance) override;
651651

652652
ValueDecl *getOriginalForClonedMember(const ValueDecl *decl) override;
653+
bool isMemberSynthesizedPerType(const ValueDecl *decl) override;
653654

654655
/// Emits diagnostics for any declarations named name
655656
/// whose direct declaration context is a TU.

include/swift/ClangImporter/ClangImporterRequests.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ struct CustomRefCountingOperationResult {
500500

501501
CustomRefCountingOperationResultKind kind;
502502
ValueDecl *operation;
503-
std::string name;
503+
StringRef name;
504504
};
505505

506506
class CustomRefCountingOperation

lib/ClangImporter/ClangImporter.cpp

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6565,6 +6565,7 @@ TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
65656565
auto namedMember = dyn_cast<ValueDecl>(member);
65666566
if (!namedMember || !namedMember->hasName() ||
65676567
namedMember->getName().getBaseName() != name ||
6568+
clangModuleLoader->isMemberSynthesizedPerType(namedMember) ||
65686569
clangModuleLoader->getOriginalForClonedMember(namedMember))
65696570
continue;
65706571

@@ -8033,6 +8034,16 @@ ValueDecl *ClangImporter::Implementation::getOriginalForClonedMember(
80338034
return nullptr;
80348035
}
80358036

8037+
bool ClangImporter::Implementation::isMemberSynthesizedPerType(
8038+
const ValueDecl *decl) {
8039+
return membersSynthesizedPerType.contains(decl);
8040+
}
8041+
8042+
void ClangImporter::Implementation::markMemberSynthesizedPerType(
8043+
const ValueDecl *decl) {
8044+
membersSynthesizedPerType.insert(decl);
8045+
}
8046+
80368047
size_t ClangImporter::Implementation::getImportedBaseMemberDeclArity(
80378048
const ValueDecl *valueDecl) {
80388049
if (auto *func = dyn_cast<FuncDecl>(valueDecl)) {
@@ -8053,6 +8064,10 @@ ValueDecl *ClangImporter::getOriginalForClonedMember(const ValueDecl *decl) {
80538064
return Impl.getOriginalForClonedMember(decl);
80548065
}
80558066

8067+
bool ClangImporter::isMemberSynthesizedPerType(const ValueDecl *decl) {
8068+
return Impl.isMemberSynthesizedPerType(decl);
8069+
}
8070+
80568071
void ClangImporter::diagnoseTopLevelValue(const DeclName &name) {
80578072
Impl.diagnoseTopLevelValue(name);
80588073
}
@@ -8206,12 +8221,15 @@ importer::getValueDeclsForName(NominalTypeDecl *decl, StringRef name) {
82068221
auto clangDecl = decl->getClangDecl();
82078222
llvm::SmallVector<ValueDecl *, 1> results;
82088223

8209-
if (name.starts_with(".")) {
8224+
if (name.consume_front(".")) {
82108225
// Look for a member of decl instead of a global.
8211-
StringRef memberName = name.drop_front(1);
8212-
if (memberName.empty())
8226+
if (name.empty())
82138227
return {};
8214-
auto declName = DeclName(ctx.getIdentifier(memberName));
8228+
auto declName = DeclName(ctx.getIdentifier(name));
8229+
auto swiftLookupResults = decl->lookupDirect(declName);
8230+
if (!swiftLookupResults.empty())
8231+
return SmallVector<ValueDecl *, 1>(swiftLookupResults.begin(),
8232+
swiftLookupResults.end());
82158233
auto allResults = evaluateOrDefault(
82168234
ctx.evaluator, ClangRecordMemberLookup({decl, declName}), {});
82178235
return SmallVector<ValueDecl *, 1>(allResults.begin(), allResults.end());
@@ -8242,9 +8260,9 @@ importer::getValueDeclsForName(NominalTypeDecl *decl, StringRef name) {
82428260
return results;
82438261
}
82448262

8245-
static const clang::RecordDecl *
8246-
getRefParentOrDiag(const clang::RecordDecl *decl, ASTContext &ctx,
8247-
ClangImporter::Implementation *importerImpl) {
8263+
const clang::RecordDecl *
8264+
importer::getRefParentOrDiag(const clang::RecordDecl *decl, ASTContext &ctx,
8265+
ClangImporter::Implementation *importerImpl) {
82488266
auto refParentDecls = getRefParentDecls(decl, ctx, importerImpl);
82498267
if (refParentDecls.empty())
82508268
return nullptr;
@@ -8257,11 +8275,11 @@ getRefParentOrDiag(const clang::RecordDecl *decl, ASTContext &ctx,
82578275
assert(refParentDecl && "refParentDecl is null inside getRefParentOrDiag");
82588276
for (const auto *attr : refParentDecl->getAttrs()) {
82598277
if (const auto swiftAttr = llvm::dyn_cast<clang::SwiftAttrAttr>(attr)) {
8260-
const auto &attribute = swiftAttr->getAttribute();
8261-
if (attribute.starts_with(retainPrefix))
8262-
uniqueRetainDecls.insert(attribute.drop_front(retainPrefix.size()));
8263-
else if (attribute.starts_with(releasePrefix))
8264-
uniqueReleaseDecls.insert(attribute.drop_front(releasePrefix.size()));
8278+
auto attribute = swiftAttr->getAttribute();
8279+
if (attribute.consume_front(retainPrefix))
8280+
uniqueRetainDecls.insert(attribute);
8281+
else if (attribute.consume_front(releasePrefix))
8282+
uniqueReleaseDecls.insert(attribute);
82658283
}
82668284
}
82678285
}
@@ -8811,19 +8829,12 @@ CustomRefCountingOperationResult CustomRefCountingOperation::evaluate(
88118829
Evaluator &evaluator, CustomRefCountingOperationDescriptor desc) const {
88128830
auto swiftDecl = desc.decl;
88138831
auto operation = desc.kind;
8814-
auto &ctx = swiftDecl->getASTContext();
88158832

8816-
std::string operationStr = operation == CustomRefCountingOperationKind::retain
8817-
? "retain:"
8818-
: "release:";
8833+
StringRef operationStr = operation == CustomRefCountingOperationKind::retain
8834+
? "retain:"
8835+
: "release:";
88198836

88208837
auto decl = cast<clang::RecordDecl>(swiftDecl->getClangDecl());
8821-
8822-
if (!hasImportAsRefAttr(decl)) {
8823-
if (auto parentRefDecl = getRefParentOrDiag(decl, ctx, nullptr))
8824-
decl = parentRefDecl;
8825-
}
8826-
88278838
if (!decl->hasAttrs())
88288839
return {CustomRefCountingOperationResult::noAttribute, nullptr, ""};
88298840

@@ -8842,10 +8853,8 @@ CustomRefCountingOperationResult CustomRefCountingOperation::evaluate(
88428853
if (retainReleaseAttrs.size() > 1)
88438854
return {CustomRefCountingOperationResult::tooManyAttributes, nullptr, ""};
88448855

8845-
auto name = retainReleaseAttrs.front()
8846-
->getAttribute()
8847-
.drop_front(StringRef(operationStr).size())
8848-
.str();
8856+
auto name = retainReleaseAttrs.front()->getAttribute().drop_front(
8857+
operationStr.size());
88498858

88508859
if (name == "immortal")
88518860
return {CustomRefCountingOperationResult::immortal, nullptr, name};

lib/ClangImporter/ImportDecl.cpp

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,6 +2190,39 @@ namespace {
21902190
return true;
21912191
}
21922192

2193+
std::pair<CustomRefCountingOperationResult,
2194+
CustomRefCountingOperationResult>
2195+
addRefCountOperationsIfRequired(ClassDecl *nominal,
2196+
clang::RecordDecl *clangType) {
2197+
auto &context = Impl.SwiftContext;
2198+
auto nonInheritedRefCountingOperations = [&] {
2199+
auto retainResult = evaluateOrDefault(
2200+
context.evaluator,
2201+
CustomRefCountingOperation(
2202+
{nominal, CustomRefCountingOperationKind::retain}),
2203+
{});
2204+
auto releaseResult = evaluateOrDefault(
2205+
context.evaluator,
2206+
CustomRefCountingOperation(
2207+
{nominal, CustomRefCountingOperationKind::release}),
2208+
{});
2209+
return std::make_pair(retainResult, releaseResult);
2210+
};
2211+
auto clangDecl = dyn_cast<clang::CXXRecordDecl>(clangType);
2212+
if (!clangDecl)
2213+
return nonInheritedRefCountingOperations();
2214+
auto baseClangDecl = dyn_cast_or_null<clang::CXXRecordDecl>(
2215+
getRefParentOrDiag(clangDecl, context, nullptr));
2216+
if (!baseClangDecl || baseClangDecl == clangDecl)
2217+
return nonInheritedRefCountingOperations();
2218+
2219+
auto baseSwiftDecl = cast<ClassDecl>(
2220+
Impl.importDecl(baseClangDecl, getActiveSwiftVersion()));
2221+
2222+
return synthesizer.addRefCountOperations(nominal, clangDecl,
2223+
baseSwiftDecl, baseClangDecl);
2224+
}
2225+
21932226
Decl *VisitRecordDecl(const clang::RecordDecl *decl) {
21942227
// Track whether this record contains fields we can't reference in Swift
21952228
// as stored properties.
@@ -2786,7 +2819,11 @@ namespace {
27862819
}
27872820

27882821
if (auto classDecl = dyn_cast<ClassDecl>(result)) {
2789-
validateForeignReferenceType(decl, classDecl);
2822+
auto operations = addRefCountOperationsIfRequired(
2823+
classDecl, const_cast<clang::RecordDecl *>(decl));
2824+
2825+
validateForeignReferenceType(decl, classDecl, operations.first,
2826+
operations.second);
27902827

27912828
auto availability = Impl.SwiftContext.getSwift58Availability();
27922829
if (!availability.isAlwaysAvailable()) {
@@ -2853,8 +2890,10 @@ namespace {
28532890
}
28542891
}
28552892

2856-
void validateForeignReferenceType(const clang::RecordDecl *decl,
2857-
ClassDecl *classDecl) {
2893+
void validateForeignReferenceType(
2894+
const clang::RecordDecl *decl, ClassDecl *classDecl,
2895+
CustomRefCountingOperationResult retainOperation,
2896+
CustomRefCountingOperationResult releaseOperation) {
28582897

28592898
enum class RetainReleaseOperationKind {
28602899
notAfunction,
@@ -2937,11 +2976,6 @@ namespace {
29372976
return RetainReleaseOperationKind::valid;
29382977
};
29392978

2940-
auto retainOperation = evaluateOrDefault(
2941-
Impl.SwiftContext.evaluator,
2942-
CustomRefCountingOperation(
2943-
{classDecl, CustomRefCountingOperationKind::retain}),
2944-
{});
29452979
if (retainOperation.kind ==
29462980
CustomRefCountingOperationResult::noAttribute) {
29472981
HeaderLoc loc(decl->getLocation());
@@ -3008,11 +3042,6 @@ namespace {
30083042
CustomRefCountingOperationResult::immortal);
30093043
}
30103044

3011-
auto releaseOperation = evaluateOrDefault(
3012-
Impl.SwiftContext.evaluator,
3013-
CustomRefCountingOperation(
3014-
{classDecl, CustomRefCountingOperationKind::release}),
3015-
{});
30163045
if (releaseOperation.kind ==
30173046
CustomRefCountingOperationResult::noAttribute) {
30183047
HeaderLoc loc(decl->getLocation());

lib/ClangImporter/ImporterImpl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "clang/Serialization/ModuleFileExtension.h"
4949
#include "llvm/ADT/APSInt.h"
5050
#include "llvm/ADT/DenseMap.h"
51+
#include "llvm/ADT/DenseSet.h"
5152
#include "llvm/ADT/Hashing.h"
5253
#include "llvm/ADT/IntrusiveRefCntPtr.h"
5354
#include "llvm/ADT/SmallBitVector.h"
@@ -692,6 +693,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
692693

693694
// Map all cloned methods back to the original member
694695
llvm::DenseMap<ValueDecl *, ValueDecl *> clonedMembers;
696+
llvm::DenseSet<const ValueDecl *> membersSynthesizedPerType;
695697

696698
// Keep track of methods that are unavailale in each class.
697699
// We need this set because these methods will be imported lazily. We don't
@@ -714,6 +716,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
714716
ClangInheritanceInfo inheritance);
715717

716718
ValueDecl *getOriginalForClonedMember(const ValueDecl *decl);
719+
bool isMemberSynthesizedPerType(const ValueDecl *decl);
720+
void markMemberSynthesizedPerType(const ValueDecl *decl);
717721

718722
static size_t getImportedBaseMemberDeclArity(const ValueDecl *valueDecl);
719723

@@ -2228,6 +2232,11 @@ getImplicitObjectParamAnnotation(const clang::FunctionDecl *FD) {
22282232
return nullptr;
22292233
}
22302234

2235+
/// Find a unique base class that is annotated as SHARED_REFERENCE if any.
2236+
const clang::RecordDecl *
2237+
getRefParentOrDiag(const clang::RecordDecl *decl, ASTContext &ctx,
2238+
ClangImporter::Implementation *importerImpl);
2239+
22312240
} // end namespace importer
22322241
} // end namespace swift
22332242

0 commit comments

Comments
 (0)