
/*- Compilations -*/

/**
 * An invocation of the compiler. Note that more than one file may be
 * compiled per invocation. For example, this command compiles three
 * source files:
 *
 *   gcc -c f1.c f2.c f3.c
 *
 * The `id` simply identifies the invocation, while `cwd` is the working
 * directory from which the compiler was invoked.
 */
compilations(
    /**
     * An invocation of the compiler. Note that more than one file may
     * be compiled per invocation. For example, this command compiles
     * three source files:
     *
     *   gcc -c f1.c f2.c f3.c
     */
    unique int id : @compilation,
    string cwd : string ref
);

/**
 * The arguments that were passed to the extractor for a compiler
 * invocation. If `id` is for the compiler invocation
 *
 *   gcc -c f1.c f2.c f3.c
 *
 * then typically there will be rows for
 *
 * num | arg
 * --- | ---
 * 0   | *path to extractor*
 * 1   | `--mimic`
 * 2   | `/usr/bin/gcc`
 * 3   | `-c`
 * 4   | f1.c
 * 5   | f2.c
 * 6   | f3.c
 */
#keyset[id, num]
compilation_args(
    int id : @compilation ref,
    int num : int ref,
    string arg : string ref
);

/**
 * The expanded arguments that were passed to the extractor for a
 * compiler invocation. This is similar to `compilation_args`, but
 * for a `@someFile` argument, it includes the arguments from that
 * file, rather than just taking the argument literally.
 */
#keyset[id, num]
compilation_expanded_args(
    int id : @compilation ref,
    int num : int ref,
    string arg : string ref
);

/**
 * Optionally, record the build mode for each compilation.
 */
compilation_build_mode(
    unique int id : @compilation ref,
    int mode : int ref
);

/*
case @compilation_build_mode.mode of
  0 = @build_mode_none
| 1 = @build_mode_manual
| 2 = @build_mode_auto
;
*/

/**
 * The source files that are compiled by a compiler invocation.
 * If `id` is for the compiler invocation
 *
 *   gcc -c f1.c f2.c f3.c
 *
 * then there will be rows for
 *
 * num | arg
 * --- | ---
 * 0   | f1.c
 * 1   | f2.c
 * 2   | f3.c
 *
 * Note that even if those files `#include` headers, those headers
 * do not appear as rows.
 */
#keyset[id, num]
compilation_compiling_files(
    int id : @compilation ref,
    int num : int ref,
    int file : @file ref
);

/**
 * The time taken by the extractor for a compiler invocation.
 *
 * For each file `num`, there will be rows for
 *
 * kind | seconds
 * ---- | ---
 * 1    | CPU seconds used by the extractor frontend
 * 2    | Elapsed seconds during the extractor frontend
 * 3    | CPU seconds used by the extractor backend
 * 4    | Elapsed seconds during the extractor backend
 */
#keyset[id, num, kind]
compilation_time(
    int id : @compilation ref,
    int num : int ref,
    /* kind:
       1 = frontend_cpu_seconds
       2 = frontend_elapsed_seconds
       3 = extractor_cpu_seconds
       4 = extractor_elapsed_seconds
    */
    int kind : int ref,
    float seconds : float ref
);

/**
 * An error or warning generated by the extractor.
 * The diagnostic message `diagnostic` was generated during compiler
 * invocation `compilation`, and is the `file_number_diagnostic_number`th
 * message generated while extracting the `file_number`th file of that
 * invocation.
 */
#keyset[compilation, file_number, file_number_diagnostic_number]
diagnostic_for(
    int diagnostic : @diagnostic ref,
    int compilation : @compilation ref,
    int file_number : int ref,
    int file_number_diagnostic_number : int ref
);

/**
 * If extraction was successful, then `cpu_seconds` and
 * `elapsed_seconds` are the CPU time and elapsed time (respectively)
 * that extraction took for compiler invocation `id`.
 */
compilation_finished(
    unique int id : @compilation ref,
    float cpu_seconds : float ref,
    float elapsed_seconds : float ref
);

/*- External data -*/

/**
 * External data, loaded from CSV files during snapshot creation. See
 * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data)
 * for more information.
 */
externalData(
  int id : @externalDataElement,
  string path : string ref,
  int column: int ref,
  string value : string ref
);

/*- Source location prefix -*/

/**
 * The source location of the snapshot.
 */
sourceLocationPrefix(string prefix : string ref);

/*- Files and folders -*/

/**
 * The location of an element.
 * The location spans column `startcolumn` of line `startline` to
 * column `endcolumn` of line `endline` in file `file`.
 * For more information, see
 * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
 */
locations_default(
  unique int id: @location_default,
  int file: @file ref,
  int beginLine: int ref,
  int beginColumn: int ref,
  int endLine: int ref,
  int endColumn: int ref
);

files(
  unique int id: @file,
  string name: string ref
);

folders(
  unique int id: @folder,
  string name: string ref
);

@container = @file | @folder

containerparent(
  int parent: @container ref,
  unique int child: @container ref
);

/*- Lines of code -*/

numlines(
  int element_id: @sourceline ref,
  int num_lines: int ref,
  int num_code: int ref,
  int num_comment: int ref
);

/*- Diagnostic messages -*/

diagnostics(
  unique int id: @diagnostic,
  int severity: int ref,
  string error_tag: string ref,
  string error_message: string ref,
  string full_error_message: string ref,
  int location: @location_default ref
);

/*- C++ dbscheme -*/

extractor_version(
    string codeql_version: string ref,
    string frontend_version: string ref
)

pch_uses(
    int pch: @pch ref,
    int compilation: @compilation ref,
    int id: @file ref
)

#keyset[pch, compilation]
pch_creations(
    int pch: @pch,
    int compilation: @compilation ref,
    int from: @file ref
)

/** An element for which line-count information is available. */
@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable;

fileannotations(
    int id: @file ref,
    int kind: int ref,
    string name: string ref,
    string value: string ref
);

inmacroexpansion(
    int id: @element ref,
    int inv: @macroinvocation ref
);

affectedbymacroexpansion(
    int id: @element ref,
    int inv: @macroinvocation ref
);

case @macroinvocation.kind of
  1 = @macro_expansion
| 2 = @other_macro_reference
;

macroinvocations(
    unique int id: @macroinvocation,
    int macro_id: @ppd_define ref,
    int location: @location_default ref,
    int kind: int ref
);

macroparent(
    unique int id: @macroinvocation ref,
    int parent_id: @macroinvocation ref
);

// a macroinvocation may be part of another location
// the way to find a constant expression that uses a macro
// is thus to find a constant expression that has a location
// to which a macro invocation is bound
macrolocationbind(
    int id: @macroinvocation ref,
    int location: @location_default ref
);

#keyset[invocation, argument_index]
macro_argument_unexpanded(
    int invocation: @macroinvocation ref,
    int argument_index: int ref,
    string text: string ref
);

#keyset[invocation, argument_index]
macro_argument_expanded(
    int invocation: @macroinvocation ref,
    int argument_index: int ref,
    string text: string ref
);

case @function.kind of
  0 = @unknown_function
| 1 = @normal_function
| 2 = @constructor
| 3 = @destructor
| 4 = @conversion_function
| 5 = @operator
// ... 6 = @builtin_function deprecated    // GCC built-in functions, e.g. __builtin___memcpy_chk
| 7 = @user_defined_literal
| 8 = @deduction_guide
;

functions(
    unique int id: @function,
    string name: string ref,
    int kind: int ref
);

builtin_functions(
    int id: @function ref
)

function_entry_point(
    int id: @function ref,
    unique int entry_point: @stmt ref
);

function_return_type(
    int id: @function ref,
    int return_type: @type ref
);

/**
 * If `function` is a coroutine, then this gives the `std::experimental::resumable_traits`
 * instance associated with it, and the variables representing the `handle` and `promise`
 * for it.
 */
