[vala] codegen: Avoid name clashes in the closure struct



commit 335636be07c27950791179dc77354d2916c9468a
Author: Luca Bruno <lucabru src gnome org>
Date:   Mon Apr 11 18:08:23 2011 +0200

    codegen: Avoid name clashes in the closure struct
    
    Fixes bug 596861.

 codegen/valaccodebasemodule.vala         |   51 +++++++++++++++++++++++-------
 codegen/valaccodecontrolflowmodule.vala  |   32 +++++++++---------
 codegen/valaccodememberaccessmodule.vala |   24 +++++++-------
 codegen/valagasyncmodule.vala            |    1 -
 codegen/valagerrormodule.vala            |    2 +-
 tests/Makefile.am                        |    1 +
 tests/asynchronous/bug596861.vala        |   19 +++++++++++
 7 files changed, 88 insertions(+), 42 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index ee23a6d..29feb48 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -39,6 +39,8 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 		public bool current_method_inner_error;
 		public bool current_method_return;
 		public Map<string,string> variable_name_map = new HashMap<string,string> (str_hash, str_equal);
+		public Map<string,int> closure_variable_count_map = new HashMap<string,int> (str_hash, str_equal);
+		public Map<LocalVariable,int> closure_variable_clash_map = new HashMap<LocalVariable,int> ();
 
 		public EmitContext (Symbol? symbol = null) {
 			current_symbol = symbol;
@@ -1785,18 +1787,18 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 				if (local.captured) {
 					generate_type_declaration (local.variable_type, cfile);
 
-					data.add_field (get_ccode_name (local.variable_type), get_variable_cname (local.name) + get_ccode_declarator_suffix (local.variable_type));
+					data.add_field (get_ccode_name (local.variable_type), get_local_cname (local) + get_ccode_declarator_suffix (local.variable_type));
 
 					if (local.variable_type is ArrayType) {
 						var array_type = (ArrayType) local.variable_type;
 						for (int dim = 1; dim <= array_type.rank; dim++) {
-							data.add_field ("gint", get_array_length_cname (get_variable_cname (local.name), dim));
+							data.add_field ("gint", get_array_length_cname (get_local_cname (local), dim));
 						}
-						data.add_field ("gint", get_array_size_cname (get_variable_cname (local.name)));
+						data.add_field ("gint", get_array_size_cname (get_local_cname (local)));
 					} else if (local.variable_type is DelegateType) {
-						data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (local.name)));
+						data.add_field ("gpointer", get_delegate_target_cname (get_local_cname (local)));
 						if (local.variable_type.value_owned) {
-							data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
+							data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_local_cname (local)));
 						}
 					}
 				}
@@ -2042,6 +2044,14 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 		stmt.declaration.accept (this);
 	}
 
+	public CCodeExpression get_local_cexpression (LocalVariable local) {
+		if (is_in_coroutine ()) {
+			return new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_local_cname (local));
+		} else {
+			return new CCodeIdentifier (get_local_cname (local));
+		}
+	}
+
 	public CCodeExpression get_variable_cexpression (string name) {
 		if (is_in_coroutine ()) {
 			return new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), get_variable_cname (name));
@@ -2050,6 +2060,17 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 		}
 	}
 
