From c298045ac8761a1bf6b376022b4a50ecf1c88a91 Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Thu, 24 Aug 2017 15:06:45 +0200
Subject: [PATCH] don't intercept ReturnExceptions when calling condition
 handlers

---
 .../r/engine/RRuntimeASTAccessImpl.java       |  4 ---
 .../truffle/r/test/ExpectedTestOutput.test    | 27 +++++++++++++++----
 .../library/base/TestConditionHandling.java   | 10 ++++++-
 3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index d1e476680c..f20257ce31 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -68,7 +68,6 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntimeASTAccess;
 import com.oracle.truffle.r.runtime.RSrcref;
-import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.RootWithBody;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.Engine;
@@ -369,9 +368,6 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         boolean gd = RContext.getInstance().stateInstrumentation.setDebugGloballyDisabled(true);
         try {
             return RContext.getEngine().evalFunction(f, null, null, true, null, args);
-        } catch (ReturnException ex) {
-            // cannot throw return exceptions further up.
-            return ex.getResult();
         } finally {
             RContext.getInstance().stateInstrumentation.setDebugGloballyDisabled(gd);
         }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 0b075e7151..dc5be13375 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -78362,6 +78362,15 @@ NULL
 NULL
 [1] "exit fun0"
 
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#
+#my.error <- function(war) cat('my.error:', war$message, '\n'); f <- function() print(g); tryCatch({f()}, error=my.error)
+my.error: object 'g' not found
+
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#
+#x <- { tryCatch(stop('fred'), error = function(e) e, finally = print('Hello'))}; x$call <- NULL; x
+[1] "Hello"
+<simpleError: fred>
+
 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#
 #{ e <- simpleError("test error"); f <- function() { tryCatch(1, finally = print("Hello")); stop(e)}; f() }
 [1] "Hello"
@@ -78390,11 +78399,6 @@ Error in f() : fred
 [1] "Hello"
 [1] 1
 
-##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#Ignored.ImplementationError#
-#{ tryCatch(stop("fred"), error = function(e) e, finally = print("Hello"))}
-[1] "Hello"
-<simpleError in doTryCatch(return(expr), name, parentenv, handler): fred>
-
 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#Output.IgnoreErrorContext#
 #{ tryCatch(stop("fred"), finally = print("Hello")) }
 Error in tryCatchList(expr, classes, parentenv, handlers) : fred
@@ -78404,6 +78408,19 @@ Error in tryCatchList(expr, classes, parentenv, handlers) : fred
 #{ tryCatch(stop("xyz"), error=function(e) { cat("<error>");123L }, finally=function() { cat("<finally>")}) }
 <error>[1] 123
 
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#Ignored.ImplementationError#
+#{ tryCatch(stop('fred'), error = function(e) e, finally = print('Hello'))}
+[1] "Hello"
+<simpleError in doTryCatch(return(expr), name, parentenv, handler): fred>
+
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWarning#
+#my.warning <- function(war) cat('my.warning:', war$message, '\n'); f <- function()  warning('from f'); tryCatch({f()}, warning=my.warning)
+my.warning: from f
+
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWarning#
+#tryCatch(warning('some warning text'), warning = function(w) {print('WARNING')})
+[1] "WARNING"
+
 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWithCallingHandlers#Output.IgnoreErrorContext#
 #withCallingHandlers(stop('error message'), error=function(e) {})
 Error in withCallingHandlers(stop("error message"), error = function(e) { :
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java
index adf3d9e2f8..985245c14c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java
@@ -46,10 +46,12 @@ public class TestConditionHandling extends TestRBase {
         // <simpleError in doTryCatch(return(expr), name, parentenv, handler): fred>
         // FastR output: [1] "Hello"
         // <simpleError: fred>
-        assertEval(Ignored.ImplementationError, "{ tryCatch(stop(\"fred\"), error = function(e) e, finally = print(\"Hello\"))}");
+        assertEval(Ignored.ImplementationError, "{ tryCatch(stop('fred'), error = function(e) e, finally = print('Hello'))}");
+        assertEval("x <- { tryCatch(stop('fred'), error = function(e) e, finally = print('Hello'))}; x$call <- NULL; x");
         assertEval("{ f <- function() { tryCatch(1, error = function(e) print(\"Hello\")); stop(\"fred\")}; f() }");
         assertEval("{ f <- function() { tryCatch(stop(\"fred\"), error = function(e) print(\"Hello\"))}; f() }");
         assertEval("{ tryCatch(stop(\"xyz\"), error=function(e) { cat(\"<error>\");123L }, finally=function() { cat(\"<finally>\")}) }");
+        assertEval("my.error <- function(war) cat('my.error:', war$message, '\\n'); f <- function() print(g); tryCatch({f()}, error=my.error)");
     }
 
     @Test
@@ -72,4 +74,10 @@ public class TestConditionHandling extends TestRBase {
         assertEval(Output.IgnoreErrorContext, "withCallingHandlers(stop('error message'), error=function(e) {})");
         assertEval(Output.IgnoreErrorMessage, "withCallingHandlers(unknownSymbol(), condition = function(e) {})");
     }
+
+    @Test
+    public void testWarning() {
+        assertEval("tryCatch(warning('some warning text'), warning = function(w) {print('WARNING')})");
+        assertEval("my.warning <- function(war) cat('my.warning:', war$message, '\\n'); f <- function()  warning('from f'); tryCatch({f()}, warning=my.warning)");
+    }
 }
-- 
GitLab