From: Marc-André Lureau Date: Sun, 24 Jan 2010 17:41:44 +0000 (+0100) Subject: Perform flow analysis on lambda expressions X-Git-Tag: 0.7.10~30 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=da67841f1fed0b391965e6c1b2179855396ab06b;p=thirdparty%2Fvala.git Perform flow analysis on lambda expressions Fixes bug 606478. --- diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala index 878936d38..43baefd4c 100644 --- a/vala/valaflowanalyzer.vala +++ b/vala/valaflowanalyzer.vala @@ -135,6 +135,25 @@ public class Vala.FlowAnalyzer : CodeVisitor { } } + public override void visit_lambda_expression (LambdaExpression le) { + var old_current_block = current_block; + var old_unreachable_reported = unreachable_reported; + var old_jump_stack = jump_stack; + current_block = null; + unreachable_reported = false; + jump_stack = new ArrayList (); + + le.accept_children (this); + + current_block = old_current_block; + unreachable_reported = old_unreachable_reported; + jump_stack = old_jump_stack; + } + + public override void visit_method_call (MethodCall mc) { + mc.accept_children (this); + } + public override void visit_method (Method m) { if (m.is_internal_symbol () && !m.used && !m.entry_point && !m.overrides && (m.base_interface_method == null || m.base_interface_method == m) @@ -151,6 +170,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { current_block = new BasicBlock (); m.entry_block.connect (current_block); + current_block.add_node (m); jump_stack.add (new JumpTarget.return_target (m.exit_block)); @@ -162,7 +182,7 @@ public class Vala.FlowAnalyzer : CodeVisitor { // end of method body reachable if (!(m.return_type is VoidType)) { - Report.error (m.source_reference, "missing return statement at end of method body"); + Report.error (m.source_reference, "missing return statement at end of method or lambda body"); m.error = true; } @@ -508,6 +528,8 @@ public class Vala.FlowAnalyzer : CodeVisitor { } public override void visit_expression_statement (ExpressionStatement stmt) { + stmt.accept_children (this); + if (unreachable (stmt)) { return; } @@ -759,6 +781,8 @@ public class Vala.FlowAnalyzer : CodeVisitor { } public override void visit_return_statement (ReturnStatement stmt) { + stmt.accept_children (this); + if (unreachable (stmt)) { return; } diff --git a/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala index 0f0bb2997..facaed95b 100644 --- a/vala/valalambdaexpression.vala +++ b/vala/valalambdaexpression.vala @@ -1,6 +1,6 @@ /* valalambdaexpression.vala * - * Copyright (C) 2006-2009 Jürg Billeter + * Copyright (C) 2006-2010 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -133,7 +133,10 @@ public class Vala.LambdaExpression : Expression { } var cb = (Delegate) ((DelegateType) target_type).delegate_symbol; - method = new Method (get_lambda_name (analyzer), cb.return_type); + method = new Method (get_lambda_name (analyzer), cb.return_type, source_reference); + // track usage for flow analyzer + method.used = true; + if (!cb.has_target || !analyzer.is_in_instance_method ()) { method.binding = MemberBinding.STATIC; } else { @@ -211,15 +214,7 @@ public class Vala.LambdaExpression : Expression { /* lambda expressions should be usable like MemberAccess of a method */ symbol_reference = method; - if (method == null) { - if (expression_body != null) { - expression_body.check (analyzer); - } else if (statement_body != null) { - statement_body.check (analyzer); - } - } else { - method.check (analyzer); - } + method.check (analyzer); value_type = new MethodType (method); value_type.value_owned = target_type.value_owned; diff --git a/vala/valamethod.vala b/vala/valamethod.vala index 608918909..4040d3747 100644 --- a/vala/valamethod.vala +++ b/vala/valamethod.vala @@ -1066,6 +1066,14 @@ public class Vala.Method : Member { } } } + + public override void get_defined_variables (Collection collection) { + // capturing variables is only supported if they are initialized + // therefore assume that captured variables are initialized + if (closure) { + get_captured_variables (collection); + } + } } // vim:sw=8 noet