[Refactoring] Support refactoring to async if callback is @convention(block)

We already have special logic to extrac the closure for closures with capture lists, add the same kind of logic for closures that are marked `@convention(block)` etc.

Resolves rdar://75301524 [SR-14328]
This commit is contained in:
Alex Hoppen
2021-04-27 00:04:28 +02:00
parent c8ba622532
commit f17fe868c6
2 changed files with 40 additions and 6 deletions

View File

@@ -5012,6 +5012,22 @@ private:
}
}
/// From the given expression \p E, which is an argument to a function call,
/// extract the passed closure if there is one. Otherwise return \c nullptr.
ClosureExpr *extractCallback(Expr *E) {
if (auto Closure = dyn_cast<ClosureExpr>(E)) {
return Closure;
} else if (auto CaptureList = dyn_cast<CaptureListExpr>(E)) {
return CaptureList->getClosureBody();
} else if (auto FunctionConversion = dyn_cast<FunctionConversionExpr>(E)) {
// Closure arguments marked as e.g. `@convention(block)` produce arguments
// that are `FunctionConversionExpr`.
return extractCallback(FunctionConversion->getSubExpr());
} else {
return nullptr;
}
}
void addAsyncAlternativeCall(const CallExpr *CE,
const AsyncHandlerDesc &HandlerDesc) {
auto ArgList = callArgs(CE);
@@ -5020,11 +5036,7 @@ private:
return;
}
auto Callback = dyn_cast<ClosureExpr>(ArgList.ref()[HandlerDesc.Index]);
auto Capture = dyn_cast<CaptureListExpr>(ArgList.ref()[HandlerDesc.Index]);
if (Capture) {
Callback = Capture->getClosureBody();
}
ClosureExpr *Callback = extractCallback(ArgList.ref()[HandlerDesc.Index]);
if (!Callback) {
DiagEngine.diagnose(CE->getStartLoc(), diag::missing_callback_arg);
return;