|
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"
|
@@ -3545,19 +3547,20 @@ namespace {
|
3545 | 3547 | return true;
|
3546 | 3548 | }
|
3547 | 3549 |
|
3548 |
| - static bool |
3549 |
| - implicitObjectParamIsLifetimeBound(const clang::FunctionDecl *FD) { |
| 3550 | + template <typename T> |
| 3551 | + static const T * |
| 3552 | + getImplicitObjectParamAnnotation(const clang::FunctionDecl *FD) { |
3550 | 3553 | const clang::TypeSourceInfo *TSI = FD->getTypeSourceInfo();
|
3551 | 3554 | if (!TSI)
|
3552 |
| - return false; |
| 3555 | + return nullptr; |
3553 | 3556 | clang::AttributedTypeLoc ATL;
|
3554 | 3557 | for (clang::TypeLoc TL = TSI->getTypeLoc();
|
3555 | 3558 | (ATL = TL.getAsAdjusted<clang::AttributedTypeLoc>());
|
3556 | 3559 | TL = ATL.getModifiedLoc()) {
|
3557 |
| - if (ATL.getAttrAs<clang::LifetimeBoundAttr>()) |
3558 |
| - return true; |
| 3560 | + if (auto attr = ATL.getAttrAs<T>()) |
| 3561 | + return attr; |
3559 | 3562 | }
|
3560 |
| - return false; |
| 3563 | + return nullptr; |
3561 | 3564 | }
|
3562 | 3565 |
|
3563 | 3566 | Decl *importFunctionDecl(
|
@@ -3869,7 +3872,8 @@ namespace {
|
3869 | 3872 | if (selfIsInOut)
|
3870 | 3873 | func->setSelfAccessKind(SelfAccessKind::Mutating);
|
3871 | 3874 | else {
|
3872 |
| - if (implicitObjectParamIsLifetimeBound(decl)) |
| 3875 | + if (getImplicitObjectParamAnnotation<clang::LifetimeBoundAttr>( |
| 3876 | + decl)) |
3873 | 3877 | func->setSelfAccessKind(SelfAccessKind::Borrowing);
|
3874 | 3878 | else
|
3875 | 3879 | func->setSelfAccessKind(SelfAccessKind::NonMutating);
|
@@ -3961,26 +3965,68 @@ namespace {
|
3961 | 3965 | auto swiftParams = result->getParameters();
|
3962 | 3966 | bool hasSelf =
|
3963 | 3967 | result->hasImplicitSelfDecl() && !isa<ConstructorDecl>(result);
|
3964 |
| - SmallBitVector inheritLifetimeParamIndicesForReturn(swiftParams->size() + |
3965 |
| - hasSelf); |
3966 |
| - SmallBitVector scopedLifetimeParamIndicesForReturn(swiftParams->size() + |
3967 |
| - hasSelf); |
3968 |
| - for (auto [idx, param] : llvm::enumerate(decl->parameters())) { |
3969 |
| - if (param->hasAttr<clang::LifetimeBoundAttr>()) { |
3970 |
| - warnForEscapableReturnType(); |
3971 |
| - if (swiftParams->get(idx)->getInterfaceType()->isEscapable()) |
3972 |
| - scopedLifetimeParamIndicesForReturn[idx] = true; |
3973 |
| - else |
3974 |
| - inheritLifetimeParamIndicesForReturn[idx] = true; |
3975 |
| - } |
3976 |
| - } |
3977 |
| - if (implicitObjectParamIsLifetimeBound(decl)) { |
| 3968 | + const auto dependencyVecSize = swiftParams->size() + hasSelf; |
| 3969 | + SmallBitVector inheritLifetimeParamIndicesForReturn(dependencyVecSize); |
| 3970 | + SmallBitVector scopedLifetimeParamIndicesForReturn(dependencyVecSize); |
| 3971 | + std::map<unsigned, SmallBitVector> inheritedArgDependences; |
| 3972 | + auto processLifetimeBound = [&](unsigned idx, Type ty) { |
3978 | 3973 | warnForEscapableReturnType();
|
3979 |
| - auto idx = result->getSelfIndex(); |
3980 |
| - if (result->getImplicitSelfDecl()->getInterfaceType()->isEscapable()) |
| 3974 | + if (ty->isEscapable()) |
3981 | 3975 | scopedLifetimeParamIndicesForReturn[idx] = true;
|
3982 | 3976 | else
|
3983 | 3977 | inheritLifetimeParamIndicesForReturn[idx] = true;
|
| 3978 | + }; |
| 3979 | + auto processLifetimeCaptureBy = |
| 3980 | + [&](const clang::LifetimeCaptureByAttr *attr, unsigned idx, Type ty) { |
| 3981 | + // FIXME: support scoped lifetimes. This is not straightforward as |
| 3982 | + // const T& is imported as taking a value |
| 3983 | + // and we assume the address of T would not escape. An |
| 3984 | + // annotation in this case contradicts our assumptions. We |
| 3985 | + // should diagnose that, and support this for the non-const |
| 3986 | + // case. |
| 3987 | + if (ty->isEscapable()) |
| 3988 | + return; |
| 3989 | + for (auto param : attr->params()) { |
| 3990 | + // FIXME: Swift assumes no escaping to globals. We should diagnose |
| 3991 | + // this. |
| 3992 | + if (param == clang::LifetimeCaptureByAttr::GLOBAL || |
| 3993 | + param == clang::LifetimeCaptureByAttr::UNKNOWN || |
| 3994 | + param == clang::LifetimeCaptureByAttr::INVALID) |
| 3995 | + continue; |
| 3996 | + |
| 3997 | + if (isa<clang::CXXMethodDecl>(decl) && |
| 3998 | + param == clang::LifetimeCaptureByAttr::THIS) { |
| 3999 | + auto [it, inserted] = inheritedArgDependences.try_emplace( |
| 4000 | + result->getSelfIndex(), SmallBitVector(dependencyVecSize)); |
| 4001 | + it->second[idx] = true; |
| 4002 | + } else { |
| 4003 | + auto [it, inserted] = inheritedArgDependences.try_emplace( |
| 4004 | + param - isa<clang::CXXMethodDecl>(decl), |
| 4005 | + SmallBitVector(dependencyVecSize)); |
| 4006 | + it->second[idx] = true; |
| 4007 | + } |
| 4008 | + } |
| 4009 | + }; |
| 4010 | + for (auto [idx, param] : llvm::enumerate(decl->parameters())) { |
| 4011 | + if (param->hasAttr<clang::LifetimeBoundAttr>()) |
| 4012 | + processLifetimeBound(idx, swiftParams->get(idx)->getInterfaceType()); |
| 4013 | + if (const auto *attr = param->getAttr<clang::LifetimeCaptureByAttr>()) |
| 4014 | + processLifetimeCaptureBy(attr, idx, |
| 4015 | + swiftParams->get(idx)->getInterfaceType()); |
| 4016 | + } |
| 4017 | + if (getImplicitObjectParamAnnotation<clang::LifetimeBoundAttr>(decl)) |
| 4018 | + processLifetimeBound(result->getSelfIndex(), |
| 4019 | + result->getImplicitSelfDecl()->getInterfaceType()); |
| 4020 | + if (auto attr = |
| 4021 | + getImplicitObjectParamAnnotation<clang::LifetimeCaptureByAttr>( |
| 4022 | + decl)) |
| 4023 | + processLifetimeCaptureBy( |
| 4024 | + attr, result->getSelfIndex(), |
| 4025 | + result->getImplicitSelfDecl()->getInterfaceType()); |
| 4026 | + |
| 4027 | + for (auto& [idx, inheritedDepVec]: inheritedArgDependences) { |
| 4028 | + lifetimeDependencies.push_back(LifetimeDependenceInfo(inheritedDepVec.any() ? IndexSubset::get(Impl.SwiftContext, |
| 4029 | + inheritedDepVec): nullptr, nullptr, idx, /*isImmortal=*/false)); |
3984 | 4030 | }
|
3985 | 4031 |
|
3986 | 4032 | if (inheritLifetimeParamIndicesForReturn.any() ||
|
|
0 commit comments