Files
llvm-project/clang-tools-extra/docs/clang-reorder-fields.rst
Konrad Kleine dea1d29d73 [clang-tools-extra][docs] Add documentation for clang-reorder-fields (#178446)
Add comprehensive documentation for the clang-reorder-fields tool,
addressing #35520. The tool has existed in the repository but was
previously undocumented.

The documentation includes:
- Basic usage examples for C and C++ structs/classes
- Constructor initializer list reordering
- Designated initializer support (C++20)
- Detailed limitations and caveats
- Command line option reference
- Common use cases (memory layout optimization, etc.)

Fixes #35520

---------

Co-authored-by: EugeneZelenko <eugene.zelenko@gmail.com>
2026-01-29 15:28:58 +01:00

424 lines
9.3 KiB
ReStructuredText

====================
Clang-Reorder-Fields
====================
.. contents::
.. toctree::
:maxdepth: 1
:program:`clang-reorder-fields` is a refactoring tool to reorder fields in
C/C++ structs and classes. This tool automatically updates:
- Field declarations in the record definition
- Constructor initializer lists in C++ classes
- Aggregate initialization expressions (both C and C++)
- Designated initializer lists (C++20)
This can be useful for optimizing memory layout, improving cache performance,
or conforming to coding standards that require specific field orderings.
Example usage
-------------
Basic struct reordering
~~~~~~~~~~~~~~~~~~~~~~~
Consider this simple struct in `example.c`:
.. code-block:: c
struct Foo {
const int *x;
int y;
double z;
int w;
};
int main() {
const int val = 42;
struct Foo foo = { &val, 0, 1.5, 17 };
return 0;
}
To reorder the fields to `z, w, y, x`, run:
.. code-block:: console
clang-reorder-fields -record-name Foo -fields-order z,w,y,x example.c --
This will reorder both the struct definition and the initialization:
.. code-block:: c
struct Foo {
double z;
int w;
int y;
const int *x;
};
int main() {
const int val = 42;
struct Foo foo = { 1.5, 17, 0, &val };
return 0;
}
Namespaced structs
~~~~~~~~~~~~~~~~~~
For C++ code with namespaces, use the fully-qualified name:
.. code-block:: c++
namespace bar {
struct Foo {
const int *x;
int y;
double z;
int w;
};
}
.. code-block:: console
clang-reorder-fields -record-name ::bar::Foo -fields-order z,w,y,x example.cpp --
For classes defined in the global namespace (without any namespace), you can
use either the simple class name or prefix it with `::`:
.. code-block:: console
clang-reorder-fields -record-name Foo -fields-order z,w,y,x example.cpp --
# or
clang-reorder-fields -record-name ::Foo -fields-order z,w,y,x example.cpp --
C++ constructor initializer lists
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The tool also reorders constructor initializer lists. Given:
.. code-block:: c++
class Foo {
public:
Foo();
private:
int x;
const char *s1;
const char *s2;
double z;
};
Foo::Foo():
x(12),
s1("abc"),
s2("def"),
z(3.14)
{}
Running:
.. code-block:: console
clang-reorder-fields -record-name Foo -fields-order s1,x,z,s2 example.cpp --
Will reorder both the field declarations and the constructor initializers:
.. code-block:: c++
class Foo {
public:
Foo();
private:
const char *s1;
int x;
double z;
const char *s2;
};
Foo::Foo():
s1("abc"),
x(12),
z(3.14),
s2("def")
{}
Designated initializers
~~~~~~~~~~~~~~~~~~~~~~~
For C++20 code using designated initializers:
.. code-block:: c++
struct Bar {
char a;
int b;
int c;
};
int main() {
Bar bar1 = { 'a', 0, 123 };
Bar bar2 = { .a = 'a', .b = 0, .c = 123 };
return 0;
}
.. code-block:: console
clang-reorder-fields --extra-arg="-std=c++20" -record-name Bar \
-fields-order c,a,b example.cpp --
Will produce:
.. code-block:: c++
struct Bar {
int c;
char a;
int b;
};
int main() {
Bar bar1 = { 123, 'a', 0 };
Bar bar2 = { .c = 123, .a = 'a', .b = 0 };
return 0;
}
In-place editing
~~~~~~~~~~~~~~~~
Use the `-i` flag to modify files in-place:
.. code-block:: console
clang-reorder-fields -record-name Foo -fields-order z,w,y,x -i example.c --
Limitations and Caveats
-----------------------
Different access specifiers
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The tool cannot reorder fields with different access specifiers
(``public/private/protected``). All fields being reordered must have the same
access level.
.. code-block:: c++
class Example {
private:
int x;
public:
int y; // Cannot reorder x and y - different access levels
};
Multiple field declarations
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Declarations with multiple fields in one statement are not supported:
.. code-block:: c
struct Example {
int a, b; // Not supported - multiple fields in one declaration
};
Macro-expanded fields
~~~~~~~~~~~~~~~~~~~~~
Macros that expand to multiple field declarations are not supported. However,
macros that expand to a single field declaration work correctly:
.. code-block:: c
#define INT_FIELD(NAME) int NAME // Supported - expands to one field
#define TWO_FIELDS int a; int b; // Not supported - expands to two fields
struct Supported {
INT_FIELD(x); // OK - this is a single field
int y;
INT_FIELD(z); // OK - this is a single field
};
struct NotSupported {
TWO_FIELDS // Not OK - expands to multiple fields
int c;
};
The tool can reorder fields declared via macros as long as each macro invocation
expands to exactly one field declaration.
Preprocessor directives
~~~~~~~~~~~~~~~~~~~~~~~
Structs with preprocessor directives between fields cannot be reordered:
.. code-block:: c
struct Example {
int a;
#ifdef FEATURE
int b;
#endif
int c; // Not supported - preprocessor directives present
};
Flexible array members
~~~~~~~~~~~~~~~~~~~~~~
In C, a flexible array member is an incomplete array type that must be the last
member of a struct (as specified by C99 and later standards). This allows the
struct to have a variable-length array at the end. Since this is a language
requirement, the tool enforces that flexible array members remain in the last
position:
.. code-block:: c
struct Example {
int count;
int data[]; // Flexible array member - must remain last
};
Attempting to reorder fields such that the flexible array member is no longer
last will result in an error:
.. code-block:: console
clang-reorder-fields -record-name Example -fields-order data,count example.c --
Will produce:
.. code-block:: text
Flexible array member must remain the last field in the struct
This ensures the generated code remains valid C.
Field dependencies in initializers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The tool will issue a warning if reordering causes a field to be used in an
initializer before it's initialized. Consider this example:
.. code-block:: c++
class Foo {
public:
Foo(int x, char c);
int x;
char c;
Dummy z;
};
Foo::Foo(int x, char c) :
x(x),
c(c),
z(this->x, c) // z's initializer uses x and c
{}
If you reorder the fields to `z, c, x`:
.. code-block:: console
clang-reorder-fields -record-name Foo -fields-order z,c,x example.cpp --
The tool will produce warnings:
.. code-block:: text
example.cpp:10:3: warning: reordering field x after z makes x uninitialized when used in init expression
example.cpp:10:3: warning: reordering field c after z makes c uninitialized when used in init expression
This warns you that in C++, member initializers are executed in the order that
fields are declared in the class, not the order they appear in the initializer
list. After reordering, `z` would be initialized first, but its initializer
tries to use `x` and `c` which haven't been initialized yet.
The tool will still perform the reordering but warns about the potential issue.
You should review these warnings and adjust your code accordingly.
:program:`clang-reorder-fields` Command Line Options
----------------------------------------------------
.. option:: --record-name=<string>
The fully-qualified name of the struct or class to reorder. Required.
For C structs, use the struct name directly (e.g., `Foo`).
For C++ classes/structs in namespaces, use the fully-qualified name including
namespaces (e.g., `::namespace::ClassName`).
For C++ classes/structs in the global namespace, you can use either the simple
name (e.g., `Foo`) or prefix with `::` (e.g., `::Foo`).
.. option:: --fields-order=<string>
Comma-separated list of field names in the desired order. Required.
All field names must exactly match the fields in the struct/class definition.
The number of fields must match the number in the definition.
.. option:: -i
Overwrite edited files in-place. If not specified, the rewritten code is
printed to stdout.
.. option:: --extra-arg=<string>
Additional argument to append to the compiler command line.
Useful for specifying language standards (e.g., `--extra-arg="-std=c++20"`).
.. option:: --extra-arg-before=<string>
Additional argument to prepend to the compiler command line.
.. option:: -p <string>
Build path. Specifies the directory containing `compile_commands.json` for
compilation database support.
Use Cases
---------
Memory layout optimization
~~~~~~~~~~~~~~~~~~~~~~~~~~
Reorder fields to minimize padding and improve cache locality:
.. code-block:: c
// Before: 24 bytes (with padding)
struct Data {
char a; // 1 byte + 7 padding
double b; // 8 bytes
char c; // 1 byte + 7 padding
};
.. code-block:: console
clang-reorder-fields -record-name Data -fields-order b,a,c data.c --
.. code-block:: c
// After: 16 bytes (less padding)
struct Data {
double b; // 8 bytes
char a; // 1 byte
char c; // 1 byte + 6 padding
};
Coding standard compliance
~~~~~~~~~~~~~~~~~~~~~~~~~~
Ensure fields are ordered according to project conventions (e.g., alphabetically,
by type, or by access pattern).
Field grouping
~~~~~~~~~~~~~~
Group related fields together for better code organization and readability.