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
README: Improve clarity and add atomic/volatile pointer tests
README changes:
- Add C++ support to title (works with both C and C++)
- Clarify "What This Adds" with two numbered features:
1. Nullable-by-default pointers
2. Type narrowing
- Remove bold formatting for cleaner appearance
- Add "zero runtime overhead" benefit
- Fix multi-level pointers example (int**, not int)
- Restructure CVE section for better flow
Test additions:
- Add atomic pointer nullability tests
- Add volatile pointer conversion tests
- Test that _Atomic(T*) gets nullability on inner type
- Test volatile nullable-to-nonnull conversions with narrowing
Copy file name to clipboardExpand all lines: README.md
+64-68Lines changed: 64 additions & 68 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,53 +1,17 @@
1
-
# Null-Safe C: An experimental C compiler
1
+
# Null-Safe Clang: An experimental C/C++ compiler
2
2
3
-
An experimental Clang fork that adds **flow-sensitive null safety** to C, inspired by modern languages like TypeScript, Kotlin, and Rust.
3
+
An experimental Clang fork that adds flow-sensitive null safety to C and C++, inspired by modern languages like TypeScript, Kotlin, and Rust.
4
4
5
5
## What This Adds
6
6
7
-
Modern languages prevent null pointer crashes through **nullable types** and **type narrowing** (also called refinement). When you write `if (p != null)`, the type system understands `p` is non-null in that branch. This catches null pointer dereferences at compile time instead of crashing at runtime.
7
+
This compiler adds two key features to prevent nullpointer crashes:
8
8
9
-
**This fork brings that safety to C** by extending Clang's existing `_Nonnull` and `_Nullable` annotations with intelligent flow analysis. All pointers are nullable by default unless explicitly marked `_Nonnull`.
9
+
1. Nullable-by-default pointers - All pointers are assumed nullable unless explicitly marked `_Nonnull`
10
+
2. Type narrowing - The compiler tracks when you've null-checked a pointer and knows it's safe to use
10
11
11
-
## Memory Safety: The Bigger Picture
12
+
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.
12
13
13
-
Null pointer dereferences are just one category of memory safety bugs. Here's how different approaches compare:
14
-
15
-
### What Gets Fixed
16
-
17
-
| Safety Issue | Null-Safe C | Standard C | Rust | Clang `-fbounds-safety`|
-[CVE-2019-5786](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-5786) - Chrome: Use-after-free in file reader
38
-
39
-
### Why This Still Matters
40
-
41
-
While Null-Safe C doesn't solve all memory safety issues, null pointer dereferences are a significant problem:
42
-
43
-
-**One in four memory safety bugs** involve null pointer dereferences ([Microsoft Security Response Center](https://github.com/microsoft/MSRC-Security-Research/blob/master/papers/2019/The%20Memory%20Safety%20Story.pdf))
44
-
-**Easier to adopt** than rewriting in Rust (100% compatible with existing C code)
45
-
-**Incremental deployment** (warnings by default, can enable per-file)
46
-
-**Complements other efforts** (combine with `-fbounds-safety` for buffer safety)
47
-
48
-
---
49
-
50
-
## Quick Example
14
+
## Example
51
15
52
16
```c
53
17
voidprocess(int* data) {
@@ -61,31 +25,58 @@ void unsafe(int* data) {
61
25
}
62
26
```
63
27
64
-
**Standard Clang/GCC**: Both functions compile without warnings.
65
-
**This fork**: The `unsafe` function warns you about the potential null dereference.
28
+
Standard Clang/GCC: Both functions compile without warnings.
29
+
This fork: The `unsafe` function warns you about the potential null dereference.
66
30
67
31
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.
68
32
69
-
**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`.
33
+
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`.
34
+
35
+
36
+
## Memory Safety in General
37
+
38
+
Null pointer dereferences are just one category of memory safety bugs. Here's how different approaches compare:
39
+
40
+
### What Gets Fixed
41
+
42
+
| Safety Issue | Null-Safe Clang (null checking) | Standard C | Rust | Clang `-fbounds-safety` |
While Null-Safe C doesn't solve all memory safety issues, null pointer dereferences are a significant problem:
54
+
55
+
- One in four memory safety bugs involve null pointer dereferences ([Microsoft Security Response Center](https://github.com/microsoft/MSRC-Security-Research/blob/master/papers/2019/The%20Memory%20Safety%20Story.pdf))
56
+
- Zero runtime overhead - nullability checks are compile-time only, no runtime checks inserted
57
+
- Easier to adopt than rewriting in Rust (100% compatible with existing C code)
58
+
- Incremental deployment (warnings by default, can enable per-file)
59
+
- Complements other efforts (combine with `-fbounds-safety` for buffer safety)
60
+
70
61
71
62
## Usage
72
63
73
-
**Basic usage (warnings enabled by default):**
64
+
Basic usage (warnings enabled by default):
74
65
```bash
75
66
clang mycode.c # Warnings for nullable dereferences
76
67
```
77
68
78
-
**Promote warnings to errors:**
69
+
Promote warnings to errors:
79
70
```bash
80
71
clang -Werror=nullability mycode.c # Treat nullability issues as errors
81
72
```
82
73
83
-
**Disable strict nullability:**
74
+
Disable strict nullability:
84
75
```bash
85
76
clang -fno-strict-nullability mycode.c # Turn off nullability checking
- Multi-level pointers: Works with `int**`, `int***`, etc.
98
+
- Pointer arithmetic: `q = p + 1` preserves narrowing from `p`
99
+
- Type checking: Through function calls, returns, and assignments
100
+
- Typedef support: Nullability annotations work seamlessly with typedefs
101
+
- Null-safe headers: Annotated C standard library in `clang/nullsafe-headers/`
102
+
- IDE integration: Enhanced `clangd` with real-time nullability diagnostics
103
+
- Real-world tested: Validated on cJSON, SQLite
113
104
114
105
## How It Works
115
106
116
-
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.
107
+
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.
117
108
118
109
### Function Call Invalidation
119
110
@@ -133,7 +124,7 @@ void example(int* p) {
133
124
134
125
This is conservative but safe—functions can modify global state or escaped pointers.
135
126
136
-
**Preserve narrowing with pure functions:**
127
+
Preserve narrowing with pure functions:
137
128
138
129
Mark side-effect-free functions with `__attribute__((pure))` or `__attribute__((const))`:
139
130
@@ -156,11 +147,16 @@ Many standard library functions already have these attributes in GNU libc header
156
147
157
148
## Null-Safe C Standard Library
158
149
159
-
The `clang/nullsafe-headers/` directory contains nullability-annotated standard library headers. These headers tell the compiler which functions can return NULL and which parameters can be NULL—information missing from system headers.
150
+
The `clang/nullsafe-headers/` directory contains nullability-annotated standard library headers. Currently includes:
These headers tell the compiler which functions can return NULL and which parameters can be NULL—information missing from system headers.
160
156
161
-
**The difference:** Functions like `malloc`, `strdup`, `getenv` are annotated to return `_Nullable` pointers (can be NULL), while parameters like `strlen`'s input are marked `_Nonnull` (must not be NULL).
157
+
Functions like `malloc`, `strdup`, `getenv` are annotated to return `_Nullable` pointers (can be NULL), while parameters like `strlen`'s input are marked `_Nonnull` (must not be NULL).
162
158
163
-
**Without null-safe headers (using system headers):**
159
+
Without null-safe headers (using system headers):
164
160
```c
165
161
#include <string.h> // System headers - no parameter nullability info
0 commit comments