From 10df6ab4c165c2df16fc49eba924c96caf8cf27b Mon Sep 17 00:00:00 2001
From: Matus Valo <matusvalo@users.noreply.github.com>
Date: Mon, 17 Apr 2023 13:05:38 +0200
Subject: [PATCH] MAINT: Explicitly mark `cdef` functions not raising exception
 with noexcept (#18266)

Also ping `cython==0.29.33` in the pre-release CI job, because this commit
is one of a few needed to fix SciPy building with the latest 3.0-beta Cython
releases.
---
 scipy/_lib/_ccallback_c.pyx                   |   2 +-
 scipy/_lib/_test_deprecation_def.pyx          |   4 +-
 scipy/cluster/_hierarchy.pyx                  |  22 ++--
 scipy/cluster/_hierarchy_distance_update.pxi  |  14 +--
 scipy/cluster/_optimal_leaf_ordering.pyx      |   6 +-
 scipy/cluster/_structures.pxi                 |  16 +--
 scipy/cluster/_vq.pyx                         |   8 +-
 scipy/interpolate/_bspl.pyx                   |   2 +-
 scipy/interpolate/_poly_common.pxi            |   2 +-
 scipy/interpolate/_ppoly.pyx                  |   8 +-
 scipy/interpolate/interpnd.pyx                |   4 +-
 scipy/io/matlab/_mio5_utils.pyx               |  16 +--
 scipy/io/matlab/_streams.pyx                  |   2 +-
 scipy/linalg/_cythonized_array_utils.pyx      |  14 +--
 scipy/linalg/_decomp_update.pyx.in            | 100 +++++++++---------
 scipy/linalg/_generate_pyx.py                 |  46 ++++----
 scipy/linalg/_matfuncs_expm.pyx.in            |  12 +--
 scipy/ndimage/src/_cytest.pxd                 |   6 +-
 scipy/ndimage/src/_cytest.pyx                 |  10 +-
 scipy/ndimage/src/_ni_label.pyx               |  20 ++--
 scipy/optimize/_bglu_dense.pyx                |   8 +-
 .../_highs/cython/src/_highs_wrapper.pyx      |   4 +-
 scipy/optimize/cython_optimize/_zeros.pxd     |   8 +-
 scipy/optimize/cython_optimize/_zeros.pyx.in  |  10 +-
 scipy/optimize/cython_optimize/c_zeros.pxd    |   2 +-
 scipy/signal/_sosfilt.pyx                     |   2 +-
 scipy/signal/_upfirdn_apply.pyx               |   8 +-
 scipy/sparse/csgraph/_flow.pyx                |   8 +-
 scipy/sparse/csgraph/_matching.pyx            |   2 +-
 scipy/sparse/csgraph/_min_spanning_tree.pyx   |   2 +-
 scipy/sparse/csgraph/_shortest_path.pyx       |  34 +++---
 scipy/sparse/csgraph/_tools.pyx               |   4 +-
 scipy/sparse/csgraph/_traversal.pyx           |  12 +--
 scipy/spatial/_ckdtree.pyx                    |   2 +-
 scipy/spatial/_qhull.pxd                      |  18 ++--
 scipy/spatial/_qhull.pyx                      |  24 ++---
 scipy/spatial/_voronoi.pyx                    |   2 +-
 scipy/spatial/setlist.pxd                     |   4 +-
 scipy/spatial/transform/_rotation.pyx         |  30 +++---
 scipy/special/_agm.pxd                        |   4 +-
 scipy/special/_boxcox.pxd                     |   8 +-
 scipy/special/_comb.pyx                       |   2 +-
 scipy/special/_complexstuff.pxd               |  32 +++---
 scipy/special/_convex_analysis.pxd            |  10 +-
 scipy/special/_cunity.pxd                     |   6 +-
 scipy/special/_cython_special.pxi             |   2 +-
 scipy/special/_cython_special_custom.pxi      |   8 +-
 scipy/special/_digamma.pxd                    |  12 +--
 scipy/special/_ellip_harm.pxd                 |   6 +-
 scipy/special/_ellip_harm_2.pyx               |  12 +--
 scipy/special/_ellipk.pxd                     |   2 +-
 scipy/special/_evalpoly.pxd                   |   2 +-
 scipy/special/_exprel.pxd                     |   2 +-
 scipy/special/_factorial.pxd                  |   2 +-
 scipy/special/_generate_pyx.py                |  24 ++---
 scipy/special/_hyp0f1.pxd                     |   6 +-
 scipy/special/_hyp2f1.pxd                     |  10 +-
 scipy/special/_hypergeometric.pxd             |   2 +-
 scipy/special/_lambertw.pxd                   |   8 +-
 scipy/special/_legacy.pxd                     |  38 +++----
 scipy/special/_loggamma.pxd                   |  14 +--
 scipy/special/_ndtri_exp.pxd                  |   4 +-
 scipy/special/_sici.pxd                       |   8 +-
 scipy/special/_spence.pxd                     |   6 +-
 scipy/special/_spherical_bessel.pxd           |  38 +++----
 scipy/special/_trig.pxd                       |   8 +-
 scipy/special/_ufuncs_extra_code_common.pxi   |   4 +-
 scipy/special/_wright_bessel.pxd              |  18 ++--
 scipy/special/_xlogy.pxd                      |   4 +-
 scipy/special/orthogonal_eval.pxd             |  62 +++++------
 scipy/special/sf_error.pxd                    |   2 +-
 scipy/special/sph_harm.pxd                    |   2 +-
 scipy/stats/_biasedurn.pyx.templ              |   8 +-
 scipy/stats/_qmc_cy.pyx                       |  22 ++--
 scipy/stats/_sobol.pyx                        |  22 ++--
 scipy/stats/_stats.pxd                        |  10 +-
 scipy/stats/_stats.pyx                        |  36 +++----
 scipy/stats/_unuran/unuran_wrapper.pyx.templ  |   8 +-
 78 files changed, 486 insertions(+), 486 deletions(-)

diff --git a/scipy/_lib/_ccallback_c.pyx b/scipy/_lib/_ccallback_c.pyx
index 0704acc6..93a7ec73 100644
--- a/scipy/_lib/_ccallback_c.pyx
+++ b/scipy/_lib/_ccallback_c.pyx
@@ -14,7 +14,7 @@ from .ccallback cimport (ccallback_t, ccallback_prepare, ccallback_release, CCAL
 # PyCapsule helpers
 #
 
-cdef void raw_capsule_destructor(object capsule):
+cdef void raw_capsule_destructor(object capsule) noexcept:
     cdef char *name
     name = PyCapsule_GetName(capsule)
     free(name)
diff --git a/scipy/_lib/_test_deprecation_def.pyx b/scipy/_lib/_test_deprecation_def.pyx
index 2ef1f52f..a976d0ed 100644
--- a/scipy/_lib/_test_deprecation_def.pyx
+++ b/scipy/_lib/_test_deprecation_def.pyx
@@ -1,7 +1,7 @@
-cdef public int foo():
+cdef public int foo() noexcept:
     return 1
 
-cdef public int foo_deprecated():
+cdef public int foo_deprecated() noexcept:
     return 1
 
 from scipy._lib.deprecation import deprecate_cython_api
diff --git a/scipy/cluster/_hierarchy.pyx b/scipy/cluster/_hierarchy.pyx
index 92c83310..8b8a00c3 100644
--- a/scipy/cluster/_hierarchy.pyx
+++ b/scipy/cluster/_hierarchy.pyx
@@ -18,7 +18,7 @@ cdef linkage_distance_update *linkage_methods = [
 include "_structures.pxi"
 
 cdef inline np.npy_int64 condensed_index(np.npy_int64 n, np.npy_int64 i,
-                                         np.npy_int64 j):
+                                         np.npy_int64 j) noexcept:
     """
     Calculate the condensed index of element (i, j) in an n x n condensed
     matrix.
@@ -29,21 +29,21 @@ cdef inline np.npy_int64 condensed_index(np.npy_int64 n, np.npy_int64 i,
         return n * j - (j * (j + 1) / 2) + (i - j - 1)
 
 
-cdef inline int is_visited(uchar *bitset, int i):
+cdef inline int is_visited(uchar *bitset, int i) noexcept:
     """
     Check if node i was visited.
     """
     return bitset[i >> 3] & (1 << (i & 7))
 
 
-cdef inline void set_visited(uchar *bitset, int i):
+cdef inline void set_visited(uchar *bitset, int i) noexcept:
     """
     Mark node i as visited.
     """
     bitset[i >> 3] |= 1 << (i & 7)
 
 
-cpdef void calculate_cluster_sizes(double[:, :] Z, double[:] cs, int n):
+cpdef void calculate_cluster_sizes(double[:, :] Z, double[:] cs, int n) noexcept:
     """
     Calculate the size of each cluster. The result is the fourth column of
     the linkage matrix.
@@ -142,7 +142,7 @@ def cluster_maxclust_dist(double[:, :] Z, int[:] T, int n, int mc):
 
 
 cpdef void cluster_maxclust_monocrit(double[:, :] Z, double[:] MC, int[:] T,
-                                     int n, int max_nc):
+                                     int n, int max_nc) noexcept:
     """
     Form flat clusters by maxclust_monocrit criterion.
 
@@ -228,7 +228,7 @@ cpdef void cluster_maxclust_monocrit(double[:, :] Z, double[:] MC, int[:] T,
 
 
 cpdef void cluster_monocrit(double[:, :] Z, double[:] MC, int[:] T,
-                            double cutoff, int n):
+                            double cutoff, int n) noexcept:
     """
     Form flat clusters by monocrit criterion.
 
@@ -368,7 +368,7 @@ def cophenetic_distances(double[:, :] Z, double[:] d, int n):
 
 
 cpdef void get_max_Rfield_for_each_cluster(double[:, :] Z, double[:, :] R,
-                                           double[:] max_rfs, int n, int rf):
+                                           double[:] max_rfs, int n, int rf) noexcept:
     """
     Get the maximum statistic for each non-singleton cluster. For the i'th
     non-singleton cluster, max_rfs[i] = max{R[j, rf] j is a descendent of i}.
@@ -431,7 +431,7 @@ cpdef void get_max_Rfield_for_each_cluster(double[:, :] Z, double[:, :] R,
     PyMem_Free(visited)
 
 
-cpdef get_max_dist_for_each_cluster(double[:, :] Z, double[:] MD, int n):
+cpdef get_max_dist_for_each_cluster(double[:, :] Z, double[:] MD, int n) noexcept:
     """
     Get the maximum inconsistency coefficient for each non-singleton cluster.
 
@@ -1080,7 +1080,7 @@ cdef class LinkageUnionFind:
         self.next_label = n
         self.size = np.ones(2 * n - 1, dtype=np.intc)
 
-    cdef int merge(self, int x, int y):
+    cdef int merge(self, int x, int y) noexcept:
         self.parent[x] = self.next_label
         self.parent[y] = self.next_label
         cdef int size = self.size[x] + self.size[y]
@@ -1088,7 +1088,7 @@ cdef class LinkageUnionFind:
         self.next_label += 1
         return size
 
-    cdef find(self, int x):
+    cdef find(self, int x) noexcept:
         cdef int p = x
 
         while self.parent[x] != x:
@@ -1100,7 +1100,7 @@ cdef class LinkageUnionFind:
         return x
 
 
-cdef label(double[:, :] Z, int n):
+cdef label(double[:, :] Z, int n) noexcept:
     """Correctly label clusters in unsorted dendrogram."""
     cdef LinkageUnionFind uf = LinkageUnionFind(n)
     cdef int i, x, y, x_root, y_root
diff --git a/scipy/cluster/_hierarchy_distance_update.pxi b/scipy/cluster/_hierarchy_distance_update.pxi
index bd47c209..17dedb30 100644
--- a/scipy/cluster/_hierarchy_distance_update.pxi
+++ b/scipy/cluster/_hierarchy_distance_update.pxi
@@ -28,34 +28,34 @@ ctypedef double (*linkage_distance_update)(double d_xi, double d_yi,
 
 
 cdef double _single(double d_xi, double d_yi, double d_xy,
-                    int size_x, int size_y, int size_i):
+                    int size_x, int size_y, int size_i) noexcept:
     return min(d_xi, d_yi)
 
 
 cdef double _complete(double d_xi, double d_yi, double d_xy,
-                      int size_x, int size_y, int size_i):
+                      int size_x, int size_y, int size_i) noexcept:
     return max(d_xi, d_yi)
 
 
 cdef double _average(double d_xi, double d_yi, double d_xy,
-                     int size_x, int size_y, int size_i):
+                     int size_x, int size_y, int size_i) noexcept:
     return (size_x * d_xi + size_y * d_yi) / (size_x + size_y)
 
 
 cdef double _centroid(double d_xi, double d_yi, double d_xy,
-                      int size_x, int size_y, int size_i):
+                      int size_x, int size_y, int size_i) noexcept:
     return sqrt((((size_x * d_xi * d_xi) + (size_y * d_yi * d_yi)) -
                  (size_x * size_y * d_xy * d_xy) / (size_x + size_y)) /
                 (size_x + size_y))
 
 
 cdef double _median(double d_xi, double d_yi, double d_xy,
-                    int size_x, int size_y, int size_i):
+                    int size_x, int size_y, int size_i) noexcept:
     return sqrt(0.5 * (d_xi * d_xi + d_yi * d_yi) - 0.25 * d_xy * d_xy)
 
 
 cdef double _ward(double d_xi, double d_yi, double d_xy,
-                  int size_x, int size_y, int size_i):
+                  int size_x, int size_y, int size_i) noexcept:
     cdef double t = 1.0 / (size_x + size_y + size_i)
     return sqrt((size_i + size_x) * t * d_xi * d_xi +
                 (size_i + size_y) * t * d_yi * d_yi -
@@ -63,5 +63,5 @@ cdef double _ward(double d_xi, double d_yi, double d_xy,
 
 
 cdef double _weighted(double d_xi, double d_yi, double d_xy,
-                      int size_x, int size_y, int size_i):
+                      int size_x, int size_y, int size_i) noexcept:
     return 0.5 * (d_xi + d_yi)
diff --git a/scipy/cluster/_optimal_leaf_ordering.pyx b/scipy/cluster/_optimal_leaf_ordering.pyx
index d8c86230..633bf395 100644
--- a/scipy/cluster/_optimal_leaf_ordering.pyx
+++ b/scipy/cluster/_optimal_leaf_ordering.pyx
@@ -38,7 +38,7 @@ np.import_array()
 @cython.boundscheck(False)
 @cython.wraparound(False)
 cdef inline void dual_swap(float* darr, int* iarr,
-                           int i1, int i2):
+                           int i1, int i2) noexcept:
     """
     [Taken from Scikit-learn.]
 
@@ -121,7 +121,7 @@ cdef int _simultaneous_sort(float* dist, int* idx,
 
 cdef inline void _sort_M_slice(float[:, ::1] M,
                                float* vals, int* idx,
-                               int dim1_min, int dim1_max, int dim2_val):
+                               int dim1_min, int dim1_max, int dim2_val) noexcept:
     """
     Simultaneously sort indices and values of M[{m}, u] using
     `_simultaneous_sort`
@@ -144,7 +144,7 @@ cdef inline void _sort_M_slice(float[:, ::1] M,
 @cython.wraparound(False)
 cdef int[:] identify_swaps(int[:, ::1] sorted_Z,
                            double[:, ::1] sorted_D,
-                           int[:, ::1] cluster_ranges):
+                           int[:, ::1] cluster_ranges) noexcept:
     """
     Implements the Optimal Leaf Ordering algorithm described in
     "Fast Optimal leaf ordering for hierarchical clustering"
diff --git a/scipy/cluster/_structures.pxi b/scipy/cluster/_structures.pxi
index 1d8f4a5f..31697ef4 100644
--- a/scipy/cluster/_structures.pxi
+++ b/scipy/cluster/_structures.pxi
@@ -42,15 +42,15 @@ cdef class Heap:
         for i in reversed(range(self.size / 2)):
             self.sift_down(i)
 
-    cpdef Pair get_min(self):
+    cpdef Pair get_min(self) noexcept:
         return Pair(self.key_by_index[0], self.values[0])
 
-    cpdef void remove_min(self):
+    cpdef void remove_min(self) noexcept:
         self.swap(0, self.size - 1)
         self.size -= 1
         self.sift_down(0)
 
-    cpdef void change_value(self, int key, double value):
+    cpdef void change_value(self, int key, double value) noexcept:
         cdef int index = self.index_by_key[key]
         cdef double old_value = self.values[index]
         self.values[index] = value
@@ -59,14 +59,14 @@ cdef class Heap:
         else:
             self.sift_down(index)
 
-    cdef void sift_up(self, int index):
+    cdef void sift_up(self, int index) noexcept:
         cdef int parent = Heap.parent(index)
         while index > 0 and self.values[parent] > self.values[index]:
             self.swap(index, parent)
             index = parent
             parent = Heap.parent(index)
 
-    cdef void sift_down(self, int index):
+    cdef void sift_down(self, int index) noexcept:
         cdef int child = Heap.left_child(index)
         while child < self.size:
             if (child + 1 < self.size and
@@ -81,14 +81,14 @@ cdef class Heap:
                 break
 
     @staticmethod
-    cdef inline int left_child(int parent):
+    cdef inline int left_child(int parent) noexcept:
         return (parent << 1) + 1
 
     @staticmethod
-    cdef inline int parent(int child):
+    cdef inline int parent(int child) noexcept:
         return (child - 1) >> 1
 
-    cdef void swap(self, int i, int j):
+    cdef void swap(self, int i, int j) noexcept:
         self.values[i], self.values[j] = self.values[j], self.values[i]
         cdef int key_i = self.key_by_index[i]
         cdef int key_j = self.key_by_index[j]
diff --git a/scipy/cluster/_vq.pyx b/scipy/cluster/_vq.pyx
index e785ea63..d5c66d29 100644
--- a/scipy/cluster/_vq.pyx
+++ b/scipy/cluster/_vq.pyx
@@ -32,7 +32,7 @@ DEF NFEATURES_CUTOFF=5
 np.import_array()
 
 
-cdef inline vq_type vec_sqr(int n, vq_type *p):
+cdef inline vq_type vec_sqr(int n, vq_type *p) noexcept:
     cdef vq_type result = 0.0
     cdef int i
     for i in range(n):
@@ -41,7 +41,7 @@ cdef inline vq_type vec_sqr(int n, vq_type *p):
 
 
 cdef inline void cal_M(int nobs, int ncodes, int nfeat, vq_type *obs,
-                       vq_type *code_book, vq_type *M):
+                       vq_type *code_book, vq_type *M) noexcept:
     """
     Calculate M = obs * code_book.T
     """
@@ -137,7 +137,7 @@ cdef int _vq(vq_type *obs, vq_type *code_book,
 
 cdef void _vq_small_nf(vq_type *obs, vq_type *code_book,
                        int ncodes, int nfeat, int nobs,
-                       int32_t *codes, vq_type *low_dist):
+                       int32_t *codes, vq_type *low_dist) noexcept:
     """
     Vector quantization using naive algorithm.
     This is preferred when nfeat is small.
@@ -243,7 +243,7 @@ def vq(np.ndarray obs, np.ndarray codes):
 
 @cython.cdivision(True)
 cdef np.ndarray _update_cluster_means(vq_type *obs, int32_t *labels,
-                                      vq_type *cb, int nobs, int nc, int nfeat):
+                                      vq_type *cb, int nobs, int nc, int nfeat) noexcept:
     """
     The underlying function (template) of _vq.update_cluster_means.
 
diff --git a/scipy/interpolate/_bspl.pyx b/scipy/interpolate/_bspl.pyx
index 347dc13b..7ca6184d 100644
--- a/scipy/interpolate/_bspl.pyx
+++ b/scipy/interpolate/_bspl.pyx
@@ -34,7 +34,7 @@ cdef inline int find_interval(const double[::1] t,
                        int k,
                        double xval,
                        int prev_l,
-                       bint extrapolate) nogil:
+                       bint extrapolate) noexcept nogil:
     """
     Find an interval such that t[interval] <= xval < t[interval+1].
 
diff --git a/scipy/interpolate/_poly_common.pxi b/scipy/interpolate/_poly_common.pxi
index 7764ed95..64f36f14 100644
--- a/scipy/interpolate/_poly_common.pxi
+++ b/scipy/interpolate/_poly_common.pxi
@@ -14,7 +14,7 @@ cdef int find_interval_ascending(const double *x,
                                  size_t nx,
                                  double xval,
                                  int prev_interval=0,
-                                 bint extrapolate=1) nogil:
+                                 bint extrapolate=1) noexcept nogil:
     """
     Find an interval such that x[interval] <= xval < x[interval+1]. Assuming
     that x is sorted in the ascending order.
diff --git a/scipy/interpolate/_ppoly.pyx b/scipy/interpolate/_ppoly.pyx
index e77230c4..12d50864 100644
--- a/scipy/interpolate/_ppoly.pyx
+++ b/scipy/interpolate/_ppoly.pyx
@@ -564,7 +564,7 @@ cdef int find_interval_descending(const double *x,
                                  size_t nx,
                                  double xval,
                                  int prev_interval=0,
-                                 bint extrapolate=1) nogil:
+                                 bint extrapolate=1) noexcept nogil:
     """
     Find an interval such that x[interval + 1] < xval <= x[interval], assuming
     that x are sorted in the descending order.
@@ -648,7 +648,7 @@ cdef int find_interval_descending(const double *x,
 @cython.wraparound(False)
 @cython.boundscheck(False)
 @cython.cdivision(True)
-cdef double_or_complex evaluate_poly1(double s, double_or_complex[:,:,::1] c, int ci, int cj, int dx) nogil:
+cdef double_or_complex evaluate_poly1(double s, double_or_complex[:,:,::1] c, int ci, int cj, int dx) noexcept nogil:
     """
     Evaluate polynomial, derivative, or antiderivative in a single interval.
 
@@ -932,7 +932,7 @@ def _croots_poly1(double[:,:,::1] c, double_complex[:,:,::1] w, double y=0):
 @cython.cdivision(True)
 cdef double_or_complex evaluate_bpoly1(double_or_complex s,
                                        double_or_complex[:,:,::1] c,
-                                       int ci, int cj) nogil:
+                                       int ci, int cj) noexcept nogil:
     """
     Evaluate polynomial in the Bernstein basis in a single interval.
 
@@ -985,7 +985,7 @@ cdef double_or_complex evaluate_bpoly1_deriv(double_or_complex s,
                                              double_or_complex[:,:,::1] c,
                                              int ci, int cj,
                                              int nu,
-                                             double_or_complex[:,:,::1] wrk) nogil:
+                                             double_or_complex[:,:,::1] wrk) noexcept nogil:
     """
     Evaluate the derivative of a polynomial in the Bernstein basis
     in a single interval.
diff --git a/scipy/interpolate/interpnd.pyx b/scipy/interpolate/interpnd.pyx
index 06ae5124..8fda7cca 100644
--- a/scipy/interpolate/interpnd.pyx
+++ b/scipy/interpolate/interpnd.pyx
@@ -350,7 +350,7 @@ class GradientEstimationWarning(Warning):
 @cython.cdivision(True)
 cdef int _estimate_gradients_2d_global(qhull.DelaunayInfo_t *d, double *data,
                                        int maxiter, double tol,
-                                       double *y) nogil:
+                                       double *y) noexcept nogil:
     """
     Estimate gradients of a function at the vertices of a 2d triangulation.
 
