|
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"
|
@@ -3474,6 +3475,21 @@ namespace {
|
3474 | 3475 | return true;
|
3475 | 3476 | }
|
3476 | 3477 |
|
| 3478 | + static bool |
| 3479 | + implicitObjectParamIsLifetimeBound(const clang::FunctionDecl *FD) { |
| 3480 | + const clang::TypeSourceInfo *TSI = FD->getTypeSourceInfo(); |
| 3481 | + if (!TSI) |
| 3482 | + return false; |
| 3483 | + clang::AttributedTypeLoc ATL; |
| 3484 | + for (clang::TypeLoc TL = TSI->getTypeLoc(); |
| 3485 | + (ATL = TL.getAsAdjusted<clang::AttributedTypeLoc>()); |
| 3486 | + TL = ATL.getModifiedLoc()) { |
| 3487 | + if (ATL.getAttrAs<clang::LifetimeBoundAttr>()) |
| 3488 | + return true; |
| 3489 | + } |
| 3490 | + return false; |
| 3491 | + } |
| 3492 | + |
3477 | 3493 | Decl *importFunctionDecl(
|
3478 | 3494 | const clang::FunctionDecl *decl, ImportedName importedName,
|
3479 | 3495 | std::optional<ImportedName> correctSwiftName,
|
@@ -3780,8 +3796,12 @@ namespace {
|
3780 | 3796 | if (!dc->isModuleScopeContext()) {
|
3781 | 3797 | if (selfIsInOut)
|
3782 | 3798 | func->setSelfAccessKind(SelfAccessKind::Mutating);
|
3783 |
| - else |
3784 |
| - func->setSelfAccessKind(SelfAccessKind::NonMutating); |
| 3799 | + else { |
| 3800 | + if (implicitObjectParamIsLifetimeBound(decl)) |
| 3801 | + func->setSelfAccessKind(SelfAccessKind::Borrowing); |
| 3802 | + else |
| 3803 | + func->setSelfAccessKind(SelfAccessKind::NonMutating); |
| 3804 | + } |
3785 | 3805 | if (selfIdx) {
|
3786 | 3806 | func->setSelfIndex(selfIdx.value());
|
3787 | 3807 | } else {
|
@@ -3820,13 +3840,70 @@ namespace {
|
3820 | 3840 | return result;
|
3821 | 3841 | }
|
3822 | 3842 |
|
| 3843 | + void addLifetimeDependencies(const clang::FunctionDecl *decl, |
| 3844 | + AbstractFunctionDecl *result) { |
| 3845 | + if (decl->getTemplatedKind() == clang::FunctionDecl::TK_FunctionTemplate) |
| 3846 | + return; |
| 3847 | + |
| 3848 | + auto swiftParams = result->getParameters(); |
| 3849 | + bool hasSelf = result->hasImplicitSelfDecl(); |
| 3850 | + SmallVector<LifetimeDependenceInfo, 1> lifetimeDependencies; |
| 3851 | + SmallBitVector inheritLifetimeParamIndicesForReturn(swiftParams->size() + |
| 3852 | + hasSelf); |
| 3853 | + SmallBitVector scopedLifetimeParamIndicesForReturn(swiftParams->size() + |
| 3854 | + hasSelf); |
| 3855 | + for (auto [idx, param] : llvm::enumerate(decl->parameters())) { |
| 3856 | + if (param->hasAttr<clang::LifetimeBoundAttr>()) { |
| 3857 | + if (swiftParams->get(idx)->getInterfaceType()->isEscapable()) |
| 3858 | + scopedLifetimeParamIndicesForReturn[idx] = true; |
| 3859 | + else |
| 3860 | + inheritLifetimeParamIndicesForReturn[idx] = true; |
| 3861 | + } |
| 3862 | + } |
| 3863 | + if (implicitObjectParamIsLifetimeBound(decl)) { |
| 3864 | + auto idx = result->getSelfIndex(); |
| 3865 | + if (result->getImplicitSelfDecl()->getInterfaceType()->isEscapable()) |
| 3866 | + scopedLifetimeParamIndicesForReturn[idx] = true; |
| 3867 | + else |
| 3868 | + inheritLifetimeParamIndicesForReturn[idx] = true; |
| 3869 | + } |
| 3870 | + |
| 3871 | + if (inheritLifetimeParamIndicesForReturn.any() || |
| 3872 | + scopedLifetimeParamIndicesForReturn.any()) |
| 3873 | + lifetimeDependencies.push_back(LifetimeDependenceInfo( |
| 3874 | + inheritLifetimeParamIndicesForReturn.any() |
| 3875 | + ? IndexSubset::get(Impl.SwiftContext, |
| 3876 | + inheritLifetimeParamIndicesForReturn) |
| 3877 | + : nullptr, |
| 3878 | + scopedLifetimeParamIndicesForReturn.any() |
| 3879 | + ? IndexSubset::get(Impl.SwiftContext, |
| 3880 | + scopedLifetimeParamIndicesForReturn) |
| 3881 | + : nullptr, |
| 3882 | + swiftParams->size(), |
| 3883 | + /*isImmortal*/ false)); |
| 3884 | + else if (auto *ctordecl = dyn_cast<clang::CXXConstructorDecl>(decl)) { |
| 3885 | + // Assume default constructed view types have no dependencies. |
| 3886 | + if (ctordecl->isDefaultConstructor() && |
| 3887 | + importer::hasNonEscapableAttr(ctordecl->getParent())) |
| 3888 | + lifetimeDependencies.push_back( |
| 3889 | + LifetimeDependenceInfo(nullptr, nullptr, 0, /*isImmortal*/ true)); |
| 3890 | + } |
| 3891 | + if (!lifetimeDependencies.empty()) { |
| 3892 | + Impl.SwiftContext.evaluator.cacheOutput( |
| 3893 | + LifetimeDependenceInfoRequest{result}, |
| 3894 | + Impl.SwiftContext.AllocateCopy(lifetimeDependencies)); |
| 3895 | + } |
| 3896 | + } |
| 3897 | + |
3823 | 3898 | void finishFuncDecl(const clang::FunctionDecl *decl,
|
3824 | 3899 | AbstractFunctionDecl *result) {
|
3825 | 3900 | // Set availability.
|
3826 | 3901 | if (decl->isVariadic()) {
|
3827 | 3902 | Impl.markUnavailable(result, "Variadic function is unavailable");
|
3828 | 3903 | }
|
3829 | 3904 |
|
| 3905 | + addLifetimeDependencies(decl, result); |
| 3906 | + |
3830 | 3907 | if (decl->hasAttr<clang::ReturnsTwiceAttr>()) {
|
3831 | 3908 | // The Clang 'returns_twice' attribute is used for functions like
|
3832 | 3909 | // 'vfork' or 'setjmp'. Because these functions may return control flow
|
|
0 commit comments