Build v3 C tests under clang too; drop GNU VA_ARGS extension ci.yml now runs the v3 C suites under three Linux toolchains: - v3-c-tests (default cc / GCC, -Wall -Wextra) - v3-c-tests-clang (stock Ubuntu clang) - v3-c-tests-clang21 (clang 21 from apt.llvm.org, matching local dev) The validator helper macros TG3__IDX_BAD / TG3__CHECK_REQ / TG3__CHECK_OPT used the GNU `, ##__VA_ARGS__` extension, which clang flags under -Wpedantic. Every call site already passes at least one variadic argument, so plain __VA_ARGS__ (C11) suffices. Local verification: clang-21 -Wall -Wextra builds tester_v3_c and tester_v3_c_v1port with zero warnings introduced by the v3 changes (only the pre-existing tg3__json_set_value_copy unused-function notice remains, unrelated to this work). All suites pass under gcc 13.3 and clang 21.1 alike, plus the 134-model cross-version verifier. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c65f976..99a3ef3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml
@@ -332,7 +332,7 @@ # v3 C runtime: internal security regression tests + ported v1 unit tests. v3-c-tests: runs-on: ubuntu-latest - name: v3 C tests (Linux x64) + name: v3 C tests (Linux x64, GCC) steps: - name: Checkout uses: actions/checkout@v4 @@ -340,13 +340,13 @@ - name: Build tester_v3_c run: | cd tests - cc -I../ -std=c11 -g -O0 -DTINYGLTF3_ENABLE_FS \ + cc -I../ -std=c11 -g -O0 -Wall -Wextra -DTINYGLTF3_ENABLE_FS \ -o tester_v3_c tester_v3_c.c ../tiny_gltf_v3.c - name: Build tester_v3_c_v1port run: | cd tests - cc -I../ -std=c11 -g -O0 -DTINYGLTF3_ENABLE_FS \ + cc -I../ -std=c11 -g -O0 -Wall -Wextra -DTINYGLTF3_ENABLE_FS \ -o tester_v3_c_v1port tester_v3_c_v1port.c ../tiny_gltf_v3.c - name: Run tester_v3_c (security regressions) @@ -359,6 +359,77 @@ cd tests ./tester_v3_c_v1port + # v3 C runtime under stock Ubuntu clang. + v3-c-tests-clang: + runs-on: ubuntu-latest + name: v3 C tests (Linux x64, Clang) + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install clang + run: | + sudo apt-get update + sudo apt-get install -y clang + + - name: Build tester_v3_c + run: | + cd tests + clang -I../ -std=c11 -g -O0 -Wall -Wextra -DTINYGLTF3_ENABLE_FS \ + -o tester_v3_c tester_v3_c.c ../tiny_gltf_v3.c + + - name: Build tester_v3_c_v1port + run: | + cd tests + clang -I../ -std=c11 -g -O0 -Wall -Wextra -DTINYGLTF3_ENABLE_FS \ + -o tester_v3_c_v1port tester_v3_c_v1port.c ../tiny_gltf_v3.c + + - name: Run tester_v3_c + run: | + cd tests + ./tester_v3_c + + - name: Run tester_v3_c_v1port + run: | + cd tests + ./tester_v3_c_v1port + + # v3 C runtime under bleeding-edge clang 21 (matches local dev environment). + v3-c-tests-clang21: + runs-on: ubuntu-24.04 + name: v3 C tests (Linux x64, Clang 21) + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install clang 21 + run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 21 + + - name: Build tester_v3_c + run: | + cd tests + clang-21 -I../ -std=c11 -g -O0 -Wall -Wextra -DTINYGLTF3_ENABLE_FS \ + -o tester_v3_c tester_v3_c.c ../tiny_gltf_v3.c + + - name: Build tester_v3_c_v1port + run: | + cd tests + clang-21 -I../ -std=c11 -g -O0 -Wall -Wextra -DTINYGLTF3_ENABLE_FS \ + -o tester_v3_c_v1port tester_v3_c_v1port.c ../tiny_gltf_v3.c + + - name: Run tester_v3_c + run: | + cd tests + ./tester_v3_c + + - name: Run tester_v3_c_v1port + run: | + cd tests + ./tester_v3_c_v1port + # v3 C runtime under ASan + UBSan for memory-safety + UB checks. v3-c-tests-sanitizers: runs-on: ubuntu-latest
diff --git a/tiny_gltf_v3.c b/tiny_gltf_v3.c index 1d35b49..1aa4bc7 100644 --- a/tiny_gltf_v3.c +++ b/tiny_gltf_v3.c
@@ -1617,22 +1617,24 @@ static int tg3__validate_indices(tg3__parse_ctx *ctx, const tg3_model *m) { uint32_t i, j; int errs = 0; - /* Helper macros — push with format and bump error counter. */ + /* Helper macros — push with format and bump error counter. Every call + * site passes at least one variadic arg, so plain __VA_ARGS__ (C11) is + * sufficient and avoids the GNU `, ##__VA_ARGS__` extension. */ #define TG3__IDX_BAD(path_str, fmt, ...) do { \ if (errs < TG3__IDX_ERR_CAP) { \ tg3__error_pushf(ctx->errors, ctx->arena, TG3_SEVERITY_ERROR, \ - TG3_ERR_INVALID_INDEX, (path_str), fmt, ##__VA_ARGS__); \ + TG3_ERR_INVALID_INDEX, (path_str), fmt, __VA_ARGS__); \ } \ ++errs; \ } while (0) #define TG3__CHECK_REQ(idx, max, path_str, fmt, ...) do { \ if ((idx) < 0 || (uint32_t)(idx) >= (max)) { \ - TG3__IDX_BAD(path_str, fmt, ##__VA_ARGS__); \ + TG3__IDX_BAD(path_str, fmt, __VA_ARGS__); \ } \ } while (0) #define TG3__CHECK_OPT(idx, max, path_str, fmt, ...) do { \ if ((idx) != -1 && ((idx) < 0 || (uint32_t)(idx) >= (max))) { \ - TG3__IDX_BAD(path_str, fmt, ##__VA_ARGS__); \ + TG3__IDX_BAD(path_str, fmt, __VA_ARGS__); \ } \ } while (0)