From 8f661a2f59e63cbed540b512dc564a3aca7c4211 Mon Sep 17 00:00:00 2001
From: Chris Robinson <chris.kcat@gmail.com>
Date: Fri, 8 Dec 2023 04:33:32 -0800
Subject: Fix some clang-tidy warnings

---
 common/alspan.h | 102 ++++++++++++++++++++++++++++----------------------------
 1 file changed, 51 insertions(+), 51 deletions(-)

(limited to 'common/alspan.h')

diff --git a/common/alspan.h b/common/alspan.h
index 341ce7c8..d91747c2 100644
--- a/common/alspan.h
+++ b/common/alspan.h
@@ -107,43 +107,43 @@ public:
 
     constexpr span& operator=(const span &rhs) noexcept = default;
 
-    constexpr reference front() const { return *mData; }
-    constexpr reference back() const { return *(mData+E-1); }
-    constexpr reference operator[](index_type idx) const { return mData[idx]; }
-    constexpr pointer data() const noexcept { return mData; }
-
-    constexpr index_type size() const noexcept { return E; }
-    constexpr index_type size_bytes() const noexcept { return E * sizeof(value_type); }
-    constexpr bool empty() const noexcept { return E == 0; }
-
-    constexpr iterator begin() const noexcept { return mData; }
-    constexpr iterator end() const noexcept { return mData+E; }
-    constexpr const_iterator cbegin() const noexcept { return mData; }
-    constexpr const_iterator cend() const noexcept { return mData+E; }
-
-    constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
-    constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }
-    constexpr const_reverse_iterator crbegin() const noexcept
+    [[nodiscard]] constexpr auto front() const -> reference { return *mData; }
+    [[nodiscard]] constexpr auto back() const -> reference { return *(mData+E-1); }
+    [[nodiscard]] constexpr auto operator[](index_type idx) const -> reference { return mData[idx]; }
+    [[nodiscard]] constexpr auto data() const noexcept -> pointer { return mData; }
+
+    [[nodiscard]] constexpr auto size() const noexcept -> index_type { return E; }
+    [[nodiscard]] constexpr auto size_bytes() const noexcept -> index_type { return E * sizeof(value_type); }
+    [[nodiscard]] constexpr auto empty() const noexcept -> bool { return E == 0; }
+
+    [[nodiscard]] constexpr auto begin() const noexcept -> iterator { return mData; }
+    [[nodiscard]] constexpr auto end() const noexcept -> iterator { return mData+E; }
+    [[nodiscard]] constexpr auto cbegin() const noexcept -> const_iterator { return mData; }
+    [[nodiscard]] constexpr auto cend() const noexcept -> const_iterator { return mData+E; }
+
+    [[nodiscard]] constexpr auto rbegin() const noexcept -> reverse_iterator { return reverse_iterator{end()}; }
+    [[nodiscard]] constexpr auto rend() const noexcept -> reverse_iterator { return reverse_iterator{begin()}; }
+    [[nodiscard]] constexpr auto crbegin() const noexcept -> const_reverse_iterator
     { return const_reverse_iterator{cend()}; }
-    constexpr const_reverse_iterator crend() const noexcept
+    [[nodiscard]] constexpr auto crend() const noexcept -> const_reverse_iterator
     { return const_reverse_iterator{cbegin()}; }
 
     template<size_t C>
-    constexpr span<element_type,C> first() const
+    [[nodiscard]] constexpr auto first() const -> span<element_type,C>
     {
         static_assert(E >= C, "New size exceeds original capacity");
         return span<element_type,C>{mData, C};
     }
 
     template<size_t C>
-    constexpr span<element_type,C> last() const
+    [[nodiscard]] constexpr auto last() const -> span<element_type,C>
     {
         static_assert(E >= C, "New size exceeds original capacity");
         return span<element_type,C>{mData+(E-C), C};
     }
 
     template<size_t O, size_t C>
-    constexpr auto subspan() const -> std::enable_if_t<C!=dynamic_extent,span<element_type,C>>
+    [[nodiscard]] constexpr auto subspan() const -> std::enable_if_t<C!=dynamic_extent,span<element_type,C>>
     {
         static_assert(E >= O, "Offset exceeds extent");
         static_assert(E-O >= C, "New size exceeds original capacity");
@@ -151,7 +151,7 @@ public:
     }
 
     template<size_t O, size_t C=dynamic_extent>
-    constexpr auto subspan() const -> std::enable_if_t<C==dynamic_extent,span<element_type,E-O>>
+    [[nodiscard]] constexpr auto subspan() const -> std::enable_if_t<C==dynamic_extent,span<element_type,E-O>>
     {
         static_assert(E >= O, "Offset exceeds extent");
         return span<element_type,E-O>{mData+O, E-O};
@@ -161,10 +161,10 @@ public:
      * defining the specialization. As a result, these methods need to be
      * defined later.
      */
-    constexpr span<element_type,dynamic_extent> first(size_t count) const;
-    constexpr span<element_type,dynamic_extent> last(size_t count) const;
-    constexpr span<element_type,dynamic_extent> subspan(size_t offset,
-        size_t count=dynamic_extent) const;
+    [[nodiscard]] constexpr auto first(size_t count) const -> span<element_type,dynamic_extent>;
+    [[nodiscard]] constexpr auto last(size_t count) const -> span<element_type,dynamic_extent>;
+    [[nodiscard]] constexpr auto subspan(size_t offset,
+        size_t count=dynamic_extent) const -> span<element_type,dynamic_extent>;
 
 private:
     pointer mData{nullptr};
@@ -221,51 +221,51 @@ public:
 
     constexpr span& operator=(const span &rhs) noexcept = default;
 
-    constexpr reference front() const { return *mData; }
-    constexpr reference back() const { return *(mDataEnd-1); }
-    constexpr reference operator[](index_type idx) const { return mData[idx]; }
-    constexpr pointer data() const noexcept { return mData; }
+    [[nodiscard]] constexpr auto front() const -> reference { return *mData; }
+    [[nodiscard]] constexpr auto back() const -> reference { return *(mDataEnd-1); }
+    [[nodiscard]] constexpr auto operator[](index_type idx) const -> reference { return mData[idx]; }
+    [[nodiscard]] constexpr auto data() const noexcept -> pointer { return mData; }
 
-    constexpr index_type size() const noexcept { return static_cast<index_type>(mDataEnd-mData); }
-    constexpr index_type size_bytes() const noexcept
+    [[nodiscard]] constexpr auto size() const noexcept -> index_type { return static_cast<index_type>(mDataEnd-mData); }
+    [[nodiscard]] constexpr auto size_bytes() const noexcept -> index_type
     { return static_cast<index_type>(mDataEnd-mData) * sizeof(value_type); }
-    constexpr bool empty() const noexcept { return mData == mDataEnd; }
+    [[nodiscard]] constexpr auto empty() const noexcept -> bool { return mData == mDataEnd; }
 
-    constexpr iterator begin() const noexcept { return mData; }
-    constexpr iterator end() const noexcept { return mDataEnd; }
-    constexpr const_iterator cbegin() const noexcept { return mData; }
-    constexpr const_iterator cend() const noexcept { return mDataEnd; }
+    [[nodiscard]] constexpr auto begin() const noexcept -> iterator { return mData; }
+    [[nodiscard]] constexpr auto end() const noexcept -> iterator { return mDataEnd; }
+    [[nodiscard]] constexpr auto cbegin() const noexcept -> const_iterator { return mData; }
+    [[nodiscard]] constexpr auto cend() const noexcept -> const_iterator { return mDataEnd; }
 
-    constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
-    constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }
-    constexpr const_reverse_iterator crbegin() const noexcept
+    [[nodiscard]] constexpr auto rbegin() const noexcept -> reverse_iterator { return reverse_iterator{end()}; }
+    [[nodiscard]] constexpr auto rend() const noexcept -> reverse_iterator { return reverse_iterator{begin()}; }
+    [[nodiscard]] constexpr auto crbegin() const noexcept -> const_reverse_iterator
     { return const_reverse_iterator{cend()}; }