+	public string get_local_cname (LocalVariable local) {
+		var cname = get_variable_cname (local.name);
+		if (is_in_coroutine ()) {
+			var clash_index = emit_context.closure_variable_clash_map.get (local);
+			if (clash_index > 0) {
+				cname = "_vala%d_%s".printf (clash_index, cname);
+			}
+		}
+		return cname;
+	}
+
 	public string get_variable_cname (string name) {
 		if (name[0] == '.') {
 			if (name == ".result") {
@@ -2104,10 +2125,16 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 		}
 
 		if (!local.captured) {
-			if (current_method != null && current_method.coroutine) {
-				closure_struct.add_field (get_ccode_name (local.variable_type), get_variable_cname (local.name) + get_ccode_declarator_suffix (local.variable_type));
+			if (is_in_coroutine ()) {
+				var count = emit_context.closure_variable_count_map.get (local.name);
+				if (count > 0) {
+					emit_context.closure_variable_clash_map.set (local, count);
+				}
+				emit_context.closure_variable_count_map.set (local.name, count + 1);
+
+				closure_struct.add_field (get_ccode_name (local.variable_type), get_local_cname (local) + get_ccode_declarator_suffix (local.variable_type));
 			} else {
-				var cvar = new CCodeVariableDeclarator (get_variable_cname (local.name), null, get_ccode_declarator_suffix (local.variable_type));
+				var cvar = new CCodeVariableDeclarator (get_local_cname (local), null, get_ccode_declarator_suffix (local.variable_type));
 
 				// try to initialize uninitialized variables
 				// initialization not necessary for variables stored in closure
@@ -2125,13 +2152,13 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 
 				if (!array_type.fixed_length) {
 					for (int dim = 1; dim <= array_type.rank; dim++) {
-						var len_var = new LocalVariable (int_type.copy (), get_array_length_cname (get_variable_cname (local.name), dim));
+						var len_var = new LocalVariable (int_type.copy (), get_array_length_cname (get_local_cname (local), dim));
 						len_var.no_init = local.initializer != null;
 						emit_temp_var (len_var);
 					}
 
 					if (array_type.rank == 1) {
-						var size_var = new LocalVariable (int_type.copy (), get_array_size_cname (get_variable_cname (local.name)));
+						var size_var = new LocalVariable (int_type.copy (), get_array_size_cname (get_local_cname (local)));
 						size_var.no_init = local.initializer != null;
 						emit_temp_var (size_var);
 					}
@@ -2141,11 +2168,11 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 				var d = deleg_type.delegate_symbol;
 				if (d.has_target) {
 					// create variable to store delegate target
-					var target_var = new LocalVariable (new PointerType (new VoidType ()), get_delegate_target_cname (get_variable_cname (local.name)));
+					var target_var = new LocalVariable (new PointerType (new VoidType ()), get_delegate_target_cname (get_local_cname (local)));
 					target_var.no_init = local.initializer != null;
 					emit_temp_var (target_var);
 					if (deleg_type.value_owned) {
-						var target_destroy_notify_var = new LocalVariable (gdestroynotify_type, get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
+						var target_destroy_notify_var = new LocalVariable (gdestroynotify_type, get_delegate_target_destroy_notify_cname (get_local_cname (local)));
 						target_destroy_notify_var.no_init = local.initializer != null;
 						emit_temp_var (target_destroy_notify_var);
 					}
diff --git a/codegen/valaccodecontrolflowmodule.vala b/codegen/valaccodecontrolflowmodule.vala
index faec8f4..5a4c297 100644
--- a/codegen/valaccodecontrolflowmodule.vala
+++ b/codegen/valaccodecontrolflowmodule.vala
@@ -232,7 +232,7 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
 		}
 
 		visit_local_variable (collection_backup);
-		ccode.add_assignment (get_variable_cexpression (collection_backup.name), get_cvalue (stmt.collection));
+		ccode.add_assignment (get_variable_cexpression (get_local_cname (collection_backup)), get_cvalue (stmt.collection));
 		
 		if (stmt.tree_can_fail && stmt.collection.tree_can_fail) {
 			// exception handling
@@ -245,11 +245,11 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
 			var array_len = get_array_length_cexpression (stmt.collection);
 
 			// store array length for use by _vala_array_free
-			ccode.add_assignment (get_variable_cexpression (get_array_length_cname (collection_backup.name, 1)), array_len);
+			ccode.add_assignment (get_variable_cexpression (get_array_length_cname (get_local_cname (collection_backup), 1)), array_len);
 
 			var iterator_variable = new LocalVariable (int_type.copy (), stmt.variable_name + "_it");
-			emit_temp_var (iterator_variable);
-			var it_name = get_variable_cname (iterator_variable.name);
+			visit_local_variable (iterator_variable);
+			var it_name = get_local_cname (iterator_variable);
 		
 			var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (it_name), array_len);
 
@@ -257,20 +257,20 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
 			                   ccond,
 			                   new CCodeAssignment (get_variable_cexpression (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (it_name), new CCodeConstant ("1"))));
 
-			CCodeExpression element_expr = new CCodeElementAccess (get_variable_cexpression (collection_backup.name), get_variable_cexpression (it_name));
+			CCodeExpression element_expr = new CCodeElementAccess (get_variable_cexpression (get_local_cname (collection_backup)), get_variable_cexpression (it_name));
 
 			var element_type = array_type.element_type.copy ();
 			element_type.value_owned = false;
 			element_expr = get_cvalue_ (transform_value (new GLibValue (element_type, element_expr, true), stmt.type_reference, stmt));
 
 			visit_local_variable (stmt.element_variable);
-			ccode.add_assignment (get_variable_cexpression (stmt.variable_name), element_expr);
+			ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr);
 
 			// set array length for stacked arrays
 			if (stmt.type_reference is ArrayType) {
 				var inner_array_type = (ArrayType) stmt.type_reference;
 				for (int dim = 1; dim <= inner_array_type.rank; dim++) {
-					ccode.add_assignment (get_variable_cexpression (get_array_length_cname (stmt.variable_name, dim)), new CCodeConstant ("-1"));
+					ccode.add_assignment (get_variable_cexpression (get_array_length_cname (get_local_cname (stmt.element_variable), dim)), new CCodeConstant ("-1"));
 				}
 			}
 
@@ -281,12 +281,12 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
 			// iterating over a GList or GSList
 
 			var iterator_variable = new LocalVariable (collection_type.copy (), stmt.variable_name + "_it");
-			emit_temp_var (iterator_variable);
-			var it_name = get_variable_cname (iterator_variable.name);
+			visit_local_variable (iterator_variable);
+			var it_name = get_local_cname (iterator_variable);
 			
 			var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (it_name), new CCodeConstant ("NULL"));
 
-			ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), get_variable_cexpression (collection_backup.name)),
+			ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), get_variable_cexpression (get_local_cname (collection_backup))),
 							ccond,
 							new CCodeAssignment (get_variable_cexpression (it_name), new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "next")));
 
