Build v3 C under clang -Weverything and MSVC /W4 Escalate v3 C warning levels in CI to catch latent issues: gcc/clang now run with -Werror, clang adds -Weverything (with a small irreducible suppression list for -Wpadded, -Wunsafe-buffer-usage, -Wcast-align, etc.), and a new MSVC job builds tester_v3_c with /W4 /WX. Source fixes to clear the elevated warnings: - tg3__arena_new_block: cast through void* to silence -Wcast-align. - tg3__value_to_json: handle TG3_VALUE_BINARY explicitly and drop the default label so -Wswitch-enum and -Wcovered-switch-default agree. - Drop unused tg3__json_set_value_copy. - tinygltf_json_c.h: enumerate all tg3json_value_type cases in tg3json_value_free / tg3json_value_copy / tg3json__stringify_value_ex. - tester_v3_c_v1port FAIL macro: split the format/newline prints so it no longer relies on the GNU `, ##__VA_ARGS__` extension. Verified: clang -Werror -Weverything builds clean, 13/13 internal tests, 18/18 v1-port tests, and 134/134 cross-version regression all pass. 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 99a3ef3..5bdc4d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml
@@ -340,13 +340,13 @@ - name: Build tester_v3_c run: | cd tests - cc -I../ -std=c11 -g -O0 -Wall -Wextra -DTINYGLTF3_ENABLE_FS \ + cc -I../ -std=c11 -g -O0 -Wall -Wextra -Wpedantic -Werror -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 -Wall -Wextra -DTINYGLTF3_ENABLE_FS \ + cc -I../ -std=c11 -g -O0 -Wall -Wextra -Wpedantic -Werror -DTINYGLTF3_ENABLE_FS \ -o tester_v3_c_v1port tester_v3_c_v1port.c ../tiny_gltf_v3.c - name: Run tester_v3_c (security regressions) @@ -375,13 +375,21 @@ - name: Build tester_v3_c run: | cd tests - clang -I../ -std=c11 -g -O0 -Wall -Wextra -DTINYGLTF3_ENABLE_FS \ + clang -I../ -std=c11 -g -O0 -Werror -Weverything \ + -Wno-padded -Wno-unsafe-buffer-usage -Wno-switch-default \ + -Wno-format-nonliteral -Wno-float-equal -Wno-cast-align \ + -Wno-declaration-after-statement -Wno-pre-c11-compat \ + -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 \ + clang -I../ -std=c11 -g -O0 -Werror -Weverything \ + -Wno-padded -Wno-unsafe-buffer-usage -Wno-switch-default \ + -Wno-format-nonliteral -Wno-float-equal -Wno-cast-align \ + -Wno-declaration-after-statement -Wno-pre-c11-compat \ + -DTINYGLTF3_ENABLE_FS \ -o tester_v3_c_v1port tester_v3_c_v1port.c ../tiny_gltf_v3.c - name: Run tester_v3_c @@ -411,13 +419,21 @@ - name: Build tester_v3_c run: | cd tests - clang-21 -I../ -std=c11 -g -O0 -Wall -Wextra -DTINYGLTF3_ENABLE_FS \ + clang-21 -I../ -std=c11 -g -O0 -Werror -Weverything \ + -Wno-padded -Wno-unsafe-buffer-usage -Wno-switch-default \ + -Wno-format-nonliteral -Wno-float-equal -Wno-cast-align \ + -Wno-declaration-after-statement -Wno-pre-c11-compat \ + -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 \ + clang-21 -I../ -std=c11 -g -O0 -Werror -Weverything \ + -Wno-padded -Wno-unsafe-buffer-usage -Wno-switch-default \ + -Wno-format-nonliteral -Wno-float-equal -Wno-cast-align \ + -Wno-declaration-after-statement -Wno-pre-c11-compat \ + -DTINYGLTF3_ENABLE_FS \ -o tester_v3_c_v1port tester_v3_c_v1port.c ../tiny_gltf_v3.c - name: Run tester_v3_c @@ -430,6 +446,30 @@ cd tests ./tester_v3_c_v1port + # v3 C runtime built with MSVC at warning-level 4 (/W4 /WX). + v3-c-tests-msvc: + runs-on: windows-latest + name: v3 C tests (Windows x64, MSVC /W4) + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build and run tester_v3_c + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + cd tests + cl /nologo /W4 /WX /std:c11 /Zi /Od /DTINYGLTF3_ENABLE_FS /I.. tester_v3_c.c ..\tiny_gltf_v3.c /Fe:tester_v3_c.exe + tester_v3_c.exe + + - name: Build and run tester_v3_c_v1port + shell: cmd + run: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" + cd tests + cl /nologo /W4 /WX /std:c11 /Zi /Od /DTINYGLTF3_ENABLE_FS /I.. tester_v3_c_v1port.c ..\tiny_gltf_v3.c /Fe:tester_v3_c_v1port.exe + tester_v3_c_v1port.exe + # v3 C runtime under ASan + UBSan for memory-safety + UB checks. v3-c-tests-sanitizers: runs-on: ubuntu-latest
diff --git a/tests/tester_v3_c_v1port.c b/tests/tester_v3_c_v1port.c index af21343..8e5103f 100644 --- a/tests/tester_v3_c_v1port.c +++ b/tests/tester_v3_c_v1port.c
@@ -135,8 +135,10 @@ fprintf(stdout, " [PASS] %s\n", label); \ return 1; \ } while (0) -#define FAIL(fmt, ...) do { \ - fprintf(stderr, " [FAIL] " fmt "\n", ##__VA_ARGS__); \ +#define FAIL(...) do { \ + fprintf(stderr, " [FAIL] "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ goto fail; \ } while (0)
diff --git a/tiny_gltf_v3.c b/tiny_gltf_v3.c index 1aa4bc7..f7a0d50 100644 --- a/tiny_gltf_v3.c +++ b/tiny_gltf_v3.c
@@ -98,17 +98,17 @@ static tg3__arena_block *tg3__arena_new_block(tg3_arena *arena, size_t min_size) { size_t cap = arena->block_size; - uint8_t *raw; + void *raw; tg3__arena_block *block; if (cap < min_size) cap = min_size; if (arena->max_single_alloc && cap > arena->max_single_alloc) return NULL; if (arena->total_allocated + sizeof(tg3__arena_block) + cap > arena->memory_budget) return NULL; - raw = (uint8_t *)arena->alloc.alloc(sizeof(tg3__arena_block) + cap, arena->alloc.user_data); + raw = arena->alloc.alloc(sizeof(tg3__arena_block) + cap, arena->alloc.user_data); if (!raw) return NULL; block = (tg3__arena_block *)raw; block->next = NULL; - block->base = raw + sizeof(tg3__arena_block); + block->base = (uint8_t *)raw + sizeof(tg3__arena_block); block->used = 0; block->capacity = cap; arena->total_allocated += sizeof(tg3__arena_block) + cap; @@ -2171,10 +2171,6 @@ return tg3__json_set_string_n(obj, key, str, str ? strlen(str) : 0); } -static int tg3__json_set_value_copy(tg3json_value *obj, const char *key, const tg3json_value *value) { - return tg3json_object_set_copy(obj, key, value); -} - static int tg3__json_array_append_int(tg3json_value *arr, int64_t value) { tg3json_value tmp; tg3json_value_init_int(&tmp, value); @@ -2370,9 +2366,11 @@ } } return 1; - default: - return 0; + case TG3_VALUE_BINARY: + /* Binary blobs cannot be represented as JSON; emit null. */ + return 1; } + return 0; /* unreachable: all enum cases handled above. */ } static int tg3__serialize_extras_ext(tg3json_value *o, const tg3_extras_ext *ee) {
diff --git a/tinygltf_json_c.h b/tinygltf_json_c.h index 67971a6..13bf284 100644 --- a/tinygltf_json_c.h +++ b/tinygltf_json_c.h
@@ -641,7 +641,11 @@ } free(value->u.object.items); break; - default: + case TG3JSON_NULL: + case TG3JSON_BOOL: + case TG3JSON_INT: + case TG3JSON_REAL: + /* Scalar variants own no heap memory. */ break; } tg3json__init_value(value); @@ -733,9 +737,8 @@ } } return 1; - default: - return 0; } + return 0; /* unreachable: all enum cases handled above. */ } const tg3json_value *tg3json_object_get_n(const tg3json_value *object, @@ -973,9 +976,8 @@ } if (indent > 0 && value->u.object.count > 0 && !tg3json__indent(buf, indent, depth)) return 0; return tg3json__buf_putc(buf, '}'); - default: - return 0; } + return 0; /* unreachable: all enum cases handled above. */ } char *tg3json_stringify(const tg3json_value *value, size_t *out_len) {