@@ -583,7 +583,7 @@ cdef double_or_complex _clough_tocher_2d_single(qhull.DelaunayInfo_t *d,
                                                 int isimplex,
                                                 double *b,
                                                 double_or_complex *f,
-                                                double_or_complex *df) nogil:
+                                                double_or_complex *df) noexcept nogil:
     """
     Evaluate Clough-Tocher interpolant on a 2D triangle.
 
diff --git a/scipy/io/matlab/_mio5_utils.pyx b/scipy/io/matlab/_mio5_utils.pyx
index 30793a61..c742e8ca 100644
--- a/scipy/io/matlab/_mio5_utils.pyx
+++ b/scipy/io/matlab/_mio5_utils.pyx
@@ -109,7 +109,7 @@ cdef cnp.dtype OPAQUE_DTYPE = mio5p.OPAQUE_DTYPE
 cdef cnp.dtype BOOL_DTYPE = np.dtype(np.bool_)
 
 
-cpdef cnp.uint32_t byteswap_u4(cnp.uint32_t u4):
+cpdef cnp.uint32_t byteswap_u4(cnp.uint32_t u4) noexcept:
     return ((u4 << 24) |
            ((u4 << 8) & 0xff0000U) |
            ((u4 >> 8 & 0xff00u)) |
@@ -406,7 +406,7 @@ cdef class VarReader5:
                 self.cstream.seek(8 - mod8, 1)
         return 0
 
-    cpdef cnp.ndarray read_numeric(self, int copy=True, size_t nnz=-1):
+    cpdef cnp.ndarray read_numeric(self, int copy=True, size_t nnz=-1) noexcept:
         ''' Read numeric data element into ndarray
 
         Reads element, then casts to ndarray.
@@ -558,7 +558,7 @@ cdef class VarReader5:
             byte_count[0] = u4s[1]
         return 0
 
-    cpdef VarHeader5 read_header(self, int check_stream_limit):
+    cpdef VarHeader5 read_header(self, int check_stream_limit) noexcept:
         ''' Return matrix header for current stream position
 
         Returns matrix headers at top level and sub levels
@@ -609,7 +609,7 @@ cdef class VarReader5:
         header.name = self.read_int8_string()
         return header
 
-    cdef inline size_t size_from_header(self, VarHeader5 header):
+    cdef inline size_t size_from_header(self, VarHeader5 header) noexcept:
         ''' Supporting routine for calculating array sizes from header
 
         Probably unnecessary optimization that uses integers stored in
@@ -750,7 +750,7 @@ cdef class VarReader5:
             shape = tuple([x for x in shape if x != 1])
         return shape
 
-    cpdef cnp.ndarray read_real_complex(self, VarHeader5 header):
+    cpdef cnp.ndarray read_real_complex(self, VarHeader5 header) noexcept:
         ''' Read real / complex matrices from stream '''
         cdef:
             cnp.ndarray res, res_j
@@ -803,7 +803,7 @@ cdef class VarReader5:
             (data[:nnz], rowind[:nnz], indptr),
             shape=(M, N))
 
-    cpdef cnp.ndarray read_char(self, VarHeader5 header):
+    cpdef cnp.ndarray read_char(self, VarHeader5 header) noexcept:
         ''' Read char matrices from stream as arrays
 
         Matrices of char are likely to be converted to matrices of
@@ -871,7 +871,7 @@ cdef class VarReader5:
                           buffer=arr,
                           order='F')
 
-    cpdef cnp.ndarray read_cells(self, VarHeader5 header):
+    cpdef cnp.ndarray read_cells(self, VarHeader5 header) noexcept:
         ''' Read cell array from stream '''
         cdef:
             size_t i
@@ -927,7 +927,7 @@ cdef class VarReader5:
         n_names_ptr[0] = n_names
         return field_names
 
-    cpdef cnp.ndarray read_struct(self, VarHeader5 header):
+    cpdef cnp.ndarray read_struct(self, VarHeader5 header) noexcept:
         ''' Read struct or object array from stream
 
         Objects are just structs with an extra field *classname*,
diff --git a/scipy/io/matlab/_streams.pyx b/scipy/io/matlab/_streams.pyx
index 8d93be01..8499de1e 100644
--- a/scipy/io/matlab/_streams.pyx
+++ b/scipy/io/matlab/_streams.pyx
@@ -236,7 +236,7 @@ def _read_string(GenericStream st, size_t n):
     return bytes(my_str)
 
 
-cpdef GenericStream make_stream(object fobj):
+cpdef GenericStream make_stream(object fobj) noexcept:
     """ Make stream of correct type for file-like `fobj`
     """
     if isinstance(fobj, GenericStream):
diff --git a/scipy/linalg/_cythonized_array_utils.pyx b/scipy/linalg/_cythonized_array_utils.pyx
index ea1c58de..9db71007 100644
--- a/scipy/linalg/_cythonized_array_utils.pyx
+++ b/scipy/linalg/_cythonized_array_utils.pyx
@@ -15,7 +15,7 @@ __all__ = ['bandwidth', 'issymmetric', 'ishermitian']
 @cython.wraparound(False)
 @cython.boundscheck(False)
 @cython.initializedcheck(False)
-cdef void swap_c_and_f_layout(lapack_t *a, lapack_t *b, int r, int c, int n) nogil:
+cdef void swap_c_and_f_layout(lapack_t *a, lapack_t *b, int r, int c, int n) noexcept nogil:
     """Recursive matrix transposition for square arrays"""
     cdef int i, j, ith_row, r2, c2
     cdef lapack_t *bb=b
@@ -129,7 +129,7 @@ def bandwidth_noncontig(np_numeric_t[:, :]A):
 @cython.initializedcheck(False)
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline (int, int) band_check_internal_c(np_numeric_t[:, ::1]A) nogil:
+cdef inline (int, int) band_check_internal_c(np_numeric_t[:, ::1]A) noexcept nogil:
     cdef Py_ssize_t n = A.shape[0], m = A.shape[1]
     cdef Py_ssize_t lower_band = 0, upper_band = 0, r, c
     cdef np_numeric_t zero = 0
@@ -160,7 +160,7 @@ cdef inline (int, int) band_check_internal_c(np_numeric_t[:, ::1]A) nogil:
 @cython.initializedcheck(False)
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline (int, int) band_check_internal_noncontig(np_numeric_t[:, :]A) nogil:
+cdef inline (int, int) band_check_internal_noncontig(np_numeric_t[:, :]A) noexcept nogil:
     cdef Py_ssize_t n = A.shape[0], m = A.shape[1]
     cdef Py_ssize_t lower_band = 0, upper_band = 0, r, c
     cdef np_numeric_t zero = 0
@@ -295,7 +295,7 @@ def is_sym_her_real_noncontig(np_numeric_t[:, :]A):
 @cython.initializedcheck(False)
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline bint is_sym_her_real_c_internal(np_numeric_t[:, ::1]A) nogil:
+cdef inline bint is_sym_her_real_c_internal(np_numeric_t[:, ::1]A) noexcept nogil:
     cdef Py_ssize_t n = A.shape[0], r, c
 
     for r in xrange(n):
@@ -308,7 +308,7 @@ cdef inline bint is_sym_her_real_c_internal(np_numeric_t[:, ::1]A) nogil:
 @cython.initializedcheck(False)
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline bint is_sym_her_real_noncontig_internal(np_numeric_t[:, :]A) nogil:
+cdef inline bint is_sym_her_real_noncontig_internal(np_numeric_t[:, :]A) noexcept nogil:
     cdef Py_ssize_t n = A.shape[0], r, c
 
     for r in xrange(n):
@@ -438,7 +438,7 @@ def is_sym_her_complex_noncontig(np_complex_numeric_t[:, :]A):
 @cython.initializedcheck(False)
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline bint is_sym_her_complex_c_internal(np_complex_numeric_t[:, ::1]A) nogil:
+cdef inline bint is_sym_her_complex_c_internal(np_complex_numeric_t[:, ::1]A) noexcept nogil:
     cdef Py_ssize_t n = A.shape[0], r, c
 
     for r in xrange(n):
@@ -450,7 +450,7 @@ cdef inline bint is_sym_her_complex_c_internal(np_complex_numeric_t[:, ::1]A) no
 @cython.initializedcheck(False)
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline bint is_sym_her_complex_noncontig_internal(np_complex_numeric_t[:, :]A) nogil:
+cdef inline bint is_sym_her_complex_noncontig_internal(np_complex_numeric_t[:, :]A) noexcept nogil:
     cdef Py_ssize_t n = A.shape[0], r, c
 
     for r in xrange(n):
diff --git a/scipy/linalg/_decomp_update.pyx.in b/scipy/linalg/_decomp_update.pyx.in
index e5801edf..2905f357 100644
--- a/scipy/linalg/_decomp_update.pyx.in
+++ b/scipy/linalg/_decomp_update.pyx.in
@@ -84,50 +84,50 @@ ctypedef fused blas_t:
     float_complex
     double_complex
 
-cdef inline blas_t* index2(blas_t* a, int* as, int i, int j) nogil:
+cdef inline blas_t* index2(blas_t* a, int* as, int i, int j) noexcept nogil:
     return a + i*as[0] + j*as[1]
 
-cdef inline blas_t* index1(blas_t* a, int* as, int i) nogil:
+cdef inline blas_t* index1(blas_t* a, int* as, int i) noexcept nogil:
     return a + i*as[0]
 
-cdef inline blas_t* row(blas_t* a, int* as, int i) nogil:
+cdef inline blas_t* row(blas_t* a, int* as, int i) noexcept nogil:
     return a + i*as[0]
 
-cdef inline blas_t* col(blas_t* a, int* as, int j) nogil:
+cdef inline blas_t* col(blas_t* a, int* as, int j) noexcept nogil:
     return a + j*as[1]
 
-cdef inline void copy(int n, blas_t* x, int incx, blas_t* y, int incy) nogil:
+cdef inline void copy(int n, blas_t* x, int incx, blas_t* y, int incy) noexcept nogil:
     {{for COND, CNAME, C in zip(CONDS, CNAMES, PREFIX)}}
     {{COND}} blas_t is {{CNAME}}:
         blas_pointers.{{C}}copy(&n, x, &incx, y, &incy)
     {{endfor}}
 
-cdef inline void swap(int n, blas_t* x, int incx, blas_t* y, int incy) nogil:
+cdef inline void swap(int n, blas_t* x, int incx, blas_t* y, int incy) noexcept nogil:
     {{for COND, CNAME, C in zip(CONDS, CNAMES, PREFIX)}}
     {{COND}} blas_t is {{CNAME}}:
         blas_pointers.{{C}}swap(&n, x, &incx, y, &incy)
     {{endfor}}
 
-cdef inline void scal(int n, blas_t a, blas_t* x, int incx) nogil:
+cdef inline void scal(int n, blas_t a, blas_t* x, int incx) noexcept nogil:
     {{for COND, CNAME, C in zip(CONDS, CNAMES, PREFIX)}}
     {{COND}} blas_t is {{CNAME}}:
         blas_pointers.{{C}}scal(&n, &a, x, &incx)
     {{endfor}}
 
 cdef inline void axpy(int n, blas_t a, blas_t* x, int incx,
-                      blas_t* y, int incy) nogil:
+                      blas_t* y, int incy) noexcept nogil:
     {{for COND, CNAME, C in zip(CONDS, CNAMES, PREFIX)}}
     {{COND}} blas_t is {{CNAME}}:
         blas_pointers.{{C}}axpy(&n, &a, x, &incx, y, &incy)
     {{endfor}}
 
-cdef inline blas_t nrm2(int n, blas_t* x, int incx) nogil:
+cdef inline blas_t nrm2(int n, blas_t* x, int incx) noexcept nogil:
     {{for COND, CNAME, C in zip(CONDS, CNAMES, ['s', 'd', 'sc', 'dz'])}}
     {{COND}} blas_t is {{CNAME}}:
         return blas_pointers.{{C}}nrm2(&n, x, &incx)
     {{endfor}}
 
-cdef inline void lartg(blas_t* a, blas_t* b, blas_t* c, blas_t* s) nogil:
+cdef inline void lartg(blas_t* a, blas_t* b, blas_t* c, blas_t* s) noexcept nogil:
     cdef blas_t g
     if blas_t is float:
         lapack_pointers.slartg(a, b, c, s, &g)
@@ -144,7 +144,7 @@ cdef inline void lartg(blas_t* a, blas_t* b, blas_t* c, blas_t* s) nogil:
     b[0] = 0
 
 cdef inline void rot(int n, blas_t* x, int incx, blas_t* y, int incy,
-                     blas_t c, blas_t s) nogil:
+                     blas_t c, blas_t s) noexcept nogil:
     if blas_t is float:
         blas_pointers.srot(&n, x, &incx, y, &incy, &c, &s)
     elif blas_t is double:
@@ -155,21 +155,21 @@ cdef inline void rot(int n, blas_t* x, int incx, blas_t* y, int incy,
         lapack_pointers.zrot(&n, x, &incx, y, &incy, <double*>&c, &s)
 
 cdef inline void larfg(int n, blas_t* alpha, blas_t* x, int incx,
-                       blas_t* tau) nogil:
+                       blas_t* tau) noexcept nogil:
     {{for COND, CNAME, C in zip(CONDS, CNAMES, PREFIX)}}
     {{COND}} blas_t is {{CNAME}}:
         lapack_pointers.{{C}}larfg(&n, alpha, x, &incx, tau)
     {{endfor}}
 
 cdef inline void larf(char* side, int m, int n, blas_t* v, int incv, blas_t tau,
-    blas_t* c, int ldc, blas_t* work) nogil:
+    blas_t* c, int ldc, blas_t* work) noexcept nogil:
     {{for COND, CNAME, C in zip(CONDS, CNAMES, PREFIX)}}
     {{COND}} blas_t is {{CNAME}}:
         lapack_pointers.{{C}}larf(side, &m, &n, v, &incv, &tau, c, &ldc, work)
     {{endfor}}
 
 cdef inline void ger(int m, int n, blas_t alpha, blas_t* x, int incx, blas_t* y,
-        int incy, blas_t* a, int lda) nogil:
+        int incy, blas_t* a, int lda) noexcept nogil:
     if blas_t is float:
         blas_pointers.sger(&m, &n, &alpha, x, &incx, y, &incy, a, &lda)
     elif blas_t is double:
@@ -180,7 +180,7 @@ cdef inline void ger(int m, int n, blas_t alpha, blas_t* x, int incx, blas_t* y,
         blas_pointers.zgeru(&m, &n, &alpha, x, &incx, y, &incy, a, &lda)
 
 cdef inline void gemv(char* trans, int m, int n, blas_t alpha, blas_t* a,
-        int lda, blas_t* x, int incx, blas_t beta, blas_t* y, int incy) nogil:
+        int lda, blas_t* x, int incx, blas_t beta, blas_t* y, int incy) noexcept nogil:
     {{for COND, CNAME, C in zip(CONDS, CNAMES, PREFIX)}}
     {{COND}} blas_t is {{CNAME}}:
         blas_pointers.{{C}}gemv(trans, &m, &n, &alpha, a, &lda, x, &incx,
@@ -189,7 +189,7 @@ cdef inline void gemv(char* trans, int m, int n, blas_t alpha, blas_t* a,
 
 cdef inline void gemm(char* transa, char* transb, int m, int n, int k,
         blas_t alpha, blas_t* a, int lda, blas_t* b, int ldb, blas_t beta,
-        blas_t* c, int ldc) nogil:
+        blas_t* c, int ldc) noexcept nogil:
     {{for COND, CNAME, C in zip(CONDS, CNAMES, PREFIX)}}
     {{COND}} blas_t is {{CNAME}}:
         blas_pointers.{{C}}gemm(transa, transb, &m, &n, &k, &alpha, a, &lda,
@@ -197,7 +197,7 @@ cdef inline void gemm(char* transa, char* transb, int m, int n, int k,
     {{endfor}}
 
 cdef inline void trmm(char* side, char* uplo, char* transa, char* diag, int m,
-        int n, blas_t alpha, blas_t* a, int lda, blas_t* b, int ldb) nogil:
+        int n, blas_t alpha, blas_t* a, int lda, blas_t* b, int ldb) noexcept nogil:
     {{for COND, CNAME, C in zip(CONDS, CNAMES, PREFIX)}}
     {{COND}} blas_t is {{CNAME}}:
         blas_pointers.{{C}}trmm(side, uplo, transa, diag, &m, &n, &alpha, a, &lda,
@@ -205,7 +205,7 @@ cdef inline void trmm(char* side, char* uplo, char* transa, char* diag, int m,
     {{endfor}}
 
 cdef inline int geqrf(int m, int n, blas_t* a, int lda, blas_t* tau,
-                      blas_t* work, int lwork) nogil:
+                      blas_t* work, int lwork) noexcept nogil:
     cdef int info
     {{for COND, CNAME, C in zip(CONDS, CNAMES, PREFIX)}}
     {{COND}} blas_t is {{CNAME}}:
@@ -214,7 +214,7 @@ cdef inline int geqrf(int m, int n, blas_t* a, int lda, blas_t* tau,
     return info
 
 cdef inline int ormqr(char* side, char* trans, int m, int n, int k, blas_t* a,
-    int lda, blas_t* tau, blas_t* c, int ldc, blas_t* work, int lwork) nogil:
+    int lda, blas_t* tau, blas_t* c, int ldc, blas_t* work, int lwork) noexcept nogil:
     cdef int info = 0
     if blas_t is float:
         lapack_pointers.sormqr(side, trans, &m, &n, &k, a, &lda, tau, c, &ldc,
@@ -234,20 +234,20 @@ cdef inline int ormqr(char* side, char* trans, int m, int n, int k, blas_t* a,
 # Utility routines
 #------------------------------------------------------------------------------
 
-cdef void blas_t_conj(int n, blas_t* x, int* xs) nogil:
+cdef void blas_t_conj(int n, blas_t* x, int* xs) noexcept nogil:
     cdef int j
     if blas_t is float_complex or blas_t is double_complex:
         for j in range(n):
             index1(x, xs, j)[0] = index1(x, xs, j)[0].conjugate()
 
-cdef void blas_t_2d_conj(int m, int n, blas_t* x, int* xs) nogil:
+cdef void blas_t_2d_conj(int m, int n, blas_t* x, int* xs) noexcept nogil:
     cdef int i, j
     if blas_t is float_complex or blas_t is double_complex:
         for i in range(m):
             for j in range(n):
                 index2(x, xs, i, j)[0] = index2(x, xs, i, j)[0].conjugate()
 
-cdef blas_t blas_t_sqrt(blas_t x) nogil:
+cdef blas_t blas_t_sqrt(blas_t x) noexcept nogil:
     if blas_t is float:
         return sqrt(x)
     elif blas_t is double:
@@ -257,19 +257,19 @@ cdef blas_t blas_t_sqrt(blas_t x) nogil:
     else:
         return sqrt((<double*>&x)[0])
 
-cdef bint blas_t_less_than(blas_t x, blas_t y) nogil:
+cdef bint blas_t_less_than(blas_t x, blas_t y) noexcept nogil:
     if blas_t is float or blas_t is double:
         return x < y
     else:
         return x.real < y.real
 
-cdef bint blas_t_less_equal(blas_t x, blas_t y) nogil:
+cdef bint blas_t_less_equal(blas_t x, blas_t y) noexcept nogil:
     if blas_t is float or blas_t is double:
         return x <= y
     else:
         return x.real <= y.real
 
-cdef int to_lwork(blas_t a, blas_t b) nogil:
+cdef int to_lwork(blas_t a, blas_t b) noexcept nogil:
     cdef int ai, bi
     if blas_t is float or blas_t is double:
         ai = <int>a
@@ -286,7 +286,7 @@ cdef int to_lwork(blas_t a, blas_t b) nogil:
 # QR update routines start here.
 #------------------------------------------------------------------------------
 
-cdef bint reorthx(int m, int n, blas_t* q, int* qs, bint qisF, int j, blas_t* u, blas_t* s) nogil:
+cdef bint reorthx(int m, int n, blas_t* q, int* qs, bint qisF, int j, blas_t* u, blas_t* s) noexcept nogil:
     # U should be all zeros on entry., and m > 1
     cdef blas_t unorm, snorm, wnorm, wpnorm, sigma_max, sigma_min, rc
     cdef char* T = 'T'
@@ -347,7 +347,7 @@ cdef bint reorthx(int m, int n, blas_t* q, int* qs, bint qisF, int j, blas_t* u,
 
 cdef int thin_qr_row_delete(int m, int n, blas_t* q, int* qs, bint qisF,
                             blas_t* r, int* rs, int k, int p_eco,
-                            int p_full) nogil:
+                            int p_full) noexcept nogil:
     cdef int i, j, argmin_row_norm
     cdef size_t usize = (m + 3*n + 1) * sizeof(blas_t)
     cdef blas_t* s
@@ -407,7 +407,7 @@ cdef int thin_qr_row_delete(int m, int n, blas_t* q, int* qs, bint qisF,
     return 1
 
 cdef void qr_block_row_delete(int m, int n, blas_t* q, int* qs,
-                              blas_t* r, int* rs, int k, int p) nogil:
+                              blas_t* r, int* rs, int k, int p) noexcept nogil:
     cdef int i, j
     cdef blas_t c,s
     cdef blas_t* W
@@ -443,7 +443,7 @@ cdef void qr_block_row_delete(int m, int n, blas_t* q, int* qs,
                 c, s.conjugate())
 
 cdef void qr_col_delete(int m, int o, int n, blas_t* q, int* qs, blas_t* r,
-                        int* rs, int k) nogil:
+                        int* rs, int k) noexcept nogil:
     """
         Here we support both full and economic decomposition, q is (m,o), and r
         is (o, n).
@@ -457,7 +457,7 @@ cdef void qr_col_delete(int m, int o, int n, blas_t* q, int* qs, blas_t* r,
     hessenberg_qr(m, n-1, q, qs, r, rs, k)
 
 cdef int qr_block_col_delete(int m, int o, int n, blas_t* q, int* qs,
-                              blas_t* r, int* rs, int k, int p) nogil:
+                              blas_t* r, int* rs, int k, int p) noexcept nogil:
     """
         Here we support both full and economic decomposition, q is (m,o), and r
         is (o, n).
@@ -481,7 +481,7 @@ cdef int qr_block_col_delete(int m, int o, int n, blas_t* q, int* qs,
     return 0
 
 cdef void thin_qr_row_insert(int m, int n, blas_t* q, int* qs, blas_t* r,
-                             int* rs, blas_t* u, int* us, int k) nogil:
+                             int* rs, blas_t* u, int* us, int k) noexcept nogil:
     cdef int j
     cdef blas_t c, s
 
@@ -497,7 +497,7 @@ cdef void thin_qr_row_insert(int m, int n, blas_t* q, int* qs, blas_t* r,
         swap(n, row(q, qs, j), qs[1], row(q, qs, j-1), qs[1])
 
 cdef void qr_row_insert(int m, int n, blas_t* q, int* qs, blas_t* r, int* rs,
-                        int k) nogil:
+                        int k) noexcept nogil:
     cdef int j
     cdef blas_t c, s
     cdef int limit = min(m-1, n)
@@ -514,7 +514,7 @@ cdef void qr_row_insert(int m, int n, blas_t* q, int* qs, blas_t* r, int* rs,
 
 cdef int thin_qr_block_row_insert(int m, int n, blas_t* q, int* qs, blas_t* r,
                                   int* rs, blas_t* u, int* us, int k,
-                                  int p) nogil:
+                                  int p) noexcept nogil:
     # as below this should someday call lapack's xtpqrt.
     cdef int j
     cdef blas_t rjj, tau
@@ -568,7 +568,7 @@ cdef int thin_qr_block_row_insert(int m, int n, blas_t* q, int* qs, blas_t* r,
     libc.stdlib.free(work)
 
 cdef int qr_block_row_insert(int m, int n, blas_t* q, int* qs,
-                             blas_t* r, int* rs, int k, int p) nogil:
+                             blas_t* r, int* rs, int k, int p) noexcept nogil:
     # this should someday call lapack's xtpqrt (requires lapack >= 3.4
     # released nov 11). RHEL6's atlas doesn't seem to have it.
     # On input this looks something like this:
@@ -620,7 +620,7 @@ cdef int qr_block_row_insert(int m, int n, blas_t* q, int* qs,
 
 cdef int thin_qr_col_insert(int m, int n, blas_t* q, int* qs, blas_t* r,
                              int* rs, blas_t* u, int* us, int k, int p_eco,
-                             int p_full, blas_t* rcond) nogil:
+                             int p_full, blas_t* rcond) noexcept nogil:
     # here q and r will always be fortran ordered since we have to allocate them
     cdef int i, j, info
     cdef blas_t c, sn
@@ -683,7 +683,7 @@ cdef int thin_qr_col_insert(int m, int n, blas_t* q, int* qs, blas_t* r,
     return 0
 
 cdef void qr_col_insert(int m, int n, blas_t* q, int* qs, blas_t* r, int* rs,
-                        int k) nogil:
+                        int k) noexcept nogil:
     cdef int j
     cdef blas_t c, s, temp, tau
     cdef blas_t* work
@@ -700,7 +700,7 @@ cdef void qr_col_insert(int m, int n, blas_t* q, int* qs, blas_t* r, int* rs,
         rot(m, col(q, qs, j), qs[0], col(q, qs, j+1), qs[0], c, s.conjugate())
 
 cdef int qr_block_col_insert(int m, int n, blas_t* q, int* qs,
-                              blas_t* r, int* rs, int k, int p) nogil:
+                              blas_t* r, int* rs, int k, int p) noexcept nogil:
     cdef int i, j
     cdef blas_t c, s
     cdef blas_t* tau = NULL
@@ -802,7 +802,7 @@ cdef int qr_block_col_insert(int m, int n, blas_t* q, int* qs,
 
 cdef void thin_qr_rank_1_update(int m, int n, blas_t* q, int* qs, bint qisF,
     blas_t* r, int* rs, blas_t* u, int* us, blas_t* v, int* vs, blas_t* s,
-    int* ss) nogil:
+    int* ss) noexcept nogil:
     """Assume that q is (M,N) and either C or F contiguous, r is (N,N), u is M,
        and V is N.  s is a 2*n work array.
     """
@@ -844,7 +844,7 @@ cdef void thin_qr_rank_1_update(int m, int n, blas_t* q, int* qs, bint qisF,
 
 cdef void thin_qr_rank_p_update(int m, int n, int p, blas_t* q, int* qs,
     bint qisF, blas_t* r, int* rs, blas_t* u, int* us, blas_t* v, int* vs,
-    blas_t* s, int* ss) nogil:
+    blas_t* s, int* ss) noexcept nogil:
     """Assume that q is (M,N) and either C or F contiguous, r is (N,N), u is
        (M,p) and V is (N,p).  s is a 2*n work array.
     """
@@ -855,7 +855,7 @@ cdef void thin_qr_rank_p_update(int m, int n, int p, blas_t* q, int* qs,
                               col(v, vs, j), vs, s, ss)
 
 cdef void qr_rank_1_update(int m, int n, blas_t* q, int* qs, blas_t* r, int* rs,
-                           blas_t* u, int* us, blas_t* v, int* vs) nogil:
+                           blas_t* u, int* us, blas_t* v, int* vs) noexcept nogil:
     """ here we will assume that the u = Q.T.dot(u) and not the bare u.
         if A is MxN then q is MxM, r is MxN, u is M and v is N.
         e.g. currently assuming full matrices.
@@ -889,7 +889,7 @@ cdef void qr_rank_1_update(int m, int n, blas_t* q, int* qs, blas_t* r, int* rs,
     # no return, return q, r from python driver.
 
 cdef int qr_rank_p_update(int m, int n, int p, blas_t* q, int* qs, blas_t* r,
-                        int* rs, blas_t* u, int* us, blas_t* v, int* vs) nogil:
+                        int* rs, blas_t* u, int* us, blas_t* v, int* vs) noexcept nogil:
     cdef int i, j
     cdef blas_t c, s
     cdef blas_t* tau = NULL
@@ -981,7 +981,7 @@ cdef int qr_rank_p_update(int m, int n, int p, blas_t* q, int* qs, blas_t* r,
     return 0
 
 cdef void hessenberg_qr(int m, int n, blas_t* q, int* qs, blas_t* r, int* rs,
-                        int k) nogil:
+                        int k) noexcept nogil:
     """Reduce an upper hessenberg matrix r, to upper triangular, starting in
        row j.  Apply these transformation to q as well. Both full and economic
        decompositions are supported here.
@@ -1002,7 +1002,7 @@ cdef void hessenberg_qr(int m, int n, blas_t* q, int* qs, blas_t* r, int* rs,
         rot(m, col(q, qs, j), qs[0], col(q, qs, j+1), qs[0], c, s.conjugate())
 
 cdef void p_subdiag_qr(int m, int o, int n, blas_t* q, int* qs, blas_t* r, int* rs,
-                       int k, int p, blas_t* work) nogil:
+                       int k, int p, blas_t* work) noexcept nogil:
     """ Reduce a matrix r to upper triangular form by eliminating the lower p
         subdiagionals using reflectors. Both full and economic decompositions
         are supported here.  In either case, q is (m,o) and r is (o,n)