coroutine(
  unique int function: @function ref,
  int traits: @type ref
);

/*
case @coroutine_placeholder_variable.kind of
  1 = @handle
| 2 = @promise
| 3 = @init_await_resume
;
*/

coroutine_placeholder_variable(
  unique int placeholder_variable: @variable ref,
  int kind: int ref,
  int function: @function ref
)

/** The `new` function used for allocating the coroutine state, if any. */
coroutine_new(
  unique int function: @function ref,
  int new: @function ref
);

/** The `delete` function used for deallocating the coroutine state, if any. */
coroutine_delete(
  unique int function: @function ref,
  int delete: @function ref
);

purefunctions(unique int id: @function ref);

function_deleted(unique int id: @function ref);

function_defaulted(unique int id: @function ref);

function_prototyped(unique int id: @function ref)

deduction_guide_for_class(
    int id: @function ref,
    int class_template: @usertype ref
)

member_function_this_type(
    unique int id: @function ref,
    int this_type: @type ref
);

#keyset[id, type_id]
fun_decls(
    int id: @fun_decl,
    int function: @function ref,
    int type_id: @type ref,
    string name: string ref,
    int location: @location_default ref
);
fun_def(unique int id: @fun_decl ref);
fun_specialized(unique int id: @fun_decl ref);
fun_implicit(unique int id: @fun_decl ref);
fun_decl_specifiers(
    int id: @fun_decl ref,
    string name: string ref
)
#keyset[fun_decl, index]
fun_decl_throws(
    int fun_decl: @fun_decl ref,
    int index: int ref,
    int type_id: @type ref
);
/* an empty throw specification is different from none */
fun_decl_empty_throws(unique int fun_decl: @fun_decl ref);
fun_decl_noexcept(
    int fun_decl: @fun_decl ref,
    int constant: @expr ref
);
fun_decl_empty_noexcept(int fun_decl: @fun_decl ref);
fun_decl_typedef_type(
    unique int fun_decl: @fun_decl ref,
    int typedeftype_id: @usertype ref
);

/*
case @fun_requires.kind of
  1 = @template_attached
| 2 = @function_attached
;
*/

fun_requires(
    int id: @fun_decl ref,
    int kind: int ref,
    int constraint: @expr ref
);

param_decl_bind(
    unique int id: @var_decl ref,
    int index: int ref,
    int fun_decl: @fun_decl ref
);

#keyset[id, type_id]
var_decls(
    int id: @var_decl,
    int variable: @variable ref,
    int type_id: @type ref,
    string name: string ref,
    int location: @location_default ref
);
var_def(unique int id: @var_decl ref);
var_specialized(int id: @var_decl ref);
var_decl_specifiers(
    int id: @var_decl ref,
    string name: string ref
)
is_structured_binding(unique int id: @variable ref);
var_requires(
    int id: @var_decl ref,
    int constraint: @expr ref
);

type_decls(
    unique int id: @type_decl,
    int type_id: @type ref,
    int location: @location_default ref
);
type_def(unique int id: @type_decl ref);
type_decl_top(
    unique int type_decl: @type_decl ref
);
type_requires(
    int id: @type_decl ref,
    int constraint: @expr ref
);

namespace_decls(
    unique int id: @namespace_decl,
    int namespace_id: @namespace ref,
    int location: @location_default ref,
    int bodylocation: @location_default ref
);

case @using.kind of
  1 = @using_declaration
| 2 = @using_directive
| 3 = @using_enum_declaration
;

usings(
    unique int id: @using,
    int element_id: @element ref,
    int location: @location_default ref,
    int kind: int ref
);

/** The element which contains the `using` declaration. */
using_container(
    int parent: @element ref,
    int child: @using ref
);

static_asserts(
    unique int id: @static_assert,
    int condition : @expr ref,
    string message : string ref,
    int location: @location_default ref,
    int enclosing : @element ref
);

// each function has an ordered list of parameters
#keyset[id, type_id]
#keyset[function, index, type_id]
params(
    int id: @parameter,
    int function: @parameterized_element ref,
    int index: int ref,
    int type_id: @type ref
);

overrides(
    int new: @function ref,
    int old: @function ref
);

#keyset[id, type_id]
membervariables(
    int id: @membervariable,
    int type_id: @type ref,
    string name: string ref
);

#keyset[id, type_id]
globalvariables(
    int id: @globalvariable,
    int type_id: @type ref,
    string name: string ref
);

#keyset[id, type_id]
localvariables(
    int id: @localvariable,
    int type_id: @type ref,
    string name: string ref
);

autoderivation(
    unique int var: @variable ref,
    int derivation_type: @type ref
);

orphaned_variables(
    int var: @localvariable ref,
    int function: @function ref
)

enumconstants(
    unique int id: @enumconstant,
    int parent: @usertype ref,
    int index: int ref,
    int type_id: @type ref,
    string name: string ref,
    int location: @location_default ref
);

@variable = @localscopevariable | @globalvariable | @membervariable;

@localscopevariable = @localvariable | @parameter;

/**
 * Built-in types are the fundamental types, e.g., integral, floating, and void.
 */
case @builtintype.kind of
   1 = @errortype
|  2 = @unknowntype
|  3 = @void
|  4 = @boolean
|  5 = @char
|  6 = @unsigned_char
|  7 = @signed_char
|  8 = @short
|  9 = @unsigned_short
| 10 = @signed_short
| 11 = @int
| 12 = @unsigned_int
| 13 = @signed_int
| 14 = @long
| 15 = @unsigned_long
| 16 = @signed_long
| 17 = @long_long
| 18 = @unsigned_long_long
| 19 = @signed_long_long
// ... 20 Microsoft-specific __int8
// ... 21 Microsoft-specific __int16
// ... 22 Microsoft-specific __int32
// ... 23 Microsoft-specific __int64
| 24 = @float
| 25 = @double
| 26 = @long_double
| 27 = @complex_float         // C99-specific _Complex float
| 28 = @complex_double        // C99-specific _Complex double
| 29 = @complex_long_double   // C99-specific _Complex long double
| 30 = @imaginary_float       // C99-specific _Imaginary float
| 31 = @imaginary_double      // C99-specific _Imaginary double
| 32 = @imaginary_long_double // C99-specific _Imaginary long double
| 33 = @wchar_t               // Microsoft-specific
| 34 = @decltype_nullptr      // C++11
| 35 = @int128                // __int128
| 36 = @unsigned_int128       // unsigned __int128
| 37 = @signed_int128         // signed __int128
| 38 = @float128              // __float128
| 39 = @complex_float128      // _Complex __float128
// ... 40 _Decimal32
// ... 41 _Decimal64
// ... 42 _Decimal128
| 43 = @char16_t
| 44 = @char32_t
| 45 = @std_float32           // _Float32
| 46 = @float32x              // _Float32x
| 47 = @std_float64           // _Float64
| 48 = @float64x              // _Float64x
| 49 = @std_float128          // _Float128
// ... 50 _Float128x
| 51 = @char8_t
| 52 = @float16               // _Float16
| 53 = @complex_float16       // _Complex _Float16
| 54 = @fp16                  // __fp16
| 55 = @std_bfloat16          // __bf16
| 56 = @std_float16           // std::float16_t
| 57 = @complex_std_float32   // _Complex _Float32
| 58 = @complex_float32x      // _Complex _Float32x
| 59 = @complex_std_float64   // _Complex _Float64
| 60 = @complex_float64x      // _Complex _Float64x
| 61 = @complex_std_float128  // _Complex _Float128
| 62 = @mfp8                  // __mfp8
| 63 = @scalable_vector_count // __SVCount_t
| 64 = @complex_fp16          // _Complex __fp16
| 65 = @complex_std_bfloat16  // _Complex __bf16
| 66 = @complex_std_float16   // _Complex std::float16_t
;

