You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An experimental Clang fork that adds flow-sensitive null safety to C and C++, inspired by modern languages like TypeScript, Kotlin, and Rust.
5
+
Nullsafe C adds NULL checks to catch errors at compile-time, not runtime. It is 100% compatible with existing C codebases and can be used incrementally to identify safety issues at compile-time.
6
6
7
-
**Try it online:**[Interactive Playground](https://cs01.github.io/llvm-project/) - See null-safety warnings in real-time in your browser!
8
-
9
-
## What This Adds
10
-
11
-
This compiler adds two key features to prevent null pointer crashes:
7
+
You can annotate your code with `_Nonnull` to presere narrowing.
12
8
13
-
1. Nullable-by-default pointers - All pointers are assumed nullable unless explicitly marked `_Nonnull`
14
-
2. Type narrowing - The compiler tracks when you've null-checked a pointer and knows it's safe to use
9
+
**Try it online:**[Interactive Playground](https://cs01.github.io/llvm-project/) - See null-safety warnings in real-time in your browser!
15
10
16
-
In standard C/C++, pointers have no nullability information and the compiler can't tell if a pointer might be null. This compiler treats all unmarked pointers as nullable by default and uses flow-sensitive analysis to track null checks. When you write `if (p)`, the type system understands `p` is non-null in that branch, just like TypeScript, Kotlin, and Rust. This catches null pointer dereferences at compile time instead of crashing at runtime.
11
+
It does this by making two changes:
12
+
1. All pointers are nullable by default, unless explicitly marked `_Nonnull`. Clang already allows the code to be annotated with `_Nullable` and `_Nonnull`, but this compiler treats all unmarked pointers as nullable by default.
13
+
2. The compiler tracks when you've null-checked a pointer and knows it's safe to use. When you write `if (p)`, the type system understands `p` is non-null in that branch.
17
14
18
15
## Example
19
16
20
17
```c
21
-
voidprocess(int* data) {
22
-
if (data) {
23
-
*data = 42; // ✓ OK - strict nullability knows data is non-null here
24
-
}
18
+
voidunsafe(int *data) {
19
+
*data = 42; // warning - data might be null!
25
20
}
26
21
27
-
void unsafe(int* data) {
28
-
*data = 42; // ⚠️ Warning - data might be null!
22
+
void safe(int *data) {
23
+
if (data) {
24
+
*data = 42; // OK - data is non-null here
25
+
}
29
26
}
30
-
```
31
-
32
-
Standard Clang/GCC: Both functions compile without warnings.
33
-
This fork: The `unsafe` function warns you about the potential null dereference.
34
27
35
-
This experimental fork of Clang adds flow-sensitive nullability analysis while remaining 100% compatible with standard C. It includes all of Clang's features plus enhanced nullability checking in both the compiler and the `clangd` language server.
28
+
void safe_typed(int *_Nonnull data) {
29
+
*data = 42; // OK - data is known to be non-null by the compiler
30
+
}
36
31
37
-
By default, strict nullability is enabled and issues warnings. You can promote warnings to errors with `-Werror=nullability`, or disable the feature entirely with `-fno-strict-nullability`.
32
+
```
33
+
Try it out in the [Interactive Playground](https://cs01.github.io/llvm-project/).
38
34
39
35
## Installation
40
36
41
-
### Quick Install (Linux/macOS)
42
-
43
-
Download and extract the latest release for your platform:
44
-
45
37
```bash
46
-
# Auto-detect your platform and install
47
38
curl -fsSL https://raw.githubusercontent.com/cs01/llvm-project/null-safe-c-dev/install.sh | sh
48
-
49
-
# Or manually download:
50
-
# Linux x86_64:
51
-
curl -L https://github.com/cs01/llvm-project/releases/latest/download/clang-nullsafe-linux-x86_64.tar.gz | tar xz
52
-
53
-
# macOS (Intel/Apple Silicon):
54
-
curl -L https://github.com/cs01/llvm-project/releases/latest/download/clang-nullsafe-macos-universal.tar.gz | tar xz
55
-
56
-
# Add to PATH
57
-
export PATH="$PWD/bin:$PATH"
58
-
clang --version
59
39
```
60
40
41
+
Or download manually from [releases](https://github.com/cs01/llvm-project/releases/latest).
- Null-safe headers: Annotated C standard library in `clang/nullsafe-headers/`
155
121
- IDE integration: `clangd` built from this fork has the same logic and warnings as clang
156
122
157
-
## How It Works
158
-
159
-
Strict nullability adds flow-sensitive analysis to Clang's semantic analyzer. When you write `if (p)`, the compiler tracks that `p` is non-null within that branch—just like TypeScript, Swift, or Kotlin do. The difference is we add this to C without changing the language itself.
160
-
161
-
### Function Call Invalidation
162
-
163
-
By default, function calls invalidate narrowing because they may have side effects:
164
-
165
-
```c
166
-
void some_function(void);
167
-
168
-
void example(int* p) {
169
-
if (p) {
170
-
*p = 1; // OK - p is narrowed to non-null
171
-
some_function(); // Invalidates narrowing
172
-
*p = 2; // Warning: p is nullable again
173
-
}
174
-
}
175
-
```
176
-
177
-
This is conservative but safe—functions can modify global state or escaped pointers.
178
-
179
-
Preserve narrowing with pure functions:
180
-
181
-
Mark side-effect-free functions with `__attribute__((pure))` or `__attribute__((const))`:
182
-
183
-
```c
184
-
inttolower(int c) __attribute__((const)); // No side effects
185
-
186
-
void example(char* p) {
187
-
if (p) {
188
-
tolower(*p); // Pure function - doesn't invalidate
189
-
*p = 'x'; // OK - p is still narrowed
190
-
}
191
-
}
192
-
```
193
-
194
-
The difference:
195
-
- `__attribute__((const))`: Only uses its arguments (e.g., `tolower`, `abs`)
196
-
- `__attribute__((pure))`: May read globals but doesn't modify anything (e.g., `strlen`)
197
-
198
-
Many standard library functions already have these attributes in GNU libc headers, so strict nullability automatically recognizes them.
199
-
200
123
## Null-Safe C Standard Library
201
124
202
-
Nullability-annotated headers for `string.h`, `stdlib.h`, and `stdio.h` are available in `clang/nullsafe-headers/`. These tell the compiler which functions return nullable pointers and which parameters must be non-null.
strcpy(copy, input); // Both parameters narrowed to non-null
218
-
free(copy);
219
-
}
220
-
}
221
-
```
222
-
223
-
See [`clang/nullsafe-headers/README.md`](clang/nullsafe-headers/README.md) for details.
125
+
Nullability-annotated headers for `string.h`, `stdlib.h`, and `stdio.h` are available in `clang/nullsafe-headers/`. See [`clang/nullsafe-headers/README.md`](clang/nullsafe-headers/README.md) for details.
0 commit comments