diff --git a/ccode/valaccodeblock.vala b/ccode/valaccodeblock.vala
index cff8613..6876bb0 100644
--- a/ccode/valaccodeblock.vala
+++ b/ccode/valaccodeblock.vala
@@ -50,6 +50,10 @@ public class Vala.CCodeBlock : CCodeStatement {
 		statements.add (statement);
 	}
 	
+	public ReadOnlyList<CCodeNode> get_statements () {
+		return new ReadOnlyList<CCodeNode> (statements);
+	}
+	
 	public override void write (CCodeWriter writer) {
 		// the last reachable statement
 		CCodeNode last_statement = null;
diff --git a/codegen/valaccodeassignmentmodule.vala b/codegen/valaccodeassignmentmodule.vala
index ab079ea..a0e3e47 100644
--- a/codegen/valaccodeassignmentmodule.vala
+++ b/codegen/valaccodeassignmentmodule.vala
@@ -234,6 +234,16 @@ internal class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
 			assignment.error = true;
 			return;
 		}
+		
+		/* Check whether any variables are being changed by this assignment */
+		var left = assignment.left.symbol_reference as LocalVariable;
+		if (left != null) {
+			current_block.set_variable_changed (left);
+		}
+		var right = assignment.right.symbol_reference as LocalVariable;
+		if (right != null && assignment.right.value_type.value_owned) {
+			current_block.set_variable_changed (right);
+		}
 
 		if (assignment.left.symbol_reference is Property) {
 			assignment.ccodenode = emit_property_assignment (assignment);
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index bea64e0..e66820a 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -37,6 +37,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 	public Method current_method;
 	public DataType current_return_type;
 	public TryStatement current_try;
+	public Block current_block;
 	public PropertyAccessor current_property_accessor;
 
 	public CCodeDeclarationSpace header_declarations;
@@ -1474,6 +1475,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 	public override void visit_block (Block b) {
 		var old_symbol = current_symbol;
 		current_symbol = b;
+		var old_block = current_block;
+		current_block = b;
 
 		b.accept_children (codegen);
 
@@ -1525,6 +1528,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		b.ccodenode = cblock;
 
 		current_symbol = old_symbol;
+		current_block = old_block;
 	}
 
 	public override void visit_empty_statement (EmptyStatement stmt) {
@@ -2280,7 +2284,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		stmt.ccodenode = cfrag;
 	}
 
-	public void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop = false) {
+	public virtual void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop = false) {
 		var b = (Block) sym;
 
 		var local_vars = b.get_local_variables ();
@@ -2387,16 +2391,21 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
 		return found;
 	}
