Skip to content

Commit fa31448

Browse files
varungandhi-appleetcwilde
authored andcommitted
[Sema] Allow swift_indirect_result and swift_context for async functions.
1 parent 7c190e7 commit fa31448

File tree

5 files changed

+39
-24
lines changed

5 files changed

+39
-24
lines changed

clang/include/clang/Basic/AttrDocs.td

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4686,7 +4686,8 @@ def SwiftContextDocs : Documentation {
46864686
let Category = DocCatVariable;
46874687
let Content = [{
46884688
The ``swift_context`` attribute marks a parameter of a ``swiftcall``
4689-
function as having the special context-parameter ABI treatment.
4689+
or ``swiftasynccall`` function as having the special context-parameter
4690+
ABI treatment.
46904691

46914692
This treatment generally passes the context value in a special register
46924693
which is normally callee-preserved.
@@ -4708,9 +4709,10 @@ provided it declares the right formal arguments.
47084709

47094710
In most respects, this is similar to the ``swiftcall`` attribute, except for
47104711
the following:
4711-
- A parameter may be marked ``swift_async_context``, but the parameter
4712-
attributes ``swift_context``, ``swift_error_result`` and
4713-
``swift_indirect_result`` are not permitted.
4712+
- A parameter may be marked ``swift_async_context``, ``swift_context``
4713+
or ``swift_indirect_result`` (with the same restrictions on parameter
4714+
ordering as ``swiftcall``) but the parameter attribute
4715+
``swift_error_result`` is not permitted.
47144716
- A ``swiftasynccall`` function must have return type ``void``.
47154717
- Within a ``swiftasynccall`` function, a call to a ``swiftasynccall``
47164718
function that is the immediate operand of a ``return`` statement is
@@ -4775,7 +4777,8 @@ def SwiftIndirectResultDocs : Documentation {
47754777
let Category = DocCatVariable;
47764778
let Content = [{
47774779
The ``swift_indirect_result`` attribute marks a parameter of a ``swiftcall``
4778-
function as having the special indirect-result ABI treatment.
4780+
or ``swiftasynccall`` function as having the special indirect-result ABI
4781+
treatment.
47794782

47804783
This treatment gives the parameter the target's normal indirect-result
47814784
ABI treatment, which may involve passing it differently from an ordinary

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3213,7 +3213,8 @@ def warn_nsdictionary_duplicate_key : Warning<
32133213
def note_nsdictionary_duplicate_key_here : Note<
32143214
"previous equal key is here">;
32153215
def err_swift_param_attr_not_swiftcall : Error<
3216-
"'%0' parameter can only be used with swiftcall calling convention">;
3216+
"'%0' parameter can only be used with swiftcall%select{ or swiftasynccall|}1 "
3217+
"calling convention%select{|s}1">;
32173218
def err_swift_indirect_result_not_first : Error<
32183219
"'swift_indirect_result' parameters must be first parameters of function">;
32193220
def err_swift_error_result_not_after_swift_context : Error<

clang/lib/Sema/SemaType.cpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2759,19 +2759,21 @@ static void checkExtParameterInfos(Sema &S, ArrayRef<QualType> paramTypes,
27592759
llvm::function_ref<SourceLocation(unsigned)> getParamLoc) {
27602760
assert(EPI.ExtParameterInfos && "shouldn't get here without param infos");
27612761

2762-
bool hasCheckedSwiftCall = false;
2763-
auto reportWrongABI = [&](unsigned paramIndex) {
2762+
bool emittedError = false;
2763+
auto actualCC = EPI.ExtInfo.getCC();
2764+
enum class RequiredCC { OnlySwift, SwiftOrSwiftAsync };
2765+
auto checkCompatible = [&](unsigned paramIndex, RequiredCC required) {
2766+
bool isCompatible =
2767+
(required == RequiredCC::OnlySwift)
2768+
? (actualCC == CC_Swift)
2769+
: (actualCC == CC_Swift || actualCC == CC_SwiftAsync);
2770+
if (isCompatible || emittedError)
2771+
return;
27642772
S.Diag(getParamLoc(paramIndex), diag::err_swift_param_attr_not_swiftcall)
2765-
<< getParameterABISpelling(EPI.ExtParameterInfos[paramIndex].getABI());
2766-
};
2767-
auto checkForSwiftCC = [&](unsigned paramIndex) {
2768-
// Only do this once.
2769-
if (hasCheckedSwiftCall) return;
2770-
hasCheckedSwiftCall = true;
2771-
if (EPI.ExtInfo.getCC() == CC_Swift) return;
2772-
reportWrongABI(paramIndex);
2773+
<< getParameterABISpelling(EPI.ExtParameterInfos[paramIndex].getABI())
2774+
<< (required == RequiredCC::OnlySwift);
2775+
emittedError = true;
27732776
};
2774-
27752777
for (size_t paramIndex = 0, numParams = paramTypes.size();
27762778
paramIndex != numParams; ++paramIndex) {
27772779
switch (EPI.ExtParameterInfos[paramIndex].getABI()) {
@@ -2782,7 +2784,7 @@ static void checkExtParameterInfos(Sema &S, ArrayRef<QualType> paramTypes,
27822784
// swift_indirect_result parameters must be a prefix of the function
27832785
// arguments.
27842786
case ParameterABI::SwiftIndirectResult:
2785-
checkForSwiftCC(paramIndex);
2787+
checkCompatible(paramIndex, RequiredCC::SwiftOrSwiftAsync);
27862788
if (paramIndex != 0 &&
27872789
EPI.ExtParameterInfos[paramIndex - 1].getABI()
27882790
!= ParameterABI::SwiftIndirectResult) {
@@ -2792,7 +2794,7 @@ static void checkExtParameterInfos(Sema &S, ArrayRef<QualType> paramTypes,
27922794
continue;
27932795

27942796
case ParameterABI::SwiftContext:
2795-
checkForSwiftCC(paramIndex);
2797+
checkCompatible(paramIndex, RequiredCC::SwiftOrSwiftAsync);
27962798
continue;
27972799

27982800
// SwiftAsyncContext is not limited to swiftasynccall functions.
@@ -2801,7 +2803,7 @@ static void checkExtParameterInfos(Sema &S, ArrayRef<QualType> paramTypes,
28012803

28022804
// swift_error parameters must be preceded by a swift_context parameter.
28032805
case ParameterABI::SwiftErrorResult:
2804-
checkForSwiftCC(paramIndex);
2806+
checkCompatible(paramIndex, RequiredCC::OnlySwift);
28052807
if (paramIndex == 0 ||
28062808
EPI.ExtParameterInfos[paramIndex - 1].getABI() !=
28072809
ParameterABI::SwiftContext) {

clang/test/Sema/attr-swiftcall.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ void multiple_ccs_async(int x) SWIFTASYNCCALL __attribute__((vectorcall)); // ex
1919
void (*functionPointer)(void) SWIFTCALL;
2020
void (*asyncFunctionPointer)(void) SWIFTASYNCCALL;
2121

22-
void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall calling convention}}
22+
void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall or swiftasynccall calling convention}}
2323
void indirect_result_bad_position(int first, INDIRECT_RESULT void *out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameters must be first parameters of function}}
2424
void indirect_result_bad_type(INDIRECT_RESULT int out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameter must have pointer type; type here is 'int'}}
2525
void indirect_result_single(INDIRECT_RESULT void *out) SWIFTCALL;
2626
void indirect_result_multiple(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTCALL;
27+
void indirect_result_single_async(INDIRECT_RESULT void *out) SWIFTASYNCCALL;
28+
void indirect_result_multiple_async(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTASYNCCALL;
2729

2830
void error_result_nonswift(ERROR_RESULT void **error); // expected-error {{'swift_error_result' parameter can only be used with swiftcall calling convention}} expected-error{{'swift_error_result' parameter must follow 'swift_context' parameter}}
2931
void error_result_bad_position2(int first, ERROR_RESULT void **error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must follow 'swift_context' parameter}}
@@ -32,10 +34,12 @@ void error_result_bad_type2(CONTEXT void *context, ERROR_RESULT int *error) SWIF
3234
void error_result_okay(int a, int b, CONTEXT void *context, ERROR_RESULT void **error) SWIFTCALL;
3335
void error_result_okay2(CONTEXT void *context, ERROR_RESULT void **error, void *selfType, char **selfWitnessTable) SWIFTCALL;
3436

35-
void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall calling convention}}
37+
void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall or swiftasynccall calling convention}}
3638
void context_bad_type(CONTEXT int context) SWIFTCALL; // expected-error {{'swift_context' parameter must have pointer type; type here is 'int'}}
3739
void context_okay(CONTEXT void *context) SWIFTCALL;
3840
void context_okay2(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTCALL;
41+
void context_okay_async(CONTEXT void *context) SWIFTASYNCCALL;
42+
void context_okay2_async(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTASYNCCALL;
3943

4044
void async_context_nonswift(ASYNC_CONTEXT void *context); // OK
4145
void async_context_bad_type(ASYNC_CONTEXT int context) SWIFTASYNCCALL; // expected-error {{'swift_async_context' parameter must have pointer type; type here is 'int'}}

clang/test/SemaCXX/attr-swiftcall.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@ void multiple_ccs_async(int x) SWIFTASYNCCALL __attribute__((vectorcall)); // ex
1616
void (*functionPointer)(void) SWIFTCALL;
1717
void (*asyncFunctionPointer)(void) SWIFTASYNCCALL;
1818

19-
void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall calling convention}}
19+
void indirect_result_nonswift(INDIRECT_RESULT void *out); // expected-error {{'swift_indirect_result' parameter can only be used with swiftcall or swiftasynccall calling convention}}
2020
void indirect_result_bad_position(int first, INDIRECT_RESULT void *out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameters must be first parameters of function}}
2121
void indirect_result_bad_type(INDIRECT_RESULT int out) SWIFTCALL; // expected-error {{'swift_indirect_result' parameter must have pointer type; type here is 'int'}}
2222
void indirect_result_single(INDIRECT_RESULT void *out) SWIFTCALL;
2323
void indirect_result_multiple(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTCALL;
24+
void indirect_result_single_async(INDIRECT_RESULT void *out) SWIFTASYNCCALL;
25+
void indirect_result_multiple_async(INDIRECT_RESULT void *out1, INDIRECT_RESULT void *out2) SWIFTASYNCCALL;
26+
2427

2528
void error_result_nonswift(ERROR_RESULT void **error); // expected-error {{'swift_error_result' parameter can only be used with swiftcall calling convention}} expected-error{{'swift_error_result' parameter must follow 'swift_context' parameter}}
2629
void error_result_bad_position2(int first, ERROR_RESULT void **error) SWIFTCALL; // expected-error {{'swift_error_result' parameter must follow 'swift_context' parameter}}
@@ -29,10 +32,12 @@ void error_result_bad_type2(CONTEXT void *context, ERROR_RESULT int *error) SWIF
2932
void error_result_okay(int a, int b, CONTEXT void *context, ERROR_RESULT void **error) SWIFTCALL;
3033
void error_result_okay(CONTEXT void *context, ERROR_RESULT void **error, void *selfType, char **selfWitnessTable) SWIFTCALL;
3134

32-
void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall calling convention}}
35+
void context_nonswift(CONTEXT void *context); // expected-error {{'swift_context' parameter can only be used with swiftcall or swiftasynccall calling convention}}
3336
void context_bad_type(CONTEXT int context) SWIFTCALL; // expected-error {{'swift_context' parameter must have pointer type; type here is 'int'}}
3437
void context_okay(CONTEXT void *context) SWIFTCALL;
3538
void context_okay(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTCALL;
39+
void context_okay_async(CONTEXT void *context) SWIFTASYNCCALL;
40+
void context_okay2_async(CONTEXT void *context, void *selfType, char **selfWitnessTable) SWIFTASYNCCALL;
3641

3742
void async_context_nonswift(ASYNC_CONTEXT void *context); // OK
3843
void async_context_bad_type(ASYNC_CONTEXT int context) SWIFTASYNCCALL; // expected-error {{'swift_async_context' parameter must have pointer type; type here is 'int'}}

0 commit comments

Comments
 (0)