From: Valeri Ochinski Date: Sat, 9 Dec 2023 12:29:31 +0000 (+0300) Subject: vala: Treat negative integer/float ranks as non-compatible X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e4fe55735fb3e151dd6340b6d3fb8acca38193a4;p=thirdparty%2Fvala.git vala: Treat negative integer/float ranks as non-compatible This allows to improve type safety for handle types. --- diff --git a/tests/Makefile.am b/tests/Makefile.am index 1685cc188..36c582eac 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -42,6 +42,9 @@ AM_TESTS_ENVIRONMENT = \ TESTS = \ basic-types/gassert.vala \ basic-types/integer-literals.vala \ + basic-types/integer-negative-rank-incompatible.test \ + basic-types/integer-negative-rank-incompatible2.test \ + basic-types/integer-negative-rank-incompatible3.test \ basic-types/integer-signed-binary-erange.test \ basic-types/integer-signed-erange.test \ basic-types/integer-signed-erange2.test \ @@ -54,6 +57,7 @@ TESTS = \ basic-types/integers-binary.vala \ basic-types/integers.vala \ basic-types/integers-boxed-cast.vala \ + basic-types/integers-negative-rank.vala \ basic-types/integers-octal-invalid.test \ basic-types/integers-octal.vala \ basic-types/escape-chars.vala \ diff --git a/tests/basic-types/integer-negative-rank-incompatible.test b/tests/basic-types/integer-negative-rank-incompatible.test new file mode 100644 index 000000000..df0c64842 --- /dev/null +++ b/tests/basic-types/integer-negative-rank-incompatible.test @@ -0,0 +1,16 @@ +Invalid Code + +[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)] +[IntegerType (rank = -1)] +struct FooHandle { +} + +[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)] +[IntegerType (rank = -1)] +struct BarHandle { +} + +void main () { + FooHandle foo = 42; + BarHandle bar = foo; +} diff --git a/tests/basic-types/integer-negative-rank-incompatible2.test b/tests/basic-types/integer-negative-rank-incompatible2.test new file mode 100644 index 000000000..f15c70f09 --- /dev/null +++ b/tests/basic-types/integer-negative-rank-incompatible2.test @@ -0,0 +1,11 @@ +Invalid Code + +[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)] +[IntegerType (rank = -1)] +struct FooHandle { +} + +void main () { + FooHandle foo = 42; + int bar = foo; +} diff --git a/tests/basic-types/integer-negative-rank-incompatible3.test b/tests/basic-types/integer-negative-rank-incompatible3.test new file mode 100644 index 000000000..2956a0a58 --- /dev/null +++ b/tests/basic-types/integer-negative-rank-incompatible3.test @@ -0,0 +1,11 @@ +Invalid Code + +[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)] +[IntegerType (rank = -1)] +struct BarHandle { +} + +void main () { + int foo = 42; + BarHandle bar = foo; +} diff --git a/tests/basic-types/integers-negative-rank.c-expected b/tests/basic-types/integers-negative-rank.c-expected new file mode 100644 index 000000000..a65dec5d6 --- /dev/null +++ b/tests/basic-types/integers-negative-rank.c-expected @@ -0,0 +1,73 @@ +/* basic_types_integers_negative_rank.c generated by valac, the Vala compiler + * generated from basic_types_integers_negative_rank.vala, do not modify */ + +#include +#include + +typedef int32_t gint; +typedef gint BarHandle; +#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg); +#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; } +#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; } +#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg); + +static void _vala_main (void); + +static void +_vala_main (void) +{ + { + gint foo = 0; + foo = 0; + _vala_assert (foo == 0, "foo == 0"); + } + { + gint foo = 0; + foo = -1; + _vala_assert (foo == -1, "foo == -1"); + } + { + gint foo = 0; + foo = 42; + _vala_assert (foo == 42, "foo == 42"); + foo = 64; + _vala_assert (foo == 64, "foo == 64"); + } + { + gint foo = 0; + BarHandle bar = 0; + foo = 36; + bar = (BarHandle) 64; + foo = (gint) bar; + _vala_assert (foo == 64, "foo == 64"); + foo = 88; + bar = (BarHandle) foo; + _vala_assert (((gint) bar) == 88, "bar == 88"); + } + { + gint foo = 0; + BarHandle bar = 0; + guint baz = 0U; + foo = 99; + bar = (BarHandle) foo; + _vala_assert (((gint) bar) == 99, "bar == 99"); + baz = (guint) bar; + _vala_assert (baz == ((guint) 99), "baz == 99"); + } + { + gint foo = 0; + gint baz = 0; + foo = 28; + baz = (gint) foo; + _vala_assert (baz == 28, "baz == 28"); + } +} + +int +main (int argc, + char ** argv) +{ + _vala_main (); + return 0; +} + diff --git a/tests/basic-types/integers-negative-rank.vala b/tests/basic-types/integers-negative-rank.vala new file mode 100644 index 000000000..cc35b92c0 --- /dev/null +++ b/tests/basic-types/integers-negative-rank.vala @@ -0,0 +1,50 @@ +[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)] +[IntegerType (rank = -1)] +struct FooHandle { +} + +struct BarHandle : FooHandle { +} + +[IntegerType (rank = -2)] +[CCode (cname = "gint", cheader_filename = "glib.h", default_value = "0", has_type_id = false)] +struct BazHandle { +} + +void main () { + { + FooHandle foo = 0; + assert (foo == 0); + } + { + FooHandle foo = -1; + assert (foo == -1); + } + { + FooHandle foo = 42; + assert (foo == 42); + foo = 64; + assert (foo == 64); + } + { + FooHandle foo = 36; + BarHandle bar = 64; + foo = bar; + assert (foo == 64); + foo = 88; + bar = foo; + assert (bar == 88); + } + { + int foo = 99; + BarHandle bar = (BarHandle) foo; + assert (bar == 99); + uint baz = (uint) bar; + assert (baz == 99); + } + { + FooHandle foo = 28; + BazHandle baz = (BazHandle) foo; + assert (baz == 28); + } +} diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala index 897eaf72c..939a6a9e7 100644 --- a/vala/valadatatype.vala +++ b/vala/valadatatype.vala @@ -369,26 +369,33 @@ public abstract class Vala.DataType : CodeNode { if (type_symbol is Struct && target_type.type_symbol is Struct) { unowned Struct expr_struct = (Struct) type_symbol; - unowned Struct expect_struct = (Struct) target_type.type_symbol; + unowned Struct target_struct = (Struct) target_type.type_symbol; - /* integer types may be implicitly cast to floating point types */ - if (expr_struct.is_integer_type () && expect_struct.is_floating_type ()) { + // Allow compatibility of struct subtypes in both ways + if (target_struct.is_subtype_of (expr_struct)) { return true; } - if ((expr_struct.is_integer_type () && expect_struct.is_integer_type ()) || - (expr_struct.is_floating_type () && expect_struct.is_floating_type ())) { - if (expr_struct.rank <= expect_struct.rank) { - return true; - } + // Negative ranks are used for handle types that are not implicitly convertible + if ((expr_struct.is_integer_type () || expr_struct.is_floating_type ()) && expr_struct.rank < 0) { + return false; + } else if ((target_struct.is_integer_type () || target_struct.is_floating_type ()) && target_struct.rank < 0) { + return false; } - if (expr_struct.is_boolean_type () && expect_struct.is_boolean_type ()) { + /* integer types may be implicitly cast to floating point types */ + if (expr_struct.is_integer_type () && target_struct.is_floating_type ()) { return true; } - // Allow compatibility of struct subtypes in both ways - if (expect_struct.is_subtype_of (expr_struct)) { + if ((expr_struct.is_integer_type () && target_struct.is_integer_type ()) || + (expr_struct.is_floating_type () && target_struct.is_floating_type ())) { + if (expr_struct.rank <= target_struct.rank) { + return true; + } + } + + if (expr_struct.is_boolean_type () && target_struct.is_boolean_type ()) { return true; } }