diff --git a/CHANGES/v2.4.md b/CHANGES/v2.4.md
index a3c83b197d6e70f5667838d6b23b15c4d6cb8531..8d2a583be6b6fd80560e251c1a6ed264886d54de 100644
--- a/CHANGES/v2.4.md
+++ b/CHANGES/v2.4.md
@@ -206,6 +206,7 @@ For users:
 For users:
   - Fix some performances regression issue with OpenMP
   - Updated NAMD patches to version 2.12 and 2.13. Old patches have been removed.
+  - GROMACS patch for gromacs-2018.4.
 
 For developers:
   - Small fix in LDFLAGS when enabling coverage.
diff --git a/configure b/configure
index efcd29191ffb68295016646080ed6f0fe3835f80..ad51997a13292f317820c869305d36f0e2138472 100755
--- a/configure
+++ b/configure
@@ -5228,7 +5228,69 @@ $as_echo "$as_me: WARNING: Your compiler appears not to support C++11" >&2;}
 $as_echo "$as_me: WARNING: Please change compiler or make sure that everything works correctly" >&2;}
 fi
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ library supports C++11 exceptions" >&5
+$as_echo_n "checking whether C++ library supports C++11 exceptions... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
 
+#include <new>
+#include <functional>
+#include <memory>
+#include <system_error>
+#include <ios>
+#include <future>
+// capable to catch:
+void func(void) {
+  try{
+  } catch(std::bad_array_new_length &) {
+  } catch(std::bad_function_call &) {
+  } catch(std::bad_weak_ptr &) {
+  } catch(std::ios_base::failure &e) {
+    if(e.code().category()==std::generic_category()) {}
+    else if(e.code().category()==std::system_category()) {}
+    else if(e.code().category()==std::iostream_category()) {}
+    else if(e.code().category()==std::future_category()) {}
+  } catch(std::system_error &e) {
+    if(e.code().category()==std::generic_category()) {}
+    else if(e.code().category()==std::system_category()) {}
+    else if(e.code().category()==std::iostream_category()) {}
+    else if(e.code().category()==std::future_category()) {}
+  }
+// capable to throw:
+  auto a=std::bad_array_new_length();
+  auto b=std::bad_function_call();
+  auto c=std::bad_weak_ptr();
+  auto d=std::system_error(10,std::generic_category(),"msg");
+  auto e=std::system_error(10,std::system_category(),"msg");
+  auto f=std::system_error(10,std::iostream_category(),"msg");
+  auto g=std::system_error(10,std::future_category(),"msg");
+  auto h=std::ios_base::failure("msg",std::error_code(10,std::generic_category()));
+  auto i=std::ios_base::failure("msg",std::error_code(10,std::system_category()));
+  auto j=std::ios_base::failure("msg",std::error_code(10,std::iostream_category()));
+  auto k=std::ios_base::failure("msg",std::error_code(10,std::future_category()));
+}
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; };
+  $as_echo "#define __PLUMED_LIBCXX11 1" >>confdefs.h
+
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
 
 
diff --git a/configure.ac b/configure.ac
index a1221ed6566ad29bb106a2aeada7b7b9088ee451..aaa860a430eb5612293bd14306e6e5c4ed66b9c2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -389,7 +389,51 @@ then
    AC_MSG_WARN([Please change compiler or make sure that everything works correctly])
 fi
 
-
+AC_MSG_CHECKING([whether C++ library supports C++11 exceptions])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
+#include <new>
+#include <functional>
+#include <memory>
+#include <system_error>
+#include <ios>
+#include <future>
+// capable to catch:
+void func(void) {
+  try{
+  } catch(std::bad_array_new_length &) {
+  } catch(std::bad_function_call &) {
+  } catch(std::bad_weak_ptr &) {
+  } catch(std::ios_base::failure &e) {
+    if(e.code().category()==std::generic_category()) {}
+    else if(e.code().category()==std::system_category()) {}
+    else if(e.code().category()==std::iostream_category()) {}
+    else if(e.code().category()==std::future_category()) {}
+  } catch(std::system_error &e) {
+    if(e.code().category()==std::generic_category()) {}
+    else if(e.code().category()==std::system_category()) {}
+    else if(e.code().category()==std::iostream_category()) {}
+    else if(e.code().category()==std::future_category()) {}
+  }
+// capable to throw:
+  auto a=std::bad_array_new_length();
+  auto b=std::bad_function_call();
+  auto c=std::bad_weak_ptr();
+  auto d=std::system_error(10,std::generic_category(),"msg");
+  auto e=std::system_error(10,std::system_category(),"msg");
+  auto f=std::system_error(10,std::iostream_category(),"msg");
+  auto g=std::system_error(10,std::future_category(),"msg");
+  auto h=std::ios_base::failure("msg",std::error_code(10,std::generic_category()));
+  auto i=std::ios_base::failure("msg",std::error_code(10,std::system_category()));
+  auto j=std::ios_base::failure("msg",std::error_code(10,std::iostream_category()));
+  auto k=std::ios_base::failure("msg",std::error_code(10,std::future_category()));
+}
+])],
+[
+  AC_MSG_RESULT([yes]);
+  AC_DEFINE([__PLUMED_LIBCXX11])
+],
+[AC_MSG_RESULT([no])
+])
 
 AC_SUBST(disable_dependency_tracking)
 
diff --git a/patches/gromacs-2018.3.config b/patches/gromacs-2018.4.config
similarity index 100%
rename from patches/gromacs-2018.3.config
rename to patches/gromacs-2018.4.config
diff --git a/patches/gromacs-2018.3.diff/src/gromacs/CMakeLists.txt b/patches/gromacs-2018.4.diff/src/gromacs/CMakeLists.txt
similarity index 100%
rename from patches/gromacs-2018.3.diff/src/gromacs/CMakeLists.txt
rename to patches/gromacs-2018.4.diff/src/gromacs/CMakeLists.txt
diff --git a/patches/gromacs-2018.3.diff/src/gromacs/CMakeLists.txt.preplumed b/patches/gromacs-2018.4.diff/src/gromacs/CMakeLists.txt.preplumed
similarity index 100%
rename from patches/gromacs-2018.3.diff/src/gromacs/CMakeLists.txt.preplumed
rename to patches/gromacs-2018.4.diff/src/gromacs/CMakeLists.txt.preplumed
diff --git a/patches/gromacs-2018.3.diff/src/gromacs/mdlib/force.cpp b/patches/gromacs-2018.4.diff/src/gromacs/mdlib/force.cpp
similarity index 96%
rename from patches/gromacs-2018.3.diff/src/gromacs/mdlib/force.cpp
rename to patches/gromacs-2018.4.diff/src/gromacs/mdlib/force.cpp
index bc1e961f1c77387a4dd7f103c1fc51acbbca9119..07e1337af3e096184aa387b5d6caf66748fca510 100644
--- a/patches/gromacs-2018.3.diff/src/gromacs/mdlib/force.cpp
+++ b/patches/gromacs-2018.4.diff/src/gromacs/mdlib/force.cpp
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -738,7 +738,6 @@ void sum_epot(gmx_grppairener_t *grpp, real *epot)
 void sum_dhdl(gmx_enerdata_t *enerd, gmx::ArrayRef<const real> lambda, t_lambda *fepvals)
 {
     int    index;
-    double dlam;
 
     enerd->dvdl_lin[efptVDW] += enerd->term[F_DVDL_VDW];  /* include dispersion correction */
     enerd->term[F_DVDL]       = 0.0;
@@ -786,13 +785,6 @@ void sum_dhdl(gmx_enerdata_t *enerd, gmx::ArrayRef<const real> lambda, t_lambda
         }
     }
 
