@@ -4117,6 +4117,50 @@ namespace {
41174117 return false ;
41184118 }
41194119
4120+ // Inject lifetime annotations selectively for some STL types so we can use
4121+ // unsafeAddress to avoid copies.
4122+ bool inferSelfDependence (const clang::FunctionDecl *decl,
4123+ AbstractFunctionDecl *result, size_t returnIdx) {
4124+ const auto *method = dyn_cast<clang::CXXMethodDecl>(decl);
4125+ if (!method)
4126+ return false ;
4127+ const auto *enclosing = method->getParent ();
4128+ if (enclosing->isInStdNamespace () &&
4129+ (enclosing->getName () == " unique_ptr" ||
4130+ enclosing->getName () == " shared_ptr" ) &&
4131+ method->isOverloadedOperator () &&
4132+ method->getOverloadedOperator () == clang::OO_Star) {
4133+ SmallVector<LifetimeDependenceInfo, 1 > lifetimeDependencies;
4134+ SmallBitVector dependenciesOfRet (returnIdx);
4135+ dependenciesOfRet[result->getSelfIndex ()] = true ;
4136+ lifetimeDependencies.push_back (LifetimeDependenceInfo (
4137+ nullptr , IndexSubset::get (Impl.SwiftContext , dependenciesOfRet),
4138+ returnIdx,
4139+ /* isImmortal*/ false ));
4140+ Impl.SwiftContext .evaluator .cacheOutput (
4141+ LifetimeDependenceInfoRequest{result},
4142+ Impl.SwiftContext .AllocateCopy (lifetimeDependencies));
4143+ Impl.returnsSelfDependentValue .insert (result);
4144+ return true ;
4145+ }
4146+ return false ;
4147+ }
4148+
4149+ static bool isReturnDependsOnSelf (
4150+ AbstractFunctionDecl *f,
4151+ const ArrayRef<LifetimeDependenceInfo> &lifetimeDeps) {
4152+ if (isa<ConstructorDecl>(f) || !f->getImportAsMemberStatus ().isInstance ())
4153+ return false ;
4154+ for (auto dependence : lifetimeDeps) {
4155+ auto returnIdx = f->getParameters ()->size () + !isa<ConstructorDecl>(f);
4156+ if (!dependence.hasInheritLifetimeParamIndices () &&
4157+ dependence.hasScopeLifetimeParamIndices () &&
4158+ dependence.getTargetIndex () == returnIdx)
4159+ return dependence.getScopeIndices ()->contains (f->getSelfIndex ());
4160+ }
4161+ return false ;
4162+ }
4163+
41204164 void addLifetimeDependencies (const clang::FunctionDecl *decl,
41214165 AbstractFunctionDecl *result) {
41224166 if (decl->getTemplatedKind () == clang::FunctionDecl::TK_FunctionTemplate)
@@ -4135,10 +4179,19 @@ namespace {
41354179 CxxEscapability::Unknown) != CxxEscapability::NonEscapable;
41364180 };
41374181
4182+ auto swiftParams = result->getParameters ();
4183+ bool hasSelf =
4184+ result->hasImplicitSelfDecl () && !isa<ConstructorDecl>(result);
4185+ auto returnIdx = swiftParams->size () + hasSelf;
4186+
4187+ if (inferSelfDependence (decl, result, returnIdx))
4188+ return ;
4189+
41384190 // FIXME: this uses '0' as the result index. That only works for
41394191 // standalone functions with no parameters.
41404192 // See markReturnsUnsafeNonescapable() for a general approach.
41414193 auto &ASTContext = result->getASTContext ();
4194+
41424195 SmallVector<LifetimeDependenceInfo, 1 > lifetimeDependencies;
41434196 LifetimeDependenceInfo immortalLifetime (nullptr , nullptr , 0 ,
41444197 /* isImmortal*/ true );
@@ -4161,10 +4214,7 @@ namespace {
41614214 }
41624215 };
41634216
4164- auto swiftParams = result->getParameters ();
4165- bool hasSelf =
4166- result->hasImplicitSelfDecl () && !isa<ConstructorDecl>(result);
4167- const auto dependencyVecSize = swiftParams->size () + hasSelf;
4217+ const auto dependencyVecSize = returnIdx;
41684218 SmallBitVector inheritLifetimeParamIndicesForReturn (dependencyVecSize);
41694219 SmallBitVector scopedLifetimeParamIndicesForReturn (dependencyVecSize);
41704220 SmallBitVector paramHasAnnotation (dependencyVecSize);
@@ -4243,7 +4293,7 @@ namespace {
42434293 ? IndexSubset::get (Impl.SwiftContext ,
42444294 scopedLifetimeParamIndicesForReturn)
42454295 : nullptr ,
4246- swiftParams-> size () + hasSelf ,
4296+ returnIdx ,
42474297 /* isImmortal*/ false ));
42484298 else if (auto *ctordecl = dyn_cast<clang::CXXConstructorDecl>(decl)) {
42494299 // Assume default constructed view types have no dependencies.
@@ -4282,6 +4332,10 @@ namespace {
42824332 }
42834333
42844334 Impl.diagnoseTargetDirectly (decl);
4335+
4336+ if (isReturnDependsOnSelf (result, lifetimeDependencies)) {
4337+ Impl.returnsSelfDependentValue .insert (result);
4338+ }
42854339 }
42864340
42874341 void finishFuncDecl (const clang::FunctionDecl *decl,
0 commit comments