mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[cxx-interop] Teach importer to interpret lifetimebound annotations
The lifetimebound annotations are now imported as lifetime dependencies. This works for basic cases but there are still some parts missing: * Support lifeitmebound annotations on constructors * A way to represent immortal/static lifetimes on the C++ side
This commit is contained in:
@@ -15,8 +15,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CFTypeInfo.h"
|
||||
#include "ImporterImpl.h"
|
||||
#include "ClangDerivedConformances.h"
|
||||
#include "ImporterImpl.h"
|
||||
#include "SwiftDeclSynthesizer.h"
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/Attr.h"
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "swift/Strings.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclObjCCommon.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
@@ -3474,6 +3475,21 @@ namespace {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
implicitObjectParamIsLifetimeBound(const clang::FunctionDecl *FD) {
|
||||
const clang::TypeSourceInfo *TSI = FD->getTypeSourceInfo();
|
||||
if (!TSI)
|
||||
return false;
|
||||
clang::AttributedTypeLoc ATL;
|
||||
for (clang::TypeLoc TL = TSI->getTypeLoc();
|
||||
(ATL = TL.getAsAdjusted<clang::AttributedTypeLoc>());
|
||||
TL = ATL.getModifiedLoc()) {
|
||||
if (ATL.getAttrAs<clang::LifetimeBoundAttr>())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Decl *importFunctionDecl(
|
||||
const clang::FunctionDecl *decl, ImportedName importedName,
|
||||
std::optional<ImportedName> correctSwiftName,
|
||||
@@ -3780,8 +3796,12 @@ namespace {
|
||||
if (!dc->isModuleScopeContext()) {
|
||||
if (selfIsInOut)
|
||||
func->setSelfAccessKind(SelfAccessKind::Mutating);
|
||||
else
|
||||
func->setSelfAccessKind(SelfAccessKind::NonMutating);
|
||||
else {
|
||||
if (implicitObjectParamIsLifetimeBound(decl))
|
||||
func->setSelfAccessKind(SelfAccessKind::Borrowing);
|
||||
else
|
||||
func->setSelfAccessKind(SelfAccessKind::NonMutating);
|
||||
}
|
||||
if (selfIdx) {
|
||||
func->setSelfIndex(selfIdx.value());
|
||||
} else {
|
||||
@@ -3820,6 +3840,61 @@ namespace {
|
||||
return result;
|
||||
}
|
||||
|
||||
void addLifetimeDependencies(const clang::FunctionDecl *decl,
|
||||
AbstractFunctionDecl *result) {
|
||||
if (decl->getTemplatedKind() == clang::FunctionDecl::TK_FunctionTemplate)
|
||||
return;
|
||||
|
||||
auto swiftParams = result->getParameters();
|
||||
bool hasSelf = result->hasImplicitSelfDecl();
|
||||
SmallVector<LifetimeDependenceInfo, 1> lifetimeDependencies;
|
||||
SmallBitVector inheritLifetimeParamIndicesForReturn(swiftParams->size() +
|
||||
hasSelf);
|
||||
SmallBitVector scopedLifetimeParamIndicesForReturn(swiftParams->size() +
|
||||
hasSelf);
|
||||
for (auto [idx, param] : llvm::enumerate(decl->parameters())) {
|
||||
if (param->hasAttr<clang::LifetimeBoundAttr>()) {
|
||||
if (swiftParams->get(idx)->getInterfaceType()->isEscapable())
|
||||
scopedLifetimeParamIndicesForReturn[idx] = true;
|
||||
else
|
||||
inheritLifetimeParamIndicesForReturn[idx] = true;
|
||||
}
|
||||
}
|
||||
if (implicitObjectParamIsLifetimeBound(decl)) {
|
||||
auto idx = result->getSelfIndex();
|
||||
if (result->getImplicitSelfDecl()->getInterfaceType()->isEscapable())
|
||||
scopedLifetimeParamIndicesForReturn[idx] = true;
|
||||
else
|
||||
inheritLifetimeParamIndicesForReturn[idx] = true;
|
||||
}
|
||||
|
||||
if (inheritLifetimeParamIndicesForReturn.any() ||
|
||||
scopedLifetimeParamIndicesForReturn.any())
|
||||
lifetimeDependencies.push_back(LifetimeDependenceInfo(
|
||||
inheritLifetimeParamIndicesForReturn.any()
|
||||
? IndexSubset::get(Impl.SwiftContext,
|
||||
inheritLifetimeParamIndicesForReturn)
|
||||
: nullptr,
|
||||
scopedLifetimeParamIndicesForReturn.any()
|
||||
? IndexSubset::get(Impl.SwiftContext,
|
||||
scopedLifetimeParamIndicesForReturn)
|
||||
: nullptr,
|
||||
swiftParams->size(),
|
||||
/*isImmortal*/ false));
|
||||
else if (auto *ctordecl = dyn_cast<clang::CXXConstructorDecl>(decl)) {
|
||||
// Assume default constructed view types have no dependencies.
|
||||
if (ctordecl->isDefaultConstructor() &&
|
||||
importer::hasNonEscapableAttr(ctordecl->getParent()))
|
||||
lifetimeDependencies.push_back(
|
||||
LifetimeDependenceInfo(nullptr, nullptr, 0, /*isImmortal*/ true));
|
||||
}
|
||||
if (!lifetimeDependencies.empty()) {
|
||||
Impl.SwiftContext.evaluator.cacheOutput(
|
||||
LifetimeDependenceInfoRequest{result},
|
||||
Impl.SwiftContext.AllocateCopy(lifetimeDependencies));
|
||||
}
|
||||
}
|
||||
|
||||
void finishFuncDecl(const clang::FunctionDecl *decl,
|
||||
AbstractFunctionDecl *result) {
|
||||
// Set availability.
|
||||
@@ -3827,6 +3902,8 @@ namespace {
|
||||
Impl.markUnavailable(result, "Variadic function is unavailable");
|
||||
}
|
||||
|
||||
addLifetimeDependencies(decl, result);
|
||||
|
||||
if (decl->hasAttr<clang::ReturnsTwiceAttr>()) {
|
||||
// The Clang 'returns_twice' attribute is used for functions like
|
||||
// 'vfork' or 'setjmp'. Because these functions may return control flow
|
||||
|
||||
Reference in New Issue
Block a user