[llvm-branch-commits] [clang] 5a28e1d - [clang] Add support for attribute 'swift_async'
Erik Pilkington via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Dec 7 14:24:25 PST 2020
Author: Erik Pilkington
Date: 2020-12-07T17:19:26-05:00
New Revision: 5a28e1d9e50eb0b866351b5ab3213678fd28374b
URL: https://github.com/llvm/llvm-project/commit/5a28e1d9e50eb0b866351b5ab3213678fd28374b
DIFF: https://github.com/llvm/llvm-project/commit/5a28e1d9e50eb0b866351b5ab3213678fd28374b.diff
LOG: [clang] Add support for attribute 'swift_async'
This attributes specifies how (or if) a given function or method will be
imported into a swift async method. rdar://70111252
Differential revision: https://reviews.llvm.org/D92742
Added:
clang/test/SemaObjC/attr-swift-async.m
Modified:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaDeclAttr.cpp
clang/test/Misc/pragma-attribute-supported-attributes-list.test
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 8e12aba5dad36..51f654fc7613a 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2352,6 +2352,16 @@ def SwiftIndirectResult : ParameterABIAttr {
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">];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 1cc8d9995b857..28f35cf2c0c74 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -4400,6 +4400,37 @@ optimizations like C++'s named return value optimization (NRVO).
}];
}
+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 = [{
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e79d021c1c945..97773d35a6947 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4050,6 +4050,13 @@ def err_attr_swift_error_return_type : Error<
"%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">,
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 11286dc3d33f8..15094854300d0 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6103,6 +6103,56 @@ static void handleSwiftNewType(Sema &S, Decl *D, const ParsedAttr &AL) {
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.
//===----------------------------------------------------------------------===//
@@ -8041,6 +8091,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
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:
diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index 96cabfc195b39..0ba6769a1a8af 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -147,6 +147,7 @@
// 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)
diff --git a/clang/test/SemaObjC/attr-swift-async.m b/clang/test/SemaObjC/attr-swift-async.m
new file mode 100644
index 0000000000000..729c19f7612a7
--- /dev/null
+++ b/clang/test/SemaObjC/attr-swift-async.m
@@ -0,0 +1,38 @@
+// 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'}}
+
+ at 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);
+ at 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
More information about the llvm-branch-commits
mailing list