builtintypes(
    unique int id: @builtintype,
    string name: string ref,
    int kind: int ref,
    int size: int ref,
    int sign: int ref,
    int alignment: int ref
);

/**
 * Derived types are types that are directly derived from existing types and
 * point to, refer to, transform type data to return a new type.
 */
case @derivedtype.kind of
   1 = @pointer
|  2 = @reference
|  3 = @type_with_specifiers
|  4 = @array
|  5 = @gnu_vector
|  6 = @routineptr
|  7 = @routinereference
|  8 = @rvalue_reference // C++11
// ... 9 type_conforming_to_protocols deprecated
| 10 = @block
| 11 = @scalable_vector // Arm SVE
;

derivedtypes(
    unique int id: @derivedtype,
    string name: string ref,
    int kind: int ref,
    int type_id: @type ref
);

pointerishsize(unique int id: @derivedtype ref,
    int size: int ref,
    int alignment: int ref);

arraysizes(
    unique int id: @derivedtype ref,
    int num_elements: int ref,
    int bytesize: int ref,
    int alignment: int ref
);

tupleelements(
    unique int id: @derivedtype ref,
    int num_elements: int ref
);

typedefbase(
    unique int id: @usertype ref,
    int type_id: @type ref
);

/**
 * An instance of the C++11 `decltype` operator or C23 `typeof`/`typeof_unqual`
 * operator taking an expression as its argument.  For example:
 * ```
 * int a;
 * decltype(1+a) b;
 * typeof(1+a) c;
 * ```
 * Here `expr` is `1+a`.
 *
 * Sometimes an additional pair of parentheses around the expression
 * changes the semantics of the decltype, e.g.
 * ```
 * struct A { double x; };
 * const A* a = new A();
 * decltype( a->x ); // type is double
 * decltype((a->x)); // type is const double&
 * ```
 * (Please consult the C++11 standard for more details).
 * `parentheses_would_change_meaning` is `true` iff that is the case.
 */

/*
case @decltype.kind of
|  0 = @decltype
|  1 = @typeof // The frontend does not differentiate between typeof and typeof_unqual
;
*/

#keyset[id, expr]
decltypes(
    int id: @decltype,
    int expr: @expr ref,
    int kind: int ref,
    int base_type: @type ref,
    boolean parentheses_would_change_meaning: boolean ref
);

case @type_operator.kind of
   0 = @typeof // The frontend does not differentiate between typeof and typeof_unqual
|  1 = @underlying_type
|  2 = @bases
|  3 = @direct_bases
|  4 = @add_lvalue_reference
|  5 = @add_pointer
|  6 = @add_rvalue_reference
|  7 = @decay
|  8 = @make_signed
|  9 = @make_unsigned
| 10 = @remove_all_extents
| 11 = @remove_const
| 12 = @remove_cv
| 13 = @remove_cvref
| 14 = @remove_extent
| 15 = @remove_pointer
| 16 = @remove_reference_t
| 17 = @remove_restrict
| 18 = @remove_volatile
| 19 = @remove_reference
;

type_operators(
    unique int id: @type_operator,
    int arg_type: @type ref,
    int kind: int ref,
    int base_type: @type ref
)

case @usertype.kind of
   0 = @unknown_usertype
|  1 = @struct
|  2 = @class
|  3 = @union
|  4 = @enum
// ... 5 = @typedef deprecated        // classic C: typedef typedef type name
// ... 6 = @template deprecated
|  7 = @template_parameter
|  8 = @template_template_parameter
|  9 = @proxy_class                   // a proxy class associated with a template parameter
// ... 10 objc_class deprecated
// ... 11 objc_protocol deprecated
// ... 12 objc_category deprecated
| 13 = @scoped_enum
// ... 14 = @using_alias deprecated   // a using name = type style typedef
| 15 = @template_struct
| 16 = @template_class
| 17 = @template_union
| 18 = @alias
;

usertypes(
    unique int id: @usertype,
    string name: string ref,
    int kind: int ref
);

usertypesize(
    unique int id: @usertype ref,
    int size: int ref,
    int alignment: int ref
);

usertype_final(unique int id: @usertype ref);

usertype_uuid(
    unique int id: @usertype ref,
    string uuid: string ref
);

/*
case @usertype.alias_kind of
| 0 = @typedef
| 1 = @alias
*/

usertype_alias_kind(
    int id: @usertype ref,
    int alias_kind: int ref
)

nontype_template_parameters(
    int id: @expr ref
);

type_template_type_constraint(
    int id: @usertype ref,
    int constraint: @expr ref
);

mangled_name(
    unique int id: @declaration ref,
    int mangled_name : @mangledname,
    boolean is_complete: boolean ref
);

is_pod_class(unique int id: @usertype ref);
is_standard_layout_class(unique int id: @usertype ref);

is_complete(unique int id: @usertype ref);

is_class_template(unique int id: @usertype ref);
class_instantiation(
    int to: @usertype ref,
    int from: @usertype ref
);
class_template_argument(
    int type_id: @usertype ref,
    int index: int ref,
    int arg_type: @type ref
);
class_template_argument_value(
    int type_id: @usertype ref,
    int index: int ref,
    int arg_value: @expr ref
);

@user_or_decltype = @usertype | @decltype;

is_proxy_class_for(
    unique int id: @usertype ref,
    int templ_param_id: @user_or_decltype ref
);

type_mentions(
    unique int id: @type_mention,
    int type_id: @type ref,
    int location: @location_default ref,
    // a_symbol_reference_kind from the frontend.
    int kind: int ref
);

is_function_template(unique int id: @function ref);
function_instantiation(
    unique int to: @function ref,
    int from: @function ref
);
function_template_argument(
    int function_id: @function ref,
    int index: int ref,
    int arg_type: @type ref
);
function_template_argument_value(
    int function_id: @function ref,
    int index: int ref,
    int arg_value: @expr ref
);

is_variable_template(unique int id: @variable ref);
variable_instantiation(
    unique int to: @variable ref,
    int from: @variable ref
);
variable_template_argument(
    int variable_id: @variable ref,
    int index: int ref,
    int arg_type: @type ref
);
variable_template_argument_value(
    int variable_id: @variable ref,
    int index: int ref,
    int arg_value: @expr ref
);

template_template_instantiation(
    int to: @usertype ref,
    int from: @usertype ref
);
template_template_argument(
    int type_id: @usertype ref,
    int index: int ref,
    int arg_type: @type ref
);
template_template_argument_value(
    int type_id: @usertype ref,
    int index: int ref,
    int arg_value: @expr ref
);

@concept = @concept_template | @concept_id;

concept_templates(
    unique int concept_id: @concept_template,
    string name: string ref,
    int location: @location_default ref
);
concept_instantiation(
    unique int to: @concept_id ref,
    int from: @concept_template ref
);
is_type_constraint(int concept_id: @concept_id ref);
concept_template_argument(
    int concept_id: @concept ref,
    int index: int ref,
    int arg_type: @type ref
);
concept_template_argument_value(
    int concept_id: @concept ref,
    int index: int ref,
    int arg_value: @expr ref
);

routinetypes(
    unique int id: @routinetype,
    int return_type: @type ref
);

routinetypeargs(
    int routine: @routinetype ref,
    int index: int ref,
    int type_id: @type ref
);

ptrtomembers(
    unique int id: @ptrtomember,
    int type_id: @type ref,
    int class_id: @type ref
);

/*
 specifiers for types, functions, and variables

    "public",
    "protected",
    "private",

    "const",
    "volatile",
    "static",

    "pure",
    "virtual",
    "sealed", // Microsoft
    "__interface", // Microsoft
    "inline",
    "explicit",

    "near", // near far extension
    "far", // near far extension
    "__ptr32", // Microsoft
    "__ptr64", // Microsoft
    "__sptr", // Microsoft
    "__uptr", // Microsoft
    "dllimport", // Microsoft
    "dllexport", // Microsoft
    "thread", // Microsoft
    "naked", // Microsoft
    "microsoft_inline", // Microsoft
    "forceinline", // Microsoft
    "selectany", // Microsoft
    "nothrow", // Microsoft
    "novtable", // Microsoft
    "noreturn", // Microsoft
    "noinline", // Microsoft
    "noalias", // Microsoft
    "restrict", // Microsoft
*/

