|
40 | 40 | #include "swift/Basic/Defer.h"
|
41 | 41 | #include "swift/Basic/PrettyStackTrace.h"
|
42 | 42 | #include "swift/Basic/Statistic.h"
|
| 43 | +#include "swift/Basic/StringExtras.h" |
43 | 44 | #include "swift/ClangImporter/ClangModule.h"
|
44 | 45 | #include "swift/Config.h"
|
45 | 46 | #include "swift/Parse/Lexer.h"
|
@@ -7575,6 +7576,46 @@ bool importer::isSpecialUIKitStructZeroProperty(const clang::NamedDecl *decl) {
|
7575 | 7576 | return ident->isStr("UIEdgeInsetsZero") || ident->isStr("UIOffsetZero");
|
7576 | 7577 | }
|
7577 | 7578 |
|
| 7579 | +/// Determine whether any of the parameters to the given function is of an |
| 7580 | +/// unsafe pointer type. |
| 7581 | +static bool hasAnyUnsafePointerParameters(FuncDecl *func) { |
| 7582 | + for (auto param : *func->getParameters()) { |
| 7583 | + Type paramType = |
| 7584 | + param->toFunctionParam().getPlainType()->lookThroughAllOptionalTypes(); |
| 7585 | + if (paramType->getAnyPointerElementType()) { |
| 7586 | + return true; |
| 7587 | + } |
| 7588 | + } |
| 7589 | + |
| 7590 | + return false; |
| 7591 | +} |
| 7592 | + |
| 7593 | +/// Determine whether the given Objective-C method is likely to be an |
| 7594 | +/// asynchronous handler based on its name. |
| 7595 | +static bool isObjCMethodLikelyAsyncHandler( |
| 7596 | + const clang::ObjCMethodDecl *method) { |
| 7597 | + auto selector = method->getSelector(); |
| 7598 | + |
| 7599 | + for (unsigned argIdx : range(std::max(selector.getNumArgs(), 1u))) { |
| 7600 | + auto selectorPiece = selector.getNameForSlot(argIdx); |
| 7601 | + // For the first selector piece, look for the word "did" anywhere. |
| 7602 | + if (argIdx == 0) { |
| 7603 | + for (auto word : camel_case::getWords(selectorPiece)) { |
| 7604 | + if (word == "did" || word == "Did") |
| 7605 | + return true; |
| 7606 | + } |
| 7607 | + |
| 7608 | + continue; |
| 7609 | + } |
| 7610 | + |
| 7611 | + // Otherwise, check whether any subsequent selector piece starts with "did". |
| 7612 | + if (camel_case::getFirstWord(selectorPiece) == "did") |
| 7613 | + return true; |
| 7614 | + } |
| 7615 | + |
| 7616 | + return false; |
| 7617 | +} |
| 7618 | + |
7578 | 7619 | /// Import Clang attributes as Swift attributes.
|
7579 | 7620 | void ClangImporter::Implementation::importAttributes(
|
7580 | 7621 | const clang::NamedDecl *ClangDecl,
|
@@ -7813,6 +7854,24 @@ void ClangImporter::Implementation::importAttributes(
|
7813 | 7854 | if (ClangDecl->hasAttr<clang::PureAttr>()) {
|
7814 | 7855 | MappedDecl->getAttrs().add(new (C) EffectsAttr(EffectsKind::ReadOnly));
|
7815 | 7856 | }
|
| 7857 | + |
| 7858 | + // Infer @asyncHandler on imported protocol methods that meet the semantic |
| 7859 | + // requirements. |
| 7860 | + if (SwiftContext.LangOpts.EnableExperimentalConcurrency) { |
| 7861 | + if (auto func = dyn_cast<FuncDecl>(MappedDecl)) { |
| 7862 | + if (auto proto = dyn_cast<ProtocolDecl>(func->getDeclContext())) { |
| 7863 | + if (proto->isObjC() && isa<clang::ObjCMethodDecl>(ClangDecl) && |
| 7864 | + func->isInstanceMember() && !isa<AccessorDecl>(func) && |
| 7865 | + isObjCMethodLikelyAsyncHandler( |
| 7866 | + cast<clang::ObjCMethodDecl>(ClangDecl)) && |
| 7867 | + func->canBeAsyncHandler() && |
| 7868 | + !hasAnyUnsafePointerParameters(func)) { |
| 7869 | + MappedDecl->getAttrs().add( |
| 7870 | + new (C) AsyncHandlerAttr(/*IsImplicit=*/false)); |
| 7871 | + } |
| 7872 | + } |
| 7873 | + } |
| 7874 | + } |
7816 | 7875 | }
|
7817 | 7876 |
|
7818 | 7877 | Decl *
|
|
0 commit comments