diff --git a/modcc/module.cpp b/modcc/module.cpp
index b13b5cb1f3f69aa9418104c1ea8f28ed28f420b5..4bc7a56516269c86100f175e6702388737e2711c 100644
--- a/modcc/module.cpp
+++ b/modcc/module.cpp
@@ -182,6 +182,23 @@ bool Module::semantic() {
     // move functions and procedures to the symbol table
     if(!move_symbols(callables_))  return false;
 
+    // Before starting the inlining process, look for the BREAKPOINT block:
+    // if it includes a SOLVE statement, check that it is the first statement
+    // in the block.
+    if (has_symbol("breakpoint", symbolKind::procedure)) {
+        bool found_non_solve = false;
+        auto breakpoint = symbols_["breakpoint"]->is_procedure();
+        for (const auto& s: breakpoint->body()->statements()) {
+            if(!s->is_solve_statement()) {
+                found_non_solve = true;
+            }
+            else if (found_non_solve) {
+                error("SOLVE statements must come first in BREAKPOINT block", s->location());
+                return false;
+            }
+        }
+    }
+
     // perform semantic analysis and inlining on function and procedure bodies
     if(auto errors = semantic_func_proc()) {
         error("There were "+std::to_string(errors)+" errors in the semantic analysis");
@@ -360,25 +377,13 @@ bool Module::semantic() {
 
     // Grab SOLVE statements, put them in `nrn_state` after translation.
     bool found_solve = false;
-    bool found_non_solve = false;
     std::set<std::string> solved_ids;
 
     for(auto& e: (breakpoint->body()->statements())) {
         SolveExpression* solve_expression = e->is_solve_statement();
-        LocalDeclaration* local_expression = e->is_local_declaration();
-        if(local_expression) {
-            continue;
-        }
         if(!solve_expression) {
-            found_non_solve = true;
             continue;
         }
-        if(found_non_solve) {
-            error("SOLVE statements must come first in BREAKPOINT block",
-                e->location());
-            return false;
-        }
-
         found_solve = true;
         std::unique_ptr<SolverVisitorBase> solver;
 
diff --git a/test/unit-modcc/mod_files/test8.mod b/test/unit-modcc/mod_files/test8.mod
new file mode 100644
index 0000000000000000000000000000000000000000..cbf21748e543ed413f8f73f27cd02d8f1f410386
--- /dev/null
+++ b/test/unit-modcc/mod_files/test8.mod
@@ -0,0 +1,42 @@
+NEURON {
+POINT_PROCESS expsyn
+RANGE tau, e
+NONSPECIFIC_CURRENT i
+}
+
+UNITS {
+(mV) = (millivolt)
+}
+
+PARAMETER {
+tau = 2.0 (ms) : the default for Neuron is 0.1
+e = 0   (mV)
+}
+
+ASSIGNED {}
+
+STATE {
+g
+}
+
+INITIAL {
+g=0
+}
+
+BREAKPOINT {
+SOLVE state METHOD cnexp
+i = foo(g)*(v - e)
+}
+
+DERIVATIVE state {
+g' = -g/tau + tau
+}
+
+NET_RECEIVE(weight) {
+g = g * weight
+}
+
+FUNCTION foo(g) {
+foo = exp(g) + 5
+}
+
diff --git a/test/unit-modcc/test_module.cpp b/test/unit-modcc/test_module.cpp
index 74040532615d59ffa7a38c354d3289e250f9aa1e..f708fc91d5af3b4b6d283a4fcb038c3bb21d281f 100644
--- a/test/unit-modcc/test_module.cpp
+++ b/test/unit-modcc/test_module.cpp
@@ -102,3 +102,14 @@ TEST(Module, linear_mechanisms) {
         }
     }
 }
+
+TEST(Module, breakpoint) {
+    // Test function call in BREAKPOINT block
+    Module m(io::read_all(DATADIR "/mod_files/test8.mod"), "test8.mod");
+    EXPECT_NE(m.buffer().size(), 0);
+
+    Parser p(m, false);
+    EXPECT_TRUE(p.parse());
+
+    EXPECT_TRUE(m.semantic());
+}