specifiers(
    unique int id: @specifier,
    unique string str: string ref
);

typespecifiers(
    int type_id: @type ref,
    int spec_id: @specifier ref
);

funspecifiers(
    int func_id: @function ref,
    int spec_id: @specifier ref
);

varspecifiers(
    int var_id: @accessible ref,
    int spec_id: @specifier ref
);

explicit_specifier_exprs(
    unique int func_id: @function ref,
    int constant: @expr ref
)

attributes(
    unique int id: @attribute,
    int kind: int ref,
    string name: string ref,
    string name_space: string ref,
    int location: @location_default ref
);

case @attribute.kind of
  0 = @gnuattribute
| 1 = @stdattribute
| 2 = @declspec
| 3 = @msattribute
| 4 = @alignas
// ... 5 @objc_propertyattribute deprecated
;

attribute_args(
    unique int id: @attribute_arg,
    int kind: int ref,
    int attribute: @attribute ref,
    int index: int ref,
    int location: @location_default ref
);

case @attribute_arg.kind of
  0 = @attribute_arg_empty
| 1 = @attribute_arg_token
| 2 = @attribute_arg_constant
| 3 = @attribute_arg_type
| 4 = @attribute_arg_constant_expr
| 5 = @attribute_arg_expr
;

attribute_arg_value(
    unique int arg: @attribute_arg ref,
    string value: string ref
);
attribute_arg_type(
    unique int arg: @attribute_arg ref,
    int type_id: @type ref
);
attribute_arg_constant(
    unique int arg: @attribute_arg ref,
    int constant: @expr ref
)
attribute_arg_expr(
    unique int arg: @attribute_arg ref,
    int expr: @expr ref
)
attribute_arg_name(
    unique int arg: @attribute_arg ref,
    string name: string ref
);

typeattributes(
    int type_id: @type ref,
    int spec_id: @attribute ref
);

funcattributes(
    int func_id: @function ref,
    int spec_id: @attribute ref
);

varattributes(
    int var_id: @accessible ref,
    int spec_id: @attribute ref
);

namespaceattributes(
    int namespace_id: @namespace ref,
    int spec_id: @attribute ref
);

stmtattributes(
    int stmt_id: @stmt ref,
    int spec_id: @attribute ref
);

@type = @builtintype
      | @derivedtype
      | @usertype
      | @routinetype
      | @ptrtomember
      | @decltype
      | @type_operator;

unspecifiedtype(
    unique int type_id: @type ref,
    int unspecified_type_id: @type ref
);

member(
    int parent: @type ref,
    int index: int ref,
    int child: @member ref
);

@enclosingfunction_child = @usertype | @variable | @namespace

enclosingfunction(
    unique int child: @enclosingfunction_child ref,
    int parent: @function ref
);

derivations(
    unique int derivation: @derivation,
    int sub: @type ref,
    int index: int ref,
    int super: @type ref,
    int location: @location_default ref
);

derspecifiers(
    int der_id: @derivation ref,
    int spec_id: @specifier ref
);

/**
 * Contains the byte offset of the base class subobject within the derived
 * class. Only holds for non-virtual base classes, but see table
 * `virtual_base_offsets` for offsets of virtual base class subobjects.
 */
direct_base_offsets(
    unique int der_id: @derivation ref,
    int offset: int ref
);

/**
 * Contains the byte offset of the virtual base class subobject for class
 * `super` within a most-derived object of class `sub`. `super` can be either a
 * direct or indirect base class.
 */
#keyset[sub, super]
virtual_base_offsets(
    int sub: @usertype ref,
    int super: @usertype ref,
    int offset: int ref
);

frienddecls(
    unique int id: @frienddecl,
    int type_id: @type ref,
    int decl_id: @declaration ref,
    int location: @location_default ref
);

@declaredtype = @usertype ;

@declaration = @function
             | @declaredtype
             | @variable
             | @enumconstant
             | @frienddecl
             | @concept_template;

@member = @membervariable
        | @function
        | @declaredtype
        | @enumconstant;

@locatable = @diagnostic
           | @declaration
           | @ppd_include
           | @ppd_define
           | @macroinvocation
           /*| @funcall*/
           | @xmllocatable
           | @attribute
           | @attribute_arg;

@namedscope = @namespace | @usertype;

@element = @locatable
         | @file
         | @folder
         | @specifier
         | @type
         | @expr
         | @namespace
         | @initialiser
         | @stmt
         | @derivation
         | @comment
         | @preprocdirect
         | @fun_decl
         | @var_decl
         | @type_decl
         | @namespace_decl
         | @using
         | @namequalifier
         | @specialnamequalifyingelement
         | @static_assert
         | @type_mention
         | @lambdacapture;

@exprparent = @element;

comments(
    unique int id: @comment,
    string contents: string ref,
    int location: @location_default ref
);

commentbinding(
    int id: @comment ref,
    int element: @element ref
);

exprconv(
    int converted: @expr ref,
    unique int conversion: @expr ref
);

compgenerated(unique int id: @element ref);

/**
 * `destructor_call` destructs the `i`'th entity that should be
 * destructed following `element`. Note that entities should be
 * destructed in reverse construction order, so for a given `element`
 * these should be called from highest to lowest `i`.
 */
#keyset[element, destructor_call]
#keyset[element, i]
synthetic_destructor_call(
    int element: @element ref,
    int i: int ref,
    int destructor_call: @routineexpr ref
);

namespaces(
    unique int id: @namespace,
    string name: string ref
);

namespace_inline(
    unique int id: @namespace ref
);

namespacembrs(
    int parentid: @namespace ref,
    unique int memberid: @namespacembr ref
);

@namespacembr = @declaration | @namespace;

exprparents(
    int expr_id: @expr ref,
    int child_index: int ref,
    int parent_id: @exprparent ref
);

expr_isload(unique int expr_id: @expr ref);

@cast = @c_style_cast
      | @const_cast
      | @dynamic_cast
      | @reinterpret_cast
      | @static_cast
      ;

/*
case @conversion.kind of
  0 = @simple_conversion           // a numeric conversion, qualification conversion, or a reinterpret_cast
| 1 = @bool_conversion             // conversion to 'bool'
| 2 = @base_class_conversion       // a derived-to-base conversion
| 3 = @derived_class_conversion    // a base-to-derived conversion
| 4 = @pm_base_class_conversion    // a derived-to-base conversion of a pointer to member
| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member
| 6 = @glvalue_adjust              // an adjustment of the type of a glvalue
| 7 = @prvalue_adjust              // an adjustment of the type of a prvalue
;
*/
/**
 * Describes the semantics represented by a cast expression. This is largely
 * independent of the source syntax of the cast, so it is separate from the
 * regular expression kind.
 */
conversionkinds(
    unique int expr_id: @cast ref,
    int kind: int ref
);

@conversion = @cast
            | @array_to_pointer
            | @parexpr
            | @reference_to
            | @ref_indirect
            | @temp_init
            | @c11_generic
            ;

/*
case @funbindexpr.kind of
  0 = @normal_call  // a normal call
| 1 = @virtual_call // a virtual call
| 2 = @adl_call     // a call whose target is only found by ADL
;
*/
iscall(
    unique int caller: @funbindexpr ref,
    int kind: int ref
);

numtemplatearguments(
    unique int expr_id: @expr ref,
    int num: int ref
);

specialnamequalifyingelements(
    unique int id: @specialnamequalifyingelement,
    unique string name: string ref
);

