diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index bea64e0..b9c4017 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -2280,7 +2280,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,13 +2387,32 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 
 		return found;
 	}
+	
+	public virtual bool variable_accessible_in_finally (LocalVariable local) {
+		if (current_try == null) return false;
+	
+		var sym = current_symbol;
+	
+		while (!(sym is Method) && sym.scope.lookup (local.name) == null) {
+
+			if ((sym.parent_node is TryStatement && ((TryStatement) sym.parent_node).finally_body != null) ||
+				(sym.parent_node is CatchClause && ((TryStatement) sym.parent_node.parent_node).finally_body != null)) {
+				
+				return true;
+			}
+		
+			sym = sym.parent_symbol;
+		}
+		
+		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_accessible_in_finally (local)) {
 				/* return expression is local variable taking ownership and
 				 * current method is transferring ownership */
 
@@ -2426,7 +2445,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_accessible_in_finally (local)) {
 				/* return expression is local variable taking ownership and
 				 * current method is transferring ownership */
 
diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala
index 90e9552..9f0ab05 100644
--- a/codegen/valagerrormodule.vala
+++ b/codegen/valagerrormodule.vala
@@ -27,6 +27,7 @@ using Gee;
 internal class Vala.GErrorModule : CCodeDelegateModule {
 	private int current_try_id = 0;
 	private int next_try_id = 0;
+	private bool is_in_catch = false;
 
 	public GErrorModule (CCodeGenerator codegen, CCodeModule? next) {
 		base (codegen, next);
@@ -178,34 +179,36 @@ internal class Vala.GErrorModule : CCodeDelegateModule {
 			append_error_free (current_symbol, free_frag, current_try);
 			cerror_block.add_statement (free_frag);
 
-			foreach (CatchClause clause in current_try.get_catch_clauses ()) {
-				// go to catch clause if error domain matches
-				var cgoto_stmt = new CCodeGotoStatement (clause.clabel_name);
+			if (!is_in_catch) {
+				foreach (CatchClause clause in current_try.get_catch_clauses ()) {
+					// go to catch clause if error domain matches
+					var cgoto_stmt = new CCodeGotoStatement (clause.clabel_name);
 
-				if (clause.error_type.equals (gerror_type)) {
-					// general catch clause, this should be the last one
-					cerror_block.add_statement (cgoto_stmt);
-					break;
-				} else {
-					var catch_type = clause.error_type as ErrorType;
-					var cgoto_block = new CCodeBlock ();
-					cgoto_block.add_statement (cgoto_stmt);
-
-					if (catch_type.error_code != null) {
-						/* catch clause specifies a specific error code */
-						var error_match = new CCodeFunctionCall (new CCodeIdentifier ("g_error_matches"));
-						error_match.add_argument (inner_error);
-						error_match.add_argument (new CCodeIdentifier (catch_type.data_type.get_upper_case_cname ()));
-						error_match.add_argument (new CCodeIdentifier (catch_type.error_code.get_cname ()));
-
-						cerror_block.add_statement (new CCodeIfStatement (error_match, cgoto_block));
+					if (clause.error_type.equals (gerror_type)) {
+						// general catch clause, this should be the last one
+						cerror_block.add_statement (cgoto_stmt);
+						break;
 					} else {
-						/* catch clause specifies a full error domain */
-						var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY,
-								new CCodeMemberAccess.pointer (inner_error, "domain"), new CCodeIdentifier
-								(clause.error_type.data_type.get_upper_case_cname ()));
-
-						cerror_block.add_statement (new CCodeIfStatement (ccond, cgoto_block));
+						var catch_type = clause.error_type as ErrorType;
+						var cgoto_block = new CCodeBlock ();
+						cgoto_block.add_statement (cgoto_stmt);
+
+						if (catch_type.error_code != null) {
+							/* catch clause specifies a specific error code */
+							var error_match = new CCodeFunctionCall (new CCodeIdentifier ("g_error_matches"));
+							error_match.add_argument (inner_error);
+							error_match.add_argument (new CCodeIdentifier (catch_type.data_type.get_upper_case_cname ()));
+							error_match.add_argument (new CCodeIdentifier (catch_type.error_code.get_cname ()));
+
+							cerror_block.add_statement (new CCodeIfStatement (error_match, cgoto_block));
+						} else {
+							/* catch clause specifies a full error domain */
+							var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY,
+									new CCodeMemberAccess.pointer (inner_error, "domain"), new CCodeIdentifier
+									(clause.error_type.data_type.get_upper_case_cname ()));
+
+							cerror_block.add_statement (new CCodeIfStatement (ccond, cgoto_block));
+						}
 					}
 				}
 			}
@@ -257,8 +260,10 @@ internal class Vala.GErrorModule : CCodeDelegateModule {
 
 		var old_try = current_try;
 		var old_try_id = current_try_id;
+		var old_is_in_catch = is_in_catch;
 		current_try = stmt;
 		current_try_id = this_try_id;
+		is_in_catch = false;
 
 		foreach (CatchClause clause in stmt.get_catch_clauses ()) {
 			clause.clabel_name = "__catch%d_%s".printf (this_try_id, clause.error_type.get_lower_case_cname ());
@@ -270,23 +275,20 @@ internal class Vala.GErrorModule : CCodeDelegateModule {
 
 		stmt.body.accept (codegen);
 
-		current_try = old_try;
-		current_try_id = old_try_id;
-
+		is_in_catch = true;
 		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;
+		is_in_catch = old_is_in_catch;
 
 		var cfrag = new CCodeFragment ();
 		cfrag.append (stmt.body.ccodenode);
 
 		foreach (CatchClause clause in stmt.get_catch_clauses ()) {
 			cfrag.append (new CCodeGotoStatement ("__finally%d".printf (this_try_id)));
-
 			cfrag.append (clause.ccodenode);
 		}
 
@@ -344,6 +346,22 @@ 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);
+	}
 }
 
 // vim:sw=8 noet
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);
 	}
 