@@ -304,7 +304,7 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
 			element_expr = get_cvalue_ (transform_value (new GLibValue (element_data_type, element_expr), stmt.type_reference, stmt));
 
 			visit_local_variable (stmt.element_variable);
-			ccode.add_assignment (get_variable_cexpression (stmt.variable_name), element_expr);
+			ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr);
 
 			stmt.body.emit (this);
 
@@ -313,17 +313,17 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
 			// iterating over a GValueArray
 
 			var iterator_variable = new LocalVariable (uint_type.copy (), "%s_index".printf (stmt.variable_name));
-			emit_temp_var (iterator_variable);
-			var arr_index = get_variable_cname (iterator_variable.name);
+			visit_local_variable (iterator_variable);
+			var arr_index = get_variable_cname (get_local_cname (iterator_variable));
 
-			var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (collection_backup.name), "n_values"));
+			var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (get_local_cname (collection_backup)), "n_values"));
 
 			ccode.open_for (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0")),
 			                   ccond,
 			                   new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1"))));
 
 			var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_get_nth"));
-			get_item.add_argument (get_variable_cexpression (collection_backup.name));
+			get_item.add_argument (get_variable_cexpression (get_local_cname (collection_backup)));
 			get_item.add_argument (get_variable_cexpression (arr_index));
 
 			CCodeExpression element_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_item);
@@ -333,7 +333,7 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
 			}
 
 			visit_local_variable (stmt.element_variable);
-			ccode.add_assignment (get_variable_cexpression (stmt.variable_name), element_expr);
+			ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr);
 
 			stmt.body.emit (this);
 
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala
index c4f75aa..818773f 100644
--- a/codegen/valaccodememberaccessmodule.vala
+++ b/codegen/valaccodememberaccessmodule.vala
@@ -336,39 +336,39 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 		} else if (local.captured) {
 			// captured variables are stored on the heap
 			var block = (Block) local.parent_symbol;
-			result.cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_variable_cname (local.name));
+			result.cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_local_cname (local));
 			if (array_type != null && !array_type.fixed_length) {
 				for (int dim = 1; dim <= array_type.rank; dim++) {
-					result.append_array_length_cvalue (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_array_length_cname (get_variable_cname (local.name), dim)));
+					result.append_array_length_cvalue (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_array_length_cname (get_local_cname (local), dim)));
 				}
 				if (array_type.rank == 1) {
-					result.array_size_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_array_size_cname (get_variable_cname (local.name)));
+					result.array_size_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_array_size_cname (get_local_cname (local)));
 				}
 			} else if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
