@@ -67,10 +67,11 @@ CFLAGS_TEST = $(CFLAGS_COMMON) -g -O1 $(SANITIZE)
6767CXXFLAGS_TEST = $(CXXFLAGS_COMMON) -g -O1 $(SANITIZE)
6868
6969# TSan (can't combine with ASan)
70+ TSAN_SANITIZE = -fsanitize=thread -fno-omit-frame-pointer
7071CFLAGS_TSAN = $(CFLAGS_COMMON) -g -O1 \
71- -fsanitize=thread -fno-omit-frame-pointer
72+ $(TSAN_SANITIZE)
7273CXXFLAGS_TSAN = $(CXXFLAGS_COMMON) -g -O1 \
73- -fsanitize=thread -fno-omit-frame-pointer
74+ $(TSAN_SANITIZE)
7475
7576# Windows needs ws2_32 (Winsock), psapi (GetProcessMemoryInfo), shell32
7677# (CommandLineToArgvW — the UTF-8 argv path in main.c, #423/#20), and
8990
9091LDFLAGS = -lm -lstdc++ -lpthread -lz $(WIN32_LIBS) $(STATIC_FLAGS)
9192LDFLAGS_TEST = -lm -lstdc++ -lpthread -lz $(SANITIZE) $(WIN32_LIBS)
92- LDFLAGS_TSAN = -lm -lstdc++ -lpthread -lz -fsanitize=thread $(WIN32_LIBS)
93+ LDFLAGS_TSAN = -lm -lstdc++ -lpthread -lz $(TSAN_SANITIZE) $(WIN32_LIBS)
9394
9495# ── Source files ─────────────────────────────────────────────────
9596
@@ -317,6 +318,7 @@ TEST_EXTRACTION_SRCS = \
317318 tests/test_extraction.c \
318319 tests/test_extraction_inheritance.c \
319320 tests/test_extraction_imports.c \
321+ tests/test_parse_coverage.c \
320322 tests/test_grammar_regression.c \
321323 tests/test_grammar_labels.c \
322324 tests/test_grammar_imports.c \
@@ -445,6 +447,7 @@ TEST_REPRO_SRCS = \
445447 tests/repro/repro_issue363.c \
446448 tests/repro/repro_issue581.c \
447449 tests/repro/repro_issue787.c \
450+ tests/repro/repro_issue842.c \
448451 tests/repro/repro_invariant_calls.c \
449452 tests/repro/repro_invariant_graph.c \
450453 tests/repro/repro_invariant_breadth.c \
@@ -483,13 +486,17 @@ GRAMMAR_CFLAGS = -std=c11 -D_DEFAULT_SOURCE -O2 -w -I$(CBM_DIR) -I$(TS_INCLUDE)
483486GRAMMAR_CFLAGS_TEST = -std=c11 -D_DEFAULT_SOURCE -g -O1 -w -I$(CBM_DIR) -I$(TS_INCLUDE) -I$(TS_SRC) \
484487 $(SANITIZE)
485488GRAMMAR_CFLAGS_TSAN = -std=c11 -D_DEFAULT_SOURCE -g -O1 -w -I$(CBM_DIR) -I$(TS_INCLUDE) -I$(TS_SRC) \
486- -fsanitize=thread -fno-omit-frame-pointer
489+ $(TSAN_SANITIZE)
487490
488491# Object files for grammars + ts_runtime + lsp_all + preprocessor
489492GRAMMAR_OBJS_TEST = $(patsubst $(CBM_DIR)/%.c,$(BUILD_DIR)/%.o,$(GRAMMAR_SRCS))
490493TS_RUNTIME_OBJ_TEST = $(BUILD_DIR)/ts_runtime.o
491494LSP_OBJ_TEST = $(BUILD_DIR)/lsp_all.o
492495PP_OBJ_TEST = $(BUILD_DIR)/preprocessor.o
496+ GRAMMAR_OBJS_TSAN = $(patsubst $(CBM_DIR)/%.c,$(BUILD_DIR)/tsan_%.o,$(GRAMMAR_SRCS))
497+ TS_RUNTIME_OBJ_TSAN = $(BUILD_DIR)/tsan_ts_runtime.o
498+ LSP_OBJ_TSAN = $(BUILD_DIR)/tsan_lsp_all.o
499+ PP_OBJ_TSAN = $(BUILD_DIR)/tsan_preprocessor.o
493500
494501# ── Targets ──────────────────────────────────────────────────────
495502
@@ -520,60 +527,94 @@ $(BUILD_DIR)/lsp_all.o: $(LSP_UNITY_DEPS) | $(BUILD_DIR)
520527$(BUILD_DIR)/preprocessor.o: $(CBM_DIR)/preprocessor.cpp | $(BUILD_DIR)
521528 $(CXX) $(CXXFLAGS_TEST) -w -I$(CBM_DIR)/vendored -c -o $@ $<
522529
530+ $(BUILD_DIR)/tsan_%.o: $(CBM_DIR)/%.c | $(BUILD_DIR)
531+ $(CC) $(GRAMMAR_CFLAGS_TSAN) -c -o $@ $<
532+
533+ $(BUILD_DIR)/tsan_ts_runtime.o: $(CBM_DIR)/ts_runtime.c | $(BUILD_DIR)
534+ $(CC) $(GRAMMAR_CFLAGS_TSAN) -c -o $@ $<
535+
536+ $(BUILD_DIR)/tsan_lsp_all.o: $(LSP_UNITY_DEPS) | $(BUILD_DIR)
537+ $(CC) $(GRAMMAR_CFLAGS_TSAN) -c -o $@ $<
538+
539+ $(BUILD_DIR)/tsan_preprocessor.o: $(CBM_DIR)/preprocessor.cpp | $(BUILD_DIR)
540+ $(CXX) $(CXXFLAGS_TSAN) -w -I$(CBM_DIR)/vendored -c -o $@ $<
541+
523542# ── Full test binary ─────────────────────────────────────────────
524543
525544# mimalloc object files
526545MIMALLOC_OBJ_TEST = $(BUILD_DIR)/mimalloc.o
546+ MIMALLOC_OBJ_TSAN = $(BUILD_DIR)/tsan_mimalloc.o
527547MIMALLOC_OBJ_PROD = $(BUILD_DIR)/prod_mimalloc.o
528548
529549$(BUILD_DIR)/mimalloc.o: $(MIMALLOC_SRC) | $(BUILD_DIR)
530550 $(CC) $(MIMALLOC_CFLAGS_TEST) -c -o $@ $<
531551
552+ $(BUILD_DIR)/tsan_mimalloc.o: $(MIMALLOC_SRC) | $(BUILD_DIR)
553+ $(CC) $(MIMALLOC_CFLAGS_TEST) $(TSAN_SANITIZE) -c -o $@ $<
554+
532555$(BUILD_DIR)/prod_mimalloc.o: $(MIMALLOC_SRC) | $(BUILD_DIR)
533556 $(CC) $(MIMALLOC_CFLAGS) -c -o $@ $<
534557
535558# sqlite3 object files (vendored amalgamation)
536559SQLITE3_OBJ_TEST = $(BUILD_DIR)/sqlite3.o
560+ SQLITE3_OBJ_TSAN = $(BUILD_DIR)/tsan_sqlite3.o
537561SQLITE3_OBJ_PROD = $(BUILD_DIR)/prod_sqlite3.o
538562
539563$(BUILD_DIR)/sqlite3.o: $(SQLITE3_SRC) | $(BUILD_DIR)
540564 $(CC) $(SQLITE3_CFLAGS_TEST) $(SANITIZE) -c -o $@ $<
541565
566+ $(BUILD_DIR)/tsan_sqlite3.o: $(SQLITE3_SRC) | $(BUILD_DIR)
567+ $(CC) $(SQLITE3_CFLAGS_TEST) $(TSAN_SANITIZE) -c -o $@ $<
568+
542569$(BUILD_DIR)/prod_sqlite3.o: $(SQLITE3_SRC) | $(BUILD_DIR)
543570 $(CC) $(SQLITE3_CFLAGS) -c -o $@ $<
544571
545572# TRE regex (only compiled on Windows — POSIX uses system <regex.h>)
546573TRE_OBJ_TEST :=
574+ TRE_OBJ_TSAN :=
547575TRE_OBJ_PROD :=
548576ifeq ($(IS_MINGW),yes)
549577TRE_OBJ_TEST = $(BUILD_DIR)/tre.o
578+ TRE_OBJ_TSAN = $(BUILD_DIR)/tsan_tre.o
550579TRE_OBJ_PROD = $(BUILD_DIR)/prod_tre.o
551580
552581$(BUILD_DIR)/tre.o: $(TRE_SRC) | $(BUILD_DIR)
553582 $(CC) $(TRE_CFLAGS) $(SANITIZE) -fno-sanitize=alignment -c -o $@ $<
554583
584+ $(BUILD_DIR)/tsan_tre.o: $(TRE_SRC) | $(BUILD_DIR)
585+ $(CC) $(TRE_CFLAGS) $(TSAN_SANITIZE) -c -o $@ $<
586+
555587$(BUILD_DIR)/prod_tre.o: $(TRE_SRC) | $(BUILD_DIR)
556588 $(CC) $(TRE_CFLAGS) -O2 -c -o $@ $<
557589endif
558590
559591# Vendored LZ4 (test build)
560592LZ4_OBJ_TEST = $(BUILD_DIR)/test_lz4.o $(BUILD_DIR)/test_lz4hc.o
593+ LZ4_OBJ_TSAN = $(BUILD_DIR)/tsan_lz4.o $(BUILD_DIR)/tsan_lz4hc.o
561594$(BUILD_DIR)/test_lz4.o: $(CBM_DIR)/vendored/lz4/lz4.c | $(BUILD_DIR)
562595 $(CC) -std=c11 -D_DEFAULT_SOURCE -g -O1 $(SANITIZE) -w -I$(CBM_DIR) -c -o $@ $<
563596$(BUILD_DIR)/test_lz4hc.o: $(CBM_DIR)/vendored/lz4/lz4hc.c | $(BUILD_DIR)
564597 $(CC) -std=c11 -D_DEFAULT_SOURCE -g -O1 $(SANITIZE) -w -I$(CBM_DIR)/vendored/lz4 -c -o $@ $<
598+ $(BUILD_DIR)/tsan_lz4.o: $(CBM_DIR)/vendored/lz4/lz4.c | $(BUILD_DIR)
599+ $(CC) -std=c11 -D_DEFAULT_SOURCE -g -O1 $(TSAN_SANITIZE) -w -I$(CBM_DIR) -c -o $@ $<
600+ $(BUILD_DIR)/tsan_lz4hc.o: $(CBM_DIR)/vendored/lz4/lz4hc.c | $(BUILD_DIR)
601+ $(CC) -std=c11 -D_DEFAULT_SOURCE -g -O1 $(TSAN_SANITIZE) -w -I$(CBM_DIR)/vendored/lz4 -c -o $@ $<
565602
566603# Vendored zstd (test build)
567604ZSTD_OBJ_TEST = $(BUILD_DIR)/test_zstd.o
605+ ZSTD_OBJ_TSAN = $(BUILD_DIR)/tsan_zstd.o
568606$(BUILD_DIR)/test_zstd.o: $(CBM_DIR)/vendored/zstd/zstd.c | $(BUILD_DIR)
569607 $(CC) -std=c11 -D_DEFAULT_SOURCE -g -O1 $(SANITIZE) -w -I$(CBM_DIR)/vendored/zstd -c -o $@ $<
608+ $(BUILD_DIR)/tsan_zstd.o: $(CBM_DIR)/vendored/zstd/zstd.c | $(BUILD_DIR)
609+ $(CC) -std=c11 -D_DEFAULT_SOURCE -g -O1 $(TSAN_SANITIZE) -w -I$(CBM_DIR)/vendored/zstd -c -o $@ $<
570610
571611# nomic-embed-code pretrained vector blob
572612UNIXCODER_OBJ = $(BUILD_DIR)/unixcoder_blob.o
573613$(UNIXCODER_OBJ): $(UNIXCODER_BLOB_SRC) vendored/nomic/code_vectors.bin | $(BUILD_DIR)
574614 $(CC) -c -o $@ $<
575615
576616OBJS_VENDORED_TEST = $(MIMALLOC_OBJ_TEST) $(SQLITE3_OBJ_TEST) $(TRE_OBJ_TEST) $(GRAMMAR_OBJS_TEST) $(TS_RUNTIME_OBJ_TEST) $(LSP_OBJ_TEST) $(PP_OBJ_TEST) $(LZ4_OBJ_TEST) $(ZSTD_OBJ_TEST) $(UNIXCODER_OBJ)
617+ OBJS_VENDORED_TSAN = $(MIMALLOC_OBJ_TSAN) $(SQLITE3_OBJ_TSAN) $(TRE_OBJ_TSAN) $(GRAMMAR_OBJS_TSAN) $(TS_RUNTIME_OBJ_TSAN) $(LSP_OBJ_TSAN) $(PP_OBJ_TSAN) $(LZ4_OBJ_TSAN) $(ZSTD_OBJ_TSAN) $(UNIXCODER_OBJ)
577618
578619$(BUILD_DIR)/test-runner: $(ALL_TEST_SRCS) $(PROD_SRCS) $(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) $(OBJS_VENDORED_TEST) | $(BUILD_DIR)
579620 $(CC) $(CFLAGS_TEST) -Itests -Itests/repro -o $@ \
@@ -601,8 +642,18 @@ test-repro: $(BUILD_DIR)/test-repro-runner
601642
602643# ── TSan full test ───────────────────────────────────────────────
603644
604- test-tsan:
605- @echo "TSan not yet wired for full extraction tests"
645+ TEST_TSAN_SUITES ?= mem slab_alloc parallel
646+ TSAN_OPTIONS ?= halt_on_error=1
647+
648+ $(BUILD_DIR)/test-runner-tsan: $(ALL_TEST_SRCS) $(PROD_SRCS) $(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) $(OBJS_VENDORED_TSAN) | $(BUILD_DIR)
649+ $(CC) $(CFLAGS_TSAN) -Itests -Itests/repro -o $@ \
650+ $(ALL_TEST_SRCS) $(PROD_SRCS) \
651+ $(EXTRACTION_SRCS) $(AC_LZ4_SRCS) $(ZSTD_SRCS) $(SQLITE_WRITER_SRC) \
652+ $(OBJS_VENDORED_TSAN) \
653+ $(LDFLAGS_TSAN)
654+
655+ test-tsan: $(BUILD_DIR)/test-runner-tsan
656+ cd $(CURDIR) && TSAN_OPTIONS="$(TSAN_OPTIONS)" $(BUILD_DIR)/test-runner-tsan $(TEST_TSAN_SUITES)
606657
607658# ── Production binary ────────────────────────────────────────────
608659
0 commit comments