|
15 | 15 | //===----------------------------------------------------------------------===//
|
16 | 16 |
|
17 | 17 | #include "CFTypeInfo.h"
|
18 |
| -#include "ImporterImpl.h" |
19 | 18 | #include "ClangDerivedConformances.h"
|
| 19 | +#include "ImporterImpl.h" |
20 | 20 | #include "SwiftDeclSynthesizer.h"
|
21 | 21 | #include "swift/AST/ASTContext.h"
|
22 | 22 | #include "swift/AST/Attr.h"
|
|
53 | 53 | #include "swift/Strings.h"
|
54 | 54 | #include "clang/AST/ASTContext.h"
|
55 | 55 | #include "clang/AST/Attr.h"
|
| 56 | +#include "clang/AST/Decl.h" |
56 | 57 | #include "clang/AST/DeclCXX.h"
|
57 | 58 | #include "clang/AST/DeclObjCCommon.h"
|
58 | 59 | #include "clang/Basic/Specifiers.h"
|
@@ -3396,6 +3397,21 @@ namespace {
|
3396 | 3397 | return true;
|
3397 | 3398 | }
|
3398 | 3399 |
|
| 3400 | + static bool |
| 3401 | + implicitObjectParamIsLifetimeBound(const clang::FunctionDecl *FD) { |
| 3402 | + const clang::TypeSourceInfo *TSI = FD->getTypeSourceInfo(); |
| 3403 | + if (!TSI) |
| 3404 | + return false; |
| 3405 | + clang::AttributedTypeLoc ATL; |
| 3406 | + for (clang::TypeLoc TL = TSI->getTypeLoc(); |
| 3407 | + (ATL = TL.getAsAdjusted<clang::AttributedTypeLoc>()); |
| 3408 | + TL = ATL.getModifiedLoc()) { |
| 3409 | + if (ATL.getAttrAs<clang::LifetimeBoundAttr>()) |
| 3410 | + return true; |
| 3411 | + } |
| 3412 | + return false; |
| 3413 | + } |
| 3414 | + |
3399 | 3415 | Decl *importFunctionDecl(
|
3400 | 3416 | const clang::FunctionDecl *decl, ImportedName importedName,
|
3401 | 3417 | std::optional<ImportedName> correctSwiftName,
|
@@ -3702,8 +3718,12 @@ namespace {
|
3702 | 3718 | if (!dc->isModuleScopeContext()) {
|
3703 | 3719 | if (selfIsInOut)
|
3704 | 3720 | func->setSelfAccessKind(SelfAccessKind::Mutating);
|
3705 |
| - else |
3706 |
| - func->setSelfAccessKind(SelfAccessKind::NonMutating); |
| 3721 | + else { |
| 3722 | + if (implicitObjectParamIsLifetimeBound(decl)) |
| 3723 | + func->setSelfAccessKind(SelfAccessKind::Borrowing); |
| 3724 | + else |
| 3725 | + func->setSelfAccessKind(SelfAccessKind::NonMutating); |
| 3726 | + } |
3707 | 3727 | if (selfIdx) {
|
3708 | 3728 | func->setSelfIndex(selfIdx.value());
|
3709 | 3729 | } else {
|
@@ -3742,13 +3762,70 @@ namespace {
|
3742 | 3762 | return result;
|
3743 | 3763 | }
|
3744 | 3764 |
|
| 3765 | + void addLifetimeDependencies(const clang::FunctionDecl *decl, |
| 3766 | + AbstractFunctionDecl *result) { |
| 3767 | + if (decl->getTemplatedKind() == clang::FunctionDecl::TK_FunctionTemplate) |
| 3768 | + return; |
| 3769 | + |
| 3770 | + auto swiftParams = result->getParameters(); |
| 3771 | + bool hasSelf = result->hasImplicitSelfDecl(); |
| 3772 | + SmallVector<LifetimeDependenceInfo, 1> lifetimeDependencies; |
| 3773 | + SmallBitVector inheritLifetimeParamIndicesForReturn(swiftParams->size() + |
| 3774 | + hasSelf); |
| 3775 | + SmallBitVector scopedLifetimeParamIndicesForReturn(swiftParams->size() + |
| 3776 | + hasSelf); |
| 3777 | + for (auto [idx, param] : llvm::enumerate(decl->parameters())) { |
| 3778 | + if (param->hasAttr<clang::LifetimeBoundAttr>()) { |
| 3779 | + if (swiftParams->get(idx)->getInterfaceType()->isEscapable()) |
| 3780 | + scopedLifetimeParamIndicesForReturn[idx] = true; |
| 3781 | + else |
| 3782 | + inheritLifetimeParamIndicesForReturn[idx] = true; |
| 3783 | + } |
| 3784 | + } |
| 3785 | + if (implicitObjectParamIsLifetimeBound(decl)) { |
| 3786 | + auto idx = result->getSelfIndex(); |
| 3787 | + if (result->getImplicitSelfDecl()->getInterfaceType()->isEscapable()) |
| 3788 | + scopedLifetimeParamIndicesForReturn[idx] = true; |
| 3789 | + else |
| 3790 | + inheritLifetimeParamIndicesForReturn[idx] = true; |
| 3791 | + } |
| 3792 | + |
| 3793 | + if (inheritLifetimeParamIndicesForReturn.any() || |
| 3794 | + scopedLifetimeParamIndicesForReturn.any()) |
| 3795 | + lifetimeDependencies.push_back(LifetimeDependenceInfo( |
| 3796 | + inheritLifetimeParamIndicesForReturn.any() |
| 3797 | + ? IndexSubset::get(Impl.SwiftContext, |
| 3798 | + inheritLifetimeParamIndicesForReturn) |
| 3799 | + : nullptr, |
| 3800 | + scopedLifetimeParamIndicesForReturn.any() |
| 3801 | + ? IndexSubset::get(Impl.SwiftContext, |
| 3802 | + scopedLifetimeParamIndicesForReturn) |
| 3803 | + : nullptr, |
| 3804 | + swiftParams->size(), |
| 3805 | + /*isImmortal*/ false)); |
| 3806 | + else if (auto *ctordecl = dyn_cast<clang::CXXConstructorDecl>(decl)) { |
| 3807 | + // Assume default constructed view types have no dependencies. |
| 3808 | + if (ctordecl->isDefaultConstructor() && |
| 3809 | + importer::hasNonEscapableAttr(ctordecl->getParent())) |
| 3810 | + lifetimeDependencies.push_back( |
| 3811 | + LifetimeDependenceInfo(nullptr, nullptr, 0, /*isImmortal*/ true)); |
| 3812 | + } |
| 3813 | + if (!lifetimeDependencies.empty()) { |
| 3814 | + Impl.SwiftContext.evaluator.cacheOutput( |
| 3815 | + LifetimeDependenceInfoRequest{result}, |
| 3816 | + Impl.SwiftContext.AllocateCopy(lifetimeDependencies)); |
| 3817 | + } |
| 3818 | + } |
| 3819 | + |
3745 | 3820 | void finishFuncDecl(const clang::FunctionDecl *decl,
|
3746 | 3821 | AbstractFunctionDecl *result) {
|
3747 | 3822 | // Set availability.
|
3748 | 3823 | if (decl->isVariadic()) {
|
3749 | 3824 | Impl.markUnavailable(result, "Variadic function is unavailable");
|
3750 | 3825 | }
|
3751 | 3826 |
|
| 3827 | + addLifetimeDependencies(decl, result); |
| 3828 | + |
3752 | 3829 | if (decl->hasAttr<clang::ReturnsTwiceAttr>()) {
|
3753 | 3830 | // The Clang 'returns_twice' attribute is used for functions like
|
3754 | 3831 | // 'vfork' or 'setjmp'. Because these functions may return control flow
|
|
0 commit comments