Clang
Clang command-line cheatsheet from first compilation to LLVM tooling, diagnostics, sanitizers, coverage, and production builds.
Clang Cheatsheet
Clang is the C, C++, Objective-C, and Objective-C++ compiler frontend in the LLVM project. It uses a GCC-compatible command-line driver while offering excellent diagnostics and a rich LLVM toolchain.
| Command | Use It For |
|---|---|
clang | Compile and link C programs |
clang++ | Compile and link C++ programs; adds the selected C++ runtime automatically |
clang-format | Automatically format source code |
clang-tidy | Run linting and modernize checks |
llvm-profdata | Merge profile or coverage runtime data |
llvm-cov | Display source-based coverage reports |
The basic pattern is:
clang [options] input.c -o output
clang++ [options] input.cpp -o outputExamples use Unix-style executable names (./app). On Windows, run a generated executable as app.exe.
1. Beginner: Compile and Run
First C Program
// hello.c
#include <stdio.h>
int main(void) {
puts("Hello, Clang!");
return 0;
}clang hello.c -o hello # Compile and link
./hello # Run on Linux/macOSFirst C++ Program
// hello.cpp
#include <iostream>
int main() {
std::cout << "Hello, Clang!\n";
}clang++ hello.cpp -o hello # Use clang++ for C++ linking
./helloEssential Commands
| Command | Meaning |
|---|---|
clang main.c | Build C program as a.out (a.exe on some Windows setups) |
clang main.c -o app | Name the output executable app |
clang -std=c17 main.c -o app | Compile C using C17 |
clang++ -std=c++20 main.cpp -o app | Compile C++ using C++20 |
clang --version | Print Clang and target information |
clang -v main.c -o app | Show selected toolchain paths and build commands |
Recommended Learning Build
clang -std=c17 -Wall -Wextra -Wpedantic -g main.c -o app| Flag | Purpose |
|---|---|
-std=c17 | Select a defined C standard |
-Wall | Enable many common warnings |
-Wextra | Enable additional useful warnings |
-Wpedantic | Warn about non-standard extensions |
-g | Include debug information for a debugger |
Treat compiler diagnostics as feedback from a very attentive reviewer: understand and fix warnings before moving on.
2. How Compilation Works
The Clang driver coordinates the same major stages used by C and C++ toolchains:
source.c -> preprocessed source -> LLVM/assembly -> object file -> executable
preprocessing compilation assemble link| Stage | Option | Typical Output | What Happens |
|---|---|---|---|
| Preprocess | -E | .i | Expand includes, macros, and conditional directives |
| Compile to assembly | -S | .s | Translate source into target assembly |
| Compile to LLVM IR | -S -emit-llvm | .ll | Produce human-readable LLVM intermediate representation |
| Assemble | -c | .o | Produce object code without linking |
| Link | default final step | executable/library | Combine objects and libraries |
clang -E hello.c -o hello.i # Preprocess only
clang -S hello.c -o hello.s # Assembly
clang -S -emit-llvm hello.c -o hello.ll # Text LLVM IR
clang -c hello.c -o hello.o # Object file
clang hello.o -o hello # Link executableKeep Intermediate Files
clang -save-temps hello.c -o helloInspect LLVM IR
clang -std=c17 -O0 -S -emit-llvm main.c -o main_O0.ll
clang -std=c17 -O2 -S -emit-llvm main.c -o main_O2.llComparing the files helps explain what optimization changes before target machine code is emitted.
3. Common Option Reference
Input and Output
| Option | Example | Purpose |
|---|---|---|
-o file | -o calculator | Set output filename |
-c | clang -c util.c | Compile without linking |
-E | clang -E config.c | Preprocess only |
-S | clang -S math.c | Generate assembly |
-emit-llvm | clang -S -emit-llvm math.c | Generate LLVM IR instead of target assembly |
-x language | clang -x c input.txt | Treat an input as a selected language |
-fsyntax-only | clang -fsyntax-only main.c | Check syntax and semantics without output |
Standards
| Language | Common Selection |
|---|---|
| C90 | -std=c90 |
| C11 | -std=c11 |
| C17 | -std=c17 |
| GNU C17 extensions | -std=gnu17 |
| C++17 | -std=c++17 |
| C++20 | -std=c++20 |
| GNU C++20 extensions | -std=gnu++20 |
Use strict standards modes when portability matters. GNU modes permit useful extensions but can tie a program to supporting compilers and platforms.
Macros and Include Paths
| Option | Example | Purpose |
|---|---|---|
-DNAME | -DDEBUG | Define macro as 1 |
-DNAME=value | -DPORT=8080 | Define macro with a value |
-UNAME | -UDEBUG | Undefine a macro |
-I dir | -Iinclude | Add header search directory |
-iquote dir | -iquote src/include | Search directory for quoted includes |
-isystem dir | -isystem vendor/include | Mark external headers as system headers |
#if defined(DEBUG)
fprintf(stderr, "count = %d\n", count);
#endifclang -DDEBUG -Iinclude src/main.c -o app4. Diagnostics and Warnings
Clang is known for source-oriented error messages, fix-it suggestions, and precise locations. Start with portable warning options shared by most C/C++ compilers.
Sensible Warning Sets
# Everyday C development
clang -std=c17 -Wall -Wextra -Wpedantic -Wconversion -Wshadow main.c -o app
# Everyday C++ development
clang++ -std=c++20 -Wall -Wextra -Wpedantic -Wconversion -Wshadow main.cpp -o app
# Continuous integration: warnings fail the build
clang -std=c17 -Wall -Wextra -Wpedantic -Werror main.c -o app| Option | Catches or Controls |
|---|---|
-Wall | Common suspicious constructs and unused code |
-Wextra | Additional parameter, comparison, and initializer issues |
-Wpedantic | Use of extensions outside the selected standard |
-Wconversion | Implicit conversions that can change values |
-Wsign-conversion | Signed and unsigned conversions |
-Wshadow | Local declarations hiding another name |
-Wformat=2 | Stronger format string checking |
-Wundef | Undefined identifiers in preprocessor conditions |
-Werror | Convert warnings into errors |
-Wno-error=name | Leave a particular warning non-fatal |
What About -Weverything?
clang -Weverything main.c -o appClang's -Weverything enables all diagnostic groups, including newly introduced and stylistic warnings. It is useful for exploration or very tightly controlled projects, but it is usually too unstable or noisy to use as a normal portable project baseline.
Diagnostic Controls
clang -fcolor-diagnostics main.c -o app
clang -fdiagnostics-show-option main.c -o app
clang -ferror-limit=5 main.c -o app| Option | Purpose |
|---|---|
-fcolor-diagnostics | Colorize diagnostic output |
-fno-color-diagnostics | Disable diagnostic color |
-fdiagnostics-show-option | Show which warning flag produced a diagnostic |
-ferror-limit=n | Stop reporting after n errors |
5. Debug Builds
Debug Build Recipe
clang -std=c17 -Wall -Wextra -Wpedantic -g -O0 main.c -o app
lldb ./app| Option | Purpose |
|---|---|
-g | Include debugger information |
-g3 | Include fuller debug information where supported |
-O0 | Keep code closest to source for initial debugging |
-Og | Apply debugging-friendly optimization |
-fno-omit-frame-pointer | Improve stack traces and some profiling workflows |
For everyday debugging:
clang -std=c17 -Wall -Wextra -g -Og -fno-omit-frame-pointer main.c -o appLLDB Quick Start
lldb ./app(lldb) breakpoint set --name main
(lldb) run
(lldb) next
(lldb) step
(lldb) frame variable
(lldb) backtraceGDB can also debug programs built by Clang when the relevant formats are supported on the platform.
6. Sanitizers: Catch Runtime Bugs
Clang sanitizer instrumentation is commonly provided through the compiler-rt runtime. Compile and link through clang or clang++ so the required runtime is included.
Address and Undefined Behavior Sanitizers
clang -std=c17 -Wall -Wextra -g -O1 \
-fsanitize=address,undefined -fno-omit-frame-pointer \
main.c -o app
./app| Sanitizer | Option | Detects Examples |
|---|---|---|
| AddressSanitizer | -fsanitize=address | Out-of-bounds access, use-after-free, some leaks |
| UndefinedBehaviorSanitizer | -fsanitize=undefined | Invalid shifts, null/misaligned access, signed overflow |
| MemorySanitizer | -fsanitize=memory | Uses of uninitialized memory on supported platforms |
| ThreadSanitizer | -fsanitize=thread | Data races in concurrent programs |
| LeakSanitizer | -fsanitize=leak | Heap allocations that remain allocated |
Do not combine AddressSanitizer and ThreadSanitizer in one executable. MemorySanitizer is especially platform/toolchain dependent and works best when dependencies are instrumented too.
Fail Immediately on Undefined Behavior
clang -g -O1 -fsanitize=undefined -fno-sanitize-recover=undefined main.c -o appInteger Conversion Checks
clang -g -O1 \
-fsanitize=implicit-integer-truncation,implicit-integer-sign-change \
main.c -o appThese checks can find unintended narrowing or sign changes even when an operation is not language-level undefined behavior.
7. Static Analysis and Linting
Built-In Static Analyzer
clang --analyze main.cFor build systems, scan-build runs the analyzer while the project builds:
scan-build make
scan-build cmake --build buildThe analyzer looks for path-sensitive problems such as null dereferences, leaks, and incorrect API usage without executing the program.
clang-tidy
clang-tidy src/main.cpp -- -std=c++20 -Iinclude
clang-tidy src/main.cpp -checks='bugprone-*,performance-*' -- -std=c++20 -IincludeWith a compilation database (compile_commands.json):
clang-tidy -p build src/main.cpp| Tool | Best For |
|---|---|
| Compiler warnings | Immediate compile-time correctness feedback |
clang --analyze / scan-build | Deeper path-sensitive bug discovery |
clang-tidy | Lint rules, API misuse, readability, modernization, performance checks |
Export a Compilation Database with CMake
cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
clang-tidy -p build src/main.cpp8. Formatting Code with clang-format
Format a File
clang-format -i src/main.c
clang-format -i src/*.cpp include/*.hppStart a Project Configuration
clang-format -style=llvm -dump-config > .clang-formatEdit .clang-format, then format files using the project style:
clang-format -i -style=file src/main.cppPreview Without Modifying
clang-format src/main.cpp
clang-format --dry-run --Werror src/main.cppclang-format is about layout, not program correctness. Use it alongside warnings, analysis, and tests.
9. Multiple Source Files
Small Project Layout
project/
include/math_utils.h
src/main.c
src/math_utils.c# One command
clang -std=c17 -Wall -Wextra -Iinclude \
src/main.c src/math_utils.c -o app
# Separate compilation
clang -std=c17 -Wall -Wextra -Iinclude -c src/main.c -o main.o
clang -std=c17 -Wall -Wextra -Iinclude -c src/math_utils.c -o math_utils.o
clang main.o math_utils.o -o appDependency Generation for Make
clang -std=c17 -Wall -Wextra -MMD -MP -Iinclude -c src/main.c -o main.o| Option | Purpose |
|---|---|
-MMD | Write user-header dependencies to a .d file |
-MP | Avoid build errors when a recorded header is later removed |
-MF file | Choose the dependency filename |
-MT target | Choose the dependency target text |
10. Linking Libraries and Runtime Choices
Link Libraries
clang main.c -lm -o app # Math library on Unix-like systems
clang main.c -pthread -o app # POSIX threading where supported
clang main.o -Llib -lshape -o app| Option | Purpose |
|---|---|
-lNAME | Link library such as libNAME.so or libNAME.a |
-Ldir | Add a library search directory |
-pthread | Compile/link thread support on compatible systems |
-fuse-ld=lld | Request LLVM's lld linker, when installed for the target |
-Wl,option | Pass an option through to the linker |
Put libraries after the object files that reference them when traditional static link ordering applies:
clang main.o geometry.o -Llib -lshape -lm -o appCreate a Static Library
clang -std=c17 -O2 -Iinclude -c src/math_utils.c -o math_utils.o
ar rcs libmathutils.a math_utils.o
clang main.o -L. -lmathutils -o appCreate a Shared Library on Linux
clang -std=c17 -O2 -fPIC -Iinclude -c src/math_utils.c -o math_utils.o
clang -shared math_utils.o -o libmathutils.so
clang main.o -L. -lmathutils -Wl,-rpath,'$ORIGIN' -o appChoose a C++ Standard Library
Depending on how Clang was installed and which platform it targets, C++ may use GNU libstdc++ or LLVM libc++.
clang++ -std=c++20 main.cpp -stdlib=libc++ -o app-stdlib=libc++ works only when the libc++ headers and runtime libraries are installed for that environment.
11. Optimization and Release Builds
Optimization Levels
| Option | Typical Use | Notes |
|---|---|---|
-O0 | Initial debugging | Minimal transformation |
-Og | Debug builds | Debug-friendly optimization |
-O1 | Light optimization | Moderate compile-time and runtime improvements |
-O2 | General releases | Sensible release starting point |
-O3 | Performance experiments | Benchmark; code size can rise |
-Oz | Minimize binary size | More size-focused than -Os |
-Ofast | Aggressive speed | Can relax floating-point and language guarantees |
Release Build Recipe
clang -std=c17 -O2 -DNDEBUG -Wall -Wextra main.c -o appLink-Time Optimization
clang -std=c17 -O2 -flto -c main.c -o main.o
clang -std=c17 -O2 -flto -c util.c -o util.o
clang -O2 -flto main.o util.o -o appWhen available, using LLVM's linker is a common pairing:
clang -O2 -flto -fuse-ld=lld main.o util.o -o appMachine-Specific Optimization
clang -O2 -march=native main.c -o appUse -march=native for local builds or controlled deployment. Binaries distributed to unrelated machines may fail if they contain unsupported instructions.
12. Source-Based Code Coverage
Clang's source-based coverage records source-level region information and reports it using LLVM tools.
Basic Workflow
# 1. Build with coverage instrumentation
clang -std=c17 -O0 -g \
-fprofile-instr-generate -fcoverage-mapping \
main.c -o app
# 2. Run tests or representative workloads
LLVM_PROFILE_FILE="app.profraw" ./app
# 3. Merge the raw profile
llvm-profdata merge -sparse app.profraw -o app.profdata
# 4. View summaries or annotated source
llvm-cov report ./app -instr-profile=app.profdata
llvm-cov show ./app -instr-profile=app.profdataHTML Coverage Report
llvm-cov show ./app -instr-profile=app.profdata \
-format=html -output-dir=coverage-htmlMultiple Test Runs
LLVM_PROFILE_FILE="profiles/app-%p.profraw" ./app test-input-1
LLVM_PROFILE_FILE="profiles/app-%p.profraw" ./app test-input-2
llvm-profdata merge -sparse profiles/*.profraw -o app.profdata
llvm-cov report ./app -instr-profile=app.profdata%p adds the process ID to each profile filename so parallel or repeated runs do not overwrite one another.
13. Profile-Guided Optimization
PGO builds an instrumented program, runs representative workloads, and then optimizes using the collected behavior.
# 1. Instrument
clang -O2 -fprofile-instr-generate main.c -o app
# 2. Run representative workloads
LLVM_PROFILE_FILE="app.profraw" ./app input.txt
# 3. Convert runtime profile data
llvm-profdata merge app.profraw -o app.profdata
# 4. Optimize with profile feedback
clang -O2 -fprofile-instr-use=app.profdata main.c -o appPGO is measurement-driven. Training input that does not represent real workloads can provide little benefit or optimize the wrong paths.
14. Preprocessor, AST, and LLVM Inspection
Inspect Macro Expansion
clang -E -Iinclude src/main.c -o main.i
clang -dM -E -x c /dev/null # Predefined C macros on UnixOn PowerShell:
'' | clang -std=c17 -dM -E -x c -Print Header Include Activity
clang -H -Iinclude -c src/main.c
clang -v -E -x c /dev/null # Include search paths on UnixView the Abstract Syntax Tree (AST)
clang -Xclang -ast-dump -fsyntax-only main.c
clang++ -std=c++20 -Xclang -ast-dump -fsyntax-only main.cppAST dumps help when learning how declarations and expressions are parsed, or when developing compiler-based tools.
LLVM IR and Optimization Remarks
clang -O2 -S -emit-llvm main.c -o main.ll
clang -O2 -Rpass=inline main.c -o app
clang -O2 -Rpass-missed=inline main.c -o appOptimization remarks help explain decisions such as successful or missed inlining opportunities.
15. C Versus C++ with Clang
| Task | C | C++ |
|---|---|---|
| Compile and link | clang main.c -o app | clang++ main.cpp -o app |
| Standard | -std=c17 | -std=c++20 |
| Compile object only | clang -c file.c | clang++ -c file.cpp |
| Link object files containing C++ | Use clang++ | clang++ *.o -o app |
Clang may compile a .cpp source when invoked as clang, but use clang++ for the final C++ link so the correct C++ runtime libraries are selected.
Call C Code from C++
/* math_api.h */
#ifdef __cplusplus
extern "C" {
#endif
int add(int a, int b);
#ifdef __cplusplus
}
#endifextern "C" exposes C-compatible linkage to C++ translation units.
16. Cross-Compilation and Targets
Clang can target platforms other than the host when the correct headers, libraries, assembler, and linker support are available.
clang -print-target-triple
clang --target=aarch64-linux-gnu -c main.c -o main.o
clang --target=x86_64-w64-windows-gnu main.c -o app.exe| Option | Purpose |
|---|---|
--target=triple | Choose the architecture/vendor/OS/environment target |
--sysroot=dir | Use a target filesystem root for headers and libraries |
-resource-dir dir | Select Clang resource headers/libraries location |
-fuse-ld=lld | Select LLVM linker if it supports the target |
Selecting --target alone is not a full cross-compiling environment: linking usually needs target runtime libraries and system headers.
17. Hardening and Production Checks
Compiler settings can add defense in depth for programs that handle untrusted data. Confirm support in the deployment toolchain and operating system.
clang -std=c17 -O2 -Wall -Wextra \
-fstack-protector-strong -D_FORTIFY_SOURCE=2 \
-fPIE -pie main.c -o app| Option | Purpose |
|---|---|
-fstack-protector-strong | Insert checks for selected stack corruption cases |
-D_FORTIFY_SOURCE=2 | Enable fortified libc checks where available |
-fPIE -pie | Produce a position-independent executable |
-Wl,-z,relro,-z,now | Request extra ELF/Linux linker hardening |
Control-Flow Protection Where Supported
clang -O2 -fcf-protection=full main.c -o appOptions such as control-flow protection are target-specific. They require matching hardware and operating-system/runtime support.
Sanitizers are generally test-time bug detectors; production hardening is not a substitute for correct bounds checks, resource limits, and protocol validation.
18. A Practical Makefile with Clang
CC := clang
CPPFLAGS := -Iinclude
CFLAGS := -std=c17 -Wall -Wextra -Wpedantic -MMD -MP
LDLIBS :=
TARGET := app
SOURCES := src/main.c src/math_utils.c
OBJECTS := $(SOURCES:.c=.o)
DEPENDS := $(OBJECTS:.o=.d)
.PHONY: all debug release coverage clean
all: debug
debug: CFLAGS += -g -Og -fsanitize=address,undefined -fno-omit-frame-pointer
debug: LDFLAGS += -fsanitize=address,undefined
debug: $(TARGET)
release: CFLAGS += -O2 -DNDEBUG
release: $(TARGET)
coverage: CFLAGS += -O0 -g -fprofile-instr-generate -fcoverage-mapping
coverage: LDFLAGS += -fprofile-instr-generate -fcoverage-mapping
coverage: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
src/%.o: src/%.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
clean:
rm -f $(TARGET) $(OBJECTS) $(DEPENDS) *.profraw *.profdata
-include $(DEPENDS)Run:
make debug
make clean
make release
make clean
make coverage
LLVM_PROFILE_FILE="app.profraw" ./app
llvm-profdata merge -sparse app.profraw -o app.profdata
llvm-cov report ./app -instr-profile=app.profdataUse separate build directories in a larger project so that release, sanitizer, and coverage objects do not get mixed.
19. Common Errors and Fixes
| Message or Symptom | Likely Cause | Typical Fix |
|---|---|---|
fatal error: 'foo.h' file not found | Header directory missing | Add -Ipath/to/headers or correct the include |
undefined reference to 'foo' | Implementation or required library not linked | Link its object or add -lNAME |
undefined reference to 'sqrt' | Math library missing on Unix-like systems | Put -lm after source/object inputs |
C++ undefined reference to runtime symbols | Linked using clang | Link final executable using clang++ |
| Sanitizer flag builds but linking fails | Runtime unavailable or link step omitted sanitizer option | Link through Clang with matching -fsanitize= flags |
llvm-cov shows no profile | Program not run or profile not merged | Run instrumented binary and use llvm-profdata merge |
| Debugger skips source lines | Optimizer transformed the code | Use -Og or -O0 during debugging |
--target object compiles but executable will not link | Target sysroot/runtime absent | Install/provide target libraries and --sysroot |
Link Ordering
# Good for traditional static link resolution
clang main.o -L. -lutils -lm -o app
# Can fail because referenced symbols appear after libraries
clang -lutils -lm main.o -o app20. Copy-Paste Build Recipes
C Development
clang -std=c17 -Wall -Wextra -Wpedantic -Wconversion -g -Og main.c -o appC Debugging with Sanitizers
clang -std=c17 -Wall -Wextra -g -O1 \
-fsanitize=address,undefined -fno-omit-frame-pointer \
main.c -o appC Release
clang -std=c17 -Wall -Wextra -O2 -DNDEBUG main.c -o appC++ Development
clang++ -std=c++20 -Wall -Wextra -Wpedantic -g -Og main.cpp -o appMultiple Files and Include Directory
clang -std=c17 -Wall -Wextra -Iinclude \
src/main.c src/io.c src/math_utils.c -o appLLVM IR
clang -std=c17 -O2 -S -emit-llvm main.c -o main.llStatic Analysis and Formatting
clang --analyze main.c
clang-format -i main.cSource-Based Coverage
clang -O0 -g -fprofile-instr-generate -fcoverage-mapping main.c -o app
LLVM_PROFILE_FILE="app.profraw" ./app
llvm-profdata merge -sparse app.profraw -o app.profdata
llvm-cov report ./app -instr-profile=app.profdata21. Learning Path and Quick Recall
Beginner
- Compile one C source file with
clang main.c -o app. - Always use warnings and a selected standard, such as
-std=c17 -Wall -Wextra. - Learn the preprocess, compile, assemble, and link stages.
- Build with
-g -Ogand step through a small program in LLDB or GDB.
Intermediate
- Compile multiple translation units and generate dependencies with
-MMD -MP. - Run sanitizer builds and static analysis in normal development.
- Adopt
clang-formatand experiment withclang-tidy. - Produce and read a source-based coverage report using
llvm-cov.
Advanced
- Inspect ASTs, LLVM IR, assembly, and optimization remarks.
- Measure LTO and PGO on real workloads.
- Build libraries and understand C++ standard library/runtime choices.
- Configure cross-compilation, hardening, and automated quality checks.
Recall Card
Build C: clang -std=c17 -Wall -Wextra file.c -o app
Build C++: clang++ -std=c++20 -Wall -Wextra file.cpp -o app
Compile only: clang -c file.c -o file.o
Link: clang main.o util.o -lm -o app
Debug: clang -g -Og file.c -o app
Sanitize: clang -g -O1 -fsanitize=address,undefined file.c -o app
Release: clang -O2 -DNDEBUG file.c -o app
Preprocess: clang -E file.c -o file.i
LLVM IR: clang -S -emit-llvm file.c -o file.ll
Analyze: clang --analyze file.c
Format: clang-format -i file.c
Coverage: clang -fprofile-instr-generate -fcoverage-mapping file.c -o app