]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Perform required casts for generic types of return-values and in/out-parameters
authorRico Tzschichholz <ricotz@ubuntu.com>
Tue, 31 Jan 2023 14:43:57 +0000 (15:43 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Tue, 31 Jan 2023 14:43:57 +0000 (15:43 +0100)
Found by -Werror=int-conversion

Fixes https://gitlab.gnome.org/GNOME/vala/issues/1407

codegen/valaccodebasemodule.vala
codegen/valaccodemethodcallmodule.vala
tests/Makefile.am
tests/generics/method-return-cast.c-expected [new file with mode: 0644]
tests/generics/method-return-cast.vala [new file with mode: 0644]
tests/generics/parameter-in-cast.c-expected [new file with mode: 0644]
tests/generics/parameter-in-cast.vala [new file with mode: 0644]
tests/generics/parameter-out-cast.c-expected [new file with mode: 0644]
tests/generics/parameter-out-cast.vala [new file with mode: 0644]

index 5d765c314b43f8efe083b49d605f317d8705f4df..cf72070eb7c0d90928d7a3acc147c6bd93a311cc 100644 (file)
@@ -4181,6 +4181,8 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        CCodeExpression result_lhs = get_cexpression ("result");
                        if (current_return_type.is_real_non_null_struct_type () && !is_in_coroutine ()) {
                                result_lhs = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, result_lhs);
+                       } else if (current_return_type is GenericType) {
+                               set_cvalue (stmt.return_expression, convert_to_generic_pointer (get_cvalue (stmt.return_expression), stmt.return_expression.value_type));
                        }
                        ccode.add_assignment (result_lhs, get_cvalue (stmt.return_expression));
                }
@@ -4341,6 +4343,8 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                        set_cvalue (expr, convert_to_generic_pointer (get_cvalue (expr), expr.target_type));
                                        ((GLibValue) expr.target_value).lvalue = false;
                                }
+                       } else if (expr.formal_target_type is GenericType && !(expr.value_type is GenericType)) {
+                               set_cvalue (expr, convert_to_generic_pointer (get_cvalue (expr), expr.value_type));
                        }
 
                        // Allow null to initialize non-null struct inside initializer list
index 6332271ad744c334f28ef276ae2773485a6e7839..95087b535a2a62adc23dfd167333c46bd27e57b5 100644 (file)
@@ -509,6 +509,8 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                                                        carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_delegate_target_destroy_notify (arg)));
                                                                }
                                                        }
+                                               } else if (param.variable_type is GenericType) {
+                                                       set_cvalue (arg, convert_from_generic_pointer (get_cvalue (arg), arg.target_type));
                                                }
                                        }
 
index f8ddab9194a8ac69daef0cee9ae83839c359e4e0..518b892a936ccacff2b4dcf508d8447b9c3f2ef1 100644 (file)
@@ -798,11 +798,14 @@ TESTS = \
        generics/integer-type-cast.vala \
        generics/integer-type-cast-return.vala \
        generics/parameter-invalid-initializer.test \
+       generics/parameter-in-cast.vala \
+       generics/parameter-out-cast.vala \
        generics/parameter-sizeof-initializer.vala \
        generics/member-dup-destroy.vala \
        generics/method-parameter-type-missing.test \
        generics/method-parameter-unknown-type-parameter.test \
        generics/method-parameter-unknown-type-parameter-2.test \
+       generics/method-return-cast.vala \
        generics/method-return-type-missing.test \
        generics/method-return-unknown-type-parameter.test \
        generics/method-return-unknown-type-parameter-2.test \
