Merge branch 'catch-value'

* catch-value:
  Catch exceptions by reference rather than by value.
diff --git a/CHANGES.current b/CHANGES.current
index c12c5eb..27f170e 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -7,6 +7,12 @@
 Version 4.0.2 (in progress)
 ===========================
 
+2020-02-14: treitmayr
+            #1724 Fix wrapping of abstract user-defined conversion operators.
+
+2020-02-13: ddurham2
+            [Python] #1512 Fix memleak when using STL containers of shared_ptr objects.
+
 2020-02-06: wsfulton
             [Python] #1673 #1674 Fix setting 'this' when extending a proxy class with __slots__.
 
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index 115747e..e77f09c 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -184,6 +184,7 @@
 	director_classes \
 	director_classic \
 	director_constructor \
+	director_conversion_operators \
 	director_default \
 	director_detect \
 	director_enum \
diff --git a/Examples/test-suite/director_conversion_operators.i b/Examples/test-suite/director_conversion_operators.i
new file mode 100644
index 0000000..afcd49d
--- /dev/null
+++ b/Examples/test-suite/director_conversion_operators.i
@@ -0,0 +1,35 @@
+%module(directors="1") director_conversion_operators
+
+%feature("director");
+
+%warnfilter(SWIGWARN_TYPEMAP_DIRECTOROUT_PTR) Bar;
+
+%rename(toFoo) Bar::operator Foo();
+%rename(toFooPtr) Bar::operator Foo *();
+%rename(toFooRef) Bar::operator Foo &();
+%rename(toFooPtrRef) Bar::operator Foo *&();
+
+%rename(toOtherFoo) Bar::operator OtherFoo();
+%rename(toOtherFooPtr) Bar::operator OtherFoo *();
+%rename(toOtherFooRef) Bar::operator OtherFoo &();
+%rename(toOtherFooPtrRef) Bar::operator OtherFoo *&();
+
+%inline %{
+   struct Foo {
+   };
+   struct OtherFoo {
+   };
+   struct Bar {
+      Foo myFoo;
+      Foo *myFooPtr;
+      virtual ~Bar() { }
+      virtual operator Foo () { return Foo(); }
+      virtual operator Foo *() { return &myFoo; }
+      virtual operator Foo &() { return myFoo; }
+      virtual operator Foo *&() { return myFooPtr; }
+      virtual operator OtherFoo () = 0;
+      virtual operator OtherFoo *() = 0;
+      virtual operator OtherFoo &() = 0;
+      virtual operator OtherFoo *&() = 0;
+   };
+%}
diff --git a/Examples/test-suite/python/cpp11_shared_ptr_upcast_runme.py b/Examples/test-suite/python/cpp11_shared_ptr_upcast_runme.py
new file mode 100644
index 0000000..08546a4
--- /dev/null
+++ b/Examples/test-suite/python/cpp11_shared_ptr_upcast_runme.py
@@ -0,0 +1,63 @@
+from cpp11_shared_ptr_upcast import *
+
+# This is a port from the Ruby equivalent test and some tests ported from
+# Examples/test-suite/ruby/cpp11_shared_ptr_upcast_runme.rb are not working and commented out with:
+# not working:
+
+def swig_assert_equal_simple(expected, got):
+    if expected != got:
+        raise RuntimeError("Expected: {}. Got: {}")
+
+# non-overloaded
+swig_assert_equal_simple(7, derived_num1(Derived(7)))
+swig_assert_equal_simple(7, derived_num2([Derived(7)]))
+swig_assert_equal_simple(7, derived_num3({0: Derived(7)}))
+
+swig_assert_equal_simple(-1, base_num1(Derived(7)))
+swig_assert_equal_simple(-1, base_num2([Derived(7)]))
+swig_assert_equal_simple(-1, base_num3({0: Derived(7)}))
+
+swig_assert_equal_simple(999, derived_num1(None))
+# not working: swig_assert_equal_simple(999, derived_num2([None]))
+# not working: swig_assert_equal_simple(999, derived_num3({0: None}))
+
+swig_assert_equal_simple(999, base_num1(None))
+# not working: swig_assert_equal_simple(999, base_num2([None]))
+# not working: swig_assert_equal_simple(999, base_num3({0: None}))
+
+# overloaded
+swig_assert_equal_simple(7, derived_num(Derived(7)))
+swig_assert_equal_simple(7, derived_num([Derived(7)]))
+swig_assert_equal_simple(7, derived_num({0: Derived(7)}))
+
+swig_assert_equal_simple(-1, base_num(Derived(7)))
+swig_assert_equal_simple(-1, base_num([Derived(7)]))
+swig_assert_equal_simple(-1, base_num({0: Derived(7)}))
+
+# ptr to shared_ptr
+swig_assert_equal_simple(7, derived2_num1(Derived2(7)))
+swig_assert_equal_simple(7, derived2_num2([Derived2(7)]))
+swig_assert_equal_simple(7, derived2_num3({0: Derived2(7)}))
+
+swig_assert_equal_simple(-1, base2_num1(Derived2(7)))
+
+# not working: try:
+# not working:     # Upcast for pointers to shared_ptr in this generic framework has not been implemented
+# not working:     swig_assert_equal_simple(-1, base2_num2([Derived2(7)]))
+# not working:     raise RuntimeError, "Failed to catch TypeError"
+# not working: except TypeError:
+# not working:     pass
+# not working: try:
+# not working:     # Upcast for pointers to shared_ptr in this generic framework has not been implemented
+# not working:     swig_assert_equal_simple(-1, base2_num3({0: Derived2(7)}))
+# not working:     raise RuntimeError, "Failed to catch TypeError"
+# not working: except TypeError:
+# not working:     pass
+
+swig_assert_equal_simple(888, derived2_num1(None))
+swig_assert_equal_simple(999, derived2_num2([None])) # although 888 would be more consistent
+swig_assert_equal_simple(999, derived2_num3({0: None})) # although 888 would be more consistent
+
+swig_assert_equal_simple(888, base2_num1(None))
+swig_assert_equal_simple(999, base2_num2([None])) # although 888 would be more consistent
+swig_assert_equal_simple(999, base2_num3({0: None})) # although 888 would be more consistent
diff --git a/Lib/python/pystdcommon.swg b/Lib/python/pystdcommon.swg
index 0242e4d..afa7135 100644
--- a/Lib/python/pystdcommon.swg
+++ b/Lib/python/pystdcommon.swg
@@ -45,11 +45,20 @@
   template <class Type>
   struct traits_asptr {   
     static int asptr(PyObject *obj, Type **val) {
-      Type *p = 0;
+      int res = SWIG_ERROR;
       swig_type_info *descriptor = type_info<Type>();
-      int res = descriptor ? SWIG_ConvertPtr(obj, (void **)&p, descriptor, 0) : SWIG_ERROR;
-      if (SWIG_IsOK(res)) {
-	if (val) *val = p;
+      if (val) {
+        Type *p = 0;
+        int newmem = 0;
+        res = descriptor ? SWIG_ConvertPtrAndOwn(obj, (void **)&p, descriptor, 0, &newmem) : SWIG_ERROR;
+        if (SWIG_IsOK(res)) {
+          if (newmem & SWIG_CAST_NEW_MEMORY) {
+            res |= SWIG_NEWOBJMASK;
+          }
+          *val = p;
+        }
+      } else {
+        res = descriptor ? SWIG_ConvertPtr(obj, 0, descriptor, 0) : SWIG_ERROR;
       }
       return res;
     }
diff --git a/Lib/ruby/std_shared_ptr.i b/Lib/ruby/std_shared_ptr.i
index dee35ec..086e308 100644
--- a/Lib/ruby/std_shared_ptr.i
+++ b/Lib/ruby/std_shared_ptr.i
@@ -13,24 +13,27 @@
   template <class Type>
   struct traits_asptr<std::shared_ptr<Type> > {
     static int asptr(VALUE obj, std::shared_ptr<Type> **val) {
-      std::shared_ptr<Type> *p = 0;
+      int res = SWIG_ERROR;
       swig_type_info *descriptor = type_info<std::shared_ptr<Type> >();
-      swig_ruby_owntype newmem = {0, 0};
-      int res = descriptor ? SWIG_ConvertPtrAndOwn(obj, (void **)&p, descriptor, 0, &newmem) : SWIG_ERROR;
-      if (SWIG_IsOK(res)) {
-	if (val) {
-	  if (*val) {
-	    **val = p ? *p : std::shared_ptr<Type>();
-	  } else {
-	    *val = p;
-	    if (newmem.own & SWIG_CAST_NEW_MEMORY) {
-	      // Upcast for pointers to shared_ptr in this generic framework has not been implemented
-	      res = SWIG_ERROR;
-	    }
-	  }
-	}
-	if (newmem.own & SWIG_CAST_NEW_MEMORY)
-	  delete p;
+      if (val) {
+        std::shared_ptr<Type> *p = 0;
+        swig_ruby_owntype newmem = {0, 0};
+        res = descriptor ? SWIG_ConvertPtrAndOwn(obj, (void **)&p, descriptor, 0, &newmem) : SWIG_ERROR;
+        if (SWIG_IsOK(res)) {
+          if (*val) {
+            **val = p ? *p : std::shared_ptr<Type>();
+          } else {
+            *val = p;
+            if (newmem.own & SWIG_CAST_NEW_MEMORY) {
+              // Upcast for pointers to shared_ptr in this generic framework has not been implemented
+              res = SWIG_ERROR;
+            }
+          }
+          if (newmem.own & SWIG_CAST_NEW_MEMORY)
+            delete p;
+        }
+      } else {
+        res = descriptor ? SWIG_ConvertPtr(obj, 0, descriptor, 0) : SWIG_ERROR;
       }
       return res;
     }
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index 470b7d0..8029dee 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -4800,6 +4800,9 @@
 		 if ($8.qualifier) {
 		   SwigType_push($4,$8.qualifier);
 		 }
+		 if ($8.val) {
+		   Setattr($$,"value",$8.val);
+		 }
 		 Setattr($$,"refqualifier",$8.refqualifier);
 		 Setattr($$,"decl",$4);
 		 Setattr($$,"parms",$6);
@@ -4818,6 +4821,9 @@
 		 if ($8.qualifier) {
 		   SwigType_push(decl,$8.qualifier);
 		 }
+		 if ($8.val) {
+		   Setattr($$,"value",$8.val);
+		 }
 		 Setattr($$,"refqualifier",$8.refqualifier);
 		 Setattr($$,"decl",decl);
 		 Setattr($$,"parms",$6);
@@ -4836,6 +4842,9 @@
 		 if ($8.qualifier) {
 		   SwigType_push(decl,$8.qualifier);
 		 }
+		 if ($8.val) {
+		   Setattr($$,"value",$8.val);
+		 }
 		 Setattr($$,"refqualifier",$8.refqualifier);
 		 Setattr($$,"decl",decl);
 		 Setattr($$,"parms",$6);
@@ -4856,6 +4865,9 @@
 		 if ($9.qualifier) {
 		   SwigType_push(decl,$9.qualifier);
 		 }
+		 if ($9.val) {
+		   Setattr($$,"value",$9.val);
+		 }
 		 Setattr($$,"refqualifier",$9.refqualifier);
 		 Setattr($$,"decl",decl);
 		 Setattr($$,"parms",$7);
@@ -4873,7 +4885,10 @@
 		if ($7.qualifier) {
 		  SwigType_push(t,$7.qualifier);
 		}
-		 Setattr($$,"refqualifier",$7.refqualifier);
+		if ($7.val) {
+		  Setattr($$,"value",$7.val);
+		}
+		Setattr($$,"refqualifier",$7.refqualifier);
 		Setattr($$,"decl",t);
 		Setattr($$,"parms",$5);
 		Setattr($$,"conversion_operator","1");