|
25 | 25 | #include "swift/AST/ConformanceLookup.h" |
26 | 26 | #include "swift/AST/Decl.h" |
27 | 27 | #include "swift/AST/DiagnosticsClangImporter.h" |
28 | | -#include "swift/ClangImporter/ClangImporter.h" |
29 | 28 | #include "swift/AST/ExistentialLayout.h" |
30 | 29 | #include "swift/AST/Expr.h" |
31 | 30 | #include "swift/AST/GenericEnvironment.h" |
32 | 31 | #include "swift/AST/GenericSignature.h" |
| 32 | +#include "swift/AST/LifetimeDependence.h" |
33 | 33 | #include "swift/AST/Module.h" |
34 | 34 | #include "swift/AST/NameLookup.h" |
35 | 35 | #include "swift/AST/NameLookupRequests.h" |
|
49 | 49 | #include "swift/Basic/StringExtras.h" |
50 | 50 | #include "swift/Basic/Version.h" |
51 | 51 | #include "swift/ClangImporter/CXXMethodBridging.h" |
| 52 | +#include "swift/ClangImporter/ClangImporter.h" |
52 | 53 | #include "swift/ClangImporter/ClangImporterRequests.h" |
53 | 54 | #include "swift/ClangImporter/ClangModule.h" |
54 | 55 | #include "swift/Parse/Lexer.h" |
|
65 | 66 | #include "clang/Sema/Lookup.h" |
66 | 67 |
|
67 | 68 | #include "llvm/ADT/STLExtras.h" |
| 69 | +#include "llvm/ADT/SmallBitVector.h" |
68 | 70 | #include "llvm/ADT/SmallString.h" |
69 | 71 | #include "llvm/ADT/Statistic.h" |
70 | 72 | #include "llvm/ADT/StringExtras.h" |
@@ -3548,19 +3550,20 @@ namespace { |
3548 | 3550 | return true; |
3549 | 3551 | } |
3550 | 3552 |
|
3551 | | - static bool |
3552 | | - implicitObjectParamIsLifetimeBound(const clang::FunctionDecl *FD) { |
| 3553 | + template <typename T> |
| 3554 | + static const T * |
| 3555 | + getImplicitObjectParamAnnotation(const clang::FunctionDecl *FD) { |
3553 | 3556 | const clang::TypeSourceInfo *TSI = FD->getTypeSourceInfo(); |
3554 | 3557 | if (!TSI) |
3555 | | - return false; |
| 3558 | + return nullptr; |
3556 | 3559 | clang::AttributedTypeLoc ATL; |
3557 | 3560 | for (clang::TypeLoc TL = TSI->getTypeLoc(); |
3558 | 3561 | (ATL = TL.getAsAdjusted<clang::AttributedTypeLoc>()); |
3559 | 3562 | TL = ATL.getModifiedLoc()) { |
3560 | | - if (ATL.getAttrAs<clang::LifetimeBoundAttr>()) |
3561 | | - return true; |
| 3563 | + if (auto attr = ATL.getAttrAs<T>()) |
| 3564 | + return attr; |
3562 | 3565 | } |
3563 | | - return false; |
| 3566 | + return nullptr; |
3564 | 3567 | } |
3565 | 3568 |
|
3566 | 3569 | Decl *importFunctionDecl( |
@@ -3872,7 +3875,8 @@ namespace { |
3872 | 3875 | if (selfIsInOut) |
3873 | 3876 | func->setSelfAccessKind(SelfAccessKind::Mutating); |
3874 | 3877 | else { |
3875 | | - if (implicitObjectParamIsLifetimeBound(decl)) |
| 3878 | + if (getImplicitObjectParamAnnotation<clang::LifetimeBoundAttr>( |
| 3879 | + decl)) |
3876 | 3880 | func->setSelfAccessKind(SelfAccessKind::Borrowing); |
3877 | 3881 | else |
3878 | 3882 | func->setSelfAccessKind(SelfAccessKind::NonMutating); |
@@ -3964,26 +3968,68 @@ namespace { |
3964 | 3968 | auto swiftParams = result->getParameters(); |
3965 | 3969 | bool hasSelf = |
3966 | 3970 | result->hasImplicitSelfDecl() && !isa<ConstructorDecl>(result); |
3967 | | - SmallBitVector inheritLifetimeParamIndicesForReturn(swiftParams->size() + |
3968 | | - hasSelf); |
3969 | | - SmallBitVector scopedLifetimeParamIndicesForReturn(swiftParams->size() + |
3970 | | - hasSelf); |
3971 | | - for (auto [idx, param] : llvm::enumerate(decl->parameters())) { |
3972 | | - if (param->hasAttr<clang::LifetimeBoundAttr>()) { |
3973 | | - warnForEscapableReturnType(); |
3974 | | - if (swiftParams->get(idx)->getInterfaceType()->isEscapable()) |
3975 | | - scopedLifetimeParamIndicesForReturn[idx] = true; |
3976 | | - else |
3977 | | - inheritLifetimeParamIndicesForReturn[idx] = true; |
3978 | | - } |
3979 | | - } |
3980 | | - if (implicitObjectParamIsLifetimeBound(decl)) { |
| 3971 | + const auto dependencyVecSize = swiftParams->size() + hasSelf; |
| 3972 | + SmallBitVector inheritLifetimeParamIndicesForReturn(dependencyVecSize); |
| 3973 | + SmallBitVector scopedLifetimeParamIndicesForReturn(dependencyVecSize); |
| 3974 | + std::map<unsigned, SmallBitVector> inheritedArgDependences; |
| 3975 | + auto processLifetimeBound = [&](unsigned idx, Type ty) { |
3981 | 3976 | warnForEscapableReturnType(); |
3982 | | - auto idx = result->getSelfIndex(); |
3983 | | - if (result->getImplicitSelfDecl()->getInterfaceType()->isEscapable()) |
| 3977 | + if (ty->isEscapable()) |
3984 | 3978 | scopedLifetimeParamIndicesForReturn[idx] = true; |
3985 | 3979 | else |
3986 | 3980 | inheritLifetimeParamIndicesForReturn[idx] = true; |
| 3981 | + }; |
| 3982 | + auto processLifetimeCaptureBy = |
| 3983 | + [&](const clang::LifetimeCaptureByAttr *attr, unsigned idx, Type ty) { |
| 3984 | + // FIXME: support scoped lifetimes. This is not straightforward as |
| 3985 | + // const T& is imported as taking a value |
| 3986 | + // and we assume the address of T would not escape. An |
| 3987 | + // annotation in this case contradicts our assumptions. We |
| 3988 | + // should diagnose that, and support this for the non-const |
| 3989 | + // case. |
| 3990 | + if (ty->isEscapable()) |
| 3991 | + return; |
| 3992 | + for (auto param : attr->params()) { |
| 3993 | + // FIXME: Swift assumes no escaping to globals. We should diagnose |
| 3994 | + // this. |
| 3995 | + if (param == clang::LifetimeCaptureByAttr::GLOBAL || |
| 3996 | + param == clang::LifetimeCaptureByAttr::UNKNOWN || |
| 3997 | + param == clang::LifetimeCaptureByAttr::INVALID) |
| 3998 | + continue; |
| 3999 | + |
| 4000 | + if (isa<clang::CXXMethodDecl>(decl) && |
| 4001 | + param == clang::LifetimeCaptureByAttr::THIS) { |
| 4002 | + auto [it, inserted] = inheritedArgDependences.try_emplace( |
| 4003 | + result->getSelfIndex(), SmallBitVector(dependencyVecSize)); |
| 4004 | + it->second[idx] = true; |
| 4005 | + } else { |
| 4006 | + auto [it, inserted] = inheritedArgDependences.try_emplace( |
| 4007 | + param - isa<clang::CXXMethodDecl>(decl), |
| 4008 | + SmallBitVector(dependencyVecSize)); |
| 4009 | + it->second[idx] = true; |
| 4010 | + } |
| 4011 | + } |
| 4012 | + }; |
| 4013 | + for (auto [idx, param] : llvm::enumerate(decl->parameters())) { |
| 4014 | + if (param->hasAttr<clang::LifetimeBoundAttr>()) |
| 4015 | + processLifetimeBound(idx, swiftParams->get(idx)->getInterfaceType()); |
| 4016 | + if (const auto *attr = param->getAttr<clang::LifetimeCaptureByAttr>()) |
| 4017 | + processLifetimeCaptureBy(attr, idx, |
| 4018 | + swiftParams->get(idx)->getInterfaceType()); |
| 4019 | + } |
| 4020 | + if (getImplicitObjectParamAnnotation<clang::LifetimeBoundAttr>(decl)) |
| 4021 | + processLifetimeBound(result->getSelfIndex(), |
| 4022 | + result->getImplicitSelfDecl()->getInterfaceType()); |
| 4023 | + if (auto attr = |
| 4024 | + getImplicitObjectParamAnnotation<clang::LifetimeCaptureByAttr>( |
| 4025 | + decl)) |
| 4026 | + processLifetimeCaptureBy( |
| 4027 | + attr, result->getSelfIndex(), |
| 4028 | + result->getImplicitSelfDecl()->getInterfaceType()); |
| 4029 | + |
| 4030 | + for (auto& [idx, inheritedDepVec]: inheritedArgDependences) { |
| 4031 | + lifetimeDependencies.push_back(LifetimeDependenceInfo(inheritedDepVec.any() ? IndexSubset::get(Impl.SwiftContext, |
| 4032 | + inheritedDepVec): nullptr, nullptr, idx, /*isImmortal=*/false)); |
3987 | 4033 | } |
3988 | 4034 |
|
3989 | 4035 | if (inheritLifetimeParamIndicesForReturn.any() || |
|
0 commit comments