Skip to content

cs01/llvm-project

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Nullsafe C: An experimental C/C++ compiler

Test Null-Safety    Try Online

Try it online: Interactive Playground - See null-safety warnings in real-time

Nullsafe C adds NULL checks to catch errors at compile-time. It is 100% compatible with existing C codebases and can be used incrementally to identify safety issues at compile-time.

This provides the following benefits:

  • Catches errors at compile-time rather than runtime, reducing crashes
  • Improves developer experience by shifting errors left and showing issues in the IDE as you code
  • Makes code more readable and maintainable, including annotations with _Nonnull
  • Adds type checking that more modern languages have (Rust, TypeScript, Kotlin)

Nullsafe C treats all pointers as potentially null ('nullable') unless it is certain they are not. It does this in two ways.

The first is by semantic analysis: if you test a pointer with if(p), then it knows that branch contains a non-null pointer.

The second is by using Clang's Nullability attributes, in particular _Nonnull. If a pointer is marked as _Nonnull the compiler will require a pointer it knows it not null is passed to it. This can be done either by passing a _Nonnull-annotated pointer, or by doing type narrowing.

If using a compiler other than clang, you can add #define _Nonnull as a no-op. You will not get the same compile checks as with Nullsafe C (clang fork), but the compillation will still succeed without error.

When a function is called, it will reset any type refinements, assuming there may be side effects. If the variable is marked const in the function signature the type narrowing is maintained, because it is guaranteed to not be made null within the function.

Note that this does not change any of the generated code. There are no performance impacts, it strictly does compile-time checks.

Examples

void unsafe(int *data) {
  *data = 42; // warning: dereferencing nullable pointer of type 'int * _Nullable'
}

Try it in the interactive playground

Type narrowing:

void safe(int *data) {
  if (data) {
    *data = 42; // OK - data is non-null here
  }
}

Try it in the interactive playground

Anontated with _Nonnull:

void safe_typed(int *_Nonnull data) {
  *data = 42; // OK - we know data is not null so we can derefernce it
}

Try it in the interactive playground

Installation

Quick Install

curl -fsSL https://raw.githubusercontent.com/cs01/llvm-project/null-safe-c-dev/install.sh | bash

Or download manually from releases.

On mac you may need to do the following:

brew install zstd
xcode-select --install  # If not already installed

Windows

Builds not available at this time, you must clone and build locally.

What's Included

Each release includes:

  • clang - The Null-Safe C compiler with flow-sensitive null checking
  • clangd - Language server for IDE integration (VSCode, vim, Neovim, Emacs, etc.)

IDE Integration

Once installed, configure your editor to use the null-safe clangd. Install the clangd extension from llvm and set the path to the clangd binary you just downloaded.

VS Code:

// settings.json
{
  "clangd.path": "/path/to/null-safe-clang/bin/clangd"
}

Neovim/vim:

require('lspconfig').clangd.setup({
  cmd = { '/path/to/null-safe-clang/bin/clangd' }
})

This gives you real-time null-safety warnings as you type!

Memory Safety

Do not that this is not a comprehensive solution, since Null pointer dereferences are just one category of memory safety bugs.

Safety Issue Standard C Null-Safe Clang (null checking)
Null pointer dereferences ❌ Unsafe ✅ Fixed
Buffer overflows ❌ Unsafe ❌ Unsafe
Use-after-free ❌ Unsafe ❌ Unsafe
Double-free ❌ Unsafe ❌ Unsafe
Uninitialized memory ❌ Unsafe ❌ Unsafe

Although this doesn't fix all memory safety issues, it catches Null pointer dereferences for free. For additional memory safety, consider a language other than C.

Why you still might want to try this

While Null-Safe Clang doesn't solve all memory safety issues in C, null pointer dereferences are a significant problem:

  • Many memory safety bugs involve null pointer dereferences
  • Easier to adopt than rewriting in Rust (100% compatible with existing C code)
  • Complements other efforts (combine with -fbounds-safety for buffer safety)
  • Incremental deployment (warnings by default, can enable per-file)

Usage

Basic usage (warnings enabled by default):

# Warnings for nullable dereferences
clang -fsyntax-only mycode.c
# Treat nullability issues as errors
clang -fsyntax-only -Werror=nullability mycode.c
# Turn off nullability checking
clang -fsyntax-only -fno-strict-nullability mycode.c

Features

  • Nullable-by-default: All pointers are _Nullable unless marked _Nonnull
  • Flow-sensitive narrowing: if (p) proves p is non-null in that scope
  • Early-exit patterns: Understands return, goto, break, continue
  • Pointer arithmetic: q = p + 1 preserves narrowing from p
  • Type checking through function calls, returns, and assignments
  • Works with Typedefs
  • Assumes functions have side effects (use __attribute__((pure)) or __attribute__((const)) to preserve narrowing)
  • Null-safe headers: Annotated C standard library in clang/nullsafe-headers/
  • IDE integration: clangd built from this fork has the same logic and warnings as clang

Null-Safe C Standard Library

Nullability-annotated headers for string.h, stdlib.h, and stdio.h are available in clang/nullsafe-headers/. See clang/nullsafe-headers/README.md for details.

About

Nullsafe C: An experimental C/C++ compiler

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

No packages published

Languages

  • LLVM 41.4%
  • C++ 31.2%
  • C 13.1%
  • Assembly 9.9%
  • MLIR 1.4%
  • Python 0.8%
  • Other 2.2%