[vala] codegen: Fix capturing generic variables having instance type parameters



commit 7ec69c78840cd3a5fe88de35784a9a3592c7b5dc
Author: Luca Bruno <lucabru src gnome org>
Date:   Tue Nov 1 11:54:14 2011 +0100

    codegen: Fix capturing generic variables having instance type parameters
    
    Fixes bug 663134.

 codegen/valaccodebasemodule.vala |   41 +++++++++++++++++++++++++++----------
 tests/Makefile.am                |    1 +
 tests/objects/bug663134.vala     |   20 ++++++++++++++++++
 3 files changed, 51 insertions(+), 11 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 47d3004..d008e1f 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -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)));
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4185195..180cacc 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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
index 0000000..fe8cc00
--- /dev/null
+++ b/tests/objects/bug663134.vala
@@ -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 ();
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]