-    /* Notes on the foreign lambda free energy difference evaluation:
-     * Adding the potential and ekin terms that depend linearly on lambda
-     * as delta lam * dvdl to the energy differences is exact.
-     * For the constraints this is not exact, but we have no other option
-     * without literally changing the lengths and reevaluating the energies at each step.
-     * (try to remedy this post 4.6 - MRS)
-     */
     if (fepvals->separate_dvdl[efptBONDED])
     {
         enerd->term[F_DVDL_BONDED] += enerd->term[F_DVDL_CONSTR];
@@ -801,7 +793,6 @@ void sum_dhdl(gmx_enerdata_t *enerd, gmx::ArrayRef<const real> lambda, t_lambda
     {
         enerd->term[F_DVDL] += enerd->term[F_DVDL_CONSTR];
     }
-    enerd->term[F_DVDL_CONSTR] = 0;
 
     for (int i = 0; i < fepvals->n_lambda; i++)
     {
@@ -814,20 +805,42 @@ void sum_dhdl(gmx_enerdata_t *enerd, gmx::ArrayRef<const real> lambda, t_lambda
            current lambda, because the contributions to the current
            lambda are automatically zeroed */
 
+        double &enerpart_lambda = enerd->enerpart_lambda[i + 1];
+
         for (size_t j = 0; j < lambda.size(); j++)
         {
             /* Note that this loop is over all dhdl components, not just the separated ones */
-            dlam = (fepvals->all_lambda[j][i] - lambda[j]);
-            enerd->enerpart_lambda[i+1] += dlam*enerd->dvdl_lin[j];
+            const double dlam  = fepvals->all_lambda[j][i] - lambda[j];
+
+            enerpart_lambda   += dlam*enerd->dvdl_lin[j];
+
+            /* Constraints can not be evaluated at foreign lambdas, so we add
+             * a linear extrapolation. This is an approximation, but usually
+             * quite accurate since constraints change little between lambdas.
+             */
+            if ((j == efptBONDED && fepvals->separate_dvdl[efptBONDED]) ||
+                (j == efptFEP && !fepvals->separate_dvdl[efptBONDED]))
+            {
+                enerpart_lambda += dlam*enerd->term[F_DVDL_CONSTR];
+            }
+
+            if (j == efptMASS)
+            {
+                enerpart_lambda += dlam*enerd->term[F_DKDL];
+            }
+
             if (debug)
             {
                 fprintf(debug, "enerdiff lam %g: (%15s), non-linear %f linear %f*%f\n",
                         fepvals->all_lambda[j][i], efpt_names[j],
-                        (enerd->enerpart_lambda[i+1] - enerd->enerpart_lambda[0]),
+                        enerpart_lambda - enerd->enerpart_lambda[0],
                         dlam, enerd->dvdl_lin[j]);
             }
         }
     }
+
+    /* The constrain contribution is now included in other terms, so clear it */
+    enerd->term[F_DVDL_CONSTR] = 0;
 }
 
 
diff --git a/patches/gromacs-2018.3.diff/src/gromacs/mdlib/force.cpp.preplumed b/patches/gromacs-2018.4.diff/src/gromacs/mdlib/force.cpp.preplumed
similarity index 96%
rename from patches/gromacs-2018.3.diff/src/gromacs/mdlib/force.cpp.preplumed
rename to patches/gromacs-2018.4.diff/src/gromacs/mdlib/force.cpp.preplumed
index f01ea4d333a52e51e9f192758e13b44295114843..c939c4e8a7f13553ec52fde621a8812dc35727b7 100644
--- a/patches/gromacs-2018.3.diff/src/gromacs/mdlib/force.cpp.preplumed
+++ b/patches/gromacs-2018.4.diff/src/gromacs/mdlib/force.cpp.preplumed
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * Copyright (c) 2013,2014,2015,2016,2017, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015,2016,2017,2018, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -724,7 +724,6 @@ void sum_epot(gmx_grppairener_t *grpp, real *epot)
 void sum_dhdl(gmx_enerdata_t *enerd, gmx::ArrayRef<const real> lambda, t_lambda *fepvals)
 {
     int    index;
-    double dlam;
 
     enerd->dvdl_lin[efptVDW] += enerd->term[F_DVDL_VDW];  /* include dispersion correction */
     enerd->term[F_DVDL]       = 0.0;
@@ -772,13 +771,6 @@ void sum_dhdl(gmx_enerdata_t *enerd, gmx::ArrayRef<const real> lambda, t_lambda
         }
     }
 
-    /* Notes on the foreign lambda free energy difference evaluation:
-     * Adding the potential and ekin terms that depend linearly on lambda
-     * as delta lam * dvdl to the energy differences is exact.
-     * For the constraints this is not exact, but we have no other option
-     * without literally changing the lengths and reevaluating the energies at each step.
-     * (try to remedy this post 4.6 - MRS)
-     */
     if (fepvals->separate_dvdl[efptBONDED])
     {
         enerd->term[F_DVDL_BONDED] += enerd->term[F_DVDL_CONSTR];
@@ -787,7 +779,6 @@ void sum_dhdl(gmx_enerdata_t *enerd, gmx::ArrayRef<const real> lambda, t_lambda
     {
         enerd->term[F_DVDL] += enerd->term[F_DVDL_CONSTR];
     }
-    enerd->term[F_DVDL_CONSTR] = 0;
 
     for (int i = 0; i < fepvals->n_lambda; i++)
     {
@@ -800,20 +791,42 @@ void sum_dhdl(gmx_enerdata_t *enerd, gmx::ArrayRef<const real> lambda, t_lambda
            current lambda, because the contributions to the current
            lambda are automatically zeroed */
 
+        double &enerpart_lambda = enerd->enerpart_lambda[i + 1];
+
         for (size_t j = 0; j < lambda.size(); j++)
         {
             /* Note that this loop is over all dhdl components, not just the separated ones */
-            dlam = (fepvals->all_lambda[j][i] - lambda[j]);
-            enerd->enerpart_lambda[i+1] += dlam*enerd->dvdl_lin[j];
+            const double dlam  = fepvals->all_lambda[j][i] - lambda[j];
+
+            enerpart_lambda   += dlam*enerd->dvdl_lin[j];
+
+            /* Constraints can not be evaluated at foreign lambdas, so we add
+             * a linear extrapolation. This is an approximation, but usually
+             * quite accurate since constraints change little between lambdas.
+             */
+            if ((j == efptBONDED && fepvals->separate_dvdl[efptBONDED]) ||
+                (j == efptFEP && !fepvals->separate_dvdl[efptBONDED]))
+            {
+                enerpart_lambda += dlam*enerd->term[F_DVDL_CONSTR];
+            }
+
+            if (j == efptMASS)
+            {
+                enerpart_lambda += dlam*enerd->term[F_DKDL];
+            }
+
             if (debug)
             {
                 fprintf(debug, "enerdiff lam %g: (%15s), non-linear %f linear %f*%f\n",
                         fepvals->all_lambda[j][i], efpt_names[j],
-                        (enerd->enerpart_lambda[i+1] - enerd->enerpart_lambda[0]),
+                        enerpart_lambda - enerd->enerpart_lambda[0],
                         dlam, enerd->dvdl_lin[j]);
             }
         }
     }
+
+    /* The constrain contribution is now included in other terms, so clear it */
+    enerd->term[F_DVDL_CONSTR] = 0;
 }
 
 
diff --git a/patches/gromacs-2018.3.diff/src/gromacs/mdlib/minimize.cpp b/patches/gromacs-2018.4.diff/src/gromacs/mdlib/minimize.cpp
similarity index 99%
rename from patches/gromacs-2018.3.diff/src/gromacs/mdlib/minimize.cpp
rename to patches/gromacs-2018.4.diff/src/gromacs/mdlib/minimize.cpp
index a268949cbb431f2cf68f8215456809c51adfe48a..05cd383814ae44eda5d9cba7de468684c207ccd5 100644
--- a/patches/gromacs-2018.3.diff/src/gromacs/mdlib/minimize.cpp
+++ b/patches/gromacs-2018.4.diff/src/gromacs/mdlib/minimize.cpp
@@ -2983,7 +2983,7 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                                     top_global, &state_work, top,
                                     inputrec, nrnb, wcycle, gstat,
                                     vsite, constr, fcd, graph, mdAtoms, fr,
-                                    mu_tot, enerd, vir, pres, atom*2+dx, FALSE);
+                                    mu_tot, enerd, vir, pres, aid*2+dx, FALSE);
                 }
 
                 cr->nnodes = nnodes;
@@ -3019,7 +3019,7 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             }
             else
             {
-                for (node = 0; (node < nnodes && atom+node < atom_index.size()); node++)
+                for (node = 0; (node < nnodes && aid+node < atom_index.size()); node++)
                 {
                     if (node > 0)
                     {
@@ -3031,7 +3031,7 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
 #endif
                     }
 
-                    row = (atom + node)*DIM + d;
+                    row = (aid + node)*DIM + d;
 
                     for (size_t j = 0; j < atom_index.size(); j++)
                     {
diff --git a/patches/gromacs-2018.3.diff/src/gromacs/mdlib/minimize.cpp.preplumed b/patches/gromacs-2018.4.diff/src/gromacs/mdlib/minimize.cpp.preplumed
similarity index 99%
rename from patches/gromacs-2018.3.diff/src/gromacs/mdlib/minimize.cpp.preplumed
rename to patches/gromacs-2018.4.diff/src/gromacs/mdlib/minimize.cpp.preplumed
index d06da48c44742dfcca9f46349a0d2480914bca2f..2c385df11ce31a2f1790093540ff1793f2a02f68 100644
--- a/patches/gromacs-2018.3.diff/src/gromacs/mdlib/minimize.cpp.preplumed
+++ b/patches/gromacs-2018.4.diff/src/gromacs/mdlib/minimize.cpp.preplumed
@@ -2909,7 +2909,7 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                                     top_global, &state_work, top,
                                     inputrec, nrnb, wcycle, gstat,
                                     vsite, constr, fcd, graph, mdAtoms, fr,
-                                    mu_tot, enerd, vir, pres, atom*2+dx, FALSE);
+                                    mu_tot, enerd, vir, pres, aid*2+dx, FALSE);
                 }
 
                 cr->nnodes = nnodes;
