[docs] Rewrite selected Clang docs to Markdown (#209283)

Tracking issue: https://github.com/llvm/llvm-project/issues/201242
Migration guide docs:
https://llvm.org/docs/SphinxQuickstartTemplate.html#markdown-migration-guidelines
RFC:
https://discourse.llvm.org/t/rfc-make-myst-markdown-the-llvm-docs-format-rip-rest/90840

This was prepared with rst2myst plus LLM-assisted cleanup. I paged
through all the generated HTML looking for migration artifacts, and all
of the differences I could find appear to be formatting error
corrections.

I noticed that there is a large block of literal rst text in APINotes.md, but I will defer that for later cleanup.
This commit is contained in:
Reid Kleckner 2026-07-15 13:54:03 -07:00 committed by GitHub
parent cf293b069a
commit 1514df3333
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 2758 additions and 2991 deletions

View file

@ -1,66 +1,32 @@
.. raw:: html
```{contents}
:local: true
```
<style type="text/css">
.none { background-color: #FFCCCC }
.part { background-color: #FFFF99 }
.good { background-color: #CCFF99 }
</style>
.. role:: none
.. role:: part
.. role:: good
.. contents::
:local:
==============
AMDGPU Support
==============
# AMDGPU Support
Clang supports OpenCL, HIP and OpenMP on AMD GPU targets.
## Predefined Macros
Predefined Macros
=================
.. list-table::
:header-rows: 1
* - Macro
- Description
* - ``__AMDGPU__``
- Indicates that the code is being compiled for an AMD GPU.
* - ``__AMDGCN__``
- Defined if the GPU target is AMDGCN.
* - ``__R600__``
- Defined if the GPU target is R600.
* - ``__<ArchName>__``
- Defined with the name of the architecture (e.g., ``__gfx906__`` for the gfx906 architecture).
* - ``__<GFXN>__``
- Defines the GFX family (e.g., for gfx906, this macro would be ``__GFX9__``).
* - ``__amdgcn_processor__``
- Defined with the processor name as a string (e.g., ``"gfx906"``).
* - ``__amdgcn_target_id__``
- Defined with the target ID as a string.
* - ``__amdgcn_feature_<feature-name>__``
- Defined for each supported target feature. The value is 1 if the feature is enabled and 0 if it is disabled. Allowed feature names are sramecc and xnack.
* - ``__AMDGCN_CUMODE__``
- Defined as 1 if the CU mode is enabled and 0 if the WGP mode is enabled.
* - ``__AMDGCN_UNSAFE_FP_ATOMICS__``
- Defined if unsafe floating-point atomics are allowed.
* - ``__HAS_FMAF__``
- Defined if FMAF instruction is available (deprecated).
* - ``__HAS_LDEXPF__``
- Defined if LDEXPF instruction is available (deprecated).
* - ``__HAS_FP64__``
- Defined if FP64 instruction is available (deprecated).
| Macro | Description |
| --- | --- |
| `__AMDGPU__` | Indicates that the code is being compiled for an AMD GPU. |
| `__AMDGCN__` | Defined if the GPU target is AMDGCN. |
| `__R600__` | Defined if the GPU target is R600. |
| `__<ArchName>__` | Defined with the name of the architecture (e.g., `__gfx906__` for the gfx906 architecture). |
| `__<GFXN>__` | Defines the GFX family (e.g., for gfx906, this macro would be `__GFX9__`). |
| `__amdgcn_processor__` | Defined with the processor name as a string (e.g., `"gfx906"`). |
| `__amdgcn_target_id__` | Defined with the target ID as a string. |
| `__amdgcn_feature_<feature-name>__` | Defined for each supported target feature. The value is 1 if the feature is enabled and 0 if it is disabled. Allowed feature names are sramecc and xnack. |
| `__AMDGCN_CUMODE__` | Defined as 1 if the CU mode is enabled and 0 if the WGP mode is enabled. |
| `__AMDGCN_UNSAFE_FP_ATOMICS__` | Defined if unsafe floating-point atomics are allowed. |
| `__HAS_FMAF__` | Defined if FMAF instruction is available (deprecated). |
| `__HAS_LDEXPF__` | Defined if LDEXPF instruction is available (deprecated). |
| `__HAS_FP64__` | Defined if FP64 instruction is available (deprecated). |
Please note that the specific architecture and feature names will vary depending on the GPU. Also, some macros are deprecated and may be removed in future releases.
Target-Specific Builtins
========================
## Target-Specific Builtins
Clang exposes AMDGPU hardware intrinsics as target-specific builtins with the
``__builtin_amdgcn_`` prefix. These are documented in :doc:`AMDGPUBuiltinReference`.
`__builtin_amdgcn_` prefix. These are documented in {doc}`AMDGPUBuiltinReference`.

View file

@ -1,6 +1,4 @@
================================================
API Notes: Annotations Without Modifying Headers
================================================
# API Notes: Annotations Without Modifying Headers
**The Problem:** You have headers you want to use, but you also want to add
extra information to the API. You don't want to put that information in the
@ -11,9 +9,9 @@ want to modify them at all.
**Incomplete solution:** Redeclare all the interesting parts of the API in your
own header and add the attributes you want. Unfortunately, this:
* doesn't work with attributes that must be present on a definition
* doesn't allow changing the definition in other ways
* requires your header to be included in any client code to take effect
- doesn't work with attributes that must be present on a definition
- doesn't allow changing the definition in other ways
- requires your header to be included in any client code to take effect
**Better solution:** Provide a "sidecar" file with the information you want to
add, and have that automatically get picked up by the module-building logic in
@ -22,14 +20,11 @@ the compiler.
That's API notes.
API notes use a YAML-based file format. YAML is a format best explained by
example, so here is a `small example
<https://github.com/llvm/llvm-project/blob/main/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.apinotes>`_
example, so here is a [small example](https://github.com/llvm/llvm-project/blob/main/clang/test/APINotes/Inputs/Frameworks/SomeKit.framework/Headers/SomeKit.apinotes)
from the compiler test suite of API
notes for a hypothetical "SomeKit" framework.
Usage
=====
## Usage
API notes files are found relative to the module map that defines a module,
under the name "SomeKit.apinotes" for a module named "SomeKit". Additionally, a
@ -42,34 +37,30 @@ PrivateHeaders directory as well, though it does not need an additional
"_private" suffix on its name.
Clang will search for API notes files next to module maps only when passed the
``-fapinotes-modules`` option.
`-fapinotes-modules` option.
Limitations
===========
## Limitations
- Since they're identified by module name, API notes cannot be used to modify
arbitrary textual headers.
"Versioned" API Notes
=====================
## "Versioned" API Notes
Many API notes affect how a C API is imported into Swift. In order to change
that behavior while still remaining backwards-compatible, API notes can be
selectively applied based on the Swift compatibility version provided to the
compiler (e.g. ``-fapi-notes-swift-version=5``). The rule is that an
compiler (e.g. `-fapi-notes-swift-version=5`). The rule is that an
explicitly-versioned API note applies to that version *and all earlier
versions,* and any applicable explicitly-versioned API note takes precedence
over an unversioned API note.
Reference
=========
## Reference
An API notes file contains a YAML dictionary with the following top-level
entries:
```{eval-rst}
:Name:
The name of the module (the framework name, for frameworks). Note that this
@ -513,3 +504,4 @@ declaration kind), all of which are optional:
- Selector: "initWithFrame:"
MethodKind: Instance
DesignatedInit: true
```

View file

@ -1,12 +1,10 @@
=================
Allocation Tokens
=================
# Allocation Tokens
.. contents::
:local:
```{contents}
:local: true
```
Introduction
============
## Introduction
Clang provides support for allocation tokens to enable allocator-level heap
organization strategies. Clang assigns mode-dependent token IDs to allocation
@ -15,55 +13,49 @@ compatible memory allocator.
Possible allocator strategies include:
* **Security Hardening**: Placing allocations into separate, isolated heap
- **Security Hardening**: Placing allocations into separate, isolated heap
partitions. For example, separating pointer-containing types from raw data
can mitigate exploits that rely on overflowing a primitive buffer to corrupt
object metadata.
* **Memory Layout Optimization**: Grouping related allocations to improve data
- **Memory Layout Optimization**: Grouping related allocations to improve data
locality and cache utilization.
* **Custom Allocation Policies**: Applying different management strategies to
- **Custom Allocation Policies**: Applying different management strategies to
different partitions.
Token Assignment Mode
=====================
## Token Assignment Mode
The default mode to calculate tokens is:
* ``typehashpointersplit``: This mode assigns a token ID based on the hash of
- `typehashpointersplit`: This mode assigns a token ID based on the hash of
the allocated type's name, where the top half ID-space is reserved for types
that contain pointers and the bottom half for types that do not contain
pointers.
Other token ID assignment modes are supported, but they may be subject to
change or removal. These may (experimentally) be selected with ``-Xclang
-falloc-token-mode=<mode>``:
change or removal. These may (experimentally) be selected with `-Xclang
-falloc-token-mode=<mode>`:
* ``typehash``: This mode assigns a token ID based on the hash of the allocated
- `typehash`: This mode assigns a token ID based on the hash of the allocated
type's name.
* ``random``: This mode assigns a statically-determined random token ID to each
- `random`: This mode assigns a statically-determined random token ID to each
allocation site.
* ``increment``: This mode assigns a simple, incrementally increasing token ID
- `increment`: This mode assigns a simple, incrementally increasing token ID
to each allocation site.
The following command-line options affect generated token IDs:
* ``-falloc-token-max=<N>``
Configures the maximum number of token IDs. By default the number of tokens
is bounded by ``SIZE_MAX``.
- `-falloc-token-max=<N>`
: Configures the maximum number of token IDs. By default the number of tokens
is bounded by `SIZE_MAX`.
Querying Token IDs with ``__builtin_infer_alloc_token``
=======================================================
## Querying Token IDs with `__builtin_infer_alloc_token`
For use cases where the token ID must be known at compile time, Clang provides
a builtin function:
.. code-block:: c
size_t __builtin_infer_alloc_token(<args>, ...);
```c
size_t __builtin_infer_alloc_token(<args>, ...);
```
This builtin returns the token ID inferred from its argument expressions, which
mirror arguments normally passed to any allocation function. The argument
@ -72,168 +64,162 @@ have side effects without any runtime impact.
For example, it can be used as follows:
.. code-block:: c
```c
struct MyType { ... };
void *__partition_alloc(size_t size, size_t partition);
#define partition_alloc(...) __partition_alloc(__VA_ARGS__, __builtin_infer_alloc_token(__VA_ARGS__))
struct MyType { ... };
void *__partition_alloc(size_t size, size_t partition);
#define partition_alloc(...) __partition_alloc(__VA_ARGS__, __builtin_infer_alloc_token(__VA_ARGS__))
void foo(void) {
MyType *x = partition_alloc(sizeof(*x));
}
```
void foo(void) {
MyType *x = partition_alloc(sizeof(*x));
}
Allocation Token Instrumentation
================================
## Allocation Token Instrumentation
To enable instrumentation of allocation functions, code can be compiled with
the ``-fsanitize=alloc-token`` flag:
the `-fsanitize=alloc-token` flag:
.. code-block:: console
% clang++ -fsanitize=alloc-token example.cc
```console
% clang++ -fsanitize=alloc-token example.cc
```
The instrumentation transforms allocation calls to include a token ID. For
example:
.. code-block:: c
```c
// Original:
ptr = malloc(size);
// Original:
ptr = malloc(size);
// Instrumented:
ptr = __alloc_token_malloc(size, <token id>);
```
// Instrumented:
ptr = __alloc_token_malloc(size, <token id>);
Runtime Interface
-----------------
### Runtime Interface
A compatible runtime must be provided that implements the token-enabled
allocation functions. The instrumentation generates calls to functions that
take a final ``size_t token_id`` argument.
take a final `size_t token_id` argument.
.. code-block:: c
```c
// C standard library functions
void *__alloc_token_malloc(size_t size, size_t token_id);
void *__alloc_token_calloc(size_t count, size_t size, size_t token_id);
void *__alloc_token_realloc(void *ptr, size_t size, size_t token_id);
// ...
// C standard library functions
void *__alloc_token_malloc(size_t size, size_t token_id);
void *__alloc_token_calloc(size_t count, size_t size, size_t token_id);
void *__alloc_token_realloc(void *ptr, size_t size, size_t token_id);
// ...
// C++ operators (mangled names)
// operator new(size_t, size_t)
void *__alloc_token__Znwm(size_t size, size_t token_id);
// operator new[](size_t, size_t)
void *__alloc_token__Znam(size_t size, size_t token_id);
// ... other variants like nothrow, etc., are also instrumented.
```
// C++ operators (mangled names)
// operator new(size_t, size_t)
void *__alloc_token__Znwm(size_t size, size_t token_id);
// operator new[](size_t, size_t)
void *__alloc_token__Znam(size_t size, size_t token_id);
// ... other variants like nothrow, etc., are also instrumented.
### Fast ABI
Fast ABI
--------
An alternative ABI can be enabled with ``-fsanitize-alloc-token-fast-abi``,
An alternative ABI can be enabled with `-fsanitize-alloc-token-fast-abi`,
which encodes the token ID in the allocation function name.
.. code-block:: c
void *__alloc_token_0_malloc(size_t size);
void *__alloc_token_1_malloc(size_t size);
void *__alloc_token_2_malloc(size_t size);
...
void *__alloc_token_0_Znwm(size_t size);
void *__alloc_token_1_Znwm(size_t size);
void *__alloc_token_2_Znwm(size_t size);
...
```c
void *__alloc_token_0_malloc(size_t size);
void *__alloc_token_1_malloc(size_t size);
void *__alloc_token_2_malloc(size_t size);
...
void *__alloc_token_0_Znwm(size_t size);
void *__alloc_token_1_Znwm(size_t size);
void *__alloc_token_2_Znwm(size_t size);
...
```
This ABI provides a more efficient alternative where
``-falloc-token-max`` is small.
`-falloc-token-max` is small.
Instrumenting Non-Standard Allocation Functions
-----------------------------------------------
### Instrumenting Non-Standard Allocation Functions
By default, AllocToken only instruments standard library allocation functions.
This simplifies adoption, as a compatible allocator only needs to provide
token-enabled variants for a well-defined set of standard functions.
To extend instrumentation to custom allocation functions, enable broader
coverage with ``-fsanitize-alloc-token-extended``. Such functions require being
marked with the `malloc
<https://clang.llvm.org/docs/AttributeReference.html#malloc>`_ or `alloc_size
<https://clang.llvm.org/docs/AttributeReference.html#alloc-size>`_ attributes
coverage with `-fsanitize-alloc-token-extended`. Such functions require being
marked with the [malloc][malloc-attribute] or
[alloc_size][alloc-size-attribute] attributes
(or a combination).
For example:
.. code-block:: c
```c
void *custom_malloc(size_t size) __attribute__((malloc));
void *my_malloc(size_t size) __attribute__((alloc_size(1)));
void *custom_malloc(size_t size) __attribute__((malloc));
void *my_malloc(size_t size) __attribute__((alloc_size(1)));
// Original:
ptr1 = custom_malloc(size);
ptr2 = my_malloc(size);
// Original:
ptr1 = custom_malloc(size);
ptr2 = my_malloc(size);
// Instrumented:
ptr1 = __alloc_token_custom_malloc(size, token_id);
ptr2 = __alloc_token_my_malloc(size, token_id);
```
// Instrumented:
ptr1 = __alloc_token_custom_malloc(size, token_id);
ptr2 = __alloc_token_my_malloc(size, token_id);
Note: Even in the default mode (without ``-fsanitize-alloc-token-extended``),
an *inline* allocation wrapper marked with the `malloc
<https://clang.llvm.org/docs/AttributeReference.html#malloc>`_ or `alloc_size
<https://clang.llvm.org/docs/AttributeReference.html#alloc-size>`_ attribute is
Note: Even in the default mode (without `-fsanitize-alloc-token-extended`),
an *inline* allocation wrapper marked with the [malloc][malloc-attribute] or
[alloc_size][alloc-size-attribute] attribute is
supported if it is inlined into its caller: the inferred token is propagated to
the allocation call the wrapper returns, which is then instrumented normally.
Wrappers that are not inlined still require
``-fsanitize-alloc-token-extended``.
`-fsanitize-alloc-token-extended`.
Disabling Instrumentation
-------------------------
[malloc-attribute]: https://clang.llvm.org/docs/AttributeReference.html#malloc
[alloc-size-attribute]: https://clang.llvm.org/docs/AttributeReference.html#alloc-size
### Disabling Instrumentation
To exclude specific functions from instrumentation, you can use the
``no_sanitize("alloc-token")`` attribute:
`no_sanitize("alloc-token")` attribute:
.. code-block:: c
__attribute__((no_sanitize("alloc-token")))
void* custom_allocator(size_t size) {
return malloc(size); // Uses original malloc
}
```c
__attribute__((no_sanitize("alloc-token")))
void* custom_allocator(size_t size) {
return malloc(size); // Uses original malloc
}
```
Note: Independent of any given allocator support, the instrumentation aims to
remain performance neutral. As such, ``no_sanitize("alloc-token")``
remain performance neutral. As such, `no_sanitize("alloc-token")`
functions may be inlined into instrumented functions and vice-versa. If
correctness is affected, such functions should explicitly be marked
``noinline``.
`noinline`.
The ``__attribute__((disable_sanitizer_instrumentation))`` is also supported to
The `__attribute__((disable_sanitizer_instrumentation))` is also supported to
disable this and other sanitizer instrumentations.
Suppressions File (Ignorelist)
------------------------------
### Suppressions File (Ignorelist)
AllocToken respects the ``src`` and ``fun`` entity types in the
:doc:`SanitizerSpecialCaseList`, which can be used to omit specified source
AllocToken respects the `src` and `fun` entity types in the
{doc}`SanitizerSpecialCaseList`, which can be used to omit specified source
files or functions from instrumentation.
.. code-block:: bash
```bash
[alloc-token]
# Exclude specific source files
src:third_party/allocator.c
# Exclude function name patterns
fun:*custom_malloc*
fun:LowLevel::*
```
[alloc-token]
# Exclude specific source files
src:third_party/allocator.c
# Exclude function name patterns
fun:*custom_malloc*
fun:LowLevel::*
```console
% clang++ -fsanitize=alloc-token -fsanitize-ignorelist=my_ignorelist.txt example.cc
```
.. code-block:: console
% clang++ -fsanitize=alloc-token -fsanitize-ignorelist=my_ignorelist.txt example.cc
Conditional Compilation with ``__SANITIZE_ALLOC_TOKEN__``
-----------------------------------------------------------
### Conditional Compilation with `__SANITIZE_ALLOC_TOKEN__`
In some cases, one may need to execute different code depending on whether
AllocToken instrumentation is enabled. The ``__SANITIZE_ALLOC_TOKEN__`` macro
AllocToken instrumentation is enabled. The `__SANITIZE_ALLOC_TOKEN__` macro
can be used for this purpose.
.. code-block:: c
#ifdef __SANITIZE_ALLOC_TOKEN__
// Code specific to -fsanitize=alloc-token builds
#endif
```c
#ifdef __SANITIZE_ALLOC_TOKEN__
// Code specific to -fsanitize=alloc-token builds
#endif
```

File diff suppressed because it is too large Load diff

View file

@ -1,90 +1,82 @@
======================================
Adoption Guide for ``-fbounds-safety``
======================================
# Adoption Guide for `-fbounds-safety`
.. contents::
:local:
```{contents}
:local: true
```
Where to get ``-fbounds-safety``
================================
## Where to get `-fbounds-safety`
The open sourcing to llvm.org's ``llvm-project`` is still on going and the
The open sourcing to llvm.org's `llvm-project` is still on going and the
feature is not available yet. In the mean time, the preview implementation is
available
`here <https://github.com/swiftlang/llvm-project/tree/stable/20240723>`_ in a
fork of ``llvm-project``. Please follow
`Building LLVM with CMake <https://llvm.org/docs/CMake.html>`_ to build the
[here](https://github.com/swiftlang/llvm-project/tree/stable/20240723) in a
fork of `llvm-project`. Please follow
[Building LLVM with CMake](https://llvm.org/docs/CMake.html) to build the
compiler.
Feature flag
============
## Feature flag
Pass ``-fbounds-safety`` as a Clang compilation flag for the C file that you
Pass `-fbounds-safety` as a Clang compilation flag for the C file that you
want to adopt. We recommend adopting the model file by file, because adoption
requires some effort to add bounds annotations and fix compiler diagnostics.
Include ``ptrcheck.h``
======================
## Include `ptrcheck.h`
``ptrcheck.h`` is a Clang toolchain header to provide definition of the bounds
annotations such as ``__counted_by``, ``__counted_by_or_null``, ``__sized_by``,
`ptrcheck.h` is a Clang toolchain header to provide definition of the bounds
annotations such as `__counted_by`, `__counted_by_or_null`, `__sized_by`,
etc. In the LLVM source tree, the header is located in
``llvm-project/clang/lib/Headers/ptrcheck.h``.
`llvm-project/clang/lib/Headers/ptrcheck.h`.
Add bounds annotations on pointers as necessary
===============================================
## Add bounds annotations on pointers as necessary
Annotate pointers on struct fields and function parameters if they are pointing
to an array of object, with appropriate bounds annotations. Please see
:doc:`BoundsSafety` to learn what kind of bounds annotations are available and
{doc}`BoundsSafety` to learn what kind of bounds annotations are available and
their semantics. Note that local pointer variables typically don't need bounds
annotations because they are implicitly a wide pointer (``__bidi_indexable``)
annotations because they are implicitly a wide pointer (`__bidi_indexable`)
that automatically carries the bounds information.
Address compiler diagnostics
============================
## Address compiler diagnostics
Once you pass ``-fbounds-safety`` to compile a C file, you will see some new
compiler warnings and errors, which guide adoption of ``-fbounds-safety``.
Once you pass `-fbounds-safety` to compile a C file, you will see some new
compiler warnings and errors, which guide adoption of `-fbounds-safety`.
Consider the following example:
.. code-block:: c
```c
#include <ptrcheck.h>
#include <ptrcheck.h>
void init_buf(int *p, int n) {
for (int i = 0; i < n; ++i)
p[i] = 0; // error: array subscript on single pointer 'p' must use a constant index of 0 to be in bounds
}
```
void init_buf(int *p, int n) {
for (int i = 0; i < n; ++i)
p[i] = 0; // error: array subscript on single pointer 'p' must use a constant index of 0 to be in bounds
}
The parameter ``int *p`` doesn't have a bounds annotation, so the compiler will
complain about the code indexing into it (``p[i]``) as it assumes that ``p`` is
pointing to a single ``int`` object or null. To address the diagnostics, you
should add a bounds annotation on ``int *p`` so that the compiler can reason
about the safety of the array subscript. In the following example, ``p`` is now
``int *__counted_by(n)``, so the compiler will allow the array subscript with
The parameter `int *p` doesn't have a bounds annotation, so the compiler will
complain about the code indexing into it (`p[i]`) as it assumes that `p` is
pointing to a single `int` object or null. To address the diagnostics, you
should add a bounds annotation on `int *p` so that the compiler can reason
about the safety of the array subscript. In the following example, `p` is now
`int *__counted_by(n)`, so the compiler will allow the array subscript with
additional run-time checks as necessary.
.. code-block:: c
```c
#include <ptrcheck.h>
#include <ptrcheck.h>
void init_buf(int *__counted_by(n) p, int n) {
for (int i = 0; i < n; ++i)
p[i] = 0; // ok; `p` is now has a type with bounds annotation.
}
```
void init_buf(int *__counted_by(n) p, int n) {
for (int i = 0; i < n; ++i)
p[i] = 0; // ok; `p` is now has a type with bounds annotation.
}
## Run test suites to fix new run-time traps
Run test suites to fix new run-time traps
=========================================
Adopting ``-fbounds-safety`` may cause your program to trap if it violates
Adopting `-fbounds-safety` may cause your program to trap if it violates
bounds safety or it has incorrect adoption. Thus, it is necessary to perform
run-time testing of your program to gain confidence that it won't trap at
run time.
Repeat the process for each remaining file
==========================================
## Repeat the process for each remaining file
Once you've done with adopting a single C file, please repeat the same process
for each remaining C file that you want to adopt.
for each remaining C file that you want to adopt.

View file

@ -1,60 +1,53 @@
============================================
Implementation plans for ``-fbounds-safety``
============================================
# Implementation plans for `-fbounds-safety`
.. contents::
:local:
```{contents}
:local: true
```
Gradual updates with experimental flag
======================================
## Gradual updates with experimental flag
The feature will be implemented as a series of smaller PRs and we will guard our
implementation with an experimental flag ``-fexperimental-bounds-safety`` until
implementation with an experimental flag `-fexperimental-bounds-safety` until
the usable model is fully available. Once the model is ready for use, we will
expose the flag ``-fbounds-safety``.
expose the flag `-fbounds-safety`.
Possible patch sets
-------------------
### Possible patch sets
* External bounds annotations and the (late) parsing logic.
* Internal bounds annotations (wide pointers) and their parsing logic.
* Clang code generation for wide pointers with debug information.
* Pointer cast semantics involving bounds annotations (this could be divided
- External bounds annotations and the (late) parsing logic.
- Internal bounds annotations (wide pointers) and their parsing logic.
- Clang code generation for wide pointers with debug information.
- Pointer cast semantics involving bounds annotations (this could be divided
into multiple sub-PRs).
* CFG analysis for pairs of related pointer and count assignments and the likes.
* Bounds check expressions in AST and the Clang code generation (this could also
- CFG analysis for pairs of related pointer and count assignments and the likes.
- Bounds check expressions in AST and the Clang code generation (this could also
be divided into multiple sub-PRs).
Proposed implementation
=======================
## Proposed implementation
External bounds annotations
---------------------------
### External bounds annotations
The bounds annotations are C type attributes appertaining to pointer types. If
an attribute is added to the position of a declaration attribute, e.g., ``int
*ptr __counted_by(size)``, the attribute appertains to the outermost pointer
type of the declaration (``int *``).
an attribute is added to the position of a declaration attribute, e.g., `int
*ptr __counted_by(size)`, the attribute appertains to the outermost pointer
type of the declaration (`int *`).
New sugar types
---------------
### New sugar types
An external bounds annotation creates a type sugar of the underlying pointer
types. We will introduce a new sugar type, ``DynamicBoundsPointerType`` to
represent ``__counted_by`` or ``__sized_by``. Using ``AttributedType`` would not
types. We will introduce a new sugar type, `DynamicBoundsPointerType` to
represent `__counted_by` or `__sized_by`. Using `AttributedType` would not
be sufficient because the type needs to hold the count or size expression as
well as some metadata necessary for analysis, while this type may be implemented
through inheritance from ``AttributedType``. Treating the annotations as type
through inheritance from `AttributedType`. Treating the annotations as type
sugars means two types with incompatible external bounds annotations may be
considered canonically the same types. This is sometimes necessary, for example,
to make the ``__counted_by`` and friends not participate in function
to make the `__counted_by` and friends not participate in function
overloading. However, this design requires a separate logic to walk through the
entire type hierarchy to check type compatibility of bounds annotations.
Late parsing for C
------------------
### Late parsing for C
A bounds annotation such as ``__counted_by(count)`` can be added to type of a
A bounds annotation such as `__counted_by(count)` can be added to type of a
struct field declaration where count is another field of the same struct
declared later. Similarly, the annotation may apply to type of a function
parameter declaration which precedes the parameter count in the same function.
@ -65,14 +58,13 @@ while the C declaration attributes and C/C++ type attributes do not have the
same logic. This requires introducing late parsing logic for C/C++ type
attributes.
Internal bounds annotations
---------------------------
### Internal bounds annotations
``__indexable`` and ``__bidi_indexable`` alter pointer representations to be
`__indexable` and `__bidi_indexable` alter pointer representations to be
equivalent to a struct with the pointer and the corresponding bounds fields.
Despite this difference in their representations, they are still pointers in
terms of types of operations that are allowed and their semantics. For instance,
a pointer dereference on a ``__bidi_indexable`` pointer will return the
a pointer dereference on a `__bidi_indexable` pointer will return the
dereferenced value same as plain C pointers, modulo the extra bounds checks
being performed before dereferencing the wide pointer. This means mapping the
wide pointers to struct types with equivalent layout won’t be sufficient. To
@ -83,16 +75,15 @@ while they are still treated as pointers.
In LLVM IR, wide pointers will be emitted as structs of equivalent
representations. Clang CodeGen will handle them as Aggregate in
``TypeEvaluationKind (TEK)``. ``AggExprEmitter`` was extended to handle pointer
operations returning wide pointers. Alternatively, a new ``TEK`` and an
`TypeEvaluationKind (TEK)`. `AggExprEmitter` was extended to handle pointer
operations returning wide pointers. Alternatively, a new `TEK` and an
expression emitter dedicated to wide pointers could be introduced.
Default bounds annotations
--------------------------
### Default bounds annotations
The model may implicitly add ``__bidi_indexable`` or ``__single`` depending on
the context of the declaration that has the pointer type. ``__bidi_indexable``
implicitly adds to local variables, while ``__single`` implicitly adds to
The model may implicitly add `__bidi_indexable` or `__single` depending on
the context of the declaration that has the pointer type. `__bidi_indexable`
implicitly adds to local variables, while `__single` implicitly adds to
pointer types specifying struct fields, function parameters, or global
variables. This means the parser may first create the pointer type without any
default pointer attribute and then recreate the type once the parser has the
@ -101,154 +92,144 @@ declaration context and determined the default attribute accordingly.
This also requires the parser to reset the type of the declaration with the
newly created type with the right default attribute.
Promotion expression
--------------------
### Promotion expression
A new expression will be introduced to represent the conversion from a pointer
with an external bounds annotation, such as ``__counted_by``, to
``__bidi_indexable``. This type of conversion cannot be handled by normal
with an external bounds annotation, such as `__counted_by`, to
`__bidi_indexable`. This type of conversion cannot be handled by normal
CastExprs because it requires an extra subexpression(s) to provide the bounds
information necessary to create a wide pointer.
Bounds check expression
-----------------------
### Bounds check expression
Bounds checks are part of semantics defined in the ``-fbounds-safety`` language
Bounds checks are part of semantics defined in the `-fbounds-safety` language
model. Hence, exposing the bounds checks and other semantic actions in the AST
is desirable. A new expression for bounds checks has been added to the AST. The
bounds check expression has a ``BoundsCheckKind`` to indicate the kind of checks
bounds check expression has a `BoundsCheckKind` to indicate the kind of checks
and has the additional sub-expressions that are necessary to perform the check
according to the kind.
Paired assignment check
-----------------------
### Paired assignment check
``-fbounds-safety`` enforces that variables or fields related with the same
external bounds annotation (e.g., ``buf`` and ``count`` related with
``__counted_by`` in the example below) must be updated side by side within the
`-fbounds-safety` enforces that variables or fields related with the same
external bounds annotation (e.g., `buf` and `count` related with
`__counted_by` in the example below) must be updated side by side within the
same basic block and without side effect in between.
.. code-block:: c
```c
typedef struct {
int *__counted_by(count) buf; size_t count;
} sized_buf_t;
typedef struct {
int *__counted_by(count) buf; size_t count;
} sized_buf_t;
void alloc_buf(sized_buf_t *sbuf, size_t nelems) {
sbuf->buf = (int *)malloc(sizeof(int) * nelems);
sbuf->count = nelems;
}
void alloc_buf(sized_buf_t *sbuf, size_t nelems) {
sbuf->buf = (int *)malloc(sizeof(int) * nelems);
sbuf->count = nelems;
}
```
To implement this rule, the compiler requires a linear representation of
statements to understand the ordering and the adjacency between the two or more
assignments. The Clang CFG is used to implement this analysis as Clang CFG
provides a linear view of statements within each ``CFGBlock`` (Clang
``CFGBlock`` represents a single basic block in a source-level CFG).
provides a linear view of statements within each `CFGBlock` (Clang
`CFGBlock` represents a single basic block in a source-level CFG).
Bounds check optimizations
--------------------------
### Bounds check optimizations
In ``-fbounds-safety``, the Clang frontend emits run-time checks for every
In `-fbounds-safety`, the Clang frontend emits run-time checks for every
memory dereference if the type system or analyses in the frontend couldn’t
verify its bounds safety. The implementation relies on LLVM optimizations to
remove redundant run-time checks. Using this optimization strategy, if the
original source code already has bounds checks, the fewer additional checks
``-fbounds-safety`` will introduce. The LLVM ``ConstraintElimination`` pass is
`-fbounds-safety` will introduce. The LLVM `ConstraintElimination` pass is
designed to remove provable redundant checks (please check Florian Hahn’s
presentation in 2021 LLVM Dev Meeting and the implementation to learn more). In
the following example, ``-fbounds-safety`` implicitly adds the redundant bounds
the following example, `-fbounds-safety` implicitly adds the redundant bounds
checks that the optimizer can remove:
.. code-block:: c
void fill_array_with_indices(int *__counted_by(count) p, size_t count) {
for (size_t i = 0; i < count; ++i) {
// implicit bounds checks:
// if (p + i < p || p + i + 1 > p + count) trap();
p[i] = i;
}
```c
void fill_array_with_indices(int *__counted_by(count) p, size_t count) {
for (size_t i = 0; i < count; ++i) {
// implicit bounds checks:
// if (p + i < p || p + i + 1 > p + count) trap();
p[i] = i;
}
}
```
``ConstraintElimination`` collects the following facts and determines if the
`ConstraintElimination` collects the following facts and determines if the
bounds checks can be safely removed:
* Inside the for-loop, ``0 <= i < count``, hence ``1 <= i + 1 <= count``.
* Pointer arithmetic ``p + count`` in the if-condition doesn’t wrap.
* ``-fbounds-safety`` treats pointer arithmetic overflow as deterministically
- Inside the for-loop, `0 <= i < count`, hence `1 <= i + 1 <= count`.
- Pointer arithmetic `p + count` in the if-condition doesn’t wrap.
- `-fbounds-safety` treats pointer arithmetic overflow as deterministically
two’s complement computation, not an undefined behavior. Therefore,
getelementptr does not typically have inbounds keyword. However, the compiler
does emit inbounds for ``p + count`` in this case because
``__counted_by(count)`` has the invariant that p has at least as many as
elements as count. Using this information, ``ConstraintElimination`` is able
to determine ``p + count`` doesn’t wrap.
* Accordingly, ``p + i`` and ``p + i + 1`` also don’t wrap.
* Therefore, ``p <= p + i`` and ``p + i + 1 <= p + count``.
* The if-condition simplifies to false and becomes dead code that the subsequent
does emit inbounds for `p + count` in this case because
`__counted_by(count)` has the invariant that p has at least as many as
elements as count. Using this information, `ConstraintElimination` is able
to determine `p + count` doesn’t wrap.
- Accordingly, `p + i` and `p + i + 1` also don’t wrap.
- Therefore, `p <= p + i` and `p + i + 1 <= p + count`.
- The if-condition simplifies to false and becomes dead code that the subsequent
optimization passes can remove.
``OptRemarks`` can be utilized to provide insights into performance tuning. It
`OptRemarks` can be utilized to provide insights into performance tuning. It
has the capability to report on checks that it cannot eliminate, possibly with
reasons, allowing programmers to adjust their code to unlock further
optimizations.
Debugging
=========
## Debugging
Internal bounds annotations
---------------------------
### Internal bounds annotations
Internal bounds annotations change a pointer into a wide pointer. The debugger
needs to understand that wide pointers are essentially pointers with a struct
layout. To handle this, a wide pointer is described as a record type in the
debug info. The type name has a special name prefix (e.g.,
``__bounds_safety$bidi_indexable``) which can be recognized by a debug info
`__bounds_safety$bidi_indexable`) which can be recognized by a debug info
consumer to provide support that goes beyond showing the internal structure of
the wide pointer. There are no DWARF extensions needed to support wide pointers.
In our implementation, LLDB recognizes wide pointer types by name and
reconstructs them as wide pointer Clang AST types for use in the expression
evaluator.
External bounds annotations
---------------------------
### External bounds annotations
Similar to internal bounds annotations, external bound annotations are described
as a typedef to their underlying pointer type in the debug info, and the bounds
are encoded as strings in the typedef’s name (e.g.,
``__bounds_safety$counted_by:N``).
`__bounds_safety$counted_by:N`).
Recognizing ``-fbounds-safety`` traps
-------------------------------------
### Recognizing `-fbounds-safety` traps
Clang emits debug info for ``-fbounds-safety`` traps as inlined functions, where
Clang emits debug info for `-fbounds-safety` traps as inlined functions, where
the function name encodes the error message. LLDB implements a frame recognizer
to surface a human-readable error cause to the end user. A debug info consumer
that is unaware of this sees an inlined function whose name encodes an error
message (e.g., : ``__bounds_safety$Bounds check failed``).
message (e.g., : `__bounds_safety$Bounds check failed`).
Expression Parsing
------------------
### Expression Parsing
In our implementation, LLDB’s expression evaluator does not enable the
``-fbounds-safety`` language option because it’s currently unable to fully
`-fbounds-safety` language option because it’s currently unable to fully
reconstruct the pointers with external bounds annotations, and also because the
evaluator operates in C++ mode, utilizing C++ reference types, while
``-fbounds-safety`` does not currently support C++. This means LLDB’s expression
evaluator can only evaluate a subset of the ``-fbounds-safety`` language model.
`-fbounds-safety` does not currently support C++. This means LLDB’s expression
evaluator can only evaluate a subset of the `-fbounds-safety` language model.
Specifically, it’s capable of evaluating the wide pointers that already exist in
the source code. All other expressions are evaluated according to C/C++
semantics.
C++ support
===========
## C++ support
C++ has multiple options to write code in a bounds-safe manner, such as
following the bounds-safety core guidelines and/or using hardened libc++ along
with the `C++ Safe Buffer model
<https://discourse.llvm.org/t/rfc-c-buffer-hardening/65734>`_. However, these
with the [C++ Safe Buffer model](https://discourse.llvm.org/t/rfc-c-buffer-hardening/65734). However, these
techniques may require ABI changes and may not be applicable to code
interoperating with C. When the ABI of an existing program needs to be preserved
and for headers shared between C and C++, ``-fbounds-safety`` offers a potential
and for headers shared between C and C++, `-fbounds-safety` offers a potential
solution.
``-fbounds-safety`` is not currently supported in C++, but we believe the
`-fbounds-safety` is not currently supported in C++, but we believe the
general approach would be applicable for future efforts.

View file

@ -1,23 +1,23 @@
=======
ClangIR
=======
# ClangIR
.. warning::
The project of upstreaming ClangIR support from the incubator repository is
still in progress, and ClangIR is not included in a default clang build. The
documentation may be incomplete and out-of-date.
:::{warning}
The project of upstreaming ClangIR support from the incubator repository is
still in progress, and ClangIR is not included in a default clang build. The
documentation may be incomplete and out-of-date.
:::
ClangIR is a high-level representation in Clang that reflects aspects of the
C/C++ languages and their extensions. It is implemented using MLIR and occupies
a position between Clang's AST and LLVM IR.
ClangIR Design Documents
========================
## ClangIR Design Documents
.. toctree::
:numbered:
:maxdepth: 1
```{toctree}
:maxdepth: 1
:numbered: true
ABILowering
CleanupAndEHDesign
CodeDuplication
```
ABILowering
CleanupAndEHDesign
CodeDuplication

View file

@ -1,12 +1,10 @@
=========================
C++ Type Aware Allocators
=========================
# C++ Type Aware Allocators
.. contents::
:local:
```{contents}
:local: true
```
Introduction
============
## Introduction
Clang includes an implementation of P2719 "Type-aware allocation and deallocation
functions".
@ -19,27 +17,27 @@ allocators.
P2719 introduces a type-identity tag as valid parameter type for all allocation
operators. This tag is a default initialized value of type `std::type_identity<T>`
where T is the type being allocated or deallocated. Unlike the other placement
where T is the type being allocated or deallocated. Unlike the other placement
arguments this tag is passed as the first parameter to the operator.
The most basic use case is as follows
.. code-block:: c++
```c++
#include <new>
#include <type_traits>
#include <new>
#include <type_traits>
struct S {
// ...
};
struct S {
// ...
};
void *operator new(std::type_identity<S>, size_t, std::align_val_t);
void operator delete(std::type_identity<S>, void *, size_t, std::align_val_t);
void *operator new(std::type_identity<S>, size_t, std::align_val_t);
void operator delete(std::type_identity<S>, void *, size_t, std::align_val_t);
void f() {
S *s = new S; // calls ::operator new(std::type_identity<S>(), sizeof(S), alignof(S))
delete s; // calls ::operator delete(std::type_identity<S>(), s, sizeof(S), alignof(S))
}
void f() {
S *s = new S; // calls ::operator new(std::type_identity<S>(), sizeof(S), alignof(S))
delete s; // calls ::operator delete(std::type_identity<S>(), s, sizeof(S), alignof(S))
}
```
While this functionality alone is powerful and useful, the true power comes
by using templates. In addition to adding the type-identity tag, P2719 allows
@ -53,38 +51,38 @@ This allows arbitrarily constrained definitions of the operators that resolve
as would be expected for any other template function resolution, e.g (only
showing `operator new` for brevity)
.. code-block:: c++
```c++
template <typename T, unsigned Size> struct Array {
T buffer[Size];
};
template <typename T, unsigned Size> struct Array {
T buffer[Size];
};
// Starting with a concrete type
void *operator new(std::type_identity<Array<int, 5>>, size_t, std::align_val_t);
// Starting with a concrete type
void *operator new(std::type_identity<Array<int, 5>>, size_t, std::align_val_t);
// Only care about five element arrays
template <typename T>
void *operator new(std::type_identity<Array<T, 5>>, size_t, std::align_val_t);
// Only care about five element arrays
template <typename T>
void *operator new(std::type_identity<Array<T, 5>>, size_t, std::align_val_t);
// An array of N floats
template <unsigned N>
void *operator new(std::type_identity<Array<float, N>>, size_t, std::align_val_t);
// An array of N floats
template <unsigned N>
void *operator new(std::type_identity<Array<float, N>>, size_t, std::align_val_t);
// Any array
template <typename T, unsigned N>
void *operator new(std::type_identity<Array<T, N>>, size_t, std::align_val_t);
// Any array
template <typename T, unsigned N>
void *operator new(std::type_identity<Array<T, N>>, size_t, std::align_val_t);
// A handy concept
template <typename T> concept Polymorphic = std::is_polymorphic_v<T>;
// A handy concept
template <typename T> concept Polymorphic = std::is_polymorphic_v<T>;
// Only applies is T is Polymorphic
template <Polymorphic T, unsigned N>
void *operator new(std::type_identity<Array<T, N>>, size_t, std::align_val_t);
// Only applies is T is Polymorphic
template <Polymorphic T, unsigned N>
void *operator new(std::type_identity<Array<T, N>>, size_t, std::align_val_t);
// Any even length array
template <typename T, unsigned N>
void *operator new(std::type_identity<Array<T, N>>, size_t, std::align_val_t)
requires(N%2 == 0);
// Any even length array
template <typename T, unsigned N>
void *operator new(std::type_identity<Array<T, N>>, size_t, std::align_val_t)
requires(N%2 == 0);
```
Operator selection then proceeds according to the usual rules for choosing
the best/most constrained match.
@ -92,19 +90,16 @@ the best/most constrained match.
Any declaration of a type aware operator new or operator delete must include a
matching complementary operator defined in the same scope.
Notes
=====
## Notes
Unconstrained Global Operators
------------------------------
### Unconstrained Global Operators
Declaring an unconstrained type aware global operator `new` or `delete` (or
`[]` variants) creates numerous hazards, similar to, but different from, those
created by attempting to replace the non-type aware global operators. For that
reason unconstrained operators are strongly discouraged.
Mismatching Constraints
-----------------------
### Mismatching Constraints
When declaring global type aware operators you should ensure the constraints
applied to new and delete match exactly, and declare them together. This
@ -112,8 +107,7 @@ limits the risk of having mismatching operators selected due to differing
constraints resulting in changes to prioritization when determining the most
viable candidate.
Declarations Across Libraries
-----------------------------
### Declarations Across Libraries
Declaring a typed allocator for a type in a separate TU or library creates
similar hazards as different libraries and TUs may see (or select) different
@ -121,35 +115,34 @@ definitions.
Under this model something like this would be risky
.. code-block:: c++
template<typename T>
void *operator new(std::type_identity<std::vector<T>>, size_t, std::align_val_t);
```c++
template<typename T>
void *operator new(std::type_identity<std::vector<T>>, size_t, std::align_val_t);
```
However this hazard is not present simply due to the use of the a type from
another library:
.. code-block:: c++
template<typename T>
struct MyType {
T thing;
};
template<typename T>
void *operator new(std::type_identity<MyType<std::vector<T>>>, size_t, std::align_val_t);
```c++
template<typename T>
struct MyType {
T thing;
};
template<typename T>
void *operator new(std::type_identity<MyType<std::vector<T>>>, size_t, std::align_val_t);
```
Here we see `std::vector` being used, but that is not the actual type being
allocated.
Implicit and Placement Parameters
---------------------------------
### Implicit and Placement Parameters
Type aware allocators are always passed both the implicit alignment and size
parameters in all cases. Explicit placement parameters are supported after the
mandatory implicit parameters.
Publication
===========
## Publication
`Type-aware allocation and deallocation functions <https://wg21.link/P2719>`_.
[Type-aware allocation and deallocation functions](https://wg21.link/P2719).
Louis Dionne, Oliver Hunt.

View file

@ -1,139 +1,125 @@
=============
Clang Plugins
=============
# Clang Plugins
Clang Plugins make it possible to run extra user defined actions during a
compilation. This document will provide a basic walkthrough of how to write and
run a Clang Plugin.
Introduction
============
## Introduction
Clang Plugins run FrontendActions over code. See the :doc:`FrontendAction
tutorial <RAVFrontendAction>` on how to write a ``FrontendAction`` using the
``RecursiveASTVisitor``. In this tutorial, we'll demonstrate how to write a
Clang Plugins run FrontendActions over code. See the {doc}`FrontendAction
tutorial <RAVFrontendAction>` on how to write a `FrontendAction` using the
`RecursiveASTVisitor`. In this tutorial, we'll demonstrate how to write a
simple clang plugin.
Writing a ``PluginASTAction``
=============================
## Writing a `PluginASTAction`
The main difference from writing normal ``FrontendActions`` is that you can
handle plugin command line options. The ``PluginASTAction`` base class declares
a ``ParseArgs`` method which you have to implement in your plugin.
The main difference from writing normal `FrontendActions` is that you can
handle plugin command line options. The `PluginASTAction` base class declares
a `ParseArgs` method which you have to implement in your plugin.
.. code-block:: c++
bool ParseArgs(const CompilerInstance &CI,
const std::vector<std::string>& args) {
for (unsigned i = 0, e = args.size(); i != e; ++i) {
if (args[i] == "-some-arg") {
// Handle the command line argument.
}
```c++
bool ParseArgs(const CompilerInstance &CI,
const std::vector<std::string>& args) {
for (unsigned i = 0, e = args.size(); i != e; ++i) {
if (args[i] == "-some-arg") {
// Handle the command line argument.
}
return true;
}
return true;
}
```
Registering a plugin
====================
## Registering a plugin
A plugin is loaded from a dynamic library at runtime by the compiler. To
register a plugin in a library, use ``FrontendPluginRegistry::Add<>``:
register a plugin in a library, use `FrontendPluginRegistry::Add<>`:
.. code-block:: c++
```c++
static FrontendPluginRegistry::Add<MyPlugin> X("my-plugin-name", "my plugin description");
```
static FrontendPluginRegistry::Add<MyPlugin> X("my-plugin-name", "my plugin description");
## Defining pragmas
Defining pragmas
================
Plugins can also define pragmas by declaring a `PragmaHandler` and
registering it using `PragmaHandlerRegistry::Add<>`:
Plugins can also define pragmas by declaring a ``PragmaHandler`` and
registering it using ``PragmaHandlerRegistry::Add<>``:
```c++
// Define a pragma handler for #pragma example_pragma
class ExamplePragmaHandler : public PragmaHandler {
public:
ExamplePragmaHandler() : PragmaHandler("example_pragma") { }
void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Token &PragmaTok) {
// Handle the pragma
}
};
.. code-block:: c++
static PragmaHandlerRegistry::Add<ExamplePragmaHandler> Y("example_pragma","example pragma description");
```
// Define a pragma handler for #pragma example_pragma
class ExamplePragmaHandler : public PragmaHandler {
public:
ExamplePragmaHandler() : PragmaHandler("example_pragma") { }
void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Token &PragmaTok) {
// Handle the pragma
}
};
## Defining attributes
static PragmaHandlerRegistry::Add<ExamplePragmaHandler> Y("example_pragma","example pragma description");
Plugins can define attributes by declaring a `ParsedAttrInfo` and registering
it using `ParsedAttrInfoRegister::Add<>`:
Defining attributes
===================
```c++
class ExampleAttrInfo : public ParsedAttrInfo {
public:
ExampleAttrInfo() {
Spellings.push_back({ParsedAttr::AS_GNU,"example"});
}
AttrHandling handleDeclAttribute(Sema &S, Decl *D,
const ParsedAttr &Attr) const override {
// Handle the attribute
return AttributeApplied;
}
};
Plugins can define attributes by declaring a ``ParsedAttrInfo`` and registering
it using ``ParsedAttrInfoRegister::Add<>``:
static ParsedAttrInfoRegistry::Add<ExampleAttrInfo> Z("example_attr","example attribute description");
```
.. code-block:: c++
The members of `ParsedAttrInfo` that a plugin attribute must define are:
class ExampleAttrInfo : public ParsedAttrInfo {
public:
ExampleAttrInfo() {
Spellings.push_back({ParsedAttr::AS_GNU,"example"});
}
AttrHandling handleDeclAttribute(Sema &S, Decl *D,
const ParsedAttr &Attr) const override {
// Handle the attribute
return AttributeApplied;
}
};
- `Spellings`, which must be populated with every [Spelling](https://clang.llvm.org/doxygen/structclang_1_1ParsedAttrInfo_1_1Spelling.html) of the
attribute, each of which consists of an attribute syntax and how the
attribute name is spelled for that syntax. If the syntax allows a scope then
the spelling must be "scope::attr" if a scope is present or "::attr" if not.
static ParsedAttrInfoRegistry::Add<ExampleAttrInfo> Z("example_attr","example attribute description");
The members of ``ParsedAttrInfo`` that a plugin attribute must define are:
* ``Spellings``, which must be populated with every `Spelling
</doxygen/structclang_1_1ParsedAttrInfo_1_1Spelling.html>`_ of the
attribute, each of which consists of an attribute syntax and how the
attribute name is spelled for that syntax. If the syntax allows a scope then
the spelling must be "scope::attr" if a scope is present or "::attr" if not.
The members of ``ParsedAttrInfo`` that may need to be defined, depending on the
The members of `ParsedAttrInfo` that may need to be defined, depending on the
attribute, are:
* ``NumArgs`` and ``OptArgs``, which set the number of required and optional
arguments to the attribute.
* ``diagAppertainsToDecl``, which checks if the attribute has been used on the
right kind of declaration and issues a diagnostic if not.
* ``handleDeclAttribute``, which is the function that applies the attribute to
a declaration. It is responsible for checking that the attribute's arguments
are valid, and typically applies the attribute by adding an ``Attr`` to the
``Decl``. It returns either ``AttributeApplied``, to indicate that the
attribute was successfully applied, or ``AttributeNotApplied`` if it wasn't.
* ``diagAppertainsToStmt``, which checks if the attribute has been used on the
right kind of statement and issues a diagnostic if not.
* ``handleStmtAttribute``, which is the function that applies the attribute to
a statement. It is responsible for checking that the attribute's arguments
are valid, and typically applies the attribute by adding an ``Attr`` to the
``Stmt``. It returns either ``AttributeApplied``, to indicate that the
attribute was successfully applied, or ``AttributeNotApplied`` if it wasn't.
* ``diagLangOpts``, which checks if the attribute is permitted for the current
language mode and issues a diagnostic if not.
* ``existsInTarget``, which checks if the attribute is permitted for the given
target.
- `NumArgs` and `OptArgs`, which set the number of required and optional
arguments to the attribute.
- `diagAppertainsToDecl`, which checks if the attribute has been used on the
right kind of declaration and issues a diagnostic if not.
- `handleDeclAttribute`, which is the function that applies the attribute to
a declaration. It is responsible for checking that the attribute's arguments
are valid, and typically applies the attribute by adding an `Attr` to the
`Decl`. It returns either `AttributeApplied`, to indicate that the
attribute was successfully applied, or `AttributeNotApplied` if it wasn't.
- `diagAppertainsToStmt`, which checks if the attribute has been used on the
right kind of statement and issues a diagnostic if not.
- `handleStmtAttribute`, which is the function that applies the attribute to
a statement. It is responsible for checking that the attribute's arguments
are valid, and typically applies the attribute by adding an `Attr` to the
`Stmt`. It returns either `AttributeApplied`, to indicate that the
attribute was successfully applied, or `AttributeNotApplied` if it wasn't.
- `diagLangOpts`, which checks if the attribute is permitted for the current
language mode and issues a diagnostic if not.
- `existsInTarget`, which checks if the attribute is permitted for the given
target.
To see a working example of an attribute plugin, see `the Attribute.cpp example
<https://github.com/llvm/llvm-project/blob/main/clang/examples/Attribute/Attribute.cpp>`_.
To see a working example of an attribute plugin, see [the Attribute.cpp example](https://github.com/llvm/llvm-project/blob/main/clang/examples/Attribute/Attribute.cpp).
Putting it all together
=======================
## Putting it all together
Let's look at an example plugin that prints top-level function names. This
Let's look at an example plugin that prints top-level function names. This
example is checked into the clang repository; please take a look at
the `latest version of PrintFunctionNames.cpp
<https://github.com/llvm/llvm-project/blob/main/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp>`_.
the [latest version of PrintFunctionNames.cpp](https://github.com/llvm/llvm-project/blob/main/clang/examples/PrintFunctionNames/PrintFunctionNames.cpp).
Running the plugin
==================
## Running the plugin
Using the compiler driver
--------------------------
### Using the compiler driver
The Clang driver accepts the `-fplugin` option to load a plugin.
Clang plugins can receive arguments from the compiler driver command
@ -141,21 +127,18 @@ line via the `fplugin-arg-<plugin name>-<argument>` option. Using this
method, the plugin name cannot contain dashes itself, but the argument
passed to the plugin can.
.. code-block:: console
$ export BD=/path/to/build/directory
$ make -C $BD CallSuperAttr
$ clang++ -fplugin=$BD/lib/CallSuperAttr.so \
-fplugin-arg-call_super_plugin-help \
test.cpp
```console
$ export BD=/path/to/build/directory
$ make -C $BD CallSuperAttr
$ clang++ -fplugin=$BD/lib/CallSuperAttr.so \
-fplugin-arg-call_super_plugin-help \
test.cpp
```
If your plugin name contains dashes, either rename the plugin or use the
cc1 command line options listed below.
Using the cc1 command line
--------------------------
### Using the cc1 command line
To run a plugin, the dynamic library containing the plugin registry must be
loaded via the `-load` command line option. This will load all plugins
@ -166,58 +149,54 @@ that are registered, and you can select the plugins to run by specifying the
Note that those options must reach clang's cc1 process. There are two
ways to do so:
* Directly call the parsing process by using the `-cc1` option; this
- Directly call the parsing process by using the `-cc1` option; this
has the downside of not configuring the default header search paths, so
you'll need to specify the full system path configuration on the command
line.
* Use clang as usual, but prefix all arguments to the cc1 process with
- Use clang as usual, but prefix all arguments to the cc1 process with
`-Xclang`.
For example, to run the ``print-function-names`` plugin over a source file in
For example, to run the `print-function-names` plugin over a source file in
clang, first build the plugin, and then call clang with the plugin from the
source tree:
.. code-block:: console
$ export BD=/path/to/build/directory
$ (cd $BD && make PrintFunctionNames )
$ clang++ -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS \
-D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE \
-I$BD/tools/clang/include -Itools/clang/include -I$BD/include -Iinclude \
tools/clang/tools/clang-check/ClangCheck.cpp -fsyntax-only \
-Xclang -load -Xclang $BD/lib/PrintFunctionNames.so -Xclang \
-plugin -Xclang print-fns
```console
$ export BD=/path/to/build/directory
$ (cd $BD && make PrintFunctionNames )
$ clang++ -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS \
-D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE \
-I$BD/tools/clang/include -Itools/clang/include -I$BD/include -Iinclude \
tools/clang/tools/clang-check/ClangCheck.cpp -fsyntax-only \
-Xclang -load -Xclang $BD/lib/PrintFunctionNames.so -Xclang \
-plugin -Xclang print-fns
```
Also see the print-function-name plugin example's
`README <https://github.com/llvm/llvm-project/blob/main/clang/examples/PrintFunctionNames/README.txt>`_
[README](https://github.com/llvm/llvm-project/blob/main/clang/examples/PrintFunctionNames/README.txt)
Using the clang command line
----------------------------
### Using the clang command line
Using `-fplugin=plugin` on the clang command line passes the plugin
through as an argument to `-load` on the cc1 command line. If the plugin
class implements the ``getActionType`` method then the plugin is run
class implements the `getActionType` method then the plugin is run
automatically. For example, to run the plugin automatically after the main AST
action (i.e. the same as using `-add-plugin`):
.. code-block:: c++
```c++
// Automatically run the plugin after the main AST action
PluginASTAction::ActionType getActionType() override {
return AddAfterMainAction;
}
```
// Automatically run the plugin after the main AST action
PluginASTAction::ActionType getActionType() override {
return AddAfterMainAction;
}
Interaction with ``-clear-ast-before-backend``
----------------------------------------------
### Interaction with `-clear-ast-before-backend`
To reduce peak memory usage of the compiler, plugins are recommended to run
*before* the main action, which is usually code generation. This is because
having any plugins that run after the codegen action automatically turns off
``-clear-ast-before-backend``. ``-clear-ast-before-backend`` reduces peak
`-clear-ast-before-backend`. `-clear-ast-before-backend` reduces peak
memory by clearing the Clang AST after generating IR and before running IR
optimizations. Use ``CmdlineBeforeMainAction`` or ``AddBeforeMainAction`` as
``getActionType`` to run plugins while still benefitting from
``-clear-ast-before-backend``. Plugins must make sure not to modify the AST,
optimizations. Use `CmdlineBeforeMainAction` or `AddBeforeMainAction` as
`getActionType` to run plugins while still benefitting from
`-clear-ast-before-backend`. Plugins must make sure not to modify the AST,
otherwise they should run after the main action.

View file

@ -1,18 +1,18 @@
Clang "man" pages
-----------------
# Clang "man" pages
The following documents are command descriptions for all of the Clang tools.
These pages describe how to use the Clang commands and what their options are.
Note that these pages do not describe all of the options available for all
tools. To get a complete listing, pass the ``--help`` (general options) or
``--help-hidden`` (general and debugging options) arguments to the tool you are
tools. To get a complete listing, pass the `--help` (general options) or
`--help-hidden` (general and debugging options) arguments to the tool you are
interested in.
Basic Commands
~~~~~~~~~~~~~~
## Basic Commands
.. toctree::
:maxdepth: 1
```{toctree}
:maxdepth: 1
clang
diagtool
```
clang
diagtool

View file

@ -1,17 +1,16 @@
======================
Control Flow Integrity
======================
# Control Flow Integrity
.. toctree::
:hidden:
```{toctree}
:hidden: true
ControlFlowIntegrityDesign
ControlFlowIntegrityDesign
```
.. contents::
:local:
```{contents}
:local: true
```
Introduction
============
## Introduction
Clang includes an implementation of a number of control flow integrity (CFI)
schemes, which are designed to abort the program upon detecting certain forms
@ -20,11 +19,11 @@ program's control flow. These schemes have been optimized for performance,
allowing developers to enable them in release builds.
To enable Clang's available CFI schemes, use the flag
``-fsanitize=cfi``. You can also enable a subset of available
:ref:`schemes <cfi-schemes>`. As currently implemented, all schemes
except for ``kcfi`` rely on link-time optimization (LTO); so it is
required to specify ``-flto`` or ``-flto=thin``, and the linker used
must support LTO, for example via the `gold plugin`_.
`-fsanitize=cfi`. You can also enable a subset of available
{ref}`schemes <cfi-schemes>`. As currently implemented, all schemes
except for `kcfi` rely on link-time optimization (LTO); so it is
required to specify `-flto` or `-flto=thin`, and the linker used
must support LTO, for example via the [gold plugin].
To allow the checks to be implemented efficiently, the program must
be structured such that certain object files are compiled with CFI
@ -34,92 +33,85 @@ the use of shared libraries in some cases.
The compiler will only produce CFI checks for a class if it can infer hidden
LTO visibility for that class. LTO visibility is a property of a class that
is inferred from flags and attributes. For more details, see the documentation
for :doc:`LTO visibility <LTOVisibility>`.
for {doc}`LTO visibility <LTOVisibility>`.
The ``-fsanitize=cfi-{vcall,nvcall,derived-cast,unrelated-cast}`` flags
require that a ``-fvisibility=`` flag also be specified. This is because the
default visibility setting is ``-fvisibility=default``, which would disable
The `-fsanitize=cfi-{vcall,nvcall,derived-cast,unrelated-cast}` flags
require that a `-fvisibility=` flag also be specified. This is because the
default visibility setting is `-fvisibility=default`, which would disable
CFI checks for classes without visibility attributes. Most users will want
to specify ``-fvisibility=hidden``, which enables CFI checks for such classes.
to specify `-fvisibility=hidden`, which enables CFI checks for such classes.
When using ``-fsanitize=cfi*`` with ``-flto=thin``, it is recommended
to reduce link times by passing `-funique-source-file-names
<UsersManual.html#cmdoption-f-no-unique-source-file-names>`_, provided
When using `-fsanitize=cfi*` with `-flto=thin`, it is recommended
to reduce link times by passing [-funique-source-file-names](https://clang.llvm.org/docs/UsersManual.html#cmdoption-f-no-unique-source-file-names), provided
that your program is compatible with it.
Experimental support for :ref:`cross-DSO control flow integrity
Experimental support for {ref}`cross-DSO control flow integrity
<cfi-cross-dso>` exists that does not require classes to have hidden LTO
visibility. This cross-DSO support has unstable ABI at this time.
.. _gold plugin: https://llvm.org/docs/GoldPlugin.html
(cfi-schemes)=
.. _cfi-schemes:
Available schemes
=================
## Available schemes
Available schemes are:
- ``-fsanitize=cfi-cast-strict``: Enables :ref:`strict cast checks
<cfi-strictness>`.
- ``-fsanitize=cfi-derived-cast``: Base-to-derived cast to the wrong
dynamic type.
- ``-fsanitize=cfi-unrelated-cast``: Cast from ``void*`` or another
unrelated type to the wrong dynamic type.
- ``-fsanitize=cfi-nvcall``: Non-virtual call via an object whose vptr is of
the wrong dynamic type.
- ``-fsanitize=cfi-vcall``: Virtual call via an object whose vptr is of the
wrong dynamic type.
- ``-fsanitize=cfi-icall``: Indirect call of a function with wrong dynamic
type.
- ``-fsanitize=cfi-mfcall``: Indirect call via a member function pointer with
wrong dynamic type.
- `-fsanitize=cfi-cast-strict`: Enables {ref}`strict cast checks
<cfi-strictness>`.
- `-fsanitize=cfi-derived-cast`: Base-to-derived cast to the wrong
dynamic type.
- `-fsanitize=cfi-unrelated-cast`: Cast from `void*` or another
unrelated type to the wrong dynamic type.
- `-fsanitize=cfi-nvcall`: Non-virtual call via an object whose vptr is of
the wrong dynamic type.
- `-fsanitize=cfi-vcall`: Virtual call via an object whose vptr is of the
wrong dynamic type.
- `-fsanitize=cfi-icall`: Indirect call of a function with wrong dynamic
type.
- `-fsanitize=cfi-mfcall`: Indirect call via a member function pointer with
wrong dynamic type.
You can use ``-fsanitize=cfi`` to enable all the schemes and use
``-fno-sanitize`` flag to narrow down the set of schemes as desired.
You can use `-fsanitize=cfi` to enable all the schemes and use
`-fno-sanitize` flag to narrow down the set of schemes as desired.
For example, you can build your program with
``-fsanitize=cfi -fno-sanitize=cfi-nvcall,cfi-icall``
`-fsanitize=cfi -fno-sanitize=cfi-nvcall,cfi-icall`
to use all schemes except for non-virtual member function call and indirect call
checking.
Remember that you have to provide ``-flto`` or ``-flto=thin`` if at
Remember that you have to provide `-flto` or `-flto=thin` if at
least one CFI scheme is enabled.
Trapping and Diagnostics
========================
## Trapping and Diagnostics
By default, CFI will abort the program immediately upon detecting a control
flow integrity violation. You can use the :ref:`-fno-sanitize-trap=
flow integrity violation. You can use the {ref}`-fno-sanitize-trap=
<controlling-code-generation>` flag to cause CFI to print a diagnostic
similar to the one below before the program aborts.
.. code-block:: console
bad-cast.cpp:109:7: runtime error: control flow integrity check for type 'B' failed during base-to-derived cast (vtable address 0x000000425a50)
0x000000425a50: note: vtable is of type 'A'
00 00 00 00 f0 f1 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 5a 42 00
^
```console
bad-cast.cpp:109:7: runtime error: control flow integrity check for type 'B' failed during base-to-derived cast (vtable address 0x000000425a50)
0x000000425a50: note: vtable is of type 'A'
00 00 00 00 f0 f1 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 5a 42 00
^
```
If diagnostics are enabled, you can also configure CFI to continue program
execution instead of aborting by using the :ref:`-fsanitize-recover=
execution instead of aborting by using the {ref}`-fsanitize-recover=
<controlling-code-generation>` flag.
Forward-Edge CFI for Virtual Calls
==================================
## Forward-Edge CFI for Virtual Calls
This scheme checks that virtual calls take place using a vptr of the correct
dynamic type; that is, the dynamic type of the called object must be a
derived class of the static type of the object used to make the call.
This CFI scheme can be enabled on its own using ``-fsanitize=cfi-vcall``.
This CFI scheme can be enabled on its own using `-fsanitize=cfi-vcall`.
For this scheme to work, all translation units containing the definition
of a virtual member function (whether inline or not), other than members
of :ref:`ignored <cfi-ignorelist>` types or types with public :doc:`LTO
visibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin``
of {ref}`ignored <cfi-ignorelist>` types or types with public {doc}`LTO
visibility <LTOVisibility>`, must be compiled with `-flto` or `-flto=thin`
enabled and be statically linked into the program.
Performance
-----------
### Performance
A performance overhead of less than 1% has been measured by running the
Dromaeo benchmark suite against an instrumented version of the Chromium
@ -129,8 +121,7 @@ virtual-call-heavy SPEC 2006 xalancbmk.
Note that this scheme has not yet been optimized for binary size; an increase
of up to 15% has been observed for Chromium.
Bad Cast Checking
=================
## Bad Cast Checking
This scheme checks that pointer casts are made to an object of the correct
dynamic type; that is, the dynamic type of the object must be a derived class
@ -143,48 +134,46 @@ of the same mechanisms.
There are two types of bad cast that may be forbidden: bad casts
from a base class to a derived class (which can be checked with
``-fsanitize=cfi-derived-cast``), and bad casts from a pointer of
type ``void*`` or another unrelated type (which can be checked with
``-fsanitize=cfi-unrelated-cast``).
`-fsanitize=cfi-derived-cast`), and bad casts from a pointer of
type `void*` or another unrelated type (which can be checked with
`-fsanitize=cfi-unrelated-cast`).
The difference between these two types of casts is that the first is defined
by the C++ standard to produce an undefined value, while the second is not
in itself undefined behavior (it is well defined to cast the pointer back
to its original type) unless the object is uninitialized and the cast is a
``static_cast`` (see C++14 [basic.life]p5).
`static_cast` (see C++14 [basic.life]p5).
If a program as a matter of policy forbids the second type of cast, that
restriction can normally be enforced. However it may in some cases be necessary
for a function to perform a forbidden cast to conform with an external API
(e.g. the ``allocate`` member function of a standard library allocator). Such
functions may be :ref:`ignored <cfi-ignorelist>`.
(e.g. the `allocate` member function of a standard library allocator). Such
functions may be {ref}`ignored <cfi-ignorelist>`.
For this scheme to work, all translation units containing the definition
of a virtual member function (whether inline or not), other than members
of :ref:`ignored <cfi-ignorelist>` types or types with public :doc:`LTO
visibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin``
of {ref}`ignored <cfi-ignorelist>` types or types with public {doc}`LTO
visibility <LTOVisibility>`, must be compiled with `-flto` or `-flto=thin`
enabled and be statically linked into the program.
Non-Virtual Member Function Call Checking
=========================================
## Non-Virtual Member Function Call Checking
This scheme checks that non-virtual calls take place using an object of
the correct dynamic type; that is, the dynamic type of the called object
must be a derived class of the static type of the object used to make the
call. The checks are currently only introduced where the object is of a
polymorphic class type. This CFI scheme can be enabled on its own using
``-fsanitize=cfi-nvcall``.
polymorphic class type. This CFI scheme can be enabled on its own using
`-fsanitize=cfi-nvcall`.
For this scheme to work, all translation units containing the definition
of a virtual member function (whether inline or not), other than members
of :ref:`ignored <cfi-ignorelist>` types or types with public :doc:`LTO
visibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin``
of {ref}`ignored <cfi-ignorelist>` types or types with public {doc}`LTO
visibility <LTOVisibility>`, must be compiled with `-flto` or `-flto=thin`
enabled and be statically linked into the program.
.. _cfi-strictness:
(cfi-strictness)=
Strictness
----------
### Strictness
If a class has a single non-virtual base and does not introduce or override
virtual member functions or fields other than an implicitly defined virtual
@ -196,56 +185,53 @@ Casting an instance of a base class to such a derived class is technically
undefined behavior, but it is a relatively common hack for introducing
member functions on class instances with specific properties that works under
most compilers and should not have security implications, so we allow it by
default. It can be disabled with ``-fsanitize=cfi-cast-strict``.
default. It can be disabled with `-fsanitize=cfi-cast-strict`.
Indirect Function Call Checking
===============================
## Indirect Function Call Checking
This scheme checks that function calls take place using a function of the
correct dynamic type; that is, the dynamic type of the function must match
the static type used at the call. This CFI scheme can be enabled on its own
using ``-fsanitize=cfi-icall``.
using `-fsanitize=cfi-icall`.
For this scheme to work, each indirect function call in the program, other
than calls in :ref:`ignored <cfi-ignorelist>` functions, must call a
function which was either compiled with ``-fsanitize=cfi-icall`` enabled,
than calls in {ref}`ignored <cfi-ignorelist>` functions, must call a
function which was either compiled with `-fsanitize=cfi-icall` enabled,
or whose address was taken by a function in a translation unit compiled with
``-fsanitize=cfi-icall``.
`-fsanitize=cfi-icall`.
If a function in a translation unit compiled with ``-fsanitize=cfi-icall``
takes the address of a function not compiled with ``-fsanitize=cfi-icall``,
If a function in a translation unit compiled with `-fsanitize=cfi-icall`
takes the address of a function not compiled with `-fsanitize=cfi-icall`,
that address may differ from the address taken by a function in a translation
unit not compiled with ``-fsanitize=cfi-icall``. This is technically a
unit not compiled with `-fsanitize=cfi-icall`. This is technically a
violation of the C and C++ standards, but it should not affect most programs.
Each translation unit compiled with ``-fsanitize=cfi-icall`` must be
Each translation unit compiled with `-fsanitize=cfi-icall` must be
statically linked into the program or shared library, and calls across
shared library boundaries are handled as if the callee was not compiled with
``-fsanitize=cfi-icall``.
`-fsanitize=cfi-icall`.
This scheme is currently supported on a limited set of targets: x86,
x86_64, arm, arch64 and wasm.
``-fsanitize-cfi-icall-generalize-pointers``
--------------------------------------------
### `-fsanitize-cfi-icall-generalize-pointers`
Mismatched pointer types are a common cause of cfi-icall check failures.
Translation units compiled with the ``-fsanitize-cfi-icall-generalize-pointers``
Translation units compiled with the `-fsanitize-cfi-icall-generalize-pointers`
flag relax pointer type checking for call sites in that translation unit,
applied across all functions compiled with ``-fsanitize=cfi-icall``.
applied across all functions compiled with `-fsanitize=cfi-icall`.
Specifically, pointers in return and argument types are treated as equivalent as
long as the qualifiers for the type they point to match. For example, ``char*``,
``char**``, and ``int*`` are considered equivalent types. However, ``char*`` and
``const char*`` are considered separate types.
long as the qualifiers for the type they point to match. For example, `char*`,
`char**`, and `int*` are considered equivalent types. However, `char*` and
`const char*` are considered separate types.
``-fsanitize-cfi-icall-generalize-pointers`` is not compatible with
``-fsanitize-cfi-cross-dso``.
`-fsanitize-cfi-icall-generalize-pointers` is not compatible with
`-fsanitize-cfi-cross-dso`.
.. _cfi-icall-experimental-normalize-integers:
(cfi-icall-experimental-normalize-integers)=
``-fsanitize-cfi-icall-experimental-normalize-integers``
--------------------------------------------------------
### `-fsanitize-cfi-icall-experimental-normalize-integers`
This option enables normalizing integer types as vendor extended types for
cross-language LLVM CFI/KCFI support with other languages that can't represent
@ -256,21 +242,20 @@ Specifically, integer types are encoded as their defined representations (e.g.,
compatibility with languages that define explicitly-sized integer types (e.g.,
i8, i16, i32, ..., in Rust).
``-fsanitize-cfi-icall-experimental-normalize-integers`` is compatible with
``-fsanitize-cfi-icall-generalize-pointers``.
`-fsanitize-cfi-icall-experimental-normalize-integers` is compatible with
`-fsanitize-cfi-icall-generalize-pointers`.
This option is currently experimental.
.. _cfi-canonical-jump-tables:
(cfi-canonical-jump-tables)=
``-fsanitize-cfi-canonical-jump-tables``
----------------------------------------
### `-fsanitize-cfi-canonical-jump-tables`
The default behavior of Clang's indirect function call checker will replace
the address of each CFI-checked function in the output file's symbol table
with the address of a jump table entry which will pass CFI checks. We refer
to this as making the jump table `canonical`. This property allows code that
was not compiled with ``-fsanitize=cfi-icall`` to take a CFI-valid address
to this as making the jump table *canonical*. This property allows code that
was not compiled with `-fsanitize=cfi-icall` to take a CFI-valid address
of a function, but it comes with a couple of caveats that are especially
relevant for users of cross-DSO CFI:
@ -279,7 +264,6 @@ relevant for users of cross-DSO CFI:
jump table entry, which must be emitted even in the common case where the
function is never address-taken anywhere in the program, and must be used
even for direct calls between DSOs, in addition to the PLT overhead.
- There is no good way to take a CFI-valid address of a function written in
assembly or a language not supported by Clang. The reason is that the code
generator would need to insert a jump table in order to form a CFI-valid
@ -292,7 +276,7 @@ relevant for users of cross-DSO CFI:
addition to adding runtime overhead.
For these reasons, we provide the option of making the jump table non-canonical
with the flag ``-fno-sanitize-cfi-canonical-jump-tables``. When the jump
with the flag `-fno-sanitize-cfi-canonical-jump-tables`. When the jump
table is made non-canonical, symbol table entries point directly to the
function body. Any instances of a function's address being taken in C will
be replaced with a jump table address.
@ -303,47 +287,44 @@ especially in cross-DSO mode which normally preserves function address
equality entirely.
Furthermore, it is occasionally necessary for code not compiled with
``-fsanitize=cfi-icall`` to take a function address that is valid
`-fsanitize=cfi-icall` to take a function address that is valid
for CFI. For example, this is necessary when a function's address
is taken by assembly code and then called by CFI-checking C code. The
``__attribute__((cfi_canonical_jump_table))`` attribute may be used to make
`__attribute__((cfi_canonical_jump_table))` attribute may be used to make
the jump table entry of a specific function canonical so that the external
code will end up taking an address for the function that will pass CFI checks.
``-fsanitize=cfi-icall`` and ``-fsanitize=function``
----------------------------------------------------
### `-fsanitize=cfi-icall` and `-fsanitize=function`
This tool is similar to ``-fsanitize=function`` in that both tools check
This tool is similar to `-fsanitize=function` in that both tools check
the types of function calls. However, the two tools occupy different points
on the design space; ``-fsanitize=function`` is a developer tool designed
to find bugs in local development builds, whereas ``-fsanitize=cfi-icall``
on the design space; `-fsanitize=function` is a developer tool designed
to find bugs in local development builds, whereas `-fsanitize=cfi-icall`
is a security hardening mechanism designed to be deployed in release builds.
``-fsanitize=function`` has a higher space and time overhead due to a more
`-fsanitize=function` has a higher space and time overhead due to a more
complex type check at indirect call sites, which may make it unsuitable for
deployment.
On the other hand, ``-fsanitize=function`` conforms more closely with the C++
On the other hand, `-fsanitize=function` conforms more closely with the C++
standard and user expectations around interaction with shared libraries;
the identity of function pointers is maintained, and calls across shared
library boundaries are no different from calls within a single program or
shared library.
.. _kcfi:
(kcfi)=
``-fsanitize=kcfi``
-------------------
### `-fsanitize=kcfi`
This is an alternative indirect call control-flow integrity scheme designed
for low-level system software, such as operating system kernels. Unlike
``-fsanitize=cfi-icall``, it doesn't require ``-flto``, won't result in
`-fsanitize=cfi-icall`, it doesn't require `-flto`, won't result in
function pointers being replaced with jump table references, and never breaks
cross-DSO function address equality. These properties make KCFI easier to
adopt in low-level software. KCFI is limited to checking only function
pointers, and isn't compatible with executable-only memory.
``-fsanitize-kcfi-arity``
-----------------------------
### `-fsanitize-kcfi-arity`
For supported targets, this feature extends kCFI by telling the compiler to
record information about each indirect-callable function's arity (i.e., the
@ -351,8 +332,7 @@ number of arguments passed in registers) into the binary. Some kernel CFI
techniques, such as FineIBT, may be able to use this information to provide
enhanced security.
Member Function Pointer Call Checking
=====================================
## Member Function Pointer Call Checking
This scheme checks that indirect calls via a member function pointer
take place using an object of the correct dynamic type. Specifically, we
@ -360,78 +340,75 @@ check that the dynamic type of the member function referenced by the member
function pointer matches the "function pointer" part of the member function
pointer, and that the member function's class type is related to the base
type of the member function. This CFI scheme can be enabled on its own using
``-fsanitize=cfi-mfcall``.
`-fsanitize=cfi-mfcall`.
The compiler will only emit a full CFI check if the member function pointer's
base type is complete. This is because the complete definition of the base
type contains information that is necessary to correctly compile the CFI
check. To ensure that the compiler always emits a full CFI check, it is
recommended to also pass the flag ``-fcomplete-member-pointers``, which
recommended to also pass the flag `-fcomplete-member-pointers`, which
enables a non-conforming language extension that requires member pointer
base types to be complete if they may be used for a call.
For this scheme to work, all translation units containing the definition
of a virtual member function (whether inline or not), other than members
of :ref:`ignored <cfi-ignorelist>` types or types with public :doc:`LTO
visibility <LTOVisibility>`, must be compiled with ``-flto`` or ``-flto=thin``
of {ref}`ignored <cfi-ignorelist>` types or types with public {doc}`LTO
visibility <LTOVisibility>`, must be compiled with `-flto` or `-flto=thin`
enabled and be statically linked into the program.
This scheme is currently not compatible with cross-DSO CFI or the
Microsoft ABI.
.. _cfi-ignorelist:
(cfi-ignorelist)=
Ignorelist
==========
## Ignorelist
A :doc:`SanitizerSpecialCaseList` can be used to relax CFI checks for certain
source files, functions and types using the ``src``, ``fun`` and ``type``
entity types. Specific CFI modes can be be specified using ``[section]``
A {doc}`SanitizerSpecialCaseList` can be used to relax CFI checks for certain
source files, functions and types using the `src`, `fun` and `type`
entity types. Specific CFI modes can be be specified using `[section]`
headers.
.. code-block:: bash
```bash
# Suppress all CFI checking for code in a file.
src:bad_file.cpp
src:bad_header.h
# Ignore all functions with names containing MyFooBar.
fun:*MyFooBar*
# Ignore all types in the standard library.
type:std::*
# Disable only unrelated cast checks for this function
[cfi-unrelated-cast]
fun:*UnrelatedCast*
# Disable CFI call checks for this function without affecting cast checks
[cfi-vcall|cfi-nvcall|cfi-icall]
fun:*BadCall*
```
# Suppress all CFI checking for code in a file.
src:bad_file.cpp
src:bad_header.h
# Ignore all functions with names containing MyFooBar.
fun:*MyFooBar*
# Ignore all types in the standard library.
type:std::*
# Disable only unrelated cast checks for this function
[cfi-unrelated-cast]
fun:*UnrelatedCast*
# Disable CFI call checks for this function without affecting cast checks
[cfi-vcall|cfi-nvcall|cfi-icall]
fun:*BadCall*
(cfi-cross-dso)=
.. _cfi-cross-dso:
Shared library support
======================
## Shared library support
Use **-f[no-]sanitize-cfi-cross-dso** to enable the cross-DSO control
flow integrity mode, which allows all CFI schemes listed above to
apply across DSO boundaries. As in the regular CFI, each DSO must be
built with ``-flto`` or ``-flto=thin``.
built with `-flto` or `-flto=thin`.
Normally, CFI checks will only be performed for classes that have hidden LTO
visibility. With this flag enabled, the compiler will emit cross-DSO CFI
checks for all classes, except for those which appear in the CFI ignorelist
or which use a ``no_sanitize`` attribute.
or which use a `no_sanitize` attribute.
Design
======
## Design
Please refer to the :doc:`design document<ControlFlowIntegrityDesign>`.
Please refer to the {doc}`design document<ControlFlowIntegrityDesign>`.
Publications
============
## Publications
`Control-Flow Integrity: Principles, Implementations, and Applications <https://research.microsoft.com/pubs/64250/ccs05.pdf>`_.
[Control-Flow Integrity: Principles, Implementations, and Applications](https://research.microsoft.com/pubs/64250/ccs05.pdf).
Martin Abadi, Mihai Budiu, Úlfar Erlingsson, Jay Ligatti.
`Enforcing Forward-Edge Control-Flow Integrity in GCC & LLVM <https://www.usenix.org/system/files/conference/usenixsecurity14/sec14-paper-tice.pdf>`_.
[Enforcing Forward-Edge Control-Flow Integrity in GCC & LLVM](https://www.usenix.org/system/files/conference/usenixsecurity14/sec14-paper-tice.pdf).
Caroline Tice, Tom Roeder, Peter Collingbourne, Stephen Checkoway,
Úlfar Erlingsson, Luis Lozano, Geoff Pike.
[gold plugin]: https://llvm.org/docs/GoldPlugin.html

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,6 @@
=======================
External Clang Examples
=======================
# External Clang Examples
Introduction
============
## Introduction
This page provides some examples of the kinds of things that people have
done with Clang that might serve as useful guides (or starting points) from
@ -19,85 +16,101 @@ where Clang is used are:
- Documentation/cross-reference generation.
If you know of (or wrote!) a tool or project using Clang, please post on
`the Discourse forums (Clang Frontend category)
<https://discourse.llvm.org/c/clang/6>`_ to have it added.
[the Discourse forums (Clang Frontend category)](https://discourse.llvm.org/c/clang/6) to have it added.
(or if you are already a Clang contributor, feel free to directly commit
additions). Since the primary purpose of this page is to provide examples
that can help developers, generally they must have code available.
List of projects and tools
==========================
## List of projects and tools
`<https://github.com/Andersbakken/rtags/>`_
"RTags is a client/server application that indexes c/c++ code and keeps
a persistent in-memory database of references, symbolnames, completions
etc."
[https://github.com/Andersbakken/rtags/](https://github.com/Andersbakken/rtags/)
`<https://rprichard.github.io/CxxCodeBrowser/>`_
"A C/C++ source code indexer and navigator."
: "RTags is a client/server application that indexes c/c++ code and keeps
a persistent in-memory database of references, symbolnames, completions
etc."
`<https://github.com/etaoins/qconnectlint>`_
"qconnectlint is a Clang tool for statically verifying the consistency
of signal and slot connections made with Qt's ``QObject::connect``."
[https://rprichard.github.io/CxxCodeBrowser/](https://rprichard.github.io/CxxCodeBrowser/)
`<https://github.com/woboq/woboq_codebrowser>`_
"The Woboq Code Browser is a web-based code browser for C/C++ projects.
Check out `<https://code.woboq.org/>`_ for an example!"
: "A C/C++ source code indexer and navigator."
`<https://github.com/mozilla/dxr>`_
"DXR is a source code cross-reference tool that uses static analysis
data collected by instrumented compilers."
[https://github.com/etaoins/qconnectlint](https://github.com/etaoins/qconnectlint)
`<https://github.com/eschulte/clang-mutate>`_
"This tool performs a number of operations on C-language source files."
: "qconnectlint is a Clang tool for statically verifying the consistency
of signal and slot connections made with Qt's `QObject::connect`."
`<https://github.com/gmarpons/Crisp>`_
"A coding rule validation add-on for LLVM/clang. Crisp rules are written
in Prolog. A high-level declarative DSL to easily write new rules is under
development. It will be called CRISP, an acronym for *Coding Rules in
Sugared Prolog*."
[https://github.com/woboq/woboq_codebrowser](https://github.com/woboq/woboq_codebrowser)
`<https://github.com/drothlis/clang-ctags>`_
"Generate tag file for C++ source code."
: "The Woboq Code Browser is a web-based code browser for C/C++ projects.
Check out [https://code.woboq.org/](https://code.woboq.org/) for an example!"
`<https://github.com/exclipy/clang_indexer>`_
"This is an indexer for C and C++ based on the libclang library."
[https://github.com/mozilla/dxr](https://github.com/mozilla/dxr)
`<https://github.com/holtgrewe/linty>`_
"Linty - C/C++ Style Checking with Python & libclang."
: "DXR is a source code cross-reference tool that uses static analysis
data collected by instrumented compilers."
`<https://github.com/axw/cmonster>`_
"cmonster is a Python wrapper for the Clang C++ parser."
[https://github.com/eschulte/clang-mutate](https://github.com/eschulte/clang-mutate)
`<https://github.com/rizsotto/Constantine>`_
"Constantine is a toy project to learn how to write clang plugin.
Implements pseudo const analysis. Generates warnings about variables,
which were declared without const qualifier."
: "This tool performs a number of operations on C-language source files."
`<https://github.com/jessevdk/cldoc>`_
"cldoc is a Clang based documentation generator for C and C++.
cldoc tries to solve the issue of writing C/C++ software documentation
with a modern, non-intrusive and robust approach."
[https://github.com/gmarpons/Crisp](https://github.com/gmarpons/Crisp)
`<https://github.com/AlexDenisov/ToyClangPlugin>`_
"The simplest Clang plugin implementing a semantic check for Objective-C.
This example shows how to use the ``DiagnosticsEngine`` (emit warnings,
errors, fixit hints). See also `<http://l.rw.rw/clang_plugin>`_ for
step-by-step instructions."
: "A coding rule validation add-on for LLVM/clang. Crisp rules are written
in Prolog. A high-level declarative DSL to easily write new rules is under
development. It will be called CRISP, an acronym for *Coding Rules in
Sugared Prolog*."
`<https://phabricator.kde.org/source/clazy>`_
"clazy is a compiler plugin which allows clang to understand Qt semantics.
You get more than 50 Qt related compiler warnings, ranging from unneeded
memory allocations to misusage of API, including fix-its for automatic
refactoring."
[https://github.com/drothlis/clang-ctags](https://github.com/drothlis/clang-ctags)
`<https://gerrit.libreoffice.org/gitweb?p=core.git;a=blob_plain;f=compilerplugins/README;hb=HEAD>`_
"LibreOffice uses a Clang plugin infrastructure to check during the build
various things, some more, some less specific to the LibreOffice source code.
There are currently around 50 such checkers, from flagging C-style casts and
uses of reserved identifiers to ensuring that code adheres to lifecycle
protocols for certain LibreOffice-specific classes. They may serve as
examples for writing RecursiveASTVisitor-based plugins."
: "Generate tag file for C++ source code."
[https://github.com/exclipy/clang_indexer](https://github.com/exclipy/clang_indexer)
: "This is an indexer for C and C++ based on the libclang library."
[https://github.com/holtgrewe/linty](https://github.com/holtgrewe/linty)
: "Linty - C/C++ Style Checking with Python & libclang."
[https://github.com/axw/cmonster](https://github.com/axw/cmonster)
: "cmonster is a Python wrapper for the Clang C++ parser."
[https://github.com/rizsotto/Constantine](https://github.com/rizsotto/Constantine)
: "Constantine is a toy project to learn how to write clang plugin.
Implements pseudo const analysis. Generates warnings about variables,
which were declared without const qualifier."
[https://github.com/jessevdk/cldoc](https://github.com/jessevdk/cldoc)
: "cldoc is a Clang based documentation generator for C and C++.
cldoc tries to solve the issue of writing C/C++ software documentation
with a modern, non-intrusive and robust approach."
[https://github.com/AlexDenisov/ToyClangPlugin](https://github.com/AlexDenisov/ToyClangPlugin)
: "The simplest Clang plugin implementing a semantic check for Objective-C.
This example shows how to use the `DiagnosticsEngine` (emit warnings,
errors, fixit hints). See also [http://l.rw.rw/clang_plugin](http://l.rw.rw/clang_plugin) for
step-by-step instructions."
[https://phabricator.kde.org/source/clazy](https://phabricator.kde.org/source/clazy)
: "clazy is a compiler plugin which allows clang to understand Qt semantics.
You get more than 50 Qt related compiler warnings, ranging from unneeded
memory allocations to misusage of API, including fix-its for automatic
refactoring."
[https://gerrit.libreoffice.org/gitweb?p=core.git;a=blob_plain;f=compilerplugins/README;hb=HEAD](https://gerrit.libreoffice.org/gitweb?p=core.git;a=blob_plain;f=compilerplugins/README;hb=HEAD)
: "LibreOffice uses a Clang plugin infrastructure to check during the build
various things, some more, some less specific to the LibreOffice source code.
There are currently around 50 such checkers, from flagging C-style casts and
uses of reserved identifiers to ensuring that code adheres to lifecycle
protocols for certain LibreOffice-specific classes. They may serve as
examples for writing RecursiveASTVisitor-based plugins."
[https://github.com/banach-space/clang-tutor](https://github.com/banach-space/clang-tutor)
: "A collection of out-of-tree Clang plugins for teaching and learning."
`<https://github.com/banach-space/clang-tutor>`_
"A collection of out-of-tree Clang plugins for teaching and learning."

View file

@ -1,64 +1,59 @@
================================
Frequently Asked Questions (FAQ)
================================
# Frequently Asked Questions (FAQ)
.. contents::
:local:
```{contents}
:local: true
```
Driver
======
## Driver
I run ``clang -cc1 ...`` and get weird errors about missing headers
-------------------------------------------------------------------
### I run `clang -cc1 ...` and get weird errors about missing headers
Given this source file:
.. code-block:: c
#include <stdio.h>
int main() {
printf("Hello world\n");
}
```c
#include <stdio.h>
int main() {
printf("Hello world\n");
}
```
If you run:
.. code-block:: console
```console
$ clang -cc1 hello.c
hello.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>
^
1 error generated.
```
$ clang -cc1 hello.c
hello.c:1:10: fatal error: 'stdio.h' file not found
#include <stdio.h>
^
1 error generated.
`clang -cc1` is the frontend, `clang` is the {doc}`driver
<DriverInternals>`. The driver invokes the frontend with options appropriate
for your system. To see these options, run:
``clang -cc1`` is the frontend, ``clang`` is the :doc:`driver
<DriverInternals>`. The driver invokes the frontend with options appropriate
for your system. To see these options, run:
.. code-block:: console
$ clang -### -c hello.c
```console
$ clang -### -c hello.c
```
Some clang command line options are driver-only options, some are frontend-only
options. Frontend-only options are intended to be used only by clang developers.
Users should not run ``clang -cc1`` directly, because ``-cc1`` options are not
options. Frontend-only options are intended to be used only by clang developers.
Users should not run `clang -cc1` directly, because `-cc1` options are not
guaranteed to be stable.
If you want to use a frontend-only option ("a ``-cc1`` option"), for example
``-ast-dump``, then you need to take the ``clang -cc1`` line generated by the
driver and add the option you need. Alternatively, you can run
``clang -Xclang <option> ...`` to force the driver pass ``<option>`` to
``clang -cc1``.
If you want to use a frontend-only option ("a `-cc1` option"), for example
`-ast-dump`, then you need to take the `clang -cc1` line generated by the
driver and add the option you need. Alternatively, you can run
`clang -Xclang <option> ...` to force the driver pass `<option>` to
`clang -cc1`.
I get errors about some headers being missing (``stddef.h``, ``stdarg.h``)
--------------------------------------------------------------------------
### I get errors about some headers being missing (`stddef.h`, `stdarg.h`)
Some header files (``stddef.h``, ``stdarg.h``, and others) are shipped with
Clang --- these are called builtin includes. Clang searches for them in a
directory relative to the location of the ``clang`` binary. If you moved the
``clang`` binary, you need to move the builtin headers, too.
Some header files (`stddef.h`, `stdarg.h`, and others) are shipped with
Clang --- these are called builtin includes. Clang searches for them in a
directory relative to the location of the `clang` binary. If you moved the
`clang` binary, you need to move the builtin headers, too.
More information can be found in the :ref:`libtooling_builtin_includes`
More information can be found in the {ref}`libtooling_builtin_includes`
section.

View file

@ -1,20 +1,17 @@
=============================
Introduction to the Clang AST
=============================
# Introduction to the Clang AST
This document gives a gentle introduction to the mysteries of the Clang
AST. It is targeted at developers who either want to contribute to
Clang, or use tools that work based on Clang's AST, like the AST
matchers.
.. raw:: html
```{raw} html
<center><iframe width="560" height="315" src="https://www.youtube.com/embed/VqCkCDFLSsc?vq=hd720" frameborder="0" allowfullscreen></iframe></center>
```
<center><iframe width="560" height="315" src="https://www.youtube.com/embed/VqCkCDFLSsc?vq=hd720" frameborder="0" allowfullscreen></iframe></center>
[Slides](https://llvm.org/devmtg/2013-04/klimek-slides.pdf)
`Slides <https://llvm.org/devmtg/2013-04/klimek-slides.pdf>`_
Introduction
============
## Introduction
Clang's AST is different from ASTs produced by some other compilers in
that it closely resembles both the written C++ code and the C++
@ -23,104 +20,102 @@ constants are available in an unreduced form in the AST. This makes
Clang's AST a good fit for refactoring tools.
Documentation for all Clang AST nodes is available via the generated
`Doxygen <https://clang.llvm.org/doxygen>`_. The doxygen online
[Doxygen](https://clang.llvm.org/doxygen). The doxygen online
documentation is also indexed by your favorite search engine, which will
make a search for clang and the AST node's class name usually turn up
the doxygen of the class you're looking for (for example, search for:
clang ParenExpr).
Examining the AST
=================
## Examining the AST
A good way to familiarize yourself with the Clang AST is to actually look
at it on some simple example code. Clang has a builtin AST-dump mode,
which can be enabled with the flag ``-ast-dump``.
which can be enabled with the flag `-ast-dump`.
Let's look at a simple example AST:
::
```
$ cat test.cc
int f(int x) {
int result = (x / 42);
return result;
}
$ cat test.cc
int f(int x) {
int result = (x / 42);
return result;
}
# Clang by default is a frontend for many tools; -Xclang is used to pass
# options directly to the C++ frontend.
$ clang -Xclang -ast-dump -fsyntax-only test.cc
TranslationUnitDecl 0x5aea0d0 <<invalid sloc>>
... cutting out internal declarations of clang ...
`-FunctionDecl 0x5aeab50 <test.cc:1:1, line:4:1> f 'int (int)'
|-ParmVarDecl 0x5aeaa90 <line:1:7, col:11> x 'int'
`-CompoundStmt 0x5aead88 <col:14, line:4:1>
|-DeclStmt 0x5aead10 <line:2:3, col:24>
| `-VarDecl 0x5aeac10 <col:3, col:23> result 'int'
| `-ParenExpr 0x5aeacf0 <col:16, col:23> 'int'
| `-BinaryOperator 0x5aeacc8 <col:17, col:21> 'int' '/'
| |-ImplicitCastExpr 0x5aeacb0 <col:17> 'int' <LValueToRValue>
| | `-DeclRefExpr 0x5aeac68 <col:17> 'int' lvalue ParmVar 0x5aeaa90 'x' 'int'
| `-IntegerLiteral 0x5aeac90 <col:21> 'int' 42
`-ReturnStmt 0x5aead68 <line:3:3, col:10>
`-ImplicitCastExpr 0x5aead50 <col:10> 'int' <LValueToRValue>
`-DeclRefExpr 0x5aead28 <col:10> 'int' lvalue Var 0x5aeac10 'result' 'int'
# Clang by default is a frontend for many tools; -Xclang is used to pass
# options directly to the C++ frontend.
$ clang -Xclang -ast-dump -fsyntax-only test.cc
TranslationUnitDecl 0x5aea0d0 <<invalid sloc>>
... cutting out internal declarations of clang ...
`-FunctionDecl 0x5aeab50 <test.cc:1:1, line:4:1> f 'int (int)'
|-ParmVarDecl 0x5aeaa90 <line:1:7, col:11> x 'int'
`-CompoundStmt 0x5aead88 <col:14, line:4:1>
|-DeclStmt 0x5aead10 <line:2:3, col:24>
| `-VarDecl 0x5aeac10 <col:3, col:23> result 'int'
| `-ParenExpr 0x5aeacf0 <col:16, col:23> 'int'
| `-BinaryOperator 0x5aeacc8 <col:17, col:21> 'int' '/'
| |-ImplicitCastExpr 0x5aeacb0 <col:17> 'int' <LValueToRValue>
| | `-DeclRefExpr 0x5aeac68 <col:17> 'int' lvalue ParmVar 0x5aeaa90 'x' 'int'
| `-IntegerLiteral 0x5aeac90 <col:21> 'int' 42
`-ReturnStmt 0x5aead68 <line:3:3, col:10>
`-ImplicitCastExpr 0x5aead50 <col:10> 'int' <LValueToRValue>
`-DeclRefExpr 0x5aead28 <col:10> 'int' lvalue Var 0x5aeac10 'result' 'int'
```
The toplevel declaration in
a translation unit is always the `translation unit
declaration <https://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html>`_.
In this example, our first user written declaration is the `function
declaration <https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html>`_
of "``f``". The body of "``f``" is a `compound
statement <https://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html>`_,
whose child nodes are a `declaration
statement <https://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html>`_
that declares our result variable, and the `return
statement <https://clang.llvm.org/doxygen/classclang_1_1ReturnStmt.html>`_.
a translation unit is always the [translation unit
declaration](https://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html).
In this example, our first user written declaration is the [function
declaration](https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html)
of "`f`". The body of "`f`" is a [compound
statement](https://clang.llvm.org/doxygen/classclang_1_1CompoundStmt.html),
whose child nodes are a [declaration
statement](https://clang.llvm.org/doxygen/classclang_1_1DeclStmt.html)
that declares our result variable, and the [return
statement](https://clang.llvm.org/doxygen/classclang_1_1ReturnStmt.html).
AST Context
===========
## AST Context
All information about the AST for a translation unit is bundled up in
the class
`ASTContext <https://clang.llvm.org/doxygen/classclang_1_1ASTContext.html>`_.
[ASTContext](https://clang.llvm.org/doxygen/classclang_1_1ASTContext.html).
It allows traversal of the whole translation unit starting from
`getTranslationUnitDecl <https://clang.llvm.org/doxygen/classclang_1_1ASTContext.html#abd909fb01ef10cfd0244832a67b1dd64>`_,
or to access Clang's `table of
identifiers <https://clang.llvm.org/doxygen/classclang_1_1ASTContext.html#a4f95adb9958e22fbe55212ae6482feb4>`_
[getTranslationUnitDecl](https://clang.llvm.org/doxygen/classclang_1_1ASTContext.html#abd909fb01ef10cfd0244832a67b1dd64),
or to access Clang's [table of
identifiers](https://clang.llvm.org/doxygen/classclang_1_1ASTContext.html#a4f95adb9958e22fbe55212ae6482feb4)
for the parsed translation unit.
AST Nodes
=========
## AST Nodes
Clang's AST nodes are modeled on a class hierarchy that does not have a
common ancestor. Instead, there are multiple larger hierarchies for
basic node types like
`Decl <https://clang.llvm.org/doxygen/classclang_1_1Decl.html>`_ and
`Stmt <https://clang.llvm.org/doxygen/classclang_1_1Stmt.html>`_. Many
[Decl](https://clang.llvm.org/doxygen/classclang_1_1Decl.html) and
[Stmt](https://clang.llvm.org/doxygen/classclang_1_1Stmt.html). Many
important AST nodes derive from
`Type <https://clang.llvm.org/doxygen/classclang_1_1Type.html>`_,
`Decl <https://clang.llvm.org/doxygen/classclang_1_1Decl.html>`_,
`DeclContext <https://clang.llvm.org/doxygen/classclang_1_1DeclContext.html>`_
or `Stmt <https://clang.llvm.org/doxygen/classclang_1_1Stmt.html>`_, with
[Type](https://clang.llvm.org/doxygen/classclang_1_1Type.html),
[Decl](https://clang.llvm.org/doxygen/classclang_1_1Decl.html),
[DeclContext](https://clang.llvm.org/doxygen/classclang_1_1DeclContext.html)
or [Stmt](https://clang.llvm.org/doxygen/classclang_1_1Stmt.html), with
some classes deriving from both Decl and DeclContext.
There are also a multitude of nodes in the AST that are not part of a
larger hierarchy, and are only reachable from specific other nodes, like
`CXXBaseSpecifier <https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html>`_.
[CXXBaseSpecifier](https://clang.llvm.org/doxygen/classclang_1_1CXXBaseSpecifier.html).
Thus, to traverse the full AST, one starts from the
`TranslationUnitDecl <https://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html>`_
[TranslationUnitDecl](https://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html)
and then recursively traverses everything that can be reached from that
node - this information has to be encoded for each specific node type.
This algorithm is encoded in the
`RecursiveASTVisitor <https://clang.llvm.org/doxygen/classclang_1_1RecursiveASTVisitor.html>`_.
See the `RecursiveASTVisitor
tutorial <https://clang.llvm.org/docs/RAVFrontendAction.html>`_.
[RecursiveASTVisitor](https://clang.llvm.org/doxygen/classclang_1_1RecursiveASTVisitor.html).
See the [RecursiveASTVisitor
tutorial](https://clang.llvm.org/docs/RAVFrontendAction.html).
The two most basic nodes in the Clang AST are statements
(`Stmt <https://clang.llvm.org/doxygen/classclang_1_1Stmt.html>`_) and
([Stmt](https://clang.llvm.org/doxygen/classclang_1_1Stmt.html)) and
declarations
(`Decl <https://clang.llvm.org/doxygen/classclang_1_1Decl.html>`_). Note
([Decl](https://clang.llvm.org/doxygen/classclang_1_1Decl.html)). Note
that expressions
(`Expr <https://clang.llvm.org/doxygen/classclang_1_1Expr.html>`_) are
([Expr](https://clang.llvm.org/doxygen/classclang_1_1Expr.html)) are
also statements in Clang's AST.

View file

@ -1,401 +1,383 @@
.. role:: raw-html(raw)
:format: html
# Libclang tutorial
Libclang tutorial
=================
The C Interface to Clang provides a relatively small API that exposes facilities for parsing source code into an abstract syntax tree (AST), loading already-parsed ASTs, traversing the AST, associating physical source locations with elements within the AST, and other facilities that support Clang-based development tools.
This C interface to Clang will never provide all of the information representation stored in Clang's C++ AST, nor should it: the intent is to maintain an API that is :ref:`relatively stable <Stability>` from one release to the next, providing only the basic functionality needed to support development tools.
The entire C interface of libclang is available in the file `Index.h`_
This C interface to Clang will never provide all of the information representation stored in Clang's C++ AST, nor should it: the intent is to maintain an API that is {ref}`relatively stable <Stability>` from one release to the next, providing only the basic functionality needed to support development tools.
The entire C interface of libclang is available in the file [Index.h]
Essential types overview
-------------------------
## Essential types overview
All types of libclang are prefixed with ``CX``
All types of libclang are prefixed with `CX`
### CXIndex
CXIndex
~~~~~~~
An Index that consists of a set of translation units that would typically be linked together into an executable or library.
CXTranslationUnit
~~~~~~~~~~~~~~~~~
### CXTranslationUnit
A single translation unit, which resides in an index.
CXCursor
~~~~~~~~
### CXCursor
A cursor representing a pointer to some element in the abstract syntax tree of a translation unit.
#### Code example
Code example
""""""""""""
```cpp
// file.cpp
struct foo{
int bar;
int* bar_pointer;
};
```
.. code-block:: cpp
```cpp
// main.cpp
#include <clang-c/Index.h>
#include <iostream>
// file.cpp
struct foo{
int bar;
int* bar_pointer;
};
.. code-block:: cpp
// main.cpp
#include <clang-c/Index.h>
#include <iostream>
int main(){
CXIndex index = clang_createIndex(0, 0); //Create index
CXTranslationUnit unit = clang_parseTranslationUnit(
index,
"file.cpp", nullptr, 0,
nullptr, 0,
CXTranslationUnit_None); //Parse "file.cpp"
int main(){
CXIndex index = clang_createIndex(0, 0); //Create index
CXTranslationUnit unit = clang_parseTranslationUnit(
index,
"file.cpp", nullptr, 0,
nullptr, 0,
CXTranslationUnit_None); //Parse "file.cpp"
if (unit == nullptr){
std::cerr << "Unable to parse translation unit. Quitting.\n";
return 0;
}
CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit
if (unit == nullptr){
std::cerr << "Unable to parse translation unit. Quitting.\n";
return 0;
}
CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit
}
```
.. code-block:: cmake
```cmake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(my_clang_tool VERSION 0.1.0)
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(my_clang_tool VERSION 0.1.0)
# This will find the default system installation of Clang; if you want to
# use a different build of clang, pass -DClang_DIR=/foobar/lib/cmake/clang
# to the CMake configure command, where /foobar is the build directory where
# you built Clang.
find_package(Clang CONFIG REQUIRED)
# This will find the default system installation of Clang; if you want to
# use a different build of clang, pass -DClang_DIR=/foobar/lib/cmake/clang
# to the CMake configure command, where /foobar is the build directory where
# you built Clang.
find_package(Clang CONFIG REQUIRED)
add_executable(my_clang_tool main.cpp)
target_include_directories(my_clang_tool PRIVATE ${CLANG_INCLUDE_DIRS})
target_link_libraries(my_clang_tool PRIVATE libclang)
```
add_executable(my_clang_tool main.cpp)
target_include_directories(my_clang_tool PRIVATE ${CLANG_INCLUDE_DIRS})
target_link_libraries(my_clang_tool PRIVATE libclang)
### Visiting elements of an AST
Visiting elements of an AST
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The elements of an AST can be recursively visited with pre-order traversal with ``clang_visitChildren``.
The elements of an AST can be recursively visited with pre-order traversal with `clang_visitChildren`.
.. code-block:: cpp
```cpp
clang_visitChildren(
cursor, //Root cursor
[](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
clang_visitChildren(
cursor, //Root cursor
[](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
CXString current_display_name = clang_getCursorDisplayName(current_cursor);
//Allocate a CXString representing the name of the current cursor
CXString current_display_name = clang_getCursorDisplayName(current_cursor);
//Allocate a CXString representing the name of the current cursor
std::cout << "Visiting element " << clang_getCString(current_display_name) << "\n";
//Print the char* value of current_display_name
std::cout << "Visiting element " << clang_getCString(current_display_name) << "\n";
//Print the char* value of current_display_name
clang_disposeString(current_display_name);
//Since clang_getCursorDisplayName allocates a new CXString, it must be freed. This applies
//to all functions returning a CXString
clang_disposeString(current_display_name);
//Since clang_getCursorDisplayName allocates a new CXString, it must be freed. This applies
//to all functions returning a CXString
return CXChildVisit_Recurse;
return CXChildVisit_Recurse;
}, //CXCursorVisitor: a function pointer
nullptr //client_data
);
}, //CXCursorVisitor: a function pointer
nullptr //client_data
);
```
The return value of ``CXCursorVisitor``, the callable argument of ``clang_visitChildren``, can return one of the three:
The return value of `CXCursorVisitor`, the callable argument of `clang_visitChildren`, can return one of the three:
#. ``CXChildVisit_Break``: Terminates the cursor traversal
#. ``CXChildVisit_Continue``: Continues the cursor traversal with the next sibling of the cursor just visited, without visiting its children.
#. ``CXChildVisit_Recurse``: Recursively traverse the children of this cursor, using the same visitor and client data
1. `CXChildVisit_Break`: Terminates the cursor traversal
2. `CXChildVisit_Continue`: Continues the cursor traversal with the next sibling of the cursor just visited, without visiting its children.
3. `CXChildVisit_Recurse`: Recursively traverse the children of this cursor, using the same visitor and client data
The expected output of that program is
.. code-block::
```
Visiting element foo
Visiting element bar
Visiting element bar_pointer
```
Visiting element foo
Visiting element bar
Visiting element bar_pointer
### Extracting information from a Cursor
% The following functions take a ``CXCursor`` as an argument and return associated information.
Extracting information from a Cursor
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. The following functions take a ``CXCursor`` as an argument and return associated information.
#### Extracting the Cursor kind
`CXCursorKind clang_getCursorKind(CXCursor)` Describes the kind of entity that a cursor refers to. Example values:
- `CXCursor_StructDecl`: A C or C++ struct.
- `CXCursor_FieldDecl`: A field in a struct, union, or C++ class.
- `CXCursor_CallExpr`: An expression that calls a function.
Extracting the Cursor kind
""""""""""""""""""""""""""
#### Extracting the Cursor type
``CXCursorKind clang_getCursorKind(CXCursor)`` Describes the kind of entity that a cursor refers to. Example values:
`CXType clang_getCursorType(CXCursor)`: Retrieve the type of a CXCursor (if any).
- ``CXCursor_StructDecl``: A C or C++ struct.
- ``CXCursor_FieldDecl``: A field in a struct, union, or C++ class.
- ``CXCursor_CallExpr``: An expression that calls a function.
A `CXType` represents a complete C++ type, including qualifiers and pointers. It has a member field `CXTypeKind kind` and additional opaque data.
Example values for `CXTypeKind kind`
Extracting the Cursor type
""""""""""""""""""""""""""
``CXType clang_getCursorType(CXCursor)``: Retrieve the type of a CXCursor (if any).
- `CXType_Invalid`: Represents an invalid type (e.g., where no type is available)
- `CXType_Pointer`: A pointer to another type
- `CXType_Int`: Regular `int`
- `CXType_Elaborated`: Represents a type that was referred to using an elaborated type keyword e.g. struct S, or via a qualified name, e.g., N::M::type, or both.
A ``CXType`` represents a complete C++ type, including qualifiers and pointers. It has a member field ``CXTypeKind kind`` and additional opaque data.
Any `CXTypeKind` can be converted to a `CXString` using `clang_getTypeKindSpelling(CXTypeKind)`.
Example values for ``CXTypeKind kind``
- ``CXType_Invalid``: Represents an invalid type (e.g., where no type is available)
- ``CXType_Pointer``: A pointer to another type
- ``CXType_Int``: Regular ``int``
- ``CXType_Elaborated``: Represents a type that was referred to using an elaborated type keyword e.g. struct S, or via a qualified name, e.g., N::M::type, or both.
Any ``CXTypeKind`` can be converted to a ``CXString`` using ``clang_getTypeKindSpelling(CXTypeKind)``.
A ``CXType`` holds additional necessary opaque type info, such as:
A `CXType` holds additional necessary opaque type info, such as:
- Which struct was referred to?
- What type is the pointer pointing to?
- Qualifiers (e.g. ``const``, ``volatile``)?
- Qualifiers (e.g. `const`, `volatile`)?
Qualifiers of a ``CXType`` can be queried with:
Qualifiers of a `CXType` can be queried with:
- ``clang_isConstQualifiedType(CXType)`` to check for ``const``
- ``clang_isRestrictQualifiedType(CXType)`` to check for ``restrict``
- ``clang_isVolatileQualifiedType(CXType)`` to check for ``volatile``
- `clang_isConstQualifiedType(CXType)` to check for `const`
- `clang_isRestrictQualifiedType(CXType)` to check for `restrict`
- `clang_isVolatileQualifiedType(CXType)` to check for `volatile`
Code example
""""""""""""
.. code-block:: cpp
#### Code example
//structs.cpp
struct A{
int value;
};
struct B{
int value;
A struct_value;
};
```cpp
//structs.cpp
struct A{
int value;
};
struct B{
int value;
A struct_value;
};
```
.. code-block:: cpp
```cpp
#include <clang-c/Index.h>
#include <iostream>
#include <clang-c/Index.h>
#include <iostream>
int main(){
CXIndex index = clang_createIndex(0, 0); //Create index
CXTranslationUnit unit = clang_parseTranslationUnit(
index,
"structs.cpp", nullptr, 0,
nullptr, 0,
CXTranslationUnit_None); //Parse "structs.cpp"
int main(){
CXIndex index = clang_createIndex(0, 0); //Create index
CXTranslationUnit unit = clang_parseTranslationUnit(
index,
"structs.cpp", nullptr, 0,
nullptr, 0,
CXTranslationUnit_None); //Parse "structs.cpp"
if (unit == nullptr){
std::cerr << "Unable to parse translation unit. Quitting.\n";
return 0;
}
CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit
if (unit == nullptr){
std::cerr << "Unable to parse translation unit. Quitting.\n";
return 0;
clang_visitChildren(
cursor,
[](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
CXType cursor_type = clang_getCursorType(current_cursor);
CXString type_kind_spelling = clang_getTypeKindSpelling(cursor_type.kind);
std::cout << "Type Kind: " << clang_getCString(type_kind_spelling);
clang_disposeString(type_kind_spelling);
if(cursor_type.kind == CXType_Pointer || // If cursor_type is a pointer
cursor_type.kind == CXType_LValueReference || // or an LValue Reference (&)
cursor_type.kind == CXType_RValueReference){ // or an RValue Reference (&&),
CXType pointed_to_type = clang_getPointeeType(cursor_type);// retrieve the pointed-to type
CXString pointed_to_type_spelling = clang_getTypeSpelling(pointed_to_type); // Spell out the entire
std::cout << "pointing to type: " << clang_getCString(pointed_to_type_spelling);// pointed-to type
clang_disposeString(pointed_to_type_spelling);
}
CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit
clang_visitChildren(
cursor,
[](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
CXType cursor_type = clang_getCursorType(current_cursor);
CXString type_kind_spelling = clang_getTypeKindSpelling(cursor_type.kind);
std::cout << "Type Kind: " << clang_getCString(type_kind_spelling);
clang_disposeString(type_kind_spelling);
if(cursor_type.kind == CXType_Pointer || // If cursor_type is a pointer
cursor_type.kind == CXType_LValueReference || // or an LValue Reference (&)
cursor_type.kind == CXType_RValueReference){ // or an RValue Reference (&&),
CXType pointed_to_type = clang_getPointeeType(cursor_type);// retrieve the pointed-to type
CXString pointed_to_type_spelling = clang_getTypeSpelling(pointed_to_type); // Spell out the entire
std::cout << "pointing to type: " << clang_getCString(pointed_to_type_spelling);// pointed-to type
clang_disposeString(pointed_to_type_spelling);
}
else if(cursor_type.kind == CXType_Record){
CXString type_spelling = clang_getTypeSpelling(cursor_type);
std::cout << ", namely " << clang_getCString(type_spelling);
clang_disposeString(type_spelling);
}
std::cout << "\n";
return CXChildVisit_Recurse;
},
nullptr
);
else if(cursor_type.kind == CXType_Record){
CXString type_spelling = clang_getTypeSpelling(cursor_type);
std::cout << ", namely " << clang_getCString(type_spelling);
clang_disposeString(type_spelling);
}
std::cout << "\n";
return CXChildVisit_Recurse;
},
nullptr
);
```
The expected output of program is:
.. code-block::
```
Type Kind: Record, namely A
Type Kind: Int
Type Kind: Record, namely B
Type Kind: Int
Type Kind: Record, namely A
Type Kind: Record, namely A
```
Type Kind: Record, namely A
Type Kind: Int
Type Kind: Record, namely B
Type Kind: Int
Type Kind: Record, namely A
Type Kind: Record, namely A
Reiterating the difference between `CXType` and `CXTypeKind`: For an example
```cpp
const char* __restrict__ variable;
```
Reiterating the difference between ``CXType`` and ``CXTypeKind``: For an example
- Type Kind will be: `CXType_Pointer` spelled `"Pointer"`
- Type will be a complex `CXType` structure, spelled `"const char* __restrict__`
.. code-block:: cpp
#### Retrieving source locations
const char* __restrict__ variable;
`CXSourceRange clang_getCursorExtent(CXCursor)` returns a `CXSourceRange`, representing a half-open range in the source code.
- Type Kind will be: ``CXType_Pointer`` spelled ``"Pointer"``
- Type will be a complex ``CXType`` structure, spelled ``"const char* __restrict__``
Use `clang_getRangeStart(CXSourceRange)` and `clang_getRangeEnd(CXSourceRange)` to retrieve the starting and end `CXSourceLocation` from a source range, respectively.
Retrieving source locations
"""""""""""""""""""""""""""
Given a `CXSourceLocation`, use `clang_getExpansionLocation` to retrieve file, line and column of a source location.
``CXSourceRange clang_getCursorExtent(CXCursor)`` returns a ``CXSourceRange``, representing a half-open range in the source code.
#### Code example
Use ``clang_getRangeStart(CXSourceRange)`` and ``clang_getRangeEnd(CXSourceRange)`` to retrieve the starting and end ``CXSourceLocation`` from a source range, respectively.
```cpp
// Again, file.cpp
struct foo{
int bar;
int* bar_pointer;
};
```
Given a ``CXSourceLocation``, use ``clang_getExpansionLocation`` to retrieve file, line and column of a source location.
```cpp
clang_visitChildren(
cursor,
[](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
Code example
""""""""""""
.. code-block:: cpp
CXType cursor_type = clang_getCursorType(current_cursor);
CXString cursor_spelling = clang_getCursorSpelling(current_cursor);
CXSourceRange cursor_range = clang_getCursorExtent(current_cursor);
std::cout << "Cursor " << clang_getCString(cursor_spelling);
// Again, file.cpp
struct foo{
int bar;
int* bar_pointer;
};
.. code-block:: cpp
CXFile file;
unsigned start_line, start_column, start_offset;
unsigned end_line, end_column, end_offset;
clang_visitChildren(
cursor,
[](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
clang_getExpansionLocation(clang_getRangeStart(cursor_range), &file, &start_line, &start_column, &start_offset);
clang_getExpansionLocation(clang_getRangeEnd (cursor_range), &file, &end_line , &end_column , &end_offset);
std::cout << " spanning lines " << start_line << " to " << end_line;
clang_disposeString(cursor_spelling);
CXType cursor_type = clang_getCursorType(current_cursor);
CXString cursor_spelling = clang_getCursorSpelling(current_cursor);
CXSourceRange cursor_range = clang_getCursorExtent(current_cursor);
std::cout << "Cursor " << clang_getCString(cursor_spelling);
CXFile file;
unsigned start_line, start_column, start_offset;
unsigned end_line, end_column, end_offset;
clang_getExpansionLocation(clang_getRangeStart(cursor_range), &file, &start_line, &start_column, &start_offset);
clang_getExpansionLocation(clang_getRangeEnd (cursor_range), &file, &end_line , &end_column , &end_offset);
std::cout << " spanning lines " << start_line << " to " << end_line;
clang_disposeString(cursor_spelling);
std::cout << "\n";
return CXChildVisit_Recurse;
},
nullptr
);
std::cout << "\n";
return CXChildVisit_Recurse;
},
nullptr
);
```
The expected output of this program is:
.. code-block::
```
Cursor foo spanning lines 2 to 5
Cursor bar spanning lines 3 to 3
Cursor bar_pointer spanning lines 4 to 4
```
Cursor foo spanning lines 2 to 5
Cursor bar spanning lines 3 to 3
Cursor bar_pointer spanning lines 4 to 4
### Complete example code
Complete example code
~~~~~~~~~~~~~~~~~~~~~
```cpp
// main.cpp
#include <clang-c/Index.h>
#include <iostream>
.. code-block:: cpp
int main(){
CXIndex index = clang_createIndex(0, 0); //Create index
CXTranslationUnit unit = clang_parseTranslationUnit(
index,
"file.cpp", nullptr, 0,
nullptr, 0,
CXTranslationUnit_None); //Parse "file.cpp"
// main.cpp
#include <clang-c/Index.h>
#include <iostream>
int main(){
CXIndex index = clang_createIndex(0, 0); //Create index
CXTranslationUnit unit = clang_parseTranslationUnit(
index,
"file.cpp", nullptr, 0,
nullptr, 0,
CXTranslationUnit_None); //Parse "file.cpp"
if (unit == nullptr){
std::cerr << "Unable to parse translation unit. Quitting.\n";
return 0;
}
CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit
clang_visitChildren(
cursor,
[](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
CXType cursor_type = clang_getCursorType(current_cursor);
CXString type_kind_spelling = clang_getTypeKindSpelling(cursor_type.kind);
std::cout << "TypeKind: " << clang_getCString(type_kind_spelling);
clang_disposeString(type_kind_spelling);
if(cursor_type.kind == CXType_Pointer || // If cursor_type is a pointer
cursor_type.kind == CXType_LValueReference || // or an LValue Reference (&)
cursor_type.kind == CXType_RValueReference){ // or an RValue Reference (&&),
CXType pointed_to_type = clang_getPointeeType(cursor_type);// retrieve the pointed-to type
CXString pointed_to_type_spelling = clang_getTypeSpelling(pointed_to_type); // Spell out the entire
std::cout << "pointing to type: " << clang_getCString(pointed_to_type_spelling);// pointed-to type
clang_disposeString(pointed_to_type_spelling);
}
else if(cursor_type.kind == CXType_Record){
CXString type_spelling = clang_getTypeSpelling(cursor_type);
std::cout << ", namely " << clang_getCString(type_spelling);
clang_disposeString(type_spelling);
}
std::cout << "\n";
return CXChildVisit_Recurse;
},
nullptr
);
clang_visitChildren(
cursor,
[](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
CXType cursor_type = clang_getCursorType(current_cursor);
CXString cursor_spelling = clang_getCursorSpelling(current_cursor);
CXSourceRange cursor_range = clang_getCursorExtent(current_cursor);
std::cout << "Cursor " << clang_getCString(cursor_spelling);
CXFile file;
unsigned start_line, start_column, start_offset;
unsigned end_line, end_column, end_offset;
clang_getExpansionLocation(clang_getRangeStart(cursor_range), &file, &start_line, &start_column, &start_offset);
clang_getExpansionLocation(clang_getRangeEnd (cursor_range), &file, &end_line , &end_column , &end_offset);
std::cout << " spanning lines " << start_line << " to " << end_line;
clang_disposeString(cursor_spelling);
std::cout << "\n";
return CXChildVisit_Recurse;
},
nullptr
);
if (unit == nullptr){
std::cerr << "Unable to parse translation unit. Quitting.\n";
return 0;
}
CXCursor cursor = clang_getTranslationUnitCursor(unit); //Obtain a cursor at the root of the translation unit
.. code-block:: cmake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(my_clang_tool VERSION 0.1.0)
clang_visitChildren(
cursor,
[](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
CXType cursor_type = clang_getCursorType(current_cursor);
# This will find the default system installation of Clang; if you want to
# use a different build of clang, pass -DClang_DIR=/foobar/lib/cmake/clang
# to the CMake configure command, where /foobar is the build directory where
# you built Clang.
find_package(Clang CONFIG REQUIRED)
CXString type_kind_spelling = clang_getTypeKindSpelling(cursor_type.kind);
std::cout << "TypeKind: " << clang_getCString(type_kind_spelling);
clang_disposeString(type_kind_spelling);
add_executable(my_clang_tool main.cpp)
target_include_directories(my_clang_tool PRIVATE ${CLANG_INCLUDE_DIRS})
target_link_libraries(my_clang_tool PRIVATE libclang)
if(cursor_type.kind == CXType_Pointer || // If cursor_type is a pointer
cursor_type.kind == CXType_LValueReference || // or an LValue Reference (&)
cursor_type.kind == CXType_RValueReference){ // or an RValue Reference (&&),
CXType pointed_to_type = clang_getPointeeType(cursor_type);// retrieve the pointed-to type
.. _Index.h: https://github.com/llvm/llvm-project/blob/main/clang/include/clang-c/Index.h
CXString pointed_to_type_spelling = clang_getTypeSpelling(pointed_to_type); // Spell out the entire
std::cout << "pointing to type: " << clang_getCString(pointed_to_type_spelling);// pointed-to type
clang_disposeString(pointed_to_type_spelling);
}
else if(cursor_type.kind == CXType_Record){
CXString type_spelling = clang_getTypeSpelling(cursor_type);
std::cout << ", namely " << clang_getCString(type_spelling);
clang_disposeString(type_spelling);
}
std::cout << "\n";
return CXChildVisit_Recurse;
},
nullptr
);
.. _Stability:
ABI and API Stability
---------------------
clang_visitChildren(
cursor,
[](CXCursor current_cursor, CXCursor parent, CXClientData client_data){
CXType cursor_type = clang_getCursorType(current_cursor);
CXString cursor_spelling = clang_getCursorSpelling(current_cursor);
CXSourceRange cursor_range = clang_getCursorExtent(current_cursor);
std::cout << "Cursor " << clang_getCString(cursor_spelling);
CXFile file;
unsigned start_line, start_column, start_offset;
unsigned end_line, end_column, end_offset;
clang_getExpansionLocation(clang_getRangeStart(cursor_range), &file, &start_line, &start_column, &start_offset);
clang_getExpansionLocation(clang_getRangeEnd (cursor_range), &file, &end_line , &end_column , &end_offset);
std::cout << " spanning lines " << start_line << " to " << end_line;
clang_disposeString(cursor_spelling);
std::cout << "\n";
return CXChildVisit_Recurse;
},
nullptr
);
}
```
```cmake
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(my_clang_tool VERSION 0.1.0)
# This will find the default system installation of Clang; if you want to
# use a different build of clang, pass -DClang_DIR=/foobar/lib/cmake/clang
# to the CMake configure command, where /foobar is the build directory where
# you built Clang.
find_package(Clang CONFIG REQUIRED)
add_executable(my_clang_tool main.cpp)
target_include_directories(my_clang_tool PRIVATE ${CLANG_INCLUDE_DIRS})
target_link_libraries(my_clang_tool PRIVATE libclang)
```
(stability)=
## ABI and API Stability
The C interfaces in libclang are intended to be relatively stable. This allows
a programmer to use libclang without having to worry as much about Clang
@ -408,38 +390,39 @@ fixed, features get implemented, etc.
The library should be ABI and API stable over time, but ABI- and API-breaking
changes can happen in the following (non-exhaustive) situations:
* Adding new enumerator to an enumeration (can be ABI-breaking in C++).
* Removing an explicitly deprecated API after a suitably long deprecation
- Adding new enumerator to an enumeration (can be ABI-breaking in C++).
- Removing an explicitly deprecated API after a suitably long deprecation
period.
* Using implementation details, such as names or comments that say something
- Using implementation details, such as names or comments that say something
is "private", "reserved", "internal", etc.
* Bug fixes and changes to Clang's internal implementation happen routinely and
- Bug fixes and changes to Clang's internal implementation happen routinely and
will change the behavior of callers.
* Rarely, bug fixes to libclang itself.
- Rarely, bug fixes to libclang itself.
The library has version macros (``CINDEX_VERSION_MAJOR``,
``CINDEX_VERSION_MINOR``, and ``CINDEX_VERSION``) which can be used to test for
specific library versions at compile time. The ``CINDEX_VERSION_MAJOR`` macro
The library has version macros (`CINDEX_VERSION_MAJOR`,
`CINDEX_VERSION_MINOR`, and `CINDEX_VERSION`) which can be used to test for
specific library versions at compile time. The `CINDEX_VERSION_MAJOR` macro
is only incremented if there are major source- or ABI-breaking changes. Except
for removing an explicitly deprecated API, the changes listed above are not
considered major source- or ABI-breaking changes. Historically, the value this
macro expands to has not changed, but may be incremented in the future should
the need arise. The ``CINDEX_VERSION_MINOR`` macro is incremented as new APIs
are added. The ``CINDEX_VERSION`` macro expands to a value based on the major
the need arise. The `CINDEX_VERSION_MINOR` macro is incremented as new APIs
are added. The `CINDEX_VERSION` macro expands to a value based on the major
and minor version macros.
In an effort to allow the library to be modified as new needs arise, the
following situations are explicitly unsupported:
* Loading different library versions into the same executable and passing
- Loading different library versions into the same executable and passing
objects between the libraries; despite general ABI stability, different
versions of the library may use different implementation details that are not
compatible across library versions.
* For the same reason as above, serializing objects from one version of the
- For the same reason as above, serializing objects from one version of the
library and deserializing with a different version is also not supported.
Note: because libclang is a wrapper around the compiler frontend, it is not a
`security-sensitive component`_ of the LLVM Project. Consider using a sandbox
[security-sensitive component] of the LLVM Project. Consider using a sandbox
or some other mitigation approach if processing untrusted input.
.. _security-sensitive component: https://llvm.org/docs/Security.html#what-is-considered-a-security-issue
[index.h]: https://github.com/llvm/llvm-project/blob/main/clang/include/clang-c/Index.h
[security-sensitive component]: https://llvm.org/docs/Security.html#what-is-considered-a-security-issue

View file

@ -1,78 +1,72 @@
=========
LibFormat
=========
# LibFormat
LibFormat is a library that implements automatic source code formatting based
on Clang. This document describes the LibFormat interface and design as well
as some basic style discussions.
If you just want to use `clang-format` as a tool or integrated into an editor,
checkout :doc:`ClangFormat`.
checkout {doc}`ClangFormat`.
Design
------
## Design
FIXME: Write up design.
## Interface
Interface
---------
The core routine of LibFormat is `reformat()`:
The core routine of LibFormat is ``reformat()``:
```c++
tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
SourceManager &SourceMgr,
std::vector<CharSourceRange> Ranges);
```
.. code-block:: c++
This reads a token stream out of the lexer `Lex` and reformats all the code
ranges in `Ranges`. The `FormatStyle` controls basic decisions made during
formatting. A list of options can be found under {ref}`style-options`.
tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
SourceManager &SourceMgr,
std::vector<CharSourceRange> Ranges);
The style options are described in {doc}`ClangFormatStyleOptions`.
This reads a token stream out of the lexer ``Lex`` and reformats all the code
ranges in ``Ranges``. The ``FormatStyle`` controls basic decisions made during
formatting. A list of options can be found under :ref:`style-options`.
(style-options)=
The style options are described in :doc:`ClangFormatStyleOptions`.
.. _style-options:
Style Options
-------------
## Style Options
The style options describe specific formatting options that can be used in
order to make `ClangFormat` comply with different style guides. Currently,
several style guides are hard-coded:
.. code-block:: c++
```c++
/// Returns a format style complying with the LLVM coding standards:
/// https://llvm.org/docs/CodingStandards.html.
FormatStyle getLLVMStyle();
/// Returns a format style complying with the LLVM coding standards:
/// https://llvm.org/docs/CodingStandards.html.
FormatStyle getLLVMStyle();
/// Returns a format style complying with Google's C++ style guide:
/// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml.
FormatStyle getGoogleStyle();
/// Returns a format style complying with Google's C++ style guide:
/// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml.
FormatStyle getGoogleStyle();
/// Returns a format style complying with Chromium's style guide:
/// https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/styleguide.md
FormatStyle getChromiumStyle();
/// Returns a format style complying with Chromium's style guide:
/// https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/styleguide.md
FormatStyle getChromiumStyle();
/// Returns a format style complying with the GNU coding standards:
/// https://www.gnu.org/prep/standards/standards.html
FormatStyle getGNUStyle();
/// Returns a format style complying with the GNU coding standards:
/// https://www.gnu.org/prep/standards/standards.html
FormatStyle getGNUStyle();
/// Returns a format style complying with Mozilla's style guide
/// https://firefox-source-docs.mozilla.org/code-quality/coding-style/index.html
FormatStyle getMozillaStyle();
/// Returns a format style complying with Mozilla's style guide
/// https://firefox-source-docs.mozilla.org/code-quality/coding-style/index.html
FormatStyle getMozillaStyle();
/// Returns a format style complying with Webkit's style guide:
/// https://webkit.org/code-style-guidelines/
FormatStyle getWebkitStyle();
/// Returns a format style complying with Webkit's style guide:
/// https://webkit.org/code-style-guidelines/
FormatStyle getWebkitStyle();
/// Returns a format style complying with Microsoft's style guide:
/// https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
FormatStyle getMicrosoftStyle();
```
/// Returns a format style complying with Microsoft's style guide:
/// https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
FormatStyle getMicrosoftStyle();
These options are also exposed in the :doc:`standalone tools <ClangFormat>`
These options are also exposed in the {doc}`standalone tools <ClangFormat>`
through the `-style` option.
In the future, we plan on making this configurable.

View file

@ -1,213 +1,200 @@
==========
LibTooling
==========
# LibTooling
LibTooling is a library to support writing standalone tools based on Clang.
This document will provide a basic walkthrough of how to write a tool using
LibTooling.
For the information on how to setup Clang Tooling for LLVM see
:doc:`HowToSetupToolingForLLVM`
{doc}`HowToSetupToolingForLLVM`
Introduction
------------
## Introduction
Tools built with LibTooling, like Clang Plugins, run ``FrontendActions`` over
Tools built with LibTooling, like Clang Plugins, run `FrontendActions` over
code.
.. See FIXME for a tutorial on how to write FrontendActions.
% See FIXME for a tutorial on how to write FrontendActions.
In this tutorial, we'll demonstrate the different ways of running Clang's
``SyntaxOnlyAction``, which runs a quick syntax check, over a bunch of code.
`SyntaxOnlyAction`, which runs a quick syntax check, over a bunch of code.
Parsing a code snippet in memory
--------------------------------
## Parsing a code snippet in memory
If you ever wanted to run a ``FrontendAction`` over some sample code, for
example to unit test parts of the Clang AST, ``runToolOnCode`` is what you
looked for. Let me give you an example:
If you ever wanted to run a `FrontendAction` over some sample code, for
example to unit test parts of the Clang AST, `runToolOnCode` is what you
looked for. Let me give you an example:
.. code-block:: c++
```c++
#include "clang/Tooling/Tooling.h"
#include "clang/Tooling/Tooling.h"
TEST(runToolOnCode, CanSyntaxCheckCode) {
// runToolOnCode returns whether the action was correctly run over the
// given code.
EXPECT_TRUE(runToolOnCode(std::make_unique<clang::SyntaxOnlyAction>(), "class X {};"));
}
```
TEST(runToolOnCode, CanSyntaxCheckCode) {
// runToolOnCode returns whether the action was correctly run over the
// given code.
EXPECT_TRUE(runToolOnCode(std::make_unique<clang::SyntaxOnlyAction>(), "class X {};"));
}
## Writing a standalone tool
Writing a standalone tool
-------------------------
Once you unit tested your ``FrontendAction`` to the point where it cannot
possibly break, it's time to create a standalone tool. For a standalone tool
Once you unit tested your `FrontendAction` to the point where it cannot
possibly break, it's time to create a standalone tool. For a standalone tool
to run clang, it first needs to figure out what command line arguments to use
for a specified file. To that end we create a ``CompilationDatabase``. There
for a specified file. To that end we create a `CompilationDatabase`. There
are different ways to create a compilation database, and we need to support all
of them depending on command-line options. There's the ``CommonOptionsParser``
of them depending on command-line options. There's the `CommonOptionsParser`
class that takes the responsibility to parse command-line parameters related to
compilation databases and inputs, so that all tools share the implementation.
Parsing common tools options
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
### Parsing common tools options
``CompilationDatabase`` can be read from a build directory or the command line.
Using ``CommonOptionsParser`` allows for explicit specification of a compile
command line, specification of build path using the ``-p`` command-line option,
`CompilationDatabase` can be read from a build directory or the command line.
Using `CommonOptionsParser` allows for explicit specification of a compile
command line, specification of build path using the `-p` command-line option,
and automatic location of the compilation database using source files paths.
.. code-block:: c++
```c++
#include "clang/Tooling/CommonOptionsParser.h"
#include "llvm/Support/CommandLine.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "llvm/Support/CommandLine.h"
using namespace clang::tooling;
using namespace llvm;
using namespace clang::tooling;
using namespace llvm;
// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static cl::OptionCategory MyToolCategory("my-tool options");
// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static cl::OptionCategory MyToolCategory("my-tool options");
int main(int argc, const char **argv) {
// CommonOptionsParser::create will parse arguments and create a
// CompilationDatabase.
auto ExpectedParser = CommonOptionsParser::create(argc, argv, MyToolCategory);
if (!ExpectedParser) {
// Fail gracefully for unsupported options.
llvm::errs() << toString(ExpectedParser.takeError());
return 1;
}
CommonOptionsParser& OptionsParser = ExpectedParser.get();
// Use OptionsParser.getCompilations() and OptionsParser.getSourcePathList()
// to retrieve CompilationDatabase and the list of input file paths.
int main(int argc, const char **argv) {
// CommonOptionsParser::create will parse arguments and create a
// CompilationDatabase.
auto ExpectedParser = CommonOptionsParser::create(argc, argv, MyToolCategory);
if (!ExpectedParser) {
// Fail gracefully for unsupported options.
llvm::errs() << toString(ExpectedParser.takeError());
return 1;
}
CommonOptionsParser& OptionsParser = ExpectedParser.get();
Creating and running a ClangTool
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Use OptionsParser.getCompilations() and OptionsParser.getSourcePathList()
// to retrieve CompilationDatabase and the list of input file paths.
}
```
Once we have a ``CompilationDatabase``, we can create a ``ClangTool`` and run
our ``FrontendAction`` over some code. For example, to run the
``SyntaxOnlyAction`` over the files "a.cc" and "b.cc" one would write:
### Creating and running a ClangTool
.. code-block:: c++
Once we have a `CompilationDatabase`, we can create a `ClangTool` and run
our `FrontendAction` over some code. For example, to run the
`SyntaxOnlyAction` over the files "a.cc" and "b.cc" one would write:
// A clang tool can run over a number of sources in the same process...
std::vector<std::string> Sources;
Sources.push_back("a.cc");
Sources.push_back("b.cc");
```c++
// A clang tool can run over a number of sources in the same process...
std::vector<std::string> Sources;
Sources.push_back("a.cc");
Sources.push_back("b.cc");
// We hand the CompilationDatabase we created and the sources to run over into
// the tool constructor.
ClangTool Tool(OptionsParser.getCompilations(), Sources);
// We hand the CompilationDatabase we created and the sources to run over into
// the tool constructor.
ClangTool Tool(OptionsParser.getCompilations(), Sources);
// The ClangTool needs a new FrontendAction for each translation unit we run
// on. Thus, it takes a FrontendActionFactory as parameter. To create a
// FrontendActionFactory from a given FrontendAction type, we call
// newFrontendActionFactory<clang::SyntaxOnlyAction>().
int result = Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>().get());
// The ClangTool needs a new FrontendAction for each translation unit we run
// on. Thus, it takes a FrontendActionFactory as parameter. To create a
// FrontendActionFactory from a given FrontendAction type, we call
// newFrontendActionFactory<clang::SyntaxOnlyAction>().
int result = Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>().get());
```
Putting it together --- the first tool
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
### Putting it together --- the first tool
Now we combine the two previous steps into our first real tool. A more advanced
Now we combine the two previous steps into our first real tool. A more advanced
version of this example tool is also checked into the clang tree at
``tools/clang-check/ClangCheck.cpp``.
`tools/clang-check/ClangCheck.cpp`.
.. code-block:: c++
```c++
// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"
// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"
using namespace clang::tooling;
using namespace llvm;
using namespace clang::tooling;
using namespace llvm;
// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static cl::OptionCategory MyToolCategory("my-tool options");
// Apply a custom category to all command-line options so that they are the
// only ones displayed.
static cl::OptionCategory MyToolCategory("my-tool options");
// CommonOptionsParser declares HelpMessage with a description of the common
// command-line options related to the compilation database and input files.
// It's nice to have this help message in all tools.
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
// CommonOptionsParser declares HelpMessage with a description of the common
// command-line options related to the compilation database and input files.
// It's nice to have this help message in all tools.
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nMore help text...\n");
// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nMore help text...\n");
int main(int argc, const char **argv) {
auto ExpectedParser = CommonOptionsParser::create(argc, argv, MyToolCategory);
if (!ExpectedParser) {
llvm::errs() << toString(ExpectedParser.takeError());
return 1;
}
CommonOptionsParser& OptionsParser = ExpectedParser.get();
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>().get());
int main(int argc, const char **argv) {
auto ExpectedParser = CommonOptionsParser::create(argc, argv, MyToolCategory);
if (!ExpectedParser) {
llvm::errs() << toString(ExpectedParser.takeError());
return 1;
}
CommonOptionsParser& OptionsParser = ExpectedParser.get();
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>().get());
}
```
Running the tool on some code
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
### Running the tool on some code
When you check out and build clang, clang-check is already built and available
to you in bin/clang-check inside your build directory.
You can run clang-check on a file in the llvm repository by specifying all the
needed parameters after a "``--``" separator:
needed parameters after a "`--`" separator:
.. code-block:: bash
$ cd /path/to/source/llvm
$ export BD=/path/to/build/llvm
$ $BD/bin/clang-check tools/clang/tools/clang-check/ClangCheck.cpp -- \
clang++ -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS \
-Itools/clang/include -I$BD/include -Iinclude \
-Itools/clang/lib/Headers -c
```bash
$ cd /path/to/source/llvm
$ export BD=/path/to/build/llvm
$ $BD/bin/clang-check tools/clang/tools/clang-check/ClangCheck.cpp -- \
clang++ -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS \
-Itools/clang/include -I$BD/include -Iinclude \
-Itools/clang/lib/Headers -c
```
As an alternative, you can also configure cmake to output a compile command
database into its build directory:
.. code-block:: bash
```bash
# Alternatively to calling cmake, use ccmake, toggle to advanced mode and
# set the parameter CMAKE_EXPORT_COMPILE_COMMANDS from the UI.
$ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .
```
# Alternatively to calling cmake, use ccmake, toggle to advanced mode and
# set the parameter CMAKE_EXPORT_COMPILE_COMMANDS from the UI.
$ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .
This creates a file called ``compile_commands.json`` in the build directory.
Now you can run :program:`clang-check` over files in the project by specifying
This creates a file called `compile_commands.json` in the build directory.
Now you can run {program}`clang-check` over files in the project by specifying
the build path as first argument and some source files as further positional
arguments:
.. code-block:: bash
```bash
$ cd /path/to/source/llvm
$ export BD=/path/to/build/llvm
$ $BD/bin/clang-check -p $BD tools/clang/tools/clang-check/ClangCheck.cpp
```
$ cd /path/to/source/llvm
$ export BD=/path/to/build/llvm
$ $BD/bin/clang-check -p $BD tools/clang/tools/clang-check/ClangCheck.cpp
(libtooling_builtin_includes)=
.. _libtooling_builtin_includes:
Builtin includes
^^^^^^^^^^^^^^^^
### Builtin includes
Clang tools need their builtin headers and search for them the same way Clang
does. Thus, the default location to look for builtin headers is in a path
``$(dirname /path/to/tool)/../lib/clang/3.3/include`` relative to the tool
binary. This works out-of-the-box for tools running from llvm's toplevel
does. Thus, the default location to look for builtin headers is in a path
`$(dirname /path/to/tool)/../lib/clang/3.3/include` relative to the tool
binary. This works out-of-the-box for tools running from llvm's toplevel
binary directory after building clang-resource-headers, or if the tool is
running from the binary directory of a clang install next to the clang binary.
Tips: if your tool fails to find ``stddef.h`` or similar headers, call the tool
with ``-v`` and look at the search paths it looks through.
Tips: if your tool fails to find `stddef.h` or similar headers, call the tool
with `-v` and look at the search paths it looks through.
Linking
^^^^^^^
### Linking
For a list of libraries to link, look at one of the tools' CMake files (for
example `clang-check/CMakeList.txt
<https://github.com/llvm/llvm-project/blob/main/clang/tools/clang-check/CMakeLists.txt>`_).
example [clang-check/CMakeList.txt](https://github.com/llvm/llvm-project/blob/main/clang/tools/clang-check/CMakeLists.txt)).

View file

@ -1,34 +1,33 @@
==============
RISC-V Support
==============
# RISC-V Support
.. contents::
:local:
```{contents}
:local: true
```
Intrinsic Detection Macros
===========================
## Intrinsic Detection Macros
Clang provides macros to detect which RISC-V intrinsics are supported by the
toolchain. This is only available if intrinsics are ratified, in other word,
experimental intrinsics do not have macro defined.
Note: This is independent from assembler support.
Intrinsic Detection
---------------------------
### Intrinsic Detection
Macros of the form ``__riscv_intrinsic_<extension>`` indicate that the toolchain
Macros of the form `__riscv_intrinsic_<extension>` indicate that the toolchain
supports intrinsics for a given extension:
.. code-block:: c
#if defined(__riscv_intrinsic_zbb)
// Toolchain supports Zbb scalar intrinsics like __riscv_orc_b_*
// These can be used with target attributes even if -march doesn't include Zbb
__attribute__((target("arch=+zbb")))
unsigned long process_with_zbb(unsigned long x) {
return __riscv_orc_b_64(x);
}
#endif
```c
#if defined(__riscv_intrinsic_zbb)
// Toolchain supports Zbb scalar intrinsics like __riscv_orc_b_*
// These can be used with target attributes even if -march doesn't include Zbb
__attribute__((target("arch=+zbb")))
unsigned long process_with_zbb(unsigned long x) {
return __riscv_orc_b_64(x);
}
#endif
```
Composite extensions are also defined when all their sub-extensions are available, e.g.
``__riscv_intrinsic_zkn`` - zbkb + zbkc + zbkx + zkne + zknd + zknh
: `__riscv_intrinsic_zkn` - zbkb + zbkc + zbkx + zkne + zknd + zknh

View file

@ -1,97 +1,92 @@
=================================================
Choosing the Right Interface for Your Application
=================================================
# Choosing the Right Interface for Your Application
Clang provides infrastructure to write tools that need syntactic and semantic
information about a program. This document will give a short introduction of
information about a program. This document will give a short introduction of
the different ways to write clang tools, and their pros and cons.
LibClang
--------
## LibClang
`LibClang <https://clang.llvm.org/doxygen/group__CINDEX.html>`_ is a stable high
level C interface to clang. When in doubt LibClang is probably the interface
you want to use. Consider the other interfaces only when you have a good
[LibClang](https://clang.llvm.org/doxygen/group__CINDEX.html) is a stable high
level C interface to clang. When in doubt LibClang is probably the interface
you want to use. Consider the other interfaces only when you have a good
reason not to use LibClang.
Canonical examples of when to use LibClang:
* Xcode
* Clang Python Bindings
- Xcode
- Clang Python Bindings
Use LibClang when you...:
* want to interface with clang from other languages than C++
* need a stable interface that takes care to be backwards compatible
* want powerful high-level abstractions, like iterating through an AST with a
- want to interface with clang from other languages than C++
- need a stable interface that takes care to be backwards compatible
- want powerful high-level abstractions, like iterating through an AST with a
cursor, and don't want to learn all the nitty gritty details of Clang's AST.
Do not use LibClang when you...:
* want full control over the Clang AST
- want full control over the Clang AST
Clang Plugins
-------------
## Clang Plugins
:doc:`Clang Plugins <ClangPlugins>` allow you to run additional actions on the
AST as part of a compilation. Plugins are dynamic libraries that are loaded at
{doc}`Clang Plugins <ClangPlugins>` allow you to run additional actions on the
AST as part of a compilation. Plugins are dynamic libraries that are loaded at
runtime by the compiler, and they're easy to integrate into your build
environment.
Canonical examples of when to use Clang Plugins:
* special lint-style warnings or errors for your project
* creating additional build artifacts from a single compile step
- special lint-style warnings or errors for your project
- creating additional build artifacts from a single compile step
Use Clang Plugins when you...:
* need your tool to rerun if any of the dependencies change
* want your tool to make or break a build
* need full control over the Clang AST
- need your tool to rerun if any of the dependencies change
- want your tool to make or break a build
- need full control over the Clang AST
Do not use Clang Plugins when you...:
* want to run tools outside of your build environment
* want full control on how Clang is set up, including mapping of in-memory
- want to run tools outside of your build environment
- want full control on how Clang is set up, including mapping of in-memory
virtual files
* need to run over a specific subset of files in your project which is not
- need to run over a specific subset of files in your project which is not
necessarily related to any changes which would trigger rebuilds
LibTooling
----------
## LibTooling
:doc:`LibTooling <LibTooling>` is a C++ interface aimed at writing standalone
tools, as well as integrating into services that run clang tools. Canonical
{doc}`LibTooling <LibTooling>` is a C++ interface aimed at writing standalone
tools, as well as integrating into services that run clang tools. Canonical
examples of when to use LibTooling:
* a simple syntax checker
* refactoring tools
- a simple syntax checker
- refactoring tools
Use LibTooling when you...:
* want to run tools over a single file, or a specific subset of files,
- want to run tools over a single file, or a specific subset of files,
independently of the build system
* want full control over the Clang AST
* want to share code with Clang Plugins
- want full control over the Clang AST
- want to share code with Clang Plugins
Do not use LibTooling when you...:
* want to run as part of the build triggered by dependency changes
* want a stable interface so you don't need to change your code when the AST API
- want to run as part of the build triggered by dependency changes
- want a stable interface so you don't need to change your code when the AST API
changes
* want high level abstractions like cursors and code completion out of the box
* do not want to write your tools in C++
- want high level abstractions like cursors and code completion out of the box
- do not want to write your tools in C++
:doc:`Clang tools <ClangTools>` are a collection of specific developer tools
{doc}`Clang tools <ClangTools>` are a collection of specific developer tools
built on top of the LibTooling infrastructure as part of the Clang project.
They are targeted at automating and improving core development activities of
C/C++ developers.
Examples of tools we are building or planning as part of the Clang project:
* Syntax checking (:program:`clang-check`)
* Automatic fixing of compile errors (:program:`clang-fixit`)
* Automatic code formatting (:program:`clang-format`)
* Migration tools for new features in new language standards
* Core refactoring tools
- Syntax checking ({program}`clang-check`)
- Automatic fixing of compile errors ({program}`clang-fixit`)
- Automatic code formatting ({program}`clang-format`)
- Migration tools for new features in new language standards
- Core refactoring tools