@@ -4117,6 +4117,50 @@ namespace {
4117
4117
return false ;
4118
4118
}
4119
4119
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
+
4120
4164
void addLifetimeDependencies (const clang::FunctionDecl *decl,
4121
4165
AbstractFunctionDecl *result) {
4122
4166
if (decl->getTemplatedKind () == clang::FunctionDecl::TK_FunctionTemplate)
@@ -4135,10 +4179,19 @@ namespace {
4135
4179
CxxEscapability::Unknown) != CxxEscapability::NonEscapable;
4136
4180
};
4137
4181
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
+
4138
4190
// FIXME: this uses '0' as the result index. That only works for
4139
4191
// standalone functions with no parameters.
4140
4192
// See markReturnsUnsafeNonescapable() for a general approach.
4141
4193
auto &ASTContext = result->getASTContext ();
4194
+
4142
4195
SmallVector<LifetimeDependenceInfo, 1 > lifetimeDependencies;
4143
4196
LifetimeDependenceInfo immortalLifetime (nullptr , nullptr , 0 ,
4144
4197
/* isImmortal*/ true );
@@ -4161,10 +4214,7 @@ namespace {
4161
4214
}
4162
4215
};
4163
4216
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;
4168
4218
SmallBitVector inheritLifetimeParamIndicesForReturn (dependencyVecSize);
4169
4219
SmallBitVector scopedLifetimeParamIndicesForReturn (dependencyVecSize);
4170
4220
SmallBitVector paramHasAnnotation (dependencyVecSize);
@@ -4243,7 +4293,7 @@ namespace {
4243
4293
? IndexSubset::get (Impl.SwiftContext ,
4244
4294
scopedLifetimeParamIndicesForReturn)
4245
4295
: nullptr ,
4246
- swiftParams-> size () + hasSelf ,
4296
+ returnIdx ,
4247
4297
/* isImmortal*/ false ));
4248
4298
else if (auto *ctordecl = dyn_cast<clang::CXXConstructorDecl>(decl)) {
4249
4299
// Assume default constructed view types have no dependencies.
@@ -4282,6 +4332,10 @@ namespace {
4282
4332
}
4283
4333
4284
4334
Impl.diagnoseTargetDirectly (decl);
4335
+
4336
+ if (isReturnDependsOnSelf (result, lifetimeDependencies)) {
4337
+ Impl.returnsSelfDependentValue .insert (result);
4338
+ }
4285
4339
}
4286
4340
4287
4341
void finishFuncDecl (const clang::FunctionDecl *decl,
0 commit comments