@namequalifiableelement = @expr | @namequalifier;
@namequalifyingelement = @namespace
                       | @specialnamequalifyingelement
                       | @usertype
                       | @decltype;

namequalifiers(
    unique int id: @namequalifier,
    unique int qualifiableelement: @namequalifiableelement ref,
    int qualifyingelement: @namequalifyingelement ref,
    int location: @location_default ref
);

varbind(
    int expr: @varbindexpr ref,
    int var: @accessible ref
);

funbind(
    int expr: @funbindexpr ref,
    int fun: @function ref
);

@any_new_expr = @new_expr
              | @new_array_expr;

@new_or_delete_expr = @any_new_expr
                    | @delete_expr
                    | @delete_array_expr;

@prefix_crement_expr = @preincrexpr | @predecrexpr;

@postfix_crement_expr = @postincrexpr | @postdecrexpr;

@increment_expr = @preincrexpr | @postincrexpr;

@decrement_expr = @predecrexpr | @postdecrexpr;

@crement_expr = @increment_expr | @decrement_expr;

@un_arith_op_expr = @arithnegexpr
                  | @unaryplusexpr
                  | @conjugation
                  | @realpartexpr
                  | @imagpartexpr
                  | @crement_expr
                  ;

@un_bitwise_op_expr = @complementexpr;

@un_log_op_expr = @notexpr;

@un_op_expr = @address_of
            | @indirect
            | @un_arith_op_expr
            | @un_bitwise_op_expr
            | @builtinaddressof
            | @vec_fill
            | @un_log_op_expr
            | @co_await
            | @co_yield
            ;

@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr;

@cmp_op_expr = @eq_op_expr | @rel_op_expr;

@eq_op_expr = @eqexpr | @neexpr;

@rel_op_expr = @gtexpr
             | @ltexpr
             | @geexpr
             | @leexpr
             | @spaceshipexpr
             ;

@bin_bitwise_op_expr = @lshiftexpr
                     | @rshiftexpr
                     | @andexpr
                     | @orexpr
                     | @xorexpr
                     ;

@p_arith_op_expr = @paddexpr
                 | @psubexpr
                 | @pdiffexpr
                 ;

@bin_arith_op_expr = @addexpr
                   | @subexpr
                   | @mulexpr
                   | @divexpr
                   | @remexpr
                   | @jmulexpr
                   | @jdivexpr
                   | @fjaddexpr
                   | @jfaddexpr
                   | @fjsubexpr
                   | @jfsubexpr
                   | @minexpr
                   | @maxexpr
                   | @p_arith_op_expr
                   ;

@bin_op_expr = @bin_arith_op_expr
             | @bin_bitwise_op_expr
             | @cmp_op_expr
             | @bin_log_op_expr
             ;

@op_expr = @un_op_expr
         | @bin_op_expr
         | @assign_expr
         | @conditionalexpr
         ;

@assign_arith_expr = @assignaddexpr
                   | @assignsubexpr
                   | @assignmulexpr
                   | @assigndivexpr
                   | @assignremexpr
                   ;

@assign_bitwise_expr = @assignandexpr
                     | @assignorexpr
                     | @assignxorexpr
                     | @assignlshiftexpr
                     | @assignrshiftexpr
                     ;

@assign_pointer_expr = @assignpaddexpr
                     | @assignpsubexpr
                     ;

@assign_op_expr = @assign_arith_expr
                | @assign_bitwise_expr
                | @assign_pointer_expr
                ;

@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr

/*
  Binary encoding of the allocator form.

  case @allocator.form of
    0 = plain
  | 1 = alignment
  ;
*/

/**
 * The allocator function associated with a `new` or `new[]` expression.
 * The `form` column specified whether the allocation call contains an alignment
 * argument.
 */
expr_allocator(
    unique int expr: @any_new_expr ref,
    int func: @function ref,
    int form: int ref
);

/*
  Binary encoding of the deallocator form.

  case @deallocator.form of
    0 = plain
  | 1 = size
  | 2 = alignment
  | 4 = destroying_delete
  ;
*/

/**
 * The deallocator function associated with a `delete`, `delete[]`, `new`, or
 * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the
 * one used to free memory if the initialization throws an exception.
 * The `form` column specifies whether the deallocation call contains a size
 * argument, and alignment argument, or both.
 */
expr_deallocator(
    unique int expr: @new_or_delete_expr ref,
    int func: @function ref,
    int form: int ref
);

/**
 * Holds if the `@conditionalexpr` is of the two operand form
 * `guard ? : false`.
 */
expr_cond_two_operand(
    unique int cond: @conditionalexpr ref
);

/**
 * The guard of `@conditionalexpr` `guard ? true : false`
 */
expr_cond_guard(
    unique int cond: @conditionalexpr ref,
    int guard: @expr ref
);

/**
 * The expression used when the guard of `@conditionalexpr`
 * `guard ? true : false` holds. For the two operand form
 * `guard ?: false` consider using `expr_cond_guard` instead.
 */
expr_cond_true(
    unique int cond: @conditionalexpr ref,
    int true: @expr ref
);

/**
 * The expression used when the guard of `@conditionalexpr`
 * `guard ? true : false` does not hold.
 */
expr_cond_false(
    unique int cond: @conditionalexpr ref,
    int false: @expr ref
);

/** A string representation of the value. */
values(
    unique int id: @value,
    string str: string ref
);

/** The actual text in the source code for the value, if any. */
valuetext(
    unique int id: @value ref,
    string text: string ref
);

valuebind(
    int val: @value ref,
    unique int expr: @expr ref
);

fieldoffsets(
    unique int id: @variable ref,
    int byteoffset: int ref,
    int bitoffset: int ref
);

bitfield(
    unique int id: @variable ref,
    int bits: int ref,
    int declared_bits: int ref
);

/* TODO
memberprefix(
    int member: @expr ref,
    int prefix: @expr ref
);
*/

/*
   kind(1) = mbrcallexpr
   kind(2) = mbrptrcallexpr
   kind(3) = mbrptrmbrcallexpr
   kind(4) = ptrmbrptrmbrcallexpr
   kind(5) = mbrreadexpr // x.y
   kind(6) = mbrptrreadexpr // p->y
   kind(7) = mbrptrmbrreadexpr // x.*pm
   kind(8) = mbrptrmbrptrreadexpr // x->*pm
   kind(9) = staticmbrreadexpr // static x.y
   kind(10) = staticmbrptrreadexpr // static p->y
*/
/* TODO
memberaccess(
    int member: @expr ref,
    int kind: int ref
);
*/

initialisers(
    unique int init: @initialiser,
    int var: @accessible ref,
    unique int expr: @expr ref,
    int location: @location_default ref
);

braced_initialisers(
    int init: @initialiser ref
);

/**
 * An ancestor for the expression, for cases in which we cannot
 * otherwise find the expression's parent.
 */
expr_ancestor(
    int exp: @expr ref,
    int ancestor: @element ref
);

exprs(
    unique int id: @expr,
    int kind: int ref,
    int location: @location_default ref
);

expr_reuse(
    int reuse: @expr ref,
    int original: @expr ref,
    int value_category: int ref
)

/*
  case @value.category of
    1 = prval
  | 2 = xval
  | 3 = lval
  ;
*/
expr_types(
    int id: @expr ref,
    int typeid: @type ref,
    int value_category: int ref
);

case @expr.kind of
    1 = @errorexpr