@@ -1041,7 +1041,7 @@ cdef void p_subdiag_qr(int m, int o, int n, blas_t* q, int* qs, blas_t* r, int*
         index2(r, rs, j, j)[0] = rjj
 
 cdef int reorth(int m, int n, blas_t* q, int* qs, bint qisF, blas_t* u,
-                int* us, blas_t* s, blas_t* RCOND) nogil:
+                int* us, blas_t* s, blas_t* RCOND) noexcept nogil:
     """Given a (m,n) matrix q with orthonormal columns and a (m,) vector u,
        find vectors s, w and scalar p such that u = Qs + pw where w is of unit
        length and orthogonal to the columns of q.
@@ -1181,7 +1181,7 @@ def _form_qTu(object a, object b):
     return qTu
 
 cdef form_qTu(cnp.ndarray q, cnp.ndarray u, void* qTuvoid, int* qTus,
-              int k):
+              int k) noexcept:
     """ assuming here that q and u have compatible shapes, and are the same
         type + Q is contiguous.  This function is preferable over simply
         calling np.dot for two reasons: 1) this output is always in F order, 2)
@@ -1312,7 +1312,7 @@ cdef form_qTu(cnp.ndarray q, cnp.ndarray u, void* qTuvoid, int* qTus,
     else:
         raise ValueError('q must be either F or C contiguous')
 
-cdef validate_array(cnp.ndarray a, bint chkfinite):
+cdef validate_array(cnp.ndarray a, bint chkfinite) noexcept:
     # here we check that a has positive strides and that its size is small
     # enough to fit in into an int, as BLAS/LAPACK require
     cdef bint copy = False
@@ -1335,7 +1335,7 @@ cdef validate_array(cnp.ndarray a, bint chkfinite):
     return a
 
 cdef tuple validate_qr(object q0, object r0, bint overwrite_q, int q_order,
-                       bint overwrite_r, int r_order, bint chkfinite):
+                       bint overwrite_r, int r_order, bint chkfinite) noexcept:
     cdef cnp.ndarray Q
     cdef cnp.ndarray R
     cdef int typecode
@@ -1388,7 +1388,7 @@ cdef tuple validate_qr(object q0, object r0, bint overwrite_q, int q_order,
 
     return Q, R, typecode, Q.shape[0], R.shape[1], economic
 
-cdef void* extract(cnp.ndarray arr, int* arrs):
+cdef void* extract(cnp.ndarray arr, int* arrs) noexcept:
     with cython.cdivision(True):    # Assumes itemsize != 0.
         if arr.ndim == 2:
             arrs[0] = arr.strides[0] / cnp.PyArray_ITEMSIZE(arr)
@@ -1757,7 +1757,7 @@ def qr_insert(Q, R, u, k, which='row', rcond=None, overwrite_qru=False, check_fi
     else:
         raise ValueError("'which' must be either 'row' or 'col'")
 
-cdef qr_insert_row(Q, R, u, int k, bint overwrite_qru, bint check_finite):
+cdef qr_insert_row(Q, R, u, int k, bint overwrite_qru, bint check_finite) noexcept:
     cdef cnp.ndarray q1, r1, u1, qnew, rnew
     cdef int j
     cdef int u_flags = cnp.NPY_BEHAVED_NS | cnp.NPY_ELEMENTSTRIDES
@@ -1877,7 +1877,7 @@ cdef qr_insert_row(Q, R, u, int k, bint overwrite_qru, bint check_finite):
                 raise MemoryError('Unable to allocate memory for array')
         return qnew, rnew
 
-cdef qr_insert_col(Q, R, u, int k, rcond, bint overwrite_qru, bint check_finite):
+cdef qr_insert_col(Q, R, u, int k, rcond, bint overwrite_qru, bint check_finite) noexcept:
     cdef cnp.ndarray q1, r1, u1, qnew, rnew
     cdef int j
     cdef int q_flags = ARRAY_ANYORDER
diff --git a/scipy/linalg/_generate_pyx.py b/scipy/linalg/_generate_pyx.py
index 4042bc09..f521d473 100644
--- a/scipy/linalg/_generate_pyx.py
+++ b/scipy/linalg/_generate_pyx.py
@@ -46,7 +46,7 @@ def arg_names_and_types(args):
 pyx_func_template = """
 cdef extern from "{header_name}":
     void _fortran_{name} "F_FUNC({name}wrp, {upname}WRP)"({ret_type} *out, {fort_args}) nogil
-cdef {ret_type} {name}({args}) nogil:
+cdef {ret_type} {name}({args}) noexcept nogil:
     cdef {ret_type} out
     _fortran_{name}(&out, {argnames})
     return out
@@ -94,7 +94,7 @@ def pyx_decl_func(name, ret_type, args, header_name):
 
 pyx_sub_template = """cdef extern from "{header_name}":
     void _fortran_{name} "F_FUNC({name},{upname})"({fort_args}) nogil
-cdef void {name}({args}) nogil:
+cdef void {name}({args}) noexcept nogil:
     _fortran_{name}({argnames})
 """
 
@@ -222,30 +222,30 @@ blas_py_wrappers = """
 
 # Python-accessible wrappers for testing:
 
-cdef inline bint _is_contiguous(double[:,:] a, int axis) nogil:
+cdef inline bint _is_contiguous(double[:,:] a, int axis) noexcept nogil:
     return (a.strides[axis] == sizeof(a[0,0]) or a.shape[axis] == 1)
 
-cpdef float complex _test_cdotc(float complex[:] cx, float complex[:] cy) nogil:
+cpdef float complex _test_cdotc(float complex[:] cx, float complex[:] cy) noexcept nogil:
     cdef:
         int n = cx.shape[0]
         int incx = cx.strides[0] // sizeof(cx[0])
         int incy = cy.strides[0] // sizeof(cy[0])
     return cdotc(&n, &cx[0], &incx, &cy[0], &incy)
 
-cpdef float complex _test_cdotu(float complex[:] cx, float complex[:] cy) nogil:
+cpdef float complex _test_cdotu(float complex[:] cx, float complex[:] cy) noexcept nogil:
     cdef:
         int n = cx.shape[0]
         int incx = cx.strides[0] // sizeof(cx[0])
         int incy = cy.strides[0] // sizeof(cy[0])
     return cdotu(&n, &cx[0], &incx, &cy[0], &incy)
 
-cpdef double _test_dasum(double[:] dx) nogil:
+cpdef double _test_dasum(double[:] dx) noexcept nogil:
     cdef:
         int n = dx.shape[0]
         int incx = dx.strides[0] // sizeof(dx[0])
     return dasum(&n, &dx[0], &incx)
 
-cpdef double _test_ddot(double[:] dx, double[:] dy) nogil:
+cpdef double _test_ddot(double[:] dx, double[:] dy) noexcept nogil:
     cdef:
         int n = dx.shape[0]
         int incx = dx.strides[0] // sizeof(dx[0])
@@ -331,87 +331,87 @@ cpdef int _test_dgemm(double alpha, double[:,:] a, double[:,:] b, double beta,
             raise ValueError("Input 'c' is neither C nor Fortran contiguous.")
     return 0
 
-cpdef double _test_dnrm2(double[:] x) nogil:
+cpdef double _test_dnrm2(double[:] x) noexcept nogil:
     cdef:
         int n = x.shape[0]
         int incx = x.strides[0] // sizeof(x[0])
     return dnrm2(&n, &x[0], &incx)
 
-cpdef double _test_dzasum(double complex[:] zx) nogil:
+cpdef double _test_dzasum(double complex[:] zx) noexcept nogil:
     cdef:
         int n = zx.shape[0]
         int incx = zx.strides[0] // sizeof(zx[0])
     return dzasum(&n, &zx[0], &incx)
 
-cpdef double _test_dznrm2(double complex[:] x) nogil:
+cpdef double _test_dznrm2(double complex[:] x) noexcept nogil:
     cdef:
         int n = x.shape[0]
         int incx = x.strides[0] // sizeof(x[0])
     return dznrm2(&n, &x[0], &incx)
 
-cpdef int _test_icamax(float complex[:] cx) nogil:
+cpdef int _test_icamax(float complex[:] cx) noexcept nogil:
     cdef:
         int n = cx.shape[0]
         int incx = cx.strides[0] // sizeof(cx[0])
     return icamax(&n, &cx[0], &incx)
 
-cpdef int _test_idamax(double[:] dx) nogil:
+cpdef int _test_idamax(double[:] dx) noexcept nogil:
     cdef:
         int n = dx.shape[0]
         int incx = dx.strides[0] // sizeof(dx[0])
     return idamax(&n, &dx[0], &incx)
 
-cpdef int _test_isamax(float[:] sx) nogil:
+cpdef int _test_isamax(float[:] sx) noexcept nogil:
     cdef:
         int n = sx.shape[0]
         int incx = sx.strides[0] // sizeof(sx[0])
     return isamax(&n, &sx[0], &incx)
 
-cpdef int _test_izamax(double complex[:] zx) nogil:
+cpdef int _test_izamax(double complex[:] zx) noexcept nogil:
     cdef:
         int n = zx.shape[0]
         int incx = zx.strides[0] // sizeof(zx[0])
     return izamax(&n, &zx[0], &incx)
 
-cpdef float _test_sasum(float[:] sx) nogil:
+cpdef float _test_sasum(float[:] sx) noexcept nogil:
     cdef:
         int n = sx.shape[0]
         int incx = sx.shape[0] // sizeof(sx[0])
     return sasum(&n, &sx[0], &incx)
 
-cpdef float _test_scasum(float complex[:] cx) nogil:
+cpdef float _test_scasum(float complex[:] cx) noexcept nogil:
     cdef:
         int n = cx.shape[0]
         int incx = cx.strides[0] // sizeof(cx[0])
     return scasum(&n, &cx[0], &incx)
 
-cpdef float _test_scnrm2(float complex[:] x) nogil:
+cpdef float _test_scnrm2(float complex[:] x) noexcept nogil:
     cdef:
         int n = x.shape[0]
         int incx = x.strides[0] // sizeof(x[0])
     return scnrm2(&n, &x[0], &incx)
 
-cpdef float _test_sdot(float[:] sx, float[:] sy) nogil:
+cpdef float _test_sdot(float[:] sx, float[:] sy) noexcept nogil:
     cdef:
         int n = sx.shape[0]
         int incx = sx.strides[0] // sizeof(sx[0])
         int incy = sy.strides[0] // sizeof(sy[0])
     return sdot(&n, &sx[0], &incx, &sy[0], &incy)
 
-cpdef float _test_snrm2(float[:] x) nogil:
+cpdef float _test_snrm2(float[:] x) noexcept nogil:
     cdef:
         int n = x.shape[0]
         int incx = x.shape[0] // sizeof(x[0])
     return snrm2(&n, &x[0], &incx)
 
-cpdef double complex _test_zdotc(double complex[:] zx, double complex[:] zy) nogil:
+cpdef double complex _test_zdotc(double complex[:] zx, double complex[:] zy) noexcept nogil:
     cdef:
         int n = zx.shape[0]
         int incx = zx.strides[0] // sizeof(zx[0])
         int incy = zy.strides[0] // sizeof(zy[0])
     return zdotc(&n, &zx[0], &incx, &zy[0], &incy)
 
-cpdef double complex _test_zdotu(double complex[:] zx, double complex[:] zy) nogil:
+cpdef double complex _test_zdotu(double complex[:] zx, double complex[:] zy) noexcept nogil:
     cdef:
         int n = zx.shape[0]
         int incx = zx.strides[0] // sizeof(zx[0])
@@ -457,10 +457,10 @@ def generate_lapack_pyx(func_sigs, sub_sigs, all_sigs, header_name):
     return preamble + funcs + subs + lapack_py_wrappers
 
 
-pxd_template = """ctypedef {ret_type} {name}_t({args}) nogil
+pxd_template = """ctypedef {ret_type} {name}_t({args}) noexcept nogil
 cdef {name}_t *{name}_f
 """
-pxd_template = """cdef {ret_type} {name}({args}) nogil
+pxd_template = """cdef {ret_type} {name}({args}) noexcept nogil
 """
 
 
diff --git a/scipy/linalg/_matfuncs_expm.pyx.in b/scipy/linalg/_matfuncs_expm.pyx.in
index 41b42c87..61383681 100644
--- a/scipy/linalg/_matfuncs_expm.pyx.in
+++ b/scipy/linalg/_matfuncs_expm.pyx.in
@@ -36,7 +36,7 @@ prefixes = ['s', 'd', 'c', 'z']
 @cython.wraparound(False)
 @cython.boundscheck(False)
 @cython.initializedcheck(False)
-cdef double norm1(lapack_t[:, ::1] A):
+cdef double norm1(lapack_t[:, ::1] A) noexcept:
     """
     Fast 1-norm computation for C-contiguous square arrays.
     Regardless of the dtype we work in double precision to prevent overflows
@@ -79,7 +79,7 @@ cdef double norm1(lapack_t[:, ::1] A):
 @cython.wraparound(False)
 @cython.boundscheck(False)
 @cython.initializedcheck(False)
-cdef double kth_power_norm_d(double* A, double* v1, double* v2, Py_ssize_t n, int spins):
+cdef double kth_power_norm_d(double* A, double* v1, double* v2, Py_ssize_t n, int spins) noexcept:
     cdef int k, int_one = 1, intn = <int>n
     cdef double one =1., zero = 0.
     for k in range(spins):
@@ -97,7 +97,7 @@ cdef double kth_power_norm_d(double* A, double* v1, double* v2, Py_ssize_t n, in
 @cython.wraparound(False)
 @cython.boundscheck(False)
 @cython.initializedcheck(False)
-cdef pick_pade_structure_{{ pfx }}({{ tname }}[:, :, ::1] Am):
+cdef pick_pade_structure_{{ pfx }}({{ tname }}[:, :, ::1] Am) noexcept:
     cdef Py_ssize_t n = Am.shape[1], i, j, k
     cdef int lm = 0, s = 0, intn = <int>n, n2= intn*intn, int_one = 1
     cdef {{ tname }}[:, :, ::1] Amv = Am
@@ -221,7 +221,7 @@ cdef pick_pade_structure_{{ pfx }}({{ tname }}[:, :, ::1] Am):
 @cython.wraparound(False)
 @cython.boundscheck(False)
 @cython.initializedcheck(False)
-cdef void pade_357_UV_calc_{{ pfx }}({{ tname }}[:, :, ::]Am, int n, int m) nogil:
+cdef void pade_357_UV_calc_{{ pfx }}({{ tname }}[:, :, ::]Am, int n, int m) noexcept nogil:
     cdef {{ tname }} b[7]
     cdef int *ipiv = <int*>malloc(n*sizeof(int))
     cdef int i, info, n2 = n*n, int_one = 1
@@ -317,7 +317,7 @@ cdef void pade_357_UV_calc_{{ pfx }}({{ tname }}[:, :, ::]Am, int n, int m) nogi
 @cython.wraparound(False)
 @cython.boundscheck(False)
 @cython.initializedcheck(False)
-cdef void pade_9_UV_calc_{{ pfx }}({{ tname }}[:, :, ::]Am, int n) nogil:
+cdef void pade_9_UV_calc_{{ pfx }}({{ tname }}[:, :, ::]Am, int n) noexcept nogil:
     cdef {{ tname }} b[9]
     cdef {{ tname }} *work = <{{ tname }}*>malloc(n*n*sizeof({{ tname }}))
     cdef int *ipiv = <int*>malloc(n*sizeof(int))
@@ -382,7 +382,7 @@ cdef void pade_9_UV_calc_{{ pfx }}({{ tname }}[:, :, ::]Am, int n) nogil:
 @cython.wraparound(False)
 @cython.boundscheck(False)
 @cython.initializedcheck(False)
-cdef void pade_13_UV_calc_{{ pfx }}({{ tname }}[:, :, ::1]Am, int n) nogil:
+cdef void pade_13_UV_calc_{{ pfx }}({{ tname }}[:, :, ::1]Am, int n) noexcept nogil:
     cdef {{ tname }} *work2 = <{{ tname }}*>malloc(n*n*sizeof({{ tname }}))
     cdef {{ tname }} *work3 = <{{ tname }}*>malloc(n*n*sizeof({{ tname }}))
     cdef {{ tname }} *work4 = <{{ tname }}*>malloc(n*n*sizeof({{ tname }}))
diff --git a/scipy/ndimage/src/_cytest.pxd b/scipy/ndimage/src/_cytest.pxd
index c022e22b..d0788783 100644
--- a/scipy/ndimage/src/_cytest.pxd
+++ b/scipy/ndimage/src/_cytest.pxd
@@ -1,8 +1,8 @@
 from numpy cimport npy_intp as intp
 
 cdef int _filter1d(double *input_line, intp input_length, double *output_line,
-	           intp output_length, void *callback_data)
+	           intp output_length, void *callback_data) noexcept
 cdef int _filter2d(double *buffer, intp filter_size, double *res,
-	           void *callback_data)
+	           void *callback_data) noexcept
 cdef int _transform(intp *output_coordinates, double *input_coordinates,
-	            int output_rank, int input_rank, void *callback_data)
+	            int output_rank, int input_rank, void *callback_data) noexcept
diff --git a/scipy/ndimage/src/_cytest.pyx b/scipy/ndimage/src/_cytest.pyx
index 3948d97a..d63c9806 100644
--- a/scipy/ndimage/src/_cytest.pyx
+++ b/scipy/ndimage/src/_cytest.pyx
@@ -8,18 +8,18 @@ from numpy cimport npy_intp as intp
 
 np.import_array()
 
-cdef void _destructor(obj):
+cdef void _destructor(obj) noexcept:
     cdef void *callback_data = PyCapsule_GetContext(obj)
     PyMem_Free(callback_data)
 
 
-cdef void _destructor_data(obj):
+cdef void _destructor_data(obj) noexcept:
     cdef void *callback_data = PyCapsule_GetPointer(obj, NULL)
     PyMem_Free(callback_data)
 
 
 cdef int _filter1d(double *input_line, intp input_length, double *output_line,
-	           intp output_length, void *callback_data):
+	           intp output_length, void *callback_data) noexcept:
     cdef intp i, j
     cdef intp filter_size = (<intp *>callback_data)[0]
 
@@ -65,7 +65,7 @@ def filter1d_capsule(intp filter_size):
 
 
 cdef int _filter2d(double *buffer, intp filter_size, double *res,
-	           void *callback_data):
+	           void *callback_data) noexcept:
     cdef intp i
     cdef double *weights = <double *>callback_data
 
@@ -111,7 +111,7 @@ def filter2d_capsule(seq):
 
 
 cdef int _transform(intp *output_coordinates, double *input_coordinates,
-	            int output_rank, int input_rank, void *callback_data):
+	            int output_rank, int input_rank, void *callback_data) noexcept:
     cdef intp i
     cdef double shift = (<double *>callback_data)[0]
 
diff --git a/scipy/ndimage/src/_ni_label.pyx b/scipy/ndimage/src/_ni_label.pyx
index d371f22b..284a52f4 100644
--- a/scipy/ndimage/src/_ni_label.pyx
+++ b/scipy/ndimage/src/_ni_label.pyx
@@ -52,7 +52,7 @@ ctypedef fused data_t:
 # the fused data is nonzero, BACKGROUND elsewhere
 ######################################################################
 cdef void fused_nonzero_line(data_t *p, np.intp_t stride,
-                             np.uintp_t *line, np.intp_t L) nogil:
+                             np.uintp_t *line, np.intp_t L) noexcept nogil:
     cdef np.intp_t i
     for i in range(L):
         line[i] = FOREGROUND if \
@@ -64,7 +64,7 @@ cdef void fused_nonzero_line(data_t *p, np.intp_t stride,
 # Load a line from a fused data array to a np.uintp_t array
 ######################################################################
 cdef void fused_read_line(data_t *p, np.intp_t stride,
-                          np.uintp_t *line, np.intp_t L) nogil:
+                          np.uintp_t *line, np.intp_t L) noexcept nogil:
     cdef np.intp_t i
     for i in range(L):
         line[i] = <np.uintp_t> (<data_t *> ((<char *> p) + i * stride))[0]
@@ -75,7 +75,7 @@ cdef void fused_read_line(data_t *p, np.intp_t stride,
 # returning True if overflowed
 ######################################################################
 cdef bint fused_write_line(data_t *p, np.intp_t stride,
-                           np.uintp_t *line, np.intp_t L) nogil:
+                           np.uintp_t *line, np.intp_t L) noexcept nogil:
     cdef np.intp_t i
     for i in range(L):
         # Check before overwrite, as this prevents us accidentally writing a 0
@@ -104,11 +104,11 @@ def get_write_line(np.ndarray[data_t] a):
 # Typedefs for referring to specialized instances of fused functions
 ######################################################################
 ctypedef void (*nonzero_line_func_t)(void *p, np.intp_t stride,
-                                     np.uintp_t *line, np.intp_t L) nogil
+                                     np.uintp_t *line, np.intp_t L) noexcept nogil
 ctypedef void (*read_line_func_t)(void *p, np.intp_t stride,
-                                  np.uintp_t *line, np.intp_t L) nogil
+                                  np.uintp_t *line, np.intp_t L) noexcept nogil
 ctypedef bint (*write_line_func_t)(void *p, np.intp_t stride,
-                                   np.uintp_t *line, np.intp_t L) nogil
+                                   np.uintp_t *line, np.intp_t L) noexcept nogil
 
 
 ######################################################################
@@ -116,7 +116,7 @@ ctypedef bint (*write_line_func_t)(void *p, np.intp_t stride,
 ######################################################################
 cdef inline np.uintp_t mark_for_merge(np.uintp_t a,
                                       np.uintp_t b,
-                                      np.uintp_t *mergetable) nogil:
+                                      np.uintp_t *mergetable) noexcept nogil:
 
     cdef:
         np.uintp_t orig_a, orig_b, minlabel
@@ -149,7 +149,7 @@ cdef inline np.uintp_t mark_for_merge(np.uintp_t a,
 ######################################################################
 cdef inline np.uintp_t take_label_or_merge(np.uintp_t cur_label,
                                            np.uintp_t neighbor_label,
-                                           np.uintp_t *mergetable) nogil:
+                                           np.uintp_t *mergetable) noexcept nogil:
     if neighbor_label == BACKGROUND:
         return cur_label
     if cur_label == FOREGROUND:
@@ -172,7 +172,7 @@ cdef np.uintp_t label_line_with_neighbor(np.uintp_t *line,
                                          bint label_unlabeled,
                                          bint use_previous,
                                          np.uintp_t next_region,
-                                         np.uintp_t *mergetable) nogil:
+                                         np.uintp_t *mergetable) noexcept nogil:
     cdef:
         np.intp_t i
 
@@ -199,7 +199,7 @@ cdef np.uintp_t label_line_with_neighbor(np.uintp_t *line,
 ######################################################################
 cpdef _label(np.ndarray input,
              np.ndarray structure,
-             np.ndarray output):
+             np.ndarray output) noexcept:
     # check dimensions
     # To understand the need for the casts to object, see
     # http://trac.cython.org/cython_trac/ticket/302
diff --git a/scipy/optimize/_bglu_dense.pyx b/scipy/optimize/_bglu_dense.pyx
index 376df50a..d6e8a35b 100644
--- a/scipy/optimize/_bglu_dense.pyx
+++ b/scipy/optimize/_bglu_dense.pyx
@@ -17,7 +17,7 @@ __all__ = ['LU', 'BGLU']
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef void swap_rows(self, double[:, ::1] H, int i):
+cdef void swap_rows(self, double[:, ::1] H, int i) noexcept:
     """
     Swaps row i of H with next row; represents matrix product by PI_i
     matrix described after matrix 5.10
@@ -32,7 +32,7 @@ cdef void swap_rows(self, double[:, ::1] H, int i):
 @cython.boundscheck(False)
 @cython.wraparound(False)
 @cython.cdivision(True) # not really important
-cdef double row_subtract(self, double[:, ::1] H, int i):
+cdef double row_subtract(self, double[:, ::1] H, int i) noexcept:
     """
     Zeros first nonzero element of row i+1 of H by subtracting appropriate
     multiple of row i; represents matrix product by matrix 5.10. Returns
@@ -52,7 +52,7 @@ cdef double row_subtract(self, double[:, ::1] H, int i):
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef void hess_lu(self, double[:, ::1] H, int i, double[:,::1] ops):
+cdef void hess_lu(self, double[:, ::1] H, int i, double[:,::1] ops) noexcept:
     """
     Converts Hessenberg matrix H with first nonzero off-diagonal in
     column i to upper triangular, recording elementary row operations.
@@ -78,7 +78,7 @@ cdef void hess_lu(self, double[:, ::1] H, int i, double[:,::1] ops):
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef void perform_ops(self, double[::1] y, double[:,::1] ops, bint rev = False):
+cdef void perform_ops(self, double[::1] y, double[:,::1] ops, bint rev = False) noexcept:
     """
     Replays operations needed to convert Hessenberg matrix into upper
     triangular form on a vector y. Equivalent to matrix multlication by
diff --git a/scipy/optimize/_highs/cython/src/_highs_wrapper.pyx b/scipy/optimize/_highs/cython/src/_highs_wrapper.pyx
index 476f3097..519730f3 100644
--- a/scipy/optimize/_highs/cython/src/_highs_wrapper.pyx
+++ b/scipy/optimize/_highs/cython/src/_highs_wrapper.pyx
@@ -68,7 +68,7 @@ for _r in _ref_opts.records:
     _ref_opt_lookup[_r.name] = _r
 
 
-cdef str _opt_warning(string name, val, valid_set=None):
+cdef str _opt_warning(string name, val, valid_set=None) noexcept:
     cdef OptionRecord * r = _ref_opt_lookup[name]
 
     # BOOL
@@ -113,7 +113,7 @@ cdef str _opt_warning(string name, val, valid_set=None):
            'See documentation for valid options. '
            'Using default.' % (name.decode(), str(val)))
 
-cdef apply_options(dict options, Highs & highs):
+cdef apply_options(dict options, Highs & highs) noexcept:
     '''Take options from dictionary and apply to HiGHS object.'''
 
     # Initialize for error checking
diff --git a/scipy/optimize/cython_optimize/_zeros.pxd b/scipy/optimize/cython_optimize/_zeros.pxd
index 1ae32c9f..c6241d02 100644
--- a/scipy/optimize/cython_optimize/_zeros.pxd
+++ b/scipy/optimize/cython_optimize/_zeros.pxd
@@ -18,16 +18,16 @@ ctypedef struct zeros_full_output:
 
 cdef double bisect(callback_type f, double xa, double xb, void* args,
                    double xtol, double rtol, int iter,
-                   zeros_full_output *full_output) nogil
+                   zeros_full_output *full_output) noexcept nogil
 
 cdef double ridder(callback_type f, double xa, double xb, void* args,
                    double xtol, double rtol, int iter,
-                   zeros_full_output *full_output) nogil
+                   zeros_full_output *full_output) noexcept nogil
 
 cdef double brenth(callback_type f, double xa, double xb, void* args,
                    double xtol, double rtol, int iter,
-                   zeros_full_output *full_output) nogil
+                   zeros_full_output *full_output) noexcept nogil
 
 cdef double brentq(callback_type f, double xa, double xb, void* args,
                    double xtol, double rtol, int iter,
-                   zeros_full_output *full_output) nogil
+                   zeros_full_output *full_output) noexcept nogil
diff --git a/scipy/optimize/cython_optimize/_zeros.pyx.in b/scipy/optimize/cython_optimize/_zeros.pyx.in
index 509d9a89..454769ed 100644
--- a/scipy/optimize/cython_optimize/_zeros.pyx.in
+++ b/scipy/optimize/cython_optimize/_zeros.pyx.in
@@ -6,7 +6,7 @@ from . cimport c_zeros
 
 
 # callback function wrapper that extracts function, args from params struct
-cdef double scipy_zeros_functions_func(double x, void *params):
+cdef double scipy_zeros_functions_func(double x, void *params) noexcept:
     cdef zeros_parameters *myparams = <zeros_parameters *> params
     cdef void* args = myparams.args
     cdef callback_type f = myparams.function
@@ -19,7 +19,7 @@ cdef double scipy_zeros_functions_func(double x, void *params):
 # cythonized way to call scalar {{ROOT_FINDER}}
 cdef double {{ROOT_FINDER}}(
         callback_type f, double xa, double xb, void *args, double xtol,
-        double rtol, int iter, zeros_full_output *full_output) nogil:
+        double rtol, int iter, zeros_full_output *full_output) noexcept nogil:
     cdef c_zeros.scipy_zeros_info solver_stats
     cdef zeros_parameters myparams
     cdef double root
@@ -49,7 +49,7 @@ ctypedef struct extra_params:
 
 
 # callback function
-cdef double f_example(double x, void *args):
+cdef double f_example(double x, void *args) noexcept:
     cdef extra_params *myargs = <extra_params *> args
     cdef double[4] a
     # unpack structure
@@ -62,7 +62,7 @@ cdef double f_example(double x, void *args):
 {{for ROOT_FINDER in root_finders}}
 # {{ROOT_FINDER}} example
 cdef double {{ROOT_FINDER}}_example(
-        tuple args, float xa, float xb, float xtol, float rtol, int mitr):
+        tuple args, float xa, float xb, float xtol, float rtol, int mitr) noexcept:
     cdef extra_params myargs
     myargs.a = args
     return {{ROOT_FINDER}}(
@@ -119,7 +119,7 @@ def loop_example(method, a0, args, xa, xb, xtol, rtol, mitr):
 
 # brentq example with full ouptut
 cdef zeros_full_output brentq_full_output_example(
-        tuple args, float xa, float xb, float xtol, float rtol, int mitr):
+        tuple args, float xa, float xb, float xtol, float rtol, int mitr) noexcept:
     cdef zeros_full_output full_output
     cdef extra_params myargs
     myargs.a = args
diff --git a/scipy/optimize/cython_optimize/c_zeros.pxd b/scipy/optimize/cython_optimize/c_zeros.pxd
index 723e479e..0d83c80e 100644
--- a/scipy/optimize/cython_optimize/c_zeros.pxd
+++ b/scipy/optimize/cython_optimize/c_zeros.pxd
@@ -1,5 +1,5 @@
 cdef extern from "../Zeros/zeros.h":
-    ctypedef double (*callback_type)(double, void*)
+    ctypedef double (*callback_type)(double, void*) noexcept
     ctypedef struct scipy_zeros_info:
         int funcalls
         int iterations
diff --git a/scipy/signal/_sosfilt.pyx b/scipy/signal/_sosfilt.pyx
index 140e66cb..e3ca7fd5 100644
--- a/scipy/signal/_sosfilt.pyx
+++ b/scipy/signal/_sosfilt.pyx
@@ -28,7 +28,7 @@ ctypedef fused DTYPE_t:
 @cython.wraparound(False)
 cdef void _sosfilt_float(DTYPE_floating_t [:, ::1] sos,
                          DTYPE_floating_t [:, ::1] x,
-                         DTYPE_floating_t [:, :, ::1] zi) nogil:
+                         DTYPE_floating_t [:, :, ::1] zi) noexcept nogil:
     # Modifies x and zi in place
     cdef Py_ssize_t n_signals = x.shape[0]
     cdef Py_ssize_t n_samples = x.shape[1]
diff --git a/scipy/signal/_upfirdn_apply.pyx b/scipy/signal/_upfirdn_apply.pyx
index 976611c9..4ba5e703 100644
--- a/scipy/signal/_upfirdn_apply.pyx
+++ b/scipy/signal/_upfirdn_apply.pyx
@@ -108,7 +108,7 @@ cpdef MODE mode_enum(mode):
 @cython.boundscheck(False)  # designed to stay within bounds
 @cython.wraparound(False)  # we don't use negative indexing
 cdef DTYPE_t _extend_left(DTYPE_t *x, np.intp_t idx, np.intp_t len_x,
-                          MODE mode, DTYPE_t cval) nogil:
+                          MODE mode, DTYPE_t cval) noexcept nogil:
     cdef DTYPE_t le = 0.
     cdef DTYPE_t lin_slope = 0.
 
@@ -174,7 +174,7 @@ cdef DTYPE_t _extend_left(DTYPE_t *x, np.intp_t idx, np.intp_t len_x,
 @cython.boundscheck(False)  # designed to stay within bounds
 @cython.wraparound(False)  # we don't use negative indexing
 cdef DTYPE_t _extend_right(DTYPE_t *x, np.intp_t idx, np.intp_t len_x,
-                           MODE mode, DTYPE_t cval) nogil:
+                           MODE mode, DTYPE_t cval) noexcept nogil:
     # note: idx will be >= len_x
     cdef DTYPE_t re = 0.
     cdef DTYPE_t lin_slope = 0.
@@ -322,7 +322,7 @@ cdef int _apply_axis_inner(DTYPE_t* data, ArrayInfo data_info,
                            DTYPE_t* output, ArrayInfo output_info,
                            np.intp_t up, np.intp_t down,
                            np.intp_t axis, MODE mode, DTYPE_t cval,
-                           np.intp_t len_out) nogil:
+                           np.intp_t len_out) noexcept nogil:
     cdef np.intp_t i
     cdef np.intp_t num_loops = 1
     cdef bint make_temp_data, make_temp_output
@@ -421,7 +421,7 @@ cdef int _apply_axis_inner(DTYPE_t* data, ArrayInfo data_info,
 cdef void _apply_impl(DTYPE_t *x, np.intp_t len_x, DTYPE_t *h_trans_flip,
                       np.intp_t len_h, DTYPE_t *out,
                       np.intp_t up, np.intp_t down, MODE mode,
-                      DTYPE_t cval, np.intp_t len_out) nogil:
+                      DTYPE_t cval, np.intp_t len_out) noexcept nogil:
     cdef np.intp_t h_per_phase = len_h // up
     cdef np.intp_t padded_len = len_x + h_per_phase - 1
     cdef np.intp_t x_idx = 0
diff --git a/scipy/sparse/csgraph/_flow.pyx b/scipy/sparse/csgraph/_flow.pyx
index 1315e54c..a76eab37 100644
--- a/scipy/sparse/csgraph/_flow.pyx
+++ b/scipy/sparse/csgraph/_flow.pyx
@@ -386,7 +386,7 @@ cdef ITYPE_t[:] _edmonds_karp(
         ITYPE_t[:] capacities,
         ITYPE_t[:] rev_edge_ptr,
         ITYPE_t source,
-        ITYPE_t sink):
+        ITYPE_t sink) noexcept:
     """Solves the maximum flow problem using the Edmonds--Karp algorithm.
 
     This assumes that for every edge in the graph, the edge in the opposite
@@ -492,7 +492,7 @@ cdef bint _build_level_graph(
         const ITYPE_t[:] heads,  # IN
         ITYPE_t[:] levels,  # IN/OUT
         ITYPE_t[:] q,  # IN/OUT
-        ) nogil:
+        ) noexcept nogil:
     """Builds layered graph from input graph using breadth first search.
 
     Parameters
@@ -553,7 +553,7 @@ cdef bint _augment_paths(
         ITYPE_t[:] progress,  # IN
         ITYPE_t[:] flows,  # OUT
         ITYPE_t[:, :] stack
-        ) nogil:
+        ) noexcept nogil:
     """Finds augmenting paths in layered graph using depth first search.
 
     Parameters
@@ -627,7 +627,7 @@ cdef ITYPE_t[:] _dinic(
         ITYPE_t[:] capacities,
         ITYPE_t[:] rev_edge_ptr,
         ITYPE_t source,
-        ITYPE_t sink):
+        ITYPE_t sink) noexcept:
     """Solves the maximum flow problem using the Dinic's algorithm.
 
     This assumes that for every edge in the graph, the edge in the opposite
diff --git a/scipy/sparse/csgraph/_matching.pyx b/scipy/sparse/csgraph/_matching.pyx
index a92e8a91..4d5c94a0 100644
--- a/scipy/sparse/csgraph/_matching.pyx
+++ b/scipy/sparse/csgraph/_matching.pyx
@@ -502,7 +502,7 @@ cdef ITYPE_t[:] _lapjvsp(ITYPE_t[:] first,
                          ITYPE_t[:] kk,
                          DTYPE_t[:] cc,
                          ITYPE_t nr,
-                         ITYPE_t nc):
+                         ITYPE_t nc) noexcept:
     """Solves the minimum weight bipartite matching problem using LAPJVsp.
 
     The implementation at hand is a straightforward port of the original Pascal
diff --git a/scipy/sparse/csgraph/_min_spanning_tree.pyx b/scipy/sparse/csgraph/_min_spanning_tree.pyx
index 9f6f64a3..ea93ac68 100644
--- a/scipy/sparse/csgraph/_min_spanning_tree.pyx
+++ b/scipy/sparse/csgraph/_min_spanning_tree.pyx
@@ -118,7 +118,7 @@ cdef void _min_spanning_tree(DTYPE_t[::1] data,
                              ITYPE_t[::1] i_sort,
                              ITYPE_t[::1] row_indices,
                              ITYPE_t[::1] predecessors,
-                             ITYPE_t[::1] rank) nogil:
+                             ITYPE_t[::1] rank) noexcept nogil:
     # Work-horse routine for computing minimum spanning tree using
     #  Kruskal's algorithm.  By separating this code here, we get more
     #  efficient indexing.
