diff --git a/include/swift/AST/ClangModuleLoader.h b/include/swift/AST/ClangModuleLoader.h index c01a76a31d2a0..8c1dc50ed732b 100644 --- a/include/swift/AST/ClangModuleLoader.h +++ b/include/swift/AST/ClangModuleLoader.h @@ -216,9 +216,13 @@ class ClangModuleLoader : public ModuleLoader { DeclContext *newContext, ClangInheritanceInfo inheritance) = 0; - /// Returnes the original method if \param decl is a clone from a base class + /// Returns the original method if \param decl is a clone from a base class virtual ValueDecl *getOriginalForClonedMember(const ValueDecl *decl) = 0; + /// Returns true if we synthesize this member for every type so no need to + /// clone it for the derived classes. + virtual bool isMemberSynthesizedPerType(const ValueDecl *decl) = 0; + /// Emits diagnostics for any declarations named name /// whose direct declaration context is a TU. virtual void diagnoseTopLevelValue(const DeclName &name) = 0; diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h index 81da1291ff293..87eb363590b09 100644 --- a/include/swift/ClangImporter/ClangImporter.h +++ b/include/swift/ClangImporter/ClangImporter.h @@ -650,6 +650,7 @@ class ClangImporter final : public ClangModuleLoader { ClangInheritanceInfo inheritance) override; ValueDecl *getOriginalForClonedMember(const ValueDecl *decl) override; + bool isMemberSynthesizedPerType(const ValueDecl *decl) override; /// Emits diagnostics for any declarations named name /// whose direct declaration context is a TU. diff --git a/include/swift/ClangImporter/ClangImporterRequests.h b/include/swift/ClangImporter/ClangImporterRequests.h index c8f9ac83ffd79..a6c2e43ece393 100644 --- a/include/swift/ClangImporter/ClangImporterRequests.h +++ b/include/swift/ClangImporter/ClangImporterRequests.h @@ -500,7 +500,7 @@ struct CustomRefCountingOperationResult { CustomRefCountingOperationResultKind kind; ValueDecl *operation; - std::string name; + StringRef name; }; class CustomRefCountingOperation diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 4e7a0c999b06a..73f78ac566104 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -6565,6 +6565,7 @@ TinyPtrVector ClangRecordMemberLookup::evaluate( auto namedMember = dyn_cast(member); if (!namedMember || !namedMember->hasName() || namedMember->getName().getBaseName() != name || + clangModuleLoader->isMemberSynthesizedPerType(namedMember) || clangModuleLoader->getOriginalForClonedMember(namedMember)) continue; @@ -8033,6 +8034,16 @@ ValueDecl *ClangImporter::Implementation::getOriginalForClonedMember( return nullptr; } +bool ClangImporter::Implementation::isMemberSynthesizedPerType( + const ValueDecl *decl) { + return membersSynthesizedPerType.contains(decl); +} + +void ClangImporter::Implementation::markMemberSynthesizedPerType( + const ValueDecl *decl) { + membersSynthesizedPerType.insert(decl); +} + size_t ClangImporter::Implementation::getImportedBaseMemberDeclArity( const ValueDecl *valueDecl) { if (auto *func = dyn_cast(valueDecl)) { @@ -8053,6 +8064,10 @@ ValueDecl *ClangImporter::getOriginalForClonedMember(const ValueDecl *decl) { return Impl.getOriginalForClonedMember(decl); } +bool ClangImporter::isMemberSynthesizedPerType(const ValueDecl *decl) { + return Impl.isMemberSynthesizedPerType(decl); +} + void ClangImporter::diagnoseTopLevelValue(const DeclName &name) { Impl.diagnoseTopLevelValue(name); } @@ -8206,12 +8221,15 @@ importer::getValueDeclsForName(NominalTypeDecl *decl, StringRef name) { auto clangDecl = decl->getClangDecl(); llvm::SmallVector results; - if (name.starts_with(".")) { + if (name.consume_front(".")) { // Look for a member of decl instead of a global. - StringRef memberName = name.drop_front(1); - if (memberName.empty()) + if (name.empty()) return {}; - auto declName = DeclName(ctx.getIdentifier(memberName)); + auto declName = DeclName(ctx.getIdentifier(name)); + auto swiftLookupResults = decl->lookupDirect(declName); + if (!swiftLookupResults.empty()) + return SmallVector(swiftLookupResults.begin(), + swiftLookupResults.end()); auto allResults = evaluateOrDefault( ctx.evaluator, ClangRecordMemberLookup({decl, declName}), {}); return SmallVector(allResults.begin(), allResults.end()); @@ -8242,9 +8260,9 @@ importer::getValueDeclsForName(NominalTypeDecl *decl, StringRef name) { return results; } -static const clang::RecordDecl * -getRefParentOrDiag(const clang::RecordDecl *decl, ASTContext &ctx, - ClangImporter::Implementation *importerImpl) { +const clang::RecordDecl * +importer::getRefParentOrDiag(const clang::RecordDecl *decl, ASTContext &ctx, + ClangImporter::Implementation *importerImpl) { auto refParentDecls = getRefParentDecls(decl, ctx, importerImpl); if (refParentDecls.empty()) return nullptr; @@ -8257,11 +8275,11 @@ getRefParentOrDiag(const clang::RecordDecl *decl, ASTContext &ctx, assert(refParentDecl && "refParentDecl is null inside getRefParentOrDiag"); for (const auto *attr : refParentDecl->getAttrs()) { if (const auto swiftAttr = llvm::dyn_cast(attr)) { - const auto &attribute = swiftAttr->getAttribute(); - if (attribute.starts_with(retainPrefix)) - uniqueRetainDecls.insert(attribute.drop_front(retainPrefix.size())); - else if (attribute.starts_with(releasePrefix)) - uniqueReleaseDecls.insert(attribute.drop_front(releasePrefix.size())); + auto attribute = swiftAttr->getAttribute(); + if (attribute.consume_front(retainPrefix)) + uniqueRetainDecls.insert(attribute); + else if (attribute.consume_front(releasePrefix)) + uniqueReleaseDecls.insert(attribute); } } } @@ -8811,19 +8829,12 @@ CustomRefCountingOperationResult CustomRefCountingOperation::evaluate( Evaluator &evaluator, CustomRefCountingOperationDescriptor desc) const { auto swiftDecl = desc.decl; auto operation = desc.kind; - auto &ctx = swiftDecl->getASTContext(); - std::string operationStr = operation == CustomRefCountingOperationKind::retain - ? "retain:" - : "release:"; + StringRef operationStr = operation == CustomRefCountingOperationKind::retain + ? "retain:" + : "release:"; auto decl = cast(swiftDecl->getClangDecl()); - - if (!hasImportAsRefAttr(decl)) { - if (auto parentRefDecl = getRefParentOrDiag(decl, ctx, nullptr)) - decl = parentRefDecl; - } - if (!decl->hasAttrs()) return {CustomRefCountingOperationResult::noAttribute, nullptr, ""}; @@ -8842,10 +8853,8 @@ CustomRefCountingOperationResult CustomRefCountingOperation::evaluate( if (retainReleaseAttrs.size() > 1) return {CustomRefCountingOperationResult::tooManyAttributes, nullptr, ""}; - auto name = retainReleaseAttrs.front() - ->getAttribute() - .drop_front(StringRef(operationStr).size()) - .str(); + auto name = retainReleaseAttrs.front()->getAttribute().drop_front( + operationStr.size()); if (name == "immortal") return {CustomRefCountingOperationResult::immortal, nullptr, name}; diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index a08fd146e3f83..ef68b9a077e20 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -2190,6 +2190,39 @@ namespace { return true; } + std::pair + addRefCountOperationsIfRequired(ClassDecl *nominal, + clang::RecordDecl *clangType) { + auto &context = Impl.SwiftContext; + auto nonInheritedRefCountingOperations = [&] { + auto retainResult = evaluateOrDefault( + context.evaluator, + CustomRefCountingOperation( + {nominal, CustomRefCountingOperationKind::retain}), + {}); + auto releaseResult = evaluateOrDefault( + context.evaluator, + CustomRefCountingOperation( + {nominal, CustomRefCountingOperationKind::release}), + {}); + return std::make_pair(retainResult, releaseResult); + }; + auto clangDecl = dyn_cast(clangType); + if (!clangDecl) + return nonInheritedRefCountingOperations(); + auto baseClangDecl = dyn_cast_or_null( + getRefParentOrDiag(clangDecl, context, nullptr)); + if (!baseClangDecl || baseClangDecl == clangDecl) + return nonInheritedRefCountingOperations(); + + auto baseSwiftDecl = cast( + Impl.importDecl(baseClangDecl, getActiveSwiftVersion())); + + return synthesizer.addRefCountOperations(nominal, clangDecl, + baseSwiftDecl, baseClangDecl); + } + Decl *VisitRecordDecl(const clang::RecordDecl *decl) { // Track whether this record contains fields we can't reference in Swift // as stored properties. @@ -2786,7 +2819,11 @@ namespace { } if (auto classDecl = dyn_cast(result)) { - validateForeignReferenceType(decl, classDecl); + auto operations = addRefCountOperationsIfRequired( + classDecl, const_cast(decl)); + + validateForeignReferenceType(decl, classDecl, operations.first, + operations.second); auto availability = Impl.SwiftContext.getSwift58Availability(); if (!availability.isAlwaysAvailable()) { @@ -2853,8 +2890,10 @@ namespace { } } - void validateForeignReferenceType(const clang::RecordDecl *decl, - ClassDecl *classDecl) { + void validateForeignReferenceType( + const clang::RecordDecl *decl, ClassDecl *classDecl, + CustomRefCountingOperationResult retainOperation, + CustomRefCountingOperationResult releaseOperation) { enum class RetainReleaseOperationKind { notAfunction, @@ -2937,11 +2976,6 @@ namespace { return RetainReleaseOperationKind::valid; }; - auto retainOperation = evaluateOrDefault( - Impl.SwiftContext.evaluator, - CustomRefCountingOperation( - {classDecl, CustomRefCountingOperationKind::retain}), - {}); if (retainOperation.kind == CustomRefCountingOperationResult::noAttribute) { HeaderLoc loc(decl->getLocation()); @@ -3008,11 +3042,6 @@ namespace { CustomRefCountingOperationResult::immortal); } - auto releaseOperation = evaluateOrDefault( - Impl.SwiftContext.evaluator, - CustomRefCountingOperation( - {classDecl, CustomRefCountingOperationKind::release}), - {}); if (releaseOperation.kind == CustomRefCountingOperationResult::noAttribute) { HeaderLoc loc(decl->getLocation()); diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index 0fe49e8994d4f..1d9db14f06a7c 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -48,6 +48,7 @@ #include "clang/Serialization/ModuleFileExtension.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallBitVector.h" @@ -692,6 +693,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation // Map all cloned methods back to the original member llvm::DenseMap clonedMembers; + llvm::DenseSet membersSynthesizedPerType; // Keep track of methods that are unavailale in each class. // We need this set because these methods will be imported lazily. We don't @@ -714,6 +716,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation ClangInheritanceInfo inheritance); ValueDecl *getOriginalForClonedMember(const ValueDecl *decl); + bool isMemberSynthesizedPerType(const ValueDecl *decl); + void markMemberSynthesizedPerType(const ValueDecl *decl); static size_t getImportedBaseMemberDeclArity(const ValueDecl *valueDecl); @@ -2231,6 +2235,11 @@ getImplicitObjectParamAnnotation(const clang::FunctionDecl *FD) { return nullptr; } +/// Find a unique base class that is annotated as SHARED_REFERENCE if any. +const clang::RecordDecl * +getRefParentOrDiag(const clang::RecordDecl *decl, ASTContext &ctx, + ClangImporter::Implementation *importerImpl); + } // end namespace importer } // end namespace swift diff --git a/lib/ClangImporter/SwiftDeclSynthesizer.cpp b/lib/ClangImporter/SwiftDeclSynthesizer.cpp index 87f593d75a5a7..efe115322f9f6 100644 --- a/lib/ClangImporter/SwiftDeclSynthesizer.cpp +++ b/lib/ClangImporter/SwiftDeclSynthesizer.cpp @@ -27,15 +27,21 @@ #include "swift/Basic/Assertions.h" #include "swift/Basic/SourceLoc.h" #include "swift/ClangImporter/ClangImporterRequests.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Attrs.inc" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/Mangle.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/Stmt.h" #include "clang/AST/Type.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/Sema.h" using namespace swift; using namespace importer; @@ -3559,6 +3565,138 @@ void SwiftDeclSynthesizer::addExplicitDeinitIfRequired( nominal->addMember(destructor); } +static void cloneReferenceAttributes(const clang::CXXRecordDecl *from, + clang::CXXRecordDecl *to, + clang::ASTContext &ctx) { + if (!from->hasAttr()) + return; + for (auto attr : from->getAttrs()) { + if (auto swiftAttr = dyn_cast(attr)) { + if (swiftAttr->getAttribute().starts_with("release:")) + to->addAttr( + clang::SwiftAttrAttr::Create(ctx, swiftAttr->getAttribute())); + else if (swiftAttr->getAttribute().starts_with("retain:")) + to->addAttr( + clang::SwiftAttrAttr::Create(ctx, swiftAttr->getAttribute())); + } + } +} + +std::pair +SwiftDeclSynthesizer::addRefCountOperations( + ClassDecl *decl, clang::CXXRecordDecl *clangDecl, const ClassDecl *baseDecl, + const clang::CXXRecordDecl *baseClangDecl) { + auto &context = ImporterImpl.SwiftContext; + auto &clangCtx = ImporterImpl.getClangASTContext(); + auto retainResult = + evaluateOrDefault(context.evaluator, + CustomRefCountingOperation( + {baseDecl, CustomRefCountingOperationKind::retain}), + {}); + auto releaseResult = evaluateOrDefault( + context.evaluator, + CustomRefCountingOperation( + {baseDecl, CustomRefCountingOperationKind::release}), + {}); + if (retainResult.kind == CustomRefCountingOperationResult::immortal || + releaseResult.kind == CustomRefCountingOperationResult::immortal) { + cloneReferenceAttributes(baseClangDecl, clangDecl, clangCtx); + return std::make_pair(retainResult, releaseResult); + } + if (!retainResult.operation || !releaseResult.operation) + return std::make_pair(retainResult, releaseResult); + auto retainClangFn = + cast(retainResult.operation->getClangDecl()); + auto releaseClangFn = + cast(releaseResult.operation->getClangDecl()); + + // Synthesize forwarding function. + auto &clangSema = ImporterImpl.getClangSema(); + + clang::QualType methodType = clangCtx.getFunctionType( + clangCtx.VoidTy, {}, clang::FunctionProtoType::ExtProtoInfo{}); + + auto generateLifetimeOperation = + [&](const clang::FunctionDecl *fd) -> const clang::CXXMethodDecl * { + auto loc = fd->getLocation(); + auto &ident = clangCtx.Idents.get("__synthesized_lifetimeAccessor_" + + fd->getNameAsString()); + clang::DeclarationName methodName(&ident); + auto method = clang::CXXMethodDecl::Create( + clangCtx, clangDecl, fd->getSourceRange().getBegin(), + clang::DeclarationNameInfo(methodName, clang::SourceLocation()), + methodType, clangCtx.getTrivialTypeSourceInfo(methodType), + clang::SC_None, + /*usesFPIntrin=*/false, /*isInline=*/true, + clang::ConstexprSpecKind::Unspecified, fd->getSourceRange().getEnd()); + method->setImplicit(); + method->setImplicitlyInline(); + method->setAccess(clang::AccessSpecifier::AS_public); + method->addAttr(clang::NoDebugAttr::CreateImplicit(clangCtx)); + + clang::Expr *argExpr = + clang::CXXThisExpr::Create(clangCtx, clang::SourceLocation(), + method->getThisType(), /*IsImplicit=*/false); + + if (auto calledMethod = dyn_cast(fd)) { + if (calledMethod->isStatic()) + return nullptr; + auto memberExpr = clangSema.BuildMemberExpr( + argExpr, /*isArrow=*/true, loc, clang::NestedNameSpecifierLoc(), + clang::SourceLocation(), + const_cast(calledMethod), + clang::DeclAccessPair::make( + const_cast(calledMethod), + clang::AS_public), + /*HadMultipleCandidates=*/false, calledMethod->getNameInfo(), + methodType, clang::VK_PRValue, clang::OK_Ordinary); + auto memberCall = clang::CXXMemberCallExpr::Create( + clangCtx, memberExpr, {}, clangCtx.VoidTy, clang::VK_PRValue, loc, + clang::FPOptionsOverride()); + method->setBody(clang::CompoundStmt::Create( + clangCtx, {memberCall}, clang::FPOptionsOverride(), loc, loc)); + } else { + clang::Expr *fnExpr = clang::DeclRefExpr::Create( + clangCtx, clang::NestedNameSpecifierLoc(), clang::SourceLocation(), + const_cast(fd), + /*RefersToEnclosingVariableOrCapture=*/false, loc, fd->getType(), + clang::VK_LValue); + auto call = + clangSema.BuildCallExpr(nullptr, fnExpr, clang::SourceLocation(), + {argExpr}, clang::SourceLocation()); + method->setBody(clang::CompoundStmt::Create( + clangCtx, {call.get()}, clang::FPOptionsOverride(), loc, loc)); + } + return method; + }; + + auto synthesizedRetain = generateLifetimeOperation(retainClangFn); + auto synthesizedRelease = generateLifetimeOperation(releaseClangFn); + if (!synthesizedRetain || !synthesizedRelease) + return std::make_pair(retainResult, releaseResult); + + // Add attributes to class. + clangDecl->addAttr(clang::SwiftAttrAttr::Create( + clangCtx, + context.AllocateCopy("retain:." + synthesizedRetain->getNameAsString()))); + clangDecl->addAttr(clang::SwiftAttrAttr::Create( + clangCtx, context.AllocateCopy("release:." + + synthesizedRelease->getNameAsString()))); + + // Update the Swift type + auto importRefCountOp = [&](const clang::CXXMethodDecl *op) { + auto importedOp = + cast(context.getClangModuleLoader()->importDeclDirectly(op)); + ImporterImpl.markMemberSynthesizedPerType(importedOp); + decl->addMember(importedOp); + decl->addMemberToLookupTable(importedOp); + }; + importRefCountOp(synthesizedRetain); + importRefCountOp(synthesizedRelease); + + return std::make_pair(retainResult, releaseResult); +} + FuncDecl *SwiftDeclSynthesizer::makeAvailabilityDomainPredicate( const clang::VarDecl *var) { ASTContext &ctx = ImporterImpl.SwiftContext; diff --git a/lib/ClangImporter/SwiftDeclSynthesizer.h b/lib/ClangImporter/SwiftDeclSynthesizer.h index a9e7e27284065..5f74048cd370a 100644 --- a/lib/ClangImporter/SwiftDeclSynthesizer.h +++ b/lib/ClangImporter/SwiftDeclSynthesizer.h @@ -16,6 +16,8 @@ #include "ImporterImpl.h" #include "swift/AST/Decl.h" #include "swift/ClangImporter/ClangImporter.h" +#include "swift/ClangImporter/ClangImporterRequests.h" +#include "clang/AST/DeclCXX.h" namespace swift { @@ -356,6 +358,14 @@ class SwiftDeclSynthesizer { void addExplicitDeinitIfRequired( NominalTypeDecl *nominal, const clang::RecordDecl *clangType); + /// When a base class is marked as SHARED_REFERENCE, synthesize a call to + /// the ref counting operations. This call does the derived to base conversion + /// that is responsible for all the offset adjustments on the pointer. + std::pair + addRefCountOperations(ClassDecl *decl, clang::CXXRecordDecl *clangDecl, + const ClassDecl *baseDecl, + const clang::CXXRecordDecl *baseClangDecl); + /// Synthesize a Swift function that calls the Clang runtime predicate /// function for the availability domain represented by `var`. FuncDecl *makeAvailabilityDomainPredicate(const clang::VarDecl *var); diff --git a/test/Interop/Cxx/foreign-reference/Inputs/inheritance.h b/test/Interop/Cxx/foreign-reference/Inputs/inheritance.h index 144a23dde8414..35505f23c4f84 100644 --- a/test/Interop/Cxx/foreign-reference/Inputs/inheritance.h +++ b/test/Interop/Cxx/foreign-reference/Inputs/inheritance.h @@ -109,8 +109,8 @@ __attribute__((swift_attr("release:immortal"))) ImmortalRefType {}; ImmortalRefType *returnImmortalRefType() { return new ImmortalRefType(); }; struct DerivedFromImmortalRefType : ImmortalRefType {}; -DerivedFromImmortalRefType *returnDerivedFromImmortalRefType() { // expected-note {{annotate 'returnDerivedFromImmortalRefType()' with either SWIFT_RETURNS_RETAINED or SWIFT_RETURNS_UNRETAINED}} - return new DerivedFromImmortalRefType(); +DerivedFromImmortalRefType *returnDerivedFromImmortalRefType() { + return new DerivedFromImmortalRefType(); }; } // namespace ImmortalRefereceExample diff --git a/test/Interop/Cxx/foreign-reference/Inputs/lifetime-operation-methods.h b/test/Interop/Cxx/foreign-reference/Inputs/lifetime-operation-methods.h index 1eac66fbe2cd0..2b8ad9438ade0 100644 --- a/test/Interop/Cxx/foreign-reference/Inputs/lifetime-operation-methods.h +++ b/test/Interop/Cxx/foreign-reference/Inputs/lifetime-operation-methods.h @@ -112,8 +112,8 @@ struct StaticRetainRelease { } SWIFT_SHARED_REFERENCE(.staticRetain, .staticRelease); struct DerivedStaticRetainRelease : StaticRetainRelease { -// expected-error@-1 {{cannot find retain function '.staticRetain' for reference type 'DerivedStaticRetainRelease'}} -// expected-error@-2 {{cannot find release function '.staticRelease' for reference type 'DerivedStaticRetainRelease'}} +// expected-error@-1 {{specified release function '.staticRelease' is a static function; expected an instance function}} +// expected-error@-2 {{specified retain function '.staticRetain' is a static function; expected an instance function}} int secondValue = 1; DerivedStaticRetainRelease(int value, int secondValue) : StaticRetainRelease(value), secondValue(secondValue) {} diff --git a/test/Interop/Cxx/foreign-reference/Inputs/logging-frts.h b/test/Interop/Cxx/foreign-reference/Inputs/logging-frts.h index 08ff830d54ed7..c9f7af84268a2 100644 --- a/test/Interop/Cxx/foreign-reference/Inputs/logging-frts.h +++ b/test/Interop/Cxx/foreign-reference/Inputs/logging-frts.h @@ -85,3 +85,10 @@ class Payload final : public SharedFRT { explicit Payload(int value) : m_value(value) {} int m_value; }; + +struct FirstBase { + int a, b, c; + virtual ~FirstBase() {} +}; + +struct DerivedFRT : FirstBase, SharedFRT {}; diff --git a/test/Interop/Cxx/foreign-reference/frt-non-primary-base.swift b/test/Interop/Cxx/foreign-reference/frt-non-primary-base.swift new file mode 100644 index 0000000000000..e96517224cdef --- /dev/null +++ b/test/Interop/Cxx/foreign-reference/frt-non-primary-base.swift @@ -0,0 +1,18 @@ +// RUN: %target-run-simple-swift(-I %swift_src_root/lib/ClangImporter/SwiftBridging -I %S/Inputs -cxx-interoperability-mode=default -Xfrontend -disable-availability-checking -Onone) | %FileCheck %s + +// REQUIRES: executable_test + +import LoggingFrts + +func go() { + let frt = DerivedFRT() + let copy = frt +} + +go() + +// CHECK: RefCount: 1, message: Ctor +// CHECK: RefCount: 2, message: retain +// CHECK: RefCount: 1, message: release +// CHECK: RefCount: 0, message: release +// CHECK: RefCount: 0, message: Dtor diff --git a/test/Interop/Cxx/foreign-reference/inheritance-diagnostics.swift b/test/Interop/Cxx/foreign-reference/inheritance-diagnostics.swift index 3803e100483e1..b1f9d9d1cdc08 100644 --- a/test/Interop/Cxx/foreign-reference/inheritance-diagnostics.swift +++ b/test/Interop/Cxx/foreign-reference/inheritance-diagnostics.swift @@ -6,7 +6,7 @@ import Inheritance let _ = ImmortalRefereceExample.returnImmortalRefType() -let _ = ImmortalRefereceExample.returnDerivedFromImmortalRefType() // expected-warning {{cannot infer ownership of foreign reference value returned by 'returnDerivedFromImmortalRefType()'}} +let _ = ImmortalRefereceExample.returnDerivedFromImmortalRefType() let _ = ExplicitAnnotationHasPrecedence1.returnValueType() let _ = ExplicitAnnotationHasPrecedence1.returnRefType() // expected-warning {{cannot infer ownership of foreign reference value returned by 'returnRefType()'}}