|   2 = @address_of // & AddressOfExpr
|   3 = @reference_to // ReferenceToExpr (implicit?)
|   4 = @indirect // * PointerDereferenceExpr
|   5 = @ref_indirect // ReferenceDereferenceExpr (implicit?)
// ...
|   8 = @array_to_pointer // (???)
|   9 = @vacuous_destructor_call // VacuousDestructorCall
// ...
|  11 = @assume // Microsoft
|  12 = @parexpr
|  13 = @arithnegexpr
|  14 = @unaryplusexpr
|  15 = @complementexpr
|  16 = @notexpr
|  17 = @conjugation // GNU ~ operator
|  18 = @realpartexpr // GNU __real
|  19 = @imagpartexpr // GNU __imag
|  20 = @postincrexpr
|  21 = @postdecrexpr
|  22 = @preincrexpr
|  23 = @predecrexpr
|  24 = @conditionalexpr
|  25 = @addexpr
|  26 = @subexpr
|  27 = @mulexpr
|  28 = @divexpr
|  29 = @remexpr
|  30 = @jmulexpr // C99 mul imaginary
|  31 = @jdivexpr // C99 div imaginary
|  32 = @fjaddexpr // C99 add real + imaginary
|  33 = @jfaddexpr // C99 add imaginary + real
|  34 = @fjsubexpr // C99 sub real - imaginary
|  35 = @jfsubexpr // C99 sub imaginary - real
|  36 = @paddexpr // pointer add (pointer + int or int + pointer)
|  37 = @psubexpr // pointer sub (pointer - integer)
|  38 = @pdiffexpr // difference between two pointers
|  39 = @lshiftexpr
|  40 = @rshiftexpr
|  41 = @andexpr
|  42 = @orexpr
|  43 = @xorexpr
|  44 = @eqexpr
|  45 = @neexpr
|  46 = @gtexpr
|  47 = @ltexpr
|  48 = @geexpr
|  49 = @leexpr
|  50 = @minexpr // GNU minimum
|  51 = @maxexpr // GNU maximum
|  52 = @assignexpr
|  53 = @assignaddexpr
|  54 = @assignsubexpr
|  55 = @assignmulexpr
|  56 = @assigndivexpr
|  57 = @assignremexpr
|  58 = @assignlshiftexpr
|  59 = @assignrshiftexpr
|  60 = @assignandexpr
|  61 = @assignorexpr
|  62 = @assignxorexpr
|  63 = @assignpaddexpr // assign pointer add
|  64 = @assignpsubexpr // assign pointer sub
|  65 = @andlogicalexpr
|  66 = @orlogicalexpr
|  67 = @commaexpr
|  68 = @subscriptexpr // access to member of an array, e.g., a[5]
// ...  69 @objc_subscriptexpr deprecated
// ...  70 @cmdaccess deprecated
// ...
|  73 = @virtfunptrexpr
|  74 = @callexpr
// ...  75 @msgexpr_normal deprecated
// ...  76 @msgexpr_super deprecated
// ...  77 @atselectorexpr deprecated
// ...  78 @atprotocolexpr deprecated
|  79 = @vastartexpr
|  80 = @vaargexpr
|  81 = @vaendexpr
|  82 = @vacopyexpr
// ...  83 @atencodeexpr deprecated
|  84 = @varaccess
|  85 = @thisaccess
// ...  86 @objc_box_expr deprecated
|  87 = @new_expr
|  88 = @delete_expr
|  89 = @throw_expr
|  90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2)
|  91 = @braced_init_list
|  92 = @type_id
|  93 = @runtime_sizeof
|  94 = @runtime_alignof
|  95 = @sizeof_pack
|  96 = @expr_stmt // GNU extension
|  97 = @routineexpr
|  98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....)
|  99 = @offsetofexpr // offsetof ::= type and field
| 100 = @hasassignexpr // __has_assign ::= type
| 101 = @hascopyexpr // __has_copy ::= type
| 102 = @hasnothrowassign // __has_nothrow_assign ::= type
| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type
| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type
| 105 = @hastrivialassign // __has_trivial_assign ::= type
| 106 = @hastrivialconstr // __has_trivial_constructor ::= type
| 107 = @hastrivialcopy // __has_trivial_copy ::= type
| 108 = @hasuserdestr // __has_user_destructor ::= type
| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type
| 110 = @isabstractexpr // __is_abstract ::= type
| 111 = @isbaseofexpr // __is_base_of ::= type type
| 112 = @isclassexpr // __is_class ::= type
| 113 = @isconvtoexpr // __is_convertible_to ::= type type
| 114 = @isemptyexpr // __is_empty ::= type
| 115 = @isenumexpr // __is_enum ::= type
| 116 = @ispodexpr // __is_pod ::= type
| 117 = @ispolyexpr // __is_polymorphic ::= type
| 118 = @isunionexpr // __is_union ::= type
| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type
| 120 = @intaddrexpr // frontend internal builtin, used to implement offsetof
// ...
| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type
| 123 = @literal
| 124 = @uuidof
| 127 = @aggregateliteral
| 128 = @delete_array_expr
| 129 = @new_array_expr
// ... 130 @objc_array_literal deprecated
// ... 131 @objc_dictionary_literal deprecated
| 132 = @foldexpr
// ...
| 200 = @ctordirectinit
| 201 = @ctorvirtualinit
| 202 = @ctorfieldinit
| 203 = @ctordelegatinginit
| 204 = @dtordirectdestruct
| 205 = @dtorvirtualdestruct
| 206 = @dtorfielddestruct
// ...
| 210 = @static_cast
| 211 = @reinterpret_cast
| 212 = @const_cast
| 213 = @dynamic_cast
| 214 = @c_style_cast
| 215 = @lambdaexpr
| 216 = @param_ref
| 217 = @noopexpr
// ...
| 294 = @istriviallyconstructibleexpr
| 295 = @isdestructibleexpr
| 296 = @isnothrowdestructibleexpr
| 297 = @istriviallydestructibleexpr
| 298 = @istriviallyassignableexpr
| 299 = @isnothrowassignableexpr
| 300 = @istrivialexpr
| 301 = @isstandardlayoutexpr
| 302 = @istriviallycopyableexpr
| 303 = @isliteraltypeexpr
| 304 = @hastrivialmoveconstructorexpr
| 305 = @hastrivialmoveassignexpr
| 306 = @hasnothrowmoveassignexpr
| 307 = @isconstructibleexpr
| 308 = @isnothrowconstructibleexpr
| 309 = @hasfinalizerexpr
| 310 = @isdelegateexpr
| 311 = @isinterfaceclassexpr
| 312 = @isrefarrayexpr
| 313 = @isrefclassexpr
| 314 = @issealedexpr
| 315 = @issimplevalueclassexpr
| 316 = @isvalueclassexpr
| 317 = @isfinalexpr
| 319 = @noexceptexpr
| 320 = @builtinshufflevector
| 321 = @builtinchooseexpr
| 322 = @builtinaddressof
| 323 = @vec_fill
| 324 = @builtinconvertvector
| 325 = @builtincomplex
| 326 = @spaceshipexpr
| 327 = @co_await
| 328 = @co_yield
| 329 = @temp_init
| 330 = @isassignable
| 331 = @isaggregate
| 332 = @hasuniqueobjectrepresentations
| 333 = @builtinbitcast
| 334 = @builtinshuffle
| 335 = @blockassignexpr
| 336 = @issame
| 337 = @isfunction
| 338 = @islayoutcompatible
| 339 = @ispointerinterconvertiblebaseof
| 340 = @isarray
| 341 = @arrayrank
| 342 = @arrayextent
| 343 = @isarithmetic
| 344 = @iscompletetype
| 345 = @iscompound
| 346 = @isconst
| 347 = @isfloatingpoint
| 348 = @isfundamental
| 349 = @isintegral
| 350 = @islvaluereference
| 351 = @ismemberfunctionpointer
| 352 = @ismemberobjectpointer
| 353 = @ismemberpointer
| 354 = @isobject
| 355 = @ispointer
| 356 = @isreference
| 357 = @isrvaluereference
| 358 = @isscalar
| 359 = @issigned
| 360 = @isunsigned
| 361 = @isvoid
| 362 = @isvolatile
| 363 = @reuseexpr
| 364 = @istriviallycopyassignable
| 365 = @isassignablenopreconditioncheck
| 366 = @referencebindstotemporary
| 367 = @issameas
| 368 = @builtinhasattribute
| 369 = @ispointerinterconvertiblewithclass
| 370 = @builtinispointerinterconvertiblewithclass
| 371 = @iscorrespondingmember
| 372 = @builtiniscorrespondingmember
| 373 = @isboundedarray
| 374 = @isunboundedarray
| 375 = @isreferenceable
| 378 = @isnothrowconvertible
| 379 = @referenceconstructsfromtemporary
| 380 = @referenceconvertsfromtemporary
| 381 = @isconvertible
| 382 = @isvalidwinrttype
| 383 = @iswinclass
| 384 = @iswininterface
| 385 = @istriviallyequalitycomparable
| 386 = @isscopedenum
| 387 = @istriviallyrelocatable
| 388 = @datasizeof
| 389 = @c11_generic
| 390 = @requires_expr
| 391 = @nested_requirement
| 392 = @compound_requirement
| 393 = @concept_id
| 394 = @isinvocable
| 395 = @isnothrowinvocable
| 396 = @isbitwisecloneable
;