diff --git a/scipy/sparse/csgraph/_shortest_path.pyx b/scipy/sparse/csgraph/_shortest_path.pyx
index 459672ca..4e158340 100644
--- a/scipy/sparse/csgraph/_shortest_path.pyx
+++ b/scipy/sparse/csgraph/_shortest_path.pyx
@@ -332,7 +332,7 @@ def floyd_warshall(csgraph, directed=True,
 cdef void _floyd_warshall(
                np.ndarray[DTYPE_t, ndim=2, mode='c'] dist_matrix,
                np.ndarray[ITYPE_t, ndim=2, mode='c'] predecessor_matrix,
-               int directed=0):
+               int directed=0) noexcept:
     # dist_matrix : in/out
     #    on input, the graph
     #    on output, the matrix of shortest paths
@@ -1059,7 +1059,7 @@ cdef int _bellman_ford_directed(
             const int[:] csr_indices,
             const int[:] csr_indptr,
             double[:, :] dist_matrix,
-            int[:, :] pred):
+            int[:, :] pred) noexcept:
     cdef:
         unsigned int Nind = dist_matrix.shape[0]
         unsigned int N = dist_matrix.shape[1]
@@ -1100,7 +1100,7 @@ cdef int _bellman_ford_undirected(
             const int[:] csr_indices,
             const int[:] csr_indptr,
             double[:, :] dist_matrix,
-            int[:, :] pred):
+            int[:, :] pred) noexcept:
     cdef:
         unsigned int Nind = dist_matrix.shape[0]
         unsigned int N = dist_matrix.shape[1]
@@ -1322,7 +1322,7 @@ cdef void _johnson_add_weights(
             double[:] csr_weights,
             int[:] csr_indices,
             int[:] csr_indptr,
-            double[:] dist_array):
+            double[:] dist_array) noexcept:
     # let w(u, v) = w(u, v) + h(u) - h(v)
     cdef unsigned int j, k, N = dist_array.shape[0]
 
@@ -1336,7 +1336,7 @@ cdef int _johnson_directed(
             const double[:] csr_weights,
             const int[:] csr_indices,
             const int[:] csr_indptr,
-            double[:] dist_array):
+            double[:] dist_array) noexcept:
     # Note: The contents of dist_array must be initialized to zero on entry
     cdef:
         unsigned int N = dist_array.shape[0]
@@ -1369,7 +1369,7 @@ cdef int _johnson_undirected(
             const double[:] csr_weights,
             const int[:] csr_indices,
             const int[:] csr_indptr,
-            double[:] dist_array):
+            double[:] dist_array) noexcept:
     # Note: The contents of dist_array must be initialized to zero on entry
     cdef:
         unsigned int N = dist_array.shape[0]
@@ -1426,7 +1426,7 @@ cdef struct FibonacciNode:
 
 cdef void initialize_node(FibonacciNode* node,
                           unsigned int index,
-                          DTYPE_t val=0):
+                          DTYPE_t val=0) noexcept:
     # Assumptions: - node is a valid pointer
     #              - node is not currently part of a heap
     node.index = index
@@ -1441,7 +1441,7 @@ cdef void initialize_node(FibonacciNode* node,
     node.children = NULL
 
 
-cdef FibonacciNode* leftmost_sibling(FibonacciNode* node):
+cdef FibonacciNode* leftmost_sibling(FibonacciNode* node) noexcept:
     # Assumptions: - node is a valid pointer
     cdef FibonacciNode* temp = node
     while(temp.left_sibling):
@@ -1449,7 +1449,7 @@ cdef FibonacciNode* leftmost_sibling(FibonacciNode* node):
     return temp
 
 
-cdef void add_child(FibonacciNode* node, FibonacciNode* new_child):
+cdef void add_child(FibonacciNode* node, FibonacciNode* new_child) noexcept:
     # Assumptions: - node is a valid pointer
     #              - new_child is a valid pointer
     #              - new_child is not the sibling or child of another node
@@ -1465,7 +1465,7 @@ cdef void add_child(FibonacciNode* node, FibonacciNode* new_child):
         node.rank = 1
 
 
-cdef void add_sibling(FibonacciNode* node, FibonacciNode* new_sibling):
+cdef void add_sibling(FibonacciNode* node, FibonacciNode* new_sibling) noexcept:
     # Assumptions: - node is a valid pointer
     #              - new_sibling is a valid pointer
     #              - new_sibling is not the child or sibling of another node
@@ -1482,7 +1482,7 @@ cdef void add_sibling(FibonacciNode* node, FibonacciNode* new_sibling):
         new_sibling.parent.rank += 1
 
 
-cdef void remove(FibonacciNode* node):
+cdef void remove(FibonacciNode* node) noexcept:
     # Assumptions: - node is a valid pointer
     if node.parent:
         node.parent.rank -= 1
@@ -1515,7 +1515,7 @@ cdef struct FibonacciHeap:
 
 
 cdef void insert_node(FibonacciHeap* heap,
-                      FibonacciNode* node):
+                      FibonacciNode* node) noexcept:
     # Assumptions: - heap is a valid pointer
     #              - node is a valid pointer
     #              - node is not the child or sibling of another node
@@ -1535,7 +1535,7 @@ cdef void insert_node(FibonacciHeap* heap,
 
 cdef void decrease_val(FibonacciHeap* heap,
                        FibonacciNode* node,
-                       DTYPE_t newval):
+                       DTYPE_t newval) noexcept:
     # Assumptions: - heap is a valid pointer
     #              - newval <= node.val
     #              - node is a valid pointer
@@ -1554,7 +1554,7 @@ cdef void decrease_val(FibonacciHeap* heap,
         heap.min_node = node
 
 
-cdef void link(FibonacciHeap* heap, FibonacciNode* node):
+cdef void link(FibonacciHeap* heap, FibonacciNode* node) noexcept:
     # Assumptions: - heap is a valid pointer
     #              - node is a valid pointer
     #              - node is already within heap
@@ -1577,7 +1577,7 @@ cdef void link(FibonacciHeap* heap, FibonacciNode* node):
             link(heap, linknode)
 
 
-cdef FibonacciNode* remove_min(FibonacciHeap* heap):
+cdef FibonacciNode* remove_min(FibonacciHeap* heap) noexcept:
     # Assumptions: - heap is a valid pointer
     #              - heap.min_node is a valid pointer
     cdef:
@@ -1630,7 +1630,7 @@ cdef FibonacciNode* remove_min(FibonacciHeap* heap):
 ######################################################################
 # Debugging: Functions for printing the Fibonacci heap
 #
-#cdef void print_node(FibonacciNode* node, int level=0):
+#cdef void print_node(FibonacciNode* node, int level=0) noexcept:
 #    print('%s(%i,%i) %i' % (level*' ', node.index, node.val, node.rank))
 #    if node.children:
 #        print_node(node.children, level+1)
@@ -1638,7 +1638,7 @@ cdef FibonacciNode* remove_min(FibonacciHeap* heap):
 #        print_node(node.right_sibling, level)
 #
 #
-#cdef void print_heap(FibonacciHeap* heap):
+#cdef void print_heap(FibonacciHeap* heap) noexcept:
 #    print("---------------------------------")
 #    if heap.min_node:
 #        print("min node: (%i, %i)" % (heap.min_node.index, heap.min_node.val))
diff --git a/scipy/sparse/csgraph/_tools.pyx b/scipy/sparse/csgraph/_tools.pyx
index b1b98d72..dde34fe7 100644
--- a/scipy/sparse/csgraph/_tools.pyx
+++ b/scipy/sparse/csgraph/_tools.pyx
@@ -389,7 +389,7 @@ cdef void _populate_graph(np.ndarray[DTYPE_t, ndim=1, mode='c'] data,
                           np.ndarray[ITYPE_t, ndim=1, mode='c'] indices,
                           np.ndarray[ITYPE_t, ndim=1, mode='c'] indptr,
                           np.ndarray[DTYPE_t, ndim=2, mode='c'] graph,
-                          DTYPE_t null_value):
+                          DTYPE_t null_value) noexcept:
     # data, indices, indptr are the csr attributes of the sparse input.
     # on input, graph should be filled with infinities, and should be
     # of size [N, N], which is also the size of the sparse matrix
@@ -592,7 +592,7 @@ cdef void _construct_dist_matrix(np.ndarray[DTYPE_t, ndim=2] graph,
                                  np.ndarray[ITYPE_t, ndim=2] pred,
                                  np.ndarray[DTYPE_t, ndim=2] dist,
                                  int directed,
-                                 DTYPE_t null_value):
+                                 DTYPE_t null_value) noexcept:
     # All matrices should be size N x N
     # note that graph will be modified if directed == False
     # dist should be all zero on entry
diff --git a/scipy/sparse/csgraph/_traversal.pyx b/scipy/sparse/csgraph/_traversal.pyx
index 8b25f590..ec5bd294 100644
--- a/scipy/sparse/csgraph/_traversal.pyx
+++ b/scipy/sparse/csgraph/_traversal.pyx
@@ -357,7 +357,7 @@ cdef unsigned int _breadth_first_directed(
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] indices,
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] indptr,
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] node_list,
-                           np.ndarray[ITYPE_t, ndim=1, mode='c'] predecessors):
+                           np.ndarray[ITYPE_t, ndim=1, mode='c'] predecessors) noexcept:
     # Inputs:
     #  head_node: (input) index of the node from which traversal starts
     #  indices: (input) CSR indices of graph
@@ -398,7 +398,7 @@ cdef unsigned int _breadth_first_undirected(
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] indices2,
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] indptr2,
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] node_list,
-                           np.ndarray[ITYPE_t, ndim=1, mode='c'] predecessors):
+                           np.ndarray[ITYPE_t, ndim=1, mode='c'] predecessors) noexcept:
     # Inputs:
     #  head_node: (input) index of the node from which traversal starts
     #  indices1: (input) CSR indices of graph
@@ -545,7 +545,7 @@ cdef unsigned int _depth_first_directed(
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] node_list,
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] predecessors,
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] root_list,
-                           np.ndarray[ITYPE_t, ndim=1, mode='c'] flag):
+                           np.ndarray[ITYPE_t, ndim=1, mode='c'] flag) noexcept:
     cdef unsigned int i, i_nl_end, cnode, pnode
     cdef unsigned int N = node_list.shape[0]
     cdef int no_children, i_root
@@ -591,7 +591,7 @@ cdef unsigned int _depth_first_undirected(
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] node_list,
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] predecessors,
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] root_list,
-                           np.ndarray[ITYPE_t, ndim=1, mode='c'] flag):
+                           np.ndarray[ITYPE_t, ndim=1, mode='c'] flag) noexcept:
     cdef unsigned int i, i_nl_end, cnode, pnode
     cdef unsigned int N = node_list.shape[0]
     cdef int no_children, i_root
@@ -647,7 +647,7 @@ cdef unsigned int _depth_first_undirected(
 cdef int _connected_components_directed(
                                  np.ndarray[ITYPE_t, ndim=1, mode='c'] indices,
                                  np.ndarray[ITYPE_t, ndim=1, mode='c'] indptr,
-                                 np.ndarray[ITYPE_t, ndim=1, mode='c'] labels):
+                                 np.ndarray[ITYPE_t, ndim=1, mode='c'] labels) noexcept:
     """
     Uses an iterative version of Tarjan's algorithm to find the
     strongly connected components of a directed graph represented as a
@@ -771,7 +771,7 @@ cdef int _connected_components_undirected(
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] indptr1,
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] indices2,
                            np.ndarray[ITYPE_t, ndim=1, mode='c'] indptr2,
-                           np.ndarray[ITYPE_t, ndim=1, mode='c'] labels):
+                           np.ndarray[ITYPE_t, ndim=1, mode='c'] labels) noexcept:
 
     cdef int v, w, j, label, SS_head
     cdef int N = labels.shape[0]
diff --git a/scipy/spatial/_ckdtree.pyx b/scipy/spatial/_ckdtree.pyx
index aaa641ee..d00d5fcf 100644
--- a/scipy/spatial/_ckdtree.pyx
+++ b/scipy/spatial/_ckdtree.pyx
@@ -343,7 +343,7 @@ cdef class cKDTreeNode:
         readonly object       lesser
         readonly object       greater
 
-    cdef void _setup(cKDTreeNode self, cKDTree parent, ckdtreenode *node, np.intp_t level):
+    cdef void _setup(cKDTreeNode self, cKDTree parent, ckdtreenode *node, np.intp_t level) noexcept:
         cdef cKDTreeNode n1, n2
         self.level = level
         self.split_dim = node.split_dim
diff --git a/scipy/spatial/_qhull.pxd b/scipy/spatial/_qhull.pxd
index a0635ac4..c397091d 100644
--- a/scipy/spatial/_qhull.pxd
+++ b/scipy/spatial/_qhull.pxd
@@ -40,33 +40,33 @@ cdef int _get_delaunay_info(DelaunayInfo_t *, obj,
 #
 
 cdef int _barycentric_inside(int ndim, double *transform,
-                             double *x, double *c, double eps) nogil
+                             double *x, double *c, double eps) noexcept nogil
 
 cdef void _barycentric_coordinate_single(int ndim, double *transform,
-                                         double *x, double *c, int i) nogil
+                                         double *x, double *c, int i) noexcept nogil
 
 cdef void _barycentric_coordinates(int ndim, double *transform,
-                                   double *x, double *c) nogil
+                                   double *x, double *c) noexcept nogil
 
 #
 # N+1-D geometry
 #
 
-cdef void _lift_point(DelaunayInfo_t *d, double *x, double *z) nogil
+cdef void _lift_point(DelaunayInfo_t *d, double *x, double *z) noexcept nogil
 
-cdef double _distplane(DelaunayInfo_t *d, int isimplex, double *point) nogil
+cdef double _distplane(DelaunayInfo_t *d, int isimplex, double *point) noexcept nogil
 
 #
 # Finding simplices
 #
 
-cdef int _is_point_fully_outside(DelaunayInfo_t *d, double *x, double eps) nogil
+cdef int _is_point_fully_outside(DelaunayInfo_t *d, double *x, double eps) noexcept nogil
 
 cdef int _find_simplex_bruteforce(DelaunayInfo_t *d, double *c, double *x,
-                                  double eps, double eps_broad) nogil
+                                  double eps, double eps_broad) noexcept nogil
 
 cdef int _find_simplex_directed(DelaunayInfo_t *d, double *c, double *x,
-                                int *start, double eps, double eps_broad) nogil
+                                int *start, double eps, double eps_broad) noexcept nogil
 
 cdef int _find_simplex(DelaunayInfo_t *d, double *c, double *x, int *start,
-                       double eps, double eps_broad) nogil
+                       double eps, double eps_broad) noexcept nogil
diff --git a/scipy/spatial/_qhull.pyx b/scipy/spatial/_qhull.pyx
index 5b47e8b0..f15a51f9 100644
--- a/scipy/spatial/_qhull.pyx
+++ b/scipy/spatial/_qhull.pyx
@@ -988,7 +988,7 @@ cdef class _Qhull:
 
 
 cdef void _visit_voronoi(qhT *_qh, FILE *ptr, vertexT *vertex, vertexT *vertexA,
-                         setT *centers, boolT unbounded):
+                         setT *centers, boolT unbounded) noexcept:
     cdef _Qhull qh = <_Qhull>ptr
     cdef int point_1, point_2, ix
     cdef list cur_vertices
@@ -1024,7 +1024,7 @@ cdef void _visit_voronoi(qhT *_qh, FILE *ptr, vertexT *vertex, vertexT *vertexA,
     return
 
 
-cdef void qh_order_vertexneighbors_nd(qhT *qh, int nd, vertexT *vertex):
+cdef void qh_order_vertexneighbors_nd(qhT *qh, int nd, vertexT *vertex) noexcept:
     if nd == 3:
         qh_order_vertexneighbors(qh, vertex)
     elif nd >= 4:
@@ -1147,7 +1147,7 @@ def _get_barycentric_transforms(np.ndarray[np.double_t, ndim=2] points,
     return Tinvs
 
 @cython.boundscheck(False)
-cdef double _matrix_norm1(int n, double *a) nogil:
+cdef double _matrix_norm1(int n, double *a) noexcept nogil:
     """Compute the 1-norm of a square matrix given in in Fortran order"""
     cdef double maxsum = 0, colsum
     cdef int i, j
@@ -1162,7 +1162,7 @@ cdef double _matrix_norm1(int n, double *a) nogil:
     return maxsum
 
 cdef int _barycentric_inside(int ndim, double *transform,
-                             double *x, double *c, double eps) nogil:
+                             double *x, double *c, double eps) noexcept nogil:
     """
     Check whether point is inside a simplex, using barycentric
     coordinates.  `c` will be filled with barycentric coordinates, if
