|
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