let Documentation = [SwiftIndirectResultDocs];
}
+def SwiftAsync : InheritableAttr {
+ let Spellings = [Clang<"swift_async">];
+ let Subjects = SubjectList<[Function, ObjCMethod]>;
+ let Args = [EnumArgument<"Kind", "Kind",
+ ["none", "swift_private", "not_swift_private"],
+ ["None", "SwiftPrivate", "NotSwiftPrivate"]>,
+ ParamIdxArgument<"CompletionHandlerIndex", /*opt=*/1>];
+ let Documentation = [SwiftAsyncDocs];
+}
+
def Suppress : StmtAttr {
let Spellings = [CXX11<"gsl", "suppress">];
let Args = [VariadicStringArgument<"DiagnosticIdentifiers">];
}];
}
+def SwiftAsyncDocs : Documentation {
+ let Category = SwiftDocs;
+ let Heading = "swift_async";
+ let Content = [{
+The ``swift_async`` attribute specifies if and how a particular function or
+Objective-C method is imported into a swift async method. For instance:
+
+.. code-block:: objc
+
+ @interface MyClass : NSObject
+ -(void)notActuallyAsync:(int)p1 withCompletionHandler:(void (^)())handler
+ __attribute__((swift_async(none)));
+
+ -(void)actuallyAsync:(int)p1 callThisAsync:(void (^)())fun
+ __attribute__((swift_async(swift_private, 1)));
+ @end
+
+Here, ``notActuallyAsync:withCompletionHandler`` would have been imported as
+``async`` (because it's last parameter's selector piece is
+``withCompletionHandler``) if not for the ``swift_async(none)`` attribute.
+Conversely, ``actuallyAsync:callThisAsync`` wouldn't have been imported as
+``async`` if not for the ``swift_async`` attribute because it doesn't match the
+naming convention.
+
+When using ``swift_async`` to enable importing, the first argument to the
+attribute is either ``swift_private`` or ``not_swift_private`` to indicate
+whether the function/method is private to the current framework, and the second
+argument is the index of the completion handler parameter.
+ }];
+}
+
def SuppressDocs : Documentation {
let Category = DocCatStmt;
let Content = [{
"%0 attribute with '%1' convention can only be applied to a "
"%select{function|method}2 returning %select{an integral type|a pointer}3">;
+def err_swift_async_no_access : Error<
+ "first argument to 'swift_async' must be either 'none', 'swift_private', or "
+ "'not_swift_private'">;
+def err_swift_async_bad_block_type : Error<
+ "'swift_async' completion handler parameter must have block type returning"
+ " 'void', type here is %0">;
+
def warn_ignored_objc_externally_retained : Warning<
"'objc_externally_retained' can only be applied to local variables "
"%select{of retainable type|with strong ownership}0">,
D->addAttr(::new (S.Context) SwiftNewTypeAttr(S.Context, AL, Kind));
}
+static void handleSwiftAsyncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+ if (!AL.isArgIdent(0)) {
+ S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type)
+ << AL << 1 << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ SwiftAsyncAttr::Kind Kind;
+ IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
+ if (!SwiftAsyncAttr::ConvertStrToKind(II->getName(), Kind)) {
+ S.Diag(AL.getLoc(), diag::err_swift_async_no_access) << AL << II;
+ return;
+ }
+
+ ParamIdx Idx;
+ if (Kind == SwiftAsyncAttr::None) {
+ // If this is 'none', then there shouldn't be any additional arguments.
+ if (!checkAttributeNumArgs(S, AL, 1))
+ return;
+ } else {
+ // Non-none swift_async requires a completion handler index argument.
+ if (!checkAttributeNumArgs(S, AL, 2))
+ return;
+
+ Expr *HandlerIdx = AL.getArgAsExpr(1);
+ if (!checkFunctionOrMethodParameterIndex(S, D, AL, 2, HandlerIdx, Idx))
+ return;
+
+ const ParmVarDecl *CompletionBlock =
+ getFunctionOrMethodParam(D, Idx.getASTIndex());
+ QualType CompletionBlockType = CompletionBlock->getType();
+ if (!CompletionBlockType->isBlockPointerType()) {
+ S.Diag(CompletionBlock->getLocation(),
+ diag::err_swift_async_bad_block_type)
+ << CompletionBlock->getType();
+ return;
+ }
+ QualType BlockTy =
+ CompletionBlockType->getAs<BlockPointerType>()->getPointeeType();
+ if (!BlockTy->getAs<FunctionType>()->getReturnType()->isVoidType()) {
+ S.Diag(CompletionBlock->getLocation(),
+ diag::err_swift_async_bad_block_type)
+ << CompletionBlock->getType();
+ return;
+ }
+ }
+
+ D->addAttr(::new (S.Context) SwiftAsyncAttr(S.Context, AL, Kind, Idx));
+}
+
//===----------------------------------------------------------------------===//
// Microsoft specific attribute handlers.
//===----------------------------------------------------------------------===//
case ParsedAttr::AT_SwiftPrivate:
handleSimpleAttribute<SwiftPrivateAttr>(S, D, AL);
break;
+ case ParsedAttr::AT_SwiftAsync:
+ handleSwiftAsyncAttr(S, D, AL);
+ break;
// XRay attributes.
case ParsedAttr::AT_XRayLogArgs:
// CHECK-NEXT: Section (SubjectMatchRule_function, SubjectMatchRule_variable_is_global, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property)
// CHECK-NEXT: SetTypestate (SubjectMatchRule_function_is_member)
// CHECK-NEXT: SpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method)
+// CHECK-NEXT: SwiftAsync (SubjectMatchRule_function, SubjectMatchRule_objc_method)
// CHECK-NEXT: SwiftAsyncName (SubjectMatchRule_objc_method, SubjectMatchRule_function)
// CHECK-NEXT: SwiftBridgedTypedef (SubjectMatchRule_type_alias)
// CHECK-NEXT: SwiftContext (SubjectMatchRule_variable_is_parameter)
--- /dev/null
+// RUN: %clang_cc1 -verify -fsyntax-only -fblocks %s
+// RUN: %clang_cc1 -xobjective-c++ -verify -fsyntax-only -fblocks %s
+
+#define SA(...) __attribute__((swift_async(__VA_ARGS__)))
+
+SA(none) int a; // expected-warning{{'swift_async' attribute only applies to functions and Objective-C methods}}
+
+SA(none) void b();
+
+SA(not_swift_private, 0) void c(); // expected-error{{'swift_async' attribute parameter 2 is out of bounds}}
+SA(swift_private, 1) void d(); // expected-error{{'swift_async' attribute parameter 2 is out of bounds}}
+SA(swift_private, 1) void e(int); // expected-error{{'swift_async' completion handler parameter must have block type returning 'void', type here is 'int'}}
+SA(not_swift_private, 1) void f(int (^)()); // expected-error{{'swift_async' completion handler parameter must have block type returning 'void', type here is 'int (^)()'}}
+SA(swift_private, 1) void g(void (^)());
+
+SA(none, 1) void h(); // expected-error{{'swift_async' attribute takes one argument}}
+SA() void i(); // expected-error{{'swift_async' attribute takes at least 1 argument}}
+SA(not_swift_private) void j(); // expected-error{{'swift_async' attribute requires exactly 2 arguments}}
+SA(43) void k(); // expected-error{{'swift_async' attribute requires parameter 1 to be an identifier}}
+SA(not_a_thing, 0) void l(); // expected-error{{first argument to 'swift_async' must be either 'none', 'swift_private', or 'not_swift_private'}}
+
+@interface TestOnMethods
+-(void)m1:(int (^)())callback SA(swift_private, 1); // expected-error{{'swift_async' completion handler parameter must have block type returning 'void', type here is 'int (^)()'}}
+-(void)m2:(void (^)())callback SA(swift_private, 0); // expected-error{{'swift_async' attribute parameter 2 is out of bounds}}
+-(void)m3:(void (^)())callback SA(swift_private, 2); // expected-error{{'swift_async' attribute parameter 2 is out of bounds}}
+-(void)m4 SA(none);
+-(void)m5:(int)p handler:(void (^)(int))callback SA(not_swift_private, 2);
+@end
+
+#ifdef __cplusplus
+struct S {
+ SA(none) void mf1();
+ SA(swift_private, 2) void mf2(void (^)());
+ SA(swift_private, 1) void mf3(void (^)()); // expected-error{{'swift_async' attribute is invalid for the implicit this argument}}
+ SA(swift_private, 0) void mf4(void (^)()); // expected-error{{'swift_async' attribute parameter 2 is out of bounds}}
+ SA(not_swift_private, 2) void mf5(int (^)()); // expected-error{{'swift_async' completion handler parameter must have block type returning 'void', type here is 'int (^)()'}}
+};
+#endif