@var_args_expr = @vastartexpr
               | @vaendexpr
               | @vaargexpr
               | @vacopyexpr
               ;

@builtin_op = @var_args_expr
            | @noopexpr
            | @offsetofexpr
            | @intaddrexpr
            | @hasassignexpr
            | @hascopyexpr
            | @hasnothrowassign
            | @hasnothrowconstr
            | @hasnothrowcopy
            | @hastrivialassign
            | @hastrivialconstr
            | @hastrivialcopy
            | @hastrivialdestructor
            | @hasuserdestr
            | @hasvirtualdestr
            | @isabstractexpr
            | @isbaseofexpr
            | @isclassexpr
            | @isconvtoexpr
            | @isemptyexpr
            | @isenumexpr
            | @ispodexpr
            | @ispolyexpr
            | @isunionexpr
            | @typescompexpr
            | @builtinshufflevector
            | @builtinconvertvector
            | @builtinaddressof
            | @istriviallyconstructibleexpr
            | @isdestructibleexpr
            | @isnothrowdestructibleexpr
            | @istriviallydestructibleexpr
            | @istriviallyassignableexpr
            | @isnothrowassignableexpr
            | @istrivialexpr
            | @isstandardlayoutexpr
            | @istriviallycopyableexpr
            | @isliteraltypeexpr
            | @hastrivialmoveconstructorexpr
            | @hastrivialmoveassignexpr
            | @hasnothrowmoveassignexpr
            | @isconstructibleexpr
            | @isnothrowconstructibleexpr
            | @hasfinalizerexpr
            | @isdelegateexpr
            | @isinterfaceclassexpr
            | @isrefarrayexpr
            | @isrefclassexpr
            | @issealedexpr
            | @issimplevalueclassexpr
            | @isvalueclassexpr
            | @isfinalexpr
            | @builtinchooseexpr
            | @builtincomplex
            | @isassignable
            | @isaggregate
            | @hasuniqueobjectrepresentations
            | @builtinbitcast
            | @builtinshuffle
            | @issame
            | @isfunction
            | @islayoutcompatible
            | @ispointerinterconvertiblebaseof
            | @isarray
            | @arrayrank
            | @arrayextent
            | @isarithmetic
            | @iscompletetype
            | @iscompound
            | @isconst
            | @isfloatingpoint
            | @isfundamental
            | @isintegral
            | @islvaluereference
            | @ismemberfunctionpointer
            | @ismemberobjectpointer
            | @ismemberpointer
            | @isobject
            | @ispointer
            | @isreference
            | @isrvaluereference
            | @isscalar
            | @issigned
            | @isunsigned
            | @isvoid
            | @isvolatile
            | @istriviallycopyassignable
            | @isassignablenopreconditioncheck
            | @referencebindstotemporary
            | @issameas
            | @builtinhasattribute
            | @ispointerinterconvertiblewithclass
            | @builtinispointerinterconvertiblewithclass
            | @iscorrespondingmember
            | @builtiniscorrespondingmember
            | @isboundedarray
            | @isunboundedarray
            | @isreferenceable
            | @isnothrowconvertible
            | @referenceconstructsfromtemporary
            | @referenceconvertsfromtemporary
            | @isconvertible
            | @isvalidwinrttype
            | @iswinclass
            | @iswininterface
            | @istriviallyequalitycomparable
            | @isscopedenum
            | @istriviallyrelocatable
            | @isinvocable
            | @isnothrowinvocable
            | @isbitwisecloneable
            ;

compound_requirement_is_noexcept(
    int expr: @compound_requirement ref
);

new_allocated_type(
    unique int expr: @new_expr ref,
    int type_id: @type ref
);

new_array_allocated_type(
    unique int expr: @new_array_expr ref,
    int type_id: @type ref
);

param_ref_to_this(
    int expr: @param_ref ref
)

/**
 * The field being initialized by an initializer expression within an aggregate
 * initializer for a class/struct/union. Position is used to sort repeated initializers.
 */
#keyset[aggregate, position]
aggregate_field_init(
    int aggregate: @aggregateliteral ref,
    int initializer: @expr ref,
    int field: @membervariable ref,
    int position: int ref,
    boolean is_designated: boolean ref
);

/**
 * The index of the element being initialized by an initializer expression
 * within an aggregate initializer for an array. Position is used to sort repeated initializers.
 */
#keyset[aggregate, position]
aggregate_array_init(
    int aggregate: @aggregateliteral ref,
    int initializer: @expr ref,
    int element_index: int ref,
    int position: int ref,
    boolean is_designated: boolean ref
);

@ctorinit = @ctordirectinit
          | @ctorvirtualinit
          | @ctorfieldinit
          | @ctordelegatinginit;
@dtordestruct = @dtordirectdestruct
              | @dtorvirtualdestruct
              | @dtorfielddestruct;


condition_decl_bind(
    unique int expr: @condition_decl ref,
    unique int decl: @declaration ref
);

typeid_bind(
    unique int expr: @type_id ref,
    int type_id: @type ref
);

uuidof_bind(
    unique int expr: @uuidof ref,
    int type_id: @type ref
);

@sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof | @sizeof_pack;

sizeof_bind(
    unique int expr: @sizeof_or_alignof ref,
    int type_id: @type ref
);

code_block(
    unique int block: @literal ref,
    unique int routine: @function ref
);

lambdas(
    unique int expr: @lambdaexpr ref,
    string default_capture: string ref,
    boolean has_explicit_return_type: boolean ref,
    boolean has_explicit_parameter_list: boolean ref
);

lambda_capture(
    unique int id: @lambdacapture,
    int lambda: @lambdaexpr ref,
    int index: int ref,
    int field: @membervariable ref,
    boolean captured_by_reference: boolean ref,
    boolean is_implicit: boolean ref,
    int location: @location_default ref
);

@funbindexpr = @routineexpr
             | @new_expr
             | @delete_expr
             | @delete_array_expr
             | @ctordirectinit
             | @ctorvirtualinit
             | @ctordelegatinginit
             | @dtordirectdestruct
             | @dtorvirtualdestruct;

@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct;
@addressable = @function | @variable ;
@accessible = @addressable | @enumconstant ;

@access = @varaccess | @routineexpr ;

fold(
    int expr: @foldexpr ref,
    string operator: string ref,
    boolean is_left_fold: boolean ref
);

stmts(
    unique int id: @stmt,
    int kind: int ref,
    int location: @location_default ref
);

case @stmt.kind of
    1 = @stmt_expr