@@ -1184,7 +1184,7 @@ cdef int _barycentric_inside(int ndim, double *transform,
     return 1
 
 cdef void _barycentric_coordinate_single(int ndim, double *transform,
-                                         double *x, double *c, int i) nogil:
+                                         double *x, double *c, int i) noexcept nogil:
     """
     Compute a single barycentric coordinate.
 
@@ -1204,7 +1204,7 @@ cdef void _barycentric_coordinate_single(int ndim, double *transform,
             c[i] += transform[ndim*i + j] * (x[j] - transform[ndim*ndim + j])
 
 cdef void _barycentric_coordinates(int ndim, double *transform,
-                                   double *x, double *c) nogil:
+                                   double *x, double *c) noexcept nogil:
     """
     Compute barycentric coordinates.
 
@@ -1222,7 +1222,7 @@ cdef void _barycentric_coordinates(int ndim, double *transform,
 # N-D geometry
 #------------------------------------------------------------------------------
 
-cdef void _lift_point(DelaunayInfo_t *d, double *x, double *z) nogil:
+cdef void _lift_point(DelaunayInfo_t *d, double *x, double *z) noexcept nogil:
     cdef int i
     z[d.ndim] = 0
     for i in range(d.ndim):
@@ -1231,7 +1231,7 @@ cdef void _lift_point(DelaunayInfo_t *d, double *x, double *z) nogil:
     z[d.ndim] *= d.paraboloid_scale
     z[d.ndim] += d.paraboloid_shift
 
-cdef double _distplane(DelaunayInfo_t *d, int isimplex, double *point) nogil:
+cdef double _distplane(DelaunayInfo_t *d, int isimplex, double *point) noexcept nogil:
     """
     qh_distplane
     """
@@ -1248,7 +1248,7 @@ cdef double _distplane(DelaunayInfo_t *d, int isimplex, double *point) nogil:
 #------------------------------------------------------------------------------
 
 cdef int _is_point_fully_outside(DelaunayInfo_t *d, double *x,
-                                 double eps) nogil:
+                                 double eps) noexcept nogil:
     """
     Is the point outside the bounding box of the triangulation?
 
@@ -1262,7 +1262,7 @@ cdef int _is_point_fully_outside(DelaunayInfo_t *d, double *x,
 
 cdef int _find_simplex_bruteforce(DelaunayInfo_t *d, double *c,
                                   double *x, double eps,
-                                  double eps_broad) nogil:
+                                  double eps_broad) noexcept nogil:
     """
     Find simplex containing point `x` by going through all simplices.
 
@@ -1320,7 +1320,7 @@ cdef int _find_simplex_bruteforce(DelaunayInfo_t *d, double *c,
 
 cdef int _find_simplex_directed(DelaunayInfo_t *d, double *c,
                                 double *x, int *start, double eps,
-                                double eps_broad) nogil:
+                                double eps_broad) noexcept nogil:
     """
     Find simplex containing point `x` via a directed walk in the tessellation.
 
@@ -1421,7 +1421,7 @@ cdef int _find_simplex_directed(DelaunayInfo_t *d, double *c,
 
 cdef int _find_simplex(DelaunayInfo_t *d, double *c,
                        double *x, int *start, double eps,
-                       double eps_broad) nogil:
+                       double eps_broad) noexcept nogil:
     """
     Find simplex containing point `x` by walking the triangulation.
 
diff --git a/scipy/spatial/_voronoi.pyx b/scipy/spatial/_voronoi.pyx
index f86086a4..ddfdee92 100644
--- a/scipy/spatial/_voronoi.pyx
+++ b/scipy/spatial/_voronoi.pyx
@@ -23,7 +23,7 @@ DEF ARRAY_FILLER = -2
 
 @cython.boundscheck(False)
 cdef void remaining_filter(np.npy_intp[:] remaining,
-                           np.npy_intp current_simplex):
+                           np.npy_intp current_simplex) noexcept:
     cdef np.npy_intp i
     for i in range(remaining.shape[0]):
         if remaining[i] == current_simplex:
diff --git a/scipy/spatial/setlist.pxd b/scipy/spatial/setlist.pxd
index 646d8bc7..554710bf 100644
--- a/scipy/spatial/setlist.pxd
+++ b/scipy/spatial/setlist.pxd
@@ -57,7 +57,7 @@ cdef inline int init(setlist_t *setlist, size_t n, size_t size_guess) except -1:
 
     return 0
 
-cdef inline void free(setlist_t *setlist):
+cdef inline void free(setlist_t *setlist) noexcept:
     """
     Free the set list
     """
@@ -73,7 +73,7 @@ cdef inline void free(setlist_t *setlist):
     setlist.alloc_sizes = NULL
     setlist.n = 0
 
-cdef inline int add(setlist_t *setlist, int n, int value) nogil:
+cdef inline int add(setlist_t *setlist, int n, int value) noexcept nogil:
     """
     Add a value to set `n`
     """
diff --git a/scipy/spatial/transform/_rotation.pyx b/scipy/spatial/transform/_rotation.pyx
index d97a9b0c..6e680777 100644
--- a/scipy/spatial/transform/_rotation.pyx
+++ b/scipy/spatial/transform/_rotation.pyx
@@ -13,13 +13,13 @@ from numpy.math cimport PI as pi, NAN, isnan # avoid MSVC error
 np.import_array()
 
 # utilities for empty array initialization
-cdef inline double[:] _empty1(int n):
+cdef inline double[:] _empty1(int n) noexcept:
     return array(shape=(n,), itemsize=sizeof(double), format=b"d")
-cdef inline double[:, :] _empty2(int n1, int n2):
+cdef inline double[:, :] _empty2(int n1, int n2) noexcept :
     return array(shape=(n1, n2), itemsize=sizeof(double), format=b"d")
-cdef inline double[:, :, :] _empty3(int n1, int n2, int n3):
+cdef inline double[:, :, :] _empty3(int n1, int n2, int n3) noexcept:
     return array(shape=(n1, n2, n3), itemsize=sizeof(double), format=b"d")
-cdef inline double[:, :] _zeros2(int n1, int n2):
+cdef inline double[:, :] _zeros2(int n1, int n2) noexcept:
     cdef double[:, :] arr = array(shape=(n1, n2),
         itemsize=sizeof(double), format=b"d")
     arr[:, :] = 0
@@ -28,7 +28,7 @@ cdef inline double[:, :] _zeros2(int n1, int n2):
 # flat implementations of numpy functions
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline double[:] _cross3(const double[:] a, const double[:] b):
+cdef inline double[:] _cross3(const double[:] a, const double[:] b) noexcept:
     cdef double[:] result = _empty1(3)
     result[0] = a[1]*b[2] - a[2]*b[1]
     result[1] = a[2]*b[0] - a[0]*b[2]
@@ -37,17 +37,17 @@ cdef inline double[:] _cross3(const double[:] a, const double[:] b):
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline double _dot3(const double[:] a, const double[:] b) nogil:
+cdef inline double _dot3(const double[:] a, const double[:] b) noexcept nogil:
     return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline double _norm3(const double[:] elems) nogil:
+cdef inline double _norm3(const double[:] elems) noexcept nogil:
     return sqrt(_dot3(elems, elems))
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline double _normalize4(double[:] elems) nogil:
+cdef inline double _normalize4(double[:] elems) noexcept nogil:
     cdef double norm = sqrt(_dot3(elems, elems) + elems[3]*elems[3])
 
     if norm == 0:
@@ -62,7 +62,7 @@ cdef inline double _normalize4(double[:] elems) nogil:
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline int _argmax4(double[:] a) nogil:
+cdef inline int _argmax4(double[:] a) noexcept nogil:
     cdef int imax = 0
     cdef double vmax = a[0]
 
@@ -81,7 +81,7 @@ cdef double[3] _ez = [0, 0, 1]
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef inline const double[:] _elementary_basis_vector(uchar axis):
+cdef inline const double[:] _elementary_basis_vector(uchar axis) noexcept:
     if axis == b'x': return _ex
     elif axis == b'y': return _ey
     elif axis == b'z': return _ez
@@ -90,7 +90,7 @@ cdef inline const double[:] _elementary_basis_vector(uchar axis):
 @cython.wraparound(False)
 cdef double[:, :] _compute_euler_from_matrix(
     np.ndarray[double, ndim=3] matrix, const uchar[:] seq, bint extrinsic=False
-):
+) noexcept:
     # The algorithm assumes intrinsic frame transformations. The algorithm
     # in the paper is formulated for rotation matrices which are transposition
     # rotation matrices used within Rotation.
@@ -227,7 +227,7 @@ cdef double[:, :] _compute_euler_from_matrix(
 @cython.wraparound(False)
 cdef inline void _compose_quat_single( # calculate p * q into r
     const double[:] p, const double[:] q, double[:] r
-):
+) noexcept:
     cdef double[:] cross = _cross3(p[:3], q[:3])
 
     r[0] = p[3]*q[0] + q[3]*p[0] + cross[0]
@@ -239,7 +239,7 @@ cdef inline void _compose_quat_single( # calculate p * q into r
 @cython.wraparound(False)
 cdef inline double[:, :] _compose_quat(
     const double[:, :] p, const double[:, :] q
-):
+) noexcept:
     cdef Py_ssize_t n = max(p.shape[0], q.shape[0])
     cdef double[:, :] product = _empty2(n, 4)
 
@@ -260,7 +260,7 @@ cdef inline double[:, :] _compose_quat(
 @cython.wraparound(False)
 cdef inline double[:, :] _make_elementary_quat(
     uchar axis, const double[:] angles
-):
+) noexcept:
     cdef Py_ssize_t n = angles.shape[0]
     cdef double[:, :] quat = _zeros2(n, 4)
 
@@ -278,7 +278,7 @@ cdef inline double[:, :] _make_elementary_quat(
 @cython.wraparound(False)
 cdef double[:, :] _elementary_quat_compose(
     const uchar[:] seq, const double[:, :] angles, bint intrinsic=False
-):
+) noexcept:
     cdef double[:, :] result = _make_elementary_quat(seq[0], angles[:, 0])
     cdef Py_ssize_t seq_len = seq.shape[0]
 
diff --git a/scipy/special/_agm.pxd b/scipy/special/_agm.pxd
index 8b31ffb3..0a67888b 100644
--- a/scipy/special/_agm.pxd
+++ b/scipy/special/_agm.pxd
@@ -5,7 +5,7 @@ from libc.math cimport log, exp, fabs, sqrt, isnan, isinf, NAN, M_PI
 from ._cephes cimport ellpk
 
 
-cdef inline double _agm_iter(double a, double b) nogil:
+cdef inline double _agm_iter(double a, double b) noexcept nogil:
     # Arithmetic-geometric mean, iterative implementation
     # a and b must be positive (not zero, not nan).
 
@@ -23,7 +23,7 @@ cdef inline double _agm_iter(double a, double b) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double agm(double a, double b) nogil:
+cdef inline double agm(double a, double b) noexcept nogil:
     # Arithmetic-geometric mean
 
     # sqrthalfmax is sqrt(np.finfo(1.0).max/2)
diff --git a/scipy/special/_boxcox.pxd b/scipy/special/_boxcox.pxd
index 275e7757..440684b7 100644
--- a/scipy/special/_boxcox.pxd
+++ b/scipy/special/_boxcox.pxd
@@ -2,7 +2,7 @@
 from libc.math cimport log, log1p, expm1, exp, fabs
 
 
-cdef inline double boxcox(double x, double lmbda) nogil:
+cdef inline double boxcox(double x, double lmbda) noexcept nogil:
     # if lmbda << 1 and log(x) < 1.0, the lmbda*log(x) product can lose
     # precision, furthermore, expm1(x) == x for x < eps.
     # For doubles, the range of log is -744.44 to +709.78, with eps being
@@ -15,7 +15,7 @@ cdef inline double boxcox(double x, double lmbda) nogil:
         return expm1(lmbda * log(x)) / lmbda
 
 
-cdef inline double boxcox1p(double x, double lmbda) nogil:
+cdef inline double boxcox1p(double x, double lmbda) noexcept nogil:
     # The argument given above in boxcox applies here with the modification
     # that the smallest value produced by log1p is the minimum representable
     # value, rather than eps.  The second condition here prevents unflow
@@ -27,14 +27,14 @@ cdef inline double boxcox1p(double x, double lmbda) nogil:
         return expm1(lmbda * lgx) / lmbda
 
 
-cdef inline double inv_boxcox(double x, double lmbda) nogil:
+cdef inline double inv_boxcox(double x, double lmbda) noexcept nogil:
     if lmbda == 0:
         return exp(x)
     else:
         return exp(log1p(lmbda * x) / lmbda)
 
 
-cdef inline double inv_boxcox1p(double x, double lmbda) nogil:
+cdef inline double inv_boxcox1p(double x, double lmbda) noexcept nogil:
     if lmbda == 0:
         return expm1(x)
     elif fabs(lmbda * x) < 1e-154:
diff --git a/scipy/special/_comb.pyx b/scipy/special/_comb.pyx
index 5f9af908..7eb79f49 100644
--- a/scipy/special/_comb.pyx
+++ b/scipy/special/_comb.pyx
@@ -30,7 +30,7 @@ def _comb_int(N, k):
     return numerator // denominator
 
 