@@ -2945,7 +2945,7 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
             }
             else
             {
-                for (node = 0; (node < nnodes && atom+node < atom_index.size()); node++)
+                for (node = 0; (node < nnodes && aid+node < atom_index.size()); node++)
                 {
                     if (node > 0)
                     {
@@ -2957,7 +2957,7 @@ double do_nm(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
 #endif
                     }
 
-                    row = (atom + node)*DIM + d;
+                    row = (aid + node)*DIM + d;
 
                     for (size_t j = 0; j < atom_index.size(); j++)
                     {
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/md.cpp b/patches/gromacs-2018.4.diff/src/programs/mdrun/md.cpp
similarity index 99%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/md.cpp
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/md.cpp
index 132d93d0dc1fed0bd8406176da9b8dc31eb9dbea..31f271a63de7822c7e4931635ef4361c8bbef70c 100644
--- a/patches/gromacs-2018.3.diff/src/programs/mdrun/md.cpp
+++ b/patches/gromacs-2018.4.diff/src/programs/mdrun/md.cpp
@@ -126,6 +126,7 @@
 #include "gromacs/utility/logger.h"
 #include "gromacs/utility/real.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
 
 #include "deform.h"
 #include "membed.h"
@@ -326,6 +327,19 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                   gmx_membed_t *membed,
                   gmx_walltime_accounting_t walltime_accounting)
 {
+    /* Workaround for 2 bugs in release-2018.
+     * NOTE: Proper fix is in release-2019, do not merge this change there.
+     */
+    if (ir->bExpanded && (EI_VV(ir->eI) ||
+                          ir->expandedvals->nstexpanded % ir->nstcalcenergy != 0))
+    {
+        ir->nstcalcenergy = 1;
+        std::string note =
+            gmx::formatString("NOTE: There are issues with expanded ensemble and certain combination of nstexpanded and nstcalcenergy, setting nstcalcenergy to %d",
+                              ir->nstcalcenergy);
+        GMX_LOG(mdlog.warning).asParagraph().appendText(note);
+    }
+
     gmx_mdoutf_t    outf = nullptr;
     gmx_int64_t     step, step_rel;
     double          elapsed_time;
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/md.cpp.preplumed b/patches/gromacs-2018.4.diff/src/programs/mdrun/md.cpp.preplumed
similarity index 99%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/md.cpp.preplumed
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/md.cpp.preplumed
index 1695e0b72d53729f4ece973596131895d9a122b8..de5a7031ff1093334ca547c574fdf64d5596c6ac 100644
--- a/patches/gromacs-2018.3.diff/src/programs/mdrun/md.cpp.preplumed
+++ b/patches/gromacs-2018.4.diff/src/programs/mdrun/md.cpp.preplumed
@@ -125,6 +125,7 @@
 #include "gromacs/utility/logger.h"
 #include "gromacs/utility/real.h"
 #include "gromacs/utility/smalloc.h"
+#include "gromacs/utility/stringutil.h"
 
 #include "deform.h"
 #include "membed.h"
@@ -315,6 +316,19 @@ double gmx::do_md(FILE *fplog, t_commrec *cr, const gmx::MDLogger &mdlog,
                   gmx_membed_t *membed,
                   gmx_walltime_accounting_t walltime_accounting)
 {
+    /* Workaround for 2 bugs in release-2018.
+     * NOTE: Proper fix is in release-2019, do not merge this change there.
+     */
+    if (ir->bExpanded && (EI_VV(ir->eI) ||
+                          ir->expandedvals->nstexpanded % ir->nstcalcenergy != 0))
+    {
+        ir->nstcalcenergy = 1;
+        std::string note =
+            gmx::formatString("NOTE: There are issues with expanded ensemble and certain combination of nstexpanded and nstcalcenergy, setting nstcalcenergy to %d",
+                              ir->nstcalcenergy);
+        GMX_LOG(mdlog.warning).asParagraph().appendText(note);
+    }
+
     gmx_mdoutf_t    outf = nullptr;
     gmx_int64_t     step, step_rel;
     double          elapsed_time;
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/mdrun.cpp b/patches/gromacs-2018.4.diff/src/programs/mdrun/mdrun.cpp
similarity index 97%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/mdrun.cpp
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/mdrun.cpp
index 31ce2bc9c914be0f812a121b538c5ae74137d95c..2fa4b51dfbca01b83f35e26a1e930f879a2354a5 100644
--- a/patches/gromacs-2018.3.diff/src/programs/mdrun/mdrun.cpp
+++ b/patches/gromacs-2018.4.diff/src/programs/mdrun/mdrun.cpp
@@ -512,6 +512,22 @@ int Mdrunner::mainFunction(int argc, char *argv[])
     handleRestart(cr, bTryToAppendFiles, nfile, fnm, &continuationOptions.appendFiles, &continuationOptions.startedFromCheckpoint);
 
     mdrunOptions.rerun            = opt2bSet("-rerun", nfile, fnm);
+
+    if (mdrunOptions.rerun)
+    {
+        /* Rerun can't work if an output file name is the same as the input file name.
+         * If this is the case, the user will get an error telling them what the issue is.
+         */
+        if (strcmp(opt2fn("-rerun", nfile, fnm), opt2fn("-o", nfile, fnm)) == 0 ||
+            strcmp(opt2fn("-rerun", nfile, fnm), opt2fn("-x", nfile, fnm)) == 0)
+        {
+            gmx_fatal(FARGS, "When using mdrun -rerun, the name of the input trajectory file "
+                      "%s cannot be identical to the name of an output file (whether "
+                      "given explicitly with -o or -x, or by default)",
+                      opt2fn("-rerun", nfile, fnm));
+        }
+    }
+
     mdrunOptions.ntompOptionIsSet = opt2parg_bSet("-ntomp", asize(pa), pa);
 
     /* We postpone opening the log file if we are appending, so we can
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/mdrun.cpp.preplumed b/patches/gromacs-2018.4.diff/src/programs/mdrun/mdrun.cpp.preplumed
similarity index 97%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/mdrun.cpp.preplumed
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/mdrun.cpp.preplumed
index 772aabda3833f87e24f6b67a76891308ec3c7ac9..a3ec5ac437710f1b2ebd8b629a0368969d668756 100644
--- a/patches/gromacs-2018.3.diff/src/programs/mdrun/mdrun.cpp.preplumed
+++ b/patches/gromacs-2018.4.diff/src/programs/mdrun/mdrun.cpp.preplumed
@@ -499,6 +499,22 @@ int Mdrunner::mainFunction(int argc, char *argv[])
     handleRestart(cr, bTryToAppendFiles, nfile, fnm, &continuationOptions.appendFiles, &continuationOptions.startedFromCheckpoint);
 
     mdrunOptions.rerun            = opt2bSet("-rerun", nfile, fnm);
+
+    if (mdrunOptions.rerun)
+    {
+        /* Rerun can't work if an output file name is the same as the input file name.
+         * If this is the case, the user will get an error telling them what the issue is.
+         */
+        if (strcmp(opt2fn("-rerun", nfile, fnm), opt2fn("-o", nfile, fnm)) == 0 ||
+            strcmp(opt2fn("-rerun", nfile, fnm), opt2fn("-x", nfile, fnm)) == 0)
+        {
+            gmx_fatal(FARGS, "When using mdrun -rerun, the name of the input trajectory file "
+                      "%s cannot be identical to the name of an output file (whether "
+                      "given explicitly with -o or -x, or by default)",
+                      opt2fn("-rerun", nfile, fnm));
+        }
+    }
+
     mdrunOptions.ntompOptionIsSet = opt2parg_bSet("-ntomp", asize(pa), pa);
 
     /* We postpone opening the log file if we are appending, so we can
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/repl_ex.cpp b/patches/gromacs-2018.4.diff/src/programs/mdrun/repl_ex.cpp
similarity index 100%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/repl_ex.cpp
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/repl_ex.cpp
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/repl_ex.cpp.preplumed b/patches/gromacs-2018.4.diff/src/programs/mdrun/repl_ex.cpp.preplumed
similarity index 100%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/repl_ex.cpp.preplumed
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/repl_ex.cpp.preplumed
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/repl_ex.h b/patches/gromacs-2018.4.diff/src/programs/mdrun/repl_ex.h
similarity index 100%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/repl_ex.h
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/repl_ex.h
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/repl_ex.h.preplumed b/patches/gromacs-2018.4.diff/src/programs/mdrun/repl_ex.h.preplumed
similarity index 100%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/repl_ex.h.preplumed
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/repl_ex.h.preplumed
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/runner.cpp b/patches/gromacs-2018.4.diff/src/programs/mdrun/runner.cpp
similarity index 99%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/runner.cpp
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/runner.cpp
index f1d993f28c7ebffbe54964aae6c9fa2bc80c18f0..25a8230eb42715d61e272b2852b176ef3d812a33 100644
--- a/patches/gromacs-2018.3.diff/src/programs/mdrun/runner.cpp
+++ b/patches/gromacs-2018.4.diff/src/programs/mdrun/runner.cpp
@@ -958,13 +958,17 @@ int Mdrunner::mdrunner()
                           !thisRankHasDuty(cr, DUTY_PP),
                           inputrec->cutoff_scheme == ecutsVERLET);
 
-#ifndef NDEBUG
-    if (EI_TPI(inputrec->eI) &&
+    // Disabled for the rest of the lifetime of release-2018 branch
+    // to prevent false positives.
+    /*
+       #ifndef NDEBUG
+       if (EI_TPI(inputrec->eI) &&
         inputrec->cutoff_scheme == ecutsVERLET)
-    {
+       {
         gmx_feenableexcept();
-    }
-#endif
+       }
+       #endif
+     */
 
     // Build a data structure that expresses which kinds of non-bonded
     // task are handled by this rank.
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/runner.cpp.preplumed b/patches/gromacs-2018.4.diff/src/programs/mdrun/runner.cpp.preplumed
similarity index 99%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/runner.cpp.preplumed
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/runner.cpp.preplumed
index 917ada5687fa1e0c3a0f62fdf3df240ba1f7b113..813be6f3ead3deb828530c431430cfdf34d8364b 100644
--- a/patches/gromacs-2018.3.diff/src/programs/mdrun/runner.cpp.preplumed
+++ b/patches/gromacs-2018.4.diff/src/programs/mdrun/runner.cpp.preplumed
@@ -952,13 +952,17 @@ int Mdrunner::mdrunner()
                           !thisRankHasDuty(cr, DUTY_PP),
                           inputrec->cutoff_scheme == ecutsVERLET);
 
-#ifndef NDEBUG
-    if (EI_TPI(inputrec->eI) &&
+    // Disabled for the rest of the lifetime of release-2018 branch
+    // to prevent false positives.
+    /*
+       #ifndef NDEBUG
+       if (EI_TPI(inputrec->eI) &&
         inputrec->cutoff_scheme == ecutsVERLET)
-    {
+       {
         gmx_feenableexcept();
-    }
-#endif
+       }
+       #endif
+     */
 
     // Build a data structure that expresses which kinds of non-bonded
     // task are handled by this rank.
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/runner.h b/patches/gromacs-2018.4.diff/src/programs/mdrun/runner.h
similarity index 100%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/runner.h
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/runner.h
diff --git a/patches/gromacs-2018.3.diff/src/programs/mdrun/runner.h.preplumed b/patches/gromacs-2018.4.diff/src/programs/mdrun/runner.h.preplumed
similarity index 100%
rename from patches/gromacs-2018.3.diff/src/programs/mdrun/runner.h.preplumed
rename to patches/gromacs-2018.4.diff/src/programs/mdrun/runner.h.preplumed
diff --git a/regtest/basic/rt-make-exceptions/main.cpp b/regtest/basic/rt-make-exceptions/main.cpp
index 238b435e91b40d24ae11aebd18fcc768d39cbf1e..4de17f3819b77d086b6f8f8cc09b4cf37610f5e9 100644
--- a/regtest/basic/rt-make-exceptions/main.cpp
+++ b/regtest/basic/rt-make-exceptions/main.cpp
@@ -1,3 +1,8 @@
+#ifdef __PLUMED_LIBCXX11
+// In order to correctly catch the thrown C++11 exceptions,
+// we notify the Plumed wrapper that those exceptions are recognized by the compiler.
+#define __PLUMED_WRAPPER_LIBCXX11 1
+#endif
 #include "plumed/tools/Stopwatch.h"
 #include "plumed/wrapper/Plumed.h"
 #include <fstream>
@@ -146,6 +151,66 @@ int main(){
     test_this(ofs,plumed,"setMasses",&masses[0]);
   }
 
+  {
+    PLMD::Plumed p;
+
+#define TEST_STD(type) try { p.cmd("throw", #type " msg"); } catch (type & e ) { plumed_assert(std::string(e.what())== #type " msg"); }
+    TEST_STD(std::logic_error);
+    TEST_STD(std::invalid_argument);
+    TEST_STD(std::domain_error);
+    TEST_STD(std::length_error);
+    TEST_STD(std::out_of_range);
+    TEST_STD(std::runtime_error);
+    TEST_STD(std::range_error);
+    TEST_STD(std::overflow_error);
+    TEST_STD(std::underflow_error);
+
+#define TEST_STD_NOMSG(type) try { p.cmd("throw", #type);} catch (type & e ) { }
+    TEST_STD_NOMSG(std::bad_cast);
+#ifdef __PLUMED_LIBCXX11
+    TEST_STD_NOMSG(std::bad_weak_ptr);
+    TEST_STD_NOMSG(std::bad_function_call);
+#endif
+    TEST_STD_NOMSG(std::bad_typeid);
+    TEST_STD_NOMSG(std::bad_alloc);
+#ifdef __PLUMED_LIBCXX11
+    TEST_STD_NOMSG(std::bad_array_new_length);
+#endif
+    TEST_STD_NOMSG(std::bad_exception);
+
+
+    try { p.cmd("throw","PLMD::Exception msg"); } catch (PLMD::Plumed::Exception &e) {
+    }
+    try { p.cmd("throw","PLMD::ExceptionError msg"); } catch (PLMD::Plumed::ExceptionError &e) {
+    }
+    try { p.cmd("throw","PLMD::ExceptionDebug msg"); } catch (PLMD::Plumed::ExceptionDebug &e) {
+    }
+    try { p.cmd("throw","PLMD::lepton::Exception msg"); } catch (PLMD::Plumed::LeptonException &e) {
+      plumed_assert(std::string(e.what())=="PLMD::lepton::Exception msg");
+    }
+#ifdef __PLUMED_LIBCXX11
+    try { p.cmd("throw","std::system_error std::generic_category 100"); } catch (std::system_error & e) {
+      plumed_assert(e.code().value()==100)<<" value="<<e.code().value();
+      plumed_assert(e.code().category()==std::generic_category());
+    }
+    try { p.cmd("throw","std::system_error std::system_category 200"); } catch (std::system_error & e) {
+      plumed_assert(e.code().value()==200);
+      plumed_assert(e.code().category()==std::system_category());
+    }
+    try { p.cmd("throw","std::system_error std::iostream_category 300"); } catch (std::system_error & e) {
+      plumed_assert(e.code().value()==300);
+      plumed_assert(e.code().category()==std::iostream_category());
+    }
+    try { p.cmd("throw","std::system_error std::future_category 400"); } catch (std::system_error & e) {
+      plumed_assert(e.code().value()==400);
+      plumed_assert(e.code().category()==std::future_category());
+    }
+#endif
+    try { p.cmd("throw","std::ios_base::failure"); } catch (std::ios_base::failure & e) {
+    }
+
+  }
+
   return 0;
 
 }
diff --git a/regtest/basic/rt-make-wrappers/main.cpp b/regtest/basic/rt-make-wrappers/main.cpp
index af84b9871cd82af1cd3aff8a84c2a7b047bd15dc..dbc508f29853b42697b539fc29a64a40b76d13a8 100644
--- a/regtest/basic/rt-make-wrappers/main.cpp
+++ b/regtest/basic/rt-make-wrappers/main.cpp
@@ -167,7 +167,7 @@ int main(){
 
 // test valid
     {
-      PLMD::Plumed p(PLMD::Plumed::invalid());
+      PLMD::Plumed p(PLMD::Plumed::makeInvalid());
       if(p) plumed_error();
     }
 
diff --git a/src/core/Makefile b/src/core/Makefile
index a5acc39c8e22c114330c137b110ba41a783db0da..47b809e16d3017266f6ca980da4c14f5f2bfcd4c 100644
--- a/src/core/Makefile
+++ b/src/core/Makefile
@@ -1,4 +1,4 @@
-USE=config tools
+USE=config tools lepton
 
 # generic makefile
 include ../maketools/make.module
diff --git a/src/core/PlumedMain.cpp b/src/core/PlumedMain.cpp
index 4d31ce87dd84b2e9dec3483c8c78f04b2dc61ba3..e8739d5a0376f25ecb3292d6ea790d24572efbce 100644
--- a/src/core/PlumedMain.cpp
+++ b/src/core/PlumedMain.cpp
@@ -40,16 +40,87 @@
 #include "tools/OpenMP.h"
 #include "tools/Tools.h"
 #include "tools/Stopwatch.h"
+#include "lepton/Exception.h"
 #include "DataFetchingObject.h"
 #include <cstdlib>
 #include <cstring>
 #include <set>
 #include <unordered_map>
+#include <exception>
+#include <stdexcept>
+#include <ios>
+#include <new>
+#include <typeinfo>
+#ifdef __PLUMED_LIBCXX11
+#include <system_error>
+#include <future>
+#include <memory>
+#include <functional>
+#endif
+
 
 using namespace std;
 
 namespace PLMD {
 
+/// Small utility just used in this file to throw arbitrary exceptions
+static void testThrow(const char* what) {
+  auto words=Tools::getWords(what);
+  plumed_assert(words.size()>0);
+#define __PLUMED_THROW_NOMSG(type) if(words[0]==#type) throw type()
+#define __PLUMED_THROW_MSG(type) if(words[0]==#type) throw type(what)
+  __PLUMED_THROW_MSG(PLMD::ExceptionError);
+  __PLUMED_THROW_MSG(PLMD::ExceptionDebug);
+  __PLUMED_THROW_MSG(PLMD::Exception);
+  __PLUMED_THROW_MSG(PLMD::lepton::Exception);
+  __PLUMED_THROW_NOMSG(std::bad_exception);
+#ifdef __PLUMED_LIBCXX11
+  __PLUMED_THROW_NOMSG(std::bad_array_new_length);
+#endif
+  __PLUMED_THROW_NOMSG(std::bad_alloc);
+#ifdef __PLUMED_LIBCXX11
+  __PLUMED_THROW_NOMSG(std::bad_function_call);
+  __PLUMED_THROW_NOMSG(std::bad_weak_ptr);
+#endif
+  __PLUMED_THROW_NOMSG(std::bad_cast);
+  __PLUMED_THROW_NOMSG(std::bad_typeid);
+  __PLUMED_THROW_MSG(std::underflow_error);
+  __PLUMED_THROW_MSG(std::overflow_error);
+  __PLUMED_THROW_MSG(std::range_error);
+  __PLUMED_THROW_MSG(std::runtime_error);
+  __PLUMED_THROW_MSG(std::out_of_range);
+  __PLUMED_THROW_MSG(std::length_error);
+  __PLUMED_THROW_MSG(std::domain_error);
+  __PLUMED_THROW_MSG(std::invalid_argument);
+  __PLUMED_THROW_MSG(std::logic_error);
+
+#ifdef __PLUMED_LIBCXX11
+  if(words[0]=="std::system_error") {
+    plumed_assert(words.size()>2);
+    int error_code;
+    Tools::convert(words[2],error_code);
+    if(words[1]=="std::generic_category") throw std::system_error(error_code,std::generic_category(),what);
+    if(words[1]=="std::system_category") throw std::system_error(error_code,std::system_category(),what);
+    if(words[1]=="std::iostream_category") throw std::system_error(error_code,std::iostream_category(),what);
+    if(words[1]=="std::future_category") throw std::system_error(error_code,std::future_category(),what);
+  }
+#endif
+
+  if(words[0]=="std::ios_base::failure") {
+#ifdef __PLUMED_LIBCXX11
+    int error_code=0;
+    if(words.size()>2) Tools::convert(words[2],error_code);
+    if(words.size()>1 && words[1]=="std::generic_category") throw std::ios_base::failure(what,std::error_code(error_code,std::generic_category()));
+    if(words.size()>1 && words[1]=="std::system_category") throw std::ios_base::failure(what,std::error_code(error_code,std::system_category()));
+    if(words.size()>1 && words[1]=="std::iostream_category") throw std::ios_base::failure(what,std::error_code(error_code,std::iostream_category()));
+    if(words.size()>1 && words[1]=="std::future_category") throw std::ios_base::failure(what,std::error_code(error_code,std::future_category()));
+#endif
+    throw std::ios_base::failure(what);
+  }
+
+  plumed_error() << "unknown exception" << what;
+}
+
 PlumedMain::PlumedMain():
   initialized(false),
 // automatically write on log in destructor
@@ -388,6 +459,11 @@ void PlumedMain::cmd(const std::string & word,void*val) {
         CHECK_NOTNULL(val,word);
         OpenMP::setNumThreads(*static_cast<unsigned*>(val));
         break;
+      /* ADDED WITH API==6 */
+      /* only used for testing */
+      case cmd_throw:
+        CHECK_NOTNULL(val,word);
+        testThrow((const char*) val);
       /* STOP API */
       case cmd_setMDEngine:
         CHECK_NOTINIT(initialized,word);
diff --git a/src/core/PlumedMainInitializer.cpp b/src/core/PlumedMainInitializer.cpp
index 6ce26232858ec46a8048ebd8a79f5c33e461e167..aca124ac5fc4b4971a88c6da20dc7744e05a4120 100644
--- a/src/core/PlumedMainInitializer.cpp
+++ b/src/core/PlumedMainInitializer.cpp
@@ -22,12 +22,25 @@
 #include "PlumedMainInitializer.h"
 #include "PlumedMain.h"
 #include "tools/Exception.h"
+#include "lepton/Exception.h"
 #include <cstdlib>
 #include <cstring>
 #include <iostream>
 #if defined __PLUMED_HAS_DLOPEN
 #include <dlfcn.h>
 #endif
+#include <exception>
+#include <stdexcept>
+#include <ios>
+#include <new>
+#include <typeinfo>
+#ifdef __PLUMED_LIBCXX11
+#include <system_error>
+#include <future>
+#include <memory>
+#include <functional>
+#endif
+
 
 using namespace std;
 
@@ -48,21 +61,6 @@ extern "C" void*plumed_plumedmain_create() {
   }
 }
 
-#define __PLUMED_CATCH(e,nothrow) \
-  catch(PLMD::ExceptionError & e) { \
-    nothrow.handler(nothrow.ptr,20200,e.what(),nullptr); \
-  } catch(PLMD::ExceptionDebug & e) { \
-    nothrow.handler(nothrow.ptr,20100,e.what(),nullptr); \
-  } catch(PLMD::Exception & e) { \
-    nothrow.handler(nothrow.ptr,20000,e.what(),nullptr); \
-  } catch(std::runtime_error & e) { \
-    nothrow.handler(nothrow.ptr,10200,e.what(),nullptr); \
-  } catch(std::logic_error & e) { \
-    nothrow.handler(nothrow.ptr,10100,e.what(),nullptr); \
-  } catch(std::exception & e) { \
-    nothrow.handler(nothrow.ptr,10000,e.what(),nullptr); \
-  }
-
 extern "C" void plumed_plumedmain_cmd(void*plumed,const char*key,const void*val) {
   plumed_massert(plumed,"trying to use a plumed object which is not initialized");
   auto p=static_cast<PLMD::PlumedMain*>(plumed);
@@ -76,7 +74,88 @@ extern "C" void plumed_plumedmain_cmd_nothrow(void*plumed,const char*key,const v
   try {
     plumed_massert(plumed,"trying to use a plumed object which is not initialized");
     static_cast<PLMD::PlumedMain*>(plumed)->cmd(key,val);;
-  } __PLUMED_CATCH(e,nothrow)
+  } catch(PLMD::ExceptionError & e) {
+    nothrow.handler(nothrow.ptr,20200,e.what(),nullptr);
+  } catch(PLMD::ExceptionDebug & e) {
+    nothrow.handler(nothrow.ptr,20100,e.what(),nullptr);
+  } catch(PLMD::Exception & e) {
+    nothrow.handler(nothrow.ptr,20000,e.what(),nullptr);
+  } catch(PLMD::lepton::Exception & e) {
+    nothrow.handler(nothrow.ptr,19900,e.what(),nullptr);
+    // 11000 to 12000 are "bad exceptions". message will be copied without new allocations
+  } catch(bad_exception & e) {
+    nothrow.handler(nothrow.ptr,11500,e.what(),nullptr);
+#ifdef __PLUMED_LIBCXX11
+  } catch(bad_array_new_length & e) {
+    nothrow.handler(nothrow.ptr,11410,e.what(),nullptr);
+#endif
+  } catch(bad_alloc & e) {
+    nothrow.handler(nothrow.ptr,11400,e.what(),nullptr);
+#ifdef __PLUMED_LIBCXX11
+  } catch(bad_function_call & e) {
+    nothrow.handler(nothrow.ptr,11300,e.what(),nullptr);
+  } catch(bad_weak_ptr & e) {
+    nothrow.handler(nothrow.ptr,11200,e.what(),nullptr);
+#endif
+  } catch(bad_cast & e) {
+    nothrow.handler(nothrow.ptr,11100,e.what(),nullptr);
+  } catch(bad_typeid & e) {
+    nothrow.handler(nothrow.ptr,11000,e.what(),nullptr);
+    // not implemented yet: std::regex_error
+    // we do not allow regex yet due to portability problems with gcc 4.8
+    // as soon as we transition to using <regex> it should be straightforward to add
+  } catch(std::ios_base::failure & e) {
+#ifdef __PLUMED_LIBCXX11
+    int value=e.code().value();
+    const void* opt[3]= {"c",&value,nullptr}; // "c" passes the error code. nullptr terminates the optional part.
+    if(e.code().category()==generic_category()) nothrow.handler(nothrow.ptr,10230,e.what(),opt);
+    else if(e.code().category()==system_category()) nothrow.handler(nothrow.ptr,10231,e.what(),opt);
+    else if(e.code().category()==iostream_category()) nothrow.handler(nothrow.ptr,10232,e.what(),opt);
+    else if(e.code().category()==future_category()) nothrow.handler(nothrow.ptr,10233,e.what(),opt);
+    else
+#endif
+      // 10239 represents std::ios_base::failure with default constructur
+      nothrow.handler(nothrow.ptr,10239,e.what(),nullptr);
+#ifdef __PLUMED_LIBCXX11
+  } catch(std::system_error & e) {
+    int value=e.code().value();
+    const void* opt[3]= {"c",&value,nullptr}; // "c" passes the error code. nullptr terminates the optional part.
+    if(e.code().category()==generic_category()) nothrow.handler(nothrow.ptr,10220,e.what(),opt);
+    else if(e.code().category()==system_category()) nothrow.handler(nothrow.ptr,10221,e.what(),opt);
+    else if(e.code().category()==iostream_category()) nothrow.handler(nothrow.ptr,10222,e.what(),opt);
+    else if(e.code().category()==future_category()) nothrow.handler(nothrow.ptr,10223,e.what(),opt);
+    // fallback to generic runtime_error
+    else nothrow.handler(nothrow.ptr,10200,e.what(),nullptr);
+#endif
+  } catch(std::underflow_error &e) {
+    nothrow.handler(nothrow.ptr,10215,e.what(),nullptr);
+  } catch(std::overflow_error &e) {
+    nothrow.handler(nothrow.ptr,10210,e.what(),nullptr);
+  } catch(std::range_error &e) {
+    nothrow.handler(nothrow.ptr,10205,e.what(),nullptr);
+  } catch(std::runtime_error & e) {
+    nothrow.handler(nothrow.ptr,10200,e.what(),nullptr);
+    // not implemented yet: std::future_error
+    // not clear how useful it would be.
+  } catch(std::out_of_range & e) {
+    nothrow.handler(nothrow.ptr,10120,e.what(),nullptr);
+  } catch(std::length_error & e) {
+    nothrow.handler(nothrow.ptr,10115,e.what(),nullptr);
+  } catch(std::domain_error & e) {
+    nothrow.handler(nothrow.ptr,10110,e.what(),nullptr);
+  } catch(std::invalid_argument & e) {
+    nothrow.handler(nothrow.ptr,10105,e.what(),nullptr);
+  } catch(std::logic_error & e) {
+    nothrow.handler(nothrow.ptr,10100,e.what(),nullptr);
+    // generic exception. message will be copied without new allocations
+    // reports all non caught exceptions that are derived from std::exception
+    // for instance, boost exceptions would end up here
+  } catch(std::exception & e) {
+    nothrow.handler(nothrow.ptr,10000,e.what(),nullptr);
+  } catch(...) {
+    std::cerr<<"+++ rethrowing an unknown error happened while using a plumed cmd"<<std::endl;
+    throw;
+  }
 }
 
 extern "C" void plumed_plumedmain_finalize(void*plumed) {
diff --git a/src/wrapper/Plumed.h b/src/wrapper/Plumed.h
index bd06dd37305d1fe43a1b45f707bcf96a643892f7..94b7b520d90c97e5bbad4647b3a6b9d13f1cc063 100644
--- a/src/wrapper/Plumed.h
+++ b/src/wrapper/Plumed.h
@@ -158,7 +158,7 @@
 \endverbatim
 
   If you want to create on purpose an invalid Plumed object (useful in C++ to postpone
-  the loading of the library) you can use `Plumed p(Plumed::invalid());`.
+  the loading of the library) you can use `Plumed p(Plumed::makeInvalid());`.
 
   To know if the global object is valid instead you should use the following function:
 \verbatim
@@ -255,6 +255,40 @@
   When you compile the FORTRAN interface, wrapper functions are added with several possible
   name mangligs, so you should not experience problems linking the plumed library with a FORTRAN file.
 
+\paragraph ReferencePlumedH-exceptions Error handling
+
+  Bad things happen. In case an error is detected by PLUMED, either because of some user error, some internal bug,
+  or some mistake in using the library, an exception will be thrown. The behavior is different depending if you use
+  PLUMED from C/FORTRAN or from C++.
+
+  First of all, notice that access to PLUMED goes through three functions:
+  - plumed_create: this, as of PLUMED 2.5, is guaranteed not to throw any exception. If there is a problem, it will
+    just return a NULL pointer
+  - plumed_cmd: this function might throw exceptions.
+  - plumed_finalize: this is a destructor and is guaranteed not to throw any exception.
+
+  The following discussion concerns all the exceptions thrown by plumed_cmd.
+
+  If you use C/FORTRAN, you will basically have no way to intercept the exception and the program will just terminate.
+
+  If you use C++ but you are calling the C interface (e.g. \ref plumed_cmd), then you might be
+  able to catch the exceptions thrown by PLUMED. Notice that all the exceptions thrown by PLUMED inherit from std::exception,
+  so you might want to catch it by reference. Notice however that there is a C layer between your C++ code and the PLUMED
+  library. In principle, the stack unwinding performed during exception handling is undefined in C and might lead to problems
+  that are system and compiler dependent. In addition to this, there might be troubles when combining different compilers
+  or different standard libraries. E.g., if you MD code is linked against a given C++ library and PLUMED is linked against
+  another one, the two std::exception types will differ and you won't be able to catch exceptions raised by PLUMED.
+
+  If you use C++ and you are calling the C++ interface (e.g. \ref Plumed::cmd), as of PLUMED 2.5 we implemented a complete
+  remapping of the exceptions thrown by PLUMED. This solves both the problems mentioned above. In particular:
+  - Instead of throwing an exception, PLUMED will return (using a \ref plumed_nothrow_handler) the details about the occurred error.
+  - An equivalent exception will be thrown within the inline PLUMED interface compiled with your MD code.
+
+  As a consequence, you will be able to combine different compilers and avoid stack unwinding in the C layer.
+
+  The remapping of exceptions takes care of all the standard C++ exceptions plus all the exceptions raised within
+  PLUMED. Unexpected exceptions that are derived from std::exception will be rethrown as std::exception.
+
 \paragraph ReferencePlumedH-2-5 New in PLUMED 2.5
 
   The wrappers in PLUMED 2.5 have been completely rewritten with several improvements.
@@ -423,6 +457,34 @@
 #define __PLUMED_WRAPPER_CXX_POLYMORPHIC 1
 #endif
 
+/*
+  1: make the default constructor create an invalid object
+  0: make the default constructor create a valid object
+
+  Only for internal usage.
+*/
+#ifndef __PLUMED_WRAPPER_CXX_DEFAULT_INVALID
+#define __PLUMED_WRAPPER_CXX_DEFAULT_INVALID 0
+#endif
+
+/*
+  Size of a buffer used to store message for exceptions with noexcept constructor.
+  Should typically hold short messages. Anyway, as long as the stack size stays within the correct
+  limits it does not seem to affect efficiency. Notice that there cannot be recursive calls of
+  PLMD::Plumed::cmd, so that it should be in practice irrelevant.
+*/
+#ifndef __PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER
+#define __PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER 512
+#endif
+
+
+/*
+ By default, assume C++11 compliant library is not available.
+*/
+
+#ifndef __PLUMED_WRAPPER_LIBCXX11
+#define __PLUMED_WRAPPER_LIBCXX11 0
+#endif
 
 /* The following macros are just to define shortcuts */
 
@@ -448,11 +510,13 @@
 #define __PLUMED_WRAPPER_STD
 #endif
 
-/* Allow using noexcept with C++11 compilers */
+/* Allow using noexcept and explicit with C++11 compilers */
 #if __cplusplus > 199711L
 #define __PLUMED_WRAPPER_CXX_NOEXCEPT noexcept
+#define __PLUMED_WRAPPER_CXX_EXPLICIT explicit
 #else
 #define __PLUMED_WRAPPER_CXX_NOEXCEPT throw()
+#define __PLUMED_WRAPPER_CXX_EXPLICIT
 #endif
 
 /* Macros for anonymous namespace */
@@ -919,17 +983,26 @@ __PLUMED_WRAPPER_EXTERN_C_END /*}*/
 
 #if defined( __cplusplus) && __PLUMED_WRAPPER_CXX /*{*/
 
-/* this is to include the NULL pointer */
 #if __PLUMED_WRAPPER_CXX_STD
-#include <cstdlib>
+#include <cstdlib> /* NULL getenv */
+#include <cstring> /* strncat strlen */
 #else
 #include <stdlib.h>
+#include <string.h>
 #endif
 
-/* these are to include standard exceptions */
-#include <exception>
-#include <stdexcept>
-#include <string>
+#include <exception> /* exception bad_exception */
+#include <stdexcept> /* runtime_error logic_error invalid_argument domain_error length_error out_of_range range_error overflow_error underflow_error */
+#include <string> /* string */
+#include <ios> /* iostream_category (C++11) ios_base::failure (C++11 and C++<11) */
+#include <new> /* bad_alloc bad_array_new_length (C++11) */
+#include <typeinfo> /* bad_typeid bad_cast */
+#if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
+#include <system_error> /* system_error generic_category system_category */
+#include <future> /* future_category */
+#include <memory> /* bad_weak_ptr */
+#include <functional> /* bad_function_call */
+#endif
 
 /* C++ interface is hidden in PLMD namespace (same as plumed library) */
 namespace PLMD {
@@ -958,18 +1031,126 @@ class Plumed {
   */
 
   struct NothrowHandler {
+    /** code used for translating messages */
     int code;
+    /** short message buffer for non-throwing exceptions */
+    char exception_buffer[__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER];
+    /** if exception_buffer='\0', message stored as an allocatable string */
     ::std::string what;
+    /** error code for system_error */
+    int error_code;
   };
 
   /**
     Callback function that sets the error handler.
+
+    opt argument is interpreted as the pointer to a null terminated array of void*.
+    The number of non-null element is expected to be even, and there should be a null element
+    that follows. Every pair of pointers should point
+    to a char, identifying the type of argument passed, and an arbitrary object.
+    Currently used to (optionally) pass error_code.
   */
   static void nothrow_handler(void*ptr,int code,const char*what,const void* opt) {
     NothrowHandler* h=(NothrowHandler*) ptr;
     h->code=code;
-    h->what=what;
-    (void) opt; /* not used yet */
+    h->exception_buffer[0]='\0';
+    h->what.clear();
+    h->error_code=0;
+    /*
+       These codes correspond to exceptions that should not allocate a separate buffer but use the fixed one.
+       Notice that a mismatch between the exceptions using the stack buffer here and those implementing
+       the stack buffer would be in practice harmless. However, it makes sense to be consistent.
+    */
+    if(code==10000 || (code>=11000 && code<12000)) {
+      __PLUMED_WRAPPER_STD strncat(h->exception_buffer,what,__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER-1);
+    } else {
+      h->what=what;
+    }
+
+    /* interpret optional arguments */
+    const void** options=(const void**)opt;
+    if(options) while(*options) {
+        if(*((char*)*options)=='c') h->error_code=*((int*)*(options+1));
+        options+=2;
+      }
+
+    static const char* debug=__PLUMED_WRAPPER_STD getenv("PLUMED_EXCEPTIONS_DEBUG");
+
+    if(debug) {
+      fprintf(stderr,"+++ PLUMED_EXCEPTIONS_DEBUG\n");
+      fprintf(stderr,"+++ code: %d error_code: %d message:\n%s\n",h->code,h->error_code,what);
+      if(__PLUMED_WRAPPER_STD strlen(what) > __PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER-1) fprintf(stderr,"+++ WARNING: message will be truncated\n");
+      fprintf(stderr,"+++ END PLUMED_EXCEPTIONS_DEBUG\n");
+    }
+
+  }
+
+  /**
+    Rethrow the exception.
+  */
+
+  static void rethrow(const NothrowHandler&h) {
+    /* The interpretation of the codes should be kept in sync with core/PlumedMainInitializer.cpp */
+    /* check if we are using a full string or a fixes size buffer */
+    const char* msg=(h.exception_buffer[0]?h.exception_buffer:h.what.c_str());
+    if(h.code==1) throw Plumed::Invalid(msg);
+    /* logic errors */
+    if(h.code>=10100 && h.code<10200) {
+      if(h.code>=10105 && h.code<10110) throw ::std::invalid_argument(msg);
+      if(h.code>=10110 && h.code<10115) throw ::std::domain_error(msg);
+      if(h.code>=10115 && h.code<10120) throw ::std::length_error(msg);
+      if(h.code>=10120 && h.code<10125) throw ::std::out_of_range(msg);
+      throw ::std::logic_error(msg);
+    }
+    /* runtime errors */
+    if(h.code>=10200 && h.code<10300) {
+      if(h.code>=10205 && h.code<10210) throw ::std::range_error(msg);
+      if(h.code>=10210 && h.code<10215) throw ::std::overflow_error(msg);
+      if(h.code>=10215 && h.code<10220) throw ::std::underflow_error(msg);
+#if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
+      if(h.code==10220) throw ::std::system_error(h.error_code,::std::generic_category(),msg);
+      if(h.code==10221) throw ::std::system_error(h.error_code,::std::system_category(),msg);
+      if(h.code==10222) throw ::std::system_error(h.error_code,::std::iostream_category(),msg);
+      if(h.code==10223) throw ::std::system_error(h.error_code,::std::future_category(),msg);
+#endif
+      if(h.code>=10230 && h.code<10240) {
+#if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
+// These cases are probably useless as it looks like this should always be std::iostream_category
+        if(h.code==10230) throw ::std::ios_base::failure(msg,std::error_code(h.error_code,::std::generic_category()));
+        if(h.code==10231) throw ::std::ios_base::failure(msg,std::error_code(h.error_code,::std::system_category()));
+        if(h.code==10232) throw ::std::ios_base::failure(msg,std::error_code(h.error_code,::std::iostream_category()));
+        if(h.code==10233) throw ::std::ios_base::failure(msg,std::error_code(h.error_code,::std::future_category()));
+#endif
+        throw ::std::ios_base::failure(msg);
+      }
+      throw ::std::runtime_error(msg);
+    }
+    /* "bad" errors */
+    if(h.code>=11000 && h.code<11100) throw Plumed::std_bad_typeid(msg);
+    if(h.code>=11100 && h.code<11200) throw Plumed::std_bad_cast(msg);
+#if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
+    if(h.code>=11200 && h.code<11300) throw Plumed::std_bad_weak_ptr(msg);
+    if(h.code>=11300 && h.code<11400) throw Plumed::std_bad_function_call(msg);
+#endif
+    if(h.code>=11400 && h.code<11500) {
+#if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
+      if(h.code>=11410 && h.code<11420) throw Plumed::std_bad_array_new_length(msg);
+#endif
+      throw Plumed::std_bad_alloc(msg);
+    }
+    if(h.code>=11500 && h.code<11600) throw Plumed::std_bad_exception(msg);
+    /* lepton error */
+    if(h.code>=19900 && h.code<20000) throw Plumed::LeptonException(msg);
+    /* plumed exceptions */
+    if(h.code>=20000 && h.code<30000) {
+      /* debug - only raised with debug options */
+      if(h.code>=20100 && h.code<20200) throw Plumed::ExceptionDebug(msg);
+      /* error - runtime check */
+      if(h.code>=20200 && h.code<20300) throw Plumed::ExceptionError(msg);
+      throw Plumed::Exception(msg);
+    }
+    /* fallback for any other exception */
+    throw Plumed::std_exception(msg);
   }
 
 public:
@@ -983,7 +1164,7 @@ public:
   {
     ::std::string msg;
   public:
-    Exception(const char* msg): msg(msg) {}
+    __PLUMED_WRAPPER_CXX_EXPLICIT Exception(const char* msg): msg(msg) {}
     Exception(const Exception & other): msg(other.what()) {}
     const char* what() const __PLUMED_WRAPPER_CXX_NOEXCEPT {return msg.c_str();}
     ~Exception() __PLUMED_WRAPPER_CXX_NOEXCEPT {}
@@ -996,7 +1177,7 @@ public:
   class ExceptionError :
     public Exception {
   public:
-    ExceptionError(const char* msg): Exception(msg) {}
+    __PLUMED_WRAPPER_CXX_EXPLICIT ExceptionError(const char* msg): Exception(msg) {}
     ExceptionError(const ExceptionError & other) : Exception(other.what()) {}
     ~ExceptionError() __PLUMED_WRAPPER_CXX_NOEXCEPT {}
   };
@@ -1008,7 +1189,7 @@ public:
   class ExceptionDebug :
     public Exception {
   public:
-    ExceptionDebug(const char* msg): Exception(msg) {}
+    __PLUMED_WRAPPER_CXX_EXPLICIT ExceptionDebug(const char* msg): Exception(msg) {}
     ExceptionDebug(const ExceptionDebug & other) : Exception(other.what()) {}
     ~ExceptionDebug() __PLUMED_WRAPPER_CXX_NOEXCEPT {}
   };
@@ -1020,11 +1201,75 @@ public:
   class Invalid :
     public Exception {
   public:
-    Invalid(const char* msg): Exception(msg) {}
+    __PLUMED_WRAPPER_CXX_EXPLICIT Invalid(const char* msg): Exception(msg) {}
     Invalid(const Invalid & other) : Exception(other.what()) {}
     ~Invalid() __PLUMED_WRAPPER_CXX_NOEXCEPT {}
   };
 
+  /**
+    Class used to rethrow Lepton exceptions.
+  */
+
+  class LeptonException :
+    public ::std::exception
+  {
+    ::std::string msg;
+  public:
+    __PLUMED_WRAPPER_CXX_EXPLICIT LeptonException(const char* msg): msg(msg) {}
+    LeptonException(const LeptonException & other): msg(other.what()) {}
+    const char* what() const __PLUMED_WRAPPER_CXX_NOEXCEPT {return msg.c_str();}
+    ~LeptonException() __PLUMED_WRAPPER_CXX_NOEXCEPT {}
+  };
+
+private:
+  /*
+    These exceptions are declared as private as they are not supposed to be
+    catched by value. they only exist to allow a buffer to be attached to
+    the std::exceptions that do not contain it already.
+    Notice that these exceptions are those whose constructor should never throw, and as
+    such they use a fixed size buffer.
+  */
+
+#define __PLUMED_WRAPPER_NOSTRING_EXCEPTION(name) \
+  class std_ ## name : \
+    public ::std::name \
+  { \
+    char msg[__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER]; \
+  public: \
+    __PLUMED_WRAPPER_CXX_EXPLICIT std_ ## name(const char * msg) __PLUMED_WRAPPER_CXX_NOEXCEPT { \
+      this->msg[0]='\0'; \
+      __PLUMED_WRAPPER_STD strncat(this->msg,msg,__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER-1); \
+      static const char* debug=__PLUMED_WRAPPER_STD getenv("PLUMED_EXCEPTIONS_DEBUG"); \
+      if(debug && __PLUMED_WRAPPER_STD strlen(msg) > __PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER-1) fprintf(stderr,"+++ WARNING: message will be truncated\n"); \
+    } \
+    std_ ## name(const std_ ## name & other) __PLUMED_WRAPPER_CXX_NOEXCEPT { \
+      msg[0]='\0'; \
+      __PLUMED_WRAPPER_STD strncat(msg,other.msg,__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER-1); \
+    } \
+    std_ ## name & operator=(const std_ ## name & other) __PLUMED_WRAPPER_CXX_NOEXCEPT { \
+      if(this==&other) return *this;\
+      msg[0]='\0'; \
+      __PLUMED_WRAPPER_STD strncat(msg,other.msg,__PLUMED_WRAPPER_CXX_EXCEPTION_BUFFER-1); \
+      return *this; \
+    } \
+    const char* what() const __PLUMED_WRAPPER_CXX_NOEXCEPT {return msg;} \
+    ~std_ ## name() __PLUMED_WRAPPER_CXX_NOEXCEPT {} \
+  };
+
+  __PLUMED_WRAPPER_NOSTRING_EXCEPTION(bad_typeid)
+  __PLUMED_WRAPPER_NOSTRING_EXCEPTION(bad_cast)
+#if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
+  __PLUMED_WRAPPER_NOSTRING_EXCEPTION(bad_weak_ptr)
+  __PLUMED_WRAPPER_NOSTRING_EXCEPTION(bad_function_call)
+#endif
+  __PLUMED_WRAPPER_NOSTRING_EXCEPTION(bad_alloc)
+#if __cplusplus > 199711L && __PLUMED_WRAPPER_LIBCXX11
+  __PLUMED_WRAPPER_NOSTRING_EXCEPTION(bad_array_new_length)
+#endif
+  __PLUMED_WRAPPER_NOSTRING_EXCEPTION(bad_exception)
+  __PLUMED_WRAPPER_NOSTRING_EXCEPTION(exception)
+
+public:
 
   /**
      Check if plumed is installed (for runtime binding)
@@ -1121,7 +1366,7 @@ public:
      \return The Plumed global object
   */
   static Plumed global() __PLUMED_WRAPPER_CXX_NOEXCEPT {
-    return plumed_global();
+    return Plumed(plumed_global());
   }
 #endif /*}*/
   /**
@@ -1133,7 +1378,11 @@ public:
     \note Performs the same task a plumed_create()
   */
 Plumed()__PLUMED_WRAPPER_CXX_NOEXCEPT :
+#if __PLUMED_WRAPPER_CXX_DEFAULT_INVALID
+  main(plumed_create_invalid())
+#else
   main(plumed_create())
+#endif
   {
   }
 
@@ -1145,12 +1394,8 @@ Plumed()__PLUMED_WRAPPER_CXX_NOEXCEPT :
      The reference counter for the corresponding object will be increased
      to make sure that the object will be available after plumed_f_finalize is called
      if the created object is still in scope.
-
   */
-// to have maximum portability of this file I do not use the explicit keyword here
-// I thus add a suppress command for cppcheck
-// cppcheck-suppress noExplicitConstructor
-Plumed(const char*c)__PLUMED_WRAPPER_CXX_NOEXCEPT :
+__PLUMED_WRAPPER_CXX_EXPLICIT Plumed(const char*c)__PLUMED_WRAPPER_CXX_NOEXCEPT :
   main(plumed_create_reference_f(c))
   {
   }
@@ -1158,10 +1403,7 @@ Plumed(const char*c)__PLUMED_WRAPPER_CXX_NOEXCEPT :
   /**
     Create a reference from a void* pointer. Available as of PLUMED 2.5.
   */
-// to have maximum portability of this file I do not use the explicit keyword here
-// I thus add a suppress command for cppcheck
-// cppcheck-suppress noExplicitConstructor
-Plumed(void*v)__PLUMED_WRAPPER_CXX_NOEXCEPT :
+__PLUMED_WRAPPER_CXX_EXPLICIT Plumed(void*v)__PLUMED_WRAPPER_CXX_NOEXCEPT :
   main(plumed_create_reference_v(v))
   {
   }
@@ -1175,10 +1417,7 @@ Plumed(void*v)__PLUMED_WRAPPER_CXX_NOEXCEPT :
      to make sure that the object will be available after plumed_finalize is called
      if the created object is still in scope.
   */
-// to have maximum portability of this file I do not use the explicit keyword here
-// I thus add a suppress command for cppcheck
-// cppcheck-suppress noExplicitConstructor
-Plumed(plumed p)__PLUMED_WRAPPER_CXX_NOEXCEPT :
+__PLUMED_WRAPPER_CXX_EXPLICIT Plumed(plumed p)__PLUMED_WRAPPER_CXX_NOEXCEPT :
   main(plumed_create_reference(p))
   {
   }
@@ -1285,17 +1524,30 @@ Plumed(Plumed&&p)__PLUMED_WRAPPER_CXX_NOEXCEPT :
     However, there will be some error reported related to the attempt to load the kernel
     when `p` is initialized. The following solution is the optimal one:
   \verbatim
-    Plumed p(Plumed::invalid());
+    Plumed p(Plumed::makeInvalid());
     setenv("PLUMED_KERNEL","/path/to/kernel/libplumedKernel.so",1);
     p=Plumed();
     p.cmd("init")
   \endverbatim
   */
-  static Plumed invalid() __PLUMED_WRAPPER_CXX_NOEXCEPT  {
+  static Plumed makeInvalid() __PLUMED_WRAPPER_CXX_NOEXCEPT  {
 // use decref to remove the extra reference
     return Plumed(plumed_create_invalid()).decref();
   }
 
+  /**
+    Create a valid PLMD::Plumed object.
+
+    Can be used to create a valid object e.g. when Plumed.h was compiled with
+    `-D__PLUMED_WRAPPER_CXX_DEFAULT_INVALID`. For internal usage.
+  */
+
+  static Plumed makeValid()__PLUMED_WRAPPER_CXX_NOEXCEPT  {
+// use decref to remove the extra reference
+    return Plumed(plumed_create()).decref();
+  }
+
+
   /**
      Retrieve the C plumed structure for this object.
 
@@ -1384,21 +1636,9 @@ Plumed(Plumed&&p)__PLUMED_WRAPPER_CXX_NOEXCEPT :
     h.code=0;
     plumed_nothrow_handler nothrow= {&h,nothrow_handler};
     plumed_cmd_nothrow(main,key,val,nothrow);
-    /* The interpretation of the codes should be kept in sync with core/PlumedMainInitializer.cpp */
-    if(h.code==0) return;
-    if(h.code==1) throw Plumed::Invalid(h.what.c_str());
-    if(h.code>=10000 && h.code<20000) {
-      if(h.code>=10100 && h.code<10200) throw ::std::logic_error(h.what.c_str());
-      if(h.code>=10200 && h.code<10300) throw ::std::runtime_error(h.what.c_str());
-    }
-    if(h.code>=20000 && h.code<30000) {
-      if(h.code>=20100 && h.code<20200) throw Plumed::ExceptionDebug(h.what.c_str());
-      if(h.code>=20200 && h.code<20300) throw Plumed::ExceptionError(h.what.c_str());
-      throw Plumed::Exception(h.what.c_str());
-    }
-    /* all other exception types are mapped to runtime_error */
-    throw ::std::runtime_error(h.what.c_str());
+    if(h.code!=0) rethrow(h);
   }
+
   /**
      Destructor
 
@@ -1423,7 +1663,7 @@ Plumed(Plumed&&p)__PLUMED_WRAPPER_CXX_NOEXCEPT :
   Comparison operator. Available as of PLUMED 2.5.
 */
 inline
-bool operator==(const Plumed&a,const Plumed&b) {
+bool operator==(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
   return a.toVoid()==b.toVoid();
 }
 
@@ -1432,7 +1672,7 @@ bool operator==(const Plumed&a,const Plumed&b) {
   Comparison operator. Available as of PLUMED 2.5.
 */
 inline
-bool operator!=(const Plumed&a,const Plumed&b) {
+bool operator!=(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
   return a.toVoid()!=b.toVoid();
 }
 
@@ -1441,7 +1681,7 @@ bool operator!=(const Plumed&a,const Plumed&b) {
   Comparison operator. Available as of PLUMED 2.5.
 */
 inline
-bool operator<=(const Plumed&a,const Plumed&b) {
+bool operator<=(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
   return a.toVoid()<=b.toVoid();
 }
 
@@ -1450,7 +1690,7 @@ bool operator<=(const Plumed&a,const Plumed&b) {
   Comparison operator. Available as of PLUMED 2.5.
 */
 inline
-bool operator<(const Plumed&a,const Plumed&b) {
+bool operator<(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
   return a.toVoid()<b.toVoid();
 }
 
@@ -1459,7 +1699,7 @@ bool operator<(const Plumed&a,const Plumed&b) {
   Comparison operator. Available as of PLUMED 2.5.
 */
 inline
-bool operator>=(const Plumed&a,const Plumed&b) {
+bool operator>=(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
   return a.toVoid()>=b.toVoid();
 }
 
@@ -1468,7 +1708,7 @@ bool operator>=(const Plumed&a,const Plumed&b) {
   Comparison operator. Available as of PLUMED 2.5.
 */
 inline
-bool operator>(const Plumed&a,const Plumed&b) {
+bool operator>(const Plumed&a,const Plumed&b) __PLUMED_WRAPPER_CXX_NOEXCEPT {
   return a.toVoid()>b.toVoid();
 }
 
@@ -1573,15 +1813,15 @@ __PLUMED_WRAPPER_ANONYMOUS_END /*}*/
 #endif /*}*/
 
 #ifdef __PLUMED_HAS_DLOPEN
-#include <dlfcn.h>
+#include <dlfcn.h> /* dlopen dlerror dlsym */
 #endif
 
 #if __PLUMED_WRAPPER_CXX_STD
-#include <cstdio>
-#include <cstring>
-#include <cassert>
-#include <cstdlib>
-#include <climits>
+#include <cstdio>  /* fprintf */
+#include <cstring> /* memcpy strlen strncpy memcmp memmove strcmp memcpy */
+#include <cassert> /* assert */
+#include <cstdlib> /* getenv malloc free abort exit */
+#include <climits> /* CHAR_BIT */
 #else
 #include <stdio.h>
 #include <string.h>
@@ -1725,7 +1965,7 @@ void* plumed_attempt_dlopen(const char*path,int mode) {
     while(pc>=pathcopy && __PLUMED_WRAPPER_STD memcmp(pc,"Kernel",6)) pc--;
     if(pc>=pathcopy) {
       __PLUMED_WRAPPER_STD memmove(pc, pc+6, __PLUMED_WRAPPER_STD strlen(pc)-5);
-      __PLUMED_FPRINTF(stderr,"+++ This error is expected if you are trying to load a kernel <=2.4");
+      __PLUMED_FPRINTF(stderr,"+++ This error is expected if you are trying to load a kernel <=2.4\n");
       __PLUMED_FPRINTF(stderr,"+++ Trying %s +++\n",pathcopy);
       p=dlopen(pathcopy,mode);
       if(!p) __PLUMED_FPRINTF(stderr,"+++ An error occurred. Message from dlopen(): %s +++\n",dlerror());