If you've ever stared at a large C codebase wondering whether two function calls touch the same shared state, you know the pain. Manual code review is error-prone, and full program analysis can be overkill. prongC was built to solve exactly this problem. It's a lightweight static analysis tool that detects shared variable accesses between function calls without requiring whole-program analysis.
The Problem It Solves
Consider this scenario: you have two function calls in your code:
foo(arg1, arg2, shared_arg);
bar(shared_arg, arg3);
Can you safely reorder them? Do they both read or modify the same variables? prongC gives you a definitive answer by tracing how each argument flows through the function bodies.
Key features
- No whole-program analysis - prongC only works with the functions and files you specify
- Individual parameter and global tracing - prongC can identify all variable accesses to globals or parameters you specify individually
- Compile database support - works seamlessly with
compile_commands.json - Multithreaded parsing - parse C files faster with
-joption
Usage
You tell prongC which files to analyze and which function calls to examine:
prongc --files="file1.c,file2.c" \
--functions="foo(arg1, arg2, shared_arg);bar(shared_arg, arg3)" \
-j8
The tool traces how each argument is used through the program and reports any overlaps.
You can also trace individual parameters of functions or globals by name:
prongc --files="file.c" \
--functions="foo(arg1)" \
--trace="foo@arg1"
Useful for
- Finding hidden variable access overlaps
- Verifying function call reordering safety
- Investigating side effects in legacy C code you're maintaining
- Exploring data dependencies across multiple files
- Undestanding unfamiliar codebases faster by uncovering data relationships
Output example
-------------------
Variable overlap:
foo(char *arg1, int arg2, bool shared_arg) → file1.c, line: 639, col: 6 │ READ : shared_arg
if (shared_arg) {
^
bar(bool shared_arg, size_t arg3) → file1.c, line: 699, col: 25 │ READ : shared_arg
var = shared_arg;
^
-------------------
Or for individual variable tracing
Input example:
prongc --files="file.c" \
--functions="foo(arg1, arg2, arg3)" \
--trace="foo@arg1"
Output:
-------------------
Tracing foo@arg1:
foo(char *arg1, int arg2, bool arg3) → file.c, line: 540, col: 9 │ READ : arg1
local = arg1;
^
-------------------













