]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Fix capturing generic variables having instance type parameters
authorLuca Bruno <lucabru@src.gnome.org>
Tue, 1 Nov 2011 10:54:14 +0000 (11:54 +0100)
committerLuca Bruno <lucabru@src.gnome.org>
Tue, 1 Nov 2011 10:57:52 +0000 (11:57 +0100)
Fixes bug 663134.

codegen/valaccodebasemodule.vala
tests/Makefile.am
tests/objects/bug663134.vala [new file with mode: 0644]

index 47d3004dfcd94ae6b547c186d23f65da4dc011e7..d008e1f16a47a364899e2e8712d342bfd3083bcb 100644 (file)
@@ -1905,18 +1905,21 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_ref_count_")));
                        ccode.open_if (ccall);
 
-                       if (parent_block != null) {
-                               int parent_block_id = get_block_id (parent_block);
-
-                               var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (parent_block_id)));
-                               unref_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)));
-                               ccode.add_expression (unref_call);
-                               ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), new CCodeConstant ("NULL"));
-                       } else {
-                               if (get_this_type () != null) {
-                                       var this_value = new GLibValue (get_data_type_for_symbol (current_type_symbol), new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "self"), true);
-                                       ccode.add_expression (destroy_value (this_value));
+                       if (get_this_type () != null) {
+                               // assign "self" for type parameters
+                               CCodeExpression cself = new CCodeIdentifier ("_data%d_".printf (block_id));
+                               unowned Block parent_closure_block = b;
+                               while (true) {
+                                       parent_closure_block = next_closure_block (parent_closure_block.parent_symbol);
+                                       if (parent_closure_block == null) {
+                                               break;
+                                       }
+                                       int parent_block_id = get_block_id (parent_closure_block);
+                                       cself = new CCodeMemberAccess.pointer (cself, "_data%d_".printf (parent_block_id));
                                }
+                               cself = new CCodeMemberAccess.pointer (cself, "self");
+                               ccode.add_declaration ("%s *".printf (get_ccode_name (current_type_symbol)), new CCodeVariableDeclarator ("self"));
+                               ccode.add_assignment (new CCodeIdentifier ("self"), cself);
                        }
 
                        // free in reverse order
@@ -1980,6 +1983,22 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                }
                        }
 
+                       // free parent block and "self" after captured variables
+                       // because they may require type parameters
+                       if (parent_block != null) {
+                               int parent_block_id = get_block_id (parent_block);
+
+                               var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (parent_block_id)));
+                               unref_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)));
+                               ccode.add_expression (unref_call);
+                               ccode.add_assignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), new CCodeConstant ("NULL"));
+                       } else {
+                               if (get_this_type () != null) {
+                                       var this_value = new GLibValue (get_data_type_for_symbol (current_type_symbol), new CCodeIdentifier ("self"), true);
+                                       ccode.add_expression (destroy_value (this_value));
+                               }
+                       }
+
                        var data_free = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
                        data_free.add_argument (new CCodeIdentifier (struct_name));
                        data_free.add_argument (new CCodeIdentifier ("_data%d_".printf (block_id)));
index 4185195c4f8bd172fef10f2b877361611c523a09..180caccf261af9f133623be8135803776219dc2a 100644 (file)
@@ -115,6 +115,7 @@ TESTS = \
        objects/bug646792.vala \
        objects/bug653138.vala \
        objects/bug654702.vala \
+       objects/bug663134.vala \
        errors/errors.vala \
        errors/bug567181.vala \
        errors/bug579101.vala \
diff --git a/tests/objects/bug663134.vala b/tests/objects/bug663134.vala
new file mode 100644 (file)
index 0000000..fe8cc00
--- /dev/null
@@ -0,0 +1,20 @@
+public class Foo<T> {
+       public void bar () {
+               T baz = null;
+               SourceFunc f = () => {
+                       baz = null;
+                       SourceFunc ff = () => {
+                               baz = null;
+                               return false;
+                       };
+                       ff ();
+                       return false;
+               };
+               f ();
+       }
+}
+
+void main () {
+       var foo = new Foo<string> ();
+       foo.bar ();
+}