diff --git a/arbor/fvm_layout.cpp b/arbor/fvm_layout.cpp
index aa0e9b3af846fcc9a2b0011432d7d3ab68c7eeb9..26fb49664564231e0b6ccf0b6ff1862392f4d922 100644
--- a/arbor/fvm_layout.cpp
+++ b/arbor/fvm_layout.cpp
@@ -340,7 +340,7 @@ fvm_discretization fvm_discretize(const std::vector<cable_cell>& cells, const ca
             }
             else {
                 auto opt_index = util::binary_search_index(D.segments, seg_info.parent_cv,
-                    [&D](const segment_info& seg_info) { return seg_info.distal_cv; });
+                    [](const segment_info& seg_info) { return seg_info.distal_cv; });
 
                 if (!opt_index) {
                     throw arbor_internal_error("fvm_layout: could not find parent segment");
diff --git a/arbor/include/arbor/morph/morphology.hpp b/arbor/include/arbor/morph/morphology.hpp
index 6eed5ef9abc081b61961dc7fc1f849c3e650f30b..0c9ed9b0e6726ee811fa3579c8fefc198f0f7329 100644
--- a/arbor/include/arbor/morph/morphology.hpp
+++ b/arbor/include/arbor/morph/morphology.hpp
@@ -10,7 +10,7 @@
 
 namespace arb {
 
-class morphology_impl;
+struct morphology_impl;
 
 using mindex_range = std::pair<const msize_t*, const msize_t*>;
 
diff --git a/arbor/io/trace.hpp b/arbor/io/trace.hpp
index 3bb71054f4058eec234cd48768ccad5beb37b829..c9f9be8fbb250cd17d13b28c92dd7a8893447d7e 100644
--- a/arbor/io/trace.hpp
+++ b/arbor/io/trace.hpp
@@ -56,8 +56,6 @@ namespace impl {
             lock_(this->guard())
         {}
 
-        emit_nl_locked(emit_nl_locked&&) = default;
-
         ~emit_nl_locked() {
             if (rdbuf()) {
                 (*this) << std::endl;
diff --git a/arbor/mechcat.cpp b/arbor/mechcat.cpp
index 05408d157cf1244e0620f3a7fa0b1e883570f333..1c2a5d0bc213671a6ee656d648d48533f4ec656f 100644
--- a/arbor/mechcat.cpp
+++ b/arbor/mechcat.cpp
@@ -229,7 +229,7 @@ struct catalogue_state {
         const std::string* base = &name;
 
         if (!defined(name)) {
-            if (implicit_deriv = derive(name)) {
+            if ((implicit_deriv = derive(name))) {
                 base = &implicit_deriv.first().parent;
             }
             else {
diff --git a/modcc/io/prefixbuf.hpp b/modcc/io/prefixbuf.hpp
index 3768779781b5bd653fc495c1adee6d2025a8d92e..107637073cc848e34b2bc72848c8a6f7ad489000 100644
--- a/modcc/io/prefixbuf.hpp
+++ b/modcc/io/prefixbuf.hpp
@@ -33,10 +33,16 @@ public:
     explicit prefixbuf(std::streambuf* inner, bool prefix_empty_lines=false):
         inner_(inner), prefix_empty_lines_(prefix_empty_lines) {}
 
-    prefixbuf(prefixbuf&&) = default;
+    prefixbuf(prefixbuf&& other): std::streambuf(other) {
+        prefix = std::move(other.prefix);
+        inner_ = other.inner_;
+        prefix_empty_lines_ = other.prefix_empty_lines_;
+        bol_ = other.bol_;
+    }
+
     prefixbuf(const prefixbuf&) = delete;
 
-    prefixbuf& operator=(prefixbuf&&) = default;
+    prefixbuf& operator=(prefixbuf&&) = delete;
     prefixbuf& operator=(const prefixbuf&) = delete;
 
     std::streambuf* inner() { return inner_; }
@@ -109,20 +115,27 @@ inline indent_manip settab(unsigned w) {
     return indent_manip{indent_manip::settab, w};
 }
 
-// Wrap an stringbuf with a prefixbuf, and present as a stream.
+// Wrap a stringbuf with a prefixbuf, and present as a stream.
 // Acts very much like a `std::ostringstream`, but with prefix
 // and indent functionality.
 
 class pfxstringstream: public std::ostream {
 public:
     pfxstringstream():
-        std::ostream(&pbuf_),
+        std::ostream(nullptr),
         sbuf_(std::ios_base::out),
         pbuf_(&sbuf_)
-    {}
+    {
+        std::ostream::rdbuf(&pbuf_);
+    }
 
-    pfxstringstream(pfxstringstream&&) = default;
-    pfxstringstream& operator=(pfxstringstream&&) = default;
+    pfxstringstream(pfxstringstream&& other):
+        std::ostream(std::move(other)),
+        sbuf_(std::move(other.sbuf_)),
+        pbuf_(std::move(other.pbuf_))
+    {
+        std::ostream::rdbuf(&pbuf_);
+    }
 
     std::string str() const { return sbuf_.str(); }
     void str(const std::string& s) { sbuf_.str(s); }
diff --git a/modcc/solvers.cpp b/modcc/solvers.cpp
index 3ab902551ff2bb7af6d04a0fc8ee2fc5705af3e7..1c8ca27e7bf3d0a1cea7bd1766ae00fe92aa1155 100644
--- a/modcc/solvers.cpp
+++ b/modcc/solvers.cpp
@@ -1,5 +1,6 @@
 #include <map>
 #include <set>
+#include <stdexcept>
 #include <string>
 #include <vector>
 
@@ -392,14 +393,18 @@ void SparseSolverVisitor::finalize() {
     for (unsigned i = 0; i<A_.nrow(); ++i) {
         const symge::sym_row& row = A_[i];
         unsigned rhs_col = A_.augcol();
-        unsigned lhs_col;
-        for (unsigned r = 0; r < A_.nrow(); r++) {
+        unsigned lhs_col = -1;
+        for (unsigned r = 0; r<A_.nrow(); ++r) {
             if (row[r]) {
                 lhs_col = r;
                 break;
             }
         }
 
+        if (lhs_col==-1) {
+            throw std::logic_error("zero row in sparse solver matrix");
+        }
+
         auto expr =
             make_expression<AssignmentExpression>(loc,
                 make_expression<IdentifierExpression>(loc, dvars_[lhs_col]),
@@ -478,14 +483,18 @@ void LinearSolverVisitor::finalize() {
     for (unsigned i = 0; i < A_.nrow(); ++i) {
         const symge::sym_row& row = A_[i];
         unsigned rhs = A_.augcol();
-        unsigned lhs;
-        for (unsigned r = 0; r < A_.nrow(); r++) {
+        unsigned lhs = -1;
+        for (unsigned r = 0; r < A_.nrow(); ++r) {
             if (row[r]) {
                 lhs = r;
                 break;
             }
         }
 
+        if (lhs==-1) {
+            throw std::logic_error("zero row in linear solver matrix");
+        }
+
         auto expr =
             make_expression<AssignmentExpression>(loc,
                     make_expression<IdentifierExpression>(loc, dvars_[lhs]),