From: Jürg Billeter Date: Wed, 28 Oct 2009 15:10:29 +0000 (+0100) Subject: GAsync: Fix temporary variable initialization in loops X-Git-Tag: 0.7.8~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3eba8bfcff9f42e5971bc31980d9f317d1782a88;p=thirdparty%2Fvala.git GAsync: Fix temporary variable initialization in loops Fixes bug 599568. --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 4da1f2157..84c066fde 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -2718,44 +2718,57 @@ internal class Vala.CCodeBaseModule : CCodeModule { public void append_temp_decl (CCodeFragment cfrag, List temp_vars) { foreach (LocalVariable local in temp_vars) { + var cdecl = new CCodeDeclaration (local.variable_type.get_cname ()); + + var vardecl = new CCodeVariableDeclarator (local.name, null, local.variable_type.get_cdeclarator_suffix ()); + // sets #line + local.ccodenode = vardecl; + cdecl.add_declarator (vardecl); + + var st = local.variable_type.data_type as Struct; + var array_type = local.variable_type as ArrayType; + + if (local.name.has_prefix ("*")) { + // do not dereference unintialized variable + // initialization is not needed for these special + // pointer temp variables + // used to avoid side-effects in assignments + } else if (local.no_init) { + // no initialization necessary for this temp var + } else if (!local.variable_type.nullable && + (st != null && !st.is_simple_type ()) || + (array_type != null && array_type.fixed_length)) { + // 0-initialize struct with struct initializer { 0 } + // necessary as they will be passed by reference + var clist = new CCodeInitializerList (); + clist.append (new CCodeConstant ("0")); + + vardecl.initializer = clist; + vardecl.init0 = true; + } else if (local.variable_type.is_reference_type_or_type_parameter () || + local.variable_type.nullable) { + vardecl.initializer = new CCodeConstant ("NULL"); + vardecl.init0 = true; + } + if (current_method != null && current_method.coroutine) { closure_struct.add_field (local.variable_type.get_cname (), local.name); - // no initialization necessary, closure struct is zeroed - } else { - var cdecl = new CCodeDeclaration (local.variable_type.get_cname ()); - - var vardecl = new CCodeVariableDeclarator (local.name, null, local.variable_type.get_cdeclarator_suffix ()); - // sets #line - local.ccodenode = vardecl; - cdecl.add_declarator (vardecl); - - var st = local.variable_type.data_type as Struct; - var array_type = local.variable_type as ArrayType; - - if (local.name.has_prefix ("*")) { - // do not dereference unintialized variable - // initialization is not needed for these special - // pointer temp variables - // used to avoid side-effects in assignments - } else if (local.no_init) { - // no initialization necessary for this temp var - } else if (!local.variable_type.nullable && - (st != null && !st.is_simple_type ()) || - (array_type != null && array_type.fixed_length)) { - // 0-initialize struct with struct initializer { 0 } - // necessary as they will be passed by reference - var clist = new CCodeInitializerList (); - clist.append (new CCodeConstant ("0")); - - vardecl.initializer = clist; - vardecl.init0 = true; - } else if (local.variable_type.is_reference_type_or_type_parameter () || - local.variable_type.nullable) { - vardecl.initializer = new CCodeConstant ("NULL"); - vardecl.init0 = true; + // even though closure struct is zerod, we need to initialize temporary variables + // as they might be used multiple times when declared in a loop + + if (vardecl.initializer is CCodeInitializerList) { + // C does not support initializer lists in assignments, use memset instead + source_declarations.add_include ("string.h"); + var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset")); + memset_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (local.name))); + memset_call.add_argument (new CCodeConstant ("0")); + memset_call.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (local.variable_type.get_cname ()))); + cfrag.append (new CCodeExpressionStatement (memset_call)); + } else if (vardecl.initializer != null) { + cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (local.name), vardecl.initializer))); } - + } else { cfrag.append (cdecl); } } diff --git a/tests/Makefile.am b/tests/Makefile.am index fa289a392..4773f3a18 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -69,6 +69,7 @@ TESTS = \ asynchronous/bug598677.vala \ asynchronous/bug598697.vala \ asynchronous/bug598698.vala \ + asynchronous/bug599568.vala \ dbus/basic-types.test \ dbus/arrays.test \ dbus/async.test \ diff --git a/tests/asynchronous/bug599568.vala b/tests/asynchronous/bug599568.vala new file mode 100644 index 000000000..77a66fd6d --- /dev/null +++ b/tests/asynchronous/bug599568.vala @@ -0,0 +1,9 @@ +async void do_foo () { + for (int i = 0; i < 2; i++) { + Value value = 42; + } +} + +void main () { + do_foo (); +}