diff --git a/.github/workflows/check-change-note.yml b/.github/workflows/check-change-note.yml
index 3330e6e1136..70b78ce7294 100644
--- a/.github/workflows/check-change-note.yml
+++ b/.github/workflows/check-change-note.yml
@@ -16,7 +16,6 @@ on:
- "shared/**/*.qll"
- "!**/experimental/**"
- "!ql/**"
- - "!rust/**"
- ".github/workflows/check-change-note.yml"
jobs:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index ced5d5021ca..e8eed93499f 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -9,7 +9,7 @@ repos:
- id: trailing-whitespace
exclude: /test/.*$(? ...
+
+# The script will modify the files in place and print the changes made.
+# The script is designed to be run from the root of the repository.
+
+#!/usr/bin/python3
+import sys
+import os
+import re
+from difflib import context_diff
+
+OVERLAY_PATTERN = re.compile(r'overlay\[[a-zA-Z?_-]+\]')
+
+def has_overlay_annotations(lines):
+ '''
+ Check whether the given lines contain any overlay[...] annotations.
+ '''
+ return any(OVERLAY_PATTERN.search(line) for line in lines)
+
+
+def is_line_comment(line):
+ return line.startswith("//") or (line.startswith("/*") and line.endswith("*/"))
+
+
+def find_file_level_module_declaration(lines):
+ '''
+ Returns the index of the existing file-level module declaration if one
+ exists. Returns None otherwise.
+ '''
+ comment = False
+ for i, line in enumerate(lines):
+ trimmed = line.strip()
+
+ if is_line_comment(trimmed):
+ continue
+ elif trimmed.startswith("/*"):
+ comment = True
+ elif comment and trimmed.endswith("*/"):
+ comment = False
+ elif not comment and trimmed.endswith("module;"):
+ return i
+
+ return None
+
+
+def is_file_module_qldoc(i, lines):
+ '''
+ Assuming a qldoc ended on line i, determine if it belongs to the implicit
+ file-level module. If it is followed by another qldoc or imports, then it
+ does and if it is followed by any other non-empty, non-comment lines, then
+ we assume that is a declaration of some kind and the qldoc is attached to
+ that declaration.
+ '''
+ comment = False
+
+ for line in lines[i+1:]:
+ trimmed = line.strip()
+
+ if trimmed.startswith("import ") or trimmed.startswith("private import ") or trimmed.startswith("/**"):
+ return True
+ elif is_line_comment(trimmed) or not trimmed:
+ continue
+ elif trimmed.startswith("/*"):
+ comment = True
+ elif comment and trimmed.endswith("*/"):
+ comment = False
+ elif not comment and trimmed:
+ return False
+
+ return True
+
+
+def find_file_module_qldoc_declaration(lines):
+ '''
+ Returns the index of last line of the implicit file module qldoc if one
+ exists. Returns None otherwise.
+ '''
+
+ qldoc = False
+ comment = False
+ for i, line in enumerate(lines):
+ trimmed = line.strip()
+
+ if trimmed.startswith("//"):
+ continue
+ elif (qldoc or trimmed.startswith("/**")) and trimmed.endswith("*/"):
+ # a qldoc just ended; determine if it belongs to the implicit file module
+ if is_file_module_qldoc(i, lines):
+ return i
+ else:
+ return None
+ elif trimmed.startswith("/**"):
+ qldoc = True
+ elif trimmed.startswith("/*"):
+ comment = True
+ elif comment and trimmed.endswith("*/"):
+ comment = False
+ elif (not qldoc and not comment) and trimmed:
+ return None
+
+ return None
+
+
+def only_comments(lines):
+ '''
+ Returns true if the lines contain only comments and empty lines.
+ '''
+ comment = False
+
+ for line in lines:
+ trimmed = line.strip()
+
+ if not trimmed or is_line_comment(trimmed):
+ continue
+ elif trimmed.startswith("/*"):
+ comment = True
+ elif comment and trimmed.endswith("*/"):
+ comment = False
+ elif comment:
+ continue
+ elif trimmed:
+ return False
+
+ return True
+
+
+def insert_toplevel_maybe_local_annotation(filename, lines):
+ '''
+ Find a suitable place to insert an overlay[local?] annotation at the top of the file.
+ Returns a pair consisting of description and the modified lines or None if no overlay
+ annotation is necessary (e.g., for files that only contain comments).
+ '''
+ if only_comments(lines):
+ return None
+
+ i = find_file_level_module_declaration(lines)
+ if not i == None:
+ out_lines = lines[:i]
+ out_lines.append("overlay[local?]\n")
+ out_lines.extend(lines[i:])
+ return (f"Annotating \"{filename}\" via existing file-level module statement", out_lines)
+
+ i = find_file_module_qldoc_declaration(lines)
+ if not i == None:
+ out_lines = lines[:i+1]
+ out_lines.append("overlay[local?]\n")
+ out_lines.append("module;\n")
+ out_lines.extend(lines[i+1:])
+ return (f"Annotating \"{filename}\" which has a file-level module qldoc", out_lines)
+
+ out_lines = ["overlay[local?]\n", "module;\n", "\n"] + lines
+ return (f"Annotating \"{filename}\" without file-level module qldoc", out_lines)
+
+
+def insert_overlay_caller_annotations(lines):
+ '''
+ Mark pragma[inline] predicates as overlay[caller?] if they are not declared private.
+ '''
+ out_lines = []
+ for i, line in enumerate(lines):
+ trimmed = line.strip()
+ if trimmed == "pragma[inline]":
+ if i + 1 < len(lines) and not "private" in lines[i+1]:
+ whitespace = line[0: line.find(trimmed)]
+ out_lines.append(f"{whitespace}overlay[caller?]\n")
+ out_lines.append(line)
+ return out_lines
+
+
+def annotate_as_appropriate(filename, lines):
+ '''
+ Insert new overlay[...] annotations according to heuristics in files without existing
+ overlay annotations.
+
+ Returns None if no annotations are needed. Otherwise, returns a pair consisting of a
+ string describing the action taken and the modified content as a list of lines.
+ '''
+ if has_overlay_annotations(lines):
+ return None
+
+ # These simple heuristics filter out those .qll files that we no _not_ want to annotate
+ # as overlay[local?]. It is not clear that these heuristics are exactly what we want,
+ # but they seem to work well enough for now (as determined by speed and accuracy numbers).
+ if (filename.endswith("Test.qll") or
+ ((filename.endswith("Query.qll") or filename.endswith("Config.qll")) and
+ any("implements DataFlow::ConfigSig" in line for line in lines))):
+ return None
+ elif not any(line for line in lines if line.strip()):
+ return None
+
+ lines = insert_overlay_caller_annotations(lines)
+ return insert_toplevel_maybe_local_annotation(filename, lines)
+
+
+def process_single_file(write, filename):
+ '''
+ Process a single file, annotating it as appropriate.
+ If write is set, the changes are written back to the file.
+ Returns True if the file requires changes.
+ '''
+ with open(filename) as f:
+ old = [line for line in f]
+
+ annotate_result = annotate_as_appropriate(filename, old)
+ if annotate_result is None:
+ return False
+
+ if not write:
+ return True
+
+ new = annotate_result[1]
+
+ diff = context_diff(old, new, fromfile=filename, tofile=filename)
+ diff = [line for line in diff]
+ if diff:
+ print(annotate_result[0])
+ for line in diff:
+ print(line.rstrip())
+ with open(filename, "w") as out_file:
+ for line in new:
+ out_file.write(line)
+
+ return True
+
+
+if len(sys.argv) > 1 and sys.argv[1] == "--check":
+ check = True
+ langs = sys.argv[2:]
+else:
+ check = False
+ langs = sys.argv[1:]
+
+dirs = []
+for lang in langs:
+ if lang in ["cpp", "go", "csharp", "java", "javascript", "python", "ruby", "rust", "swift"]:
+ dirs.append(f"{lang}/ql/lib")
+ else:
+ raise Exception(f"Unknown language \"{lang}\".")
+
+if dirs:
+ dirs.append("shared")
+
+missingAnnotations = []
+
+for roots in dirs:
+ for dirpath, dirnames, filenames in os.walk(roots):
+ for filename in filenames:
+ if filename.endswith(".qll") and not dirpath.endswith("tutorial"):
+ path = os.path.join(dirpath, filename)
+ res = process_single_file(not check, path)
+ if check and res:
+ missingAnnotations.append(path)
+
+
+if len(missingAnnotations) > 0:
+ print("The following files have no overlay annotations:")
+ for path in missingAnnotations[:10]:
+ print("- " + path)
+ if len(missingAnnotations) > 10:
+ print("and " + str(len(missingAnnotations) - 10) + " additional files.")
+ print()
+ print("Please manually add overlay annotations or use the config/add-overlay-annotations.py script to automatically add sensible default overlay annotations.")
+ exit(1)
diff --git a/config/opcode-qldoc.py b/config/opcode-qldoc.py
index e379e6a3ea9..1c892ee3c85 100644
--- a/config/opcode-qldoc.py
+++ b/config/opcode-qldoc.py
@@ -8,9 +8,9 @@ needs_an_re = re.compile(r'^(?!Unary)[AEIOU]') # Name requiring "an" instead of
start_qldoc_re = re.compile(r'^\s*/\*\*') # Start of a QLDoc comment
end_qldoc_re = re.compile(r'\*/\s*$') # End of a QLDoc comment
blank_qldoc_line_re = re.compile(r'^\s*\*\s*$') # A line in a QLDoc comment with only the '*'
-instruction_class_re = re.compile(r'^class (?P[A-aa-z0-9]+)Instruction\s') # Declaration of an `Instruction` class
-opcode_base_class_re = re.compile(r'^abstract class (?P[A-aa-z0-9]+)Opcode\s') # Declaration of an `Opcode` base class
-opcode_class_re = re.compile(r'^ class (?P[A-aa-z0-9]+)\s') # Declaration of an `Opcode` class
+instruction_class_re = re.compile(r'^class (?P[A-Za-z0-9]+)Instruction\s') # Declaration of an `Instruction` class
+opcode_base_class_re = re.compile(r'^abstract class (?P[A-Za-z0-9]+)Opcode\s') # Declaration of an `Opcode` base class
+opcode_class_re = re.compile(r'^ class (?P[A-Za-z0-9]+)\s') # Declaration of an `Opcode` class
script_dir = path.realpath(path.dirname(__file__))
instruction_path = path.realpath(path.join(script_dir, '../cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll'))
diff --git a/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/builtintypes.ql b/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/builtintypes.ql
new file mode 100644
index 00000000000..9088493ce34
--- /dev/null
+++ b/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/builtintypes.ql
@@ -0,0 +1,14 @@
+class BuiltinType extends @builtintype {
+ string toString() { none() }
+}
+
+from BuiltinType type, string name, int kind, int kind_new, int size, int sign, int alignment
+where
+ builtintypes(type, name, kind, size, sign, alignment) and
+ if
+ type instanceof @complex_fp16 or
+ type instanceof @complex_std_bfloat16 or
+ type instanceof @complex_std_float16
+ then kind_new = 2
+ else kind_new = kind
+select type, name, kind_new, size, sign, alignment
diff --git a/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/old.dbscheme b/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/old.dbscheme
new file mode 100644
index 00000000000..7bc12b02a43
--- /dev/null
+++ b/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/old.dbscheme
@@ -0,0 +1,2509 @@
+
+/**
+ * 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
+);
+
+/**
+ * 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, 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
+);
+
+/**
+ * The source location of the snapshot.
+ */
+sourceLocationPrefix(string prefix : string ref);
+
+/**
+ * Information about packages that provide code used during compilation.
+ * The `id` is just a unique identifier.
+ * The `namespace` is typically the name of the package manager that
+ * provided the package (e.g. "dpkg" or "yum").
+ * The `package_name` is the name of the package, and `version` is its
+ * version (as a string).
+ */
+external_packages(
+ unique int id: @external_package,
+ string namespace : string ref,
+ string package_name : string ref,
+ string version : string ref
+);
+
+/**
+ * Holds if File `fileid` was provided by package `package`.
+ */
+header_to_external_package(
+ int fileid : @file ref,
+ int package : @external_package ref
+);
+
+/*
+ * Version history
+ */
+
+svnentries(
+ unique int id : @svnentry,
+ string revision : string ref,
+ string author : string ref,
+ date revisionDate : date ref,
+ int changeSize : int ref
+)
+
+svnaffectedfiles(
+ int id : @svnentry ref,
+ int file : @file ref,
+ string action : string ref
+)
+
+svnentrymsg(
+ unique int id : @svnentry ref,
+ string message : string ref
+)
+
+svnchurn(
+ int commit : @svnentry ref,
+ int file : @file ref,
+ int addedLines : int ref,
+ int deletedLines : int ref
+)
+
+/*
+ * C++ dbscheme
+ */
+
+extractor_version(
+ string codeql_version: string ref,
+ string frontend_version: string ref
+)
+
+@location = @location_stmt | @location_expr | @location_default ;
+
+/**
+ * The location of an element that is not an expression or a statement.
+ * 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(
+ /** The location of an element that is not an expression or a statement. */
+ unique int id: @location_default,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/**
+ * The location of a statement.
+ * 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_stmt(
+ /** The location of a statement. */
+ unique int id: @location_stmt,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/**
+ * The location of an expression.
+ * 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_expr(
+ /** The location of an expression. */
+ unique int id: @location_expr,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/** An element for which line-count information is available. */
+@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref
+);
+
+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
+);
+
+files(
+ unique int id: @file,
+ string name: string ref
+);
+
+folders(
+ unique int id: @folder,
+ string name: string ref
+);
+
+@container = @folder | @file
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref
+);
+
+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 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
+ 1 = @normal_function
+| 2 = @constructor
+| 3 = @destructor
+| 4 = @conversion_function
+| 5 = @operator
+| 6 = @builtin_function // 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
+);
+
+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 // _Decimal32
+| 41 = @decimal64 // _Decimal64
+| 42 = @decimal128 // _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 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;
+
+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_expr 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_expr 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
+;
+
+@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
+ ;
+
+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
+);
+
+/**
+ * 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_stmt 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
+| 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
+);
+
+link_targets(
+ int id: @link_target,
+ int binary: @file ref
+);
+
+link_parent(
+ int element : @element ref,
+ int link_target : @link_target 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;
diff --git a/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/semmlecode.cpp.dbscheme b/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/semmlecode.cpp.dbscheme
new file mode 100644
index 00000000000..e3834605178
--- /dev/null
+++ b/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/semmlecode.cpp.dbscheme
@@ -0,0 +1,2506 @@
+
+/**
+ * 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
+);
+
+/**
+ * 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, 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
+);
+
+/**
+ * The source location of the snapshot.
+ */
+sourceLocationPrefix(string prefix : string ref);
+
+/**
+ * Information about packages that provide code used during compilation.
+ * The `id` is just a unique identifier.
+ * The `namespace` is typically the name of the package manager that
+ * provided the package (e.g. "dpkg" or "yum").
+ * The `package_name` is the name of the package, and `version` is its
+ * version (as a string).
+ */
+external_packages(
+ unique int id: @external_package,
+ string namespace : string ref,
+ string package_name : string ref,
+ string version : string ref
+);
+
+/**
+ * Holds if File `fileid` was provided by package `package`.
+ */
+header_to_external_package(
+ int fileid : @file ref,
+ int package : @external_package ref
+);
+
+/*
+ * Version history
+ */
+
+svnentries(
+ unique int id : @svnentry,
+ string revision : string ref,
+ string author : string ref,
+ date revisionDate : date ref,
+ int changeSize : int ref
+)
+
+svnaffectedfiles(
+ int id : @svnentry ref,
+ int file : @file ref,
+ string action : string ref
+)
+
+svnentrymsg(
+ unique int id : @svnentry ref,
+ string message : string ref
+)
+
+svnchurn(
+ int commit : @svnentry ref,
+ int file : @file ref,
+ int addedLines : int ref,
+ int deletedLines : int ref
+)
+
+/*
+ * C++ dbscheme
+ */
+
+extractor_version(
+ string codeql_version: string ref,
+ string frontend_version: string ref
+)
+
+@location = @location_stmt | @location_expr | @location_default ;
+
+/**
+ * The location of an element that is not an expression or a statement.
+ * 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(
+ /** The location of an element that is not an expression or a statement. */
+ unique int id: @location_default,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/**
+ * The location of a statement.
+ * 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_stmt(
+ /** The location of a statement. */
+ unique int id: @location_stmt,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/**
+ * The location of an expression.
+ * 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_expr(
+ /** The location of an expression. */
+ unique int id: @location_expr,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/** An element for which line-count information is available. */
+@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref
+);
+
+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
+);
+
+files(
+ unique int id: @file,
+ string name: string ref
+);
+
+folders(
+ unique int id: @folder,
+ string name: string ref
+);
+
+@container = @folder | @file
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref
+);
+
+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 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
+ 1 = @normal_function
+| 2 = @constructor
+| 3 = @destructor
+| 4 = @conversion_function
+| 5 = @operator
+| 6 = @builtin_function // 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
+);
+
+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 // _Decimal32
+| 41 = @decimal64 // _Decimal64
+| 42 = @decimal128 // _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
+;
+
+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 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;
+
+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_expr 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_expr 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
+;
+
+@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
+ ;
+
+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
+);
+
+/**
+ * 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_stmt 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
+| 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
+);
+
+link_targets(
+ int id: @link_target,
+ int binary: @file ref
+);
+
+link_parent(
+ int element : @element ref,
+ int link_target : @link_target 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;
diff --git a/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/upgrade.properties b/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/upgrade.properties
new file mode 100644
index 00000000000..c8d1d2d3c3a
--- /dev/null
+++ b/cpp/downgrades/7bc12b02a4363149f0727a4bce07952dbb9d98aa/upgrade.properties
@@ -0,0 +1,3 @@
+description: Introduce new complex 16-bit floating-point types
+compatibility: backwards
+builtintypes.rel: run builtintypes.qlo
diff --git a/cpp/ql/lib/CHANGELOG.md b/cpp/ql/lib/CHANGELOG.md
index c46ab004464..392305a6489 100644
--- a/cpp/ql/lib/CHANGELOG.md
+++ b/cpp/ql/lib/CHANGELOG.md
@@ -1,3 +1,20 @@
+## 5.2.0
+
+### Deprecated APIs
+
+* The `ThrowingFunction` class (`semmle.code.cpp.models.interfaces.Throwing`) has been deprecated. Please use the `AlwaysSehThrowingFunction` class instead.
+
+### New Features
+
+* Added a predicate `getAnAttribute` to `Namespace` to retrieve a namespace attribute.
+* The Microsoft-specific `__leave` statement is now supported.
+* A new class `LeaveStmt` extending `JumpStmt` was added to represent `__leave` statements.
+* Added a predicate `hasParameterList` to `LambdaExpression` to capture whether a lambda has an explicitly specified parameter list.
+
+### Bug Fixes
+
+* `resolveTypedefs` now properly resolves typedefs for `ArrayType`s.
+
## 5.1.0
### New Features
diff --git a/cpp/ql/lib/change-notes/2014-12-13-deprecate-throwing.md b/cpp/ql/lib/change-notes/2014-12-13-deprecate-throwing.md
deleted file mode 100644
index 9a46cc7da8f..00000000000
--- a/cpp/ql/lib/change-notes/2014-12-13-deprecate-throwing.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: deprecated
----
-* The `ThrowingFunction` class (`semmle.code.cpp.models.interfaces.Throwing`) has been deprecated. Please use the `AlwaysSehThrowingFunction` class instead.
diff --git a/cpp/ql/lib/change-notes/2025-06-06-lambda-parameters.md b/cpp/ql/lib/change-notes/2025-06-06-lambda-parameters.md
deleted file mode 100644
index 44f9b12968d..00000000000
--- a/cpp/ql/lib/change-notes/2025-06-06-lambda-parameters.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: feature
----
-* Added a predicate `hasParameterList` to `LambdaExpression` to capture whether a lambda has an explicitly specified parameter list.
diff --git a/cpp/ql/lib/change-notes/2025-06-11-leave-stmt.md b/cpp/ql/lib/change-notes/2025-06-11-leave-stmt.md
deleted file mode 100644
index d06be5b77a9..00000000000
--- a/cpp/ql/lib/change-notes/2025-06-11-leave-stmt.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-category: feature
----
-* The Microsoft-specific `__leave` statement is now supported.
-* A new class `LeaveStmt` extending `JumpStmt` was added to represent `__leave` statements.
\ No newline at end of file
diff --git a/cpp/ql/lib/change-notes/2025-06-16-namespace-attributes.md b/cpp/ql/lib/change-notes/2025-06-16-namespace-attributes.md
deleted file mode 100644
index cbed27e109c..00000000000
--- a/cpp/ql/lib/change-notes/2025-06-16-namespace-attributes.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: feature
----
-* Added a predicate `getAnAttribute` to `Namespace` to retrieve a namespace attribute.
diff --git a/cpp/ql/lib/change-notes/2025-06-17-arraytype-typedefs.md b/cpp/ql/lib/change-notes/2025-06-17-arraytype-typedefs.md
deleted file mode 100644
index 0bc3130e6a3..00000000000
--- a/cpp/ql/lib/change-notes/2025-06-17-arraytype-typedefs.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: fix
----
-* `resolveTypedefs` now properly resolves typedefs for `ArrayType`s.
diff --git a/cpp/ql/lib/change-notes/2025-06-24-float16.md b/cpp/ql/lib/change-notes/2025-06-24-float16.md
new file mode 100644
index 00000000000..24737d2b406
--- /dev/null
+++ b/cpp/ql/lib/change-notes/2025-06-24-float16.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* Added support for `__fp16 _Complex` and `__bf16 _Complex` types
diff --git a/cpp/ql/lib/change-notes/released/5.2.0.md b/cpp/ql/lib/change-notes/released/5.2.0.md
new file mode 100644
index 00000000000..a55198c1086
--- /dev/null
+++ b/cpp/ql/lib/change-notes/released/5.2.0.md
@@ -0,0 +1,16 @@
+## 5.2.0
+
+### Deprecated APIs
+
+* The `ThrowingFunction` class (`semmle.code.cpp.models.interfaces.Throwing`) has been deprecated. Please use the `AlwaysSehThrowingFunction` class instead.
+
+### New Features
+
+* Added a predicate `getAnAttribute` to `Namespace` to retrieve a namespace attribute.
+* The Microsoft-specific `__leave` statement is now supported.
+* A new class `LeaveStmt` extending `JumpStmt` was added to represent `__leave` statements.
+* Added a predicate `hasParameterList` to `LambdaExpression` to capture whether a lambda has an explicitly specified parameter list.
+
+### Bug Fixes
+
+* `resolveTypedefs` now properly resolves typedefs for `ArrayType`s.
diff --git a/cpp/ql/lib/codeql-pack.release.yml b/cpp/ql/lib/codeql-pack.release.yml
index dd8d287d010..9e57a36a7dc 100644
--- a/cpp/ql/lib/codeql-pack.release.yml
+++ b/cpp/ql/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 5.1.0
+lastReleaseVersion: 5.2.0
diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml
index c0dd5d2ae2a..e826864ae64 100644
--- a/cpp/ql/lib/qlpack.yml
+++ b/cpp/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/cpp-all
-version: 5.1.1-dev
+version: 5.2.1-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp
diff --git a/cpp/ql/lib/semmle/code/cpp/Type.qll b/cpp/ql/lib/semmle/code/cpp/Type.qll
index f866d9f77e2..0256349972b 100644
--- a/cpp/ql/lib/semmle/code/cpp/Type.qll
+++ b/cpp/ql/lib/semmle/code/cpp/Type.qll
@@ -858,6 +858,15 @@ private predicate floatingPointTypeMapping(
or
// __mfp8
kind = 62 and base = 2 and domain = TRealDomain() and realKind = 62 and extended = false
+ or
+ // _Complex __fp16
+ kind = 64 and base = 2 and domain = TComplexDomain() and realKind = 54 and extended = false
+ or
+ // _Complex __bf16
+ kind = 65 and base = 2 and domain = TComplexDomain() and realKind = 55 and extended = false
+ or
+ // _Complex std::float16_t
+ kind = 66 and base = 2 and domain = TComplexDomain() and realKind = 56 and extended = false
}
/**
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll
index 1b63322610a..00863781257 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll
@@ -54,6 +54,8 @@ private predicate isDeeplyConstBelow(Type t) {
or
isDeeplyConst(t.(GNUVectorType).getBaseType())
or
+ isDeeplyConst(t.(ScalableVectorType).getBaseType())
+ or
isDeeplyConst(t.(FunctionPointerIshType).getBaseType())
or
isDeeplyConst(t.(PointerWrapper).getTemplateArgument(0))
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll b/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll
index d873e3ec757..b25bb041f33 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll
@@ -29,6 +29,10 @@ private int getTypeSizeWorkaround(Type type) {
not arrayType.hasArraySize() and
result = getPointerSize()
)
+ or
+ // Scalable vectors are opaque and not of fixed size. Use 0 as a substitute.
+ type instanceof ScalableVectorType and
+ result = 0
)
)
}
@@ -136,6 +140,8 @@ private predicate isOpaqueType(Type type) {
type instanceof PointerToMemberType // PTMs are missing size info
or
type instanceof ScalableVectorCount
+ or
+ type instanceof ScalableVectorType
}
/**
diff --git a/cpp/ql/lib/semmlecode.cpp.dbscheme b/cpp/ql/lib/semmlecode.cpp.dbscheme
index e3834605178..7bc12b02a43 100644
--- a/cpp/ql/lib/semmlecode.cpp.dbscheme
+++ b/cpp/ql/lib/semmlecode.cpp.dbscheme
@@ -693,6 +693,9 @@ case @builtintype.kind of
| 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(
diff --git a/cpp/ql/lib/semmlecode.cpp.dbscheme.stats b/cpp/ql/lib/semmlecode.cpp.dbscheme.stats
index dc51cf5b218..696e1ac9e41 100644
--- a/cpp/ql/lib/semmlecode.cpp.dbscheme.stats
+++ b/cpp/ql/lib/semmlecode.cpp.dbscheme.stats
@@ -336,6 +336,18 @@
@scalable_vector_count
124
+
+ @complex_fp16
+ 124
+
+
+ @complex_std_bfloat16
+ 124
+
+
+ @complex_std_float16
+ 124
+
@pointer
455609
diff --git a/cpp/ql/lib/upgrades/e38346051783182ea75822e4adf8d4c6a949bc37/old.dbscheme b/cpp/ql/lib/upgrades/e38346051783182ea75822e4adf8d4c6a949bc37/old.dbscheme
new file mode 100644
index 00000000000..e3834605178
--- /dev/null
+++ b/cpp/ql/lib/upgrades/e38346051783182ea75822e4adf8d4c6a949bc37/old.dbscheme
@@ -0,0 +1,2506 @@
+
+/**
+ * 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
+);
+
+/**
+ * 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, 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
+);
+
+/**
+ * The source location of the snapshot.
+ */
+sourceLocationPrefix(string prefix : string ref);
+
+/**
+ * Information about packages that provide code used during compilation.
+ * The `id` is just a unique identifier.
+ * The `namespace` is typically the name of the package manager that
+ * provided the package (e.g. "dpkg" or "yum").
+ * The `package_name` is the name of the package, and `version` is its
+ * version (as a string).
+ */
+external_packages(
+ unique int id: @external_package,
+ string namespace : string ref,
+ string package_name : string ref,
+ string version : string ref
+);
+
+/**
+ * Holds if File `fileid` was provided by package `package`.
+ */
+header_to_external_package(
+ int fileid : @file ref,
+ int package : @external_package ref
+);
+
+/*
+ * Version history
+ */
+
+svnentries(
+ unique int id : @svnentry,
+ string revision : string ref,
+ string author : string ref,
+ date revisionDate : date ref,
+ int changeSize : int ref
+)
+
+svnaffectedfiles(
+ int id : @svnentry ref,
+ int file : @file ref,
+ string action : string ref
+)
+
+svnentrymsg(
+ unique int id : @svnentry ref,
+ string message : string ref
+)
+
+svnchurn(
+ int commit : @svnentry ref,
+ int file : @file ref,
+ int addedLines : int ref,
+ int deletedLines : int ref
+)
+
+/*
+ * C++ dbscheme
+ */
+
+extractor_version(
+ string codeql_version: string ref,
+ string frontend_version: string ref
+)
+
+@location = @location_stmt | @location_expr | @location_default ;
+
+/**
+ * The location of an element that is not an expression or a statement.
+ * 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(
+ /** The location of an element that is not an expression or a statement. */
+ unique int id: @location_default,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/**
+ * The location of a statement.
+ * 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_stmt(
+ /** The location of a statement. */
+ unique int id: @location_stmt,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/**
+ * The location of an expression.
+ * 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_expr(
+ /** The location of an expression. */
+ unique int id: @location_expr,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/** An element for which line-count information is available. */
+@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref
+);
+
+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
+);
+
+files(
+ unique int id: @file,
+ string name: string ref
+);
+
+folders(
+ unique int id: @folder,
+ string name: string ref
+);
+
+@container = @folder | @file
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref
+);
+
+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 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
+ 1 = @normal_function
+| 2 = @constructor
+| 3 = @destructor
+| 4 = @conversion_function
+| 5 = @operator
+| 6 = @builtin_function // 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
+);
+
+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 // _Decimal32
+| 41 = @decimal64 // _Decimal64
+| 42 = @decimal128 // _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
+;
+
+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 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;
+
+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_expr 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_expr 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
+;
+
+@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
+ ;
+
+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
+);
+
+/**
+ * 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_stmt 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
+| 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
+);
+
+link_targets(
+ int id: @link_target,
+ int binary: @file ref
+);
+
+link_parent(
+ int element : @element ref,
+ int link_target : @link_target 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;
diff --git a/cpp/ql/lib/upgrades/e38346051783182ea75822e4adf8d4c6a949bc37/semmlecode.cpp.dbscheme b/cpp/ql/lib/upgrades/e38346051783182ea75822e4adf8d4c6a949bc37/semmlecode.cpp.dbscheme
new file mode 100644
index 00000000000..7bc12b02a43
--- /dev/null
+++ b/cpp/ql/lib/upgrades/e38346051783182ea75822e4adf8d4c6a949bc37/semmlecode.cpp.dbscheme
@@ -0,0 +1,2509 @@
+
+/**
+ * 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
+);
+
+/**
+ * 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, 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
+);
+
+/**
+ * The source location of the snapshot.
+ */
+sourceLocationPrefix(string prefix : string ref);
+
+/**
+ * Information about packages that provide code used during compilation.
+ * The `id` is just a unique identifier.
+ * The `namespace` is typically the name of the package manager that
+ * provided the package (e.g. "dpkg" or "yum").
+ * The `package_name` is the name of the package, and `version` is its
+ * version (as a string).
+ */
+external_packages(
+ unique int id: @external_package,
+ string namespace : string ref,
+ string package_name : string ref,
+ string version : string ref
+);
+
+/**
+ * Holds if File `fileid` was provided by package `package`.
+ */
+header_to_external_package(
+ int fileid : @file ref,
+ int package : @external_package ref
+);
+
+/*
+ * Version history
+ */
+
+svnentries(
+ unique int id : @svnentry,
+ string revision : string ref,
+ string author : string ref,
+ date revisionDate : date ref,
+ int changeSize : int ref
+)
+
+svnaffectedfiles(
+ int id : @svnentry ref,
+ int file : @file ref,
+ string action : string ref
+)
+
+svnentrymsg(
+ unique int id : @svnentry ref,
+ string message : string ref
+)
+
+svnchurn(
+ int commit : @svnentry ref,
+ int file : @file ref,
+ int addedLines : int ref,
+ int deletedLines : int ref
+)
+
+/*
+ * C++ dbscheme
+ */
+
+extractor_version(
+ string codeql_version: string ref,
+ string frontend_version: string ref
+)
+
+@location = @location_stmt | @location_expr | @location_default ;
+
+/**
+ * The location of an element that is not an expression or a statement.
+ * 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(
+ /** The location of an element that is not an expression or a statement. */
+ unique int id: @location_default,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/**
+ * The location of a statement.
+ * 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_stmt(
+ /** The location of a statement. */
+ unique int id: @location_stmt,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/**
+ * The location of an expression.
+ * 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_expr(
+ /** The location of an expression. */
+ unique int id: @location_expr,
+ int container: @container ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref
+);
+
+/** An element for which line-count information is available. */
+@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref
+);
+
+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
+);
+
+files(
+ unique int id: @file,
+ string name: string ref
+);
+
+folders(
+ unique int id: @folder,
+ string name: string ref
+);
+
+@container = @folder | @file
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref
+);
+
+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 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
+ 1 = @normal_function
+| 2 = @constructor
+| 3 = @destructor
+| 4 = @conversion_function
+| 5 = @operator
+| 6 = @builtin_function // 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
+);
+
+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 // _Decimal32
+| 41 = @decimal64 // _Decimal64
+| 42 = @decimal128 // _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 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;
+
+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_expr 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_expr 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
+;
+
+@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
+ ;
+
+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
+);
+
+/**
+ * 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_stmt 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
+| 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
+);
+
+link_targets(
+ int id: @link_target,
+ int binary: @file ref
+);
+
+link_parent(
+ int element : @element ref,
+ int link_target : @link_target 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;
diff --git a/cpp/ql/lib/upgrades/e38346051783182ea75822e4adf8d4c6a949bc37/upgrade.properties b/cpp/ql/lib/upgrades/e38346051783182ea75822e4adf8d4c6a949bc37/upgrade.properties
new file mode 100644
index 00000000000..03985f017e3
--- /dev/null
+++ b/cpp/ql/lib/upgrades/e38346051783182ea75822e4adf8d4c6a949bc37/upgrade.properties
@@ -0,0 +1,2 @@
+description: Support more complex 16-bit floating-point types
+compatibility: full
diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md
index 4edd493015a..7fc5b0d92bd 100644
--- a/cpp/ql/src/CHANGELOG.md
+++ b/cpp/ql/src/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 1.4.3
+
+### Minor Analysis Improvements
+
+* Added flow model for the following libraries: `madler/zlib`, `google/brotli`, `libidn/libidn2`, `libssh2/libssh2/`, `nghttp2/nghttp2`, `libuv/libuv/`, and `curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
+
## 1.4.2
No user-facing changes.
diff --git a/cpp/ql/src/change-notes/2025-06-13-mad-summaries.md b/cpp/ql/src/change-notes/released/1.4.3.md
similarity index 84%
rename from cpp/ql/src/change-notes/2025-06-13-mad-summaries.md
rename to cpp/ql/src/change-notes/released/1.4.3.md
index f70b9037cd4..2280196429b 100644
--- a/cpp/ql/src/change-notes/2025-06-13-mad-summaries.md
+++ b/cpp/ql/src/change-notes/released/1.4.3.md
@@ -1,4 +1,5 @@
----
-category: minorAnalysis
----
-* Added flow model for the following libraries: `madler/zlib`, `google/brotli`, `libidn/libidn2`, `libssh2/libssh2/`, `nghttp2/nghttp2`, `libuv/libuv/`, and `curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
\ No newline at end of file
+## 1.4.3
+
+### Minor Analysis Improvements
+
+* Added flow model for the following libraries: `madler/zlib`, `google/brotli`, `libidn/libidn2`, `libssh2/libssh2/`, `nghttp2/nghttp2`, `libuv/libuv/`, and `curl/curl`. This may result in more alerts when running queries on codebases that use these libraries.
diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml
index a76cacdf799..08f88b689fb 100644
--- a/cpp/ql/src/codeql-pack.release.yml
+++ b/cpp/ql/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.4.2
+lastReleaseVersion: 1.4.3
diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml
index 290c18cb815..ade2daeb369 100644
--- a/cpp/ql/src/qlpack.yml
+++ b/cpp/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/cpp-queries
-version: 1.4.3-dev
+version: 1.4.4-dev
groups:
- cpp
- queries
diff --git a/cpp/ql/test/library-tests/floats/float128/usertypes.ql b/cpp/ql/test/library-tests/floats/float128/usertypes.ql
index d3677562532..2b85c9519ab 100644
--- a/cpp/ql/test/library-tests/floats/float128/usertypes.ql
+++ b/cpp/ql/test/library-tests/floats/float128/usertypes.ql
@@ -2,6 +2,9 @@ import cpp
from UserType t, Type related
where
- related = t.(Class).getABaseClass() or
- related = t.(TypedefType).getUnderlyingType()
+ (
+ related = t.(Class).getABaseClass() or
+ related = t.(TypedefType).getUnderlyingType()
+ ) and
+ exists(t.getFile())
select t, related
diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected
index d3ef1de1e13..53ebaf2114f 100644
--- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected
+++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected
@@ -58,7 +58,7 @@
#-----| Type = [LongType] unsigned long
#-----| getParameter(1): [Parameter] (unnamed parameter 1)
#-----| Type = [ScopedEnum] align_val_t
-arm.cpp:
+arm_neon.cpp:
# 6| [TopLevelFunction] uint8x8_t vadd_u8(uint8x8_t, uint8x8_t)
# 6| :
# 6| getParameter(0): [Parameter] a
@@ -76,59 +76,105 @@ arm.cpp:
# 7| getRightOperand(): [VariableAccess] b
# 7| Type = [CTypedefType] uint8x8_t
# 7| ValueCategory = prvalue(load)
-# 12| [TopLevelFunction] uint16x8_t __builtin_aarch64_uaddlv8qi_uuu(uint8x8_t, uint8x8_t)
+# 10| [TopLevelFunction] uint16x8_t vaddl_u8(uint8x8_t, uint8x8_t)
+# 10| :
+# 10| getParameter(0): [Parameter] a
+# 10| Type = [CTypedefType] uint8x8_t
+# 10| getParameter(1): [Parameter] b
+# 10| Type = [CTypedefType] uint8x8_t
+# 12| [TopLevelFunction] uint16x8_t arm_add(uint8x8_t, uint8x8_t*)
# 12| :
-# 12| getParameter(0): [Parameter] (unnamed parameter 0)
+# 12| getParameter(0): [Parameter] a
# 12| Type = [CTypedefType] uint8x8_t
-# 12| getParameter(1): [Parameter] (unnamed parameter 1)
-# 12| Type = [CTypedefType] uint8x8_t
-# 14| [TopLevelFunction] uint16x8_t vaddl_u8(uint8x8_t, uint8x8_t)
-# 14| :
-# 14| getParameter(0): [Parameter] a
-# 14| Type = [CTypedefType] uint8x8_t
-# 14| getParameter(1): [Parameter] b
-# 14| Type = [CTypedefType] uint8x8_t
-# 14| getEntryPoint(): [BlockStmt] { ... }
-# 15| getStmt(0): [ReturnStmt] return ...
-# 15| getExpr(): [FunctionCall] call to __builtin_aarch64_uaddlv8qi_uuu
-# 15| Type = [CTypedefType] uint16x8_t
-# 15| ValueCategory = prvalue
-# 15| getArgument(0): [VariableAccess] a
-# 15| Type = [CTypedefType] uint8x8_t
-# 15| ValueCategory = prvalue(load)
-# 15| getArgument(1): [VariableAccess] b
-# 15| Type = [CTypedefType] uint8x8_t
-# 15| ValueCategory = prvalue(load)
-# 18| [TopLevelFunction] uint16x8_t arm_add(uint8x8_t, uint8x8_t)
-# 18| :
-# 18| getParameter(0): [Parameter] a
-# 18| Type = [CTypedefType] uint8x8_t
-# 18| getParameter(1): [Parameter] b
-# 18| Type = [CTypedefType] uint8x8_t
-# 18| getEntryPoint(): [BlockStmt] { ... }
-# 19| getStmt(0): [DeclStmt] declaration
-# 19| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
-# 19| Type = [CTypedefType] uint8x8_t
-# 19| getVariable().getInitializer(): [Initializer] initializer for c
-# 19| getExpr(): [FunctionCall] call to vadd_u8
-# 19| Type = [CTypedefType] uint8x8_t
-# 19| ValueCategory = prvalue
-# 19| getArgument(0): [VariableAccess] a
-# 19| Type = [CTypedefType] uint8x8_t
-# 19| ValueCategory = prvalue(load)
-# 19| getArgument(1): [VariableAccess] b
-# 19| Type = [CTypedefType] uint8x8_t
-# 19| ValueCategory = prvalue(load)
-# 20| getStmt(1): [ReturnStmt] return ...
-# 20| getExpr(): [FunctionCall] call to vaddl_u8
-# 20| Type = [CTypedefType] uint16x8_t
-# 20| ValueCategory = prvalue
-# 20| getArgument(0): [VariableAccess] a
-# 20| Type = [CTypedefType] uint8x8_t
-# 20| ValueCategory = prvalue(load)
-# 20| getArgument(1): [VariableAccess] c
-# 20| Type = [CTypedefType] uint8x8_t
-# 20| ValueCategory = prvalue(load)
+# 12| getParameter(1): [Parameter] b
+# 12| Type = [PointerType] uint8x8_t *
+# 12| getEntryPoint(): [BlockStmt] { ... }
+# 13| getStmt(0): [DeclStmt] declaration
+# 13| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
+# 13| Type = [CTypedefType] uint8x8_t
+# 13| getVariable().getInitializer(): [Initializer] initializer for c
+# 13| getExpr(): [FunctionCall] call to vadd_u8
+# 13| Type = [CTypedefType] uint8x8_t
+# 13| ValueCategory = prvalue
+# 13| getArgument(0): [VariableAccess] a
+# 13| Type = [CTypedefType] uint8x8_t
+# 13| ValueCategory = prvalue(load)
+# 13| getArgument(1): [PointerDereferenceExpr] * ...
+# 13| Type = [CTypedefType] uint8x8_t
+# 13| ValueCategory = prvalue(load)
+# 13| getOperand(): [VariableAccess] b
+# 13| Type = [PointerType] uint8x8_t *
+# 13| ValueCategory = prvalue(load)
+# 14| getStmt(1): [ReturnStmt] return ...
+# 14| getExpr(): [FunctionCall] call to vaddl_u8
+# 14| Type = [CTypedefType] uint16x8_t
+# 14| ValueCategory = prvalue
+# 14| getArgument(0): [VariableAccess] a
+# 14| Type = [CTypedefType] uint8x8_t
+# 14| ValueCategory = prvalue(load)
+# 14| getArgument(1): [VariableAccess] c
+# 14| Type = [CTypedefType] uint8x8_t
+# 14| ValueCategory = prvalue(load)
+# 20| [TopLevelFunction] mfloat8x8_t vreinterpret_mf8_s8(int8x8_t)
+# 20| :
+# 20| getParameter(0): [Parameter] (unnamed parameter 0)
+# 20| Type = [CTypedefType] int8x8_t
+# 22| [TopLevelFunction] mfloat8x8_t arm_reinterpret(int8x8_t*)
+# 22| :
+# 22| getParameter(0): [Parameter] a
+# 22| Type = [PointerType] int8x8_t *
+# 22| getEntryPoint(): [BlockStmt] { ... }
+# 23| getStmt(0): [ReturnStmt] return ...
+# 23| getExpr(): [FunctionCall] call to vreinterpret_mf8_s8
+# 23| Type = [CTypedefType] mfloat8x8_t
+# 23| ValueCategory = prvalue
+# 23| getArgument(0): [PointerDereferenceExpr] * ...
+# 23| Type = [CTypedefType] int8x8_t
+# 23| ValueCategory = prvalue(load)
+# 23| getOperand(): [VariableAccess] a
+# 23| Type = [PointerType] int8x8_t *
+# 23| ValueCategory = prvalue(load)
+arm_sve.cpp:
+# 6| [TopLevelFunction] svuint8x2_t svsel_u8_x2(svcount_t, svuint8x2_t, svuint8x2_t)
+# 6| :
+# 6| getParameter(0): [Parameter] (unnamed parameter 0)
+# 6| Type = [CTypedefType] svcount_t
+# 6| getParameter(1): [Parameter] (unnamed parameter 1)
+# 6| Type = [CTypedefType] svuint8x2_t
+# 6| getParameter(2): [Parameter] (unnamed parameter 2)
+# 6| Type = [CTypedefType] svuint8x2_t
+# 8| [TopLevelFunction] svuint8x2_t arm_sel(svcount_t, svuint8x2_t, svuint8x2_t*)
+# 8| :
+# 8| getParameter(0): [Parameter] a
+# 8| Type = [CTypedefType] svcount_t
+# 8| getParameter(1): [Parameter] b
+# 8| Type = [CTypedefType] svuint8x2_t
+# 8| getParameter(2): [Parameter] c
+# 8| Type = [PointerType] svuint8x2_t *
+# 8| getEntryPoint(): [BlockStmt] { ... }
+# 9| getStmt(0): [DeclStmt] declaration
+# 9| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d
+# 9| Type = [CTypedefType] svuint8x2_t
+# 9| getVariable().getInitializer(): [Initializer] initializer for d
+# 9| getExpr(): [FunctionCall] call to svsel_u8_x2
+# 9| Type = [CTypedefType] svuint8x2_t
+# 9| ValueCategory = prvalue
+# 9| getArgument(0): [VariableAccess] a
+# 9| Type = [CTypedefType] svcount_t
+# 9| ValueCategory = prvalue(load)
+# 9| getArgument(1): [VariableAccess] b
+# 9| Type = [CTypedefType] svuint8x2_t
+# 9| ValueCategory = prvalue(load)
+# 9| getArgument(2): [PointerDereferenceExpr] * ...
+# 9| Type = [CTypedefType] svuint8x2_t
+# 9| ValueCategory = prvalue(load)
+# 9| getOperand(): [VariableAccess] c
+# 9| Type = [PointerType] svuint8x2_t *
+# 9| ValueCategory = prvalue(load)
+# 10| getStmt(1): [ReturnStmt] return ...
+# 10| getExpr(): [VariableAccess] d
+# 10| Type = [CTypedefType] svuint8x2_t
+# 10| ValueCategory = prvalue(load)
bad_asts.cpp:
# 5| [CopyAssignmentOperator] Bad::S& Bad::S::operator=(Bad::S const&)
# 5| :
@@ -10807,22 +10853,22 @@ ir.cpp:
# 885| Type = [FunctionPointerType] ..(*)(..)
# 885| ValueCategory = prvalue
# 886| getStmt(2): [ReturnStmt] return ...
-# 888| [TopLevelFunction] void VAListUsage(int, __va_list_tag[1])
+# 888| [TopLevelFunction] void VAListUsage(int, __builtin_va_list)
# 888| :
# 888| getParameter(0): [Parameter] x
# 888| Type = [IntType] int
# 888| getParameter(1): [Parameter] args
-# 888| Type = [ArrayType] __va_list_tag[1]
+# 888| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 888| getEntryPoint(): [BlockStmt] { ... }
# 889| getStmt(0): [DeclStmt] declaration
# 889| getDeclarationEntry(0): [VariableDeclarationEntry] definition of args2
-# 889| Type = [ArrayType] __va_list_tag[1]
+# 889| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 890| getStmt(1): [ExprStmt] ExprStmt
# 890| getExpr(): [BuiltInVarArgCopy] __builtin_va_copy
# 890| Type = [VoidType] void
# 890| ValueCategory = prvalue
# 890| getDestinationVAList(): [VariableAccess] args2
-# 890| Type = [ArrayType] __va_list_tag[1]
+# 890| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 890| ValueCategory = lvalue
# 890| getSourceVAList(): [VariableAccess] args
# 890| Type = [PointerType] __va_list_tag *
@@ -10859,7 +10905,7 @@ ir.cpp:
# 893| Type = [VoidType] void
# 893| ValueCategory = prvalue
# 893| getVAList(): [VariableAccess] args2
-# 893| Type = [ArrayType] __va_list_tag[1]
+# 893| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 893| ValueCategory = lvalue
# 893| getVAList().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 893| Type = [PointerType] __va_list_tag *
@@ -10872,13 +10918,13 @@ ir.cpp:
# 896| getEntryPoint(): [BlockStmt] { ... }
# 897| getStmt(0): [DeclStmt] declaration
# 897| getDeclarationEntry(0): [VariableDeclarationEntry] definition of args
-# 897| Type = [ArrayType] __va_list_tag[1]
+# 897| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 899| getStmt(1): [ExprStmt] ExprStmt
# 899| getExpr(): [BuiltInVarArgsStart] __builtin_va_start
# 899| Type = [VoidType] void
# 899| ValueCategory = prvalue
# 899| getVAList(): [VariableAccess] args
-# 899| Type = [ArrayType] __va_list_tag[1]
+# 899| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 899| ValueCategory = lvalue
# 899| getLastNamedParameter(): [VariableAccess] x
# 899| Type = [IntType] int
@@ -10888,16 +10934,16 @@ ir.cpp:
# 899| ValueCategory = prvalue
# 900| getStmt(2): [DeclStmt] declaration
# 900| getDeclarationEntry(0): [VariableDeclarationEntry] definition of args2
-# 900| Type = [ArrayType] __va_list_tag[1]
+# 900| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 901| getStmt(3): [ExprStmt] ExprStmt
# 901| getExpr(): [BuiltInVarArgCopy] __builtin_va_copy
# 901| Type = [VoidType] void
# 901| ValueCategory = prvalue
# 901| getDestinationVAList(): [VariableAccess] args2
-# 901| Type = [ArrayType] __va_list_tag[1]
+# 901| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 901| ValueCategory = lvalue
# 901| getSourceVAList(): [VariableAccess] args
-# 901| Type = [ArrayType] __va_list_tag[1]
+# 901| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 901| ValueCategory = lvalue
# 901| getDestinationVAList().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 901| Type = [PointerType] __va_list_tag *
@@ -10913,7 +10959,7 @@ ir.cpp:
# 902| Type = [DoubleType] double
# 902| ValueCategory = prvalue(load)
# 902| getVAList(): [VariableAccess] args
-# 902| Type = [ArrayType] __va_list_tag[1]
+# 902| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 902| ValueCategory = lvalue
# 902| getVAList().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 902| Type = [PointerType] __va_list_tag *
@@ -10926,7 +10972,7 @@ ir.cpp:
# 903| Type = [IntType] int
# 903| ValueCategory = prvalue(load)
# 903| getVAList(): [VariableAccess] args
-# 903| Type = [ArrayType] __va_list_tag[1]
+# 903| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 903| ValueCategory = lvalue
# 903| getVAList().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 903| Type = [PointerType] __va_list_tag *
@@ -10940,7 +10986,7 @@ ir.cpp:
# 904| Type = [VoidType] void
# 904| ValueCategory = prvalue
# 904| getVAList(): [VariableAccess] args
-# 904| Type = [ArrayType] __va_list_tag[1]
+# 904| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 904| ValueCategory = lvalue
# 904| getVAList().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 904| Type = [PointerType] __va_list_tag *
@@ -10953,7 +10999,7 @@ ir.cpp:
# 905| Type = [IntType] int
# 905| ValueCategory = prvalue(load)
# 905| getArgument(1): [VariableAccess] args2
-# 905| Type = [ArrayType] __va_list_tag[1]
+# 905| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 905| ValueCategory = lvalue
# 905| getArgument(1).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 905| Type = [PointerType] __va_list_tag *
@@ -10963,7 +11009,7 @@ ir.cpp:
# 906| Type = [VoidType] void
# 906| ValueCategory = prvalue
# 906| getVAList(): [VariableAccess] args2
-# 906| Type = [ArrayType] __va_list_tag[1]
+# 906| Type = [BuiltInVarArgsList,CTypedefType] __builtin_va_list
# 906| ValueCategory = lvalue
# 906| getVAList().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 906| Type = [PointerType] __va_list_tag *
diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
index c6f2bb1639e..575631ab041 100644
--- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
+++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected
@@ -1,4 +1,4 @@
-arm.cpp:
+arm_neon.cpp:
# 6| uint8x8_t vadd_u8(uint8x8_t, uint8x8_t)
# 6| Block 0
# 6| v6_1(void) = EnterFunction :
@@ -21,65 +21,107 @@ arm.cpp:
# 6| v6_11(void) = AliasedUse : m6_3
# 6| v6_12(void) = ExitFunction :
-# 14| uint16x8_t vaddl_u8(uint8x8_t, uint8x8_t)
-# 14| Block 0
-# 14| v14_1(void) = EnterFunction :
-# 14| m14_2(unknown) = AliasedDefinition :
-# 14| m14_3(unknown) = InitializeNonLocal :
-# 14| m14_4(unknown) = Chi : total:m14_2, partial:m14_3
-# 14| r14_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
-# 14| m14_6(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r14_5
-# 14| r14_7(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
-# 14| m14_8(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r14_7
-# 15| r15_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
-# 15| r15_2(glval) = FunctionAddress[__builtin_aarch64_uaddlv8qi_uuu] :
-# 15| r15_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
-# 15| r15_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r15_3, m14_6
-# 15| r15_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
-# 15| r15_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r15_5, m14_8
-# 15| r15_7(__attribute((neon_vector_type(8))) unsigned short) = Call[__builtin_aarch64_uaddlv8qi_uuu] : func:r15_2, 0:r15_4, 1:r15_6
-# 15| m15_8(unknown) = ^CallSideEffect : ~m14_4
-# 15| m15_9(unknown) = Chi : total:m14_4, partial:m15_8
-# 15| m15_10(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r15_1, r15_7
-# 14| r14_9(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
-# 14| v14_10(void) = ReturnValue : &:r14_9, m15_10
-# 14| v14_11(void) = AliasedUse : ~m15_9
-# 14| v14_12(void) = ExitFunction :
+# 12| uint16x8_t arm_add(uint8x8_t, uint8x8_t*)
+# 12| Block 0
+# 12| v12_1(void) = EnterFunction :
+# 12| m12_2(unknown) = AliasedDefinition :
+# 12| m12_3(unknown) = InitializeNonLocal :
+# 12| m12_4(unknown) = Chi : total:m12_2, partial:m12_3
+# 12| r12_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
+# 12| m12_6(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r12_5
+# 12| r12_7(glval<__attribute((neon_vector_type(8))) unsigned char *>) = VariableAddress[b] :
+# 12| m12_8(__attribute((neon_vector_type(8))) unsigned char *) = InitializeParameter[b] : &:r12_7
+# 12| r12_9(__attribute((neon_vector_type(8))) unsigned char *) = Load[b] : &:r12_7, m12_8
+# 12| m12_10(unknown) = InitializeIndirection[b] : &:r12_9
+# 13| r13_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
+# 13| r13_2(glval) = FunctionAddress[vadd_u8] :
+# 13| r13_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
+# 13| r13_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r13_3, m12_6
+# 13| r13_5(glval<__attribute((neon_vector_type(8))) unsigned char *>) = VariableAddress[b] :
+# 13| r13_6(__attribute((neon_vector_type(8))) unsigned char *) = Load[b] : &:r13_5, m12_8
+# 13| r13_7(__attribute((neon_vector_type(8))) unsigned char) = Load[?] : &:r13_6, ~m12_10
+# 13| r13_8(__attribute((neon_vector_type(8))) unsigned char) = Call[vadd_u8] : func:r13_2, 0:r13_4, 1:r13_7
+# 13| m13_9(unknown) = ^CallSideEffect : ~m12_4
+# 13| m13_10(unknown) = Chi : total:m12_4, partial:m13_9
+# 13| m13_11(__attribute((neon_vector_type(8))) unsigned char) = Store[c] : &:r13_1, r13_8
+# 14| r14_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
+# 14| r14_2(glval) = FunctionAddress[vaddl_u8] :
+# 14| r14_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
+# 14| r14_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r14_3, m12_6
+# 14| r14_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
+# 14| r14_6(__attribute((neon_vector_type(8))) unsigned char) = Load[c] : &:r14_5, m13_11
+# 14| r14_7(__attribute((neon_vector_type(8))) unsigned short) = Call[vaddl_u8] : func:r14_2, 0:r14_4, 1:r14_6
+# 14| m14_8(unknown) = ^CallSideEffect : ~m13_10
+# 14| m14_9(unknown) = Chi : total:m13_10, partial:m14_8
+# 14| m14_10(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r14_1, r14_7
+# 12| v12_11(void) = ReturnIndirection[b] : &:r12_9, m12_10
+# 12| r12_12(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
+# 12| v12_13(void) = ReturnValue : &:r12_12, m14_10
+# 12| v12_14(void) = AliasedUse : ~m14_9
+# 12| v12_15(void) = ExitFunction :
-# 18| uint16x8_t arm_add(uint8x8_t, uint8x8_t)
-# 18| Block 0
-# 18| v18_1(void) = EnterFunction :
-# 18| m18_2(unknown) = AliasedDefinition :
-# 18| m18_3(unknown) = InitializeNonLocal :
-# 18| m18_4(unknown) = Chi : total:m18_2, partial:m18_3
-# 18| r18_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
-# 18| m18_6(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r18_5
-# 18| r18_7(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
-# 18| m18_8(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r18_7
-# 19| r19_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
-# 19| r19_2(glval) = FunctionAddress[vadd_u8] :
-# 19| r19_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
-# 19| r19_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r19_3, m18_6
-# 19| r19_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
-# 19| r19_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r19_5, m18_8
-# 19| r19_7(__attribute((neon_vector_type(8))) unsigned char) = Call[vadd_u8] : func:r19_2, 0:r19_4, 1:r19_6
-# 19| m19_8(unknown) = ^CallSideEffect : ~m18_4
-# 19| m19_9(unknown) = Chi : total:m18_4, partial:m19_8
-# 19| m19_10(__attribute((neon_vector_type(8))) unsigned char) = Store[c] : &:r19_1, r19_7
-# 20| r20_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
-# 20| r20_2(glval) = FunctionAddress[vaddl_u8] :
-# 20| r20_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
-# 20| r20_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r20_3, m18_6
-# 20| r20_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
-# 20| r20_6(__attribute((neon_vector_type(8))) unsigned char) = Load[c] : &:r20_5, m19_10
-# 20| r20_7(__attribute((neon_vector_type(8))) unsigned short) = Call[vaddl_u8] : func:r20_2, 0:r20_4, 1:r20_6
-# 20| m20_8(unknown) = ^CallSideEffect : ~m19_9
-# 20| m20_9(unknown) = Chi : total:m19_9, partial:m20_8
-# 20| m20_10(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r20_1, r20_7
-# 18| r18_9(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
-# 18| v18_10(void) = ReturnValue : &:r18_9, m20_10
-# 18| v18_11(void) = AliasedUse : ~m20_9
-# 18| v18_12(void) = ExitFunction :
+# 22| mfloat8x8_t arm_reinterpret(int8x8_t*)
+# 22| Block 0
+# 22| v22_1(void) = EnterFunction :
+# 22| m22_2(unknown) = AliasedDefinition :
+# 22| m22_3(unknown) = InitializeNonLocal :
+# 22| m22_4(unknown) = Chi : total:m22_2, partial:m22_3
+# 22| r22_5(glval) = VariableAddress[a] :
+# 22| m22_6(char *) = InitializeParameter[a] : &:r22_5
+# 22| r22_7(char *) = Load[a] : &:r22_5, m22_6
+# 22| m22_8(unknown) = InitializeIndirection[a] : &:r22_7
+# 23| r23_1(glval<__mfp8>) = VariableAddress[#return] :
+# 23| r23_2(glval) = FunctionAddress[vreinterpret_mf8_s8] :
+# 23| r23_3(glval) = VariableAddress[a] :
+# 23| r23_4(char *) = Load[a] : &:r23_3, m22_6
+# 23| r23_5(char) = Load[?] : &:r23_4, ~m22_8
+# 23| r23_6(__mfp8) = Call[vreinterpret_mf8_s8] : func:r23_2, 0:r23_5
+# 23| m23_7(unknown) = ^CallSideEffect : ~m22_4
+# 23| m23_8(unknown) = Chi : total:m22_4, partial:m23_7
+# 23| m23_9(__mfp8) = Store[#return] : &:r23_1, r23_6
+# 22| v22_9(void) = ReturnIndirection[a] : &:r22_7, m22_8
+# 22| r22_10(glval<__mfp8>) = VariableAddress[#return] :
+# 22| v22_11(void) = ReturnValue : &:r22_10, m23_9
+# 22| v22_12(void) = AliasedUse : ~m23_8
+# 22| v22_13(void) = ExitFunction :
+
+arm_sve.cpp:
+# 8| svuint8x2_t arm_sel(svcount_t, svuint8x2_t, svuint8x2_t*)
+# 8| Block 0
+# 8| v8_1(void) = EnterFunction :
+# 8| m8_2(unknown) = AliasedDefinition :
+# 8| m8_3(unknown) = InitializeNonLocal :
+# 8| m8_4(unknown) = Chi : total:m8_2, partial:m8_3
+# 8| r8_5(glval<__SVCount_t>) = VariableAddress[a] :
+# 8| m8_6(__SVCount_t) = InitializeParameter[a] : &:r8_5
+# 8| r8_7(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[b] :
+# 8| m8_8(__edg_scalable_vector_type__(unsigned char, 2)) = InitializeParameter[b] : &:r8_7
+# 8| r8_9(glval<__edg_scalable_vector_type__(unsigned char, 2) *>) = VariableAddress[c] :
+# 8| m8_10(__edg_scalable_vector_type__(unsigned char, 2) *) = InitializeParameter[c] : &:r8_9
+# 8| r8_11(__edg_scalable_vector_type__(unsigned char, 2) *) = Load[c] : &:r8_9, m8_10
+# 8| m8_12(unknown) = InitializeIndirection[c] : &:r8_11
+# 9| r9_1(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[d] :
+# 9| r9_2(glval) = FunctionAddress[svsel_u8_x2] :
+# 9| r9_3(glval<__SVCount_t>) = VariableAddress[a] :
+# 9| r9_4(__SVCount_t) = Load[a] : &:r9_3, m8_6
+# 9| r9_5(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[b] :
+# 9| r9_6(__edg_scalable_vector_type__(unsigned char, 2)) = Load[b] : &:r9_5, m8_8
+# 9| r9_7(glval<__edg_scalable_vector_type__(unsigned char, 2) *>) = VariableAddress[c] :
+# 9| r9_8(__edg_scalable_vector_type__(unsigned char, 2) *) = Load[c] : &:r9_7, m8_10
+# 9| r9_9(__edg_scalable_vector_type__(unsigned char, 2)) = Load[?] : &:r9_8, ~m8_12
+# 9| r9_10(__edg_scalable_vector_type__(unsigned char, 2)) = Call[svsel_u8_x2] : func:r9_2, 0:r9_4, 1:r9_6, 2:r9_9
+# 9| m9_11(unknown) = ^CallSideEffect : ~m8_4
+# 9| m9_12(unknown) = Chi : total:m8_4, partial:m9_11
+# 9| m9_13(__edg_scalable_vector_type__(unsigned char, 2)) = Store[d] : &:r9_1, r9_10
+# 10| r10_1(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[#return] :
+# 10| r10_2(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[d] :
+# 10| r10_3(__edg_scalable_vector_type__(unsigned char, 2)) = Load[d] : &:r10_2, m9_13
+# 10| m10_4(__edg_scalable_vector_type__(unsigned char, 2)) = Store[#return] : &:r10_1, r10_3
+# 8| v8_13(void) = ReturnIndirection[c] : &:r8_11, m8_12
+# 8| r8_14(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[#return] :
+# 8| v8_15(void) = ReturnValue : &:r8_14, m10_4
+# 8| v8_16(void) = AliasedUse : ~m9_12
+# 8| v8_17(void) = ExitFunction :
bad_asts.cpp:
# 9| int Bad::S::MemberFunction(int)
@@ -8614,7 +8656,7 @@ ir.cpp:
# 883| v883_13(void) = AliasedUse : m883_3
# 883| v883_14(void) = ExitFunction :
-# 888| void VAListUsage(int, __va_list_tag[1])
+# 888| void VAListUsage(int, __builtin_va_list)
# 888| Block 0
# 888| v888_1(void) = EnterFunction :
# 888| m888_2(unknown) = AliasedDefinition :
diff --git a/cpp/ql/test/library-tests/ir/ir/arm.cpp b/cpp/ql/test/library-tests/ir/ir/arm.cpp
deleted file mode 100644
index 36e20715bc5..00000000000
--- a/cpp/ql/test/library-tests/ir/ir/arm.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// semmle-extractor-options: --edg --target --edg linux_arm64
-
-typedef __Uint8x8_t uint8x8_t;
-typedef __Uint16x8_t uint16x8_t;
-
-uint8x8_t vadd_u8(uint8x8_t a, uint8x8_t b) {
- return a + b;
-}
-
-// Workaround: the frontend only exposes this when the arm_neon.h
-// header is encountered.
-uint16x8_t __builtin_aarch64_uaddlv8qi_uuu(uint8x8_t, uint8x8_t);
-
-uint16x8_t vaddl_u8(uint8x8_t a, uint8x8_t b) {
- return __builtin_aarch64_uaddlv8qi_uuu (a, b);
-}
-
-uint16x8_t arm_add(uint8x8_t a, uint8x8_t b) {
- uint8x8_t c = vadd_u8(a, b);
- return vaddl_u8(a, c);
-}
diff --git a/cpp/ql/test/library-tests/ir/ir/arm_neon.cpp b/cpp/ql/test/library-tests/ir/ir/arm_neon.cpp
new file mode 100644
index 00000000000..d1659dfba35
--- /dev/null
+++ b/cpp/ql/test/library-tests/ir/ir/arm_neon.cpp
@@ -0,0 +1,24 @@
+// semmle-extractor-options: --edg --target --edg linux_arm64 --gnu_version 150000
+
+typedef __Uint8x8_t uint8x8_t;
+typedef __Uint16x8_t uint16x8_t;
+
+uint8x8_t vadd_u8(uint8x8_t a, uint8x8_t b) {
+ return a + b;
+}
+
+uint16x8_t vaddl_u8(uint8x8_t a, uint8x8_t b);
+
+uint16x8_t arm_add(uint8x8_t a, uint8x8_t *b) {
+ uint8x8_t c = vadd_u8(a, *b);
+ return vaddl_u8(a, c);
+}
+
+typedef __attribute__((neon_vector_type(8))) __mfp8 mfloat8x8_t;
+typedef __attribute__((neon_vector_type(8))) char int8x8_t;
+
+mfloat8x8_t vreinterpret_mf8_s8(int8x8_t);
+
+mfloat8x8_t arm_reinterpret(int8x8_t *a) {
+ return vreinterpret_mf8_s8(*a);
+}
diff --git a/cpp/ql/test/library-tests/ir/ir/arm_sve.cpp b/cpp/ql/test/library-tests/ir/ir/arm_sve.cpp
new file mode 100644
index 00000000000..33bad8abbe4
--- /dev/null
+++ b/cpp/ql/test/library-tests/ir/ir/arm_sve.cpp
@@ -0,0 +1,11 @@
+// semmle-extractor-options: --edg --target --edg linux_arm64 --clang_version 190000
+
+typedef __clang_svuint8x2_t svuint8x2_t;
+typedef __SVCount_t svcount_t;
+
+svuint8x2_t svsel_u8_x2(svcount_t, svuint8x2_t, svuint8x2_t);
+
+svuint8x2_t arm_sel(svcount_t a, svuint8x2_t b, svuint8x2_t *c) {
+ svuint8x2_t d = svsel_u8_x2(a, b, *c);
+ return d;
+}
diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected
index f594062a0a5..e57a3bc11b5 100644
--- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected
+++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected
@@ -1,4 +1,4 @@
-arm.cpp:
+arm_neon.cpp:
# 6| uint8x8_t vadd_u8(uint8x8_t, uint8x8_t)
# 6| Block 0
# 6| v6_1(void) = EnterFunction :
@@ -20,60 +20,100 @@ arm.cpp:
# 6| v6_10(void) = AliasedUse : ~m?
# 6| v6_11(void) = ExitFunction :
-# 14| uint16x8_t vaddl_u8(uint8x8_t, uint8x8_t)
-# 14| Block 0
-# 14| v14_1(void) = EnterFunction :
-# 14| mu14_2(unknown) = AliasedDefinition :
-# 14| mu14_3(unknown) = InitializeNonLocal :
-# 14| r14_4(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
-# 14| mu14_5(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r14_4
-# 14| r14_6(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
-# 14| mu14_7(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r14_6
-# 15| r15_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
-# 15| r15_2(glval) = FunctionAddress[__builtin_aarch64_uaddlv8qi_uuu] :
-# 15| r15_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
-# 15| r15_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r15_3, ~m?
-# 15| r15_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
-# 15| r15_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r15_5, ~m?
-# 15| r15_7(__attribute((neon_vector_type(8))) unsigned short) = Call[__builtin_aarch64_uaddlv8qi_uuu] : func:r15_2, 0:r15_4, 1:r15_6
-# 15| mu15_8(unknown) = ^CallSideEffect : ~m?
-# 15| mu15_9(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r15_1, r15_7
-# 14| r14_8(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
-# 14| v14_9(void) = ReturnValue : &:r14_8, ~m?
-# 14| v14_10(void) = AliasedUse : ~m?
-# 14| v14_11(void) = ExitFunction :
+# 12| uint16x8_t arm_add(uint8x8_t, uint8x8_t*)
+# 12| Block 0
+# 12| v12_1(void) = EnterFunction :
+# 12| mu12_2(unknown) = AliasedDefinition :
+# 12| mu12_3(unknown) = InitializeNonLocal :
+# 12| r12_4(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
+# 12| mu12_5(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r12_4
+# 12| r12_6(glval<__attribute((neon_vector_type(8))) unsigned char *>) = VariableAddress[b] :
+# 12| mu12_7(__attribute((neon_vector_type(8))) unsigned char *) = InitializeParameter[b] : &:r12_6
+# 12| r12_8(__attribute((neon_vector_type(8))) unsigned char *) = Load[b] : &:r12_6, ~m?
+# 12| mu12_9(unknown) = InitializeIndirection[b] : &:r12_8
+# 13| r13_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
+# 13| r13_2(glval) = FunctionAddress[vadd_u8] :
+# 13| r13_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
+# 13| r13_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r13_3, ~m?
+# 13| r13_5(glval<__attribute((neon_vector_type(8))) unsigned char *>) = VariableAddress[b] :
+# 13| r13_6(__attribute((neon_vector_type(8))) unsigned char *) = Load[b] : &:r13_5, ~m?
+# 13| r13_7(__attribute((neon_vector_type(8))) unsigned char) = Load[?] : &:r13_6, ~m?
+# 13| r13_8(__attribute((neon_vector_type(8))) unsigned char) = Call[vadd_u8] : func:r13_2, 0:r13_4, 1:r13_7
+# 13| mu13_9(unknown) = ^CallSideEffect : ~m?
+# 13| mu13_10(__attribute((neon_vector_type(8))) unsigned char) = Store[c] : &:r13_1, r13_8
+# 14| r14_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
+# 14| r14_2(glval) = FunctionAddress[vaddl_u8] :
+# 14| r14_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
+# 14| r14_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r14_3, ~m?
+# 14| r14_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
+# 14| r14_6(__attribute((neon_vector_type(8))) unsigned char) = Load[c] : &:r14_5, ~m?
+# 14| r14_7(__attribute((neon_vector_type(8))) unsigned short) = Call[vaddl_u8] : func:r14_2, 0:r14_4, 1:r14_6
+# 14| mu14_8(unknown) = ^CallSideEffect : ~m?
+# 14| mu14_9(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r14_1, r14_7
+# 12| v12_10(void) = ReturnIndirection[b] : &:r12_8, ~m?
+# 12| r12_11(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
+# 12| v12_12(void) = ReturnValue : &:r12_11, ~m?
+# 12| v12_13(void) = AliasedUse : ~m?
+# 12| v12_14(void) = ExitFunction :
-# 18| uint16x8_t arm_add(uint8x8_t, uint8x8_t)
-# 18| Block 0
-# 18| v18_1(void) = EnterFunction :
-# 18| mu18_2(unknown) = AliasedDefinition :
-# 18| mu18_3(unknown) = InitializeNonLocal :
-# 18| r18_4(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
-# 18| mu18_5(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r18_4
-# 18| r18_6(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
-# 18| mu18_7(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r18_6
-# 19| r19_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
-# 19| r19_2(glval) = FunctionAddress[vadd_u8] :
-# 19| r19_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
-# 19| r19_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r19_3, ~m?
-# 19| r19_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] :
-# 19| r19_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r19_5, ~m?
-# 19| r19_7(__attribute((neon_vector_type(8))) unsigned char) = Call[vadd_u8] : func:r19_2, 0:r19_4, 1:r19_6
-# 19| mu19_8(unknown) = ^CallSideEffect : ~m?
-# 19| mu19_9(__attribute((neon_vector_type(8))) unsigned char) = Store[c] : &:r19_1, r19_7
-# 20| r20_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
-# 20| r20_2(glval) = FunctionAddress[vaddl_u8] :
-# 20| r20_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] :
-# 20| r20_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r20_3, ~m?
-# 20| r20_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] :
-# 20| r20_6(__attribute((neon_vector_type(8))) unsigned char) = Load[c] : &:r20_5, ~m?
-# 20| r20_7(__attribute((neon_vector_type(8))) unsigned short) = Call[vaddl_u8] : func:r20_2, 0:r20_4, 1:r20_6
-# 20| mu20_8(unknown) = ^CallSideEffect : ~m?
-# 20| mu20_9(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r20_1, r20_7
-# 18| r18_8(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] :
-# 18| v18_9(void) = ReturnValue : &:r18_8, ~m?
-# 18| v18_10(void) = AliasedUse : ~m?
-# 18| v18_11(void) = ExitFunction :
+# 22| mfloat8x8_t arm_reinterpret(int8x8_t*)
+# 22| Block 0
+# 22| v22_1(void) = EnterFunction :
+# 22| mu22_2(unknown) = AliasedDefinition :
+# 22| mu22_3(unknown) = InitializeNonLocal :
+# 22| r22_4(glval) = VariableAddress[a] :
+# 22| mu22_5(char *) = InitializeParameter[a] : &:r22_4
+# 22| r22_6(char *) = Load[a] : &:r22_4, ~m?
+# 22| mu22_7(unknown) = InitializeIndirection[a] : &:r22_6
+# 23| r23_1(glval<__mfp8>) = VariableAddress[#return] :
+# 23| r23_2(glval) = FunctionAddress[vreinterpret_mf8_s8] :
+# 23| r23_3(glval) = VariableAddress[a] :
+# 23| r23_4(char *) = Load[a] : &:r23_3, ~m?
+# 23| r23_5(char) = Load[?] : &:r23_4, ~m?
+# 23| r23_6(__mfp8) = Call[vreinterpret_mf8_s8] : func:r23_2, 0:r23_5
+# 23| mu23_7(unknown) = ^CallSideEffect : ~m?
+# 23| mu23_8(__mfp8) = Store[#return] : &:r23_1, r23_6
+# 22| v22_8(void) = ReturnIndirection[a] : &:r22_6, ~m?
+# 22| r22_9(glval<__mfp8>) = VariableAddress[#return] :
+# 22| v22_10(void) = ReturnValue : &:r22_9, ~m?
+# 22| v22_11(void) = AliasedUse : ~m?
+# 22| v22_12(void) = ExitFunction :
+
+arm_sve.cpp:
+# 8| svuint8x2_t arm_sel(svcount_t, svuint8x2_t, svuint8x2_t*)
+# 8| Block 0
+# 8| v8_1(void) = EnterFunction :
+# 8| mu8_2(unknown) = AliasedDefinition :
+# 8| mu8_3(unknown) = InitializeNonLocal :
+# 8| r8_4(glval<__SVCount_t>) = VariableAddress[a] :
+# 8| mu8_5(__SVCount_t) = InitializeParameter[a] : &:r8_4
+# 8| r8_6(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[b] :
+# 8| mu8_7(__edg_scalable_vector_type__(unsigned char, 2)) = InitializeParameter[b] : &:r8_6
+# 8| r8_8(glval<__edg_scalable_vector_type__(unsigned char, 2) *>) = VariableAddress[c] :
+# 8| mu8_9(__edg_scalable_vector_type__(unsigned char, 2) *) = InitializeParameter[c] : &:r8_8
+# 8| r8_10(__edg_scalable_vector_type__(unsigned char, 2) *) = Load[c] : &:r8_8, ~m?
+# 8| mu8_11(unknown) = InitializeIndirection[c] : &:r8_10
+# 9| r9_1(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[d] :
+# 9| r9_2(glval) = FunctionAddress[svsel_u8_x2] :
+# 9| r9_3(glval<__SVCount_t>) = VariableAddress[a] :
+# 9| r9_4(__SVCount_t) = Load[a] : &:r9_3, ~m?
+# 9| r9_5(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[b] :
+# 9| r9_6(__edg_scalable_vector_type__(unsigned char, 2)) = Load[b] : &:r9_5, ~m?
+# 9| r9_7(glval<__edg_scalable_vector_type__(unsigned char, 2) *>) = VariableAddress[c] :
+# 9| r9_8(__edg_scalable_vector_type__(unsigned char, 2) *) = Load[c] : &:r9_7, ~m?
+# 9| r9_9(__edg_scalable_vector_type__(unsigned char, 2)) = Load[?] : &:r9_8, ~m?
+# 9| r9_10(__edg_scalable_vector_type__(unsigned char, 2)) = Call[svsel_u8_x2] : func:r9_2, 0:r9_4, 1:r9_6, 2:r9_9
+# 9| mu9_11(unknown) = ^CallSideEffect : ~m?
+# 9| mu9_12(__edg_scalable_vector_type__(unsigned char, 2)) = Store[d] : &:r9_1, r9_10
+# 10| r10_1(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[#return] :
+# 10| r10_2(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[d] :
+# 10| r10_3(__edg_scalable_vector_type__(unsigned char, 2)) = Load[d] : &:r10_2, ~m?
+# 10| mu10_4(__edg_scalable_vector_type__(unsigned char, 2)) = Store[#return] : &:r10_1, r10_3
+# 8| v8_12(void) = ReturnIndirection[c] : &:r8_10, ~m?
+# 8| r8_13(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[#return] :
+# 8| v8_14(void) = ReturnValue : &:r8_13, ~m?
+# 8| v8_15(void) = AliasedUse : ~m?
+# 8| v8_16(void) = ExitFunction :
bad_asts.cpp:
# 9| int Bad::S::MemberFunction(int)
@@ -7955,7 +7995,7 @@ ir.cpp:
# 883| v883_12(void) = AliasedUse : ~m?
# 883| v883_13(void) = ExitFunction :
-# 888| void VAListUsage(int, __va_list_tag[1])
+# 888| void VAListUsage(int, __builtin_va_list)
# 888| Block 0
# 888| v888_1(void) = EnterFunction :
# 888| mu888_2(unknown) = AliasedDefinition :
diff --git a/cpp/ql/test/library-tests/templates/instantiation_directive/functions.expected b/cpp/ql/test/library-tests/templates/instantiation_directive/functions.expected
index 672fae72e06..eba49fd1c6d 100644
--- a/cpp/ql/test/library-tests/templates/instantiation_directive/functions.expected
+++ b/cpp/ql/test/library-tests/templates/instantiation_directive/functions.expected
@@ -1,3 +1,5 @@
| file://:0:0:0:0 | operator= | file://:0:0:0:0 | __va_list_tag && |
| file://:0:0:0:0 | operator= | file://:0:0:0:0 | const __va_list_tag & |
+| test.cpp:2:6:2:6 | foo | file://:0:0:0:0 | float |
+| test.cpp:2:6:2:6 | foo | file://:0:0:0:0 | int |
| test.cpp:2:6:2:8 | foo | test.cpp:1:19:1:19 | T |
diff --git a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/instantiations.expected b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/instantiations.expected
index e1c7f956c7b..7a7b1761e98 100644
--- a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/instantiations.expected
+++ b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/instantiations.expected
@@ -10,3 +10,4 @@
| isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | ClassTemplateInstantiation | file://:0:0:0:0 | int |
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | ClassTemplateInstantiation | file://:0:0:0:0 | long |
| load.cpp:13:7:13:27 | basic_text_iprimitive | ClassTemplateInstantiation | load.cpp:3:7:3:24 | std_istream_mockup |
+| load.cpp:22:10:22:10 | load | FunctionTemplateInstantiation | file://:0:0:0:0 | short |
diff --git a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected
index cb35f7a6dd0..316b5273cdc 100644
--- a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected
+++ b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected
@@ -104,6 +104,15 @@
| isfromtemplateinstantiation.cpp:99:1:99:1 | return ... | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass |
| isfromtemplateinstantiation.cpp:99:1:99:1 | return ... | isfromtemplateinstantiation.cpp:97:52:97:52 | AnotherTemplateClass::myMethod2(MyClassEnum) |
| isfromtemplateinstantiation.cpp:110:3:110:3 | definition of var_template | isfromtemplateinstantiation.cpp:110:3:110:3 | var_template |
+| isfromtemplateinstantiation.cpp:129:6:129:6 | AnotherTemplateClass::f() | isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass |
+| isfromtemplateinstantiation.cpp:129:6:129:6 | definition of f | isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass |
+| isfromtemplateinstantiation.cpp:129:6:129:6 | definition of f | isfromtemplateinstantiation.cpp:129:6:129:6 | AnotherTemplateClass::f() |
+| isfromtemplateinstantiation.cpp:129:10:129:22 | { ... } | isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass |
+| isfromtemplateinstantiation.cpp:129:10:129:22 | { ... } | isfromtemplateinstantiation.cpp:129:6:129:6 | AnotherTemplateClass::f() |
+| isfromtemplateinstantiation.cpp:129:12:129:20 | return ... | isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass |
+| isfromtemplateinstantiation.cpp:129:12:129:20 | return ... | isfromtemplateinstantiation.cpp:129:6:129:6 | AnotherTemplateClass::f() |
+| isfromtemplateinstantiation.cpp:129:19:129:19 | 1 | isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass |
+| isfromtemplateinstantiation.cpp:129:19:129:19 | 1 | isfromtemplateinstantiation.cpp:129:6:129:6 | AnotherTemplateClass::f() |
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer |
| isfromtemplateinstantiation.cpp:135:31:135:35 | declaration of Inner | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer |
| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner |
@@ -112,7 +121,94 @@
| isfromtemplateinstantiation.cpp:137:7:137:7 | y | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner |
| load.cpp:15:14:15:15 | definition of is | load.cpp:13:7:13:27 | basic_text_iprimitive |
| load.cpp:15:14:15:15 | is | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:18:5:18:5 | basic_text_iprimitive::basic_text_iprimitive(std_istream_mockup &) | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:18:5:18:5 | definition of basic_text_iprimitive | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:18:5:18:5 | definition of basic_text_iprimitive | load.cpp:18:5:18:5 | basic_text_iprimitive::basic_text_iprimitive(std_istream_mockup &) |
+| load.cpp:18:36:18:42 | definition of isParam | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:18:36:18:42 | definition of isParam | load.cpp:18:5:18:5 | basic_text_iprimitive::basic_text_iprimitive(std_istream_mockup &) |
+| load.cpp:18:36:18:42 | std_istream_mockup & isParam | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:18:36:18:42 | std_istream_mockup & isParam | load.cpp:18:5:18:5 | basic_text_iprimitive::basic_text_iprimitive(std_istream_mockup &) |
+| load.cpp:19:11:19:21 | constructor init of field is | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:19:11:19:21 | constructor init of field is | load.cpp:18:5:18:5 | basic_text_iprimitive::basic_text_iprimitive(std_istream_mockup &) |
+| load.cpp:19:14:19:20 | (reference dereference) | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:19:14:19:20 | (reference dereference) | load.cpp:18:5:18:5 | basic_text_iprimitive::basic_text_iprimitive(std_istream_mockup &) |
+| load.cpp:19:14:19:20 | (reference to) | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:19:14:19:20 | (reference to) | load.cpp:18:5:18:5 | basic_text_iprimitive::basic_text_iprimitive(std_istream_mockup &) |
+| load.cpp:19:14:19:20 | isParam | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:19:14:19:20 | isParam | load.cpp:18:5:18:5 | basic_text_iprimitive::basic_text_iprimitive(std_istream_mockup &) |
+| load.cpp:19:23:19:24 | { ... } | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:19:23:19:24 | { ... } | load.cpp:18:5:18:5 | basic_text_iprimitive::basic_text_iprimitive(std_istream_mockup &) |
+| load.cpp:19:24:19:24 | return ... | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:19:24:19:24 | return ... | load.cpp:18:5:18:5 | basic_text_iprimitive::basic_text_iprimitive(std_istream_mockup &) |
+| load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:22:10:22:10 | definition of load | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:22:10:22:10 | definition of load | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
| load.cpp:22:10:22:13 | basic_text_iprimitive::load(T &) | load.cpp:13:7:13:27 | basic_text_iprimitive |
| load.cpp:22:10:22:13 | declaration of load | load.cpp:13:7:13:27 | basic_text_iprimitive |
| load.cpp:22:19:22:19 | T & t | load.cpp:13:7:13:27 | basic_text_iprimitive |
| load.cpp:22:19:22:19 | declaration of t | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:22:19:22:19 | definition of t | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:22:19:22:19 | definition of t | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:22:19:22:19 | short & t | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:22:19:22:19 | short & t | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:23:5:25:5 | { ... } | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:23:5:25:5 | { ... } | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:24:9:24:10 | (reference dereference) | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:24:9:24:10 | (reference dereference) | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:24:9:24:10 | is | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:24:9:24:10 | is | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:24:9:24:10 | this | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:24:9:24:10 | this | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:24:9:24:16 | ExprStmt | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:24:9:24:16 | ExprStmt | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:24:12:24:12 | call to operator>> | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:24:12:24:12 | call to operator>> | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:24:12:24:16 | (reference dereference) | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:24:12:24:16 | (reference dereference) | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:24:15:24:15 | (reference dereference) | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:24:15:24:15 | (reference dereference) | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:24:15:24:15 | (reference to) | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:24:15:24:15 | (reference to) | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:24:15:24:15 | t | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:24:15:24:15 | t | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:25:5:25:5 | return ... | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:25:5:25:5 | return ... | load.cpp:22:10:22:10 | basic_text_iprimitive::load(short &) |
+| load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:27:10:27:10 | definition of load | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:27:10:27:10 | definition of load | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:27:22:27:22 | char & t | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:27:22:27:22 | char & t | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:27:22:27:22 | definition of t | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:27:22:27:22 | definition of t | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:28:5:32:5 | { ... } | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:28:5:32:5 | { ... } | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:29:9:29:20 | declaration | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:29:9:29:20 | declaration | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:29:19:29:19 | definition of i | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:29:19:29:19 | definition of i | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:29:19:29:19 | i | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:29:19:29:19 | i | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:30:9:30:12 | call to load | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:30:9:30:12 | call to load | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:30:9:30:12 | this | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:30:9:30:12 | this | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:30:9:30:16 | ExprStmt | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:30:9:30:16 | ExprStmt | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:30:14:30:14 | (reference to) | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:30:14:30:14 | (reference to) | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:30:14:30:14 | i | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:30:14:30:14 | i | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:31:9:31:9 | (reference dereference) | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:31:9:31:9 | (reference dereference) | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:31:9:31:9 | t | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:31:9:31:9 | t | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:31:9:31:13 | ... = ... | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:31:9:31:13 | ... = ... | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:31:9:31:14 | ExprStmt | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:31:9:31:14 | ExprStmt | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:31:13:31:13 | (char)... | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:31:13:31:13 | (char)... | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:31:13:31:13 | i | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:31:13:31:13 | i | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
+| load.cpp:32:5:32:5 | return ... | load.cpp:13:7:13:27 | basic_text_iprimitive |
+| load.cpp:32:5:32:5 | return ... | load.cpp:27:10:27:10 | basic_text_iprimitive::load(char &) |
diff --git a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected
index 8a78058a723..ce20dedcfca 100644
--- a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected
+++ b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected
@@ -425,7 +425,16 @@ isFromUninstantiatedTemplate
| isfromtemplateinstantiation.cpp:123:6:123:6 | f | | | Declaration | |
| isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass | | T | Declaration | |
| isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass | I | | Declaration | |
+| isfromtemplateinstantiation.cpp:129:6:129:6 | definition of f | | T | Definition | |
+| isfromtemplateinstantiation.cpp:129:6:129:6 | definition of f | I | | Definition | |
| isfromtemplateinstantiation.cpp:129:6:129:6 | f | | T | Declaration | |
+| isfromtemplateinstantiation.cpp:129:6:129:6 | f | I | | Declaration | |
+| isfromtemplateinstantiation.cpp:129:10:129:22 | { ... } | | T | Stmt | |
+| isfromtemplateinstantiation.cpp:129:10:129:22 | { ... } | I | | Stmt | |
+| isfromtemplateinstantiation.cpp:129:12:129:20 | return ... | | T | Stmt | |
+| isfromtemplateinstantiation.cpp:129:12:129:20 | return ... | I | | Stmt | |
+| isfromtemplateinstantiation.cpp:129:19:129:19 | 1 | | T | Expr | |
+| isfromtemplateinstantiation.cpp:129:19:129:19 | 1 | I | | Expr | |
| isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | T | Declaration | |
| isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | I | | Declaration | |
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | | T | Declaration | |
@@ -461,21 +470,82 @@ isFromUninstantiatedTemplate
| load.cpp:15:14:15:15 | definition of is | I | | Definition | |
| load.cpp:15:14:15:15 | is | | T | Declaration | |
| load.cpp:15:14:15:15 | is | I | | Declaration | |
+| load.cpp:18:5:18:5 | basic_text_iprimitive | I | | Declaration | |
| load.cpp:18:5:18:25 | basic_text_iprimitive | | T | Declaration | |
+| load.cpp:18:36:18:42 | definition of isParam | | T | Definition | |
+| load.cpp:18:36:18:42 | definition of isParam | I | | Definition | |
+| load.cpp:18:36:18:42 | isParam | | T | Declaration | |
+| load.cpp:18:36:18:42 | isParam | I | | Declaration | |
+| load.cpp:19:11:19:21 | constructor init of field is | | T | Expr | |
+| load.cpp:19:11:19:21 | constructor init of field is | I | | Expr | |
| load.cpp:19:14:19:20 | (reference dereference) | | T | Expr | |
+| load.cpp:19:14:19:20 | (reference dereference) | I | | Expr | |
| load.cpp:19:14:19:20 | (reference to) | | T | Expr | |
+| load.cpp:19:14:19:20 | (reference to) | I | | Expr | |
| load.cpp:19:14:19:20 | isParam | | T | Expr | Ref |
+| load.cpp:19:14:19:20 | isParam | I | | Expr | Ref |
+| load.cpp:19:23:19:24 | { ... } | | T | Stmt | |
+| load.cpp:19:23:19:24 | { ... } | I | | Stmt | |
+| load.cpp:19:24:19:24 | return ... | | T | Stmt | |
+| load.cpp:19:24:19:24 | return ... | I | | Stmt | |
+| load.cpp:22:10:22:10 | load | I | | Declaration | |
| load.cpp:22:10:22:13 | load | | T | Declaration | |
| load.cpp:22:10:22:13 | load | I | T | Declaration | |
+| load.cpp:22:19:22:19 | definition of t | | T | Definition | |
+| load.cpp:22:19:22:19 | definition of t | I | | Definition | |
| load.cpp:22:19:22:19 | t | | T | Declaration | |
+| load.cpp:22:19:22:19 | t | I | | Declaration | |
| load.cpp:22:19:22:19 | t | I | T | Declaration | |
+| load.cpp:23:5:25:5 | { ... } | | T | Stmt | |
+| load.cpp:23:5:25:5 | { ... } | I | | Stmt | |
| load.cpp:24:9:24:10 | (reference dereference) | | T | Expr | |
+| load.cpp:24:9:24:10 | (reference dereference) | I | | Expr | |
| load.cpp:24:9:24:10 | is | | T | Expr | Not ref |
+| load.cpp:24:9:24:10 | is | I | | Expr | Not ref |
| load.cpp:24:9:24:10 | this | | T | Expr | |
+| load.cpp:24:9:24:10 | this | I | | Expr | |
+| load.cpp:24:9:24:16 | ExprStmt | | T | Stmt | |
+| load.cpp:24:9:24:16 | ExprStmt | I | | Stmt | |
| load.cpp:24:15:24:15 | (reference dereference) | | T | Expr | |
+| load.cpp:24:15:24:15 | (reference dereference) | I | | Expr | |
+| load.cpp:24:15:24:15 | (reference to) | I | | Expr | |
| load.cpp:24:15:24:15 | t | | T | Expr | Not ref |
+| load.cpp:24:15:24:15 | t | I | | Expr | Ref |
+| load.cpp:25:5:25:5 | return ... | | T | Stmt | |
+| load.cpp:25:5:25:5 | return ... | I | | Stmt | |
+| load.cpp:27:10:27:10 | load | I | | Declaration | |
| load.cpp:27:10:27:13 | load | | T | Declaration | |
+| load.cpp:27:22:27:22 | definition of t | | T | Definition | |
+| load.cpp:27:22:27:22 | definition of t | I | | Definition | |
+| load.cpp:27:22:27:22 | t | | T | Declaration | |
+| load.cpp:27:22:27:22 | t | I | | Declaration | |
+| load.cpp:28:5:32:5 | { ... } | | T | Stmt | |
+| load.cpp:28:5:32:5 | { ... } | I | | Stmt | |
+| load.cpp:29:9:29:20 | declaration | | T | Stmt | |
+| load.cpp:29:9:29:20 | declaration | I | | Stmt | |
+| load.cpp:29:19:29:19 | definition of i | | T | Definition | |
+| load.cpp:29:19:29:19 | definition of i | I | | Definition | |
+| load.cpp:29:19:29:19 | i | | T | Declaration | |
+| load.cpp:29:19:29:19 | i | I | | Declaration | |
+| load.cpp:30:9:30:12 | Unknown literal | | T | Expr | |
+| load.cpp:30:9:30:12 | call to load | I | | Expr | |
+| load.cpp:30:9:30:12 | this | I | | Expr | |
+| load.cpp:30:9:30:16 | ExprStmt | | T | Stmt | |
+| load.cpp:30:9:30:16 | ExprStmt | I | | Stmt | |
+| load.cpp:30:14:30:14 | (reference to) | I | | Expr | |
+| load.cpp:30:14:30:14 | i | | T | Expr | Not ref |
+| load.cpp:30:14:30:14 | i | I | | Expr | Ref |
| load.cpp:31:9:31:9 | (reference dereference) | | T | Expr | |
+| load.cpp:31:9:31:9 | (reference dereference) | I | | Expr | |
| load.cpp:31:9:31:9 | t | | T | Expr | Not ref |
+| load.cpp:31:9:31:9 | t | I | | Expr | Not ref |
+| load.cpp:31:9:31:13 | ... = ... | | T | Expr | |
+| load.cpp:31:9:31:13 | ... = ... | I | | Expr | |
+| load.cpp:31:9:31:14 | ExprStmt | | T | Stmt | |
+| load.cpp:31:9:31:14 | ExprStmt | I | | Stmt | |
| load.cpp:31:13:31:13 | (char)... | | T | Expr | |
+| load.cpp:31:13:31:13 | (char)... | I | | Expr | |
| load.cpp:31:13:31:13 | i | | T | Expr | Not ref |
+| load.cpp:31:13:31:13 | i | I | | Expr | Not ref |
+| load.cpp:32:5:32:5 | return ... | | T | Stmt | |
+| load.cpp:32:5:32:5 | return ... | I | | Stmt | |
diff --git a/cpp/ql/test/library-tests/templates/switch/test.expected b/cpp/ql/test/library-tests/templates/switch/test.expected
index 1ba49e1caf9..b4124494ffe 100644
--- a/cpp/ql/test/library-tests/templates/switch/test.expected
+++ b/cpp/ql/test/library-tests/templates/switch/test.expected
@@ -1 +1,2 @@
| test.cpp:13:3:20:3 | switch (...) ... | 3 |
+| test.cpp:13:3:20:3 | switch (...) ... | 3 |
diff --git a/cpp/ql/test/library-tests/templates/type_instantiations/types.expected b/cpp/ql/test/library-tests/templates/type_instantiations/types.expected
index 548f5f10189..e6c8b1d9406 100644
--- a/cpp/ql/test/library-tests/templates/type_instantiations/types.expected
+++ b/cpp/ql/test/library-tests/templates/type_instantiations/types.expected
@@ -5,10 +5,13 @@
| file://:0:0:0:0 | _Complex _Float64 |
| file://:0:0:0:0 | _Complex _Float64x |
| file://:0:0:0:0 | _Complex _Float128 |
+| file://:0:0:0:0 | _Complex __bf16 |
| file://:0:0:0:0 | _Complex __float128 |
+| file://:0:0:0:0 | _Complex __fp16 |
| file://:0:0:0:0 | _Complex double |
| file://:0:0:0:0 | _Complex float |
| file://:0:0:0:0 | _Complex long double |
+| file://:0:0:0:0 | _Complex std::float16_t |
| file://:0:0:0:0 | _Decimal32 |
| file://:0:0:0:0 | _Decimal64 |
| file://:0:0:0:0 | _Decimal128 |
diff --git a/cpp/ql/test/library-tests/type_sizes/type_sizes.expected b/cpp/ql/test/library-tests/type_sizes/type_sizes.expected
index c77aadc8f4f..ac1344753e9 100644
--- a/cpp/ql/test/library-tests/type_sizes/type_sizes.expected
+++ b/cpp/ql/test/library-tests/type_sizes/type_sizes.expected
@@ -25,10 +25,13 @@
| file://:0:0:0:0 | _Complex _Float64 | 16 |
| file://:0:0:0:0 | _Complex _Float64x | 32 |
| file://:0:0:0:0 | _Complex _Float128 | 32 |
+| file://:0:0:0:0 | _Complex __bf16 | 4 |
| file://:0:0:0:0 | _Complex __float128 | 32 |
+| file://:0:0:0:0 | _Complex __fp16 | 4 |
| file://:0:0:0:0 | _Complex double | 16 |
| file://:0:0:0:0 | _Complex float | 8 |
| file://:0:0:0:0 | _Complex long double | 32 |
+| file://:0:0:0:0 | _Complex std::float16_t | 4 |
| file://:0:0:0:0 | _Decimal32 | 4 |
| file://:0:0:0:0 | _Decimal64 | 8 |
| file://:0:0:0:0 | _Decimal128 | 16 |
diff --git a/cpp/ql/test/library-tests/unspecified_type/types/unspecified_type.expected b/cpp/ql/test/library-tests/unspecified_type/types/unspecified_type.expected
index 94185a66899..3f22b9f98f5 100644
--- a/cpp/ql/test/library-tests/unspecified_type/types/unspecified_type.expected
+++ b/cpp/ql/test/library-tests/unspecified_type/types/unspecified_type.expected
@@ -7,10 +7,13 @@
| file://:0:0:0:0 | _Complex _Float64 | _Complex _Float64 |
| file://:0:0:0:0 | _Complex _Float64x | _Complex _Float64x |
| file://:0:0:0:0 | _Complex _Float128 | _Complex _Float128 |
+| file://:0:0:0:0 | _Complex __bf16 | _Complex __bf16 |
| file://:0:0:0:0 | _Complex __float128 | _Complex __float128 |
+| file://:0:0:0:0 | _Complex __fp16 | _Complex __fp16 |
| file://:0:0:0:0 | _Complex double | _Complex double |
| file://:0:0:0:0 | _Complex float | _Complex float |
| file://:0:0:0:0 | _Complex long double | _Complex long double |
+| file://:0:0:0:0 | _Complex std::float16_t | _Complex std::float16_t |
| file://:0:0:0:0 | _Decimal32 | _Decimal32 |
| file://:0:0:0:0 | _Decimal64 | _Decimal64 |
| file://:0:0:0:0 | _Decimal128 | _Decimal128 |
diff --git a/cpp/ql/test/library-tests/variables/variables/types.expected b/cpp/ql/test/library-tests/variables/variables/types.expected
index 362ab5c6433..c2ea5f7cfe3 100644
--- a/cpp/ql/test/library-tests/variables/variables/types.expected
+++ b/cpp/ql/test/library-tests/variables/variables/types.expected
@@ -6,10 +6,13 @@
| _Complex _Float64 | BinaryFloatingPointType, ComplexNumberType | | | | |
| _Complex _Float64x | BinaryFloatingPointType, ComplexNumberType | | | | |
| _Complex _Float128 | BinaryFloatingPointType, ComplexNumberType | | | | |
+| _Complex __bf16 | BinaryFloatingPointType, ComplexNumberType | | | | |
| _Complex __float128 | BinaryFloatingPointType, ComplexNumberType | | | | |
+| _Complex __fp16 | BinaryFloatingPointType, ComplexNumberType | | | | |
| _Complex double | BinaryFloatingPointType, ComplexNumberType | | | | |
| _Complex float | BinaryFloatingPointType, ComplexNumberType | | | | |
| _Complex long double | BinaryFloatingPointType, ComplexNumberType | | | | |
+| _Complex std::float16_t | BinaryFloatingPointType, ComplexNumberType | | | | |
| _Decimal32 | Decimal32Type | | | | |
| _Decimal64 | Decimal64Type | | | | |
| _Decimal128 | Decimal128Type | | | | |
diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/WrongTypeFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/WrongTypeFormatArguments.expected
index 8a05434fde6..6e17cecc33b 100644
--- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/WrongTypeFormatArguments.expected
+++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/WrongTypeFormatArguments.expected
@@ -10,6 +10,8 @@
| printf1.h:44:18:44:20 | ull | This format specifier for type 'int' does not match the argument type 'unsigned long long'. |
| printf1.h:45:18:45:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:46:18:46:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
+| printf1.h:62:19:62:20 | ul | This format specifier for type 'size_t' does not match the argument type 'unsigned long'. |
+| printf1.h:68:19:68:21 | sst | This format specifier for type 'size_t' does not match the argument type 'long'. |
| printf1.h:71:19:71:20 | st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:72:19:72:20 | ST | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:73:19:73:22 | c_st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/printf1.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/printf1.h
index e2d4f50fc1f..2fb361d485c 100644
--- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/printf1.h
+++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/printf1.h
@@ -59,13 +59,13 @@ void g()
const SIZE_T C_ST = sizeof(st);
ssize_t sst;
- printf("%zu", ul); // ok (dubious, e.g. on 64-bit Windows `long` is 4 bytes but `size_t` is 8)
+ printf("%zu", ul); // not ok
printf("%zu", st); // ok
printf("%zu", ST); // ok
printf("%zu", c_st); // ok
printf("%zu", C_ST); // ok
printf("%zu", sizeof(ul)); // ok
- printf("%zu", sst); // not ok [NOT DETECTED]
+ printf("%zu", sst); // not ok
printf("%zd", ul); // not ok [NOT DETECTED]
printf("%zd", st); // not ok
diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/WrongTypeFormatArguments.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/WrongTypeFormatArguments.expected
index f50708f9eb4..0958cba59e7 100644
--- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/WrongTypeFormatArguments.expected
+++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/WrongTypeFormatArguments.expected
@@ -10,6 +10,8 @@
| printf1.h:44:18:44:20 | ull | This format specifier for type 'int' does not match the argument type 'unsigned long long'. |
| printf1.h:45:18:45:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:46:18:46:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
+| printf1.h:62:19:62:20 | ul | This format specifier for type 'size_t' does not match the argument type 'unsigned long'. |
+| printf1.h:68:19:68:21 | sst | This format specifier for type 'size_t' does not match the argument type 'long'. |
| printf1.h:71:19:71:20 | st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:72:19:72:20 | ST | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:73:19:73:22 | c_st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/printf1.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/printf1.h
index 223ffc6a212..8222cfa67b2 100644
--- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/printf1.h
+++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/printf1.h
@@ -59,13 +59,13 @@ void g()
const SIZE_T C_ST = sizeof(st);
ssize_t sst;
- printf("%zu", ul); // ok (dubious, e.g. on 64-bit Windows `long` is 4 bytes but `size_t` is 8)
+ printf("%zu", ul); // not ok
printf("%zu", st); // ok
printf("%zu", ST); // ok
printf("%zu", c_st); // ok
printf("%zu", C_ST); // ok
printf("%zu", sizeof(ul)); // ok
- printf("%zu", sst); // not ok [NOT DETECTED]
+ printf("%zu", sst); // not ok
printf("%zd", ul); // not ok [NOT DETECTED]
printf("%zd", st); // not ok
diff --git a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md
index 127bb19bbc6..99267b32a40 100644
--- a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md
+++ b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.7.43
+
+No user-facing changes.
+
## 1.7.42
No user-facing changes.
diff --git a/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.43.md b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.43.md
new file mode 100644
index 00000000000..10a22c6b4be
--- /dev/null
+++ b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.7.43.md
@@ -0,0 +1,3 @@
+## 1.7.43
+
+No user-facing changes.
diff --git a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml
index 8317cee0ddb..9b37539bf65 100644
--- a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml
+++ b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.7.42
+lastReleaseVersion: 1.7.43
diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml
index a86abb4812b..b9e0c245b85 100644
--- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml
+++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all
-version: 1.7.43-dev
+version: 1.7.44-dev
groups:
- csharp
- solorigate
diff --git a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md
index 127bb19bbc6..99267b32a40 100644
--- a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md
+++ b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.7.43
+
+No user-facing changes.
+
## 1.7.42
No user-facing changes.
diff --git a/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.43.md b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.43.md
new file mode 100644
index 00000000000..10a22c6b4be
--- /dev/null
+++ b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.7.43.md
@@ -0,0 +1,3 @@
+## 1.7.43
+
+No user-facing changes.
diff --git a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml
index 8317cee0ddb..9b37539bf65 100644
--- a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml
+++ b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.7.42
+lastReleaseVersion: 1.7.43
diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml
index caf1e66033e..7cf7f04a63a 100644
--- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml
+++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries
-version: 1.7.43-dev
+version: 1.7.44-dev
groups:
- csharp
- solorigate
diff --git a/csharp/ql/lib/CHANGELOG.md b/csharp/ql/lib/CHANGELOG.md
index 5eeedc6f77b..3124c68b6ab 100644
--- a/csharp/ql/lib/CHANGELOG.md
+++ b/csharp/ql/lib/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 5.1.9
+
+No user-facing changes.
+
## 5.1.8
No user-facing changes.
diff --git a/csharp/ql/lib/change-notes/released/5.1.9.md b/csharp/ql/lib/change-notes/released/5.1.9.md
new file mode 100644
index 00000000000..78965f168e0
--- /dev/null
+++ b/csharp/ql/lib/change-notes/released/5.1.9.md
@@ -0,0 +1,3 @@
+## 5.1.9
+
+No user-facing changes.
diff --git a/csharp/ql/lib/codeql-pack.release.yml b/csharp/ql/lib/codeql-pack.release.yml
index 8ffbb79d224..f9bf2605261 100644
--- a/csharp/ql/lib/codeql-pack.release.yml
+++ b/csharp/ql/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 5.1.8
+lastReleaseVersion: 5.1.9
diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml
index 464284c56cb..faa7e5e7198 100644
--- a/csharp/ql/lib/qlpack.yml
+++ b/csharp/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/csharp-all
-version: 5.1.9-dev
+version: 5.1.10-dev
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp
diff --git a/csharp/ql/src/CHANGELOG.md b/csharp/ql/src/CHANGELOG.md
index 4eabf64f6a5..da76eab521c 100644
--- a/csharp/ql/src/CHANGELOG.md
+++ b/csharp/ql/src/CHANGELOG.md
@@ -1,3 +1,14 @@
+## 1.3.0
+
+### Query Metadata Changes
+
+* Query metadata tags have been systematically updated for many C# queries. Primary categorization as either `reliability` or `maintainability`, and relevant sub-category tags such as `readability`, `useless-code`, `complexity`, `performance`, `correctness`, `error-handling`, and `concurrency`. Aligns with the established [Query file metadata and alert message style guide](https://github.com/github/codeql/blob/main/docs/query-metadata-style-guide.md#quality-query-sub-category-tags).
+* Adjusts the `@security-severity` from 9.3 to 7.3 for `cs/uncontrolled-format-string` to align `CWE-134` severity for memory safe languages to better reflect their impact.
+
+### Minor Analysis Improvements
+
+* The queries `cs/dereferenced-value-is-always-null` and `cs/dereferenced-value-may-be-null` have been improved to reduce false positives. The queries no longer assume that expressions are dereferenced when passed as the receiver (`this` parameter) to extension methods where that parameter is a nullable type.
+
## 1.2.2
No user-facing changes.
diff --git a/csharp/ql/src/change-notes/2025-06-03-dereferece-extension-method.md b/csharp/ql/src/change-notes/2025-06-03-dereferece-extension-method.md
deleted file mode 100644
index b12ec9768d5..00000000000
--- a/csharp/ql/src/change-notes/2025-06-03-dereferece-extension-method.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: minorAnalysis
----
-* The queries `cs/dereferenced-value-is-always-null` and `cs/dereferenced-value-may-be-null` have been improved to reduce false positives. The queries no longer assume that expressions are dereferenced when passed as the receiver (`this` parameter) to extension methods where that parameter is a nullable type.
diff --git a/csharp/ql/src/change-notes/2025-06-06-reduce-CWE-134-for-memory-safe-languages.md b/csharp/ql/src/change-notes/2025-06-06-reduce-CWE-134-for-memory-safe-languages.md
deleted file mode 100644
index 60006391ac6..00000000000
--- a/csharp/ql/src/change-notes/2025-06-06-reduce-CWE-134-for-memory-safe-languages.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: queryMetadata
----
-* Adjusts the `@security-severity` from 9.3 to 7.3 for `cs/uncontrolled-format-string` to align `CWE-134` severity for memory safe languages to better reflect their impact.
diff --git a/csharp/ql/src/change-notes/2025-06-16-tagging.md b/csharp/ql/src/change-notes/2025-06-16-tagging.md
deleted file mode 100644
index d0b8d2c41ee..00000000000
--- a/csharp/ql/src/change-notes/2025-06-16-tagging.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-category: queryMetadata
----
-* Query metadata tags have been systematically updated for many C# queries. Primary categorization as either `reliability` or `maintainability`, and relevant sub-category tags such as `readability`, `useless-code`, `complexity`, `performance`, `correctness`, `error-handling`, and `concurrency`. Aligns with the established [Query file metadata and alert message style guide](https://github.com/github/codeql/blob/main/docs/query-metadata-style-guide.md#quality-query-sub-category-tags).
diff --git a/csharp/ql/src/change-notes/released/1.3.0.md b/csharp/ql/src/change-notes/released/1.3.0.md
new file mode 100644
index 00000000000..91cd3426944
--- /dev/null
+++ b/csharp/ql/src/change-notes/released/1.3.0.md
@@ -0,0 +1,10 @@
+## 1.3.0
+
+### Query Metadata Changes
+
+* Query metadata tags have been systematically updated for many C# queries. Primary categorization as either `reliability` or `maintainability`, and relevant sub-category tags such as `readability`, `useless-code`, `complexity`, `performance`, `correctness`, `error-handling`, and `concurrency`. Aligns with the established [Query file metadata and alert message style guide](https://github.com/github/codeql/blob/main/docs/query-metadata-style-guide.md#quality-query-sub-category-tags).
+* Adjusts the `@security-severity` from 9.3 to 7.3 for `cs/uncontrolled-format-string` to align `CWE-134` severity for memory safe languages to better reflect their impact.
+
+### Minor Analysis Improvements
+
+* The queries `cs/dereferenced-value-is-always-null` and `cs/dereferenced-value-may-be-null` have been improved to reduce false positives. The queries no longer assume that expressions are dereferenced when passed as the receiver (`this` parameter) to extension methods where that parameter is a nullable type.
diff --git a/csharp/ql/src/codeql-pack.release.yml b/csharp/ql/src/codeql-pack.release.yml
index 0a70a9a01a7..ec16350ed6f 100644
--- a/csharp/ql/src/codeql-pack.release.yml
+++ b/csharp/ql/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 1.2.2
+lastReleaseVersion: 1.3.0
diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml
index 6437a730f15..b6307e4210a 100644
--- a/csharp/ql/src/qlpack.yml
+++ b/csharp/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/csharp-queries
-version: 1.2.3-dev
+version: 1.3.1-dev
groups:
- csharp
- queries
diff --git a/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/MVCTests/ProfileController.cs b/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/MVCTests/ProfileController.cs
index 9c20313b84b..84af3b50d1f 100644
--- a/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/MVCTests/ProfileController.cs
+++ b/csharp/ql/test/query-tests/Security Features/CWE-285/MissingAccessControl/MVCTests/ProfileController.cs
@@ -41,6 +41,14 @@ public class ProfileController : Controller
doThings();
return View();
}
+
+ // GOOD: The Authorize attribute is used.
+ [Authorize("foo")]
+ public ActionResult Delete5(int id)
+ {
+ doThings();
+ return View();
+ }
}
[Authorize]
diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-rust.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-rust.rst
new file mode 100644
index 00000000000..8aed9fc9326
--- /dev/null
+++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-rust.rst
@@ -0,0 +1,242 @@
+.. _analyzing-data-flow-in-rust:
+
+Analyzing data flow in Rust
+=============================
+
+You can use CodeQL to track the flow of data through a Rust program to places where the data is used.
+
+About this article
+------------------
+
+This article describes how data flow analysis is implemented in the CodeQL libraries for Rust and includes examples to help you write your own data flow queries.
+The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking.
+For a more general introduction to modeling data flow, see ":ref:`About data flow analysis `."
+
+.. include:: ../reusables/new-data-flow-api.rst
+
+Local data flow
+---------------
+
+Local data flow tracks the flow of data within a single method or callable. Local data flow is easier, faster, and more precise than global data flow. Before using more complex tracking, consider local tracking, as it is sufficient for many queries.
+
+Using local data flow
+~~~~~~~~~~~~~~~~~~~~~
+
+You can use the local data flow library by importing the ``codeql.rust.dataflow.DataFlow`` module. The library uses the class ``Node`` to represent any element through which data can flow.
+Common ``Node`` types include expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``).
+You can use the ``asExpr`` member predicate to map a data flow ``ExprNode`` to its corresponding ``ExprCfgNode`` in the control-flow library.
+Similarly, you can map a data flow ``ParameterNode`` to its corresponding ``Parameter`` AST node using the ``asParameter`` member predicate.
+
+.. code-block:: ql
+
+ class Node {
+ /**
+ * Gets the expression corresponding to this node, if any.
+ */
+ CfgNodes::ExprCfgNode asExpr() { ... }
+
+ /**
+ * Gets the parameter corresponding to this node, if any.
+ */
+ Parameter asParameter() { ... }
+
+ ...
+ }
+
+Note that because ``asExpr`` maps from data-flow to control-flow nodes, you need to call the ``getExpr`` member predicate on the control-flow node to map to the corresponding AST node. For example, you can write ``node.asExpr().getExpr()``.
+A control-flow graph considers every way control can flow through code, consequently, there can be multiple data-flow and control-flow nodes associated with a single expression node in the AST.
+
+The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``.
+You can apply the predicate recursively by using the ``+`` and ``*`` operators, or you can use the predefined recursive predicate ``localFlow``.
+
+For example, you can find flow from an expression ``source`` to an expression ``sink`` in zero or more local steps:
+
+.. code-block:: ql
+
+ DataFlow::localFlow(source, sink)
+
+Using local taint tracking
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Local taint tracking extends local data flow to include flow steps where values are not preserved, for example, string manipulation.
+For example:
+
+.. code-block:: rust
+
+ let y: String = "Hello ".to_owned() + x
+
+If ``x`` is a tainted string then ``y`` is also tainted.
+
+The local taint tracking library is in the module ``TaintTracking``.
+Like local data flow, a predicate ``localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo)`` holds if there is an immediate taint propagation edge from the node ``nodeFrom`` to the node ``nodeTo``.
+You can apply the predicate recursively by using the ``+`` and ``*`` operators, or you can use the predefined recursive predicate ``localTaint``.
+
+For example, you can find taint propagation from an expression ``source`` to an expression ``sink`` in zero or more local steps:
+
+.. code-block:: ql
+
+ TaintTracking::localTaint(source, sink)
+
+
+Using local sources
+~~~~~~~~~~~~~~~~~~~
+
+When exploring local data flow or taint propagation between two expressions, such as in the previous example, you typically constrain the expressions to those relevant to your investigation.
+The next section provides concrete examples, but first introduces the concept of a local source.
+
+A local source is a data-flow node with no local data flow into it.
+It is a local origin of data flow, a place where a new value is created.
+This includes parameters (which only receive values from global data flow) and most expressions (because they are not value-preserving).
+The class ``LocalSourceNode`` represents data-flow nodes that are also local sources.
+It includes a useful member predicate ``flowsTo(DataFlow::Node node)``, which holds if there is local data flow from the local source to ``node``.
+
+Examples of local data flow
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This query finds the argument passed in each call to ``File::create``:
+
+.. code-block:: ql
+
+ import rust
+
+ from CallExpr call
+ where call.getStaticTarget().(Function).getCanonicalPath() = "::create"
+ select call.getArg(0)
+
+Unfortunately, this only returns the expression used as the argument, not the possible values that could be passed to it. To address this, you can use local data flow to find all expressions that flow into the argument.
+
+.. code-block:: ql
+
+ import rust
+ import codeql.rust.dataflow.DataFlow
+
+ from CallExpr call, DataFlow::ExprNode source, DataFlow::ExprNode sink
+ where
+ call.getStaticTarget().(Function).getCanonicalPath() = "::create" and
+ sink.asExpr().getExpr() = call.getArg(0) and
+ DataFlow::localFlow(source, sink)
+ select source, sink
+
+You can vary the source by making the source the parameter of a function instead of an expression. The following query finds where a parameter is used in file creation:
+
+.. code-block:: ql
+
+ import rust
+ import codeql.rust.dataflow.DataFlow
+
+ from CallExpr call, DataFlow::ParameterNode source, DataFlow::ExprNode sink
+ where
+ call.getStaticTarget().(Function).getCanonicalPath() = "::create" and
+ sink.asExpr().getExpr() = call.getArg(0) and
+ DataFlow::localFlow(source, sink)
+ select source, sink
+
+Global data flow
+----------------
+
+Global data flow tracks data flow throughout the entire program, and is therefore more powerful than local data flow.
+However, global data flow is less precise than local data flow, and the analysis typically requires significantly more time and memory to perform.
+
+.. pull-quote:: Note
+
+ .. include:: ../reusables/path-problem.rst
+
+Using global data flow
+~~~~~~~~~~~~~~~~~~~~~~
+
+We can use the global data flow library by implementing the signature ``DataFlow::ConfigSig`` and applying the module ``DataFlow::Global``:
+
+.. code-block:: ql
+
+ import codeql.rust.dataflow.DataFlow
+
+ module MyDataFlowConfiguration implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) {
+ ...
+ }
+
+ predicate isSink(DataFlow::Node sink) {
+ ...
+ }
+ }
+
+ module MyDataFlow = DataFlow::Global;
+
+These predicates are defined in the configuration:
+
+- ``isSource`` - defines where data may flow from.
+- ``isSink`` - defines where data may flow to.
+- ``isBarrier`` - optional, defines where data flow is blocked.
+- ``isAdditionalFlowStep`` - optional, adds additional flow steps.
+
+The last line (``module MyDataFlow = ...``) instantiates the parameterized module for data flow analysis by passing the configuration to the parameterized module. Data flow analysis can then be performed using ``MyDataFlow::flow(DataFlow::Node source, DataFlow::Node sink)``:
+
+.. code-block:: ql
+
+ from DataFlow::Node source, DataFlow::Node sink
+ where MyDataFlow::flow(source, sink)
+ select source, "Dataflow to $@.", sink, sink.toString()
+
+Using global taint tracking
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Global taint tracking relates to global data flow in the same way that local taint tracking relates to local data flow.
+In other words, global taint tracking extends global data flow with additional non-value-preserving steps.
+The global taint tracking library uses the same configuration module as the global data flow library. You can perform taint flow analysis using ``TaintTracking::Global``:
+
+.. code-block:: ql
+
+ module MyTaintFlow = TaintTracking::Global;
+
+ from DataFlow::Node source, DataFlow::Node sink
+ where MyTaintFlow::flow(source, sink)
+ select source, "Taint flow to $@.", sink, sink.toString()
+
+Predefined sources
+~~~~~~~~~~~~~~~~~~
+
+The library module ``codeql.rust.Concepts`` contains a number of predefined sources and sinks that you can use to write security queries to track data flow and taint flow.
+
+Examples of global data flow
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The following global taint-tracking query finds places where a string literal is used in a function call argument named "password".
+ - Since this is a taint-tracking query, the ``TaintTracking::Global`` module is used.
+ - The ``isSource`` predicate defines sources as any ``StringLiteralExpr``.
+ - The ``isSink`` predicate defines sinks as arguments to a ``CallExpr`` called "password".
+ - The sources and sinks may need to be adjusted for a particular use. For example, passwords might be represented by a type other than ``String`` or passed in arguments with a different name than "password".
+
+.. code-block:: ql
+
+ import rust
+ import codeql.rust.dataflow.DataFlow
+ import codeql.rust.dataflow.TaintTracking
+
+ module ConstantPasswordConfig implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node node) { node.asExpr().getExpr() instanceof StringLiteralExpr }
+
+ predicate isSink(DataFlow::Node node) {
+ // any argument going to a parameter called `password`
+ exists(Function f, CallExpr call, int index |
+ call.getArg(index) = node.asExpr().getExpr() and
+ call.getStaticTarget() = f and
+ f.getParam(index).getPat().(IdentPat).getName().getText() = "password"
+ )
+ }
+ }
+
+ module ConstantPasswordFlow = TaintTracking::Global;
+
+ from DataFlow::Node sourceNode, DataFlow::Node sinkNode
+ where ConstantPasswordFlow::flow(sourceNode, sinkNode)
+ select sinkNode, "The value $@ is used as a constant password.", sourceNode, sourceNode.toString()
+
+
+Further reading
+---------------
+
+- `Exploring data flow with path queries `__ in the GitHub documentation.
+
+
+.. include:: ../reusables/rust-further-reading.rst
+.. include:: ../reusables/codeql-ref-tools-further-reading.rst
diff --git a/docs/codeql/codeql-language-guides/codeql-for-rust.rst b/docs/codeql/codeql-language-guides/codeql-for-rust.rst
new file mode 100644
index 00000000000..24292909467
--- /dev/null
+++ b/docs/codeql/codeql-language-guides/codeql-for-rust.rst
@@ -0,0 +1,16 @@
+
+.. _codeql-for-rust:
+
+CodeQL for Rust
+=========================
+
+Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Rust code.
+
+.. toctree::
+ :hidden:
+
+ codeql-library-for-rust
+ analyzing-data-flow-in-rust
+
+- :doc:`CodeQL library for Rust `: When analyzing Rust code, you can make use of the large collection of classes in the CodeQL library for Rust.
+- :doc:`Analyzing data flow in Rust `: You can use CodeQL to track the flow of data through a Rust program to places where the data is used.
diff --git a/docs/codeql/codeql-language-guides/codeql-library-for-rust.rst b/docs/codeql/codeql-language-guides/codeql-library-for-rust.rst
new file mode 100644
index 00000000000..84da28c7dfc
--- /dev/null
+++ b/docs/codeql/codeql-language-guides/codeql-library-for-rust.rst
@@ -0,0 +1,61 @@
+.. _codeql-library-for-rust:
+
+CodeQL library for Rust
+=================================
+
+When analyzing Rust code, you can make use of the large collection of classes in the CodeQL library for Rust.
+
+Overview
+--------
+
+CodeQL ships with a library for analyzing Rust code. The classes in this library present the data from a CodeQL database in an object-oriented form and provide
+abstractions and predicates to help you with common analysis tasks.
+
+The library is implemented as a set of CodeQL modules, which are files with the extension ``.qll``. The
+module `rust.qll `__ imports most other standard library modules, so you can include them
+by beginning your query with:
+
+.. code-block:: ql
+
+ import rust
+
+The CodeQL libraries model various aspects of Rust code. The above import includes the abstract syntax tree (AST) library, which is used for locating program elements
+to match syntactic elements in the source code. This can be used to find values, patterns, and structures.
+
+The control flow graph (CFG) is imported using:
+
+.. code-block:: ql
+
+ import codeql.rust.controlflow.ControlFlowGraph
+
+The CFG models the control flow between statements and expressions. For example, it can determine whether one expression can
+be evaluated before another expression, or whether an expression "dominates" another one, meaning that all paths to an
+expression must flow through another expression first.
+
+The data flow library is imported using:
+
+.. code-block:: ql
+
+ import codeql.rust.dataflow.DataFlow
+
+Data flow tracks the flow of data through the program, including across function calls (interprocedural data flow) and between steps in a job or workflow.
+Data flow is particularly useful for security queries, where untrusted data flows to vulnerable parts of the program. The taint-tracking library is related to data flow,
+and helps you find how data can *influence* other values in a program, even when it is not copied exactly.
+
+To summarize, the main Rust library modules are:
+
+.. list-table:: Main Rust library modules
+ :header-rows: 1
+
+ * - Import
+ - Description
+ * - ``rust``
+ - The standard Rust library
+ * - ``codeql.rust.elements``
+ - The abstract syntax tree library (also imported by `rust.qll`)
+ * - ``codeql.rust.controlflow.ControlFlowGraph``
+ - The control flow graph library
+ * - ``codeql.rust.dataflow.DataFlow``
+ - The data flow library
+ * - ``codeql.rust.dataflow.TaintTracking``
+ - The taint tracking library
diff --git a/docs/codeql/codeql-language-guides/customizing-library-models-for-javascript.rst b/docs/codeql/codeql-language-guides/customizing-library-models-for-javascript.rst
index fa2c1d4e8a8..413471be885 100644
--- a/docs/codeql/codeql-language-guides/customizing-library-models-for-javascript.rst
+++ b/docs/codeql/codeql-language-guides/customizing-library-models-for-javascript.rst
@@ -517,7 +517,6 @@ The following components are supported:
- **Member[**\ `name`\ **]** selects the property with the given name.
- **AnyMember** selects any property regardless of name.
- **ArrayElement** selects an element of an array.
-- **Element** selects an element of an array, iterator, or set object.
- **MapValue** selects a value of a map object.
- **Awaited** selects the value of a promise.
- **Instance** selects instances of a class, including instances of its subclasses.
diff --git a/docs/codeql/codeql-language-guides/index.rst b/docs/codeql/codeql-language-guides/index.rst
index ca03ebffd75..5ec9a715a4d 100644
--- a/docs/codeql/codeql-language-guides/index.rst
+++ b/docs/codeql/codeql-language-guides/index.rst
@@ -15,4 +15,5 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
codeql-for-javascript
codeql-for-python
codeql-for-ruby
+ codeql-for-rust
codeql-for-swift
diff --git a/docs/codeql/codeql-overview/codeql-tools.rst b/docs/codeql/codeql-overview/codeql-tools.rst
index ada1a75689e..12d13897413 100644
--- a/docs/codeql/codeql-overview/codeql-tools.rst
+++ b/docs/codeql/codeql-overview/codeql-tools.rst
@@ -39,6 +39,8 @@ maintained by GitHub are:
- ``codeql/python-all`` (`changelog `__, `source `__)
- ``codeql/ruby-queries`` (`changelog `__, `source `__)
- ``codeql/ruby-all`` (`changelog `__, `source `__)
+- ``codeql/rust-queries`` (`changelog `__, `source `__)
+- ``codeql/rust-all`` (`changelog `__, `source `__)
- ``codeql/swift-queries`` (`changelog `__, `source `__)
- ``codeql/swift-all`` (`changelog `__, `source `__)
diff --git a/docs/codeql/query-help/codeql-cwe-coverage.rst b/docs/codeql/query-help/codeql-cwe-coverage.rst
index 6236289a9ab..0c0089a576d 100644
--- a/docs/codeql/query-help/codeql-cwe-coverage.rst
+++ b/docs/codeql/query-help/codeql-cwe-coverage.rst
@@ -35,5 +35,5 @@ Note that the CWE coverage includes both "`supported queries `
- :doc:`CodeQL query help for Python `
- :doc:`CodeQL query help for Ruby `
+- :doc:`CodeQL query help for Rust `
- :doc:`CodeQL query help for Swift `
.. pull-quote:: Information
@@ -37,5 +38,6 @@ For a full list of the CWEs covered by these queries, see ":doc:`CodeQL CWE cove
javascript
python
ruby
+ rust
swift
codeql-cwe-coverage
diff --git a/docs/codeql/query-help/rust-cwe.md b/docs/codeql/query-help/rust-cwe.md
new file mode 100644
index 00000000000..6468ff890ac
--- /dev/null
+++ b/docs/codeql/query-help/rust-cwe.md
@@ -0,0 +1,7 @@
+# CWE coverage for Rust
+
+An overview of CWE coverage for Rust in the latest release of CodeQL.
+
+## Overview
+
+
diff --git a/docs/codeql/query-help/rust.rst b/docs/codeql/query-help/rust.rst
new file mode 100644
index 00000000000..b430fd3692e
--- /dev/null
+++ b/docs/codeql/query-help/rust.rst
@@ -0,0 +1,8 @@
+CodeQL query help for Rust
+============================
+
+.. include:: ../reusables/query-help-overview.rst
+
+These queries are published in the CodeQL query pack ``codeql/rust-queries`` (`changelog `__, `source `__).
+
+.. include:: toc-rust.rst
diff --git a/docs/codeql/reusables/extractors.rst b/docs/codeql/reusables/extractors.rst
index 30ccef6e465..c09926666b0 100644
--- a/docs/codeql/reusables/extractors.rst
+++ b/docs/codeql/reusables/extractors.rst
@@ -6,9 +6,9 @@
- Identifier
* - GitHub Actions
- ``actions``
- * - C/C++
+ * - C/C++
- ``cpp``
- * - C#
+ * - C#
- ``csharp``
* - Go
- ``go``
@@ -20,5 +20,7 @@
- ``python``
* - Ruby
- ``ruby``
+ - Rust
+ - ``rust``
* - Swift
- - ``swift``
\ No newline at end of file
+ - ``swift``
diff --git a/docs/codeql/reusables/rust-further-reading.rst b/docs/codeql/reusables/rust-further-reading.rst
new file mode 100644
index 00000000000..a82dee7f28e
--- /dev/null
+++ b/docs/codeql/reusables/rust-further-reading.rst
@@ -0,0 +1,2 @@
+- `CodeQL queries for Rust `__
+- `CodeQL library reference for Rust `__
diff --git a/docs/codeql/reusables/supported-frameworks.rst b/docs/codeql/reusables/supported-frameworks.rst
index 07a5e509fec..3d89a663004 100644
--- a/docs/codeql/reusables/supported-frameworks.rst
+++ b/docs/codeql/reusables/supported-frameworks.rst
@@ -307,6 +307,51 @@ and the CodeQL library pack ``codeql/ruby-all`` (`changelog `__, `source `__)
+and the CodeQL library pack ``codeql/rust-all`` (`changelog `__, `source `__).
+All support is experimental.
+
+.. csv-table::
+ :header-rows: 1
+ :class: fullWidthTable
+ :widths: auto
+ :align: left
+
+ Name, Category
+ `actix-web `__, Web framework
+ alloc, Standard library
+ `clap `__, Utility library
+ core, Standard library
+ `digest `__, Cryptography library
+ `futures-executor `__, Utility library
+ `hyper `__, HTTP library
+ `hyper-util `__, HTTP library
+ `libc `__, Utility library
+ `log `__, Logging library
+ `md5 `__, Utility library
+ `memchr `__, Utility library
+ `once_cell `__, Utility library
+ `poem `__, Web framework
+ `postgres `__, Database
+ proc_macro, Standard library
+ `rand `__, Utility library
+ `regex `__, Utility library
+ `reqwest `__, HTTP client
+ `rocket `__, Web framework
+ `rusqlite `__, Database
+ std, Standard library
+ `rust-crypto `__, Cryptography library
+ `serde `__, Serialization
+ `smallvec `__, Utility library
+ `sqlx `__, Database
+ `tokio `__, Asynchronous IO
+ `tokio-postgres `__, Database
+ `url `__, Utility library
+
Swift built-in support
================================
diff --git a/docs/codeql/reusables/supported-versions-compilers.rst b/docs/codeql/reusables/supported-versions-compilers.rst
index e85bc5d70f2..904a60b71cb 100644
--- a/docs/codeql/reusables/supported-versions-compilers.rst
+++ b/docs/codeql/reusables/supported-versions-compilers.rst
@@ -25,8 +25,9 @@
JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [8]_"
Python [9]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py``
Ruby [10]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
- Swift [11]_,"Swift 5.4-6.1","Swift compiler","``.swift``"
- TypeScript [12]_,"2.6-5.8",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``"
+ Rust [11]_,"Rust editions 2021 and 2024","Rust compiler","``.rs``, ``Cargo.toml``"
+ Swift [12]_,"Swift 5.4-6.1","Swift compiler","``.swift``"
+ TypeScript [13]_,"2.6-5.8",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``"
.. container:: footnote-group
@@ -40,5 +41,6 @@
.. [8] JSX and Flow code, YAML, JSON, HTML, and XML files may also be analyzed with JavaScript files.
.. [9] The extractor requires Python 3 to run. To analyze Python 2.7 you should install both versions of Python.
.. [10] Requires glibc 2.17.
- .. [11] Support for the analysis of Swift requires macOS.
- .. [12] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default.
+ .. [11] Requires ``rustup`` and ``cargo`` to be installed. Features from nightly toolchains are not supported.
+ .. [12] Support for the analysis of Swift requires macOS.
+ .. [13] TypeScript analysis is performed by running the JavaScript extractor with TypeScript enabled. This is the default.
diff --git a/docs/codeql/writing-codeql-queries/about-codeql-queries.rst b/docs/codeql/writing-codeql-queries/about-codeql-queries.rst
index f4e60b513c9..92e4b963bff 100644
--- a/docs/codeql/writing-codeql-queries/about-codeql-queries.rst
+++ b/docs/codeql/writing-codeql-queries/about-codeql-queries.rst
@@ -79,6 +79,7 @@ When writing your own alert queries, you would typically import the standard lib
- :ref:`CodeQL library guide for JavaScript `
- :ref:`CodeQL library guide for Python `
- :ref:`CodeQL library guide for Ruby `
+- :ref:`CodeQL library guide for Rust `
- :ref:`CodeQL library guide for TypeScript `
There are also libraries containing commonly used predicates, types, and other modules associated with different analyses, including data flow, control flow, and taint-tracking. In order to calculate path graphs, path queries require you to import a data flow library into the query file. For more information, see ":doc:`Creating path queries `."
diff --git a/docs/query-help-style-guide.md b/docs/query-help-style-guide.md
index 88b9844fc22..3ed9f439490 100644
--- a/docs/query-help-style-guide.md
+++ b/docs/query-help-style-guide.md
@@ -16,11 +16,33 @@ When you contribute a new [supported query](supported-queries.md) to this reposi
### Location and file name
-Query help files must have the same base name as the query they describe and must be located in the same directory.
+Query help files must have the same base name as the query they describe and must be located in the same directory.
### File structure and layout
-Query help files are written using a custom XML format, and stored in a file with a `.qhelp` extension. The basic structure is as follows:
+Query help files can be written in either a custom XML format (with a `.qhelp` extension) or in Markdown (with a `.md` extension). Both formats are supported by the CodeQL documentation tooling. There are a few minor differences, noted in the section `Differences between XML and markdown formats` below.
+
+#### Markdown query help files
+
+A Markdown query help file should use the following structure and section order (note that the `Implementation notes` section is optional):
+
+```
+## Overview
+
+## Recommendation
+
+## Example
+
+## Implementation notes
+
+## References
+```
+
+Each section should be clearly marked with the appropriate heading. See the other Markdown files in this repository for examples.
+
+#### XML query help files
+
+Query help files can also be written using a custom XML format, and stored in a file with a `.qhelp` extension. The basic structure is as follows:
```xml
@@ -33,7 +55,7 @@ The header and single top-level `` element are both mandatory.
### Section-level elements
-Section-level elements are used to group the information within the query help file. All query help files should include at least the following section elements, in the order specified:
+Section-level elements are used to group the information within the query help file. For both Markdown and XML formats, the following sections should be included, in the order specified:
1. `overview`—a short summary of the issue that the query identifies, including an explanation of how it could affect the behavior of the program.
2. `recommendation`—information on how to fix the issue highlighted by the query.
@@ -42,10 +64,9 @@ Section-level elements are used to group the information within the query help f
For further information about the other section-level, block, list and table elements supported by query help files, see [Query help files](https://codeql.github.com/docs/writing-codeql-queries/query-help-files/) on codeql.github.com.
-
## English style
-You should write the overview and recommendation elements in simple English that is easy to follow. You should:
+You should write the overview and recommendation sections in simple English that is easy to follow. You should:
* Use simple sentence structures and avoid complex or academic language.
* Avoid colloquialisms and contractions.
@@ -57,10 +78,11 @@ You should write the overview and recommendation elements in simple English that
Whenever possible, you should include a code example that helps to explain the issue you are highlighting. Any code examples that you include should adhere to the following guidelines:
* The example should be less than 20 lines, but it should still clearly illustrate the issue that the query identifies. If appropriate, then the example may also be runnable.
-* Put the code example after the recommendation element where possible. Only include an example in the description element if absolutely necessary.
+* Put the code example after the recommendation section where possible. Only include an example in the description section if absolutely necessary.
* If you are using an example to illustrate the solution to a problem, and the change required is minor, avoid repeating the whole example. It is preferable to either describe the change required or to include a smaller snippet of the corrected code.
* Clearly indicate which of the samples is an example of bad coding practice and which is recommended practice.
-* Define the code examples in `src` files. The language is inferred from the file extension:
+* For Markdown files, use fenced code blocks with the appropriate language identifier (for example, ```java ).
+* For XML files, define the code examples in `src` files. The language is inferred from the file extension:
```xml
@@ -74,11 +96,11 @@ Whenever possible, you should include a code example that helps to explain the i
```
-Note, if any code words are included in the `overview` and `recommendation` sections, they should be formatted with ` ... ` for emphasis.
+Note, if any code words are included in the `overview` and `recommendation` sections, in Markdown they should be formatted with backticks (`...`) and in XML they should be formatted with` ... ` for emphasis.
## Including references
-You should include one or more references, list formatted with ` ... ` for each item, to provide further information about the problem that your query is designed to find. References can be of the following types:
+You should include one or more references, formatted as an unordered list (`- ...` or `* ...`) in Markdown or with ` ... ` for each item in XML, to provide further information about the problem that your query is designed to find. References can be of the following types:
### Books
@@ -90,7 +112,7 @@ For example:
>W. C. Wake, _Refactoring Workbook_, pp. 93 – 94, Addison-Wesley Professional, 2004.
-Note, & symbols need to be replaced by \&. The symbol will be displayed correctly in the HTML files generated from the query help files.
+Note, & symbols need to be replaced by \& in XML. The symbol will be displayed correctly in the HTML files generated from the query help files.
### Academic papers
@@ -98,7 +120,6 @@ If you are citing an academic paper, we recommend adopting the reference style o
>S. R. Chidamber and C. F. Kemerer, _A metrics suite for object-oriented design_. IEEE Transactions on Software Engineering, 20(6):476-493, 1994.
-
### Websites
If you are citing a website, please use the following format, without breadcrumb trails:
@@ -111,28 +132,123 @@ For example:
### Referencing potential security weaknesses
-If your query checks code for a CWE weakness, you should use the `@tags` element in the query file to reference the associated CWEs, as explained [here](query-metadata-style-guide.md). When you use these tags, a link to the appropriate entry from the [MITRE.org](https://cwe.mitre.org/scoring/index.html) site will automatically appear as a reference in the output HTML file.
+If your query checks code for a CWE weakness, you should use the `@tags` element in the query file to reference the associated CWEs, as explained [here](query-metadata-style-guide.md). When you use these tags in a query help file in the custom XML format, a link to the appropriate entry from the [MITRE.org](https://cwe.mitre.org/scoring/index.html) site will automatically appear as a reference in the output HTML file.
-## Validating qhelp files
+## Validating query help files
-Before making a pull request, please ensure the `.qhelp` files are well-formed and can be generated without errors. This can be done locally with the CodeQL CLI, as shown in the following example:
+Before making a pull request, please ensure the `.qhelp` or `.md` files are well-formed and can be generated without errors. This can be done locally with the CodeQL CLI, as shown in the following example:
```bash
# codeql generate query-help --format=
# For example:
codeql generate query-help ./myCustomQuery.qhelp --format=markdown
+codeql generate query-help ./myCustomQuery.md --format=markdown
```
+Please include the query help files (and any associated code snippets) in your pull request, but do not commit the generated Markdown.
-Please include the `.qhelp` files (and any associated code snippets) in your pull request, but do not commit the generated Markdown.
+More information on how to test your query help files can be found [within the documentation](https://docs.github.com/en/code-security/codeql-cli/using-the-codeql-cli/testing-query-help-files)
-More information on how to test your `.qhelp` files can be found [within the documentation](https://docs.github.com/en/code-security/codeql-cli/using-the-codeql-cli/testing-query-help-files)
+## Differences between XML and markdown formats
+
+1. The XML format allows for the contents of other files to be included in the output generated by processing the file, as mentioned in the section `Code examples`. This is not possible with the Markdown format.
+2. When using the XML format, references are added to the output HTML file based on CWE tags, as mentioned in the section `Referencing potential security weaknesses`.
+3. For custom queries and custom query packs, only the Markdown format is supported.
## Query help example
-The following example is a query help file for a query from the standard query suite for Java:
+The following example is a query help file for a query from the standard query suite for Java, shown in both Markdown and XML formats.
-```xml
+### Markdown example
+
+````markdown
+# Overview
+
+A control structure (an `if` statement or a loop) has a body that is either a block
+of statements surrounded by curly braces or a single statement.
+
+If you omit braces, it is particularly important to ensure that the indentation of the code
+matches the control flow of the code.
+
+## Recommendation
+
+It is usually considered good practice to include braces for all control
+structures in Java. This is because it makes it easier to maintain the code
+later. For example, it's easy to see at a glance which part of the code is in the
+scope of an `if` statement, and adding more statements to the body of the `if`
+statement is less error-prone.
+
+You should also ensure that the indentation of the code is consistent with the actual flow of
+control, so that it does not confuse programmers.
+
+## Example
+
+In the example below, the original version of `Cart` is missing braces. This means
+that the code triggers a `NullPointerException` at runtime if `i`
+is `null`.
+
+```java
+class Cart {
+ Map items = ...
+ public void addItem(Item i) {
+ // No braces and misleading indentation.
+ if (i != null)
+ log("Adding item: " + i);
+ // Indentation suggests that the following statements
+ // are in the body of the 'if'.
+ Integer curQuantity = items.get(i.getID());
+ if (curQuantity == null) curQuantity = 0;
+ items.put(i.getID(), curQuantity+1);
+ }
+}
+```
+
+The corrected version of `Cart` does include braces, so
+that the code executes as the indentation suggests.
+
+```java
+class Cart {
+ Map items = ...
+ public void addItem(Item i) {
+ // Braces included.
+ if (i != null) {
+ log("Adding item: " + i);
+ Integer curQuantity = items.get(i.getID());
+ if (curQuantity == null) curQuantity = 0;
+ items.put(i.getID(), curQuantity+1);
+ }
+ }
+}
+```
+
+In the following example the indentation may or may not be misleading depending on your tab width
+settings. As such, mixing tabs and spaces in this way is not recommended, since what looks fine in
+one context can be very misleading in another.
+
+```java
+// Tab width 8
+ if (b) // Indentation: 1 tab
+ f(); // Indentation: 2 tabs
+ g(); // Indentation: 8 spaces
+
+// Tab width 4
+ if (b) // Indentation: 1 tab
+ f(); // Indentation: 2 tabs
+ g(); // Indentation: 8 spaces
+```
+
+If you mix tabs and spaces in this way, then you might get seemingly false positives, since your
+tab width settings cannot be taken into account.
+
+## References
+
+* Java SE Documentation: [Compound Statements](https://www.oracle.com/java/technologies/javase/codeconventions-statements.html#15395)
+* Wikipedia: [Indentation style](https://en.wikipedia.org/wiki/Indentation_style)
+````
+
+### XML example
+
+````xml
@@ -154,13 +270,13 @@ later. For example, it's easy to see at a glance which part of the code is in th
scope of an