@@ -3651,9 +3651,21 @@ namespace {
36513651
36523652 result->setHasUnreferenceableStorage (hasUnreferenceableStorage);
36533653
3654- if (cxxRecordDecl)
3654+ if (cxxRecordDecl) {
36553655 result->setIsCxxNonTrivial (!cxxRecordDecl->isTriviallyCopyable ());
36563656
3657+ for (auto &subscriptInfo : Impl.cxxSubscripts ) {
3658+ auto declAndParameterType = subscriptInfo.first ;
3659+ if (declAndParameterType.first != result)
3660+ continue ;
3661+
3662+ auto getterAndSetter = subscriptInfo.second ;
3663+ auto subscript = makeSubscript (getterAndSetter.first ,
3664+ getterAndSetter.second );
3665+ result->addMember (subscript);
3666+ }
3667+ }
3668+
36573669 return result;
36583670 }
36593671
@@ -3945,12 +3957,10 @@ namespace {
39453957 AbstractStorageDecl *owningStorage;
39463958 switch (importedName.getAccessorKind ()) {
39473959 case ImportedAccessorKind::None:
3948- owningStorage = nullptr ;
3949- break ;
3950-
39513960 case ImportedAccessorKind::SubscriptGetter:
39523961 case ImportedAccessorKind::SubscriptSetter:
3953- llvm_unreachable (" Not possible for a function" );
3962+ owningStorage = nullptr ;
3963+ break ;
39543964
39553965 case ImportedAccessorKind::PropertyGetter: {
39563966 auto property = getImplicitProperty (importedName, decl);
@@ -4147,6 +4157,30 @@ namespace {
41474157 func->setImportAsStaticMember ();
41484158 }
41494159 }
4160+
4161+ if (importedName.isSubscriptAccessor ()) {
4162+ assert (func->getParameters ()->size () == 1 );
4163+ auto typeDecl = dc->getSelfNominalTypeDecl ();
4164+ auto parameterType = func->getParameters ()->get (0 )->getType ();
4165+ if (!typeDecl || !parameterType)
4166+ return nullptr ;
4167+
4168+ auto &getterAndSetter = Impl.cxxSubscripts [{ typeDecl,
4169+ parameterType }];
4170+
4171+ switch (importedName.getAccessorKind ()) {
4172+ case ImportedAccessorKind::SubscriptGetter:
4173+ getterAndSetter.first = func;
4174+ break ;
4175+ case ImportedAccessorKind::SubscriptSetter:
4176+ getterAndSetter.second = func;
4177+ break ;
4178+ default :
4179+ llvm_unreachable (" invalid subscript kind" );
4180+ }
4181+
4182+ Impl.markUnavailable (func, " use subscript" );
4183+ }
41504184 // Someday, maybe this will need to be 'open' for C++ virtual methods.
41514185 func->setAccess (AccessLevel::Public);
41524186 }
@@ -4976,6 +5010,15 @@ namespace {
49765010 SubscriptDecl *importSubscript (Decl *decl,
49775011 const clang::ObjCMethodDecl *objcMethod);
49785012
5013+ // / Given either the getter, the setter, or both getter & setter
5014+ // / for a subscript operation, create the Swift subscript declaration.
5015+ // /
5016+ // / \param getter function returning `UnsafePointer<T>`
5017+ // / \param setter function returning `UnsafeMutablePointer<T>`
5018+ // / \return subscript declaration
5019+ SubscriptDecl *makeSubscript (FuncDecl *getter,
5020+ FuncDecl *setter);
5021+
49795022 // / Import the accessor and its attributes.
49805023 AccessorDecl *importAccessor (clang::ObjCMethodDecl *clangAccessor,
49815024 AbstractStorageDecl *storage,
@@ -7363,6 +7406,244 @@ SwiftDeclConverter::importAccessor(clang::ObjCMethodDecl *clangAccessor,
73637406 return accessor;
73647407}
73657408
7409+ static InOutExpr *
7410+ createInOutSelfExpr (AccessorDecl *accessorDecl) {
7411+ ASTContext &ctx = accessorDecl->getASTContext ();
7412+
7413+ auto inoutSelfDecl = accessorDecl->getImplicitSelfDecl ();
7414+ auto inoutSelfRefExpr =
7415+ new (ctx) DeclRefExpr (inoutSelfDecl, DeclNameLoc (),
7416+ /* implicit=*/ true );
7417+ inoutSelfRefExpr->setType (LValueType::get (inoutSelfDecl->getInterfaceType ()));
7418+
7419+ auto inoutSelfExpr =
7420+ new (ctx) InOutExpr (SourceLoc (),
7421+ inoutSelfRefExpr,
7422+ accessorDecl->mapTypeIntoContext (
7423+ inoutSelfDecl->getValueInterfaceType ()),
7424+ /* isImplicit=*/ true );
7425+ inoutSelfExpr->setType (InOutType::get (inoutSelfDecl->getInterfaceType ()));
7426+ return inoutSelfExpr;
7427+ }
7428+
7429+ static DeclRefExpr *
7430+ createParamRefExpr (AccessorDecl *accessorDecl, unsigned index) {
7431+ ASTContext &ctx = accessorDecl->getASTContext ();
7432+
7433+ auto paramDecl = accessorDecl->getParameters ()->get (index);
7434+ auto paramRefExpr = new (ctx) DeclRefExpr (paramDecl,
7435+ DeclNameLoc (),
7436+ /* Implicit=*/ true );
7437+ paramRefExpr->setType (paramDecl->getType ());
7438+ return paramRefExpr;
7439+ }
7440+
7441+ static CallExpr *
7442+ createAccessorImplCallExpr (FuncDecl *accessorImpl,
7443+ InOutExpr *inoutSelfExpr,
7444+ DeclRefExpr *keyRefExpr) {
7445+ ASTContext &ctx = accessorImpl->getASTContext ();
7446+
7447+ auto accessorImplExpr =
7448+ new (ctx) DeclRefExpr (ConcreteDeclRef (accessorImpl),
7449+ DeclNameLoc (),
7450+ /* Implicit=*/ true );
7451+ accessorImplExpr->setType (accessorImpl->getInterfaceType ());
7452+
7453+ auto accessorImplDotCallExpr =
7454+ new (ctx) DotSyntaxCallExpr (accessorImplExpr,
7455+ SourceLoc (),
7456+ inoutSelfExpr);
7457+ accessorImplDotCallExpr->setType (accessorImpl->getMethodInterfaceType ());
7458+ accessorImplDotCallExpr->setThrows (false );
7459+
7460+ auto *accessorImplCallExpr =
7461+ CallExpr::createImplicit (ctx, accessorImplDotCallExpr,
7462+ { keyRefExpr }, { Identifier () });
7463+ accessorImplCallExpr->setType (accessorImpl->getResultInterfaceType ());
7464+ accessorImplCallExpr->setThrows (false );
7465+ return accessorImplCallExpr;
7466+ }
7467+
7468+ // / Synthesizer callback for a subscript getter.
7469+ static std::pair<BraceStmt *, bool >
7470+ synthesizeSubscriptGetterBody (AbstractFunctionDecl *afd, void *context) {
7471+ auto getterDecl = cast<AccessorDecl>(afd);
7472+ auto getterImpl = static_cast <FuncDecl *>(context);
7473+
7474+ ASTContext &ctx = getterDecl->getASTContext ();
7475+
7476+ InOutExpr *inoutSelfExpr = createInOutSelfExpr (getterDecl);
7477+ DeclRefExpr *keyRefExpr = createParamRefExpr (getterDecl, 0 );
7478+
7479+ Type elementTy = getterDecl->getResultInterfaceType ();
7480+
7481+ auto *getterImplCallExpr = createAccessorImplCallExpr (getterImpl,
7482+ inoutSelfExpr,
7483+ keyRefExpr);
7484+
7485+ // `getterImpl` can return either UnsafePointer or UnsafeMutablePointer.
7486+ // Retrieve the corresponding `.pointee` declaration.
7487+ PointerTypeKind ptrKind;
7488+ getterImpl->getResultInterfaceType ()->getAnyPointerElementType (ptrKind);
7489+ VarDecl *pointeePropertyDecl = ctx.getPointerPointeePropertyDecl (ptrKind);
7490+
7491+ SubstitutionMap subMap =
7492+ SubstitutionMap::get (ctx.getUnsafePointerDecl ()->getGenericSignature (),
7493+ { elementTy }, { });
7494+ auto pointeePropertyRefExpr =
7495+ new (ctx) MemberRefExpr (getterImplCallExpr,
7496+ SourceLoc (),
7497+ ConcreteDeclRef (pointeePropertyDecl, subMap),
7498+ DeclNameLoc (),
7499+ /* implicit=*/ true );
7500+ pointeePropertyRefExpr->setType (elementTy);
7501+
7502+ auto returnStmt = new (ctx) ReturnStmt (SourceLoc (),
7503+ pointeePropertyRefExpr,
7504+ /* implicit=*/ true );
7505+
7506+ auto body = BraceStmt::create (ctx, SourceLoc (), { returnStmt }, SourceLoc (),
7507+ /* implicit=*/ true );
7508+ return { body, /* isTypeChecked=*/ true };
7509+ }
7510+
7511+ // / Synthesizer callback for a subscript setter.
7512+ static std::pair<BraceStmt *, bool >
7513+ synthesizeSubscriptSetterBody (AbstractFunctionDecl *afd, void *context) {
7514+ auto setterDecl = cast<AccessorDecl>(afd);
7515+ auto setterImpl = static_cast <FuncDecl *>(context);
7516+
7517+ ASTContext &ctx = setterDecl->getASTContext ();
7518+
7519+ InOutExpr *inoutSelfExpr = createInOutSelfExpr (setterDecl);
7520+ DeclRefExpr *valueParamRefExpr = createParamRefExpr (setterDecl, 0 );
7521+ DeclRefExpr *keyParamRefExpr = createParamRefExpr (setterDecl, 1 );
7522+
7523+ Type elementTy = valueParamRefExpr->getDecl ()->getInterfaceType ();
7524+
7525+ auto *setterImplCallExpr = createAccessorImplCallExpr (setterImpl,
7526+ inoutSelfExpr,
7527+ keyParamRefExpr);
7528+
7529+ VarDecl *pointeePropertyDecl = ctx.getPointerPointeePropertyDecl (PTK_UnsafeMutablePointer);
7530+
7531+ SubstitutionMap subMap =
7532+ SubstitutionMap::get (ctx.getUnsafeMutablePointerDecl ()->getGenericSignature (),
7533+ { elementTy }, { });
7534+ auto pointeePropertyRefExpr =
7535+ new (ctx) MemberRefExpr (setterImplCallExpr,
7536+ SourceLoc (),
7537+ ConcreteDeclRef (pointeePropertyDecl, subMap),
7538+ DeclNameLoc (),
7539+ /* implicit=*/ true );
7540+ pointeePropertyRefExpr->setType (LValueType::get (elementTy));
7541+
7542+ auto assignExpr = new (ctx) AssignExpr (pointeePropertyRefExpr,
7543+ SourceLoc (),
7544+ valueParamRefExpr,
7545+ /* implicit*/ true );
7546+ assignExpr->setType (TupleType::getEmpty (ctx));
7547+
7548+ auto body = BraceStmt::create (ctx, SourceLoc (), { assignExpr, }, SourceLoc ());
7549+ return { body, /* isTypeChecked=*/ true };
7550+ }
7551+
7552+ SubscriptDecl *
7553+ SwiftDeclConverter::makeSubscript (FuncDecl *getter, FuncDecl *setter) {
7554+ assert ((getter || setter) && " getter or setter required to generate subscript" );
7555+
7556+ // If only a setter (imported from non-const `operator[]`) is defined,
7557+ // generate both get & set accessors from it.
7558+ FuncDecl *getterImpl = getter ? getter : setter;
7559+ FuncDecl *setterImpl = setter;
7560+
7561+ // Get the return type wrapped in `Unsafe(Mutable)Pointer<T>`.
7562+ const auto rawElementTy = getterImpl->getResultInterfaceType ();
7563+ // Unwrap `T`.
7564+ const auto elementTy = rawElementTy->getAnyPointerElementType ();
7565+
7566+ auto &ctx = Impl.SwiftContext ;
7567+ auto bodyParams = getterImpl->getParameters ();
7568+ DeclName name (ctx, DeclBaseName::createSubscript (), bodyParams);
7569+ auto dc = getterImpl->getDeclContext ();
7570+
7571+ SubscriptDecl *subscript = SubscriptDecl::createImported (ctx,
7572+ name,
7573+ getterImpl->getLoc (),
7574+ bodyParams,
7575+ getterImpl->getLoc (),
7576+ elementTy,
7577+ dc,
7578+ getterImpl->getClangNode ());
7579+ subscript->setAccess (AccessLevel::Public);
7580+
7581+ AccessorDecl *getterDecl = AccessorDecl::create (ctx,
7582+ getterImpl->getLoc (),
7583+ getterImpl->getLoc (),
7584+ AccessorKind::Get,
7585+ subscript,
7586+ SourceLoc (),
7587+ subscript->getStaticSpelling (),
7588+ false ,
7589+ SourceLoc (),
7590+ nullptr ,
7591+ bodyParams,
7592+ elementTy,
7593+ dc);
7594+ getterDecl->setAccess (AccessLevel::Public);
7595+ getterDecl->setImplicit ();
7596+ getterDecl->setIsDynamic (false );
7597+ getterDecl->setIsTransparent (true );
7598+ getterDecl->setBodySynthesizer (synthesizeSubscriptGetterBody, getterImpl);
7599+
7600+ if (getterImpl->isMutating ()) {
7601+ getterDecl->setSelfAccessKind (SelfAccessKind::Mutating);
7602+ subscript->setIsGetterMutating (true );
7603+ }
7604+
7605+ AccessorDecl *setterDecl = nullptr ;
7606+ if (setterImpl) {
7607+ auto paramVarDecl =
7608+ new (ctx) ParamDecl (SourceLoc (), SourceLoc (),
7609+ Identifier (), SourceLoc (),
7610+ ctx.getIdentifier (" newValue" ), dc);
7611+ paramVarDecl->setSpecifier (ParamSpecifier::Default);
7612+ paramVarDecl->setInterfaceType (elementTy);
7613+
7614+ auto setterParamList =
7615+ ParameterList::create (ctx, { paramVarDecl, bodyParams->get (0 ) });
7616+
7617+ setterDecl = AccessorDecl::create (ctx,
7618+ setterImpl->getLoc (),
7619+ setterImpl->getLoc (),
7620+ AccessorKind::Set,
7621+ subscript,
7622+ SourceLoc (),
7623+ subscript->getStaticSpelling (),
7624+ false ,
7625+ SourceLoc (),
7626+ nullptr ,
7627+ setterParamList,
7628+ TupleType::getEmpty (ctx),
7629+ dc);
7630+ setterDecl->setAccess (AccessLevel::Public);
7631+ setterDecl->setImplicit ();
7632+ setterDecl->setIsDynamic (false );
7633+ setterDecl->setIsTransparent (true );
7634+ setterDecl->setBodySynthesizer (synthesizeSubscriptSetterBody, setterImpl);
7635+
7636+ if (setterImpl->isMutating ()) {
7637+ setterDecl->setSelfAccessKind (SelfAccessKind::Mutating);
7638+ subscript->setIsSetterMutating (true );
7639+ }
7640+ }
7641+
7642+ makeComputed (subscript, getterDecl, setterDecl);
7643+
7644+ return subscript;
7645+ }
7646+
73667647void SwiftDeclConverter::addProtocols (
73677648 ProtocolDecl *protocol, SmallVectorImpl<ProtocolDecl *> &protocols,
73687649 llvm::SmallPtrSetImpl<ProtocolDecl *> &known) {
0 commit comments