Merge remote-tracking branch 'origin/main' into rebranch

This commit is contained in:
swift-ci
2022-06-16 11:13:54 -07:00
4 changed files with 129 additions and 9 deletions

View File

@@ -3595,12 +3595,24 @@ namespace {
if (auto cxxMethod = dyn_cast<clang::CXXMethodDecl>(m)) {
auto cxxOperatorKind = cxxMethod->getOverloadedOperator();
if (cxxOperatorKind == clang::OO_Star && cxxMethod->param_empty()) {
// This is a dereference operator. We synthesize a computed
// property called `pointee` for it.
VarDecl *pointeeProperty = makeDereferencedPointeeProperty(MD);
result->addMember(pointeeProperty);
Impl.markUnavailable(MD, "use .pointee property");
MD->overwriteAccess(AccessLevel::Private);
}
// Check if this method _is_ an overloaded operator but is not a
// call / subscript. Those 2 operators do not need static versions
if (cxxOperatorKind != clang::OverloadedOperatorKind::OO_None &&
cxxOperatorKind != clang::OverloadedOperatorKind::OO_Call &&
cxxOperatorKind !=
clang::OverloadedOperatorKind::OO_Subscript) {
// call / subscript / dereference. Those 3 operators do not need
// static versions.
else if (cxxOperatorKind !=
clang::OverloadedOperatorKind::OO_None &&
cxxOperatorKind !=
clang::OverloadedOperatorKind::OO_Call &&
cxxOperatorKind !=
clang::OverloadedOperatorKind::OO_Subscript) {
auto opFuncDecl = makeOperator(MD, cxxMethod);
@@ -5410,6 +5422,11 @@ namespace {
/// \param setter function returning `UnsafeMutablePointer<T>`
/// \return subscript declaration
SubscriptDecl *makeSubscript(FuncDecl *getter, FuncDecl *setter);
/// Given an imported C++ dereference operator (`operator*()`), create a
/// `pointee` computed property.
VarDecl *makeDereferencedPointeeProperty(FuncDecl *dereferenceFunc);
FuncDecl *makeOperator(FuncDecl *operatorMethod,
clang::CXXMethodDecl *clangOperator);
@@ -7833,16 +7850,21 @@ SwiftDeclConverter::importAccessor(const clang::ObjCMethodDecl *clangAccessor,
return accessor;
}
/// Synthesizer callback for a subscript getter.
/// Synthesizer callback for a subscript getter or a getter for a
/// dereference property (`var pointee`). If the getter's implementation returns
/// an UnsafePointer or UnsafeMutablePointer, it unwraps the pointer and returns
/// the underlying value.
static std::pair<BraceStmt *, bool>
synthesizeSubscriptGetterBody(AbstractFunctionDecl *afd, void *context) {
synthesizeUnwrappingGetterBody(AbstractFunctionDecl *afd, void *context) {
auto getterDecl = cast<AccessorDecl>(afd);
auto getterImpl = static_cast<FuncDecl *>(context);
ASTContext &ctx = getterDecl->getASTContext();
Expr *selfExpr = createSelfExpr(getterDecl);
DeclRefExpr *keyRefExpr = createParamRefExpr(getterDecl, 0);
DeclRefExpr *keyRefExpr = getterDecl->getParameters()->size() == 0
? nullptr
: createParamRefExpr(getterDecl, 0);
Type elementTy = getterDecl->getResultInterfaceType();
@@ -8048,7 +8070,7 @@ SwiftDeclConverter::makeSubscript(FuncDecl *getter, FuncDecl *setter) {
getterDecl->setImplicit();
getterDecl->setIsDynamic(false);
getterDecl->setIsTransparent(true);
getterDecl->setBodySynthesizer(synthesizeSubscriptGetterBody, getterImpl);
getterDecl->setBodySynthesizer(synthesizeUnwrappingGetterBody, getterImpl);
if (getterImpl->isMutating()) {
getterDecl->setSelfAccessKind(SelfAccessKind::Mutating);
@@ -8101,6 +8123,47 @@ SwiftDeclConverter::makeSubscript(FuncDecl *getter, FuncDecl *setter) {
return subscript;
}
VarDecl *
SwiftDeclConverter::makeDereferencedPointeeProperty(FuncDecl *dereferenceFunc) {
auto &ctx = Impl.SwiftContext;
auto dc = dereferenceFunc->getDeclContext();
// Get the return type wrapped in `Unsafe(Mutable)Pointer<T>`.
const auto rawElementTy = dereferenceFunc->getResultInterfaceType();
// Unwrap `T`. Use rawElementTy for return by value.
const auto elementTy = rawElementTy->getAnyPointerElementType()
? rawElementTy->getAnyPointerElementType()
: rawElementTy;
auto result = new (ctx)
VarDecl(/*isStatic*/ false, VarDecl::Introducer::Var,
dereferenceFunc->getStartLoc(), ctx.getIdentifier("pointee"), dc);
result->setInterfaceType(elementTy);
result->setAccess(AccessLevel::Public);
result->setImplInfo(StorageImplInfo::getImmutableComputed());
AccessorDecl *getterDecl = AccessorDecl::create(
ctx, dereferenceFunc->getLoc(), dereferenceFunc->getLoc(),
AccessorKind::Get, result, SourceLoc(), StaticSpellingKind::None,
/*async*/ false, SourceLoc(),
/*throws*/ false, SourceLoc(), nullptr, ParameterList::createEmpty(ctx),
elementTy, dc);
getterDecl->setAccess(AccessLevel::Public);
getterDecl->setImplicit();
getterDecl->setIsDynamic(false);
getterDecl->setIsTransparent(true);
getterDecl->setBodySynthesizer(synthesizeUnwrappingGetterBody,
dereferenceFunc);
if (dereferenceFunc->isMutating()) {
getterDecl->setSelfAccessKind(SelfAccessKind::Mutating);
result->setIsGetterMutating(true);
}
makeComputed(result, getterDecl, /*setter*/ nullptr);
return result;
}
static std::pair<BraceStmt *, bool>
synthesizeOperatorMethodBody(AbstractFunctionDecl *afd, void *context) {
ASTContext &ctx = afd->getASTContext();

View File

@@ -274,4 +274,25 @@ struct DerivedFromReadWriteIntArray : ReadWriteIntArray {};
struct DerivedFromNonTrivialArrayByVal : NonTrivialArrayByVal {};
struct Iterator {
private:
int value = 123;
public:
int &operator*() { return value; }
};
struct ConstIterator {
private:
int value = 234;
public:
const int &operator*() const { return value; }
};
struct ConstIteratorByVal {
private:
int value = 456;
public:
int operator*() const { return value; }
};
#endif

View File

@@ -190,3 +190,21 @@
// CHECK: subscript(x: Int32) -> NonTrivial { get }
// CHECK: mutating func __operatorSubscriptConst(_ x: Int32) -> NonTrivial
// CHECK: }
// CHECK: struct Iterator {
// CHECK: var pointee: Int32 { mutating get }
// CHECK: @available(*, unavailable, message: "use .pointee property")
// CHECK: mutating func __operatorStar() -> UnsafeMutablePointer<Int32>
// CHECK: }
// CHECK: struct ConstIterator {
// CHECK: var pointee: Int32 { get }
// CHECK: @available(*, unavailable, message: "use .pointee property")
// CHECK: func __operatorStar() -> UnsafePointer<Int32>
// CHECK: }
// CHECK: struct ConstIteratorByVal {
// CHECK: var pointee: Int32 { get }
// CHECK: @available(*, unavailable, message: "use .pointee property")
// CHECK: func __operatorStar() -> Int32
// CHECK: }

View File

@@ -240,4 +240,22 @@ OperatorsTestSuite.test("PtrToPtr.subscript (inline)") {
// expectEqual(23, arr[0])
//}
OperatorsTestSuite.test("Iterator.pointee") {
var iter = Iterator()
let res = iter.pointee
expectEqual(123, res)
}
OperatorsTestSuite.test("ConstIterator.pointee") {
let iter = ConstIterator()
let res = iter.pointee
expectEqual(234, res)
}
OperatorsTestSuite.test("ConstIteratorByVal.pointee") {
let iter = ConstIteratorByVal()
let res = iter.pointee
expectEqual(456, res)
}
runAllTests()