From: Rico Tzschichholz Date: Mon, 25 Mar 2024 14:34:52 +0000 (+0100) Subject: codegen: Properly pass through a null-terminated out argument X-Git-Tag: 0.56.17~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e6b64b7b80adfc28e5ba2d39c707cd38b31f976;p=thirdparty%2Fvala.git codegen: Properly pass through a null-terminated out argument --- diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala index dcb8f8bab..16f4f36c5 100644 --- a/codegen/valaccodemethodcallmodule.vala +++ b/codegen/valaccodemethodcallmodule.vala @@ -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)); diff --git a/tests/Makefile.am b/tests/Makefile.am index b8c41c5c2..605a5bed2 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 000000000..1a401d14f --- /dev/null +++ b/tests/methods/parameter-out-array-resize-null-terminated.c-expected @@ -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 +#include +#include + +#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 index 000000000..27337719b --- /dev/null +++ b/tests/methods/parameter-out-array-resize-null-terminated.vala @@ -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); + } +}