# Buggy code
def cumprod(a, axis=None, dtype=None, out=None):
    """Returns the cumulative product of an array along a given axis.

    Args:
        a (cupy.ndarray): Input array.
        axis (int): Axis along which the cumulative product is taken. If it is
        not specified, the input is flattened.
        dtype: Data type specifier.
        out (cupy.ndarray): Output array.

    Returns:
        cupy.ndarray: The result array.

    .. seealso:: :func:`numpy.cumprod`

    """
    if out is None:
        if dtype is None:
            kind = a.dtype.kind
            if kind == "b":
                dtype = numpy.dtype("l")
            elif kind == "i" and a.dtype.itemsize < numpy.dtype("l").itemsize:
                dtype = numpy.dtype("l")
            elif kind == "u" and a.dtype.itemsize < numpy.dtype("L").itemsize:
                dtype = numpy.dtype("L")
            else:
                dtype = a.dtype

        out = a.astype(dtype)
    else:
        out[...] = a

    if axis is None:
        out = out.ravel()
    elif not (-a.ndim <= axis < a.ndim):
        raise ValueError("axis(={}) out of bounds".format(axis))
    else:
        return _proc_as_batch(_cumprod_batch, out, axis=axis)

    kern = core.ElementwiseKernel(
        "int64 pos",
        "raw T x",
        """
        if (i & pos) {
          x[i] *= x[i ^ pos | (pos - 1)];
        }
        """,
        "cumprod_kernel",
    )

    pos = 1
    while pos < out.size:
        kern(pos, out, size=out.size)
        pos <<= 1
    return out


# Traceback (AttributeError)
import cupy
cupy.cumprod
<function cumprod at 0x7f9a460b4c80>
cupy.cumprod(cupy.ndarray(()), axis=-10000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/cupy/math/sumprod.py", line 206, in cumprod
raise numpy.AxisError('axis(={}) out of bounds'.format(axis))
AttributeError: module 'numpy' has no attribute 'AxisError'

# Fixed code
def cumprod(a, axis=None, dtype=None, out=None):
    """Returns the cumulative product of an array along a given axis.

    Args:
        a (cupy.ndarray): Input array.
        axis (int): Axis along which the cumulative product is taken. If it is
        not specified, the input is flattened.
        dtype: Data type specifier.
        out (cupy.ndarray): Output array.

    Returns:
        cupy.ndarray: The result array.

    .. seealso:: :func:`numpy.cumprod`

    """
    if out is None:
        if dtype is None:
            kind = a.dtype.kind
            if kind == "b":
                dtype = numpy.dtype("l")
            elif kind == "i" and a.dtype.itemsize < numpy.dtype("l").itemsize:
                dtype = numpy.dtype("l")
            elif kind == "u" and a.dtype.itemsize < numpy.dtype("L").itemsize:
                dtype = numpy.dtype("L")
            else:
                dtype = a.dtype

        out = a.astype(dtype)
    else:
        out[...] = a

    if axis is None:
        out = out.ravel()
    elif not (-a.ndim <= axis < a.ndim):
        raise core.core._AxisError("axis(={}) out of bounds".format(axis))
    else:
        return _proc_as_batch(_cumprod_batch, out, axis=axis)

    kern = core.ElementwiseKernel(
        "int64 pos",
        "raw T x",
        """
        if (i & pos) {
          x[i] *= x[i ^ pos | (pos - 1)];
        }
        """,
        "cumprod_kernel",
    )

    pos = 1
    while pos < out.size:
        kern(pos, out, size=out.size)
        pos <<= 1
    return out