]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Perform flow analysis on lambda expressions
authorMarc-André Lureau <marcandre.lureau@gmail.com>
Sun, 24 Jan 2010 17:41:44 +0000 (18:41 +0100)
committerJürg Billeter <j@bitron.ch>
Fri, 29 Jan 2010 20:57:40 +0000 (21:57 +0100)
Fixes bug 606478.

vala/valaflowanalyzer.vala
vala/valalambdaexpression.vala
vala/valamethod.vala

index 878936d3898c386ed3550159fd84d8229bebd8d0..43baefd4c8f2ae864fd866be228bdd59ebe17cb9 100644 (file)
@@ -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<JumpTarget> ();
+
+               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;
                }
index 0f0bb29979787f1ff30682b6af11389eb8b71528..facaed95b985057d03f83dacd20af4a052feb71a 100644 (file)
@@ -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;
index 608918909d46274da5d8bc3fa47edb9227ad7492..4040d374785f379bfc1ef9b73d94b6bca12c945a 100644 (file)
@@ -1066,6 +1066,14 @@ public class Vala.Method : Member {
                        }
                }
        }
+
+       public override void get_defined_variables (Collection<LocalVariable> 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