[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <d2399574-ec64-7765-b6ef-1e792a7e0d5c@rasmusvillemoes.dk>
Date: Tue, 30 Aug 2022 11:41:31 +0200
From: Rasmus Villemoes <linux@...musvillemoes.dk>
To: Bart Van Assche <bvanassche@....org>,
Kees Cook <keescook@...omium.org>
Cc: linux-kernel@...r.kernel.org,
Andrew Morton <akpm@...ux-foundation.org>,
Arnd Bergmann <arnd@...db.de>,
Dan Williams <dan.j.williams@...el.com>,
Eric Dumazet <edumazet@...gle.com>,
Ingo Molnar <mingo@...hat.com>,
Isabella Basso <isabbasso@...eup.net>,
"Jason A. Donenfeld" <Jason@...c4.com>,
Josh Poimboeuf <jpoimboe@...nel.org>,
Luc Van Oostenryck <luc.vanoostenryck@...il.com>,
Masami Hiramatsu <mhiramat@...nel.org>,
Nathan Chancellor <nathan@...nel.org>,
Peter Zijlstra <peterz@...radead.org>,
Sander Vanheule <sander@...nheule.net>,
Steven Rostedt <rostedt@...dmis.org>,
Vlastimil Babka <vbabka@...e.cz>,
Yury Norov <yury.norov@...il.com>
Subject: Re: [PATCH 1/2] testing/selftests: Add tests for the is_signed_type()
macro
On 26/08/2022 18.21, Bart Van Assche wrote:
> Although not documented, is_signed_type() must support the 'bool' and
> pointer types next to scalar and enumeration types. Add a selftest that
> verifies that this macro handles all supported types correctly.
>
> +static void is_signed_type_test(struct kunit *test)
> +{
> + KUNIT_EXPECT_EQ(test, is_signed_type(bool), false);
> + KUNIT_EXPECT_EQ(test, is_signed_type(signed char), true);
> + KUNIT_EXPECT_EQ(test, is_signed_type(unsigned char), false);
Nice. You could consider adding
#ifdef __UNSIGNED_CHAR__
KUNIT_EXPECT_EQ(test, is_signed_type(char), false);
#else
KUNIT_EXPECT_EQ(test, is_signed_type(char), true);
#endif
The kernel depends on the compiler providing __UNSIGNED_CHAR__ in two
places (one in ext4, one in printf test suite).
> + KUNIT_EXPECT_EQ(test, is_signed_type(int), true);
> + KUNIT_EXPECT_EQ(test, is_signed_type(unsigned int), false);
> + KUNIT_EXPECT_EQ(test, is_signed_type(long), true);
> + KUNIT_EXPECT_EQ(test, is_signed_type(unsigned long), false);
> + KUNIT_EXPECT_EQ(test, is_signed_type(long long), true);
> + KUNIT_EXPECT_EQ(test, is_signed_type(unsigned long long), false);
> + KUNIT_EXPECT_EQ(test, is_signed_type(enum unsigned_enum), false);
> + KUNIT_EXPECT_EQ(test, is_signed_type(enum signed_enum), true);
Yeah. But enum types are one of the weirdest aspects of C. Taking your
example and expanding with a positive value that doesn't fit an int:
#include <stdio.h>
#define is_signed_type(t) ((t)-1 < (t)1)
#define typeinfo(t) printf("%-24s signed %d, size %zu\n", #t,
is_signed_type(t), sizeof(t))
enum unsigned_enum {
constant_a = 3,
constant_d = 3000000000,
};
enum signed_enum {
constant_b = -1,
constant_c = 2,
};
int main(int argc, char *argv[])
{
enum unsigned_enum a = constant_a;
enum unsigned_enum d = constant_d;
enum signed_enum b = constant_b;
enum signed_enum c = constant_c;
typeinfo(enum unsigned_enum);
typeinfo(enum signed_enum);
typeinfo(typeof(constant_a));
typeinfo(typeof(constant_b));
typeinfo(typeof(constant_c));
typeinfo(typeof(constant_d));
typeinfo(typeof(a));
typeinfo(typeof(b));
typeinfo(typeof(c));
typeinfo(typeof(d));
return 0;
}
This gives me
enum unsigned_enum signed 0, size 4
enum signed_enum signed 1, size 4
typeof(constant_a) signed 1, size 4
typeof(constant_b) signed 1, size 4
typeof(constant_c) signed 1, size 4
typeof(constant_d) signed 0, size 4
typeof(a) signed 0, size 4
typeof(b) signed 1, size 4
typeof(c) signed 1, size 4
typeof(d) signed 0, size 4
That is, typeof(constant_a) is not the same type (different signedness)
as enum unsigned_enum! While both constant_d (due to its size) and
variables declared as 'enum unsigned_enum' do indeed have that
underlying unsigned type.
At least gcc and clang agree on this weirdness, but I haven't been able
to find a spec mandating this. Anyway, this was just an aside.
Acked-by: Rasmus Villemoes <linux@...musvillemoes.dk>
Powered by blists - more mailing lists