Skip to content

Clang command-line cheatsheet from first compilation to LLVM tooling, diagnostics, sanitizers, coverage, and production builds.

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.

CommandUse It For
clangCompile and link C programs
clang++Compile and link C++ programs; adds the selected C++ runtime automatically
clang-formatAutomatically format source code
clang-tidyRun linting and modernize checks
llvm-profdataMerge profile or coverage runtime data
llvm-covDisplay source-based coverage reports

The basic pattern is:

Terminal window
clang [options] input.c -o output
clang++ [options] input.cpp -o output

Examples use Unix-style executable names (./app). On Windows, run a generated executable as app.exe.


hello.c
#include <stdio.h>
int main(void) {
puts("Hello, Clang!");
return 0;
}
Terminal window
clang hello.c -o hello # Compile and link
./hello # Run on Linux/macOS
hello.cpp
#include <iostream>
int main() {
std::cout << "Hello, Clang!\n";
}
Terminal window
clang++ hello.cpp -o hello # Use clang++ for C++ linking
./hello
CommandMeaning
clang main.cBuild C program as a.out (a.exe on some Windows setups)
clang main.c -o appName the output executable app
clang -std=c17 main.c -o appCompile C using C17
clang++ -std=c++20 main.cpp -o appCompile C++ using C++20
clang --versionPrint Clang and target information
clang -v main.c -o appShow selected toolchain paths and build commands
Terminal window
clang -std=c17 -Wall -Wextra -Wpedantic -g main.c -o app
FlagPurpose
-std=c17Select a defined C standard
-WallEnable many common warnings
-WextraEnable additional useful warnings
-WpedanticWarn about non-standard extensions
-gInclude debug information for a debugger

Treat compiler diagnostics as feedback from a very attentive reviewer: understand and fix warnings before moving on.


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
StageOptionTypical OutputWhat Happens
Preprocess-E.iExpand includes, macros, and conditional directives
Compile to assembly-S.sTranslate source into target assembly
Compile to LLVM IR-S -emit-llvm.llProduce human-readable LLVM intermediate representation
Assemble-c.oProduce object code without linking
Linkdefault final stepexecutable/libraryCombine objects and libraries
Terminal window
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 executable
Terminal window
clang -save-temps hello.c -o hello
Terminal window
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.ll

Comparing the files helps explain what optimization changes before target machine code is emitted.


OptionExamplePurpose
-o file-o calculatorSet output filename
-cclang -c util.cCompile without linking
-Eclang -E config.cPreprocess only
-Sclang -S math.cGenerate assembly
-emit-llvmclang -S -emit-llvm math.cGenerate LLVM IR instead of target assembly
-x languageclang -x c input.txtTreat an input as a selected language
-fsyntax-onlyclang -fsyntax-only main.cCheck syntax and semantics without output
LanguageCommon 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.

OptionExamplePurpose
-DNAME-DDEBUGDefine macro as 1
-DNAME=value-DPORT=8080Define macro with a value
-UNAME-UDEBUGUndefine a macro
-I dir-IincludeAdd header search directory
-iquote dir-iquote src/includeSearch directory for quoted includes
-isystem dir-isystem vendor/includeMark external headers as system headers
#if defined(DEBUG)
fprintf(stderr, "count = %d\n", count);
#endif
Terminal window
clang -DDEBUG -Iinclude src/main.c -o app

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.

Terminal window
# 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
OptionCatches or Controls
-WallCommon suspicious constructs and unused code
-WextraAdditional parameter, comparison, and initializer issues
-WpedanticUse of extensions outside the selected standard
-WconversionImplicit conversions that can change values
-Wsign-conversionSigned and unsigned conversions
-WshadowLocal declarations hiding another name
-Wformat=2Stronger format string checking
-WundefUndefined identifiers in preprocessor conditions
-WerrorConvert warnings into errors
-Wno-error=nameLeave a particular warning non-fatal
Terminal window
clang -Weverything main.c -o app

Clang’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.

Terminal window
clang -fcolor-diagnostics main.c -o app
clang -fdiagnostics-show-option main.c -o app
clang -ferror-limit=5 main.c -o app
OptionPurpose
-fcolor-diagnosticsColorize diagnostic output
-fno-color-diagnosticsDisable diagnostic color
-fdiagnostics-show-optionShow which warning flag produced a diagnostic
-ferror-limit=nStop reporting after n errors

Terminal window
clang -std=c17 -Wall -Wextra -Wpedantic -g -O0 main.c -o app
lldb ./app
OptionPurpose
-gInclude debugger information
-g3Include fuller debug information where supported
-O0Keep code closest to source for initial debugging
-OgApply debugging-friendly optimization
-fno-omit-frame-pointerImprove stack traces and some profiling workflows

For everyday debugging:

Terminal window
clang -std=c17 -Wall -Wextra -g -Og -fno-omit-frame-pointer main.c -o app
Terminal window
lldb ./app
(lldb) breakpoint set --name main
(lldb) run
(lldb) next
(lldb) step
(lldb) frame variable
(lldb) backtrace

GDB can also debug programs built by Clang when the relevant formats are supported on the platform.


Clang sanitizer instrumentation is commonly provided through the compiler-rt runtime. Compile and link through clang or clang++ so the required runtime is included.

Terminal window
clang -std=c17 -Wall -Wextra -g -O1 \
-fsanitize=address,undefined -fno-omit-frame-pointer \
main.c -o app
./app
SanitizerOptionDetects Examples
AddressSanitizer-fsanitize=addressOut-of-bounds access, use-after-free, some leaks
UndefinedBehaviorSanitizer-fsanitize=undefinedInvalid shifts, null/misaligned access, signed overflow
MemorySanitizer-fsanitize=memoryUses of uninitialized memory on supported platforms
ThreadSanitizer-fsanitize=threadData races in concurrent programs
LeakSanitizer-fsanitize=leakHeap 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.

Terminal window
clang -g -O1 -fsanitize=undefined -fno-sanitize-recover=undefined main.c -o app
Terminal window
clang -g -O1 \
-fsanitize=implicit-integer-truncation,implicit-integer-sign-change \
main.c -o app

These checks can find unintended narrowing or sign changes even when an operation is not language-level undefined behavior.


Terminal window
clang --analyze main.c

For build systems, scan-build runs the analyzer while the project builds:

Terminal window
scan-build make
scan-build cmake --build build

The analyzer looks for path-sensitive problems such as null dereferences, leaks, and incorrect API usage without executing the program.

Terminal window
clang-tidy src/main.cpp -- -std=c++20 -Iinclude
clang-tidy src/main.cpp -checks='bugprone-*,performance-*' -- -std=c++20 -Iinclude

With a compilation database (compile_commands.json):

Terminal window
clang-tidy -p build src/main.cpp
ToolBest For
Compiler warningsImmediate compile-time correctness feedback
clang --analyze / scan-buildDeeper path-sensitive bug discovery
clang-tidyLint rules, API misuse, readability, modernization, performance checks
Terminal window
cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
clang-tidy -p build src/main.cpp

Terminal window
clang-format -i src/main.c
clang-format -i src/*.cpp include/*.hpp
Terminal window
clang-format -style=llvm -dump-config > .clang-format

Edit .clang-format, then format files using the project style:

Terminal window
clang-format -i -style=file src/main.cpp
Terminal window
clang-format src/main.cpp
clang-format --dry-run --Werror src/main.cpp

clang-format is about layout, not program correctness. Use it alongside warnings, analysis, and tests.


project/
include/math_utils.h
src/main.c
src/math_utils.c
Terminal window
# 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 app
Terminal window
clang -std=c17 -Wall -Wextra -MMD -MP -Iinclude -c src/main.c -o main.o
OptionPurpose
-MMDWrite user-header dependencies to a .d file
-MPAvoid build errors when a recorded header is later removed
-MF fileChoose the dependency filename
-MT targetChoose the dependency target text

Terminal window
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
OptionPurpose
-lNAMELink library such as libNAME.so or libNAME.a
-LdirAdd a library search directory
-pthreadCompile/link thread support on compatible systems
-fuse-ld=lldRequest LLVM’s lld linker, when installed for the target
-Wl,optionPass an option through to the linker

Put libraries after the object files that reference them when traditional static link ordering applies:

Terminal window
clang main.o geometry.o -Llib -lshape -lm -o app
Terminal window
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 app
Terminal window
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 app

Depending on how Clang was installed and which platform it targets, C++ may use GNU libstdc++ or LLVM libc++.

Terminal window
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.


OptionTypical UseNotes
-O0Initial debuggingMinimal transformation
-OgDebug buildsDebug-friendly optimization
-O1Light optimizationModerate compile-time and runtime improvements
-O2General releasesSensible release starting point
-O3Performance experimentsBenchmark; code size can rise
-OzMinimize binary sizeMore size-focused than -Os
-OfastAggressive speedCan relax floating-point and language guarantees
Terminal window
clang -std=c17 -O2 -DNDEBUG -Wall -Wextra main.c -o app
Terminal window
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 app

When available, using LLVM’s linker is a common pairing:

Terminal window
clang -O2 -flto -fuse-ld=lld main.o util.o -o app
Terminal window
clang -O2 -march=native main.c -o app

Use -march=native for local builds or controlled deployment. Binaries distributed to unrelated machines may fail if they contain unsupported instructions.


Clang’s source-based coverage records source-level region information and reports it using LLVM tools.

Terminal window
# 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.profdata
Terminal window
llvm-cov show ./app -instr-profile=app.profdata \
-format=html -output-dir=coverage-html
Terminal window
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.


PGO builds an instrumented program, runs representative workloads, and then optimizes using the collected behavior.

Terminal window
# 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 app

PGO 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

Section titled “14. Preprocessor, AST, and LLVM Inspection”
Terminal window
clang -E -Iinclude src/main.c -o main.i
clang -dM -E -x c /dev/null # Predefined C macros on Unix

On PowerShell:

Terminal window
'' | clang -std=c17 -dM -E -x c -
Terminal window
clang -H -Iinclude -c src/main.c
clang -v -E -x c /dev/null # Include search paths on Unix
Terminal window
clang -Xclang -ast-dump -fsyntax-only main.c
clang++ -std=c++20 -Xclang -ast-dump -fsyntax-only main.cpp

AST dumps help when learning how declarations and expressions are parsed, or when developing compiler-based tools.

Terminal window
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 app

Optimization remarks help explain decisions such as successful or missed inlining opportunities.


TaskCC++
Compile and linkclang main.c -o appclang++ main.cpp -o app
Standard-std=c17-std=c++20
Compile object onlyclang -c file.cclang++ -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.

math_api.h
#ifdef __cplusplus
extern "C" {
#endif
int add(int a, int b);
#ifdef __cplusplus
}
#endif

extern "C" exposes C-compatible linkage to C++ translation units.


Clang can target platforms other than the host when the correct headers, libraries, assembler, and linker support are available.

Terminal window
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
OptionPurpose
--target=tripleChoose the architecture/vendor/OS/environment target
--sysroot=dirUse a target filesystem root for headers and libraries
-resource-dir dirSelect Clang resource headers/libraries location
-fuse-ld=lldSelect 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.


Compiler settings can add defense in depth for programs that handle untrusted data. Confirm support in the deployment toolchain and operating system.

Terminal window
clang -std=c17 -O2 -Wall -Wextra \
-fstack-protector-strong -D_FORTIFY_SOURCE=2 \
-fPIE -pie main.c -o app
OptionPurpose
-fstack-protector-strongInsert checks for selected stack corruption cases
-D_FORTIFY_SOURCE=2Enable fortified libc checks where available
-fPIE -pieProduce a position-independent executable
-Wl,-z,relro,-z,nowRequest extra ELF/Linux linker hardening
Terminal window
clang -O2 -fcf-protection=full main.c -o app

Options 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.


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:

Terminal window
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.profdata

Use separate build directories in a larger project so that release, sanitizer, and coverage objects do not get mixed.


Message or SymptomLikely CauseTypical Fix
fatal error: 'foo.h' file not foundHeader directory missingAdd -Ipath/to/headers or correct the include
undefined reference to 'foo'Implementation or required library not linkedLink its object or add -lNAME
undefined reference to 'sqrt'Math library missing on Unix-like systemsPut -lm after source/object inputs
C++ undefined reference to runtime symbolsLinked using clangLink final executable using clang++
Sanitizer flag builds but linking failsRuntime unavailable or link step omitted sanitizer optionLink through Clang with matching -fsanitize= flags
llvm-cov shows no profileProgram not run or profile not mergedRun instrumented binary and use llvm-profdata merge
Debugger skips source linesOptimizer transformed the codeUse -Og or -O0 during debugging
--target object compiles but executable will not linkTarget sysroot/runtime absentInstall/provide target libraries and --sysroot
Terminal window
# 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 app

Terminal window
clang -std=c17 -Wall -Wextra -Wpedantic -Wconversion -g -Og main.c -o app
Terminal window
clang -std=c17 -Wall -Wextra -g -O1 \
-fsanitize=address,undefined -fno-omit-frame-pointer \
main.c -o app
Terminal window
clang -std=c17 -Wall -Wextra -O2 -DNDEBUG main.c -o app
Terminal window
clang++ -std=c++20 -Wall -Wextra -Wpedantic -g -Og main.cpp -o app
Terminal window
clang -std=c17 -Wall -Wextra -Iinclude \
src/main.c src/io.c src/math_utils.c -o app
Terminal window
clang -std=c17 -O2 -S -emit-llvm main.c -o main.ll
Terminal window
clang --analyze main.c
clang-format -i main.c
Terminal window
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.profdata

  1. Compile one C source file with clang main.c -o app.
  2. Always use warnings and a selected standard, such as -std=c17 -Wall -Wextra.
  3. Learn the preprocess, compile, assemble, and link stages.
  4. Build with -g -Og and step through a small program in LLDB or GDB.
  1. Compile multiple translation units and generate dependencies with -MMD -MP.
  2. Run sanitizer builds and static analysis in normal development.
  3. Adopt clang-format and experiment with clang-tidy.
  4. Produce and read a source-based coverage report using llvm-cov.
  1. Inspect ASTs, LLVM IR, assembly, and optimization remarks.
  2. Measure LTO and PGO on real workloads.
  3. Build libraries and understand C++ standard library/runtime choices.
  4. Configure cross-compilation, hardening, and automated quality checks.
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