]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Catch and throw possible inner error of lock statements
authorRico Tzschichholz <ricotz@ubuntu.com>
Thu, 10 Feb 2022 17:07:56 +0000 (18:07 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Sun, 20 Mar 2022 17:58:32 +0000 (18:58 +0100)
See 40c1dbfbfedb6c4a6b88df045eb1c2e7bdd38d93

Fixes https://gitlab.gnome.org/GNOME/vala/issues/83

tests/Makefile.am
tests/control-flow/lock-if-throw.vala [new file with mode: 0644]
vala/valalockstatement.vala

index 48d9a9b01ac07e0300c46deca584d3e81ee84123..22039493abc15d7fd1c84225bb1be4e855cce37b 100644 (file)
@@ -275,6 +275,7 @@ TESTS = \
        control-flow/for-switch-continue.vala \
        control-flow/foreach.vala \
        control-flow/local-clash-with-implicit-this.vala \
+       control-flow/lock-if-throw.vala \
        control-flow/missing-break.test \
        control-flow/missing-return.test \
        control-flow/nested-conditional.vala \
diff --git a/tests/control-flow/lock-if-throw.vala b/tests/control-flow/lock-if-throw.vala
new file mode 100644 (file)
index 0000000..22747c5
--- /dev/null
@@ -0,0 +1,24 @@
+errordomain FooError {
+       FAIL;
+}
+
+class Foo {
+       bool manam = true;
+
+       public bool bar () throws Error {
+               bool result;
+
+               lock (manam) {
+                       if (manam) {
+                               throw new FooError.FAIL ("foo");
+                       } else {
+                               result = true;
+                       }
+               }
+
+               return result;
+       }
+}
+
+void main () {
+}
index c9cc96e7c7a509a5d0b4b8ba15c05997db61c103..d0f9d09328c89893529291a5be0b9b1e3216ce51 100644 (file)
@@ -84,14 +84,26 @@ public class Vala.LockStatement : CodeNode, Statement {
 
        public override bool check (CodeContext context) {
                if (body != null) {
-                       // if the statement isn't empty, it is converted into a try statement
+                       if (!body.check (context)) {
+                               return false;
+                       }
 
+                       // if the statement isn't empty, it is converted into a try statement
                        var fin_body = new Block (source_reference);
                        fin_body.add_statement (new UnlockStatement (resource, source_reference));
 
+                       var try_stmt = new TryStatement (body, fin_body, source_reference);
+                       if (body.tree_can_fail) {
+                               var catch_body = new Block (source_reference);
+                               catch_body.add_statement (new ThrowStatement (new ReferenceTransferExpression (new MemberAccess.simple ("_lock_error_")), source_reference));
+                               var catch_clause = new CatchClause (new ErrorType (null, null), "_lock_error_", catch_body, source_reference);
+                               catch_clause.error_type.value_owned = true;
+                               try_stmt.add_catch_clause (catch_clause);
+                       }
+
                        var block = new Block (source_reference);
                        block.add_statement (new LockStatement (resource, null, source_reference));
-                       block.add_statement (new TryStatement (body, fin_body, source_reference));
+                       block.add_statement (try_stmt);
 
                        var parent_block = (Block) parent_node;
                        parent_block.replace_statement (this, block);