-    constexpr const_reverse_iterator crend() const noexcept
+    [[nodiscard]] constexpr auto crend() const noexcept -> const_reverse_iterator
     { return const_reverse_iterator{cbegin()}; }
 
     template<size_t C>
-    constexpr span<element_type,C> first() const
+    [[nodiscard]] constexpr auto first() const -> span<element_type,C>
     { return span<element_type,C>{mData, C}; }
 
-    constexpr span first(size_t count) const
+    [[nodiscard]] constexpr auto first(size_t count) const -> span
     { return (count >= size()) ? *this : span{mData, mData+count}; }
 
     template<size_t C>
-    constexpr span<element_type,C> last() const
+    [[nodiscard]] constexpr auto last() const -> span<element_type,C>
     { return span<element_type,C>{mDataEnd-C, C}; }
 
-    constexpr span last(size_t count) const
+    [[nodiscard]] constexpr auto last(size_t count) const -> span
     { return (count >= size()) ? *this : span{mDataEnd-count, mDataEnd}; }
 
     template<size_t O, size_t C>
-    constexpr auto subspan() const -> std::enable_if_t<C!=dynamic_extent,span<element_type,C>>
+    [[nodiscard]] constexpr auto subspan() const -> std::enable_if_t<C!=dynamic_extent,span<element_type,C>>
     { return span<element_type,C>{mData+O, C}; }
 
     template<size_t O, size_t C=dynamic_extent>
-    constexpr auto subspan() const -> std::enable_if_t<C==dynamic_extent,span<element_type,C>>
+    [[nodiscard]] constexpr auto subspan() const -> std::enable_if_t<C==dynamic_extent,span<element_type,C>>
     { return span<element_type,C>{mData+O, mDataEnd}; }
 
-    constexpr span subspan(size_t offset, size_t count=dynamic_extent) const
+    [[nodiscard]] constexpr auto subspan(size_t offset, size_t count=dynamic_extent) const -> span
     {
         return (offset > size()) ? span{} :
             (count >= size()-offset) ? span{mData+offset, mDataEnd} :
@@ -278,21 +278,21 @@ private:
 };
 
 template<typename T, size_t E>
-constexpr inline auto span<T,E>::first(size_t count) const -> span<element_type,dynamic_extent>
+[[nodiscard]] constexpr inline auto span<T,E>::first(size_t count) const -> span<element_type,dynamic_extent>
 {
     return (count >= size()) ? span<element_type>{mData, extent} :
         span<element_type>{mData, count};
 }
 
 template<typename T, size_t E>
-constexpr inline auto span<T,E>::last(size_t count) const -> span<element_type,dynamic_extent>
+[[nodiscard]] constexpr inline auto span<T,E>::last(size_t count) const -> span<element_type,dynamic_extent>
 {
     return (count >= size()) ? span<element_type>{mData, extent} :
         span<element_type>{mData+extent-count, count};
 }
 
 template<typename T, size_t E>
