@@ -3595,12 +3595,24 @@ namespace {
3595
3595
if (auto cxxMethod = dyn_cast<clang::CXXMethodDecl>(m)) {
3596
3596
auto cxxOperatorKind = cxxMethod->getOverloadedOperator ();
3597
3597
3598
+ if (cxxOperatorKind == clang::OO_Star && cxxMethod->param_empty ()) {
3599
+ // This is a dereference operator. We synthesize a computed
3600
+ // property called `pointee` for it.
3601
+ VarDecl *pointeeProperty = makeDereferencedPointeeProperty (MD);
3602
+ result->addMember (pointeeProperty);
3603
+
3604
+ Impl.markUnavailable (MD, " use .pointee property" );
3605
+ MD->overwriteAccess (AccessLevel::Private);
3606
+ }
3598
3607
// Check if this method _is_ an overloaded operator but is not a
3599
- // call / subscript. Those 2 operators do not need static versions
3600
- if (cxxOperatorKind != clang::OverloadedOperatorKind::OO_None &&
3601
- cxxOperatorKind != clang::OverloadedOperatorKind::OO_Call &&
3602
- cxxOperatorKind !=
3603
- clang::OverloadedOperatorKind::OO_Subscript) {
3608
+ // call / subscript / dereference. Those 3 operators do not need
3609
+ // static versions.
3610
+ else if (cxxOperatorKind !=
3611
+ clang::OverloadedOperatorKind::OO_None &&
3612
+ cxxOperatorKind !=
3613
+ clang::OverloadedOperatorKind::OO_Call &&
3614
+ cxxOperatorKind !=
3615
+ clang::OverloadedOperatorKind::OO_Subscript) {
3604
3616
3605
3617
auto opFuncDecl = makeOperator (MD, cxxMethod);
3606
3618
@@ -5410,6 +5422,11 @@ namespace {
5410
5422
// / \param setter function returning `UnsafeMutablePointer<T>`
5411
5423
// / \return subscript declaration
5412
5424
SubscriptDecl *makeSubscript (FuncDecl *getter, FuncDecl *setter);
5425
+
5426
+ // / Given an imported C++ dereference operator (`operator*()`), create a
5427
+ // / `pointee` computed property.
5428
+ VarDecl *makeDereferencedPointeeProperty (FuncDecl *dereferenceFunc);
5429
+
5413
5430
FuncDecl *makeOperator (FuncDecl *operatorMethod,
5414
5431
clang::CXXMethodDecl *clangOperator);
5415
5432
@@ -7833,16 +7850,21 @@ SwiftDeclConverter::importAccessor(const clang::ObjCMethodDecl *clangAccessor,
7833
7850
return accessor;
7834
7851
}
7835
7852
7836
- // / Synthesizer callback for a subscript getter.
7853
+ // / Synthesizer callback for a subscript getter or a getter for a
7854
+ // / dereference property (`var pointee`). If the getter's implementation returns
7855
+ // / an UnsafePointer or UnsafeMutablePointer, it unwraps the pointer and returns
7856
+ // / the underlying value.
7837
7857
static std::pair<BraceStmt *, bool >
7838
- synthesizeSubscriptGetterBody (AbstractFunctionDecl *afd, void *context) {
7858
+ synthesizeUnwrappingGetterBody (AbstractFunctionDecl *afd, void *context) {
7839
7859
auto getterDecl = cast<AccessorDecl>(afd);
7840
7860
auto getterImpl = static_cast <FuncDecl *>(context);
7841
7861
7842
7862
ASTContext &ctx = getterDecl->getASTContext ();
7843
7863
7844
7864
Expr *selfExpr = createSelfExpr (getterDecl);
7845
- DeclRefExpr *keyRefExpr = createParamRefExpr (getterDecl, 0 );
7865
+ DeclRefExpr *keyRefExpr = getterDecl->getParameters ()->size () == 0
7866
+ ? nullptr
7867
+ : createParamRefExpr (getterDecl, 0 );
7846
7868
7847
7869
Type elementTy = getterDecl->getResultInterfaceType ();
7848
7870
@@ -8048,7 +8070,7 @@ SwiftDeclConverter::makeSubscript(FuncDecl *getter, FuncDecl *setter) {
8048
8070
getterDecl->setImplicit ();
8049
8071
getterDecl->setIsDynamic (false );
8050
8072
getterDecl->setIsTransparent (true );
8051
- getterDecl->setBodySynthesizer (synthesizeSubscriptGetterBody , getterImpl);
8073
+ getterDecl->setBodySynthesizer (synthesizeUnwrappingGetterBody , getterImpl);
8052
8074
8053
8075
if (getterImpl->isMutating ()) {
8054
8076
getterDecl->setSelfAccessKind (SelfAccessKind::Mutating);
@@ -8101,6 +8123,47 @@ SwiftDeclConverter::makeSubscript(FuncDecl *getter, FuncDecl *setter) {
8101
8123
return subscript;
8102
8124
}
8103
8125
8126
+ VarDecl *
8127
+ SwiftDeclConverter::makeDereferencedPointeeProperty (FuncDecl *dereferenceFunc) {
8128
+ auto &ctx = Impl.SwiftContext ;
8129
+ auto dc = dereferenceFunc->getDeclContext ();
8130
+
8131
+ // Get the return type wrapped in `Unsafe(Mutable)Pointer<T>`.
8132
+ const auto rawElementTy = dereferenceFunc->getResultInterfaceType ();
8133
+ // Unwrap `T`. Use rawElementTy for return by value.
8134
+ const auto elementTy = rawElementTy->getAnyPointerElementType ()
8135
+ ? rawElementTy->getAnyPointerElementType ()
8136
+ : rawElementTy;
8137
+
8138
+ auto result = new (ctx)
8139
+ VarDecl (/* isStatic*/ false , VarDecl::Introducer::Var,
8140
+ dereferenceFunc->getStartLoc (), ctx.getIdentifier (" pointee" ), dc);
8141
+ result->setInterfaceType (elementTy);
8142
+ result->setAccess (AccessLevel::Public);
8143
+ result->setImplInfo (StorageImplInfo::getImmutableComputed ());
8144
+
8145
+ AccessorDecl *getterDecl = AccessorDecl::create (
8146
+ ctx, dereferenceFunc->getLoc (), dereferenceFunc->getLoc (),
8147
+ AccessorKind::Get, result, SourceLoc (), StaticSpellingKind::None,
8148
+ /* async*/ false , SourceLoc (),
8149
+ /* throws*/ false , SourceLoc (), nullptr , ParameterList::createEmpty (ctx),
8150
+ elementTy, dc);
8151
+ getterDecl->setAccess (AccessLevel::Public);
8152
+ getterDecl->setImplicit ();
8153
+ getterDecl->setIsDynamic (false );
8154
+ getterDecl->setIsTransparent (true );
8155
+ getterDecl->setBodySynthesizer (synthesizeUnwrappingGetterBody,
8156
+ dereferenceFunc);
8157
+
8158
+ if (dereferenceFunc->isMutating ()) {
8159
+ getterDecl->setSelfAccessKind (SelfAccessKind::Mutating);
8160
+ result->setIsGetterMutating (true );
8161
+ }
8162
+
8163
+ makeComputed (result, getterDecl, /* setter*/ nullptr );
8164
+ return result;
8165
+ }
8166
+
8104
8167
static std::pair<BraceStmt *, bool >
8105
8168
synthesizeOperatorMethodBody (AbstractFunctionDecl *afd, void *context) {
8106
8169
ASTContext &ctx = afd->getASTContext ();
0 commit comments