From 9af6e969a1a7338e98a2d667e28bdc29b83ba91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Wed, 21 Oct 2026 15:26:25 -0700 Subject: [PATCH] Validate sorted lookup tables at compile time. (#4078) --- src/shader.cpp | 9 ++++++--- src/vertexlayout.cpp | 6 ++++-- tools/shaderc/pp.cpp | 10 +++++++--- tools/texturev/texturev.cpp | 3 --- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/shader.cpp b/src/shader.cpp index 7d748cec5..9cab403c7 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -13,7 +13,7 @@ namespace bgfx uint16_t id; }; - static DescriptorTypeToId s_descriptorTypeToId[] = + static constexpr DescriptorTypeToId s_descriptorTypeToId[] = { // NOTICE: // DescriptorType must be in order how it appears in DescriptorType::Enum! id is @@ -22,6 +22,7 @@ namespace bgfx { DescriptorType::StorageImage, 0x0003 }, }; static_assert(BX_COUNTOF(s_descriptorTypeToId) == DescriptorType::Count); + static_assert(bx::isSorted(s_descriptorTypeToId, BX_COUNTOF(s_descriptorTypeToId), [](const DescriptorTypeToId& _lhs, const DescriptorTypeToId& _rhs) { return _lhs.type <= _rhs.type; }) ); DescriptorType::Enum idToDescriptorType(uint16_t _id) { @@ -47,7 +48,7 @@ namespace bgfx uint8_t id; }; - static TextureComponentTypeToId s_textureComponentTypeToId[] = + static constexpr TextureComponentTypeToId s_textureComponentTypeToId[] = { // see comment in s_descriptorTypeToId { TextureComponentType::Float, 0x00 }, @@ -57,6 +58,7 @@ namespace bgfx { TextureComponentType::UnfilterableFloat, 0x04 }, }; static_assert(BX_COUNTOF(s_textureComponentTypeToId) == TextureComponentType::Count); + static_assert(bx::isSorted(s_textureComponentTypeToId, BX_COUNTOF(s_textureComponentTypeToId), [](const TextureComponentTypeToId& _lhs, const TextureComponentTypeToId& _rhs) { return _lhs.type <= _rhs.type; }) ); TextureComponentType::Enum idToTextureComponentType(uint8_t _id) { @@ -82,7 +84,7 @@ namespace bgfx uint8_t id; }; - static TextureDimensionToId s_textureDimensionToId[] = + static constexpr TextureDimensionToId s_textureDimensionToId[] = { // see comment in s_descriptorTypeToId { TextureDimension::Dimension1D, 0x01 }, @@ -95,6 +97,7 @@ namespace bgfx { TextureDimension::Dimension2DMSArray, 0x08 }, }; static_assert(BX_COUNTOF(s_textureDimensionToId) == TextureDimension::Count); + static_assert(bx::isSorted(s_textureDimensionToId, BX_COUNTOF(s_textureDimensionToId), [](const TextureDimensionToId& _lhs, const TextureDimensionToId& _rhs) { return _lhs.dimension <= _rhs.dimension; }) ); TextureDimension::Enum idToTextureDimension(uint8_t _id) { diff --git a/src/vertexlayout.cpp b/src/vertexlayout.cpp index 9671d2ccc..ef517c969 100644 --- a/src/vertexlayout.cpp +++ b/src/vertexlayout.cpp @@ -187,7 +187,7 @@ namespace bgfx uint16_t id; }; - static AttribToId s_attribToId[] = + static constexpr AttribToId s_attribToId[] = { // NOTICE: // Attrib must be in order how it appears in Attrib::Enum! id is @@ -220,6 +220,7 @@ namespace bgfx { Attrib::TexCoord15, 0x0021 }, }; static_assert(BX_COUNTOF(s_attribToId) == Attrib::Count); + static_assert(bx::isSorted(s_attribToId, BX_COUNTOF(s_attribToId), [](const AttribToId& _lhs, const AttribToId& _rhs) { return _lhs.attr <= _rhs.attr; }) ); Attrib::Enum idToAttrib(uint16_t id) { @@ -245,7 +246,7 @@ namespace bgfx uint16_t id; }; - static AttribTypeToId s_attribTypeToId[] = + static constexpr AttribTypeToId s_attribTypeToId[] = { // NOTICE: // AttribType must be in order how it appears in AttribType::Enum! @@ -262,6 +263,7 @@ namespace bgfx { AttribType::Uint32, 0x0009 }, }; static_assert(BX_COUNTOF(s_attribTypeToId) == AttribType::Count); + static_assert(bx::isSorted(s_attribTypeToId, BX_COUNTOF(s_attribTypeToId), [](const AttribTypeToId& _lhs, const AttribTypeToId& _rhs) { return _lhs.type <= _rhs.type; }) ); AttribType::Enum idToAttribType(uint16_t id) { diff --git a/tools/shaderc/pp.cpp b/tools/shaderc/pp.cpp index 496cf84d2..dfe660a05 100644 --- a/tools/shaderc/pp.cpp +++ b/tools/shaderc/pp.cpp @@ -745,9 +745,14 @@ namespace shaderc , ( (const OpInfo*)_rhs)->lexeme ); } + + static constexpr bool lessFn(const OpInfo& _lhs, const OpInfo& _rhs) + { + return 0 >= bx::strCmp(_lhs.lexeme, _rhs.lexeme); + } }; - static const OpInfo s_ops[] = + static constexpr OpInfo s_ops[] = { { "!=", 6 }, { "%", 10 }, @@ -769,6 +774,7 @@ namespace shaderc { "||", 1 }, }; static_assert(uint8_t(Op::Count) == BX_COUNTOF(s_ops), "s_ops must match Op."); + static_assert(bx::isSorted(s_ops, BX_COUNTOF(s_ops), OpInfo::lessFn), "s_ops must be sorted!"); Op findOp(const bx::StringView& _lexeme) { @@ -2917,8 +2923,6 @@ namespace shaderc bool run(const bx::StringView& _name, const bx::StringView& _source, bx::WriterI* _writer, bx::Error* _err) { - BX_ASSERT(bx::isSorted(s_ops, BX_COUNTOF(s_ops), OpInfo::cmpFn), "s_ops must be sorted!"); - m_out = _writer; m_err.reset(); m_ok = true; diff --git a/tools/texturev/texturev.cpp b/tools/texturev/texturev.cpp index 1cb1fad6f..ee141ca4f 100644 --- a/tools/texturev/texturev.cpp +++ b/tools/texturev/texturev.cpp @@ -93,9 +93,6 @@ static void initSupportedExt() } BX_ASSERT(NULL == supportedExt[s_numSupportedExt], "s_supportedExt array is too small."); - BX_ASSERT(bx::isSorted(s_supportedExt, s_numSupportedExt, sizeof(s_supportedExt[0]), compareExt) - , "s_supportedExt must be sorted!" - ); } static bool isExtSupported(const bx::StringView& _ext)