From: Rico Tzschichholz Date: Fri, 15 Mar 2024 13:14:56 +0000 (+0100) Subject: parser: Allow declaration of static nested methods (local functions) X-Git-Tag: 0.56.17~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0247d6ed065ec3a3b3a45d3ec617d5a9d1ba9986;p=thirdparty%2Fvala.git parser: Allow declaration of static nested methods (local functions) Fixes https://gitlab.gnome.org/GNOME/vala/issues/1533 --- diff --git a/tests/Makefile.am b/tests/Makefile.am index b2e0d9019..0068d0b75 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -196,6 +196,7 @@ TESTS = \ methods/extern.vala \ methods/iterator.vala \ methods/local-functions.vala \ + methods/local-functions-to-delegate.vala \ methods/parameter-fixed-array-initializer.vala \ methods/parameter-out-free-on-error.vala \ methods/parameter-ref-array-resize.vala \ diff --git a/tests/methods/local-functions-to-delegate.c-expected b/tests/methods/local-functions-to-delegate.c-expected new file mode 100644 index 000000000..2dae0d488 --- /dev/null +++ b/tests/methods/local-functions-to-delegate.c-expected @@ -0,0 +1,160 @@ +/* methods_local_functions_to_delegate.c generated by valac, the Vala compiler + * generated from methods_local_functions_to_delegate.vala, do not modify */ + +#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 + +typedef gint (*Foo) (gint i, gpointer user_data); +typedef gint (*Bar) (gint i); +typedef gint (*_LocalFunc0_) (gint i, gpointer user_data); +typedef gint (*_LocalFunc1_) (gint i); +typedef struct _Block1Data Block1Data; +#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); + +struct _Block1Data { + int _ref_count_; + gint j; +}; + +VALA_EXTERN void foo (Foo f, + gpointer f_target); +VALA_EXTERN void bar (Bar b); +static void _vala_main (void); +static Block1Data* block1_data_ref (Block1Data* _data1_); +static void block1_data_unref (void * _userdata_); +static gint ___lambda4_ (Block1Data* _data1_, + gint i); +static gint ____lambda4___localfunc0_ (gint i, + gpointer self); +static gint ___lambda5_ (gint i); +static gint ____lambda5___localfunc1_ (gint i); + +void +foo (Foo f, + gpointer f_target) +{ + _vala_assert (f (13, f_target) == 39, "f (13) == 39"); +} + +void +bar (Bar b) +{ + _vala_assert (b (42) == 84, "b (42) == 84"); +} + +static Block1Data* +block1_data_ref (Block1Data* _data1_) +{ + g_atomic_int_inc (&_data1_->_ref_count_); + return _data1_; +} + +static void +block1_data_unref (void * _userdata_) +{ + Block1Data* _data1_; + _data1_ = (Block1Data*) _userdata_; + if (g_atomic_int_dec_and_test (&_data1_->_ref_count_)) { + g_slice_free (Block1Data, _data1_); + } +} + +static gint +___lambda4_ (Block1Data* _data1_, + gint i) +{ + gint result; + result = i * _data1_->j; + return result; +} + +static gint +____lambda4___localfunc0_ (gint i, + gpointer self) +{ + gint result; + result = ___lambda4_ (self, i); + return result; +} + +static gint +___lambda5_ (gint i) +{ + gint result; + result = 2 * i; + return result; +} + +static gint +____lambda5___localfunc1_ (gint i) +{ + gint result; + result = ___lambda5_ (i); + return result; +} + +static void +_vala_main (void) +{ + { + Block1Data* _data1_; + _LocalFunc0_ func = NULL; + gpointer func_target; + Foo f = NULL; + gpointer f_target; + GDestroyNotify f_target_destroy_notify; + _data1_ = g_slice_new0 (Block1Data); + _data1_->_ref_count_ = 1; + _data1_->j = 3; + func = ____lambda4___localfunc0_; + func_target = _data1_; + foo (func, func_target); + f = func; + f_target = func_target; + f_target_destroy_notify = NULL; + _vala_assert (f (23, f_target) == 69, "f (23) == 69"); + (f_target_destroy_notify == NULL) ? NULL : (f_target_destroy_notify (f_target), NULL); + f = NULL; + f_target = NULL; + f_target_destroy_notify = NULL; + block1_data_unref (_data1_); + _data1_ = NULL; + } + { + _LocalFunc1_ func = NULL; + Bar b = NULL; + func = ____lambda5___localfunc1_; + bar (func); + b = func; + _vala_assert (b (23) == 46, "b (23) == 46"); + } +} + +int +main (int argc, + char ** argv) +{ + _vala_main (); + return 0; +} + diff --git a/tests/methods/local-functions-to-delegate.vala b/tests/methods/local-functions-to-delegate.vala new file mode 100644 index 000000000..394080bab --- /dev/null +++ b/tests/methods/local-functions-to-delegate.vala @@ -0,0 +1,35 @@ +delegate int Foo (int i); + +[CCode (has_target = false)] +delegate int Bar (int i); + +void foo (Foo f) { + assert (f (13) == 39); +} + +void bar (Bar b) { + assert (b (42) == 84); +} + +void main () { + { + int j = 3; + int func (int i) { + return i * j; + } + foo (func); + + Foo f = func; + assert (f (23) == 69); + } + { + static int func (int i) { + return 2 * i; + } + bar (func); + + Bar b = func; + assert (b (23) == 46); + } +} + diff --git a/vala/valaparser.vala b/vala/valaparser.vala index 60107afba..31d285595 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -1934,6 +1934,7 @@ public class Vala.Parser : CodeVisitor { var begin = get_location (); try { + accept (TokenType.STATIC); skip_type (); if (accept (TokenType.IDENTIFIER) && accept (TokenType.OPEN_PARENS)) { rollback (begin); @@ -2166,6 +2167,7 @@ public class Vala.Parser : CodeVisitor { void parse_local_function_declaration (Block block) throws ParseError { var begin = get_location (); + var is_static = accept (TokenType.STATIC); var type = parse_type (true, false); var sym = parse_symbol_name (); @@ -2181,6 +2183,7 @@ public class Vala.Parser : CodeVisitor { var src = get_src (begin); var d = new Delegate ("_LocalFunc%i_".printf (next_local_func_id++), type, src); + d.has_target = !is_static; foreach (var param in params) { d.add_parameter (param); }