-				result.delegate_target_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_cname (get_variable_cname (local.name)));
+				result.delegate_target_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_cname (get_local_cname (local)));
 				if (delegate_type.value_owned) {
-					result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
+					result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), get_delegate_target_destroy_notify_cname (get_local_cname (local)));
 				}
 			}
 		} else {
-			result.cvalue = get_variable_cexpression (local.name);
+			result.cvalue = get_local_cexpression (local);
 			if (array_type != null && !array_type.fixed_length) {
 				for (int dim = 1; dim <= array_type.rank; dim++) {
-					result.append_array_length_cvalue (get_variable_cexpression (get_array_length_cname (get_variable_cname (local.name), dim)));
+					result.append_array_length_cvalue (get_variable_cexpression (get_array_length_cname (get_local_cname (local), dim)));
 				}
 				if (array_type.rank == 1) {
-					result.array_size_cvalue = get_variable_cexpression (get_array_size_cname (get_variable_cname (local.name)));
+					result.array_size_cvalue = get_variable_cexpression (get_array_size_cname (get_local_cname (local)));
 				}
 			} else if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
 				if (is_in_coroutine ()) {
-					result.delegate_target_cvalue = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), get_delegate_target_cname (get_variable_cname (local.name)));
+					result.delegate_target_cvalue = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), get_delegate_target_cname (get_local_cname (local)));
 					if (local.variable_type.value_owned) {
-						result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
+						result.delegate_target_destroy_notify_cvalue = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data_"), get_delegate_target_destroy_notify_cname (get_local_cname (local)));
 					}
 				} else {
-					result.delegate_target_cvalue = new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (local.name)));
+					result.delegate_target_cvalue = new CCodeIdentifier (get_delegate_target_cname (get_local_cname (local)));
 					if (local.variable_type.value_owned) {
-						result.delegate_target_destroy_notify_cvalue = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
+						result.delegate_target_destroy_notify_cvalue = new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_local_cname (local)));
 					}
 				}
 			}
diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala
index a7c4af1..64ec2b5 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -386,7 +386,6 @@ public class Vala.GAsyncModule : GSignalModule {
 		}
 	}
 
-
 	void generate_finish_function (Method m) {
 		push_context (new EmitContext ());
 
diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala
index 10a080a..23d11a3 100644
--- a/codegen/valagerrormodule.vala
+++ b/codegen/valagerrormodule.vala
@@ -346,7 +346,7 @@ public class Vala.GErrorModule : CCodeDelegateModule {
 
 		if (clause.error_variable != null) {
 			visit_local_variable (clause.error_variable);
-			ccode.add_assignment (get_variable_cexpression (clause.error_variable.name), get_variable_cexpression ("_inner_error_"));
+			ccode.add_assignment (get_variable_cexpression (get_local_cname (clause.error_variable)), get_variable_cexpression ("_inner_error_"));
 		} else {
 			// error object is not used within catch statement, clear it
 			var cclear = new CCodeFunctionCall (new CCodeIdentifier ("g_clear_error"));
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 303be72..1ce7421 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -123,6 +123,7 @@ TESTS = \
 	asynchronous/bug595735.vala \
 	asynchronous/bug595755.vala \
 	asynchronous/bug596177.vala \
+	asynchronous/bug596861.vala \
 	asynchronous/bug597294.vala \
 	asynchronous/bug598677.vala \
 	asynchronous/bug598697.vala \
diff --git a/tests/asynchronous/bug596861.vala b/tests/asynchronous/bug596861.vala
new file mode 100644
index 0000000..f73ccfa
--- /dev/null
+++ b/tests/asynchronous/bug596861.vala
@@ -0,0 +1,19 @@
+async int foo () throws Error {
+	try {
+		yield foo ();
+	} catch (Error e) {
+		try {
+			yield foo ();
+		} catch (Error e) {
+			return 0;
+		}
+	}
+	foreach (var e in new int[]{1,2,3}) {
+	}
+	foreach (var e in new int[]{1,2,3}) {
+	}
+	return 0;
+}
+
+void main() {
+}



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