]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Properly pass through a null-terminated out argument
authorRico Tzschichholz <ricotz@ubuntu.com>
Mon, 25 Mar 2024 14:34:52 +0000 (15:34 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Mon, 15 Apr 2024 08:29:10 +0000 (10:29 +0200)
codegen/valaccodemethodcallmodule.vala
tests/Makefile.am
tests/methods/parameter-out-array-resize-null-terminated.c-expected [new file with mode: 0644]
tests/methods/parameter-out-array-resize-null-terminated.vala [new file with mode: 0644]

index dcb8f8bab59839dc8c0375bb21281f25730f3be9..16f4f36c57ae514b6403f34715cc9f234071f022 100644 (file)
@@ -1023,7 +1023,8 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                        store_value (unary.inner.target_value, transform_value (unary.target_value, unary.inner.value_type, arg), expr.source_reference);
 
                        // handle out null terminated arrays
-                       if (param != null && get_ccode_array_null_terminated (param)) {
+                       if (param != null && get_ccode_array_null_terminated (param)
+                           && unary.inner.symbol_reference != null && get_ccode_array_length (unary.inner.symbol_reference)) {
                                requires_array_length = true;
                                var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
                                len_call.add_argument (get_cvalue_ (unary.inner.target_value));
index b8c41c5c2ac6f3cd0e74c8c7c1ecf2aa5028867c..605a5bed2ca88fdf947ad957ee5896d26e0b6a8f 100644 (file)
@@ -199,6 +199,7 @@ TESTS = \
        methods/local-functions-to-delegate.vala \
        methods/parameter-fixed-array-initializer.vala \
        methods/parameter-out-free-on-error.vala \
+       methods/parameter-out-array-resize-null-terminated.vala \
        methods/parameter-ref-array-resize.vala \
        methods/parameter-ref-array-resize-captured.vala \
        methods/parameter-ref-array-resize-null-terminated.vala \
diff --git a/tests/methods/parameter-out-array-resize-null-terminated.c-expected b/tests/methods/parameter-out-array-resize-null-terminated.c-expected
new file mode 100644 (file)
index 0000000..1a401d1
--- /dev/null
@@ -0,0 +1,175 @@
+/* methods_parameter_out_array_resize_null_terminated.c generated by valac, the Vala compiler
+ * generated from methods_parameter_out_array_resize_null_terminated.vala, do not modify */
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#if !defined(VALA_STRICT_C)
+#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
+#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
+#elif defined(__clang__) && (__clang_major__ >= 16)
+#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
+#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
+#endif
+#endif
+#if !defined(VALA_EXTERN)
+#if defined(_MSC_VER)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+#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 foo (gchar*** bar);
+VALA_EXTERN void faz (gchar*** bar);
+static void _vala_main (void);
+static void _vala_array_destroy (gpointer array,
+                          gssize array_length,
+                          GDestroyNotify destroy_func);
+static void _vala_array_free (gpointer array,
+                       gssize array_length,
+                       GDestroyNotify destroy_func);
+static gssize _vala_array_length (gpointer array);
+
+void
+foo (gchar*** bar)
+{
+       gchar** _vala_bar = NULL;
+       gint _vala_bar_length1 = 0;
+       gchar* _tmp0_;
+       gchar* _tmp1_;
+       gchar* _tmp2_;
+       gchar* _tmp3_;
+       gchar** _tmp4_;
+       _tmp0_ = g_strdup ("foo");
+       _tmp1_ = g_strdup ("bar");
+       _tmp2_ = g_strdup ("manam");
+       _tmp3_ = g_strdup ("!");
+       _tmp4_ = g_new0 (gchar*, 4 + 1);
+       _tmp4_[0] = _tmp0_;
+       _tmp4_[1] = _tmp1_;
+       _tmp4_[2] = _tmp2_;
+       _tmp4_[3] = _tmp3_;
+       _vala_bar = (_vala_array_free (_vala_bar, _vala_array_length (_vala_bar), (GDestroyNotify) g_free), NULL);
+       _vala_bar = _tmp4_;
+       if (bar) {
+               *bar = _vala_bar;
+       } else {
+               _vala_bar = (_vala_array_free (_vala_bar, _vala_array_length (_vala_bar), (GDestroyNotify) g_free), NULL);
+       }
+}
+
+void
+faz (gchar*** bar)
+{
+       gchar** _vala_bar = NULL;
+       gint _vala_bar_length1 = 0;
+       gchar** _tmp0_ = NULL;
+       foo (&_tmp0_);
+       _vala_bar = (_vala_array_free (_vala_bar, _vala_array_length (_vala_bar), (GDestroyNotify) g_free), NULL);
+       _vala_bar = _tmp0_;
+       if (bar) {
+               *bar = _vala_bar;
+       } else {
+               _vala_bar = (_vala_array_free (_vala_bar, _vala_array_length (_vala_bar), (GDestroyNotify) g_free), NULL);
+       }
+}
+
+static void
+_vala_main (void)
+{
+       {
+               gchar** bar = NULL;
+               gint bar_length1 = 0;
+               gint _bar_size_ = 0;
+               gchar** _tmp0_ = NULL;
+               const gchar* _tmp1_;
+               const gchar* _tmp2_;
+               foo (&_tmp0_);
+               bar = (_vala_array_free (bar, bar_length1, (GDestroyNotify) g_free), NULL);
+               bar = _tmp0_;
+               bar_length1 = -1;
+               _bar_size_ = bar_length1;
+               bar_length1 = _vala_array_length (bar);
+               _vala_assert (bar_length1 == 4, "bar.length == 4");
+               _tmp1_ = bar[2];
+               _vala_assert (g_strcmp0 (_tmp1_, "manam") == 0, "bar[2] == \"manam\"");
+               _tmp2_ = bar[4];
+               _vala_assert (_tmp2_ == NULL, "bar[4] == null");
+               bar = (_vala_array_free (bar, bar_length1, (GDestroyNotify) g_free), NULL);
+       }
+       {
+               gchar** bar = NULL;
+               gint bar_length1 = 0;
+               gint _bar_size_ = 0;
+               gchar** _tmp3_ = NULL;
+               const gchar* _tmp4_;
+               const gchar* _tmp5_;
+               faz (&_tmp3_);
+               bar = (_vala_array_free (bar, bar_length1, (GDestroyNotify) g_free), NULL);
+               bar = _tmp3_;
+               bar_length1 = -1;
+               _bar_size_ = bar_length1;
+               bar_length1 = _vala_array_length (bar);
+               _vala_assert (bar_length1 == 4, "bar.length == 4");
+               _tmp4_ = bar[2];
+               _vala_assert (g_strcmp0 (_tmp4_, "manam") == 0, "bar[2] == \"manam\"");
+               _tmp5_ = bar[4];
+               _vala_assert (_tmp5_ == NULL, "bar[4] == null");
+               bar = (_vala_array_free (bar, bar_length1, (GDestroyNotify) g_free), NULL);
+       }
+}
+
+int
+main (int argc,
+      char ** argv)
+{
+       _vala_main ();
+       return 0;
+}
+
+static void
+_vala_array_destroy (gpointer array,
+                     gssize array_length,
+                     GDestroyNotify destroy_func)
+{
+       if ((array != NULL) && (destroy_func != NULL)) {
+               gssize i;
+               for (i = 0; i < array_length; i = i + 1) {
+                       if (((gpointer*) array)[i] != NULL) {
+                               destroy_func (((gpointer*) array)[i]);
+                       }
+               }
+       }
+}
+
+static void
+_vala_array_free (gpointer array,
+                  gssize array_length,
+                  GDestroyNotify destroy_func)
+{
+       _vala_array_destroy (array, array_length, destroy_func);
+       g_free (array);
+}
+
+static gssize
+_vala_array_length (gpointer array)
+{
+       gssize length;
+       length = 0;
+       if (array) {
+               while (((gpointer*) array)[length]) {
+                       length++;
+               }
+       }
+       return length;
+}
+
diff --git a/tests/methods/parameter-out-array-resize-null-terminated.vala b/tests/methods/parameter-out-array-resize-null-terminated.vala
new file mode 100644 (file)
index 0000000..2733771
--- /dev/null
@@ -0,0 +1,24 @@
+void foo ([CCode (array_length = false, array_null_terminated = true)] out string[] bar) {
+       bar = { "foo", "bar", "manam", "!" };
+}
+
+void faz ([CCode (array_length = false, array_null_terminated = true)] out string[] bar) {
+       foo (out bar);
+}
+
+void main () {
+       {
+               string[] bar;
+               foo (out bar);
+               assert (bar.length == 4);
+               assert (bar[2] == "manam");
+               assert (bar[4] == null);
+       }
+       {
+               string[] bar;
+               faz (out bar);
+               assert (bar.length == 4);
+               assert (bar[2] == "manam");
+               assert (bar[4] == null);
+       }
+}