-cdef unsigned long _comb_int_long(unsigned long N, unsigned long k):
+cdef unsigned long _comb_int_long(unsigned long N, unsigned long k) noexcept:
     """
     Compute binom(N, k) for integers.
     Returns 0 if error/overflow encountered.
diff --git a/scipy/special/_complexstuff.pxd b/scipy/special/_complexstuff.pxd
index 96e8196d..ce11be1d 100644
--- a/scipy/special/_complexstuff.pxd
+++ b/scipy/special/_complexstuff.pxd
@@ -32,51 +32,51 @@ ctypedef union _complex_pun:
     double_complex c99
 
 cdef inline np.npy_cdouble npy_cdouble_from_double_complex(
-        double_complex x) nogil:
+        double_complex x) noexcept nogil:
     cdef _complex_pun z
     z.c99 = x
     return z.npy
 
 cdef inline double_complex double_complex_from_npy_cdouble(
-        np.npy_cdouble x) nogil:
+        np.npy_cdouble x) noexcept nogil:
     cdef _complex_pun z
     z.npy = x
     return z.c99
 
-cdef inline bint zisnan(number_t x) nogil:
+cdef inline bint zisnan(number_t x) noexcept nogil:
     if number_t is double_complex:
         return isnan(x.real) or isnan(x.imag)
     else:
         return isnan(x)
 
-cdef inline bint zisfinite(number_t x) nogil:
+cdef inline bint zisfinite(number_t x) noexcept nogil:
     if number_t is double_complex:
         return isfinite(x.real) and isfinite(x.imag)
     else:
         return isfinite(x)
 
-cdef inline bint zisinf(number_t x) nogil:
+cdef inline bint zisinf(number_t x) noexcept nogil:
     if number_t is double_complex:
         return not zisnan(x) and not zisfinite(x)
     else:
         return isinf(x)
 
-cdef inline double zreal(number_t x) nogil:
+cdef inline double zreal(number_t x) noexcept nogil:
     if number_t is double_complex:
         return x.real
     else:
         return x
 
-cdef inline double zabs(number_t x) nogil:
+cdef inline double zabs(number_t x) noexcept nogil:
     if number_t is double_complex:
         return npy_cabs(npy_cdouble_from_double_complex(x))
     else:
         return fabs(x)
 
-cdef inline double zarg(double complex x) nogil:
+cdef inline double zarg(double complex x) noexcept nogil:
     return npy_carg(npy_cdouble_from_double_complex(x))
 
-cdef inline number_t zlog(number_t x) nogil:
+cdef inline number_t zlog(number_t x) noexcept nogil:
     cdef np.npy_cdouble r
     if number_t is double_complex:
         r = npy_clog(npy_cdouble_from_double_complex(x))
@@ -84,7 +84,7 @@ cdef inline number_t zlog(number_t x) nogil:
     else:
         return log(x)
 
-cdef inline number_t zexp(number_t x) nogil:
+cdef inline number_t zexp(number_t x) noexcept nogil:
     cdef np.npy_cdouble r
     if number_t is double_complex:
         r = npy_cexp(npy_cdouble_from_double_complex(x))
@@ -92,7 +92,7 @@ cdef inline number_t zexp(number_t x) nogil:
     else:
         return exp(x)
 
-cdef inline number_t zsin(number_t x) nogil:
+cdef inline number_t zsin(number_t x) noexcept nogil:
     cdef np.npy_cdouble r
     if number_t is double_complex:
         r = npy_csin(npy_cdouble_from_double_complex(x))
@@ -100,7 +100,7 @@ cdef inline number_t zsin(number_t x) nogil:
     else:
         return sin(x)
 
-cdef inline number_t zcos(number_t x) nogil:
+cdef inline number_t zcos(number_t x) noexcept nogil:
     cdef np.npy_cdouble r
     if number_t is double_complex:
         r = npy_ccos(npy_cdouble_from_double_complex(x))
@@ -108,7 +108,7 @@ cdef inline number_t zcos(number_t x) nogil:
     else:
         return cos(x)
 
-cdef inline number_t zsqrt(number_t x) nogil:
+cdef inline number_t zsqrt(number_t x) noexcept nogil:
     cdef np.npy_cdouble r
     if number_t is double_complex:
         r = npy_csqrt(npy_cdouble_from_double_complex(x))
@@ -116,7 +116,7 @@ cdef inline number_t zsqrt(number_t x) nogil:
     else:
         return sqrt(x)
 
-cdef inline number_t zpow(number_t x, double y) nogil:
+cdef inline number_t zpow(number_t x, double y) noexcept nogil:
     cdef np.npy_cdouble r, z
     # FIXME
     if number_t is double_complex:
@@ -127,14 +127,14 @@ cdef inline number_t zpow(number_t x, double y) nogil:
     else:
         return pow(x, y)
 
-cdef inline double_complex zpack(double zr, double zi) nogil:
+cdef inline double_complex zpack(double zr, double zi) noexcept nogil:
     cdef np.npy_cdouble z
     z.real = zr
     z.imag = zi
     return double_complex_from_npy_cdouble(z)
 
 @cython.cdivision(True)
-cdef inline double complex zlog1(double complex z) nogil:
+cdef inline double complex zlog1(double complex z) noexcept nogil:
     """
     Compute log, paying special attention to accuracy around 1. We
     implement this ourselves because some systems (most notably the
diff --git a/scipy/special/_convex_analysis.pxd b/scipy/special/_convex_analysis.pxd
index 70bf0aa6..2fe95b95 100644
--- a/scipy/special/_convex_analysis.pxd
+++ b/scipy/special/_convex_analysis.pxd
@@ -1,6 +1,6 @@
 from libc.math cimport log, fabs, expm1, log1p, isnan, NAN, INFINITY
 
-cdef inline double entr(double x) nogil:
+cdef inline double entr(double x) noexcept nogil:
     if isnan(x):
         return x
     elif x > 0:
@@ -10,7 +10,7 @@ cdef inline double entr(double x) nogil:
     else:
         return -INFINITY
 
-cdef inline double kl_div(double x, double y) nogil:
+cdef inline double kl_div(double x, double y) noexcept nogil:
     if isnan(x) or isnan(y):
         return NAN
     elif x > 0 and y > 0:
@@ -20,7 +20,7 @@ cdef inline double kl_div(double x, double y) nogil:
     else:
         return INFINITY
 
-cdef inline double rel_entr(double x, double y) nogil:
+cdef inline double rel_entr(double x, double y) noexcept nogil:
     if isnan(x) or isnan(y):
         return NAN
     elif x > 0 and y > 0:
@@ -30,7 +30,7 @@ cdef inline double rel_entr(double x, double y) nogil:
     else:
         return INFINITY
 
-cdef inline double huber(double delta, double r) nogil:
+cdef inline double huber(double delta, double r) noexcept nogil:
     if delta < 0:
         return INFINITY
     elif fabs(r) <= delta:
@@ -38,7 +38,7 @@ cdef inline double huber(double delta, double r) nogil:
     else:
         return delta * (fabs(r) - 0.5 * delta);
 
-cdef inline double pseudo_huber(double delta, double r) nogil:
+cdef inline double pseudo_huber(double delta, double r) noexcept nogil:
     cdef double u, v
     if delta < 0:
         return INFINITY
diff --git a/scipy/special/_cunity.pxd b/scipy/special/_cunity.pxd
index 06653f99..9cb010f9 100644
--- a/scipy/special/_cunity.pxd
+++ b/scipy/special/_cunity.pxd
@@ -36,7 +36,7 @@ from ._cephes cimport log1p, expm1, cosm1
 # This expression suffers from cancellation when x < 0 and
 # y = +/-sqrt(2*fabs(x)). To get around this cancellation problem, we use
 # double-double precision when necessary.
-cdef inline double complex clog1p(double complex z) nogil:
+cdef inline double complex clog1p(double complex z) noexcept nogil:
     cdef double zr, zi, x, y, az, azi
     cdef np.npy_cdouble ret
 
@@ -65,7 +65,7 @@ cdef inline double complex clog1p(double complex z) nogil:
     ret = npy_clog(npy_cdouble_from_double_complex(z))
     return double_complex_from_npy_cdouble(ret)
 
-cdef inline double complex clog1p_ddouble(double zr, double zi) nogil:
+cdef inline double complex clog1p_ddouble(double zr, double zi) noexcept nogil:
     cdef double x, y
     cdef double2 r, i, two, rsqr, isqr, rtwo, absm1
 
@@ -90,7 +90,7 @@ cdef inline double complex clog1p_ddouble(double zr, double zi) nogil:
 # z.real = -log(cos(z.imag)).  There isn't a way around this problem  that
 # doesn't involve computing exp(z.real) and/or cos(z.imag) to higher
 # precision.
-cdef inline double complex cexpm1(double complex z) nogil:
+cdef inline double complex cexpm1(double complex z) noexcept nogil:
     cdef double zr, zi, ezr, x, y
     cdef np.npy_cdouble ret
 
diff --git a/scipy/special/_cython_special.pxi b/scipy/special/_cython_special.pxi
index b5e9270b..97ef1489 100644
--- a/scipy/special/_cython_special.pxi
+++ b/scipy/special/_cython_special.pxi
@@ -10,7 +10,7 @@ from numpy cimport (
 cdef extern from "numpy/ufuncobject.h":
     int PyUFunc_getfperr() nogil
 
-cdef public int wrap_PyUFunc_getfperr() nogil:
+cdef public int wrap_PyUFunc_getfperr() noexcept nogil:
     """
     Call PyUFunc_getfperr in a context where PyUFunc_API array is initialized;
     this avoids messing with the UNIQUE_SYMBOL #defines
diff --git a/scipy/special/_cython_special_custom.pxi b/scipy/special/_cython_special_custom.pxi
index 8769a892..7a479084 100644
--- a/scipy/special/_cython_special_custom.pxi
+++ b/scipy/special/_cython_special_custom.pxi
@@ -1,7 +1,7 @@
 from . cimport _spherical_bessel
 
 
-cpdef number_t spherical_jn(long n, number_t z, bint derivative=0) nogil:
+cpdef number_t spherical_jn(long n, number_t z, bint derivative=0) noexcept nogil:
     """See the documentation for scipy.special.spherical_jn"""
     if derivative:
         if number_t is double:
@@ -15,7 +15,7 @@ cpdef number_t spherical_jn(long n, number_t z, bint derivative=0) nogil:
         return _spherical_bessel.spherical_jn_complex(n, z)
 
 
-cpdef number_t spherical_yn(long n, number_t z, bint derivative=0) nogil:
+cpdef number_t spherical_yn(long n, number_t z, bint derivative=0) noexcept nogil:
     """See the documentation for scipy.special.spherical_yn"""
     if derivative:
         if number_t is double:
@@ -29,7 +29,7 @@ cpdef number_t spherical_yn(long n, number_t z, bint derivative=0) nogil:
         return _spherical_bessel.spherical_yn_complex(n, z)
 
 
-cpdef number_t spherical_in(long n, number_t z, bint derivative=0) nogil:
+cpdef number_t spherical_in(long n, number_t z, bint derivative=0) noexcept nogil:
     """See the documentation for scipy.special.spherical_in"""
     if derivative:
         if number_t is double:
@@ -43,7 +43,7 @@ cpdef number_t spherical_in(long n, number_t z, bint derivative=0) nogil:
         return _spherical_bessel.spherical_in_complex(n, z)
 
 
-cpdef number_t spherical_kn(long n, number_t z, bint derivative=0) nogil:
+cpdef number_t spherical_kn(long n, number_t z, bint derivative=0) noexcept nogil:
     """See the documentation for scipy.special.spherical_kn"""
     if derivative:
         if number_t is double:
diff --git a/scipy/special/_digamma.pxd b/scipy/special/_digamma.pxd
index fc1baffa..f3aefa29 100644
--- a/scipy/special/_digamma.pxd
+++ b/scipy/special/_digamma.pxd
@@ -36,7 +36,7 @@ DEF negroot = -0.504083008264455409
 DEF negrootval = 7.2897639029768949e-17
 
 
-cdef inline double digamma(double z) nogil:
+cdef inline double digamma(double z) noexcept nogil:
     """Wrap Cephes' psi to take advantage of the series expansion around
     the smallest negative zero.
 
@@ -48,7 +48,7 @@ cdef inline double digamma(double z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex cdigamma(double complex z) nogil:
+cdef inline double complex cdigamma(double complex z) noexcept nogil:
     """
     Compute the digamma function for complex arguments. The strategy
     is:
@@ -113,7 +113,7 @@ cdef inline double complex cdigamma(double complex z) nogil:
 @cython.cdivision(True)
 cdef inline double complex forward_recurrence(double complex z,
                                               double complex psiz,
-                                               int n) nogil:
+                                               int n) noexcept nogil:
     """
     Compute digamma(z + n) using digamma(z) using the recurrence
     relation
@@ -135,7 +135,7 @@ cdef inline double complex forward_recurrence(double complex z,
 @cython.cdivision(True)
 cdef inline double complex backward_recurrence(double complex z,
                                                double complex psiz,
-                                               int n) nogil:
+                                               int n) noexcept nogil:
     """
     Compute digamma(z - n) using digamma(z) and a recurrence
     relation.
@@ -151,7 +151,7 @@ cdef inline double complex backward_recurrence(double complex z,
 
 
 @cython.cdivision(True)
-cdef inline double complex asymptotic_series(double complex z) nogil:
+cdef inline double complex asymptotic_series(double complex z) noexcept nogil:
     """
     Evaluate digamma using an asymptotic series. See
 
@@ -185,7 +185,7 @@ cdef inline double complex asymptotic_series(double complex z) nogil:
     return res
 
 
-cdef inline number_t zeta_series(number_t z, double root, double rootval) nogil:
+cdef inline number_t zeta_series(number_t z, double root, double rootval) noexcept nogil:
     """
     The coefficients of the Taylor series for digamma at any point can
     be expressed in terms of the Hurwitz zeta function. If we
diff --git a/scipy/special/_ellip_harm.pxd b/scipy/special/_ellip_harm.pxd
index 4f83d05c..f980efd2 100644
--- a/scipy/special/_ellip_harm.pxd
+++ b/scipy/special/_ellip_harm.pxd
@@ -50,7 +50,7 @@ cdef extern from "lapack_defs.h":
 @cython.cdivision(True)
 cdef inline double* lame_coefficients(double h2, double k2, int n, int p,
                                       void **bufferp, double signm,
-                                      double signn) nogil:
+                                      double signn) noexcept nogil:
 
     # Ensure that the caller can safely call free(*bufferp) even if an
     # invalid argument is found in the following validation code.
@@ -183,7 +183,7 @@ cdef inline double* lame_coefficients(double h2, double k2, int n, int p,
 @cython.cdivision(True)
 cdef inline double ellip_harm_eval(double h2, double k2, int n, int p,
                                    double s, double *eigv, double signm,
-                                   double signn) nogil:
+                                   double signn) noexcept nogil:
     cdef int size, tp, r, j
     cdef double s2, pp, lambda_romain, psi
     s2 = s*s
@@ -210,7 +210,7 @@ cdef inline double ellip_harm_eval(double h2, double k2, int n, int p,
 
 
 cdef inline double ellip_harmonic(double h2, double k2, int n, int p, double s,
-                                  double signm, double signn) nogil:
+                                  double signm, double signn) noexcept nogil:
     cdef double result
     cdef double *eigv
     cdef void *bufferp
diff --git a/scipy/special/_ellip_harm_2.pyx b/scipy/special/_ellip_harm_2.pyx
index 5b7010b1..38582858 100644
--- a/scipy/special/_ellip_harm_2.pyx
+++ b/scipy/special/_ellip_harm_2.pyx
@@ -13,7 +13,7 @@ ctypedef struct _ellip_data_t:
     double h2, k2
     int n, p
 
-cdef double _F_integrand(double t, void *user_data) nogil:
+cdef double _F_integrand(double t, void *user_data) noexcept nogil:
     cdef _ellip_data_t *data = <_ellip_data_t *>user_data
     cdef double h2, k2, t2, i, result
     cdef int n, p
@@ -28,7 +28,7 @@ cdef double _F_integrand(double t, void *user_data) nogil:
     result = 1/(i*i*sqrt(1 - t2*k2)*sqrt(1 - t2*h2))
     return result
 
-cdef double _F_integrand1(double t, void *user_data) nogil:
+cdef double _F_integrand1(double t, void *user_data) noexcept nogil:
     cdef _ellip_data_t *data = <_ellip_data_t *>user_data
     cdef double h2, k2, i, h, result
     cdef int n, p
@@ -45,7 +45,7 @@ cdef double _F_integrand1(double t, void *user_data) nogil:
     result = i*i/sqrt((t + h)*(t + k))
     return result
 
-cdef double _F_integrand2(double t, void *user_data) nogil:
+cdef double _F_integrand2(double t, void *user_data) noexcept nogil:
     cdef _ellip_data_t *data = <_ellip_data_t *>user_data
     cdef double h2, k2, t2, i, h, result
     cdef int n, p
@@ -63,7 +63,7 @@ cdef double _F_integrand2(double t, void *user_data) nogil:
     result = t2*i*i/sqrt((t + h)*(t + k))
     return result
 
-cdef double _F_integrand3(double t, void *user_data) nogil:
+cdef double _F_integrand3(double t, void *user_data) noexcept nogil:
     cdef _ellip_data_t *data = <_ellip_data_t *>user_data
     cdef double h2, k2, t2, i, h, result
     cdef int n, p
@@ -80,7 +80,7 @@ cdef double _F_integrand3(double t, void *user_data) nogil:
     result = i*i/sqrt((t + h)*(k2 - t2))
     return result
 
-cdef double _F_integrand4(double t, void *user_data) nogil:
+cdef double _F_integrand4(double t, void *user_data) noexcept nogil:
     cdef _ellip_data_t *data = <_ellip_data_t *>user_data
     cdef double h2, k2, t2, i, h, result
     cdef int n, p
@@ -192,7 +192,7 @@ np.import_ufunc()
 cdef extern from "numpy/ufuncobject.h":
     int PyUFunc_getfperr() nogil
 
-cdef public int wrap_PyUFunc_getfperr() nogil:
+cdef public int wrap_PyUFunc_getfperr() noexcept nogil:
     """
     Call PyUFunc_getfperr in a context where PyUFunc_API array is initialized;
     this avoids messing with the UNIQUE_SYMBOL #defines
diff --git a/scipy/special/_ellipk.pxd b/scipy/special/_ellipk.pxd
index 55c2f094..fc170327 100644
--- a/scipy/special/_ellipk.pxd
+++ b/scipy/special/_ellipk.pxd
@@ -1,5 +1,5 @@
 from ._cephes cimport ellpk
 
 
-cdef inline double ellipk(double m) nogil:
+cdef inline double ellipk(double m) noexcept nogil:
     return ellpk(1.0 - m)
diff --git a/scipy/special/_evalpoly.pxd b/scipy/special/_evalpoly.pxd
index c1d76aaf..e6a5b552 100644
--- a/scipy/special/_evalpoly.pxd
+++ b/scipy/special/_evalpoly.pxd
@@ -18,7 +18,7 @@ from ._complexstuff cimport zabs
 
 
 cdef inline double complex cevalpoly(double *coeffs, int degree,
-                                     double complex z) nogil:
+                                     double complex z) noexcept nogil:
     """Evaluate a polynomial with real coefficients at a complex point.
 
     Uses equation (3) in section 4.6.4 of [1]. Note that it is more
diff --git a/scipy/special/_exprel.pxd b/scipy/special/_exprel.pxd
index c8660189..66f5acdd 100644
--- a/scipy/special/_exprel.pxd
+++ b/scipy/special/_exprel.pxd
@@ -1,6 +1,6 @@
 from libc.math cimport expm1, fabs, log, INFINITY
 
-cdef inline double exprel(double x) nogil:
+cdef inline double exprel(double x) noexcept nogil:
     if fabs(x) < 1e-16:
         return 1.0
     elif x > 717:  # near log(DBL_MAX)
diff --git a/scipy/special/_factorial.pxd b/scipy/special/_factorial.pxd
index f28b732c..5b65cf30 100644
--- a/scipy/special/_factorial.pxd
+++ b/scipy/special/_factorial.pxd
@@ -1,7 +1,7 @@
 from ._cephes cimport Gamma
 
 
-cdef inline double _factorial(double n) nogil:
+cdef inline double _factorial(double n) noexcept nogil:
     if n < 0:
         return 0
     else:
diff --git a/scipy/special/_generate_pyx.py b/scipy/special/_generate_pyx.py
index 8e3e49db..ad5532ff 100644
--- a/scipy/special/_generate_pyx.py
+++ b/scipy/special/_generate_pyx.py
@@ -100,10 +100,10 @@ ctypedef fused number_t:
     double complex
     double
 
-cpdef number_t spherical_jn(long n, number_t z, bint derivative=*) nogil
-cpdef number_t spherical_yn(long n, number_t z, bint derivative=*) nogil
-cpdef number_t spherical_in(long n, number_t z, bint derivative=*) nogil
-cpdef number_t spherical_kn(long n, number_t z, bint derivative=*) nogil
+cpdef number_t spherical_jn(long n, number_t z, bint derivative=*) noexcept nogil
+cpdef number_t spherical_yn(long n, number_t z, bint derivative=*) noexcept nogil
+cpdef number_t spherical_in(long n, number_t z, bint derivative=*) noexcept nogil
+cpdef number_t spherical_kn(long n, number_t z, bint derivative=*) noexcept nogil
 """
 
 CYTHON_SPECIAL_PYX = """\
@@ -371,7 +371,7 @@ def generate_loop(func_inputs, func_outputs, func_retval,
     name = "loop_%s_%s_%s_As_%s_%s" % (
         func_retval, func_inputs, func_outputs, ufunc_inputs, ufunc_outputs
         )
-    body = "cdef void %s(char **args, np.npy_intp *dims, np.npy_intp *steps, void *data) nogil:\n" % name
+    body = "cdef void %s(char **args, np.npy_intp *dims, np.npy_intp *steps, void *data) noexcept nogil:\n" % name
     body += "    cdef np.npy_intp i, n = dims[0]\n"
     body += "    cdef void *func = (<void**>data)[0]\n"
     body += "    cdef char *func_name = <char*>(<void**>data)[1]\n"
@@ -409,7 +409,7 @@ def generate_loop(func_inputs, func_outputs, func_retval,
     else:
         rv = ""
 
-    funcall = "        %s(<%s(*)(%s) nogil>func)(%s)\n" % (
+    funcall = "        %s(<%s(*)(%s) noexcept nogil>func)(%s)\n" % (
         rv, CY_TYPES[func_retval], ", ".join(ftypes), ", ".join(fvars))
 
     # Cast-check inputs and call function
@@ -629,7 +629,7 @@ class Func:
             if header.endswith("h") and nptypes_for_h:
                 cy_proto = c_proto + "nogil"
             else:
-                cy_proto = "%s (*)(%s) nogil" % (CY_TYPES[ret], ", ".join(cy_args))
+                cy_proto = "%s (*)(%s) noexcept nogil" % (CY_TYPES[ret], ", ".join(cy_args))
             prototypes.append((func_name, c_proto, cy_proto, header))
         return prototypes
 
@@ -1013,7 +1013,7 @@ class FusedFunc(Func):
             # Functions from _ufuncs_cxx are exported as a void*
             # pointers; cast them to the correct types
             func_name = "scipy.special._ufuncs_cxx._export_{}".format(func_name)
-            func_name = "(<{}(*)({}) nogil>{})"\
+            func_name = "(<{}(*)({}) noexcept nogil>{})"\
                     .format(rettype, ", ".join(intypes + outtypes), func_name)
         else:
             func_name = self.cython_func_name(func_name, specialized=True)
@@ -1126,9 +1126,9 @@ class FusedFunc(Func):
                 callvars.append("{} *{}".format(outtype, outvar))
         if len(self.outvars) == 1:
             outtype, _ = self.outtypes[0]
-            dec = "cpdef {} {}({}) nogil".format(outtype, self.name, ", ".join(callvars))
+            dec = "cpdef {} {}({}) noexcept nogil".format(outtype, self.name, ", ".join(callvars))
         else:
-            dec = "cdef void {}({}) nogil".format(self.name, ", ".join(callvars))
+            dec = "cdef void {}({}) noexcept nogil".format(self.name, ", ".join(callvars))
         head.append(dec + ":")
         head.append(tab + '"""{}"""'.format(self.doc))
         if len(self.outvars) == 1:
@@ -1174,7 +1174,7 @@ class FusedFunc(Func):
             callvars.append("{} {}".format(intype, invar))
         for outvar, (outtype, _) in zip(self.outvars, self.outtypes):
             callvars.append("{} *{}".format(outtype, outvar))
-        dec = "cdef void {}({}) nogil".format(self.name, ", ".join(callvars))
+        dec = "cdef void {}({}) noexcept nogil".format(self.name, ", ".join(callvars))
         head.append(dec + ":")
         head.append(tab + '"""{}"""'.format(self.doc))
         head.extend(self._get_tmp_decs(all_tmpvars))
@@ -1259,7 +1259,7 @@ def generate_ufuncs(fn_prefix, cxx_fn_prefix, ufuncs):
     cxx_defs = []
     cxx_pxd_defs = [
         "from . cimport sf_error",
-        "cdef void _set_action(sf_error.sf_error_t, sf_error.sf_action_t) nogil"
+        "cdef void _set_action(sf_error.sf_error_t, sf_error.sf_action_t) noexcept nogil"
     ]
     cxx_defs_h = []
 
diff --git a/scipy/special/_hyp0f1.pxd b/scipy/special/_hyp0f1.pxd
index baacca8c..e12088fd 100644
--- a/scipy/special/_hyp0f1.pxd
+++ b/scipy/special/_hyp0f1.pxd
@@ -20,7 +20,7 @@ cdef extern from "amos_wrappers.h":
 #
 # Real-valued kernel
 #
-cdef inline double _hyp0f1_real(double v, double z) nogil:
+cdef inline double _hyp0f1_real(double v, double z) noexcept nogil:
     cdef double arg, v1, arg_exp, bess_val
 
     # handle poles, zeros
@@ -48,7 +48,7 @@ cdef inline double _hyp0f1_real(double v, double z) nogil:
         return pow(arg, 1.0 - v) * Gamma(v) * jv(v - 1, 2*arg)
 
 
-cdef inline double _hyp0f1_asy(double v, double z) nogil:
+cdef inline double _hyp0f1_asy(double v, double z) noexcept nogil:
     r"""Asymptotic expansion for I_{v-1}(2*sqrt(z)) * Gamma(v)
     for real $z > 0$ and $v\to +\infty$.
 
@@ -95,7 +95,7 @@ cdef inline double _hyp0f1_asy(double v, double z) nogil:
 #
 # Complex valued kernel
 #
-cdef inline double complex _hyp0f1_cmplx(double v, double complex z) nogil:
+cdef inline double complex _hyp0f1_cmplx(double v, double complex z) noexcept nogil:
     cdef:
         np.npy_cdouble zz = npy_cdouble_from_double_complex(z)
         np.npy_cdouble r
diff --git a/scipy/special/_hyp2f1.pxd b/scipy/special/_hyp2f1.pxd
index 14181b80..febdb049 100644
--- a/scipy/special/_hyp2f1.pxd
+++ b/scipy/special/_hyp2f1.pxd
@@ -81,7 +81,7 @@ DEF LOG_PI_2 = 0.5723649429247001  # log(M_PI) / 2
 @cython.cdivision(True)
 cdef inline double complex hyp2f1_complex(
         double a, double b, double c, double complex z
-) nogil:
+) noexcept nogil:
     cdef:
         double modulus_z
         double max_degree
@@ -231,7 +231,7 @@ cdef inline double complex hyp2f1_series(
         uint64_t max_degree,
         bint early_stop,
         double rtol,
-) nogil:
+) noexcept nogil:
     """Return Truncated Maclaurin series for hyp2f1.
 
     Series is convergent for |z| < 1 but is only practical for numerical
@@ -286,7 +286,7 @@ cdef inline double complex hyp2f1_lopez_temme_series(
         double complex z,
         int max_degree,
         double rtol,
-) nogil:
+) noexcept nogil:
     """Lopez-Temme Series for Gaussian hypergeometric function [4].
 
     Converges for all z with real(z) < 1, including in the regions surrounding
@@ -321,7 +321,7 @@ cdef inline double complex hyp2f1_lopez_temme_series(
 
 
 @cython.cdivision(True)
-cdef inline double four_gammas(double u, double v, double w, double x) nogil:
+cdef inline double four_gammas(double u, double v, double w, double x) noexcept nogil:
     cdef double result
     # Without loss of generality, assume |u| >= |v|, |w| >= |x|.
     if fabs(v) > fabs(u):
@@ -350,7 +350,7 @@ cdef inline double four_gammas(double u, double v, double w, double x) nogil:
 @cython.cdivision(True)
 cdef inline double four_gammas_lanczos(
         double u, double v, double w, double x
-) nogil:
+) noexcept nogil:
     """Compute ratio of gamma functions using lanczos approximation.
 
     Computes gamma(u)*gamma(v)/(gamma(w)*gamma(x))
diff --git a/scipy/special/_hypergeometric.pxd b/scipy/special/_hypergeometric.pxd
index e2df5bef..df88d8b8 100644
--- a/scipy/special/_hypergeometric.pxd
+++ b/scipy/special/_hypergeometric.pxd
@@ -13,7 +13,7 @@ DEF ACCEPTABLE_RTOL = 1e-7
 
 
 @cython.cdivision(True)
-cdef inline double hyperu(double a, double b, double x) nogil:
+cdef inline double hyperu(double a, double b, double x) noexcept nogil:
     if isnan(a) or isnan(b) or isnan(x):
         return NAN
 
diff --git a/scipy/special/_lambertw.pxd b/scipy/special/_lambertw.pxd
index 3d601f7b..566b5e0d 100644
--- a/scipy/special/_lambertw.pxd
+++ b/scipy/special/_lambertw.pxd
@@ -31,7 +31,7 @@ DEF OMEGA = 0.56714329040978387299997  # W(1, 0)
 
 
 @cython.cdivision(True)
-cdef inline double complex lambertw_scalar(double complex z, long k, double tol) nogil:
+cdef inline double complex lambertw_scalar(double complex z, long k, double tol) noexcept nogil:
     cdef int i
     cdef double absz, p
     cdef double complex w
@@ -101,7 +101,7 @@ cdef inline double complex lambertw_scalar(double complex z, long k, double tol)
 
 
 @cython.cdivision(True)
-cdef inline double complex lambertw_branchpt(double complex z) nogil:
+cdef inline double complex lambertw_branchpt(double complex z) noexcept nogil:
     """Series for W(z, 0) around the branch point; see 4.22 in [1]."""
     cdef double *coeffs = [-1.0/3.0, 1.0, -1.0]
     cdef double complex p = zsqrt(2*(M_E*z + 1))
@@ -110,7 +110,7 @@ cdef inline double complex lambertw_branchpt(double complex z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex lambertw_pade0(double complex z) nogil:
+cdef inline double complex lambertw_pade0(double complex z) noexcept nogil:
     """(3, 2) Pade approximation for W(z, 0) around 0."""
     cdef:
         double *num = [
@@ -131,7 +131,7 @@ cdef inline double complex lambertw_pade0(double complex z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex lambertw_asy(double complex z, long k) nogil:
+cdef inline double complex lambertw_asy(double complex z, long k) noexcept nogil:
     """Compute the W function using the first two terms of the
     asymptotic series. See 4.20 in [1].
 
diff --git a/scipy/special/_legacy.pxd b/scipy/special/_legacy.pxd
index a97f56dc..6992b1a1 100644
--- a/scipy/special/_legacy.pxd
+++ b/scipy/special/_legacy.pxd
@@ -23,21 +23,21 @@ cdef extern from "Python.h":
     # Purposefully ignore the raised PyError --- assume the ufunc will collect it
     int PyErr_WarnEx_noerr "PyErr_WarnEx" (object, char *, int)
 
-cdef inline void _legacy_cast_check(char *func_name, double x, double y) nogil:
+cdef inline void _legacy_cast_check(char *func_name, double x, double y) noexcept nogil:
     if <int>x != x or <int>y != y:
         with gil:
             PyErr_WarnEx_noerr(RuntimeWarning,
                                "floating point number truncated to an integer",
                                1)
 
-cdef inline void _legacy_deprecation(char *func_name, double x, double y) nogil:
+cdef inline void _legacy_deprecation(char *func_name, double x, double y) noexcept nogil:
         with gil:
             PyErr_WarnEx_noerr(DeprecationWarning,
                                "non-integer arg n is deprecated, removed in SciPy 1.7.x",
                                1)
 
 cdef inline double complex sph_harmonic_unsafe(double m, double n,
-                                               double theta, double phi) nogil:
+                                               double theta, double phi) noexcept nogil:
     if isnan(m) or isnan(n):
         return NAN
     _legacy_cast_check("sph_harm", m, n)
@@ -45,100 +45,100 @@ cdef inline double complex sph_harmonic_unsafe(double m, double n,
 
 cdef inline double ellip_harmonic_unsafe(double h2, double k2, double n,
                                          double p, double l, double signm,
-                                         double signn) nogil:
+                                         double signn) noexcept nogil:
     if isnan(n) or isnan(p):
         return NAN
     _legacy_cast_check("_ellip_harm", n, p)
     return ellip_harmonic(h2, k2, <int>n, <int>p, l, signm, signn)
 
-cdef inline double bdtr_unsafe(double k, double n, double p) nogil:
+cdef inline double bdtr_unsafe(double k, double n, double p) noexcept nogil:
     _legacy_deprecation("bdtr", k, n)
     if isnan(n) or isinf(n):
         return NAN
     else:
         return bdtr(k, <int>n, p)
 
-cdef inline double bdtrc_unsafe(double k, double n, double p) nogil:
+cdef inline double bdtrc_unsafe(double k, double n, double p) noexcept nogil:
     _legacy_deprecation("bdtrc", k, n)
     if isnan(n) or isinf(n):
         return NAN
     else:
         return bdtrc(k, <int>n, p)
 
-cdef inline double bdtri_unsafe(double k, double n, double p) nogil:
+cdef inline double bdtri_unsafe(double k, double n, double p) noexcept nogil:
     _legacy_deprecation("bdtri", k, n)
     if isnan(n) or isinf(n):
         return NAN
     else:
         return bdtri(k, <int>n, p)
 
-cdef inline double expn_unsafe(double n, double x) nogil:
+cdef inline double expn_unsafe(double n, double x) noexcept nogil:
     if isnan(n):
         return n
     _legacy_cast_check("expn", n, 0)
     return expn(<int>n, x)
 
-cdef inline double nbdtrc_unsafe(double k, double n, double p) nogil:
+cdef inline double nbdtrc_unsafe(double k, double n, double p) noexcept nogil:
     if isnan(k) or isnan(n):
         return NAN
     _legacy_cast_check("nbdtrc", k, n)
     return nbdtrc(<int>k, <int>n, p)
 
-cdef inline double nbdtr_unsafe(double k, double n, double p)  nogil:
+cdef inline double nbdtr_unsafe(double k, double n, double p) noexcept nogil:
     if isnan(k) or isnan(n):
         return NAN
     _legacy_cast_check("nbdtr", k, n)
     return nbdtr(<int>k, <int>n, p)
 
-cdef inline double nbdtri_unsafe(double k, double n, double p) nogil:
+cdef inline double nbdtri_unsafe(double k, double n, double p) noexcept nogil:
     if isnan(k) or isnan(n):
         return NAN
     _legacy_cast_check("nbdtri", k, n)
     return nbdtri(<int>k, <int>n, p)
 
-cdef inline double pdtri_unsafe(double k, double y) nogil:
+cdef inline double pdtri_unsafe(double k, double y) noexcept nogil:
     if isnan(k):
         return k
     _legacy_cast_check("pdtri", k, 0)
     return pdtri(<int>k, y)
 
-cdef inline double kn_unsafe(double n, double x) nogil:
+cdef inline double kn_unsafe(double n, double x) noexcept nogil:
     if isnan(n):
         return n
     _legacy_cast_check("kn", n, 0)
     return cbesk_wrap_real_int(<int>n, x)
 
-cdef inline double yn_unsafe(double n, double x) nogil:
+cdef inline double yn_unsafe(double n, double x) noexcept nogil:
     if isnan(n):
         return n
     _legacy_cast_check("yn", n, 0)
     return yn(<int>n, x)
 
-cdef inline double smirnov_unsafe(double n, double e) nogil:
+cdef inline double smirnov_unsafe(double n, double e) noexcept nogil:
     if isnan(n):
         return n
     _legacy_cast_check("smirnov", n, 0)
     return smirnov(<int>n, e)
 
-cdef inline double smirnovc_unsafe(double n, double e) nogil:
+cdef inline double smirnovc_unsafe(double n, double e) noexcept nogil:
     if isnan(n):
         return n
     _legacy_cast_check("smirnovc", n, 0)
     return smirnovc(<int>n, e)
 
-cdef inline double smirnovp_unsafe(double n, double e) nogil:
+cdef inline double smirnovp_unsafe(double n, double e) noexcept nogil:
     if isnan(n):
         return n
     _legacy_cast_check("smirnovp", n, 0)
     return smirnovp(<int>n, e)
 
-cdef inline double smirnovi_unsafe(double n, double p) nogil:
+cdef inline double smirnovi_unsafe(double n, double p) noexcept nogil:
     if isnan(n):
         return n
     _legacy_cast_check("smirnovi", n, 0)
     return smirnovi(<int>n, p)
 
-cdef inline double smirnovci_unsafe(double n, double p) nogil:
+cdef inline double smirnovci_unsafe(double n, double p) noexcept nogil:
     if isnan(n):
         return n
     _legacy_cast_check("smirnovci", n, 0)
diff --git a/scipy/special/_loggamma.pxd b/scipy/special/_loggamma.pxd
index c2f91074..bd730147 100644
--- a/scipy/special/_loggamma.pxd
+++ b/scipy/special/_loggamma.pxd
@@ -35,7 +35,7 @@ DEF SMALLY = 7
 DEF TAYLOR_RADIUS = 0.2
 
 
-cdef inline double loggamma_real(double x) nogil:
+cdef inline double loggamma_real(double x) noexcept nogil:
     if x < 0.0:
         return NAN
 
@@ -43,7 +43,7 @@ cdef inline double loggamma_real(double x) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex loggamma(double complex z) nogil:
+cdef inline double complex loggamma(double complex z) noexcept nogil:
     """Compute the principal branch of log-Gamma."""
     cdef double tmp
 