-constexpr inline auto span<T,E>::subspan(size_t offset, size_t count) const
+[[nodiscard]] constexpr inline auto span<T,E>::subspan(size_t offset, size_t count) const
     -> span<element_type,dynamic_extent>
 {
     return (offset > size()) ? span<element_type>{} :
-- 
cgit v1.2.3


From 073d79c2047143e70bb199077fe3c8dbafe0a606 Mon Sep 17 00:00:00 2001
From: Chris Robinson <chris.kcat@gmail.com>
Date: Sun, 10 Dec 2023 11:34:04 -0800
Subject: More clang-tidy cleanup

And suppress some warnings
---
 al/eax/globals.h          |   2 +
 al/effect.h               |   2 +-
 alc/alc.cpp               | 183 ++++++++++++++++++++++++----------------------
 alc/backends/pipewire.cpp |  58 +++++++++------
 alc/export_list.h         |  16 ++--
 alc/inprogext.h           |   2 +
 common/alspan.h           |   8 +-
 core/helpers.h            |   4 +-
 8 files changed, 151 insertions(+), 124 deletions(-)

(limited to 'common/alspan.h')

diff --git a/al/eax/globals.h b/al/eax/globals.h
index ff05d009..4d501ff9 100644
--- a/al/eax/globals.h
+++ b/al/eax/globals.h
@@ -3,6 +3,7 @@
 
 inline bool eax_g_is_enabled{true};
 
+/* NOLINTBEGIN(*-avoid-c-arrays) */
 inline constexpr char eax1_ext_name[]{"EAX"};
 inline constexpr char eax2_ext_name[]{"EAX2.0"};
 inline constexpr char eax3_ext_name[]{"EAX3.0"};
@@ -16,5 +17,6 @@ inline constexpr char eax_eax_get_func_name[]{"EAXGet"};
 
 inline constexpr char eax_eax_set_buffer_mode_func_name[]{"EAXSetBufferMode"};
 inline constexpr char eax_eax_get_buffer_mode_func_name[]{"EAXGetBufferMode"};
+/* NOLINTEND(*-avoid-c-arrays) */
 
 #endif // !EAX_GLOBALS_INCLUDED
diff --git a/al/effect.h b/al/effect.h
index 7c5c40dc..fef03475 100644
--- a/al/effect.h
+++ b/al/effect.h
@@ -34,7 +34,7 @@ enum {
 inline std::bitset<MAX_EFFECTS> DisabledEffects;
 
 struct EffectList {
-    const char name[16];
+    const char name[16]; /* NOLINT(*-avoid-c-arrays) */
     ALuint type;
     ALenum val;
 };
diff --git a/alc/alc.cpp b/alc/alc.cpp
index 3fcdcc3e..6e851b74 100644
--- a/alc/alc.cpp
+++ b/alc/alc.cpp
@@ -50,7 +50,6 @@
 #include <mutex>
 #include <new>
 #include <optional>
-#include <stddef.h>
 #include <stdexcept>
 #include <string>
 #include <type_traits>
@@ -196,66 +195,66 @@ using float2 = std::array<float,2>;
  ************************************************/
 struct BackendInfo {
     const char *name;
-    BackendFactory& (*getFactory)(void);
+    BackendFactory& (*getFactory)();
 };
 
-BackendInfo BackendList[] = {
+std::array BackendList{
 #ifdef HAVE_PIPEWIRE
-    { "pipewire", PipeWireBackendFactory::getFactory },
+    BackendInfo{"pipewire", PipeWireBackendFactory::getFactory},
 #endif
 #ifdef HAVE_PULSEAUDIO
-    { "pulse", PulseBackendFactory::getFactory },
+    BackendInfo{"pulse", PulseBackendFactory::getFactory},
 #endif
 #ifdef HAVE_WASAPI
-    { "wasapi", WasapiBackendFactory::getFactory },
+    BackendInfo{"wasapi", WasapiBackendFactory::getFactory},
 #endif
 #ifdef HAVE_COREAUDIO
-    { "core", CoreAudioBackendFactory::getFactory },
+    BackendInfo{"core", CoreAudioBackendFactory::getFactory},
 #endif
 #ifdef HAVE_OBOE
-    { "oboe", OboeBackendFactory::getFactory },
+    BackendInfo{"oboe", OboeBackendFactory::getFactory},
 #endif
 #ifdef HAVE_OPENSL
-    { "opensl", OSLBackendFactory::getFactory },
+    BackendInfo{"opensl", OSLBackendFactory::getFactory},
 #endif
 #ifdef HAVE_ALSA
-    { "alsa", AlsaBackendFactory::getFactory },
+    BackendInfo{"alsa", AlsaBackendFactory::getFactory},
 #endif
 #ifdef HAVE_SOLARIS
-    { "solaris", SolarisBackendFactory::getFactory },
+    BackendInfo{"solaris", SolarisBackendFactory::getFactory},
 #endif
 #ifdef HAVE_SNDIO
-    { "sndio", SndIOBackendFactory::getFactory },
+    BackendInfo{"sndio", SndIOBackendFactory::getFactory},
 #endif
 #ifdef HAVE_OSS
-    { "oss", OSSBackendFactory::getFactory },
+    BackendInfo{"oss", OSSBackendFactory::getFactory},
 #endif
 #ifdef HAVE_JACK
-    { "jack", JackBackendFactory::getFactory },
+    BackendInfo{"jack", JackBackendFactory::getFactory},
 #endif
 #ifdef HAVE_DSOUND
-    { "dsound", DSoundBackendFactory::getFactory },
+    BackendInfo{"dsound", DSoundBackendFactory::getFactory},
 #endif
 #ifdef HAVE_WINMM
-    { "winmm", WinMMBackendFactory::getFactory },
+    BackendInfo{"winmm", WinMMBackendFactory::getFactory},
 #endif
 #ifdef HAVE_PORTAUDIO
-    { "port", PortBackendFactory::getFactory },
+    BackendInfo{"port", PortBackendFactory::getFactory},
 #endif
 #ifdef HAVE_SDL2
-    { "sdl2", SDL2BackendFactory::getFactory },
+    BackendInfo{"sdl2", SDL2BackendFactory::getFactory},
 #endif
 
-    { "null", NullBackendFactory::getFactory },
+    BackendInfo{"null", NullBackendFactory::getFactory},
 #ifdef HAVE_WAVE
-    { "wave", WaveBackendFactory::getFactory },
+    BackendInfo{"wave", WaveBackendFactory::getFactory},
 #endif
 };
 
 BackendFactory *PlaybackFactory{};
 BackendFactory *CaptureFactory{};
 
-
+/* NOLINTBEGIN(*-avoid-c-arrays) */
 constexpr ALCchar alcNoError[] = "No Error";
 constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device";
 constexpr ALCchar alcErrInvalidContext[] = "Invalid Context";
@@ -270,6 +269,7 @@ constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory";
 
 /* Enumerated device names */
 constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0";
+/* NOLINTEND(*-avoid-c-arrays) */
 
 std::string alcAllDevicesList;
 std::string alcCaptureDeviceList;
@@ -298,6 +298,7 @@ constexpr uint DitherRNGSeed{22222u};
 /************************************************
  * ALC information
  ************************************************/
+/* NOLINTBEGIN(*-avoid-c-arrays) */
 constexpr ALCchar alcNoDeviceExtList[] =
     "ALC_ENUMERATE_ALL_EXT "
     "ALC_ENUMERATION_EXT "
@@ -328,6 +329,7 @@ constexpr ALCchar alcExtensionList[] =
     "ALC_SOFT_pause_device "
     "ALC_SOFT_reopen_device "
     "ALC_SOFT_system_events";
+/* NOLINTEND(*-avoid-c-arrays) */
 constexpr int alcMajorVersion{1};
 constexpr int alcMinorVersion{1};
 
@@ -347,7 +349,7 @@ std::vector<ALCcontext*> ContextList;
 std::recursive_mutex ListLock;
 
 
-void alc_initconfig(void)
+void alc_initconfig()
 {
     if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL"))
     {
@@ -672,7 +674,7 @@ void alc_initconfig(void)
 
 #ifdef ALSOFT_EAX
     {
-        static constexpr char eax_block_name[] = "eax";
+        const char *eax_block_name{"eax"};
 
         if(const auto eax_enable_opt = ConfigValueBool(nullptr, eax_block_name, "enable"))
         {
@@ -736,44 +738,45 @@ void ProbeCaptureDeviceList()
 struct DevFmtPair { DevFmtChannels chans; DevFmtType type; };
 std::optional<DevFmtPair> DecomposeDevFormat(ALenum format)
 {
-    static const struct {
+    struct FormatType {
         ALenum format;
         DevFmtChannels channels;
         DevFmtType type;
-    } list[] = {
-        { AL_FORMAT_MONO8,    DevFmtMono, DevFmtUByte },
-        { AL_FORMAT_MONO16,   DevFmtMono, DevFmtShort },
-        { AL_FORMAT_MONO_I32, DevFmtMono, DevFmtInt },
-        { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat },
-
-        { AL_FORMAT_STEREO8,    DevFmtStereo, DevFmtUByte },
-        { AL_FORMAT_STEREO16,   DevFmtStereo, DevFmtShort },
-        { AL_FORMAT_STEREO_I32, DevFmtStereo, DevFmtInt },
-        { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat },
-
-        { AL_FORMAT_QUAD8,    DevFmtQuad, DevFmtUByte },
-        { AL_FORMAT_QUAD16,   DevFmtQuad, DevFmtShort },
-        { AL_FORMAT_QUAD32,   DevFmtQuad, DevFmtFloat },
-        { AL_FORMAT_QUAD_I32, DevFmtQuad, DevFmtInt },
-        { AL_FORMAT_QUAD_FLOAT32, DevFmtQuad, DevFmtFloat },
-
-        { AL_FORMAT_51CHN8,    DevFmtX51, DevFmtUByte },
-        { AL_FORMAT_51CHN16,   DevFmtX51, DevFmtShort },
-        { AL_FORMAT_51CHN32,   DevFmtX51, DevFmtFloat },
-        { AL_FORMAT_51CHN_I32, DevFmtX51, DevFmtInt },
-        { AL_FORMAT_51CHN_FLOAT32, DevFmtX51, DevFmtFloat },
-
-        { AL_FORMAT_61CHN8,    DevFmtX61, DevFmtUByte },
-        { AL_FORMAT_61CHN16,   DevFmtX61, DevFmtShort },
-        { AL_FORMAT_61CHN32,   DevFmtX61, DevFmtFloat },
-        { AL_FORMAT_61CHN_I32, DevFmtX61, DevFmtInt },
-        { AL_FORMAT_61CHN_FLOAT32, DevFmtX61, DevFmtFloat },
-
-        { AL_FORMAT_71CHN8,    DevFmtX71, DevFmtUByte },
-        { AL_FORMAT_71CHN16,   DevFmtX71, DevFmtShort },
-        { AL_FORMAT_71CHN32,   DevFmtX71, DevFmtFloat },
-        { AL_FORMAT_71CHN_I32, DevFmtX71, DevFmtInt },
-        { AL_FORMAT_71CHN_FLOAT32, DevFmtX71, DevFmtFloat },
+    };
+    static constexpr std::array list{
+        FormatType{AL_FORMAT_MONO8,    DevFmtMono, DevFmtUByte},
+        FormatType{AL_FORMAT_MONO16,   DevFmtMono, DevFmtShort},
+        FormatType{AL_FORMAT_MONO_I32, DevFmtMono, DevFmtInt},
+        FormatType{AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat},
+
+        FormatType{AL_FORMAT_STEREO8,    DevFmtStereo, DevFmtUByte},
+        FormatType{AL_FORMAT_STEREO16,   DevFmtStereo, DevFmtShort},
+        FormatType{AL_FORMAT_STEREO_I32, DevFmtStereo, DevFmtInt},
+        FormatType{AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat},
+
+        FormatType{AL_FORMAT_QUAD8,    DevFmtQuad, DevFmtUByte},
+        FormatType{AL_FORMAT_QUAD16,   DevFmtQuad, DevFmtShort},
+        FormatType{AL_FORMAT_QUAD32,   DevFmtQuad, DevFmtFloat},
+        FormatType{AL_FORMAT_QUAD_I32, DevFmtQuad, DevFmtInt},
+        FormatType{AL_FORMAT_QUAD_FLOAT32, DevFmtQuad, DevFmtFloat},
+
+        FormatType{AL_FORMAT_51CHN8,    DevFmtX51, DevFmtUByte},
+        FormatType{AL_FORMAT_51CHN16,   DevFmtX51, DevFmtShort},
+        FormatType{AL_FORMAT_51CHN32,   DevFmtX51, DevFmtFloat},
+        FormatType{AL_FORMAT_51CHN_I32, DevFmtX51, DevFmtInt},
+        FormatType{AL_FORMAT_51CHN_FLOAT32, DevFmtX51, DevFmtFloat},
+
+        FormatType{AL_FORMAT_61CHN8,    DevFmtX61, DevFmtUByte},
+        FormatType{AL_FORMAT_61CHN16,   DevFmtX61, DevFmtShort},
+        FormatType{AL_FORMAT_61CHN32,   DevFmtX61, DevFmtFloat},
+        FormatType{AL_FORMAT_61CHN_I32, DevFmtX61, DevFmtInt},
+        FormatType{AL_FORMAT_61CHN_FLOAT32, DevFmtX61, DevFmtFloat},
+
+        FormatType{AL_FORMAT_71CHN8,    DevFmtX71, DevFmtUByte},
+        FormatType{AL_FORMAT_71CHN16,   DevFmtX71, DevFmtShort},
+        FormatType{AL_FORMAT_71CHN32,   DevFmtX71, DevFmtFloat},
+        FormatType{AL_FORMAT_71CHN_I32, DevFmtX71, DevFmtInt},
+        FormatType{AL_FORMAT_71CHN_FLOAT32, DevFmtX71, DevFmtFloat},
     };
 
     for(const auto &item : list)
@@ -1034,54 +1037,56 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
 
         if(auto typeopt = device->configValue<std::string>(nullptr, "sample-type"))
         {
-            static constexpr struct TypeMap {
-                const char name[8];
+            struct TypeMap {
+                const char name[8]; /* NOLINT(*-avoid-c-arrays) */
                 DevFmtType type;
-            } typelist[] = {
-                { "int8",    DevFmtByte   },
-                { "uint8",   DevFmtUByte  },
-                { "int16",   DevFmtShort  },
-                { "uint16",  DevFmtUShort },
-                { "int32",   DevFmtInt    },
-                { "uint32",  DevFmtUInt   },
-                { "float32", DevFmtFloat  },
+            };
+            static constexpr std::array typelist{
+                TypeMap{"int8",    DevFmtByte  },
+                TypeMap{"uint8",   DevFmtUByte },
+                TypeMap{"int16",   DevFmtShort },
+                TypeMap{"uint16",  DevFmtUShort},
+                TypeMap{"int32",   DevFmtInt   },
+                TypeMap{"uint32",  DevFmtUInt  },
+                TypeMap{"float32", DevFmtFloat },
             };
 
             const ALCchar *fmt{typeopt->c_str()};
-            auto iter = std::find_if(std::begin(typelist), std::end(typelist),
+            auto iter = std::find_if(typelist.begin(), typelist.end(),
                 [fmt](const TypeMap &entry) -> bool
                 { return al::strcasecmp(entry.name, fmt) == 0; });
-            if(iter == std::end(typelist))
+            if(iter == typelist.end())
                 ERR("Unsupported sample-type: %s\n", fmt);
             else
                 opttype = iter->type;
         }
         if(auto chanopt = device->configValue<std::string>(nullptr, "channels"))
         {
-            static constexpr struct ChannelMap {
-                const char name[16];
+            struct ChannelMap {
+                const char name[16]; /* NOLINT(*-avoid-c-arrays) */
                 DevFmtChannels chans;
                 uint8_t order;
-            } chanlist[] = {
-                { "mono",       DevFmtMono,   0 },
-                { "stereo",     DevFmtStereo, 0 },
-                { "quad",       DevFmtQuad,   0 },
-                { "surround51", DevFmtX51,    0 },
-                { "surround61", DevFmtX61,    0 },
-                { "surround71", DevFmtX71,    0 },
-                { "surround714", DevFmtX714,  0 },
-                { "surround3d71", DevFmtX3D71, 0 },
-                { "surround51rear", DevFmtX51, 0 },
-                { "ambi1", DevFmtAmbi3D, 1 },
-                { "ambi2", DevFmtAmbi3D, 2 },
-                { "ambi3", DevFmtAmbi3D, 3 },
+            };
+            static constexpr std::array chanlist{
+                ChannelMap{"mono",       DevFmtMono,   0},
+                ChannelMap{"stereo",     DevFmtStereo, 0},
+                ChannelMap{"quad",       DevFmtQuad,   0},
+                ChannelMap{"surround51", DevFmtX51,    0},
+                ChannelMap{"surround61", DevFmtX61,    0},
+                ChannelMap{"surround71", DevFmtX71,    0},
+                ChannelMap{"surround714", DevFmtX714,  0},
+                ChannelMap{"surround3d71", DevFmtX3D71, 0},
+                ChannelMap{"surround51rear", DevFmtX51, 0},
+                ChannelMap{"ambi1", DevFmtAmbi3D, 1},
+                ChannelMap{"ambi2", DevFmtAmbi3D, 2},
+                ChannelMap{"ambi3", DevFmtAmbi3D, 3},
             };
 
             const ALCchar *fmt{chanopt->c_str()};
-            auto iter = std::find_if(std::begin(chanlist), std::end(chanlist),
+            auto iter = std::find_if(chanlist.end(), chanlist.end(),
                 [fmt](const ChannelMap &entry) -> bool
                 { return al::strcasecmp(entry.name, fmt) == 0; });
-            if(iter == std::end(chanlist))
+            if(iter == chanlist.end())
                 ERR("Unsupported channels: %s\n", fmt);
             else
             {
@@ -1856,7 +1861,7 @@ FORCE_ALIGN void ALC_APIENTRY alsoft_set_log_callback(LPALSOFTLOGCALLBACK callba
 }
 
 /** Returns a new reference to the currently active context for this thread. */
-ContextRef GetContextRef(void)
+ContextRef GetContextRef()
 {
     ALCcontext *context{ALCcontext::getThreadContext()};
     if(context)
@@ -2980,7 +2985,7 @@ ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) noexcept
         auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx);
         if(ctxiter != ContextList.end() && *ctxiter == ctx)
         {
-            orphanctxs.emplace_back(ContextRef{*ctxiter});
+            orphanctxs.emplace_back(*ctxiter);
             ContextList.erase(ctxiter);
         }
     }
diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp
index ca7e3cf3..d934071e 100644
--- a/alc/backends/pipewire.cpp
+++ b/alc/backends/pipewire.cpp
@@ -28,12 +28,12 @@
 #include <cstring>
 #include <cerrno>
 #include <chrono>
+#include <cstdint>
 #include <ctime>
 #include <list>
 #include <memory>
 #include <mutex>
 #include <optional>
-#include <stdint.h>
 #include <thread>
 #include <type_traits>
 #include <utility>
@@ -169,8 +169,10 @@ using std::chrono::milliseconds;
 using std::chrono::nanoseconds;
 using uint = unsigned int;
 
+/* NOLINTBEGIN(*-avoid-c-arrays) */
 constexpr char pwireDevice[] = "PipeWire Output";
 constexpr char pwireInput[] = "PipeWire Input";
+/* NOLINTEND(*-avoid-c-arrays) */
 
 
 bool check_version(const char *version)
@@ -238,7 +240,7 @@ bool pwire_load()
     if(pwire_handle)
         return true;
 
-    static constexpr char pwire_library[] = "libpipewire-0.3.so.0";
+    const char *pwire_library{"libpipewire-0.3.so.0"};
     std::string missing_funcs;
 
     pwire_handle = LoadLib(pwire_library);
@@ -434,9 +436,11 @@ public:
 
     explicit operator bool() const noexcept { return mLoop != nullptr; }
 
+    [[nodiscard]]
     auto start() const { return pw_thread_loop_start(mLoop); }
     auto stop() const { return pw_thread_loop_stop(mLoop); }
 
+    [[nodiscard]]
     auto getLoop() const { return pw_thread_loop_get_loop(mLoop); }
 
     auto lock() const { return pw_thread_loop_lock(mLoop); }
@@ -501,8 +505,8 @@ struct NodeProxy {
         /* Track changes to the enumerable and current formats (indicates the
          * default and active format, which is what we're interested in).
          */
-        uint32_t fmtids[]{SPA_PARAM_EnumFormat, SPA_PARAM_Format};
-        ppw_node_subscribe_params(mNode.get(), std::data(fmtids), std::size(fmtids));
+        std::array<uint32_t,2> fmtids{{SPA_PARAM_EnumFormat, SPA_PARAM_Format}};
+        ppw_node_subscribe_params(mNode.get(), fmtids.data(), fmtids.size());
     }
     ~NodeProxy()
     { spa_hook_remove(&mListener); }
@@ -765,25 +769,32 @@ void DeviceNode::Remove(uint32_t id)
 }
 
 
-const spa_audio_channel MonoMap[]{
+constexpr std::array MonoMap{
     SPA_AUDIO_CHANNEL_MONO
-}, StereoMap[] {
+};
+constexpr std::array StereoMap{
     SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR
-}, QuadMap[]{
+};
+constexpr std::array QuadMap{
     SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR
-}, X51Map[]{
+};
+constexpr std::array X51Map{
     SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
     SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR
-}, X51RearMap[]{
+};
+constexpr std::array X51RearMap{
     SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
     SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR
-}, X61Map[]{
+};
+constexpr std::array X61Map{
     SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
     SPA_AUDIO_CHANNEL_RC, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR
-}, X71Map[]{
+};
+constexpr std::array X71Map{
     SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
     SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR
-}, X714Map[]{
+};
+constexpr std::array X714Map{
     SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
     SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR,
     SPA_AUDIO_CHANNEL_TFL, SPA_AUDIO_CHANNEL_TFR, SPA_AUDIO_CHANNEL_TRL, SPA_AUDIO_CHANNEL_TRR
@@ -793,10 +804,10 @@ const spa_audio_channel MonoMap[]{
  * Checks if every channel in 'map1' exists in 'map0' (that is, map0 is equal
  * to or a superset of map1).
  */
-template<size_t N>
-bool MatchChannelMap(const al::span<const uint32_t> map0, const spa_audio_channel (&map1)[N])
+bool MatchChannelMap(const al::span<const uint32_t> map0,
+    const al::span<const spa_audio_channel> map1)
 {
-    if(map0.size() < N)
+    if(map0.size() < map1.size())
         return false;
     for(const spa_audio_channel chid : map1)
     {
@@ -956,6 +967,7 @@ void DeviceNode::parseChannelCount(const spa_pod *value, bool force_update) noex
 }
 
 
+/* NOLINTBEGIN(*-avoid-c-arrays) */
 constexpr char MonitorPrefix[]{"Monitor of "};
 constexpr auto MonitorPrefixLen = std::size(MonitorPrefix) - 1;
 constexpr char AudioSinkClass[]{"Audio/Sink"};
@@ -963,6 +975,7 @@ constexpr char AudioSourceClass[]{"Audio/Source"};
 constexpr char AudioSourceVirtualClass[]{"Audio/Source/Virtual"};
 constexpr char AudioDuplexClass[]{"Audio/Duplex"};
 constexpr char StreamClass[]{"Stream/"};
+/* NOLINTEND(*-avoid-c-arrays) */
 
 void NodeProxy::infoCallback(const pw_node_info *info) noexcept
 {
@@ -1103,8 +1116,8 @@ int MetadataProxy::propertyCallback(uint32_t id, const char *key, const char *ty
         return 0;
     }
 
-    spa_json it[2]{};
-    spa_json_init(&it[0], value, strlen(value));
+    std::array<spa_json,2> it{};
+    spa_json_init(it.data(), value, strlen(value));
     if(spa_json_enter_object(&it[0], &it[1]) <= 0)
         return 0;
 
@@ -1425,7 +1438,7 @@ class PipeWirePlayback final : public BackendBase {
 
 public:
     PipeWirePlayback(DeviceBase *device) noexcept : BackendBase{device} { }
-    ~PipeWirePlayback()
+    ~PipeWirePlayback() final
     {
         /* Stop the mainloop so the stream can be properly destroyed. */
         if(mLoop) mLoop.stop();
@@ -1915,7 +1928,7 @@ class PipeWireCapture final : public BackendBase {
 
 public:
     PipeWireCapture(DeviceBase *device) noexcept : BackendBase{device} { }
-    ~PipeWireCapture() { if(mLoop) mLoop.stop(); }
+    ~PipeWireCapture() final { if(mLoop) mLoop.stop(); }
 
     DEF_NEWDEL(PipeWireCapture)
 };
@@ -2057,7 +2070,8 @@ void PipeWireCapture::open(std::string_view name)
     static constexpr uint32_t pod_buffer_size{1024};
     PodDynamicBuilder b(pod_buffer_size);
 
-    const spa_pod *params[]{spa_format_audio_raw_build(b.get(), SPA_PARAM_EnumFormat, &info)};
+    std::array params{static_cast<const spa_pod*>(spa_format_audio_raw_build(b.get(),
+        SPA_PARAM_EnumFormat, &info))};
     if(!params[0])
         throw al::backend_exception{al::backend_error::DeviceError,
             "Failed to set PipeWire audio format parameters"};
@@ -2099,7 +2113,7 @@ void PipeWireCapture::open(std::string_view name)
 
     constexpr pw_stream_flags Flags{PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE
         | PW_STREAM_FLAG_MAP_BUFFERS | PW_STREAM_FLAG_RT_PROCESS};
-    if(int res{pw_stream_connect(mStream.get(), PW_DIRECTION_INPUT, PwIdAny, Flags, params, 1)})
+    if(int res{pw_stream_connect(mStream.get(), PW_DIRECTION_INPUT, PwIdAny, Flags, params.data(), 1)})
         throw al::backend_exception{al::backend_error::DeviceError,
             "Error connecting PipeWire stream (res: %d)", res};
 
@@ -2174,7 +2188,7 @@ bool PipeWireBackendFactory::init()
     }
     TRACE("Found PipeWire version \"%s\" (%s or newer)\n", version, pw_get_headers_version());
 
-    pw_init(0, nullptr);
+    pw_init(nullptr, nullptr);
     if(!gEventHandler.init())
         return false;
 
diff --git a/alc/export_list.h b/alc/export_list.h
index c5af1ab0..7856bdc8 100644
--- a/alc/export_list.h
+++ b/alc/export_list.h
@@ -16,7 +16,8 @@ struct FuncExport {
     const char *funcName;
     void *address;
 };
-#define DECL(x) { #x, reinterpret_cast<void*>(x) }
+#define DECL(x) FuncExport{#x, reinterpret_cast<void*>(x)}
+/* NOLINTNEXTLINE(*-avoid-c-arrays) Too large for std::array auto-deduction :( */
 inline const FuncExport alcFunctions[]{
     DECL(alcCreateContext),
     DECL(alcMakeContextCurrent),
@@ -376,8 +377,9 @@ inline const FuncExport alcFunctions[]{
 
     /* Extra functions */
     DECL(alsoft_set_log_callback),
+};
 #ifdef ALSOFT_EAX
-}, eaxFunctions[]{
+inline const std::array eaxFunctions{
     DECL(EAXGet),
     DECL(EAXSet),
     DECL(EAXGetBufferMode),
@@ -387,15 +389,16 @@ inline const FuncExport alcFunctions[]{
     DECL(EAXSetDirect),
     DECL(EAXGetBufferModeDirect),
     DECL(EAXSetBufferModeDirect),
-#endif
 };
+#endif
 #undef DECL
 
 struct EnumExport {
     const char *enumName;
     int value;
 };
-#define DECL(x) { #x, (x) }
+#define DECL(x) EnumExport{#x, (x)}
+/* NOLINTNEXTLINE(*-avoid-c-arrays) Too large for std::array auto-deduction :( */
 inline const EnumExport alcEnumerations[]{
     DECL(ALC_INVALID),
     DECL(ALC_FALSE),
@@ -901,15 +904,16 @@ inline const EnumExport alcEnumerations[]{
     DECL(AL_AUXILIARY_EFFECT_SLOT_EXT),
 
     DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT),
+};
 #ifdef ALSOFT_EAX
-}, eaxEnumerations[]{
+inline const std::array eaxEnumerations{
     DECL(AL_EAX_RAM_SIZE),
     DECL(AL_EAX_RAM_FREE),
     DECL(AL_STORAGE_AUTOMATIC),
     DECL(AL_STORAGE_HARDWARE),
     DECL(AL_STORAGE_ACCESSIBLE),
-#endif // ALSOFT_EAX
 };
+#endif // ALSOFT_EAX
 #undef DECL
 
 #endif /* ALC_EXPORT_LIST_H */
diff --git a/alc/inprogext.h b/alc/inprogext.h
index 64d187f1..a150af86 100644
--- a/alc/inprogext.h
+++ b/alc/inprogext.h
@@ -1,6 +1,7 @@
 #ifndef INPROGEXT_H
 #define INPROGEXT_H
 
+/* NOLINTBEGIN */
 #include "AL/al.h"
 #include "AL/alc.h"
 #include "AL/alext.h"
@@ -436,5 +437,6 @@ void AL_APIENTRY alGetInteger64vDirectSOFT(ALCcontext *context, ALenum pname, AL
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
+/* NOLINTEND */
 
 #endif /* INPROGEXT_H */
diff --git a/common/alspan.h b/common/alspan.h
index d91747c2..37b475d2 100644
--- a/common/alspan.h
+++ b/common/alspan.h
@@ -44,7 +44,7 @@ namespace detail_ {
         && !std::is_array<C>::value && has_size_and_data<C>;
 
     template<typename T, typename U>
-    constexpr bool is_array_compatible = std::is_convertible<T(*)[],U(*)[]>::value;
+    constexpr bool is_array_compatible = std::is_convertible<T(*)[],U(*)[]>::value; /* NOLINT(*-avoid-c-arrays) */
 
     template<typename C, typename T>
     constexpr bool is_valid_container = is_valid_container_type<C>
@@ -81,7 +81,7 @@ public:
     constexpr explicit span(U first, V) : mData{::al::to_address(first)}
     {}
 
-    constexpr span(type_identity_t<element_type> (&arr)[E]) noexcept
+    constexpr span(type_identity_t<element_type> (&arr)[E]) noexcept /* NOLINT(*-avoid-c-arrays) */
         : span{std::data(arr), std::size(arr)}
     { }
     constexpr span(std::array<value_type,E> &arr) noexcept
@@ -199,7 +199,7 @@ public:
     { }
 
     template<size_t N>
-    constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept
+    constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept /* NOLINT(*-avoid-c-arrays) */
         : span{std::data(arr), std::size(arr)}
     { }
     template<size_t N>
@@ -305,7 +305,7 @@ template<typename T, typename EndOrSize>
 span(T, EndOrSize) -> span<std::remove_reference_t<decltype(*std::declval<T&>())>>;
 
 template<typename T, std::size_t N>
-span(T (&)[N]) -> span<T, N>;
+span(T (&)[N]) -> span<T, N>; /* NOLINT(*-avoid-c-arrays) */
 
 template<typename T, std::size_t N>
 span(std::array<T, N>&) -> span<T, N>;
diff --git a/core/helpers.h b/core/helpers.h
index df51c116..64fc67fb 100644
--- a/core/helpers.h
+++ b/core/helpers.h
@@ -15,11 +15,11 @@ struct PathNamePair {
         : path{std::forward<T>(path_)}, fname{std::forward<U>(fname_)}
     { }
 };
-const PathNamePair &GetProcBinary(void);
+const PathNamePair &GetProcBinary();
 
 extern int RTPrioLevel;
 extern bool AllowRTTimeLimit;
-void SetRTPriority(void);
+void SetRTPriority();
 
 std::vector<std::string> SearchDataFiles(const char *match, const char *subdir);
 
-- 
cgit v1.2.3


From 71523810a10d70c07c1009254613466405d2bee1 Mon Sep 17 00:00:00 2001
From: Chris Robinson <chris.kcat@gmail.com>
Date: Wed, 20 Dec 2023 20:37:28 -0800
Subject: Update span to better check out-of-bounds subspan requests

---
 common/alspan.h | 114 ++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 77 insertions(+), 37 deletions(-)

(limited to 'common/alspan.h')

diff --git a/common/alspan.h b/common/alspan.h
index 37b475d2..822915da 100644
--- a/common/alspan.h
+++ b/common/alspan.h
@@ -5,6 +5,7 @@
 #include <cstddef>
 #include <initializer_list>
 #include <iterator>
+#include <stdexcept>
 #include <type_traits>
 
 #include "almalloc.h"
@@ -12,7 +13,7 @@
 
 namespace al {
 
-constexpr size_t dynamic_extent{static_cast<size_t>(-1)};
+inline constexpr size_t dynamic_extent{static_cast<size_t>(-1)};
 
 template<typename T, size_t E=dynamic_extent>
 class span;
@@ -23,31 +24,31 @@ namespace detail_ {
     template<typename T, size_t E>
     struct is_span_<span<T,E>> : std::true_type { };
     template<typename T>
-    constexpr bool is_span_v = is_span_<std::remove_cv_t<T>>::value;
+    inline constexpr bool is_span_v = is_span_<std::remove_cv_t<T>>::value;
 
     template<typename T>
     struct is_std_array_ : std::false_type { };
     template<typename T, size_t N>
     struct is_std_array_<std::array<T,N>> : std::true_type { };
     template<typename T>
-    constexpr bool is_std_array_v = is_std_array_<std::remove_cv_t<T>>::value;
+    inline constexpr bool is_std_array_v = is_std_array_<std::remove_cv_t<T>>::value;
 
     template<typename T, typename = void>
-    constexpr bool has_size_and_data = false;
+    inline constexpr bool has_size_and_data = false;
     template<typename T>
-    constexpr bool has_size_and_data<T,
+    inline constexpr bool has_size_and_data<T,
         std::void_t<decltype(std::size(std::declval<T>())),decltype(std::data(std::declval<T>()))>>
         = true;
 
     template<typename C>
-    constexpr bool is_valid_container_type = !is_span_v<C> && !is_std_array_v<C>
+    inline constexpr bool is_valid_container_type = !is_span_v<C> && !is_std_array_v<C>
         && !std::is_array<C>::value && has_size_and_data<C>;
 
     template<typename T, typename U>
-    constexpr bool is_array_compatible = std::is_convertible<T(*)[],U(*)[]>::value; /* NOLINT(*-avoid-c-arrays) */
+    inline constexpr bool is_array_compatible = std::is_convertible<T(*)[],U(*)[]>::value; /* NOLINT(*-avoid-c-arrays) */
 
     template<typename C, typename T>
-    constexpr bool is_valid_container = is_valid_container_type<C>
+    inline constexpr bool is_valid_container = is_valid_container_type<C>
         && is_array_compatible<std::remove_pointer_t<decltype(std::data(std::declval<C&>()))>,T>;
 } // namespace detail_
 
@@ -79,7 +80,7 @@ public:
     constexpr explicit span(U iter, index_type) : mData{::al::to_address(iter)} { }
     template<typename U, typename V, REQUIRES(!std::is_convertible<V,size_t>::value)>
     constexpr explicit span(U first, V) : mData{::al::to_address(first)}
-    {}
+    { }
 
     constexpr span(type_identity_t<element_type> (&arr)[E]) noexcept /* NOLINT(*-avoid-c-arrays) */
         : span{std::data(arr), std::size(arr)}
@@ -107,8 +108,8 @@ public:
 
     constexpr span& operator=(const span &rhs) noexcept = default;
 
-    [[nodiscard]] constexpr auto front() const -> reference { return *mData; }
-    [[nodiscard]] constexpr auto back() const -> reference { return *(mData+E-1); }
+    [[nodiscard]] constexpr auto front() const -> reference { return mData[0]; }
+    [[nodiscard]] constexpr auto back() const -> reference { return mData[E-1]; }
     [[nodiscard]] constexpr auto operator[](index_type idx) const -> reference { return mData[idx]; }
     [[nodiscard]] constexpr auto data() const noexcept -> pointer { return mData; }
 
@@ -192,7 +193,7 @@ public:
 
     constexpr span() noexcept = default;
     template<typename U>
-    constexpr span(U iter, index_type count) : mData{::al::to_address(iter)}, mDataEnd{::al::to_address(iter) + count}
+    constexpr span(U iter, index_type count) : mData{::al::to_address(iter)}, mDataLength{count}
     { }
     template<typename U, typename V, REQUIRES(!std::is_convertible<V,size_t>::value)>
     constexpr span(U first, V last) : span{::al::to_address(first), static_cast<size_t>(last - first)}
@@ -221,20 +222,19 @@ public:
 
     constexpr span& operator=(const span &rhs) noexcept = default;
 
-    [[nodiscard]] constexpr auto front() const -> reference { return *mData; }
-    [[nodiscard]] constexpr auto back() const -> reference { return *(mDataEnd-1); }
+    [[nodiscard]] constexpr auto front() const -> reference { return mData[0]; }
+    [[nodiscard]] constexpr auto back() const -> reference { return mData[mDataLength-1]; }
     [[nodiscard]] constexpr auto operator[](index_type idx) const -> reference { return mData[idx]; }
     [[nodiscard]] constexpr auto data() const noexcept -> pointer { return mData; }
 
-    [[nodiscard]] constexpr auto size() const noexcept -> index_type { return static_cast<index_type>(mDataEnd-mData); }
-    [[nodiscard]] constexpr auto size_bytes() const noexcept -> index_type
-    { return static_cast<index_type>(mDataEnd-mData) * sizeof(value_type); }
-    [[nodiscard]] constexpr auto empty() const noexcept -> bool { return mData == mDataEnd; }
+    [[nodiscard]] constexpr auto size() const noexcept -> index_type { return mDataLength; }
+    [[nodiscard]] constexpr auto size_bytes() const noexcept -> index_type { return mDataLength * sizeof(value_type); }
+    [[nodiscard]] constexpr auto empty() const noexcept -> bool { return mDataLength == 0; }
 
     [[nodiscard]] constexpr auto begin() const noexcept -> iterator { return mData; }
-    [[nodiscard]] constexpr auto end() const noexcept -> iterator { return mDataEnd; }
+    [[nodiscard]] constexpr auto end() const noexcept -> iterator { return mData+mDataLength; }
     [[nodiscard]] constexpr auto cbegin() const noexcept -> const_iterator { return mData; }
-    [[nodiscard]] constexpr auto cend() const noexcept -> const_iterator { return mDataEnd; }
+    [[nodiscard]] constexpr auto cend() const noexcept -> const_iterator { return mData+mDataLength; }
 
     [[nodiscard]] constexpr auto rbegin() const noexcept -> reverse_iterator { return reverse_iterator{end()}; }
     [[nodiscard]] constexpr auto rend() const noexcept -> reverse_iterator { return reverse_iterator{begin()}; }
@@ -245,59 +245,99 @@ public:
 
     template<size_t C>
     [[nodiscard]] constexpr auto first() const -> span<element_type,C>
-    { return span<element_type,C>{mData, C}; }
+    {
+        if(C > mDataLength)
+            throw std::out_of_range{"Subspan count out of range"};
+        return span<element_type,C>{mData, C};
+    }
 
     [[nodiscard]] constexpr auto first(size_t count) const -> span
-    { return (count >= size()) ? *this : span{mData, mData+count}; }
+    {
+        if(count > mDataLength)
+            throw std::out_of_range{"Subspan count out of range"};
+        return span{mData, count};
+    }
 
     template<size_t C>
     [[nodiscard]] constexpr auto last() const -> span<element_type,C>
-    { return span<element_type,C>{mDataEnd-C, C}; }
+    {
+        if(C > mDataLength)
+            throw std::out_of_range{"Subspan count out of range"};
+        return span<element_type,C>{mData+mDataLength-C, C};
+    }
 
     [[nodiscard]] constexpr auto last(size_t count) const -> span
-    { return (count >= size()) ? *this : span{mDataEnd-count, mDataEnd}; }
+    {
+        if(count > mDataLength)
+            throw std::out_of_range{"Subspan count out of range"};
+        return span{mData+mDataLength-count, count};
+    }
 
     template<size_t O, size_t C>
     [[nodiscard]] constexpr auto subspan() const -> std::enable_if_t<C!=dynamic_extent,span<element_type,C>>
-    { return span<element_type,C>{mData+O, C}; }
+    {
+        if(O > mDataLength)
+            throw std::out_of_range{"Subspan offset out of range"};
+        if(C > mDataLength-O)
+            throw std::out_of_range{"Subspan length out of range"};
+        return span<element_type,C>{mData+O, C};
+    }
 
     template<size_t O, size_t C=dynamic_extent>
     [[nodiscard]] constexpr auto subspan() const -> std::enable_if_t<C==dynamic_extent,span<element_type,C>>
-    { return span<element_type,C>{mData+O, mDataEnd}; }
+    {
+        if(O > mDataLength)
+            throw std::out_of_range{"Subspan offset out of range"};
+        return span<element_type,C>{mData+O, mDataLength-O};
+    }
 
     [[nodiscard]] constexpr auto subspan(size_t offset, size_t count=dynamic_extent) const -> span
     {
-        return (offset > size()) ? span{} :
-            (count >= size()-offset) ? span{mData+offset, mDataEnd} :
-            span{mData+offset, mData+offset+count};
+        if(offset > mDataLength)
+            throw std::out_of_range{"Subspan offset out of range"};
+        if(count != dynamic_extent)
+        {
+            if(count > mDataLength-offset)
+                throw std::out_of_range{"Subspan length out of range"};
+            return span{mData+offset, count};
+        }
+        return span{mData+offset, mDataLength-offset};
     }
 
 private:
     pointer mData{nullptr};
-    pointer mDataEnd{nullptr};
+    index_type mDataLength{0};
 };
 
 template<typename T, size_t E>
 [[nodiscard]] constexpr inline auto span<T,E>::first(size_t count) const -> span<element_type,dynamic_extent>
 {
-    return (count >= size()) ? span<element_type>{mData, extent} :
-        span<element_type>{mData, count};
+    if(count > size())
+        throw std::out_of_range{"Subspan count out of range"};
+    return span<element_type>{mData, count};
 }
 
 template<typename T, size_t E>
 [[nodiscard]] constexpr inline auto span<T,E>::last(size_t count) const -> span<element_type,dynamic_extent>
 {
-    return (count >= size()) ? span<element_type>{mData, extent} :
-        span<element_type>{mData+extent-count, count};
+    if(count > size())
+        throw std::out_of_range{"Subspan count out of range"};
+    return span<element_type>{mData+size()-count, count};
 }
 
 template<typename T, size_t E>
 [[nodiscard]] constexpr inline auto span<T,E>::subspan(size_t offset, size_t count) const
     -> span<element_type,dynamic_extent>
 {
-    return (offset > size()) ? span<element_type>{} :
-        (count >= size()-offset) ? span<element_type>{mData+offset, mData+extent} :
-        span<element_type>{mData+offset, mData+offset+count};
+    if(offset > size())
+        throw std::out_of_range{"Subspan offset out of range"};
+    if(count != dynamic_extent)
+    {
+        if(count > size()-offset)
+            throw std::out_of_range{"Subspan length out of range"};
+        return span{mData+offset, count};
+    }
+    return span{mData+offset, size()-offset};
 }
 
 
-- 
cgit v1.2.3