Skip to content

Commit a2d983c

Browse files
authored
Improve diagnostic wording for invalid callback attribute uses (#134423)
We were previously telling the user how many arguments were passed to the attribute rather than saying how many arguments were expected to be passed to the callback function. This rewords the diagnostic to hopefully be a bit more clear. Fixes #47451
1 parent a97f734 commit a2d983c

File tree

4 files changed

+32
-29
lines changed

4 files changed

+32
-29
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,10 @@ Bug Fixes to Attribute Support
367367
or ``__attribute__((malloc(deallocator, ptr-index)))``
368368
(`#51607 <https://github.com/llvm/llvm-project/issues/51607>`_).
369369

370+
- Corrected the diagnostic for the ``callback`` attribute when passing too many
371+
or too few attribute argument indicies for the specified callback function.
372+
(#GH47451)
373+
370374
Bug Fixes to C++ Support
371375
^^^^^^^^^^^^^^^^^^^^^^^^
372376

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3195,6 +3195,10 @@ def err_attribute_wrong_number_arguments : Error<
31953195
def err_attribute_wrong_number_arguments_for : Error <
31963196
"%0 attribute references function %1, which %plural{0:takes no arguments|1:takes one argument|"
31973197
":takes exactly %2 arguments}2">;
3198+
def err_callback_attribute_wrong_arg_count : Error<
3199+
"'callback' attribute references function of type %0 which expects %1 "
3200+
"%plural{1:argument|:arguments}1 but attribute specifies %2 parameter index "
3201+
"%plural{1:argument|:arguments}2">;
31983202
def err_attribute_bounds_for_function : Error<
31993203
"%0 attribute references parameter %1, but the function %2 has only %3 parameters">;
32003204
def err_attribute_no_member_function : Error<

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4145,15 +4145,10 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
41454145
return;
41464146
}
41474147

4148-
if (CalleeFnProtoType->getNumParams() > EncodingIndices.size() - 1) {
4149-
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
4150-
<< AL << (unsigned)(EncodingIndices.size() - 1);
4151-
return;
4152-
}
4153-
4154-
if (CalleeFnProtoType->getNumParams() < EncodingIndices.size() - 1) {
4155-
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments)
4156-
<< AL << (unsigned)(EncodingIndices.size() - 1);
4148+
if (CalleeFnProtoType->getNumParams() != EncodingIndices.size() - 1) {
4149+
S.Diag(AL.getLoc(), diag::err_callback_attribute_wrong_arg_count)
4150+
<< QualType{CalleeFnProtoType, 0} << CalleeFnProtoType->getNumParams()
4151+
<< (unsigned)(EncodingIndices.size() - 1);
41574152
return;
41584153
}
41594154

clang/test/Sema/attr-callback-broken.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
__attribute__((callback())) void no_callee(void (*callback)(void)); // expected-error {{'callback' attribute specifies no callback callee}}
44

5-
__attribute__((callback(1, 1))) void too_many_args_1(void (*callback)(void)) {} // expected-error {{'callback' attribute takes one argument}}
6-
__attribute__((callback(1, -1))) void too_many_args_2(double (*callback)(void)); // expected-error {{'callback' attribute takes one argument}}
7-
__attribute__((callback(1, 2, 2))) void too_many_args_3(void (*callback)(int), int); // expected-error {{'callback' attribute requires exactly 2 arguments}}
5+
__attribute__((callback(1, 1))) void too_many_args_1(void (*callback)(void)) {} // expected-error-re {{'callback' attribute references function of type 'void ({{(void)?}})' which expects 0 arguments but attribute specifies 1 parameter index argument}}
6+
__attribute__((callback(1, -1))) void too_many_args_2(double (*callback)(void)); // expected-error-re {{'callback' attribute references function of type 'double ({{(void)?}})' which expects 0 arguments but attribute specifies 1 parameter index argument}}
7+
__attribute__((callback(1, 2, 2))) void too_many_args_3(void (*callback)(int), int); // expected-error {{'callback' attribute references function of type 'void (int)' which expects 1 argument but attribute specifies 2 parameter index arguments}}
88

9-
__attribute__((callback(1, 2))) void too_few_args_1(void (*callback)(int, int), int); // expected-error {{'callback' attribute takes one argument}}
10-
__attribute__((callback(1))) void too_few_args_2(int (*callback)(int)); // expected-error {{'callback' attribute takes no arguments}}
11-
__attribute__((callback(1, -1))) void too_few_args_3(void (*callback)(int, int)) {} // expected-error {{'callback' attribute takes one argument}}
9+
__attribute__((callback(1, 2))) void too_few_args_1(void (*callback)(int, int), int); // expected-error {{'callback' attribute references function of type 'void (int, int)' which expects 2 arguments but attribute specifies 1 parameter index argument}}
10+
__attribute__((callback(1))) void too_few_args_2(int (*callback)(int)); // expected-error {{'callback' attribute references function of type 'int (int)' which expects 1 argument but attribute specifies 0 parameter index arguments}}
11+
__attribute__((callback(1, -1))) void too_few_args_3(void (*callback)(int, int)) {} // expected-error {{'callback' attribute references function of type 'void (int, int)' which expects 2 arguments but attribute specifies 1 parameter index argument}}
1212

1313
__attribute__((callback(-1))) void oob_args_1(void (*callback)(void)); // expected-error {{'callback' attribute specifies invalid callback callee}}
1414
__attribute__((callback(2))) void oob_args_2(int *(*callback)(void)) {} // expected-error {{'callback' attribute parameter 1 is out of bounds}}
@@ -33,22 +33,22 @@ __attribute__((callback(1, 0))) void no_this_2(void *(*callback)(int, void *));
3333
__attribute__((callback(1, -1))) void vararg_cb_1(void (*callback)(int, ...)) {} // expected-error {{'callback' attribute callee may not be variadic}}
3434
__attribute__((callback(1, 1))) void vararg_cb_2(void (*callback)(int, ...), int a); // expected-error {{'callback' attribute callee may not be variadic}}
3535

36-
__attribute__((callback(1, -1, 1, 2, 3, 4, -1))) void varargs_1(void (*callback)(int, ...), int a, float b, double c) {} // expected-error {{'callback' attribute requires exactly 6 arguments}}
37-
__attribute__((callback(1, -1, 4, 2, 3, 4, -1))) void varargs_2(void (*callback)(void *, double, int, ...), int a, float b, double c); // expected-error {{'callback' attribute requires exactly 6 arguments}}
36+
__attribute__((callback(1, -1, 1, 2, 3, 4, -1))) void varargs_1(void (*callback)(int, ...), int a, float b, double c) {} // expected-error {{'callback' attribute references function of type 'void (int, ...)' which expects 1 argument but attribute specifies 6 parameter index arguments}}
37+
__attribute__((callback(1, -1, 4, 2, 3, 4, -1))) void varargs_2(void (*callback)(void *, double, int, ...), int a, float b, double c); // expected-error {{'callback' attribute references function of type 'void (void *, double, int, ...)' which expects 3 arguments but attribute specifies 6 parameter index arguments}}
3838

39-
__attribute__((callback(1, -1, 1))) void self_arg_1(void (*callback)(int, ...)) {} // expected-error {{'callback' attribute requires exactly 2 arguments}}
40-
__attribute__((callback(1, -1, 1, -1, -1, 1))) void self_arg_2(void (*callback)(int, ...)); // expected-error {{'callback' attribute requires exactly 5 arguments}}
39+
__attribute__((callback(1, -1, 1))) void self_arg_1(void (*callback)(int, ...)) {} // expected-error {{'callback' attribute references function of type 'void (int, ...)' which expects 1 argument but attribute specifies 2 parameter index arguments}}
40+
__attribute__((callback(1, -1, 1, -1, -1, 1))) void self_arg_2(void (*callback)(int, ...)); // expected-error {{'callback' attribute references function of type 'void (int, ...)' which expects 1 argument but attribute specifies 5 parameter index arguments}}
4141

4242
__attribute__((callback(cb))) void unknown_name1(void (*callback)(void)) {} // expected-error {{'callback' attribute argument 'cb' is not a known function parameter}}
4343
__attribute__((callback(cb, ab))) void unknown_name2(void (*cb)(int), int a) {} // expected-error {{'callback' attribute argument 'ab' is not a known function parameter}}
4444

45-
__attribute__((callback(callback, 1))) void too_many_args_1b(void (*callback)(void)) {} // expected-error {{'callback' attribute takes one argument}}
46-
__attribute__((callback(callback, __))) void too_many_args_2b(double (*callback)(void)); // expected-error {{'callback' attribute takes one argument}}
47-
__attribute__((callback(callback, 2, 2))) void too_many_args_3b(void (*callback)(int), int); // expected-error {{'callback' attribute requires exactly 2 arguments}}
45+
__attribute__((callback(callback, 1))) void too_many_args_1b(void (*callback)(void)) {} // expected-error-re {{'callback' attribute references function of type 'void ({{(void)?}})' which expects 0 arguments but attribute specifies 1 parameter index argument}}
46+
__attribute__((callback(callback, __))) void too_many_args_2b(double (*callback)(void)); // expected-error-re {{'callback' attribute references function of type 'double ({{(void)?}})' which expects 0 arguments but attribute specifies 1 parameter index argument}}
47+
__attribute__((callback(callback, 2, 2))) void too_many_args_3b(void (*callback)(int), int); // expected-error {{'callback' attribute references function of type 'void (int)' which expects 1 argument but attribute specifies 2 parameter index arguments}}
4848

49-
__attribute__((callback(callback, a))) void too_few_args_1b(void (*callback)(int, int), int a); // expected-error {{'callback' attribute takes one argument}}
50-
__attribute__((callback(callback))) void too_few_args_2b(int (*callback)(int)); // expected-error {{'callback' attribute takes no arguments}}
51-
__attribute__((callback(callback, __))) void too_few_args_3b(void (*callback)(int, int)) {} // expected-error {{'callback' attribute takes one argument}}
49+
__attribute__((callback(callback, a))) void too_few_args_1b(void (*callback)(int, int), int a); // expected-error {{'callback' attribute references function of type 'void (int, int)' which expects 2 arguments but attribute specifies 1 parameter index argument}}
50+
__attribute__((callback(callback))) void too_few_args_2b(int (*callback)(int)); // expected-error {{'callback' attribute references function of type 'int (int)' which expects 1 argument but attribute specifies 0 parameter index arguments}}
51+
__attribute__((callback(callback, __))) void too_few_args_3b(void (*callback)(int, int)) {} // expected-error {{'callback' attribute references function of type 'void (int, int)' which expects 2 arguments but attribute specifies 1 parameter index argument}}
5252

5353
__attribute__((callback(__))) void oob_args_1b(void (*callback)(void)); // expected-error {{'callback' attribute specifies invalid callback callee}}
5454

@@ -68,8 +68,8 @@ __attribute__((callback(1, this))) void no_this_2b(void *(*callback)(int, void *
6868
__attribute__((callback(callback, __))) void vararg_cb_1b(void (*callback)(int, ...)) {} // expected-error {{'callback' attribute callee may not be variadic}}
6969
__attribute__((callback(1, a))) void vararg_cb_2b(void (*callback)(int, ...), int a); // expected-error {{'callback' attribute callee may not be variadic}}
7070

71-
__attribute__((callback(callback, __, callback, a, b, c, __))) void varargs_1b(void (*callback)(int, ...), int a, float b, double c) {} // expected-error {{'callback' attribute requires exactly 6 arguments}}
72-
__attribute__((callback(1, __, c, a, b, c, -1))) void varargs_2b(void (*callback)(void *, double, int, ...), int a, float b, double c); // expected-error {{'callback' attribute requires exactly 6 arguments}}
71+
__attribute__((callback(callback, __, callback, a, b, c, __))) void varargs_1b(void (*callback)(int, ...), int a, float b, double c) {} // expected-error {{'callback' attribute references function of type 'void (int, ...)' which expects 1 argument but attribute specifies 6 parameter index arguments}}
72+
__attribute__((callback(1, __, c, a, b, c, -1))) void varargs_2b(void (*callback)(void *, double, int, ...), int a, float b, double c); // expected-error {{'callback' attribute references function of type 'void (void *, double, int, ...)' which expects 3 arguments but attribute specifies 6 parameter index arguments}}
7373

74-
__attribute__((callback(1, __, callback))) void self_arg_1b(void (*callback)(int, ...)) {} // expected-error {{'callback' attribute requires exactly 2 arguments}}
75-
__attribute__((callback(callback, __, callback, __, __, callback))) void self_arg_2b(void (*callback)(int, ...)); // expected-error {{'callback' attribute requires exactly 5 arguments}}
74+
__attribute__((callback(1, __, callback))) void self_arg_1b(void (*callback)(int, ...)) {} // expected-error {{'callback' attribute references function of type 'void (int, ...)' which expects 1 argument but attribute specifies 2 parameter index arguments}}
75+
__attribute__((callback(callback, __, callback, __, __, callback))) void self_arg_2b(void (*callback)(int, ...)); // expected-error {{'callback' attribute references function of type 'void (int, ...)' which expects 1 argument but attribute specifies 5 parameter index arguments}}

0 commit comments

Comments
 (0)