@@ -71,7 +71,7 @@ cdef inline double complex loggamma(double complex z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex loggamma_recurrence(double complex z) nogil:
+cdef inline double complex loggamma_recurrence(double complex z) noexcept nogil:
     """Backward recurrence relation.
 
     See Proposition 2.2 in [1] and the Julia implementation [2].
@@ -94,7 +94,7 @@ cdef inline double complex loggamma_recurrence(double complex z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex loggamma_stirling(double complex z) nogil:
+cdef inline double complex loggamma_stirling(double complex z) noexcept nogil:
     """Stirling series for log-Gamma.
 
     The coefficients are B[2*n]/(2*n*(2*n - 1)) where B[2*n] is the
@@ -115,7 +115,7 @@ cdef inline double complex loggamma_stirling(double complex z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex loggamma_taylor(double complex z) nogil:
+cdef inline double complex loggamma_taylor(double complex z) noexcept nogil:
     """Taylor series for log-Gamma around z = 1.
 
     It is
@@ -145,7 +145,7 @@ cdef inline double complex loggamma_taylor(double complex z) nogil:
     return z*cevalpoly(coeffs, 22, z)
 
 
-cdef inline double complex cgamma(double complex z) nogil:
+cdef inline double complex cgamma(double complex z) noexcept nogil:
     """Compute Gamma(z) using loggamma."""
     if z.real <= 0 and z == floor(z.real):
         # Poles
@@ -154,7 +154,7 @@ cdef inline double complex cgamma(double complex z) nogil:
     return zexp(loggamma(z))
 
 
-cdef inline double complex crgamma(double complex z) nogil:
+cdef inline double complex crgamma(double complex z) noexcept nogil:
     """Compute 1/Gamma(z) using loggamma."""
     if z.real <= 0 and z == floor(z.real):
         # Zeros at 0, -1, -2, ...
diff --git a/scipy/special/_ndtri_exp.pxd b/scipy/special/_ndtri_exp.pxd
index 14a7a889..72c33eb2 100644
--- a/scipy/special/_ndtri_exp.pxd
+++ b/scipy/special/_ndtri_exp.pxd
@@ -109,7 +109,7 @@ cdef extern from "cephes/polevl.h":
 from ._cephes cimport ndtri
 
 @cython.cdivision(True)
-cdef inline double _ndtri_exp_small_y(double y) nogil:
+cdef inline double _ndtri_exp_small_y(double y) noexcept nogil:
     """Return inverse of log CDF of normal distribution for very small y
 
     For p sufficiently small, the inverse of the CDF of the normal
@@ -160,7 +160,7 @@ cdef inline double _ndtri_exp_small_y(double y) nogil:
     return x1 - x0
 
 
-cdef inline double ndtri_exp(double y) nogil:
+cdef inline double ndtri_exp(double y) noexcept nogil:
     """Return inverse of logarithm of Normal CDF evaluated at y."""
     if y < -DBL_MAX:
         return -INFINITY
diff --git a/scipy/special/_sici.pxd b/scipy/special/_sici.pxd
index 5250283c..d1aa0478 100644
--- a/scipy/special/_sici.pxd
+++ b/scipy/special/_sici.pxd
@@ -24,7 +24,7 @@ DEF TOL = 2.220446092504131e-16
 DEF EULER = 0.577215664901532860606512090082402431  # Euler constant
     
 
-cdef inline double complex zexpi(double complex z) nogil:
+cdef inline double complex zexpi(double complex z) noexcept nogil:
     cdef np.npy_cdouble r
     r = cexpi_wrap(npy_cdouble_from_double_complex(z))
     return double_complex_from_npy_cdouble(r)
@@ -32,7 +32,7 @@ cdef inline double complex zexpi(double complex z) nogil:
 
 @cython.cdivision(True)
 cdef inline void power_series(int sgn, double complex z,
-                             double complex *s, double complex *c) nogil:
+                             double complex *s, double complex *c) noexcept nogil:
     """DLMF 6.6.5 and 6.6.6. If sgn = -1 computes si/ci, and if sgn = 1
     computes shi/chi.
 
@@ -56,7 +56,7 @@ cdef inline void power_series(int sgn, double complex z,
 
     
 cdef inline int csici(double complex z,
-                      double complex *si, double complex *ci) nogil:
+                      double complex *si, double complex *ci) noexcept nogil:
     """Compute sin/cos integrals at complex arguments. The algorithm
     largely follows that of [1].
 
@@ -105,7 +105,7 @@ cdef inline int csici(double complex z,
 
 
 cdef inline int cshichi(double complex z,
-                        double complex *shi, double complex *chi) nogil:
+                        double complex *shi, double complex *chi) noexcept nogil:
     """Compute sinh/cosh integrals at complex arguments. The algorithm
     largely follows that of [1].
 
diff --git a/scipy/special/_spence.pxd b/scipy/special/_spence.pxd
index 73ed675e..2525629a 100644
--- a/scipy/special/_spence.pxd
+++ b/scipy/special/_spence.pxd
@@ -20,7 +20,7 @@ DEF PISQ_6 = 1.6449340668482264365
 
 
 @cython.cdivision(True)
-cdef inline double complex cspence(double complex z) nogil:
+cdef inline double complex cspence(double complex z) noexcept nogil:
     """
     Compute Spence's function for complex arguments. The strategy is:
     - If z is close to 0, use a series centered at 0.
@@ -42,7 +42,7 @@ cdef inline double complex cspence(double complex z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex cspence_series0(double complex z) nogil:
+cdef inline double complex cspence_series0(double complex z) noexcept nogil:
     """
     A series centered at z = 0; see
 
@@ -71,7 +71,7 @@ cdef inline double complex cspence_series0(double complex z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex cspence_series1(double complex z) nogil:
+cdef inline double complex cspence_series1(double complex z) noexcept nogil:
     """
     A series centered at z = 1 which enjoys faster convergence than
     the Taylor series. See [3]. The number of terms used comes from
diff --git a/scipy/special/_spherical_bessel.pxd b/scipy/special/_spherical_bessel.pxd
index 06e2610f..bbffbef8 100644
--- a/scipy/special/_spherical_bessel.pxd
+++ b/scipy/special/_spherical_bessel.pxd
@@ -43,7 +43,7 @@ from ._cephes cimport iv
 
 # Fused type wrappers
 
-cdef inline number_t cbesj(double v, number_t z) nogil:
+cdef inline number_t cbesj(double v, number_t z) noexcept nogil:
     cdef npy_cdouble r
     if number_t is double:
         return cbesj_wrap_real(v, z)
@@ -51,7 +51,7 @@ cdef inline number_t cbesj(double v, number_t z) nogil:
         r = cbesj_wrap(v, npy_cdouble_from_double_complex(z))
         return double_complex_from_npy_cdouble(r)
 
-cdef inline number_t cbesy(double v, number_t z) nogil:
+cdef inline number_t cbesy(double v, number_t z) noexcept nogil:
     cdef npy_cdouble r
     if number_t is double:
         return cbesy_wrap_real(v, z)
@@ -59,7 +59,7 @@ cdef inline number_t cbesy(double v, number_t z) nogil:
         r = cbesy_wrap(v, npy_cdouble_from_double_complex(z))
         return double_complex_from_npy_cdouble(r)
 
-cdef inline number_t cbesk(double v, number_t z) nogil:
+cdef inline number_t cbesk(double v, number_t z) noexcept nogil:
     cdef npy_cdouble r
     if number_t is double:
         return cbesk_wrap_real(v, z)
@@ -71,7 +71,7 @@ cdef inline number_t cbesk(double v, number_t z) nogil:
 # Spherical Bessel functions
 
 @cython.cdivision(True)
-cdef inline double spherical_jn_real(long n, double x) nogil:
+cdef inline double spherical_jn_real(long n, double x) noexcept nogil:
     cdef double s0, s1, sn
     cdef int idx
 
@@ -110,7 +110,7 @@ cdef inline double spherical_jn_real(long n, double x) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex spherical_jn_complex(long n, double complex z) nogil:
+cdef inline double complex spherical_jn_complex(long n, double complex z) noexcept nogil:
     cdef double complex out
     if zisnan(z):
         return z
@@ -139,7 +139,7 @@ cdef inline double complex spherical_jn_complex(long n, double complex z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double spherical_yn_real(long n, double x) nogil:
+cdef inline double spherical_yn_real(long n, double x) noexcept nogil:
     cdef double s0, s1, sn
     cdef int idx
 
@@ -174,7 +174,7 @@ cdef inline double spherical_yn_real(long n, double x) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex spherical_yn_complex(long n, double complex z) nogil:
+cdef inline double complex spherical_yn_complex(long n, double complex z) noexcept nogil:
 
     if zisnan(z):
         return z
@@ -195,7 +195,7 @@ cdef inline double complex spherical_yn_complex(long n, double complex z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double spherical_in_real(long n, double z) nogil:
+cdef inline double spherical_in_real(long n, double z) noexcept nogil:
 
     if isnan(z):
         return z
@@ -219,7 +219,7 @@ cdef inline double spherical_in_real(long n, double z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex spherical_in_complex(long n, double complex z) nogil:
+cdef inline double complex spherical_in_complex(long n, double complex z) noexcept nogil:
     cdef npy_cdouble s
 
     if zisnan(z):
@@ -248,7 +248,7 @@ cdef inline double complex spherical_in_complex(long n, double complex z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double spherical_kn_real(long n, double z) nogil:
+cdef inline double spherical_kn_real(long n, double z) noexcept nogil:
 
     if isnan(z):
         return z
@@ -268,7 +268,7 @@ cdef inline double spherical_kn_real(long n, double z) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex spherical_kn_complex(long n, double complex z) nogil:
+cdef inline double complex spherical_kn_complex(long n, double complex z) noexcept nogil:
 
     if zisnan(z):
         return z
@@ -293,7 +293,7 @@ cdef inline double complex spherical_kn_complex(long n, double complex z) nogil:
 # Derivatives
 
 @cython.cdivision(True)
-cdef inline double spherical_jn_d_real(long n, double x) nogil:
+cdef inline double spherical_jn_d_real(long n, double x) noexcept nogil:
     if n == 0:
         return -spherical_jn_real(1, x)
     else:
@@ -310,7 +310,7 @@ cdef inline double spherical_jn_d_real(long n, double x) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex spherical_jn_d_complex(long n, double complex x) nogil:
+cdef inline double complex spherical_jn_d_complex(long n, double complex x) noexcept nogil:
     if n == 0:
         return -spherical_jn_complex(1, x)
     else:
@@ -319,7 +319,7 @@ cdef inline double complex spherical_jn_d_complex(long n, double complex x) nogi
 
 
 @cython.cdivision(True)
-cdef inline double spherical_yn_d_real(long n, double x) nogil:
+cdef inline double spherical_yn_d_real(long n, double x) noexcept nogil:
     if n == 0:
         return -spherical_yn_real(1, x)
     else:
@@ -328,7 +328,7 @@ cdef inline double spherical_yn_d_real(long n, double x) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex spherical_yn_d_complex(long n, double complex x) nogil:
+cdef inline double complex spherical_yn_d_complex(long n, double complex x) noexcept nogil:
     if n == 0:
         return -spherical_yn_complex(1, x)
     else:
@@ -337,7 +337,7 @@ cdef inline double complex spherical_yn_d_complex(long n, double complex x) nogi
 
 
 @cython.cdivision(True)
-cdef inline double spherical_in_d_real(long n, double x) nogil:
+cdef inline double spherical_in_d_real(long n, double x) noexcept nogil:
     if n == 0:
         return spherical_in_real(1, x)
     else:
@@ -348,7 +348,7 @@ cdef inline double spherical_in_d_real(long n, double x) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex spherical_in_d_complex(long n, double complex x) nogil:
+cdef inline double complex spherical_in_d_complex(long n, double complex x) noexcept nogil:
     if n == 0:
         return spherical_in_complex(1, x)
     else:
@@ -359,7 +359,7 @@ cdef inline double complex spherical_in_d_complex(long n, double complex x) nogi
 
 
 @cython.cdivision(True)
-cdef inline double spherical_kn_d_real(long n, double x) nogil:
+cdef inline double spherical_kn_d_real(long n, double x) noexcept nogil:
     if n == 0:
         return -spherical_kn_real(1, x)
     else:
@@ -368,7 +368,7 @@ cdef inline double spherical_kn_d_real(long n, double x) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double complex spherical_kn_d_complex(long n, double complex x) nogil:
+cdef inline double complex spherical_kn_d_complex(long n, double complex x) noexcept nogil:
     if n == 0:
         return -spherical_kn_complex(1, x)
     else:
diff --git a/scipy/special/_trig.pxd b/scipy/special/_trig.pxd
index f7cdc9cb..d4d031af 100644
--- a/scipy/special/_trig.pxd
+++ b/scipy/special/_trig.pxd
@@ -11,7 +11,7 @@ from ._cephes cimport sinpi as dsinpi, cospi as dcospi
 from ._complexstuff cimport number_t, double_complex, zpack
 
 
-cdef inline double complex csinpi(double complex z) nogil:
+cdef inline double complex csinpi(double complex z) noexcept nogil:
     """Compute sin(pi*z) for complex arguments."""
     cdef:
         double x = z.real
@@ -50,7 +50,7 @@ cdef inline double complex csinpi(double complex z) nogil:
     return zpack(coshfac*exphpiy, sinhfac*exphpiy)
 
 
-cdef inline double complex ccospi(double complex z) nogil:
+cdef inline double complex ccospi(double complex z) noexcept nogil:
     """Compute cos(pi*z) for complex arguments."""
     cdef:
         double x = z.real
@@ -81,14 +81,14 @@ cdef inline double complex ccospi(double complex z) nogil:
     return zpack(coshfac*exphpiy, sinhfac*exphpiy)
 
 
-cdef inline number_t sinpi(number_t z) nogil:
+cdef inline number_t sinpi(number_t z) noexcept nogil:
     if number_t is double:
         return dsinpi(z)
     else:
         return csinpi(z)
 
 
-cdef inline number_t cospi(number_t z) nogil:
+cdef inline number_t cospi(number_t z) noexcept nogil:
     if number_t is double:
         return dcospi(z)
     else:
diff --git a/scipy/special/_ufuncs_extra_code_common.pxi b/scipy/special/_ufuncs_extra_code_common.pxi
index e6e9573e..95930004 100644
--- a/scipy/special/_ufuncs_extra_code_common.pxi
+++ b/scipy/special/_ufuncs_extra_code_common.pxi
@@ -12,7 +12,7 @@ ctypedef double complex double_complex
 cdef extern from "numpy/ufuncobject.h":
     int PyUFunc_getfperr() nogil
 
-cdef public int wrap_PyUFunc_getfperr() nogil:
+cdef public int wrap_PyUFunc_getfperr() noexcept nogil:
     """
     Call PyUFunc_getfperr in a context where PyUFunc_API array is initialized;
     this avoids messing with the UNIQUE_SYMBOL #defines
@@ -27,5 +27,5 @@ np.import_array()
 np.import_ufunc()
 
 cdef void _set_action(sf_error.sf_error_t code,
-                      sf_error.sf_action_t action) nogil:
+                      sf_error.sf_action_t action) noexcept nogil:
     sf_error.set_action(code, action)
diff --git a/scipy/special/_wright_bessel.pxd b/scipy/special/_wright_bessel.pxd
index 2f986a3a..815f6f31 100644
--- a/scipy/special/_wright_bessel.pxd
+++ b/scipy/special/_wright_bessel.pxd
@@ -39,7 +39,7 @@ DEF exp_inf = 709.78271289338403
 
 
 @cython.cdivision(True)
-cdef inline double _exp_rgamma(double x, double y) nogil:
+cdef inline double _exp_rgamma(double x, double y) noexcept nogil:
     """Compute exp(x) / gamma(y) = exp(x) * rgamma(y).
 
     This helper function avoids overflow by using the lanczos approximation
@@ -53,7 +53,7 @@ cdef inline double _exp_rgamma(double x, double y) nogil:
 
 @cython.cdivision(True)
 cdef inline double _wb_series(double a, double b, double x,
-    unsigned int nstart, unsigned int nstop) nogil:
+    unsigned int nstart, unsigned int nstop) noexcept nogil:
     """1. Taylor series expansion in x=0, for x <= 1
 
     Phi(a, b, x) = sum_k x^k / k! / Gamma(a*k+b)
@@ -82,7 +82,7 @@ cdef inline double _wb_series(double a, double b, double x,
 
 @cython.cdivision(True)
 cdef inline double _wb_large_a(double a, double b, double x,
-    unsigned int n) nogil:
+    unsigned int n) noexcept nogil:
     """2. Taylor series expansion in x=0, for large a.
 
     Phi(a, b, x) = sum_k x^k / k! / Gamma(a*k+b)
@@ -109,7 +109,7 @@ cdef inline double _wb_large_a(double a, double b, double x,
 
 
 @cython.cdivision(True)
-cdef inline double _wb_small_a(double a, double b, double x, int order) nogil:
+cdef inline double _wb_small_a(double a, double b, double x, int order) noexcept nogil:
     """3. Taylor series in a=0 up to order 5, for tiny a and not too large x
 
     Phi(a, b, x) = exp(x)/Gamma(b)
@@ -219,7 +219,7 @@ cdef inline double _wb_small_a(double a, double b, double x, int order) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double _wb_asymptotic(double a, double b, double x) nogil:
+cdef inline double _wb_asymptotic(double a, double b, double x) noexcept nogil:
     """4. Asymptotic expansion for large x up to order 8
 
     Phi(a, b, x) ~ Z^(1/2-b) * exp((1+a)/a * Z) * sum_k (-1)^k * C_k / Z^k
@@ -579,7 +579,7 @@ cdef inline double _wb_asymptotic(double a, double b, double x) nogil:
 
 @cython.cdivision(True)
 cdef inline double _Kmod(double eps, double a, double b, double x,
-                         double r) nogil:
+                         double r) noexcept nogil:
     """Compute integrand Kmod(eps, a, b, x, r) for Gauss-Laguerre quadrature.
 
     K(a, b, x, r+eps) = exp(-r-eps) * Kmod(eps, a, b, x, r)
@@ -592,7 +592,7 @@ cdef inline double _Kmod(double eps, double a, double b, double x,
 
 @cython.cdivision(True)
 cdef inline double _P(double eps, double a, double b, double x,
-                      double phi) nogil:
+                      double phi) noexcept nogil:
     """Compute integrand P for Gauss-Legendre quadrature.
 
     P(eps, a, b, x, phi) =
@@ -607,7 +607,7 @@ cdef inline double _P(double eps, double a, double b, double x,
 
 
 @cython.cdivision(True)
-cdef inline double wright_bessel_integral(double a, double b, double x) nogil:
+cdef inline double wright_bessel_integral(double a, double b, double x) noexcept nogil:
     """5. Integral representation
 
     K(a, b, x, r) = exp(-r + x * r^(-a) * cos(pi*a)) * r^(-b)
@@ -770,7 +770,7 @@ cdef inline double wright_bessel_integral(double a, double b, double x) nogil:
 
 
 @cython.cdivision(True)
-cdef inline double wright_bessel_scalar(double a, double b, double x) nogil:
+cdef inline double wright_bessel_scalar(double a, double b, double x) noexcept nogil:
     """Compute Wright's generalized Bessel function for scalar arguments.
 
     According to [1], it is an entire function defined as
diff --git a/scipy/special/_xlogy.pxd b/scipy/special/_xlogy.pxd
index a5866d3e..b9ddf300 100644
--- a/scipy/special/_xlogy.pxd
+++ b/scipy/special/_xlogy.pxd
@@ -3,13 +3,13 @@ from libc.math cimport log1p
 from ._complexstuff cimport zlog, zisnan, number_t
 from ._cunity cimport clog1p
 
-cdef inline number_t xlogy(number_t x, number_t y) nogil:
+cdef inline number_t xlogy(number_t x, number_t y) noexcept nogil:
     if x == 0 and not zisnan(y):
         return 0
     else:
         return x * zlog(y)
 
-cdef inline number_t xlog1py(number_t x, number_t y) nogil:
+cdef inline number_t xlog1py(number_t x, number_t y) noexcept nogil:
     if x == 0 and not zisnan(y):
         return 0
     else:
diff --git a/scipy/special/orthogonal_eval.pxd b/scipy/special/orthogonal_eval.pxd
index 764f1dd1..9d55bc71 100644
--- a/scipy/special/orthogonal_eval.pxd
+++ b/scipy/special/orthogonal_eval.pxd
@@ -43,7 +43,7 @@ cdef extern from "specfun_wrappers.h":
 
 # Fused type wrappers
 
-cdef inline number_t hyp2f1(double a, double b, double c, number_t z) nogil:
+cdef inline number_t hyp2f1(double a, double b, double c, number_t z) noexcept nogil:
     cdef npy_cdouble r
     if number_t is double:
         return hyp2f1_wrap(a, b, c, z)
@@ -51,7 +51,7 @@ cdef inline number_t hyp2f1(double a, double b, double c, number_t z) nogil:
         r = chyp2f1_wrap(a, b, c, npy_cdouble_from_double_complex(z))
         return double_complex_from_npy_cdouble(r)
 
-cdef inline number_t hyp1f1(double a, double b, number_t z) nogil:
+cdef inline number_t hyp1f1(double a, double b, number_t z) noexcept nogil:
     cdef npy_cdouble r
     if number_t is double:
         return hyp1f1_wrap(a, b, z)
@@ -65,7 +65,7 @@ cdef inline number_t hyp1f1(double a, double b, number_t z) nogil:
 #-----------------------------------------------------------------------------
 
 @cython.cdivision(True)
-cdef inline double binom(double n, double k) nogil:
+cdef inline double binom(double n, double k) noexcept nogil:
     cdef double kx, nx, num, den, dk, sgn
     cdef int i
 
@@ -129,7 +129,7 @@ cdef inline double binom(double n, double k) nogil:
 # Jacobi
 #-----------------------------------------------------------------------------
 
-cdef inline number_t eval_jacobi(double n, double alpha, double beta, number_t x) nogil:
+cdef inline number_t eval_jacobi(double n, double alpha, double beta, number_t x) noexcept nogil:
     cdef double a, b, c, d
     cdef number_t g
 
@@ -141,7 +141,7 @@ cdef inline number_t eval_jacobi(double n, double alpha, double beta, number_t x
     return d * hyp2f1(a, b, c, g)
 
 @cython.cdivision(True)
-cdef inline double eval_jacobi_l(long n, double alpha, double beta, double x) nogil:
+cdef inline double eval_jacobi_l(long n, double alpha, double beta, double x) noexcept nogil:
     cdef long kk
     cdef double p, d
     cdef double k, t
@@ -167,11 +167,11 @@ cdef inline double eval_jacobi_l(long n, double alpha, double beta, double x) no
 #-----------------------------------------------------------------------------
 
 @cython.cdivision(True)
-cdef inline number_t eval_sh_jacobi(double n, double p, double q, number_t x) nogil:
+cdef inline number_t eval_sh_jacobi(double n, double p, double q, number_t x) noexcept nogil:
     return eval_jacobi(n, p-q, q-1, 2*x-1) / binom(2*n + p - 1, n)
 
 @cython.cdivision(True)
-cdef inline double eval_sh_jacobi_l(long n, double p, double q, double x) nogil:
+cdef inline double eval_sh_jacobi_l(long n, double p, double q, double x) noexcept nogil:
     return eval_jacobi_l(n, p-q, q-1, 2*x-1) / binom(2*n + p - 1, n)
 
 #-----------------------------------------------------------------------------
@@ -179,7 +179,7 @@ cdef inline double eval_sh_jacobi_l(long n, double p, double q, double x) nogil:
 #-----------------------------------------------------------------------------
 
 @cython.cdivision(True)
-cdef inline number_t eval_gegenbauer(double n, double alpha, number_t x) nogil:
+cdef inline number_t eval_gegenbauer(double n, double alpha, number_t x) noexcept nogil:
     cdef double a, b, c, d
     cdef number_t g
 
@@ -191,7 +191,7 @@ cdef inline number_t eval_gegenbauer(double n, double alpha, number_t x) nogil:
     return d * hyp2f1(a, b, c, g)
 
 @cython.cdivision(True)
-cdef inline double eval_gegenbauer_l(long n, double alpha, double x) nogil:
+cdef inline double eval_gegenbauer_l(long n, double alpha, double x) noexcept nogil:
     cdef long kk
     cdef long a, b
     cdef double p, d
@@ -247,7 +247,7 @@ cdef inline double eval_gegenbauer_l(long n, double alpha, double x) nogil:
 # Chebyshev 1st kind (T)
 #-----------------------------------------------------------------------------
 
-cdef inline number_t eval_chebyt(double n, number_t x) nogil:
+cdef inline number_t eval_chebyt(double n, number_t x) noexcept nogil:
     cdef double a, b, c, d
     cdef number_t g
 
@@ -258,7 +258,7 @@ cdef inline number_t eval_chebyt(double n, number_t x) nogil:
     g = 0.5*(1-x)
     return hyp2f1(a, b, c, g)
 
-cdef inline double eval_chebyt_l(long k, double x) nogil:
+cdef inline double eval_chebyt_l(long k, double x) noexcept nogil:
     # Use Chebyshev T recurrence directly, see [MH]
     cdef long m
     cdef double b2, b1, b0
@@ -281,7 +281,7 @@ cdef inline double eval_chebyt_l(long k, double x) nogil:
 # Chebyshev 2st kind (U)
 #-----------------------------------------------------------------------------
 
-cdef inline number_t eval_chebyu(double n, number_t x) nogil:
+cdef inline number_t eval_chebyu(double n, number_t x) noexcept nogil:
     cdef double a, b, c, d
     cdef number_t g
 
@@ -292,7 +292,7 @@ cdef inline number_t eval_chebyu(double n, number_t x) nogil:
     g = 0.5*(1-x)
     return d*hyp2f1(a, b, c, g)
 
-cdef inline double eval_chebyu_l(long k, double x) nogil:
+cdef inline double eval_chebyu_l(long k, double x) noexcept nogil:
     cdef long m
     cdef int sign
     cdef double b2, b1, b0
@@ -320,47 +320,47 @@ cdef inline double eval_chebyu_l(long k, double x) nogil:
 # Chebyshev S
 #-----------------------------------------------------------------------------
 
-cdef inline number_t eval_chebys(double n, number_t x) nogil:
+cdef inline number_t eval_chebys(double n, number_t x) noexcept nogil:
     return eval_chebyu(n, 0.5*x)
 
-cdef inline double eval_chebys_l(long n, double x) nogil:
+cdef inline double eval_chebys_l(long n, double x) noexcept nogil:
     return eval_chebyu_l(n, 0.5*x)
 
 #-----------------------------------------------------------------------------
 # Chebyshev C
 #-----------------------------------------------------------------------------
 
-cdef inline number_t eval_chebyc(double n, number_t x) nogil:
+cdef inline number_t eval_chebyc(double n, number_t x) noexcept nogil:
     return 2*eval_chebyt(n, 0.5*x)
 
-cdef inline double eval_chebyc_l(long n, double x) nogil:
+cdef inline double eval_chebyc_l(long n, double x) noexcept nogil:
     return 2*eval_chebyt_l(n, 0.5*x)
 
 #-----------------------------------------------------------------------------
 # Chebyshev 1st kind shifted
 #-----------------------------------------------------------------------------
 
-cdef inline number_t eval_sh_chebyt(double n, number_t x) nogil:
+cdef inline number_t eval_sh_chebyt(double n, number_t x) noexcept nogil:
     return eval_chebyt(n, 2*x-1)
 
-cdef inline double eval_sh_chebyt_l(long n, double x) nogil:
+cdef inline double eval_sh_chebyt_l(long n, double x) noexcept nogil:
     return eval_chebyt_l(n, 2*x-1)
 
 #-----------------------------------------------------------------------------
 # Chebyshev 2st kind shifted
 #-----------------------------------------------------------------------------
 
-cdef inline number_t eval_sh_chebyu(double n, number_t x) nogil:
+cdef inline number_t eval_sh_chebyu(double n, number_t x) noexcept nogil:
     return eval_chebyu(n, 2*x-1)
 
-cdef inline double eval_sh_chebyu_l(long n, double x) nogil:
+cdef inline double eval_sh_chebyu_l(long n, double x) noexcept nogil:
     return eval_chebyu_l(n, 2*x-1)
 
 #-----------------------------------------------------------------------------
 # Legendre
 #-----------------------------------------------------------------------------
 
-cdef inline number_t eval_legendre(double n, number_t x) nogil:
+cdef inline number_t eval_legendre(double n, number_t x) noexcept nogil:
     cdef double a, b, c, d
     cdef number_t g
 
@@ -372,7 +372,7 @@ cdef inline number_t eval_legendre(double n, number_t x) nogil:
     return d*hyp2f1(a, b, c, g)
 
 @cython.cdivision(True)
-cdef inline double eval_legendre_l(long n, double x) nogil:
+cdef inline double eval_legendre_l(long n, double x) noexcept nogil:
     cdef long kk, a
     cdef double p, d
     cdef double k
@@ -418,17 +418,17 @@ cdef inline double eval_legendre_l(long n, double x) nogil:
 # Legendre Shifted
 #-----------------------------------------------------------------------------
 
-cdef inline number_t eval_sh_legendre(double n, number_t x) nogil:
+cdef inline number_t eval_sh_legendre(double n, number_t x) noexcept nogil:
     return eval_legendre(n, 2*x-1)
 
-cdef inline double eval_sh_legendre_l(long n, double x) nogil:
+cdef inline double eval_sh_legendre_l(long n, double x) noexcept nogil:
     return eval_legendre_l(n, 2*x-1)
 
 #-----------------------------------------------------------------------------
 # Generalized Laguerre
 #-----------------------------------------------------------------------------
 
-cdef inline number_t eval_genlaguerre(double n, double alpha, number_t x) nogil:
+cdef inline number_t eval_genlaguerre(double n, double alpha, number_t x) noexcept nogil:
     cdef double a, b, d
     cdef number_t g
 
@@ -444,7 +444,7 @@ cdef inline number_t eval_genlaguerre(double n, double alpha, number_t x) nogil:
     return d * hyp1f1(a, b, g)
 
 @cython.cdivision(True)
-cdef inline double eval_genlaguerre_l(long n, double alpha, double x) nogil:
+cdef inline double eval_genlaguerre_l(long n, double alpha, double x) noexcept nogil:
     cdef long kk
     cdef double p, d
     cdef double k
@@ -476,17 +476,17 @@ cdef inline double eval_genlaguerre_l(long n, double alpha, double x) nogil:
 # Laguerre
 #-----------------------------------------------------------------------------
 
-cdef inline number_t eval_laguerre(double n, number_t x) nogil:
+cdef inline number_t eval_laguerre(double n, number_t x) noexcept nogil:
     return eval_genlaguerre(n, 0., x)
 
-cdef inline double eval_laguerre_l(long n, double x) nogil:
+cdef inline double eval_laguerre_l(long n, double x) noexcept nogil:
     return eval_genlaguerre_l(n, 0., x)
 
 #-----------------------------------------------------------------------------
 # Hermite (statistician's)
 #-----------------------------------------------------------------------------
 
-cdef inline double eval_hermitenorm(long n, double x) nogil:
+cdef inline double eval_hermitenorm(long n, double x) noexcept nogil:
     cdef long k
     cdef double y1, y2, y3
 
@@ -518,7 +518,7 @@ cdef inline double eval_hermitenorm(long n, double x) nogil:
 #-----------------------------------------------------------------------------
 
 @cython.cdivision(True)
-cdef inline double eval_hermite(long n, double x) nogil:
+cdef inline double eval_hermite(long n, double x) noexcept nogil:
     if n < 0:
         sf_error.error(
             "eval_hermite",
diff --git a/scipy/special/sf_error.pxd b/scipy/special/sf_error.pxd
index 305e5b85..1885a912 100644
--- a/scipy/special/sf_error.pxd
+++ b/scipy/special/sf_error.pxd
@@ -25,7 +25,7 @@ cdef extern from "sf_error.h":
     sf_action_t get_action "sf_error_get_action" (sf_error_t code) nogil
 
 
-cdef inline int _sf_error_test_function(int code) nogil:
+cdef inline int _sf_error_test_function(int code) noexcept nogil:
     """Function that can raise every sf_error category for testing
     purposes.
 
diff --git a/scipy/special/sph_harm.pxd b/scipy/special/sph_harm.pxd
index 1a9bc7aa..24ecb2c7 100644
--- a/scipy/special/sph_harm.pxd
+++ b/scipy/special/sph_harm.pxd
@@ -8,7 +8,7 @@ from ._complexstuff cimport *
 from libc.math cimport cos, sqrt, fabs, NAN, M_PI
 from libc.stdlib cimport abs
 
-cdef inline double complex sph_harmonic(int m, int n, double theta, double phi) nogil:
+cdef inline double complex sph_harmonic(int m, int n, double theta, double phi) noexcept nogil:
     cdef double x, prefactor
     cdef double complex val
     cdef int mp
diff --git a/scipy/stats/_biasedurn.pyx.templ b/scipy/stats/_biasedurn.pyx.templ
index 752c3b62..01cd3978 100644
--- a/scipy/stats/_biasedurn.pyx.templ
+++ b/scipy/stats/_biasedurn.pyx.templ
@@ -78,18 +78,18 @@ cdef class _PyWalleniusNCHypergeometric:
 
 IF NPY_OLD:
     cdef object _glob_rng
-    cdef double next_double() nogil:
+    cdef double next_double() noexcept nogil:
         with gil:
             return _glob_rng.uniform()
-    cdef double next_normal(const double m, const double s) nogil:
+    cdef double next_normal(const double m, const double s) noexcept nogil:
         with gil:
             return _glob_rng.normal(m, s)
 ELSE:
     cdef bitgen_t* _glob_rng
-    cdef double next_double() nogil:
+    cdef double next_double() noexcept nogil:
         global _glob_rng
         return _glob_rng.next_double(_glob_rng.state)
-    cdef double next_normal(const double m, const double s) nogil:
+    cdef double next_normal(const double m, const double s) noexcept nogil:
         global _glob_rng
         return random_normal(_glob_rng, m, s)
 
diff --git a/scipy/stats/_qmc_cy.pyx b/scipy/stats/_qmc_cy.pyx
index 6dc47e5f..f165cb0d 100644
--- a/scipy/stats/_qmc_cy.pyx
+++ b/scipy/stats/_qmc_cy.pyx
@@ -59,7 +59,7 @@ def _cy_wrapper_l2_star_discrepancy(double[:, ::1] sample,
 
 
 cdef double centered_discrepancy(double[:, ::1] sample_view,
-                                 bint iterative, unsigned int workers) nogil:
+                                 bint iterative, unsigned int workers) noexcept nogil:
     cdef:
         Py_ssize_t n = sample_view.shape[0]
         Py_ssize_t d = sample_view.shape[1]
@@ -86,7 +86,7 @@ cdef double centered_discrepancy(double[:, ::1] sample_view,
 
 
 cdef double centered_discrepancy_loop(double[:, ::1] sample_view,
-                                      Py_ssize_t istart, Py_ssize_t istop) nogil:
+                                      Py_ssize_t istart, Py_ssize_t istop) noexcept nogil:
 
     cdef:
         Py_ssize_t i, j, k
@@ -107,7 +107,7 @@ cdef double centered_discrepancy_loop(double[:, ::1] sample_view,
 
 
 cdef double wrap_around_discrepancy(double[:, ::1] sample_view,
-                                    bint iterative, unsigned int workers) nogil:
+                                    bint iterative, unsigned int workers) noexcept nogil:
     cdef:
         Py_ssize_t n = sample_view.shape[0]
         Py_ssize_t d = sample_view.shape[1]
@@ -123,7 +123,7 @@ cdef double wrap_around_discrepancy(double[:, ::1] sample_view,
 
 
 cdef double wrap_around_loop(double[:, ::1] sample_view,
-                             Py_ssize_t istart, Py_ssize_t istop) nogil:
+                             Py_ssize_t istart, Py_ssize_t istop) noexcept nogil:
 
     cdef:
         Py_ssize_t i, j, k
@@ -141,7 +141,7 @@ cdef double wrap_around_loop(double[:, ::1] sample_view,
 
 
 cdef double mixture_discrepancy(double[:, ::1] sample_view,
-                                bint iterative, unsigned int workers) nogil:
+                                bint iterative, unsigned int workers) noexcept nogil:
     cdef:
         Py_ssize_t n = sample_view.shape[0]
         Py_ssize_t d = sample_view.shape[1]
@@ -170,7 +170,7 @@ cdef double mixture_discrepancy(double[:, ::1] sample_view,
 
 
 cdef double mixture_loop(double[:, ::1] sample_view, Py_ssize_t istart,
-                         Py_ssize_t istop) nogil:
+                         Py_ssize_t istop) noexcept nogil:
 
     cdef:
         Py_ssize_t i, j, k
@@ -193,7 +193,7 @@ cdef double mixture_loop(double[:, ::1] sample_view, Py_ssize_t istart,
 
 
 cdef double l2_star_discrepancy(double[:, ::1] sample_view,
-                                bint iterative, unsigned int workers) nogil:
+                                bint iterative, unsigned int workers) noexcept nogil:
     cdef:
         Py_ssize_t n = sample_view.shape[0]
         Py_ssize_t d = sample_view.shape[1]
@@ -219,7 +219,7 @@ cdef double l2_star_discrepancy(double[:, ::1] sample_view,
 
 
 cdef double l2_star_loop(double[:, ::1] sample_view, Py_ssize_t istart,
-                         Py_ssize_t istop) nogil:
+                         Py_ssize_t istop) noexcept nogil:
 
     cdef:
         Py_ssize_t i, j, k
@@ -248,7 +248,7 @@ def _cy_wrapper_update_discrepancy(double[::1] x_new_view,
 
 cdef double c_update_discrepancy(double[::1] x_new_view,
                                  double[:, ::1] sample_view,
-                                 double initial_disc):
+                                 double initial_disc) noexcept:
     cdef:
         Py_ssize_t n = sample_view.shape[0] + 1
         Py_ssize_t d = sample_view.shape[1]
@@ -295,7 +295,7 @@ ctypedef double (*func_type)(double[:, ::1], Py_ssize_t,
 
 cdef double threaded_loops(func_type loop_func,
                            double[:, ::1] sample_view,
-                           unsigned int workers) nogil:
+                           unsigned int workers) noexcept nogil:
     cdef:
         Py_ssize_t n = sample_view.shape[0]
         double disc2 = 0
@@ -328,7 +328,7 @@ cdef void one_thread_loop(func_type loop_func,
                           double[:, ::1] sample_view,
                           Py_ssize_t istart,
                           Py_ssize_t istop,
-                          _) nogil:
+                          _) noexcept nogil:
 
     cdef double tmp = loop_func(sample_view, istart, istop)
 
diff --git a/scipy/stats/_sobol.pyx b/scipy/stats/_sobol.pyx
index 6e766f36..733e85b7 100644
--- a/scipy/stats/_sobol.pyx
+++ b/scipy/stats/_sobol.pyx
@@ -150,7 +150,7 @@ def _initialize_direction_numbers(poly, vinit, dtype):
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef int bit_length(uint_32_64 n):
+cdef int bit_length(uint_32_64 n) noexcept:
     cdef int bits = 0
     cdef uint_32_64 nloc = n
     while nloc != 0:
@@ -161,7 +161,7 @@ cdef int bit_length(uint_32_64 n):
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef int low_0_bit(uint_32_64 x) nogil:
+cdef int low_0_bit(uint_32_64 x) noexcept nogil:
     """Get the position of the right-most 0 bit for an integer.
 
     Examples:
@@ -195,7 +195,7 @@ cdef int low_0_bit(uint_32_64 x) nogil:
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef int ibits(uint_32_64 x, const int pos, const int length) nogil:
+cdef int ibits(uint_32_64 x, const int pos, const int length) noexcept nogil:
     """Extract a sequence of bits from the bit representation of an integer.
 
     Extract the sequence from position `pos` (inclusive) to ``pos + length``
@@ -236,7 +236,7 @@ cdef int ibits(uint_32_64 x, const int pos, const int length) nogil:
 @cython.wraparound(False)
 cpdef void _initialize_v(
     uint_32_64[:, ::1] v, const int dim, const int bits
-):
+) noexcept:
     """Initialize matrix of size ``dim * bits`` with direction numbers."""
     cdef int d, i, j, k, m
     cdef uint_32_64 p, newv, pow2
@@ -313,7 +313,7 @@ cdef void draw(
     uint_32_64[:, ::1] sv,
     uint_32_64[::1] quasi,
     cnp.float64_t[:, ::1] sample
-) nogil:
+) noexcept nogil:
     cdef int j, l
     cdef uint_32_64 num_gen_loc = num_gen
     cdef uint_32_64 i, qtmp
@@ -333,7 +333,7 @@ cpdef void _fast_forward(const uint_32_64 n,
                          const uint_32_64 num_gen,
                          const int dim,
                          uint_32_64[:, ::1] sv,
-                         uint_32_64[::1] quasi) nogil:
+                         uint_32_64[::1] quasi) noexcept nogil:
     cdef int j, l
     cdef uint_32_64 num_gen_loc = num_gen
     cdef uint_32_64 i
@@ -346,7 +346,7 @@ cpdef void _fast_forward(const uint_32_64 n,
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-cdef uint_32_64 cdot_pow2(uint_32_64[::1] a) nogil:
+cdef uint_32_64 cdot_pow2(uint_32_64[::1] a) noexcept nogil:
     cdef int i
     cdef int size = a.shape[0]
     cdef uint_32_64 z = 0
@@ -362,7 +362,7 @@ cdef uint_32_64 cdot_pow2(uint_32_64[::1] a) nogil:
 cpdef void _cscramble(const int dim,
                       const int bits,
                       uint_32_64[:, :, ::1] ltm,
-                      uint_32_64[:, ::1] sv) nogil:
+                      uint_32_64[:, ::1] sv) noexcept nogil:
     """Scrambling using (left) linear matrix scramble (LMS)."""
     cdef int d, i, j, k, p
     cdef uint_32_64 l, lsmdp, t1, t2, vdj
@@ -391,7 +391,7 @@ cpdef void _cscramble(const int dim,
 @cython.boundscheck(False)
 @cython.wraparound(False)
 cpdef void _fill_p_cumulative(cnp.float_t[::1] p,
-                              cnp.float_t[::1] p_cumulative) nogil:
+                              cnp.float_t[::1] p_cumulative) noexcept nogil:
     cdef int i
     cdef int len_p = p.shape[0]
     cdef float tot = 0
@@ -406,7 +406,7 @@ cpdef void _fill_p_cumulative(cnp.float_t[::1] p,
 @cython.wraparound(False)
 cpdef void _categorize(cnp.float_t[::1] draws,
                        cnp.float_t[::1] p_cumulative,
-                       cnp.int_t[::1] result) nogil:
+                       cnp.int_t[::1] result) noexcept nogil:
     cdef int i
     cdef int n_p = p_cumulative.shape[0]
     for i in range(draws.shape[0]):
@@ -418,7 +418,7 @@ cpdef void _categorize(cnp.float_t[::1] draws,
 @cython.wraparound(False)
 cdef int _find_index(cnp.float_t[::1] p_cumulative,
                      const int size,
-                     const float value) nogil:
+                     const float value) noexcept nogil:
     cdef int l = 0
     cdef int r = size - 1
     cdef int m
diff --git a/scipy/stats/_stats.pxd b/scipy/stats/_stats.pxd
index b50e16c5..d9dce901 100644
--- a/scipy/stats/_stats.pxd
+++ b/scipy/stats/_stats.pxd
@@ -1,9 +1,9 @@
 # destined to be used in a LowLevelCallable
 cdef double _geninvgauss_pdf(double x, void *user_data) nogil except *
-cdef double _studentized_range_cdf(int n, double[2] x, void *user_data) nogil
-cdef double _studentized_range_cdf_asymptotic(double z, void *user_data) nogil
-cdef double _studentized_range_pdf(int n, double[2] x, void *user_data) nogil
-cdef double _studentized_range_pdf_asymptotic(double z, void *user_data) nogil
-cdef double _studentized_range_moment(int n, double[3] x_arg, void *user_data) nogil
+cdef double _studentized_range_cdf(int n, double[2] x, void *user_data) noexcept nogil
+cdef double _studentized_range_cdf_asymptotic(double z, void *user_data) noexcept nogil
+cdef double _studentized_range_pdf(int n, double[2] x, void *user_data) noexcept nogil
+cdef double _studentized_range_pdf_asymptotic(double z, void *user_data) noexcept nogil
+cdef double _studentized_range_moment(int n, double[3] x_arg, void *user_data) noexcept nogil
 cdef double _genhyperbolic_pdf(double x, void *user_data) nogil except *
 cdef double _genhyperbolic_logpdf(double x, void *user_data) nogil except *
diff --git a/scipy/stats/_stats.pyx b/scipy/stats/_stats.pyx
index b8496b1f..d2a3035a 100644
--- a/scipy/stats/_stats.pyx
+++ b/scipy/stats/_stats.pyx
@@ -14,7 +14,7 @@ cimport scipy.special.cython_special as cs
 
 np.import_array()
 
-cdef double von_mises_cdf_series(double k, double x, unsigned int p):
+cdef double von_mises_cdf_series(double k, double x, unsigned int p) noexcept:
     cdef double s, c, sn, cn, R, V
     cdef unsigned int n
     s = math.sin(x)
@@ -490,11 +490,11 @@ def _local_correlations(distx, disty, global_corr='mgc'):
     return corr_mat
 
 
-cpdef double geninvgauss_logpdf(double x, double p, double b) nogil:
+cpdef double geninvgauss_logpdf(double x, double p, double b) noexcept nogil:
     return _geninvgauss_logpdf_kernel(x, p, b)
 
 
-cdef double _geninvgauss_logpdf_kernel(double x, double p, double b) nogil:
+cdef double _geninvgauss_logpdf_kernel(double x, double p, double b) noexcept nogil:
     cdef double z, c
 
     if x <= 0:
@@ -521,19 +521,19 @@ cdef double _geninvgauss_pdf(double x, void *user_data) nogil except *:
     return math.exp(_geninvgauss_logpdf_kernel(x, p, b))
 
 
-cdef double _phi(double z) nogil:
+cdef double _phi(double z) noexcept nogil:
     """evaluates the normal PDF. Used in `studentized_range`"""
     cdef double inv_sqrt_2pi = 0.3989422804014327
     return inv_sqrt_2pi * math.exp(-0.5 * z * z)
 
 
-cdef double _logphi(double z) nogil:
+cdef double _logphi(double z) noexcept nogil:
     """evaluates the log of the normal PDF. Used in `studentized_range`"""
     cdef double log_inv_sqrt_2pi = -0.9189385332046727
     return log_inv_sqrt_2pi - 0.5 * z * z
 
 
-cdef double _Phi(double z) nogil:
+cdef double _Phi(double z) noexcept nogil:
     """evaluates the normal CDF. Used in `studentized_range`"""
     # use a custom function because using cs.ndtr results in incorrect PDF at
     # q=0 on 32bit systems. Use a hardcoded 1/sqrt(2) constant rather than
@@ -542,14 +542,14 @@ cdef double _Phi(double z) nogil:
     return 0.5 * math.erfc(-z * inv_sqrt_2)
 
 
-cpdef double _studentized_range_cdf_logconst(double k, double df):
+cpdef double _studentized_range_cdf_logconst(double k, double df) noexcept:
     """Evaluates log of constant terms in the cdf integrand"""
     cdef double log_2 = 0.6931471805599453
     return (math.log(k) + (df / 2) * math.log(df)
             - (math.lgamma(df / 2) + (df / 2 - 1) * log_2))
 
 
-cpdef double _studentized_range_pdf_logconst(double k, double df):
+cpdef double _studentized_range_pdf_logconst(double k, double df) noexcept:
     """Evaluates log of constant terms in the pdf integrand"""
     cdef double log_2 = 0.6931471805599453
     return (math.log(k) + math.log(k - 1) + (df / 2) * math.log(df)
@@ -557,7 +557,7 @@ cpdef double _studentized_range_pdf_logconst(double k, double df):
 
 
 cdef double _studentized_range_cdf(int n, double[2] integration_var,
-                                   void *user_data) nogil:
+                                   void *user_data) noexcept nogil:
     # evaluates the integrand of Equation (3) by Batista, et al [2]
     # destined to be used in a LowLevelCallable
     q = (<double *> user_data)[0]
@@ -578,7 +578,7 @@ cdef double _studentized_range_cdf(int n, double[2] integration_var,
     return math.exp(log_terms) * math.pow(_Phi(z + q * s) - _Phi(z), k - 1)
 
 
-cdef double _studentized_range_cdf_asymptotic(double z, void *user_data) nogil:
+cdef double _studentized_range_cdf_asymptotic(double z, void *user_data) noexcept nogil:
     # evaluates the integrand of equation (2) by Lund, Lund, page 205. [4]
     # destined to be used in a LowLevelCallable
     q = (<double *> user_data)[0]
@@ -588,7 +588,7 @@ cdef double _studentized_range_cdf_asymptotic(double z, void *user_data) nogil:
 
 
 cdef double _studentized_range_pdf(int n, double[2] integration_var,
-                                   void *user_data) nogil:
+                                   void *user_data) noexcept nogil:
     # evaluates the integrand of equation (4) by Batista, et al [2]
     # destined to be used in a LowLevelCallable
     q = (<double *> user_data)[0]
@@ -610,7 +610,7 @@ cdef double _studentized_range_pdf(int n, double[2] integration_var,
     return math.exp(log_terms) * math.pow(_Phi(s * q + z) - _Phi(z), k - 2)
 
 
-cdef double _studentized_range_pdf_asymptotic(double z, void *user_data) nogil:
+cdef double _studentized_range_pdf_asymptotic(double z, void *user_data) noexcept nogil:
     # evaluates the integrand of equation (2) by Lund, Lund, page 205. [4]
     # destined to be used in a LowLevelCallable
     q = (<double *> user_data)[0]
@@ -620,7 +620,7 @@ cdef double _studentized_range_pdf_asymptotic(double z, void *user_data) nogil:
 
 
 cdef double _studentized_range_moment(int n, double[3] integration_var,
-                                      void *user_data) nogil:
+                                      void *user_data) noexcept nogil:
     # destined to be used in a LowLevelCallable
     K = (<double *> user_data)[0]  # the Kth moment to calc.
     k = (<double *> user_data)[1]
@@ -640,7 +640,7 @@ cdef double _studentized_range_moment(int n, double[3] integration_var,
             _studentized_range_pdf(4, integration_var, pdf_data))
 
 
-cpdef double genhyperbolic_pdf(double x, double p, double a, double b) nogil:
+cpdef double genhyperbolic_pdf(double x, double p, double a, double b) noexcept nogil:
     return math.exp(_genhyperbolic_logpdf_kernel(x, p, a, b))
 
 
@@ -657,7 +657,7 @@ cdef double _genhyperbolic_pdf(double x, void *user_data) nogil except *:
 
 cpdef double genhyperbolic_logpdf(
         double x, double p, double a, double b
-        ) nogil:
+        ) noexcept nogil:
     return _genhyperbolic_logpdf_kernel(x, p, a, b)
 
 cdef double _genhyperbolic_logpdf(double x, void *user_data) nogil except *:
@@ -673,7 +673,7 @@ cdef double _genhyperbolic_logpdf(double x, void *user_data) nogil except *:
 
 cdef double _genhyperbolic_logpdf_kernel(
         double x, double p, double a, double b
-        ) nogil:
+        ) noexcept nogil:
     cdef double t1, t2, t3, t4, t5
 
     t1 = _log_norming_constant(p, a, b)
@@ -686,7 +686,7 @@ cdef double _genhyperbolic_logpdf_kernel(
 
     return t1 + t3 + t4 + t5
 
-cdef double _log_norming_constant(double p, double a, double b) nogil:
+cdef double _log_norming_constant(double p, double a, double b) noexcept nogil:
     cdef double t1, t2, t3, t4, t5, t6
 
     t1 = math.pow(a, 2) - math.pow(b, 2)
@@ -713,7 +713,7 @@ cdef inline int gaussian_kernel_estimate_inner(
     real[:, :] points_,  real[:, :] values_, real[:, :] xi_,
     real[:, :] estimate, real[:, :] cho_cov,
     int n, int m, int d, int p,
-) nogil:
+) noexcept nogil:
     cdef:
         int i, j, k
         real residual, arg, norm
-- 
2.23.0