diff --git a/tests/generics/method-return-cast.c-expected b/tests/generics/method-return-cast.c-expected
new file mode 100644 (file)
index 0000000..08e05f3
--- /dev/null
@@ -0,0 +1,127 @@
+/* generics_method_return_cast.c generated by valac, the Vala compiler
+ * generated from generics_method_return_cast.vala, do not modify */
+
+#include <glib.h>
+#include <glib-object.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+#define _g_free0(var) (var = (g_free (var), NULL))
+#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);
+
+VALA_EXTERN gboolean get_bool (void);
+VALA_EXTERN gpointer minim_b (GType t_type,
+                  GBoxedCopyFunc t_dup_func,
+                  GDestroyNotify t_destroy_func);
+VALA_EXTERN guint32 get_uint32 (void);
+VALA_EXTERN gpointer minim_u (GType t_type,
+                  GBoxedCopyFunc t_dup_func,
+                  GDestroyNotify t_destroy_func);
+VALA_EXTERN gchar* get_string (void);
+VALA_EXTERN gpointer minim_s (GType t_type,
+                  GBoxedCopyFunc t_dup_func,
+                  GDestroyNotify t_destroy_func);
+static void _vala_main (void);
+
+gboolean
+get_bool (void)
+{
+       gboolean result;
+       result = TRUE;
+       return result;
+}
+
+gpointer
+minim_b (GType t_type,
+         GBoxedCopyFunc t_dup_func,
+         GDestroyNotify t_destroy_func)
+{
+       gpointer result;
+       result = (gpointer) ((gintptr) get_bool ());
+       return result;
+}
+
+guint32
+get_uint32 (void)
+{
+       guint32 result;
+       result = (guint32) 42U;
+       return result;
+}
+
+gpointer
+minim_u (GType t_type,
+         GBoxedCopyFunc t_dup_func,
+         GDestroyNotify t_destroy_func)
+{
+       gpointer result;
+       result = (gpointer) ((guintptr) get_uint32 ());
+       return result;
+}
+
+gchar*
+get_string (void)
+{
+       gchar* _tmp0_;
+       gchar* result;
+       _tmp0_ = g_strdup ("bar");
+       result = _tmp0_;
+       return result;
+}
+
+gpointer
+minim_s (GType t_type,
+         GBoxedCopyFunc t_dup_func,
+         GDestroyNotify t_destroy_func)
+{
+       gchar* _tmp0_;
+       gpointer result;
+       _tmp0_ = get_string ();
+       result = _tmp0_;
+       return result;
+}
+
+static void
+_vala_main (void)
+{
+       {
+               gpointer _tmp0_;
+               _tmp0_ = minim_b (G_TYPE_BOOLEAN, NULL, NULL);
+               _vala_assert (((gboolean) ((gintptr) _tmp0_)) == TRUE, "minim_b<bool> () == true");
+       }
+       {
+               gpointer _tmp1_;
+               _tmp1_ = minim_u (G_TYPE_UINT, NULL, NULL);
+               _vala_assert (((guint32) ((guintptr) _tmp1_)) == ((guint32) 42U), "minim_u<uint32> () == 42U");
+       }
+       {
+               gpointer _tmp2_;
+               gchar* _tmp3_;
+               _tmp2_ = minim_s (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free);
+               _tmp3_ = (gchar*) _tmp2_;
+               _vala_assert (g_strcmp0 (_tmp3_, "bar") == 0, "minim_s<string> () == \"bar\"");
+               _g_free0 (_tmp3_);
+       }
+}
+
+int
+main (int argc,
+      char ** argv)
+{
+       _vala_main ();
+       return 0;
+}
+
diff --git a/tests/generics/method-return-cast.vala b/tests/generics/method-return-cast.vala
new file mode 100644 (file)
index 0000000..ae3bc8d
--- /dev/null
@@ -0,0 +1,35 @@
+bool get_bool () {
+       return true;
+}
+
+T minim_b<T> () {
+       return get_bool ();
+}
+
+uint32 get_uint32 () {
+       return 42U;
+}
+
+T minim_u<T> () {
+       return get_uint32 ();
+}
+
+string get_string () {
+       return "bar";
+}
+
+T minim_s<T> () {
+       return get_string ();
+}
+
+void main () {
+       {
+               assert (minim_b<bool> () == true);
+       }
+       {
+               assert (minim_u<uint32> () == 42U);
+       }
+       {
+               assert (minim_s<string> () == "bar");
+       }
+}
diff --git a/tests/generics/parameter-in-cast.c-expected b/tests/generics/parameter-in-cast.c-expected
new file mode 100644 (file)
index 0000000..2c70aae
--- /dev/null
@@ -0,0 +1,172 @@
+/* generics_parameter_in_cast.c generated by valac, the Vala compiler
+ * generated from generics_parameter_in_cast.vala, do not modify */
+
+#include <glib-object.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+#define _g_free0(var) (var = (g_free (var), NULL))
+#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);
+
+VALA_EXTERN gpointer manam (GType t_type,
+                GBoxedCopyFunc t_dup_func,
+                GDestroyNotify t_destroy_func,
+                gconstpointer foo);
+VALA_EXTERN gboolean get_bool (void);
+VALA_EXTERN gpointer minim_b (GType t_type,
+                  GBoxedCopyFunc t_dup_func,
+                  GDestroyNotify t_destroy_func);
+VALA_EXTERN guint32 get_uint32 (void);
+VALA_EXTERN gpointer minim_u (GType t_type,
+                  GBoxedCopyFunc t_dup_func,
+                  GDestroyNotify t_destroy_func);
+VALA_EXTERN gchar* get_string (void);
+VALA_EXTERN gpointer minim_s (GType t_type,
+                  GBoxedCopyFunc t_dup_func,
+                  GDestroyNotify t_destroy_func);
+static void _vala_main (void);
+
+gpointer
+manam (GType t_type,
+       GBoxedCopyFunc t_dup_func,
+       GDestroyNotify t_destroy_func,
+       gconstpointer foo)
+{
+       gpointer _tmp0_;
+       gpointer result;
+       _tmp0_ = ((foo != NULL) && (t_dup_func != NULL)) ? t_dup_func ((gpointer) foo) : ((gpointer) foo);
+       result = _tmp0_;
+       return result;
+}
+
+gboolean
+get_bool (void)
+{
+       gboolean result;
+       result = TRUE;
+       return result;
+}
+
+gpointer
+minim_b (GType t_type,
+         GBoxedCopyFunc t_dup_func,
+         GDestroyNotify t_destroy_func)
+{
+       gpointer _tmp0_;
+       gpointer result;
+       _tmp0_ = manam (t_type, (GBoxedCopyFunc) t_dup_func, (GDestroyNotify) t_destroy_func, (gpointer) ((gintptr) get_bool ()));
+       result = _tmp0_;
+       return result;
+}
+
+guint32
+get_uint32 (void)
+{
+       guint32 result;
+       result = (guint32) 23U;
+       return result;
+}
+
+gpointer
+minim_u (GType t_type,
+         GBoxedCopyFunc t_dup_func,
+         GDestroyNotify t_destroy_func)
+{
+       gpointer _tmp0_;
+       gpointer result;
+       _tmp0_ = manam (t_type, (GBoxedCopyFunc) t_dup_func, (GDestroyNotify) t_destroy_func, (gpointer) ((guintptr) get_uint32 ()));
+       result = _tmp0_;
+       return result;
+}
+
+gchar*
+get_string (void)
+{
+       gchar* _tmp0_;
+       gchar* result;
+       _tmp0_ = g_strdup ("bar");
+       result = _tmp0_;
+       return result;
+}
+
+gpointer
+minim_s (GType t_type,
+         GBoxedCopyFunc t_dup_func,
+         GDestroyNotify t_destroy_func)
+{
+       gchar* _tmp0_;
+       gchar* _tmp1_;
+       gpointer _tmp2_;
+       gpointer _tmp3_;
+       gpointer result;
+       _tmp0_ = get_string ();
+       _tmp1_ = _tmp0_;
+       _tmp2_ = manam (t_type, (GBoxedCopyFunc) t_dup_func, (GDestroyNotify) t_destroy_func, _tmp1_);
+       _tmp3_ = _tmp2_;
+       _g_free0 (_tmp1_);
+       result = _tmp3_;
+       return result;
+}
+
+static void
+_vala_main (void)
+{
+       {
+               gpointer _tmp0_;
+               gpointer _tmp1_;
+               _tmp0_ = manam (G_TYPE_BOOLEAN, NULL, NULL, (gpointer) ((gintptr) get_bool ()));
+               _vala_assert (((gboolean) ((gintptr) _tmp0_)) == TRUE, "manam<bool> (get_bool ()) == true");
+               _tmp1_ = minim_b (G_TYPE_BOOLEAN, NULL, NULL);
+               _vala_assert (((gboolean) ((gintptr) _tmp1_)) == TRUE, "minim_b<bool> () == true");
+       }
+       {
+               gpointer _tmp2_;
+               gpointer _tmp3_;
+               _tmp2_ = manam (G_TYPE_UINT, NULL, NULL, (gpointer) ((guintptr) get_uint32 ()));
+               _vala_assert (((guint32) ((guintptr) _tmp2_)) == ((guint32) 23U), "manam<uint32> (get_uint32 ()) == 23U");
+               _tmp3_ = minim_u (G_TYPE_UINT, NULL, NULL);
+               _vala_assert (((guint32) ((guintptr) _tmp3_)) == ((guint32) 23U), "minim_u<uint32> () == 23U");
+       }
+       {
+               gchar* _tmp4_;
+               gchar* _tmp5_;
+               gpointer _tmp6_;
+               gchar* _tmp7_;
+               gpointer _tmp8_;
+               gchar* _tmp9_;
+               _tmp4_ = get_string ();
+               _tmp5_ = _tmp4_;
+               _tmp6_ = manam (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free, _tmp5_);
+               _tmp7_ = (gchar*) _tmp6_;
+               _vala_assert (g_strcmp0 (_tmp7_, "bar") == 0, "manam<string> (get_string ()) == \"bar\"");
+               _g_free0 (_tmp7_);
+               _g_free0 (_tmp5_);
+               _tmp8_ = minim_s (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free);
+               _tmp9_ = (gchar*) _tmp8_;
+               _vala_assert (g_strcmp0 (_tmp9_, "bar") == 0, "minim_s<string> () == \"bar\"");
+               _g_free0 (_tmp9_);
+       }
+}
+
+int
+main (int argc,
+      char ** argv)
+{
+       _vala_main ();
+       return 0;
+}
+
diff --git a/tests/generics/parameter-in-cast.vala b/tests/generics/parameter-in-cast.vala
new file mode 100644 (file)
index 0000000..270b744
--- /dev/null
@@ -0,0 +1,42 @@
+T manam<T> (T foo) {
+       return foo;
+}
+
+bool get_bool () {
+       return true;
+}
+
+T minim_b<T> () {
+       return manam<T> (get_bool ());
+}
+
+uint32 get_uint32 () {
+       return 23U;
+}
+
+T minim_u<T> () {
+       return manam<T> (get_uint32 ());
+}
+
+string get_string () {
+       return "bar";
+}
+
+T minim_s<T> () {
+       return manam<T> (get_string ());
+}
+
+void main () {
+       {
+               assert (manam<bool> (get_bool ()) == true);
+               assert (minim_b<bool> () == true);
+       }
+       {
+               assert (manam<uint32> (get_uint32 ()) == 23U);
+               assert (minim_u<uint32> () == 23U);
+       }
+       {
+               assert (manam<string> (get_string ()) == "bar");
+               assert (minim_s<string> () == "bar");
+       }
+}
diff --git a/tests/generics/parameter-out-cast.c-expected b/tests/generics/parameter-out-cast.c-expected
new file mode 100644 (file)
index 0000000..a14f175
--- /dev/null
@@ -0,0 +1,86 @@
+/* generics_parameter_out_cast.c generated by valac, the Vala compiler
+ * generated from generics_parameter_out_cast.vala, do not modify */
+
+#include <glib-object.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+#define _g_free0(var) (var = (g_free (var), NULL))
+#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);
+
+VALA_EXTERN void manam (GType t_type,
+            GBoxedCopyFunc t_dup_func,
+            GDestroyNotify t_destroy_func,
+            gconstpointer foo,
+            gpointer* bar);
+static void _vala_main (void);
+
+void
+manam (GType t_type,
+       GBoxedCopyFunc t_dup_func,
+       GDestroyNotify t_destroy_func,
+       gconstpointer foo,
+       gpointer* bar)
+{
+       gpointer _vala_bar = NULL;
+       gpointer _tmp0_;
+       _tmp0_ = ((foo != NULL) && (t_dup_func != NULL)) ? t_dup_func ((gpointer) foo) : ((gpointer) foo);
+       ((_vala_bar == NULL) || (t_destroy_func == NULL)) ? NULL : (_vala_bar = (t_destroy_func (_vala_bar), NULL));
+       _vala_bar = _tmp0_;
+       if (bar) {
+               *bar = _vala_bar;
+       } else {
+               ((_vala_bar == NULL) || (t_destroy_func == NULL)) ? NULL : (_vala_bar = (t_destroy_func (_vala_bar), NULL));
+       }
+}
+
+static void
+_vala_main (void)
+{
+       {
+               gboolean bar = FALSE;
+               gpointer _tmp0_ = NULL;
+               manam (G_TYPE_BOOLEAN, NULL, NULL, (gpointer) ((gintptr) TRUE), &_tmp0_);
+               bar = (gboolean) ((gintptr) _tmp0_);
+               _vala_assert (bar == TRUE, "bar == true");
+       }
+       {
+               guint32 bar = 0U;
+               gpointer _tmp1_ = NULL;
+               manam (G_TYPE_UINT, NULL, NULL, (gpointer) ((guintptr) 23U), &_tmp1_);
+               bar = (guint32) ((guintptr) _tmp1_);
+               _vala_assert (bar == ((guint32) 23U), "bar == 23U");
+       }
+       {
+               gchar* bar = NULL;
+               gpointer _tmp2_ = NULL;
+               manam (G_TYPE_STRING, (GBoxedCopyFunc) g_strdup, (GDestroyNotify) g_free, "bar", &_tmp2_);
+               _g_free0 (bar);
+               bar = (gchar*) _tmp2_;
+               _vala_assert (g_strcmp0 (bar, "bar") == 0, "bar == \"bar\"");
+               _g_free0 (bar);
+       }
+}
+
+int
+main (int argc,
+      char ** argv)
+{
+       _vala_main ();
+       return 0;
+}
+
diff --git a/tests/generics/parameter-out-cast.vala b/tests/generics/parameter-out-cast.vala
new file mode 100644 (file)
index 0000000..110ffc9
--- /dev/null
@@ -0,0 +1,21 @@
+void manam<T> (T foo, out T bar) {
+       bar = foo;
+}
+
+void main () {
+       {
+               bool bar;
+               manam<bool> (true, out bar);
+               assert (bar == true);
+       }
+       {
+               uint32 bar;
+               manam<uint32> (23U, out bar);
+               assert (bar == 23U);
+       }
+       {
+               string bar;
+               manam<string> ("bar", out bar);
+               assert (bar == "bar");
+       }
+}