+	
+	public virtual bool variable_changed_in_finally (LocalVariable local) {
+		return false;
+	}
 
 	public override void visit_return_statement (ReturnStatement stmt) {
 		// avoid unnecessary ref/unref pair
 		if (stmt.return_expression != null) {
 			var local = stmt.return_expression.symbol_reference as LocalVariable;
 			if (current_return_type.value_owned
-			    && local != null && local.variable_type.value_owned) {
+			    && local != null && local.variable_type.value_owned && !variable_changed_in_finally (local)) {
 				/* return expression is local variable taking ownership and
 				 * current method is transferring ownership */
 
+				
 				// don't ref expression
 				stmt.return_expression.value_type.value_owned = true;
 			}
@@ -2426,7 +2435,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			// avoid unnecessary ref/unref pair
 			var local = stmt.return_expression.symbol_reference as LocalVariable;
 			if (current_return_type.value_owned
-			    && local != null && local.variable_type.value_owned) {
+			    && local != null && local.variable_type.value_owned && !variable_changed_in_finally (local)) {
 				/* return expression is local variable taking ownership and
 				 * current method is transferring ownership */
 
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index f62ff3a..239424f 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -33,6 +33,13 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 	public override void visit_method_call (MethodCall expr) {
 		expr.accept_children (codegen);
 
+		foreach (var arg in expr.get_argument_list ()) {
+			var local = arg.symbol_reference as LocalVariable;
+			if (local != null && arg.value_type.value_owned) {
+				current_block.set_variable_changed (local);
+			}
+		}
+
 		// the bare function call
 		var ccall = new CCodeFunctionCall ((CCodeExpression) expr.call.ccodenode);
 
diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala
index 90e9552..5bcb182 100644
--- a/codegen/valagerrormodule.vala
+++ b/codegen/valagerrormodule.vala
@@ -267,19 +267,15 @@ internal class Vala.GErrorModule : CCodeDelegateModule {
 		if (stmt.finally_body != null) {
 			stmt.finally_body.accept (codegen);
 		}
-
+		
 		stmt.body.accept (codegen);
-
-		current_try = old_try;
-		current_try_id = old_try_id;
-
+		
 		foreach (CatchClause clause in stmt.get_catch_clauses ()) {
 			clause.accept (codegen);
 		}
 
-		if (stmt.finally_body != null) {
-			stmt.finally_body.accept (codegen);
-		}
+		current_try = old_try;
+		current_try_id = old_try_id;
 
 		var cfrag = new CCodeFragment ();
 		cfrag.append (stmt.body.ccodenode);
@@ -344,6 +340,40 @@ internal class Vala.GErrorModule : CCodeDelegateModule {
 
 		clause.ccodenode = cfrag;
 	}
+	
+	
+	public override void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop = false) {
+	
+		var finally_block = (Block) null;
+		if (sym.parent_node is TryStatement)
+			finally_block = (sym.parent_node as TryStatement).finally_body;
+		else if (sym.parent_node is CatchClause)
+			finally_block = (sym.parent_node.parent_node as TryStatement).finally_body;
+			
+		if (finally_block != null) {
+			cfrag.append (finally_block.ccodenode);
+		}
+		
+		base.append_local_free (sym, cfrag, stop_at_loop);
+	}
+	
+	// Scans all the finally block for the presence of assignment to the returned variable
+	public override bool variable_changed_in_finally (LocalVariable variable)
+	{
+		if (current_try == null) return false;
+	
+		var sym = current_symbol;
+	
+		while (!(sym is Method)) {
+			if (sym.parent_node is TryStatement && ((TryStatement) sym.parent_node).finally_body != null) {
+				if (((TryStatement) sym.parent_node).finally_body.changes_variable (variable)) return true;
+			}
+		
+			sym = sym.parent_symbol;
+		}
+		
+		return false;
+	}
 }
 
 // vim:sw=8 noet
diff --git a/vala/valablock.vala b/vala/valablock.vala
index 9c99ec8..470fd13 100644
--- a/vala/valablock.vala
+++ b/vala/valablock.vala
@@ -35,6 +35,8 @@ public class Vala.Block : Symbol, Statement {
 
 	private Gee.List<Statement> statement_list = new ArrayList<Statement> ();
 	private Gee.List<LocalVariable> local_variables = new ArrayList<LocalVariable> ();
+	private Gee.Set<LocalVariable> changed_variables = new HashSet<LocalVariable> ((a) => str_hash ((a as Symbol).name),
+	                                                                               (a, b) => str_equal ((a as Symbol).name, (b as Symbol).name));
 	
 	/**
 	 * Creates a new block.
@@ -100,6 +102,14 @@ public class Vala.Block : Symbol, Statement {
 	public void remove_local_variable (LocalVariable local) {
 		local_variables.remove (local);
 	}
+	
+	public void set_variable_changed (LocalVariable local) {
+		changed_variables.add (local);
+	}
+	
+	public bool changes_variable (LocalVariable local) {
+		return changed_variables.contains (local);
+	}
 
 	/**
 	 * Returns a copy of the list of local variables.
diff --git a/vala/valacatchclause.vala b/vala/valacatchclause.vala
index 8d3d412..4187cb2 100644
--- a/vala/valacatchclause.vala
+++ b/vala/valacatchclause.vala
@@ -47,12 +47,28 @@ public class Vala.CatchClause : CodeNode {
 	/**
 	 * Specifies the error handler body.
 	 */
-	public Block body { get; set; }
+	public Block body {
+		get {
+			return _body;
+		}
+		set {
+			_body = value;
+			_body.parent_node = this;
+		}
+	}
 	
 	/**
 	 * Specifies the declarator for the generated error variable.
 	 */
-	public LocalVariable error_variable { get; set; }
+	public LocalVariable error_variable {
+		get {
+			return _error_variable;
+		}
+		set {
+			_error_variable = value;
+			_error_variable.parent_node = this;
+		}
+	}
 
 	/**
 	 * Specifies the label used for this catch clause in the C code.
@@ -61,6 +77,9 @@ public class Vala.CatchClause : CodeNode {
 
 	private DataType _data_type;
 
+	private Block _body;
+	private LocalVariable _error_variable;
+
 	/**
 	 * Creates a new catch 
 	 *
diff --git a/vala/valaifstatement.vala b/vala/valaifstatement.vala
index 4a97f81..36a69e1 100644
--- a/vala/valaifstatement.vala
+++ b/vala/valaifstatement.vala
@@ -42,14 +42,33 @@ public class Vala.IfStatement : CodeNode, Statement {
 	/**
 	 * The statement to be evaluated if the condition holds.
 	 */
-	public Block true_statement { get; set; }
+	public Block true_statement {
+		get {
+			return _true_statement;
+		}
+		set {
+			_true_statement = value;
+			_true_statement.parent_node = this;
+		}
+	}
 	
 	/**
 	 * The optional statement to be evaluated if the condition doesn't hold.
 	 */
-	public Block? false_statement { get; set; }
+	public Block? false_statement {
+		get {
+			return _false_statement;
+		}
+		set {
+			_false_statement = value;
+			if (_false_statement != null)
+				_false_statement.parent_node = this;
+		}
+	}
 
 	private Expression _condition;
+	private Block _true_statement;
+	private Block _false_statement;
 
 	/**
 	 * Creates a new if statement.
diff --git a/vala/valatrystatement.vala b/vala/valatrystatement.vala
index 715ab7d..c94bd9b 100644
--- a/vala/valatrystatement.vala
+++ b/vala/valatrystatement.vala
@@ -30,13 +30,32 @@ public class Vala.TryStatement : CodeNode, Statement {
 	/**
 	 * Specifies the body of the try statement.
 	 */
-	public Block body { get; set; }
+	public Block body {
+		get {
+			return _body;
+		}
+		set {
+			_body = value;
+			_body.parent_node = this;
+		}
+	}
 
 	/**
 	 * Specifies the body of the optional finally clause.
 	 */
-	public Block? finally_body { get; set; }
+	public Block? finally_body {
+		get {
+			return _finally_body;
+		}
+		set {
+			_finally_body = value;
+			if (_finally_body != null)
+				_finally_body.parent_node = this;
+		}
+	}
 
+	private Block _body;
+	private Block _finally_body;
 	private Gee.List<CatchClause> catch_clauses = new ArrayList<CatchClause> ();
 
 	/**
@@ -59,6 +78,7 @@ public class Vala.TryStatement : CodeNode, Statement {
 	 * @param clause a catch clause
 	 */
 	public void add_catch_clause (CatchClause clause) {
+		clause.parent_node = this;
 		catch_clauses.add (clause);
 	}
 
