]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Treat negative integer/float ranks as non-compatible
authorValeri Ochinski <v19930312@gmail.com>
Sat, 9 Dec 2023 12:29:31 +0000 (15:29 +0300)
committerRico Tzschichholz <ricotz@ubuntu.com>
Tue, 12 Dec 2023 10:06:40 +0000 (11:06 +0100)
This allows to improve type safety for handle types.

tests/Makefile.am
tests/basic-types/integer-negative-rank-incompatible.test [new file with mode: 0644]
tests/basic-types/integer-negative-rank-incompatible2.test [new file with mode: 0644]
tests/basic-types/integer-negative-rank-incompatible3.test [new file with mode: 0644]
tests/basic-types/integers-negative-rank.c-expected [new file with mode: 0644]
tests/basic-types/integers-negative-rank.vala [new file with mode: 0644]
vala/valadatatype.vala

index 1685cc188e1a88a4c5348debccdf79a07eb8d870..36c582eac8132eab6d843c0fe691ae04f01dc08d 100644 (file)
@@ -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 (file)
index 0000000..df0c648
--- /dev/null
@@ -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 (file)
index 0000000..f15c70f
--- /dev/null
@@ -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 (file)
index 0000000..2956a0a
--- /dev/null
@@ -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 (file)
index 0000000..a65dec5
--- /dev/null
@@ -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 <stdint.h>
+#include <glib.h>
+
+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 (file)
index 0000000..cc35b92
--- /dev/null
@@ -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);
+       }
+}
index 897eaf72c391999acf36d3f6849b3f6769889660..939a6a9e73e05a656f3fb5318f387be55d9cf200 100644 (file)
@@ -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;
                        }
                }