BPF List
 help / color / mirror / Atom feed
From: "Jose E. Marchesi" <jose.marchesi@oracle.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: bpf@vger.kernel.org, Eduard Zingerman <eddyz87@gmail.com>,
	Yonghong Song <yhs@meta.com>,
	david.faust@oracle.com, cupertino.miranda@oracle.com,
	Andrii Nakryiko <andriin@fb.com>
Subject: Re: Anonymous struct types in parameter lists in BPF selftests
Date: Fri, 26 Jan 2024 10:56:53 +0100	[thread overview]
Message-ID: <87frykwh7e.fsf@oracle.com> (raw)
In-Reply-To: <CAEf4BzYwPb55URks8P6wTJGvqYT=6gdh2RLU+=ri2rfABeDVaQ@mail.gmail.com> (Andrii Nakryiko's message of "Thu, 25 Jan 2024 13:56:35 -0800")


> On Thu, Jan 25, 2024 at 3:31 AM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
>>
>>
>> Hello.
>>
>> In C functions whose declarations/definitions use struct types or enum
>> types (or pointers to them) in the parameter list, the scope of such
>> defined types is limited to the parameter list, which makes the
>> functions basically un-callable with type-correct arguments.
>>
>> Therefore GCC has always emitted a warning when it finds such function
>> declarations, be them named:
>>
>>   int f ( struct root { int i; } *arg)
>>   {
>>     return arg->i;
>>   }
>>
>>   foo.c:1:9: warning: 'struct root' declared inside parameter list
>>              will not be visible outside of this definition or declaration
>>     1 |   int f(struct root { int i; } *_)
>>       |         ^~~~~~~~~~~
>>
>> or anonymous:
>>
>>   int f ( struct { int i; } *arg)
>>   {
>>     return arg->i;
>>   }
>>
>>   foo.c:1:9: warning: anonymous struct declared inside parameter list
>>              will not be visible outside of this definition or declaration
>>     1 |   int f ( struct { int i; } *arg)
>>       |           ^~~~~~
>>
>> This warning cannot be disabled.
>>
>> Clang, on the other side, emits the warning by default when the type is
>> no anonymous (this warning can be disabled with -Wno-visibility):
>>
>>   int f ( struct root { int i; } *arg)
>>   {
>>     return arg->i;
>>   }
>>
>>   foo.c:1:18: warning: declaration of 'struct root' will not be visible
>>               outside of this function [-Wvisibility]
>>     int f ( struct root { int i; } *arg)
>>
>> But it doesn't emit any warning if the type is anonymous, which is
>> puzzling to some (see
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108189).
>>
>> Now, there are a few BPF selftests that contain function declarations
>> that get arguments of anonymous struct types defined inline:
>>
>>   btf_dump_test_case_bitfields.c
>>   btf_dump_test_case_namespacing.c
>>   btf_dump_test_case_packing.c
>>   btf_dump_test_case_padding.c
>>   btf_dump_test_case_syntax.c
>>
>> The first four tests can easily be changed to no longer use anonymous
>> definitions of struct types in the formal arguments, since their purpose
>> (as far as I can see) is to test quirks related to struct fields and
>> other unrelated issue.  This makes them buildable with GCC with -Werror.
>> See diff below.
>>
>> However, btf_dump_test_case_syntax.c explicitly tests the dumping of a C
>> function like the above:
>>
>>  * - `fn_ptr2_t`: function, taking anonymous struct as a first arg and pointer
>>  *   to a function, that takes int and returns int, as a second arg; returning
>>  *   a pointer to a const pointer to a char. Equivalent to:
>>  *      typedef struct { int a; } s_t;
>>  *      typedef int (*fn_t)(int);
>>  *      typedef char * const * (*fn_ptr2_t)(s_t, fn_t);
>>
>> the function being:
>>
>>   typedef char * const * (*fn_ptr2_t)(struct {
>>         int a;
>>   }, int (*)(int));
>>
>> which is not really equivalent to the above because one is an anonymous
>> struct type, the other is named, and also the scope issue described
>> above.
>
> "Equivalent" in the conceptual sense to explain arcane C syntax.
>
>>
>> That makes me wonder, since this is testing the C generation from BTF,
>> what motivated this particular test?  Is there some particular code in
>> the kernel (or anywhere else) that uses anonymous struct types defined
>> in parameter lists?  If so, how are these functions used?
>
> I don't remember, but I'm not sure I'd be able to come up with such
> monstrosity by myself (but who knows...) I used vmlinux BTF and kept
> fixing and improving BTF dumper until I could dump everything in
> vmlinux BTF and make it compile without warnings (that's my
> recollection). So I suspect there is something in kernel that uses
> similar kind of declarations.

Yeah that's what I thought.  Such construction may become to happen in
headers because of some (perhaps unintended and unused) corner case of
application of macros, or who knows.  I wouldn't be comfortable removing
the test case.

>>
>> I understand the code above is legal C code, even if questionable in
>> practice, so perhaps the right thing to do is to build these selftests
>> with -Wno-error, because the warnings are actually expected?
>
> Is it possible to have #pragma equivalent of -Wno-error? That probably
> would be best. But yeah, we can just add -Wno-error to
> btf_dump_test_case_syntax.c in Makefile, if it's just one file.

Yes I will try with the pragma.

>>
>> diff --git a/tools/testing/selftests/bpf/progs/btf_dump_test_case_bitfields.c b/tools/testing/selftests/bpf/progs/btf_dump_test_case_bitfields.c
>> index e01690618e1e..7ee9f6fcb8d9 100644
>> --- a/tools/testing/selftests/bpf/progs/btf_dump_test_case_bitfields.c
>> +++ b/tools/testing/selftests/bpf/progs/btf_dump_test_case_bitfields.c
>> @@ -82,11 +82,12 @@ struct bitfield_flushed {
>>         long b: 16;
>>  };
>>
>> -int f(struct {
>> +struct root {
>>         struct bitfields_only_mixed_types _1;
>>         struct bitfield_mixed_with_others _2;
>>         struct bitfield_flushed _3;
>> -} *_)
>> +};
>> +int f(struct root *_)
>>  {
>>         return 0;
>>  }
>
> Changes like this are fine, if they don't change the order of type
> outputs (i.e., if tests still succeed with these changes, I have no
> objections).

Ok, I will prepare a patch for all this.
Thank you!

>> diff --git
>> a/tools/testing/selftests/bpf/progs/btf_dump_test_case_namespacing.c
>> b/tools/testing/selftests/bpf/progs/btf_dump_test_case_namespacing.c
>> index 92a4ad428710..0472183ed56d 100644
>
> [...]

      reply	other threads:[~2024-01-26  9:57 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-25 11:31 Anonymous struct types in parameter lists in BPF selftests Jose E. Marchesi
2024-01-25 14:08 ` Eduard Zingerman
2024-01-25 21:56 ` Andrii Nakryiko
2024-01-26  9:56   ` Jose E. Marchesi [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87frykwh7e.fsf@oracle.com \
    --to=jose.marchesi@oracle.com \
    --cc=andrii.nakryiko@gmail.com \
    --cc=andriin@fb.com \
    --cc=bpf@vger.kernel.org \
    --cc=cupertino.miranda@oracle.com \
    --cc=david.faust@oracle.com \
    --cc=eddyz87@gmail.com \
    --cc=yhs@meta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox