Clang Compiler

Clang compiler cheatsheet — compile C/C++, enable sanitizers, set optimization flags. clang -O2, -fsanitize=address, -Wall -Wextra. Debug memory errors and crashes.

9 min read

What it is

Clang is a C, C++, and Objective-C compiler that provides fast compilation, rich diagnostics, and a flexible architecture for building and analyzing code.

Installation

Linux (Debian/Ubuntu)

sudo apt update
sudo apt install clang

Linux (Fedora)

sudo dnf install clang

macOS

Clang is included with Xcode. Install Xcode from the App Store, then open Xcode and accept the license agreement. The command-line tools can be installed separately:

xcode-select --install

Windows

Clang can be installed as part of the LLVM project. Download the installer from the official LLVM releases page: https://releases.llvm.org/. Alternatively, it can be installed via package managers like Chocolatey:

choco install llvm

Ensure the LLVM bin directory is added to your system’s PATH.

Core Concepts

  • Frontend: Parses the source code, performs semantic analysis, and generates an intermediate representation (IR).
  • Optimizer: Transforms the IR to improve performance and reduce code size.
  • Backend (Code Generator): Translates the optimized IR into machine code for a specific target architecture.
  • Intermediate Representation (IR): An abstract representation of the program code that is independent of the source language and the target machine. LLVM IR is commonly used.
  • Diagnostics: Clang’s advanced error and warning messages, often providing suggestions and highlighting the exact location of issues.

Commands / Usage

Compiling and Linking

Compiling a single C file

clang hello.c -o hello

Compiles hello.c and creates an executable named hello.

Compiling a single C++ file

clang++ main.cpp -o my_program

Compiles main.cpp using the C++ frontend and creates an executable named my_program.

Compiling multiple source files

clang main.c utils.c -o my_app

Compiles main.c and utils.c and links them into a single executable my_app.

Creating an object file

clang -c main.c -o main.o

Compiles main.c into an object file main.o without linking.

Linking object files

clang main.o utils.o -o my_app

Links pre-compiled object files main.o and utils.o into an executable my_app.

Specifying C standard

clang -std=c11 my_code.c -o c11_app

Compiles my_code.c using the C11 standard. Other common standards include c99, c++14, c++17, c++20.

Specifying C++ standard

clang++ -std=c++17 my_cpp_code.cpp -o cpp17_app

Compiles my_cpp_code.cpp using the C++17 standard.

Enabling C++ exceptions

clang++ -fexceptions my_cpp_code.cpp -o cpp_exceptions_app

Enables C++ exception handling. This is usually enabled by default for C++ but can be explicitly set.

Disabling C++ exceptions

clang++ -fno-exceptions my_cpp_code.cpp -o cpp_no_exceptions_app

Disables C++ exception handling.

Enabling C++ RTTI (Run-Time Type Information)

clang++ -frtti my_cpp_code.cpp -o cpp_rtti_app

Enables RTTI, necessary for dynamic_cast and typeid.

Disabling C++ RTTI

clang++ -fno-rtti my_cpp_code.cpp -o cpp_no_rtti_app

Disables RTTI.

Specifying optimization level

clang -O2 my_code.c -o optimized_app

Compiles with optimization level 2. Common levels:

  • -O0: No optimization (default).
  • -O1: Basic optimization.
  • -O2: More optimization.
  • -O3: Aggressive optimization.
  • -Os: Optimize for size.
  • -Oz: Optimize aggressively for size.
  • -Ofast: -O3 plus aggressive floating-point optimizations.

Debugging information

clang -g my_code.c -o debug_app

Includes debugging information in the executable, allowing debuggers like GDB or LLDB to be used effectively.

Warning flags

clang -Wall -Wextra -pedantic my_code.c -o warnings_app

Enables a wide range of warnings (-Wall), extra warnings (-Wextra), and pedantic warnings (-pedantic) to catch potential issues.

Treat warnings as errors

clang -Werror my_code.c -o error_on_warning_app

Treats all compiler warnings as errors, causing compilation to fail if any warnings are issued.

Include paths

clang main.c -I/usr/local/include -o app_with_includes

Adds /usr/local/include to the list of directories searched for header files.

Library paths

clang main.c -L/usr/local/lib -lmylib -o app_with_libs

Adds /usr/local/lib to the list of directories searched for libraries and links against libmylib.so (or .a).

Linking a specific library

clang main.c -lm -o math_app

Links the math library (libm.so or .a).

Generating a shared library

clang -shared -fPIC my_lib.c -o libmylib.so

Compiles my_lib.c into a position-independent code shared library libmylib.so.

Generating a static library

clang -c my_lib.c
clang -static -cr libmylib.a my_lib.o

Compiles my_lib.c to my_lib.o, then creates a static library libmylib.a from it.

Specifying target architecture

clang --target=arm64-apple-ios14.0 main.c -o ios_app

Compiles main.c for the specified target architecture and OS version.

Language Features and Extensions

Enabling Objective-C ARC (Automatic Reference Counting)

clang -fobjc-arc main.m -o arc_app

Enables ARC for Objective-C code.

Enabling Objective-C garbage collection (deprecated)

clang -fobjc-gc main.m -o gc_app

Enables garbage collection for Objective-C code.

Enabling GNU extensions

clang -std=gnu11 main.c -o gnu_app

Enables GNU extensions for the specified standard (e.g., gnu11 for C).

Preprocessing

Preprocessing only

clang -E main.c -o main.i

Runs only the preprocessor on main.c, outputting the result to main.i.

Assembling only

clang -S main.c -o main.s

Compiles main.c to assembly code (main.s) without assembling it into machine code.

Generating LLVM IR

clang -emit-llvm main.c -S -o main.ll

Emits LLVM IR in human-readable format (.ll) instead of machine code.

Generating bitcode

clang -emit-llvm -c main.c -o main.bc

Emits LLVM IR in a compact, binary format (bitcode, .bc) suitable for later linking or optimization.

Analysis and Diagnostics

Generating a compilation database (for IDEs like VS Code, CLion)

clang -MJ compile_commands.json main.c -c

Generates a compile_commands.json file that IDEs can use to understand your project’s build settings.

Suppressing specific warnings

clang -Wno-unused-variable my_code.c -o no_unused_var_app

Disables warnings about unused variables. To suppress other warnings, replace unused-variable with the specific warning name (e.g., unused-function, shadow).

Verbose output

clang -v main.c -o verbose_app

Shows the commands being executed by Clang, including the compiler, assembler, and linker invocations.

Showing internal passes

clang -mllvm -debug-pass=Arguments my_code.c -o debug_passes_app

Prints the optimization passes that LLVM runs during compilation.

Linking

Creating an executable from object files and libraries

clang main.o utils.o -L/path/to/libs -lmylib -o final_app

Links main.o and utils.o, searching for libraries in /path/to/libs and linking against libmylib.

Creating a dynamic executable (default on most systems)

clang main.c -o dynamic_exe

Creating a static executable

clang main.c -static -o static_exe

Attempts to link all libraries statically. This may not be possible for all libraries.

Linking against a specific C++ standard library

clang++ main.cpp -stdlib=libc++ -o cpp_libcxx_app

Links against the libc++ standard library (common on macOS and FreeBSD).

clang++ main.cpp -stdlib=libstdc++ -o cpp_libstdcxx_app

Links against the libstdc++ standard library (common on Linux).

Miscellaneous

Print version

clang --version

Displays the Clang compiler version.

Help

clang --help

Shows a summary of available command-line options.

Common Patterns

Building a simple C project with multiple files:

# Compile each file into an object file
clang -c main.c -o main.o
clang -c utils.c -o utils.o

# Link object files into an executable
clang main.o utils.o -o my_program

Building a C++ project with flags:

clang++ -std=c++17 -Wall -Wextra -O2 main.cpp utils.cpp -o my_cpp_app

Debugging a segfault:

# Compile with debug symbols
clang -g my_program.c -o my_program_debug

# Run the program and inspect the crash with a debugger
gdb ./my_program_debug
# Inside gdb: run, then bt (backtrace) on crash

Or using LLDB on macOS:

# Compile with debug symbols
clang -g my_program.c -o my_program_debug

# Run the program and inspect the crash with a debugger
lldb ./my_program_debug
# Inside lldb: run, then bt (backtrace) on crash

Generating a static library and using it:

# Create object files for the library
clang -c mylib_part1.c -o mylib_part1.o
clang -c mylib_part2.c -o mylib_part2.o

# Create the static library
ar rcs libmylib.a mylib_part1.o mylib_part2.o

# Compile and link your main program, using the static library
clang main.c -L. -lmylib -o my_app
# Note: -L. tells the linker to look in the current directory for libraries.

Generating a shared library and using it:

# Create object files with position-independent code
clang -fPIC -c mylib_part1.c -o mylib_part1.o
clang -fPIC -c mylib_part2.c -o mylib_part2.o

# Create the shared library
clang -shared mylib_part1.o mylib_part2.o -o libmylib.so

# Compile and link your main program, using the shared library
clang main.c -L. -lmylib -o my_app
# On Linux, you might need to set LD_LIBRARY_PATH to find the shared library at runtime:
# export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
# ./my_app

Using clang-tidy for static analysis (requires separate installation or build from source):

# Install clang-tidy (e.g., on Ubuntu)
sudo apt install clang-tidy

# Run clang-tidy on a file
clang-tidy -checks='*' main.c -- -std=c11

This runs all available checks on main.c and uses -std=c11 as compiler arguments to understand the code context.

Gotchas

  • clang vs clang++: Always use clang++ when compiling C++ code. While clang can sometimes compile C++ files, clang++ ensures the correct C++ standard library and headers are used by default.
  • Linking C++ standard library: When mixing C and C++ code, or when explicitly controlling linking, you might need to tell Clang to link the C++ standard library. For example, clang main.c my_cpp_code.o -lstdc++ -o my_app.
  • ar for static libraries: Clang itself doesn’t create static libraries (.a files). You need to use the ar (archiver) utility after creating object files.
  • LD_LIBRARY_PATH (Linux): When developing and testing shared libraries, the runtime linker might not find libmylib.so unless you add its directory to LD_LIBRARY_PATH. This is generally not recommended for production deployment.
  • System headers: Clang searches for system headers in standard locations. If you’re using custom system headers, you’ll need to specify their path using -I.
  • --target for cross-compilation: When cross-compiling (e.g., compiling for ARM on an x86 machine), correctly specifying the --target flag is crucial. The format is typically architecture-vendor-os-abi.
  • Warning flags: -Wall is comprehensive but doesn’t enable all warnings. -Wextra adds more, and -pedantic enforces strict ISO standard compliance. Using -Werror can be useful for CI but can be frustrating during initial development.