@@ -3595,12 +3595,24 @@ namespace {
35953595 if (auto cxxMethod = dyn_cast<clang::CXXMethodDecl>(m)) {
35963596 auto cxxOperatorKind = cxxMethod->getOverloadedOperator ();
35973597
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+ }
35983607 // 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) {
36043616
36053617 auto opFuncDecl = makeOperator (MD, cxxMethod);
36063618
@@ -5410,6 +5422,11 @@ namespace {
54105422 // / \param setter function returning `UnsafeMutablePointer<T>`
54115423 // / \return subscript declaration
54125424 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+
54135430 FuncDecl *makeOperator (FuncDecl *operatorMethod,
54145431 clang::CXXMethodDecl *clangOperator);
54155432
@@ -7833,16 +7850,21 @@ SwiftDeclConverter::importAccessor(const clang::ObjCMethodDecl *clangAccessor,
78337850 return accessor;
78347851}
78357852
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.
78377857static std::pair<BraceStmt *, bool >
7838- synthesizeSubscriptGetterBody (AbstractFunctionDecl *afd, void *context) {
7858+ synthesizeUnwrappingGetterBody (AbstractFunctionDecl *afd, void *context) {
78397859 auto getterDecl = cast<AccessorDecl>(afd);
78407860 auto getterImpl = static_cast <FuncDecl *>(context);
78417861
78427862 ASTContext &ctx = getterDecl->getASTContext ();
78437863
78447864 Expr *selfExpr = createSelfExpr (getterDecl);
7845- DeclRefExpr *keyRefExpr = createParamRefExpr (getterDecl, 0 );
7865+ DeclRefExpr *keyRefExpr = getterDecl->getParameters ()->size () == 0
7866+ ? nullptr
7867+ : createParamRefExpr (getterDecl, 0 );
78467868
78477869 Type elementTy = getterDecl->getResultInterfaceType ();
78487870
@@ -8048,7 +8070,7 @@ SwiftDeclConverter::makeSubscript(FuncDecl *getter, FuncDecl *setter) {
80488070 getterDecl->setImplicit ();
80498071 getterDecl->setIsDynamic (false );
80508072 getterDecl->setIsTransparent (true );
8051- getterDecl->setBodySynthesizer (synthesizeSubscriptGetterBody , getterImpl);
8073+ getterDecl->setBodySynthesizer (synthesizeUnwrappingGetterBody , getterImpl);
80528074
80538075 if (getterImpl->isMutating ()) {
80548076 getterDecl->setSelfAccessKind (SelfAccessKind::Mutating);
@@ -8101,6 +8123,47 @@ SwiftDeclConverter::makeSubscript(FuncDecl *getter, FuncDecl *setter) {
81018123 return subscript;
81028124}
81038125
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+
81048167static std::pair<BraceStmt *, bool >
81058168synthesizeOperatorMethodBody (AbstractFunctionDecl *afd, void *context) {
81068169 ASTContext &ctx = afd->getASTContext ();
0 commit comments