[cxx-interop] Import increment operators

C++ pre-increment operator `T& T::operator++()` is mapped into a non-mutating function `successor() -> Self`.

The naming matches existing functions for `UnsafePointer`/`UnsafeMutablePointer`.

The purpose of this is to be used for iterator bridging: C++ requires iterators to define a pre-increment operator (https://en.cppreference.com/w/cpp/named_req/Iterator), which Swift will use to iterate over C++ sequences and collections.
This commit is contained in:
Egor Zhdan
2022-06-18 01:16:52 +01:00
parent 1839ddb115
commit d29b78eed1
8 changed files with 184 additions and 11 deletions

View File

@@ -144,7 +144,7 @@ SwiftDeclSynthesizer::createVarWithPattern(DeclContext *dc, Identifier name,
VarDecl::Introducer introducer,
bool isImplicit, AccessLevel access,
AccessLevel setterAccess) {
ASTContext &ctx = ImporterImpl.SwiftContext;
ASTContext &ctx = dc->getASTContext();
// Create a variable to store the underlying value.
auto var = new (ctx) VarDecl(
@@ -1720,6 +1720,97 @@ VarDecl *SwiftDeclSynthesizer::makeDereferencedPointeeProperty(
return result;
}
// MARK: C++ increment operator
/// Synthesizer callback for a successor function.
///
/// \code
/// var __copy: Self
/// __copy = self
/// __copy.__operatorPlusPlus()
/// return __copy
/// \endcode
static std::pair<BraceStmt *, bool>
synthesizeSuccessorFuncBody(AbstractFunctionDecl *afd, void *context) {
auto successorDecl = cast<FuncDecl>(afd);
auto incrementImpl = static_cast<FuncDecl *>(context);
ASTContext &ctx = successorDecl->getASTContext();
auto emptyTupleTy = TupleType::getEmpty(ctx);
auto returnTy = successorDecl->getResultInterfaceType();
auto selfDecl = successorDecl->getImplicitSelfDecl();
auto selfRefExpr = new (ctx) DeclRefExpr(selfDecl, DeclNameLoc(),
/*implicit*/ true);
selfRefExpr->setType(selfDecl->getInterfaceType());
// Create a `__copy` variable.
VarDecl *copyDecl = nullptr;
PatternBindingDecl *patternDecl = nullptr;
std::tie(copyDecl, patternDecl) = SwiftDeclSynthesizer::createVarWithPattern(
successorDecl, ctx.getIdentifier("__copy"), returnTy,
VarDecl::Introducer::Var,
/*isImplicit*/ true, AccessLevel::Public, AccessLevel::Public);
auto copyRefLValueExpr = new (ctx) DeclRefExpr(copyDecl, DeclNameLoc(),
/*implicit*/ true);
copyRefLValueExpr->setType(LValueType::get(copyDecl->getInterfaceType()));
auto inoutCopyExpr = new (ctx) InOutExpr(
SourceLoc(), copyRefLValueExpr,
successorDecl->mapTypeIntoContext(copyDecl->getValueInterfaceType()),
/*isImplicit*/ true);
inoutCopyExpr->setType(InOutType::get(copyDecl->getInterfaceType()));
// Copy `self` to `__copy`.
auto copyAssignExpr = new (ctx) AssignExpr(copyRefLValueExpr, SourceLoc(),
selfRefExpr, /*implicit*/ true);
copyAssignExpr->setType(emptyTupleTy);
// Call `operator++`.
auto incrementExpr = createAccessorImplCallExpr(incrementImpl, inoutCopyExpr);
auto copyRefRValueExpr = new (ctx) DeclRefExpr(copyDecl, DeclNameLoc(),
/*implicit*/ true);
copyRefRValueExpr->setType(copyDecl->getInterfaceType());
auto returnStmt = new (ctx) ReturnStmt(SourceLoc(), copyRefRValueExpr,
/*implicit*/ true);
auto body = BraceStmt::create(ctx, SourceLoc(),
{
copyDecl,
patternDecl,
copyAssignExpr,
incrementExpr,
returnStmt,
},
SourceLoc());
return {body, /*isTypeChecked*/ true};
}
FuncDecl *SwiftDeclSynthesizer::makeSuccessorFunc(FuncDecl *incrementFunc) {
auto &ctx = ImporterImpl.SwiftContext;
auto dc = incrementFunc->getDeclContext();
auto returnTy = incrementFunc->getImplicitSelfDecl()->getInterfaceType();
auto nameId = ctx.getIdentifier("successor");
auto *params = ParameterList::createEmpty(ctx);
DeclName name(ctx, DeclBaseName(nameId), params);
auto result = FuncDecl::createImplicit(
ctx, StaticSpellingKind::None, name, SourceLoc(),
/*Async*/ false, /*Throws*/ false,
/*GenericParams*/ nullptr, params, returnTy, dc);
result->setAccess(AccessLevel::Public);
result->setIsDynamic(false);
result->setBodySynthesizer(synthesizeSuccessorFuncBody, incrementFunc);
return result;
}
// MARK: C++ arithmetic operators
static std::pair<BraceStmt *, bool>