|   2 = @stmt_if
|   3 = @stmt_while
|   4 = @stmt_goto
|   5 = @stmt_label
|   6 = @stmt_return
|   7 = @stmt_block
|   8 = @stmt_end_test_while // do { ... } while ( ... )
|   9 = @stmt_for
|  10 = @stmt_switch_case
|  11 = @stmt_switch
|  13 = @stmt_asm // "asm" statement or the body of an asm function
|  15 = @stmt_try_block
|  16 = @stmt_microsoft_try // Microsoft
|  17 = @stmt_decl
|  18 = @stmt_set_vla_size // C99
|  19 = @stmt_vla_decl // C99
|  25 = @stmt_assigned_goto // GNU
|  26 = @stmt_empty
|  27 = @stmt_continue
|  28 = @stmt_break
|  29 = @stmt_range_based_for // C++11
// ...  30 @stmt_at_autoreleasepool_block deprecated
// ...  31 @stmt_objc_for_in deprecated
// ...  32 @stmt_at_synchronized deprecated
|  33 = @stmt_handler
// ...  34 @stmt_finally_end deprecated
|  35 = @stmt_constexpr_if
|  37 = @stmt_co_return
|  38 = @stmt_consteval_if
|  39 = @stmt_not_consteval_if
|  40 = @stmt_leave
;

type_vla(
    int type_id: @type ref,
    int decl: @stmt_vla_decl ref
);

variable_vla(
    int var: @variable ref,
    int decl: @stmt_vla_decl ref
);

type_is_vla(unique int type_id: @derivedtype ref)

if_initialization(
    unique int if_stmt: @stmt_if ref,
    int init_id: @stmt ref
);

if_then(
    unique int if_stmt: @stmt_if ref,
    int then_id: @stmt ref
);

if_else(
    unique int if_stmt: @stmt_if ref,
    int else_id: @stmt ref
);

constexpr_if_initialization(
    unique int constexpr_if_stmt: @stmt_constexpr_if ref,
    int init_id: @stmt ref
);

constexpr_if_then(
    unique int constexpr_if_stmt: @stmt_constexpr_if ref,
    int then_id: @stmt ref
);

constexpr_if_else(
    unique int constexpr_if_stmt: @stmt_constexpr_if ref,
    int else_id: @stmt ref
);

@stmt_consteval_or_not_consteval_if = @stmt_consteval_if | @stmt_not_consteval_if;

consteval_if_then(
    unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref,
    int then_id: @stmt ref
);

consteval_if_else(
    unique int constexpr_if_stmt: @stmt_consteval_or_not_consteval_if ref,
    int else_id: @stmt ref
);

while_body(
    unique int while_stmt: @stmt_while ref,
    int body_id: @stmt ref
);

do_body(
    unique int do_stmt: @stmt_end_test_while ref,
    int body_id: @stmt ref
);

switch_initialization(
    unique int switch_stmt: @stmt_switch ref,
    int init_id: @stmt ref
);

#keyset[switch_stmt, index]
switch_case(
    int switch_stmt: @stmt_switch ref,
    int index: int ref,
    int case_id: @stmt_switch_case ref
);

switch_body(
    unique int switch_stmt: @stmt_switch ref,
    int body_id: @stmt ref
);

@stmt_for_or_range_based_for = @stmt_for
                             | @stmt_range_based_for;

for_initialization(
    unique int for_stmt: @stmt_for_or_range_based_for ref,
    int init_id: @stmt ref
);

for_condition(
    unique int for_stmt: @stmt_for ref,
    int condition_id: @expr ref
);

for_update(
    unique int for_stmt: @stmt_for ref,
    int update_id: @expr ref
);

for_body(
    unique int for_stmt: @stmt_for ref,
    int body_id: @stmt ref
);

@stmtparent = @stmt | @expr_stmt ;
stmtparents(
    unique int id: @stmt ref,
    int index: int ref,
    int parent: @stmtparent ref
);

ishandler(unique int block: @stmt_block ref);

@cfgnode = @stmt | @expr | @function | @initialiser ;

stmt_decl_bind(
    int stmt: @stmt_decl ref,
    int num: int ref,
    int decl: @declaration ref
);

stmt_decl_entry_bind(
    int stmt: @stmt_decl ref,
    int num: int ref,
    int decl_entry: @element ref
);

@parameterized_element = @function | @stmt_block | @requires_expr;

blockscope(
    unique int block: @stmt_block ref,
    int enclosing: @parameterized_element ref
);

@jump = @stmt_goto | @stmt_break | @stmt_continue | @stmt_leave;

@jumporlabel = @jump | @stmt_label | @literal;

jumpinfo(
    unique int id: @jumporlabel ref,
    string str: string ref,
    int target: @stmt ref
);

preprocdirects(
    unique int id: @preprocdirect,
    int kind: int ref,
    int location: @location_default ref
);
case @preprocdirect.kind of
   0 = @ppd_if
|  1 = @ppd_ifdef
|  2 = @ppd_ifndef
|  3 = @ppd_elif
|  4 = @ppd_else
|  5 = @ppd_endif
|  6 = @ppd_plain_include
|  7 = @ppd_define
|  8 = @ppd_undef
|  9 = @ppd_line
| 10 = @ppd_error
| 11 = @ppd_pragma
| 12 = @ppd_objc_import
| 13 = @ppd_include_next
| 14 = @ppd_ms_import
| 15 = @ppd_elifdef
| 16 = @ppd_elifndef
| 17 = @ppd_embed
| 18 = @ppd_warning
;

@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next | @ppd_ms_import;

@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif | @ppd_elifdef | @ppd_elifndef;

preprocpair(
    int begin : @ppd_branch ref,
    int elseelifend : @preprocdirect ref
);

preproctrue(int branch : @ppd_branch ref);
preprocfalse(int branch : @ppd_branch ref);

preproctext(
    unique int id: @preprocdirect ref,
    string head: string ref,
    string body: string ref
);

includes(
    unique int id: @ppd_include ref,
    int included: @file ref
);

embeds(
    unique int id: @ppd_embed ref,
    int included: @file ref
);

link_targets(
    int id: @link_target,
    int binary: @file ref
);

link_parent(
    int element : @element ref,
    int link_target : @link_target ref
);

/*- Database metadata -*/

/**
 * The CLI will automatically emit applicable tuples for this table,
 * such as `databaseMetadata("isOverlay", "true")` when building an
 * overlay database.
 */
databaseMetadata(
  string metadataKey: string ref,
  string value: string ref
);

/*- Overlay support -*/

/**
 * The CLI will automatically emit tuples for each new/modified/deleted file
 * when building an overlay database.
 */
overlayChangedFiles(
  string path: string ref
);

/*- XML Files -*/

xmlEncoding(
  unique int id: @file ref,
  string encoding: string ref
);

xmlDTDs(
  unique int id: @xmldtd,
  string root: string ref,
  string publicId: string ref,
  string systemId: string ref,
  int fileid: @file ref
);

xmlElements(
  unique int id: @xmlelement,
  string name: string ref,
  int parentid: @xmlparent ref,
  int idx: int ref,
  int fileid: @file ref
);

xmlAttrs(
  unique int id: @xmlattribute,
  int elementid: @xmlelement ref,
  string name: string ref,
  string value: string ref,
  int idx: int ref,
  int fileid: @file ref
);

xmlNs(
  int id: @xmlnamespace,
  string prefixName: string ref,
  string URI: string ref,
  int fileid: @file ref
);

xmlHasNs(
  int elementId: @xmlnamespaceable ref,
  int nsId: @xmlnamespace ref,
  int fileid: @file ref
);

xmlComments(
  unique int id: @xmlcomment,
  string text: string ref,
  int parentid: @xmlparent ref,
  int fileid: @file ref
);

xmlChars(
  unique int id: @xmlcharacters,
  string text: string ref,
  int parentid: @xmlparent ref,
  int idx: int ref,
  int isCDATA: int ref,
  int fileid: @file ref
);

@xmlparent = @file | @xmlelement;
@xmlnamespaceable = @xmlelement | @xmlattribute;

xmllocations(
  int xmlElement: @xmllocatable ref,
  int location: @location_default ref
);

@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
