]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
parser: Allow declaration of static nested methods (local functions)
authorRico Tzschichholz <ricotz@ubuntu.com>
Fri, 15 Mar 2024 13:14:56 +0000 (14:14 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Tue, 19 Mar 2024 08:35:53 +0000 (09:35 +0100)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/1533

tests/Makefile.am
tests/methods/local-functions-to-delegate.c-expected [new file with mode: 0644]
tests/methods/local-functions-to-delegate.vala [new file with mode: 0644]
vala/valaparser.vala

index b2e0d9019ab7362675cb47008282c67d3f9f709d..0068d0b7510e6207d0aaa83d23e7b916e78ec73e 100644 (file)
@@ -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 (file)
index 0000000..2dae0d4
--- /dev/null
@@ -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 <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
+
+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 (file)
index 0000000..394080b
--- /dev/null
@@ -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);
+       }
+}
+
index 60107afbaef5a238c5eee1da21798c3a983e7aa0..31d285595ad01691dc46189fa31fb4d93c54cbf8 100644 (file)
@@ -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);
                }