The cluttered structure of C11 types resulting from the second step of the question can be simplified by removal/reduction of less important nodes and delegating some redundant/subsidiary information to be presented by other means.
I propose the following five-step algorithm for that:
- Removal of all extended integer types (strictly conforming implementation assumed);
- Reduction of the standard integer types (as they do not partition types any more);
- Grouping the structure:
- A scalar types vs aggregate types pair of sub-trees (represented as a tree),
- A basic types vs derived types pair of sub-trees (represented by coloured regions),
- real types and derived declarator types (represented as stroked sub-regions of these),
- character types (represented with different text colour);
- Application of an off-standard production: object types = scalar types + aggregate types;
- Supplementing the object types of missing union types and atomic types.
The resulting C11 type system summary looks as follows:
The grey stroke/areas are introduced to increase readability of the tree.
The type summary does not include the concept of “type declaration completeness” because it is a state, observed at a particular point within a translation unit. At run-time, all objects and functions are instances of a complete type. The void
type is an exception but, as a no-type (or any-type in case of a pointer), it is intentionally excluded from the diagram.
The const
, volatile
, restrict
and _Atomic
are type qualifiers which, contrary to type specifiers for the derived types, cannot be applied recursively. Any combination of these may prepend any type definition (as long as it makes sense). Thus, including them in the diagram would complicate it, while not introducing any suitable information. The apparent exception makes the _Atomic (type)
construct, which is taken into account as being a type specifier for the atomic type – one of the derived types listed in the C11 standard.