diff --git a/CHANGES.current b/CHANGES.current
index 2e991b61b..e268b30ea 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -55,6 +55,10 @@ Version 4.2.0 (in progress)
*** POTENTIAL INCOMPATIBILITY ***
+2022-11-13: olly
+ [PHP] #2419 Update the documentation to reflect that SWIG 4.1.0
+ dropped support for -noproxy when generating PHP wrappers.
+
2022-11-05: wsfulton
#2417 Fix -swiglib for Windows when building with CMake.
diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html
index 97a48b707..fad7f6a2f 100644
--- a/Doc/Manual/Php.html
+++ b/Doc/Manual/Php.html
@@ -635,18 +635,12 @@ variable, or assigning NULL to a variable.
-SWIG defaults to wrapping C++ structs and classes with PHP classes.
+SWIG wraps C++ structs and classes with PHP classes.
Since SWIG 4.1.0, this is done entirely via PHP's C API - earlier SWIG
versions generated a PHP wrapper script which defined proxy classes
which called a set of flat functions which actually wrapped the C++ class.
-
-If you don't want the class wrappers, you can pass the command-line option
-"-noproxy" in which case you'll get C++ classes wrapped as flat functions
-as described below.
-
-
This interface file
@@ -699,33 +693,16 @@ Member variables and methods are accessed using the -> operator.
-The -noproxy option flattens the object structure and
-generates collections of named functions. The above example results
-in the following PHP functions:
+SWIG/PHP used to support a -noproxy option to flatten the class
+structure and generate collections of named flat functions. This is no
+longer supported as of SWIG 4.1.0.
-
-new_Vector();
-Vector_x_set($obj, $d);
-Vector_x_get($obj);
-Vector_y_set($obj, $d);
-Vector_y_get($obj);
-Vector_z_set($obj, $d);
-Vector_z_get($obj);
-Vector_magnitude($obj);
-new_Complex();
-Complex_re_set($obj, $d);
-Complex_re_get($obj);
-Complex_im_set($obj, $d);
-Complex_im_get($obj);
-
-
-The constructor is called when new Object() (or
-new_Object() if using -noproxy) is used to create an
+The constructor is called when new Object() is used to create an
instance of the object. If multiple constructors are defined for an
object, function overloading will be used to determine which
constructor to execute.
diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html
index cc33d6152..3c5e0620b 100644
--- a/Doc/Manual/SWIGPlus.html
+++ b/Doc/Manual/SWIGPlus.html
@@ -255,7 +255,7 @@ details. The SWIG Wiki also has further details.
Compatibility Note: Early versions of SWIG generated just a flattened low-level C style API to C++ classes by default.
-The -noproxy commandline option is recognised by many target languages and will generate just this
+The -noproxy commandline option is recognised by some target languages and will generate just this
interface as in earlier versions.
diff --git a/Examples/test-suite/r/pointer_reference_runme.R b/Examples/test-suite/r/pointer_reference_runme.R
new file mode 100644
index 000000000..4a2a7ea1b
--- /dev/null
+++ b/Examples/test-suite/r/pointer_reference_runme.R
@@ -0,0 +1,24 @@
+clargs <- commandArgs(trailing=TRUE)
+source(file.path(clargs[1], "unittest.R"))
+#source("unittest.R")
+
+dyn.load(paste("pointer_reference", .Platform$dynlib.ext, sep=""))
+source("pointer_reference.R")
+cacheMetaData(1)
+
+
+s = Struct_value_get(Struct_pInstance_get())
+unittest(s, 10)
+
+ss = Struct(20)
+Struct_pInstance_set(ss)
+s = Struct_value_get(Struct_pInstance_get())
+unittest(s, 20)
+
+s = overloading(1)
+unittest(s, 111)
+
+s = overloading(ss)
+unittest(s, 222)
+
+
diff --git a/Examples/test-suite/r/template_class_reuse_name_runme.R b/Examples/test-suite/r/template_class_reuse_name_runme.R
new file mode 100644
index 000000000..256482213
--- /dev/null
+++ b/Examples/test-suite/r/template_class_reuse_name_runme.R
@@ -0,0 +1,52 @@
+clargs <- commandArgs(trailing=TRUE)
+source(file.path(clargs[1], "unittest.R"))
+#source("unittest.R")
+
+dyn.load(paste("template_class_reuse_name", .Platform$dynlib.ext, sep=""))
+source("template_class_reuse_name.R")
+cacheMetaData(1)
+
+
+
+
+
+Bool1()$tt()
+Bool1False()$ff()
+
+Bool2()$tt()
+Bool2False()$ff()
+
+Bool3()$tt()
+Bool3False()$ff()
+
+Bool4()$tt()
+Bool4False()$ff()
+
+
+BoolForward1()$tt()
+BoolForward1False()$ff()
+
+BoolForward2()$tt()
+BoolForward2False()$ff()
+
+BoolForward3()$tt()
+BoolForward3False()$ff()
+
+BoolForward4()$tt()
+BoolForward4False()$ff()
+
+
+IntBool1()$tt()
+IntBool1False()$ff()
+
+IntBool2()$tt()
+IntBool2False()$ff()
+
+IntBool3()$tt()
+IntBool3False()$ff()
+
+IntBool4()$tt()
+IntBool4False()$ff()
+
+Duplicate2_0_n(Duplicate2_0())
+Duplicate3_n(Duplicate3())
diff --git a/Examples/test-suite/r/template_classes_runme.R b/Examples/test-suite/r/template_classes_runme.R
new file mode 100644
index 000000000..e40dfd4cc
--- /dev/null
+++ b/Examples/test-suite/r/template_classes_runme.R
@@ -0,0 +1,57 @@
+
+clargs <- commandArgs(trailing=TRUE)
+source(file.path(clargs[1], "unittest.R"))
+#source("unittest.R")
+
+dyn.load(paste("template_classes", .Platform$dynlib.ext, sep=""))
+source("template_classes.R")
+cacheMetaData(1)
+
+
+# This test is just testing incorrect number of arguments/parameters checking
+
+point = PointInt()
+rectangle = RectangleInt()
+
+p = RectangleInt_getPoint(rectangle)
+unittest(PointInt_getX(p), 0)
+
+RectangleInt_setPoint(rectangle, point)
+
+unittest(RectangleInt_static_noargs(), 0)
+unittest(RectangleInt_static_onearg(12), 12)
+
+
+argCheckFailed = F
+try({
+ RectangleInt_setPoint(rectangle)
+ argCheckFailed = T
+}, silent=T)
+unittest(argCheckFailed, F)
+
+
+argCheckFailed = F
+try({
+ RectangleInt_getPoint(rectangle, 0, .copy = F)
+ argCheckFailed = T
+}, silent=T)
+unittest(argCheckFailed, F)
+
+
+argCheckFailed = F
+try({
+ RectangleInt_static_noargs(123, .copy = F)
+ argCheckFailed = T
+}, silent=T)
+unittest(argCheckFailed, F)
+
+
+
+argCheckFailed = F
+try({
+ RectangleInt_static_onearg()
+ argCheckFailed = T
+}, silent=T)
+unittest(argCheckFailed, F)
+
+
diff --git a/Examples/test-suite/r/template_default_arg_overloaded_extend_runme.R b/Examples/test-suite/r/template_default_arg_overloaded_extend_runme.R
new file mode 100644
index 000000000..3ec4eb3e9
--- /dev/null
+++ b/Examples/test-suite/r/template_default_arg_overloaded_extend_runme.R
@@ -0,0 +1,25 @@
+clargs <- commandArgs(trailing=TRUE)
+source(file.path(clargs[1], "unittest.R"))
+#source("unittest.R")
+
+dyn.load(paste("template_default_arg_overloaded_extend", .Platform$dynlib.ext, sep=""))
+source("template_default_arg_overloaded_extend.R")
+cacheMetaData(1)
+
+
+
+
+rs = ResultSet()
+
+unittest(rs$go_get_method(0, SearchPoint()), -1)
+unittest(rs$go_get_method(0, SearchPoint(), 100), 100)
+
+unittest(rs$go_get_template(0, SearchPoint()), -2)
+unittest(rs$go_get_template(0, SearchPoint(), 100), 100)
+
+unittest(rs$over(), "over(int)")
+unittest(rs$over(10), "over(int)")
+unittest(rs$over(SearchPoint()), "over(giai2::SearchPoint, int)")
+unittest(rs$over(SearchPoint(), 10), "over(giai2::SearchPoint, int)")
+unittest(rs$over(T, SearchPoint()), "over(bool, gaia2::SearchPoint, int)")
+unittest(rs$over(T, SearchPoint(), 10), "over(bool, gaia2::SearchPoint, int)")
diff --git a/Examples/test-suite/r/template_default_arg_overloaded_runme.R b/Examples/test-suite/r/template_default_arg_overloaded_runme.R
new file mode 100644
index 000000000..bf9272d3c
--- /dev/null
+++ b/Examples/test-suite/r/template_default_arg_overloaded_runme.R
@@ -0,0 +1,53 @@
+
+clargs <- commandArgs(trailing=TRUE)
+source(file.path(clargs[1], "unittest.R"))
+#source("unittest.R")
+
+dyn.load(paste("template_default_arg_overloaded", .Platform$dynlib.ext, sep=""))
+source("template_default_arg_overloaded.R")
+cacheMetaData(1)
+
+
+
+
+pl = PropertyList()
+unittest(1, pl$setInt("int", 10))
+unittest(1, pl$setInt("int", 10, F))
+
+unittest(2, pl$set("int", pl))
+unittest(2, pl$set("int", pl, F))
+
+unittest(3, pl$setInt("int", 10, "int"))
+unittest(3, pl$setInt("int", 10, "int", F))
+
+
+pl = PropertyListGlobal()
+unittest(1, pl$setIntGlobal("int", 10))
+unittest(1, pl$setIntGlobal("int", 10, F))
+
+unittest(2, pl$set("int", pl))
+unittest(2, pl$set("int", pl, F))
+
+unittest(3, pl$setIntGlobal("int", 10, "int"))
+unittest(3, pl$setIntGlobal("int", 10, "int", F))
+
+
+unittest(1, GoopIntGlobal(10))
+unittest(1, GoopIntGlobal(10, T))
+
+unittest(2, goopGlobal(3))
+unittest(2, goopGlobal())
+
+unittest(3, GoopIntGlobal("int", F))
+unittest(3, GoopIntGlobal("int"))
+
+
+unittest(1, GoopInt(10))
+unittest(1, GoopInt(10, T))
+
+unittest(2, goop(3))
+unittest(2, goop())
+
+unittest(3, GoopInt("int", F))
+unittest(3, GoopInt("int"))
+
diff --git a/Examples/test-suite/r/template_ref_type_runme.R b/Examples/test-suite/r/template_ref_type_runme.R
new file mode 100644
index 000000000..2565019d7
--- /dev/null
+++ b/Examples/test-suite/r/template_ref_type_runme.R
@@ -0,0 +1,14 @@
+
+clargs <- commandArgs(trailing=TRUE)
+source(file.path(clargs[1], "unittest.R"))
+#source("unittest.R")
+
+dyn.load(paste("template_ref_type", .Platform$dynlib.ext, sep=""))
+source("template_ref_type.R")
+cacheMetaData(1)
+
+xr = XC()
+y = Y()
+
+unittest(Y_find(y, xr), FALSE)
+