lkml.org 
[lkml]   [2022]   [Aug]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
SubjectRe: [PATCH 1/2] testing/selftests: Add tests for the is_signed_type() macro
From
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@rasmusvillemoes.dk>

\
 
 \ /
  Last update: 2022-08-30 11:41    [W:0.145 / U:0.148 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site