From 4516c1d3f363a1e75b5f1548ae5e5ef199f37cec Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Sat, 15 Aug 2009 23:22:20 +0000 Subject: [PATCH] Fix exception handling when %catches is used in C# git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@11583 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- CHANGES.current | 7 +- Examples/test-suite/catches.i | 33 ++++++++++ Examples/test-suite/common.mk | 1 + Examples/test-suite/csharp/catches_runme.cs | 66 +++++++++++++++++++ .../csharp/exception_order_runme.cs | 48 ++++++++++++++ Lib/exception.i | 6 ++ Source/Modules/allocate.cxx | 3 +- Source/Modules/csharp.cxx | 22 +------ 8 files changed, 163 insertions(+), 23 deletions(-) create mode 100644 Examples/test-suite/catches.i create mode 100644 Examples/test-suite/csharp/catches_runme.cs create mode 100644 Examples/test-suite/csharp/exception_order_runme.cs diff --git a/CHANGES.current b/CHANGES.current index 70914fb2f..6e6295378 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,6 +1,9 @@ Version 1.3.40 (in progress) ============================ +2009-08-16: wsfulton + [C#] Fix exception handling when %catches is used, reported by Juan Manuel Alvarez. + 2009-08-15: wsfulton Fix %template seg fault on some cases of overloading the templated method. Bug reported by Jan Kupec. @@ -128,8 +131,8 @@ Version 1.3.40 (in progress) Fix -Wallkw option as reported by Solomon Gibbs. 2009-07-02: wsfulton - Fix syntax error when a nested struct contains a comment containing a * followed eventually by a /. - Regression from 1.3.37, reported by Solomon Gibbs. + Fix syntax error when a nested struct contains a comment containing a * followed + eventually by a /. Regression from 1.3.37, reported by Solomon Gibbs. 2009-07-01: vmiklos [PHP] Unknown properties are no longer ignored in proxy diff --git a/Examples/test-suite/catches.i b/Examples/test-suite/catches.i new file mode 100644 index 000000000..8f09ae24c --- /dev/null +++ b/Examples/test-suite/catches.i @@ -0,0 +1,33 @@ +%module catches + +%{ +#if defined(_MSC_VER) + #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) +#endif +%} + +%include // for throws(...) typemap + +%catches(int, const char *, const ThreeException&) test_catches(int i); +%catches(int, ...) test_exception_specification(int i); // override the exception specification +%catches(...) test_catches_all(int i); + +%inline %{ +struct ThreeException {}; +void test_catches(int i) { + if (i == 1) { + throw int(1); + } else if (i == 2) { + throw (const char *)"two"; + } else if (i == 3) { + throw ThreeException(); + } +} +void test_exception_specification(int i) throw(int, const char *, const ThreeException&) { + test_catches(i); +} +void test_catches_all(int i) { + test_catches(i); +} +%} + diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index 9987f3c0f..492378b16 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -117,6 +117,7 @@ CPP_TEST_CASES += \ arrays_scope \ bloody_hell \ bools \ + catches \ cast_operator \ casts \ char_strings \ diff --git a/Examples/test-suite/csharp/catches_runme.cs b/Examples/test-suite/csharp/catches_runme.cs new file mode 100644 index 000000000..2b5290eac --- /dev/null +++ b/Examples/test-suite/csharp/catches_runme.cs @@ -0,0 +1,66 @@ +using System; +using catchesNamespace; + +public class runme { + static void Main() { + // test_catches() + try { + catches.test_catches(1); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "C++ int exception thrown, value: 1") + throw new ApplicationException("bad exception order: " + e.Message); + } + + try { + catches.test_catches(2); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "two") + throw new ApplicationException("bad exception order: " + e.Message); + } + + try { + catches.test_catches(3); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "C++ ThreeException const & exception thrown") + throw new ApplicationException("bad exception order: " + e.Message); + } + + // test_exception_specification() + try { + catches.test_exception_specification(1); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "C++ int exception thrown, value: 1") + throw new ApplicationException("bad exception order: " + e.Message); + } + + try { + catches.test_exception_specification(2); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "unknown exception") + throw new ApplicationException("bad exception order: " + e.Message); + } + + try { + catches.test_exception_specification(3); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "unknown exception") + throw new ApplicationException("bad exception order: " + e.Message); + } + + // test_catches_all() + try { + catches.test_catches_all(1); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "unknown exception") + throw new ApplicationException("bad exception order: " + e.Message); + } + + } +} diff --git a/Examples/test-suite/csharp/exception_order_runme.cs b/Examples/test-suite/csharp/exception_order_runme.cs new file mode 100644 index 000000000..16b32983f --- /dev/null +++ b/Examples/test-suite/csharp/exception_order_runme.cs @@ -0,0 +1,48 @@ +using System; +using exception_orderNamespace; + +public class runme { + static void Main() { + A a = new A(); + + try { + a.foo(); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "C++ E1 exception thrown") + throw new ApplicationException("bad exception order: " + e.Message); + } + + try { + a.bar(); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "C++ E2 exception thrown") + throw new ApplicationException("bad exception order: " + e.Message); + } + + try { + a.foobar(); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "postcatch unknown") + throw new ApplicationException("bad exception order: " + e.Message); + } + + try { + a.barfoo(1); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "C++ E1 exception thrown") + throw new ApplicationException("bad exception order: " + e.Message); + } + + try { + a.barfoo(2); + throw new Exception("missed exception"); + } catch (ApplicationException e) { + if (e.Message != "C++ E2 * exception thrown") + throw new ApplicationException("bad exception order: " + e.Message); + } + } +} diff --git a/Lib/exception.i b/Lib/exception.i index e30ac1a5d..a1a47554e 100644 --- a/Lib/exception.i +++ b/Lib/exception.i @@ -262,9 +262,15 @@ SWIGINTERN void SWIG_CSharpException(int code, const char *msg) { /* rethrow the unknown exception */ +#ifdef SWIGCSHARP +%typemap(throws,noblock=1, canthrow=1) (...) { + SWIG_exception(SWIG_RuntimeError,"unknown exception"); +} +#else %typemap(throws,noblock=1) (...) { SWIG_exception(SWIG_RuntimeError,"unknown exception"); } +#endif #endif /* __cplusplus */ diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx index e8397e6a6..d78dd13d7 100644 --- a/Source/Modules/allocate.cxx +++ b/Source/Modules/allocate.cxx @@ -527,8 +527,7 @@ class Allocate:public Dispatcher { } ParmList *throws = Getattr(n, "throws"); if (throws) { - /* if there is no an explicit catchlist, - we catch everything in the throwlist */ + /* if there is no explicit catchlist, we catch everything in the throws list */ if (!catchlist) { Setattr(n, "catchlist", throws); } diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index fa76e42c8..b5444d4b4 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -898,9 +898,9 @@ public: } } - // Get any C# exception classes in the throws typemap + // Look for usage of throws typemap and the canthrow flag ParmList *throw_parm_list = NULL; - if ((throw_parm_list = Getattr(n, "throws"))) { + if ((throw_parm_list = Getattr(n, "catchlist"))) { Swig_typemap_attach_parms("throws", throw_parm_list, f); for (p = throw_parm_list; p; p = nextSibling(p)) { if ((tm = Getattr(p, "tmap:throws"))) { @@ -3063,13 +3063,6 @@ public: return tm; } - /* ----------------------------------------------------------------------------- - * addThrows() - // TODO: remove - * ----------------------------------------------------------------------------- */ - void addThrows(Node *, const String *, Node *) { - } - /* ----------------------------------------------------------------------------- * canThrow() * Determine whether the code in the typemap can throw a C# exception. @@ -3417,10 +3410,6 @@ public: Printf(arg, "j%s", ln); - /* Add various typemap's 'throws' clauses */ - addThrows(n, "tmap:directorin", p); - addThrows(n, "tmap:out", p); - /* And add to the upcall args */ if (gencomma > 0) Printf(jupcall_args, ", "); @@ -3549,9 +3538,8 @@ public: Printf(declaration, " virtual %s", target); Delete(target); - // Get any Java exception classes in the throws typemap + // Add any exception specifications to the methods in the director class ParmList *throw_parm_list = NULL; - if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { int gencomma = 0; @@ -3562,13 +3550,10 @@ public: Swig_typemap_attach_parms("throws", throw_parm_list, 0); for (p = throw_parm_list; p; p = nextSibling(p)) { if ((tm = Getattr(p, "tmap:throws"))) { - addThrows(n, "tmap:throws", p); - if (gencomma++) { Append(w->def, ", "); Append(declaration, ", "); } - Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0)); Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0)); } @@ -3621,7 +3606,6 @@ public: /* Copy jresult into c_result... */ if ((tm = Swig_typemap_lookup("directorout", tp, result_str, w))) { - addThrows(n, "tmap:directorout", tp); Replaceall(tm, "$input", jresult_str); Replaceall(tm, "$result", result_str); Printf(w->code, "%s\n", tm);