gcc/ChangeLog:
* doc/libdiagnostics/Makefile: New file.
* doc/libdiagnostics/conf.py: New file.
* doc/libdiagnostics/index.rst: New file.
* doc/libdiagnostics/make.bat: New file.
* doc/libdiagnostics/topics/diagnostic-manager.rst: New file.
* doc/libdiagnostics/topics/diagnostics.rst: New file.
* doc/libdiagnostics/topics/execution-paths.rst: New file.
* doc/libdiagnostics/topics/fix-it-hints.rst: New file.
* doc/libdiagnostics/topics/index.rst: New file.
* doc/libdiagnostics/topics/logical-locations.rst: New file.
* doc/libdiagnostics/topics/message-formatting.rst: New file.
* doc/libdiagnostics/topics/metadata.rst: New file.
* doc/libdiagnostics/topics/physical-locations.rst: New file.
* doc/libdiagnostics/topics/retrofitting.rst: New file.
* doc/libdiagnostics/topics/sarif.rst: New file.
* doc/libdiagnostics/topics/text-output.rst: New file.
* doc/libdiagnostics/topics/ux.rst: New file.
* doc/libdiagnostics/tutorial/01-hello-world.rst: New file.
* doc/libdiagnostics/tutorial/02-physical-locations.rst: New file.
* doc/libdiagnostics/tutorial/03-logical-locations.rst: New file.
* doc/libdiagnostics/tutorial/04-notes.rst: New file.
* doc/libdiagnostics/tutorial/05-warnings.rst: New file.
* doc/libdiagnostics/tutorial/06-fix-it-hints.rst: New file.
* doc/libdiagnostics/tutorial/07-execution-paths.rst: New file.
* doc/libdiagnostics/tutorial/index.rst: New file.
Signed-off-by: David Malcolm <[email protected]>
---
gcc/doc/libdiagnostics/Makefile | 20 ++
gcc/doc/libdiagnostics/conf.py | 27 ++
gcc/doc/libdiagnostics/index.rst | 113 +++++++
gcc/doc/libdiagnostics/make.bat | 35 +++
.../topics/diagnostic-manager.rst | 58 ++++
gcc/doc/libdiagnostics/topics/diagnostics.rst | 127 ++++++++
.../libdiagnostics/topics/execution-paths.rst | 93 ++++++
.../libdiagnostics/topics/fix-it-hints.rst | 135 +++++++++
gcc/doc/libdiagnostics/topics/index.rst | 38 +++
.../topics/logical-locations.rst | 109 +++++++
.../topics/message-formatting.rst | 224 ++++++++++++++
gcc/doc/libdiagnostics/topics/metadata.rst | 149 ++++++++++
.../topics/physical-locations.rst | 281 ++++++++++++++++++
.../libdiagnostics/topics/retrofitting.rst | 23 ++
gcc/doc/libdiagnostics/topics/sarif.rst | 51 ++++
gcc/doc/libdiagnostics/topics/text-output.rst | 87 ++++++
gcc/doc/libdiagnostics/topics/ux.rst | 26 ++
.../tutorial/01-hello-world.rst | 173 +++++++++++
.../tutorial/02-physical-locations.rst | 260 ++++++++++++++++
.../tutorial/03-logical-locations.rst | 60 ++++
gcc/doc/libdiagnostics/tutorial/04-notes.rst | 66 ++++
.../libdiagnostics/tutorial/05-warnings.rst | 44 +++
.../tutorial/06-fix-it-hints.rst | 61 ++++
.../tutorial/07-execution-paths.rst | 141 +++++++++
gcc/doc/libdiagnostics/tutorial/example-1.png | Bin 0 -> 5646 bytes
gcc/doc/libdiagnostics/tutorial/index.rst | 32 ++
26 files changed, 2433 insertions(+)
create mode 100644 gcc/doc/libdiagnostics/Makefile
create mode 100644 gcc/doc/libdiagnostics/conf.py
create mode 100644 gcc/doc/libdiagnostics/index.rst
create mode 100644 gcc/doc/libdiagnostics/make.bat
create mode 100644 gcc/doc/libdiagnostics/topics/diagnostic-manager.rst
create mode 100644 gcc/doc/libdiagnostics/topics/diagnostics.rst
create mode 100644 gcc/doc/libdiagnostics/topics/execution-paths.rst
create mode 100644 gcc/doc/libdiagnostics/topics/fix-it-hints.rst
create mode 100644 gcc/doc/libdiagnostics/topics/index.rst
create mode 100644 gcc/doc/libdiagnostics/topics/logical-locations.rst
create mode 100644 gcc/doc/libdiagnostics/topics/message-formatting.rst
create mode 100644 gcc/doc/libdiagnostics/topics/metadata.rst
create mode 100644 gcc/doc/libdiagnostics/topics/physical-locations.rst
create mode 100644 gcc/doc/libdiagnostics/topics/retrofitting.rst
create mode 100644 gcc/doc/libdiagnostics/topics/sarif.rst
create mode 100644 gcc/doc/libdiagnostics/topics/text-output.rst
create mode 100644 gcc/doc/libdiagnostics/topics/ux.rst
create mode 100644 gcc/doc/libdiagnostics/tutorial/01-hello-world.rst
create mode 100644 gcc/doc/libdiagnostics/tutorial/02-physical-locations.rst
create mode 100644 gcc/doc/libdiagnostics/tutorial/03-logical-locations.rst
create mode 100644 gcc/doc/libdiagnostics/tutorial/04-notes.rst
create mode 100644 gcc/doc/libdiagnostics/tutorial/05-warnings.rst
create mode 100644 gcc/doc/libdiagnostics/tutorial/06-fix-it-hints.rst
create mode 100644 gcc/doc/libdiagnostics/tutorial/07-execution-paths.rst
create mode 100644 gcc/doc/libdiagnostics/tutorial/example-1.png
create mode 100644 gcc/doc/libdiagnostics/tutorial/index.rst
diff --git a/gcc/doc/libdiagnostics/Makefile b/gcc/doc/libdiagnostics/Makefile
new file mode 100644
index 000000000000..d4bb2cbb9edd
--- /dev/null
+++ b/gcc/doc/libdiagnostics/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = .
+BUILDDIR = _build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/gcc/doc/libdiagnostics/conf.py b/gcc/doc/libdiagnostics/conf.py
new file mode 100644
index 000000000000..1ff7552411d0
--- /dev/null
+++ b/gcc/doc/libdiagnostics/conf.py
@@ -0,0 +1,27 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# For the full list of built-in configuration values, see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Project information -----------------------------------------------------
+#
https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = 'libdiagnostics'
+copyright = '2024, David Malcolm'
+author = 'David Malcolm'
+
+# -- General configuration ---------------------------------------------------
+#
https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = []
+
+templates_path = ['_templates']
+exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+
+
+
+# -- Options for HTML output -------------------------------------------------
+#
https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+html_theme = 'alabaster'
+html_static_path = ['_static']
diff --git a/gcc/doc/libdiagnostics/index.rst b/gcc/doc/libdiagnostics/index.rst
new file mode 100644
index 000000000000..a05eb4ef261d
--- /dev/null
+++ b/gcc/doc/libdiagnostics/index.rst
@@ -0,0 +1,113 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+libdiagnostics
+==============
+
+This document describes `libdiagnostics
<https://gcc.gnu.org/wiki/libdiagnostics>`_,
+an API for programs to use to emit diagnostics (such as for "lint"-style
checker
+tools), supporting:
+
+* text output similar to GCC's errors and warnings::
+
+ test-typo.c:19:13: error: unknown field 'colour'
+ 19 | return p->colour;
+ | ^~~~~~
+
+ quoting pertinent source code (with a cache), and underlining
+ :doc:`points and ranges in the files being tested
<tutorial/02-physical-locations>`,
+ possibly with labels::
+
+ test-labelled-ranges.c:9:6: error: mismatching types: 'int' and 'const char
*'
+ 19 | 42 + "foo"
+ | ~~ ^ ~~~~~
+ | | |
+ | int const char *
+
+* emitting :doc:`fix-it hints <tutorial/06-fix-it-hints>`::
+
+ test-fix-it-hint.c:19:13: error: unknown field 'colour'; did you mean
'color'
+ 19 | return p->colour;
+ | ^~~~~~
+ | color
+
+ and generating patches from them::
+
+ @@ -16,7 +16,7 @@
+ struct rgb
+ get_color (struct object *p)
+ {
+ - return p->colour;
+ + return p->color;
+ }
+
+* capturing :doc:`execution paths<tutorial/07-execution-paths>` through code::
+
+ In function 'make_a_list_of_random_ints_badly':
+ test-warning-with-path.c:30:5: warning: passing NULL as argument 1 to
'PyList_Append' which requires a non-NULL parameter"
+ 30 | PyList_Append(list, item);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~
+ make_a_list_of_random_ints_badly': events 1-3
+ 26 | list = PyList_New(0);
+ | ^~~~~~~~~~~~~
+ | |
+ | (1) when 'PyList_New' fails, returning NULL
+ 27 |
+ 28 | for (i = 0; i < count; i++) {
+ | ~~~~~~~~~
+ | |
+ | (2) when 'i < count'
+ 29 | item = PyLong_FromLong(random());
+ 30 | PyList_Append(list, item);
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | |
+ | (3) when calling 'PyList_Append', passing NULL from (1) as
argument 1
+
+* support for emitting machine-readable representations of the above
+ using the :doc:`SARIF file format <topics/sarif>`
+
+There are actually two APIs for the library:
+
+* a pure C API: ``libdiagnostics.h``
+
+* a C++ wrapper API: ``libdiagnostics+.h``. This is a header-only
+ collection of wrapper classes around the C API to give a less
+ verbose API.
+
+This documentation covers the C API.
+
+Contents
+********
+
+.. toctree::
+ :maxdepth: 2
+
+ tutorial/index.rst
+ topics/index.rst
+
+libdiagnostics is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+
+Indices and tables
+******************
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/gcc/doc/libdiagnostics/make.bat b/gcc/doc/libdiagnostics/make.bat
new file mode 100644
index 000000000000..954237b9b9f2
--- /dev/null
+++ b/gcc/doc/libdiagnostics/make.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively
you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.https://www.sphinx-doc.org/
+ exit /b 1
+)
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/gcc/doc/libdiagnostics/topics/diagnostic-manager.rst
b/gcc/doc/libdiagnostics/topics/diagnostic-manager.rst
new file mode 100644
index 000000000000..7f86f6bba613
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/diagnostic-manager.rst
@@ -0,0 +1,58 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Diagnostic Managers
+===================
+
+.. type:: diagnostic_manager;
+
+A :type:`diagnostic_manager` is an opaque bundle of state for a client of
+libdiagnostics.
+
+It has zero of more "output sinks" to which diagnostics are emitted.
+
+Responsibilities include:
+
+* location-management
+
+* caching of source file content
+
+* patch generation
+
+.. function:: diagnostic_manager *diagnostic_manager_new (void)
+
+ Create a new diagnostic_manager.
+ The caller will need to call :func:`diagnostic_release_manager`
+ on it at some point.
+
+ .. note:: No output sinks are created by default; so you will want
+ to create one with something like:
+
+ .. code-block::
+
+ diagnostic_manager_add_text_sink (diag_mgr, stderr,
+ DIAGNOSTIC_COLORIZE_IF_TTY);
+
+.. function:: void diagnostic_manager_release (diagnostic_manager *diag_mgr)
+
+ Release a diagnostic_manager.
+
+ This will flush output to all of the output sinks, and clean up.
+
+ The parameter must be non-NULL.
diff --git a/gcc/doc/libdiagnostics/topics/diagnostics.rst
b/gcc/doc/libdiagnostics/topics/diagnostics.rst
new file mode 100644
index 000000000000..66f0a25143cb
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/diagnostics.rst
@@ -0,0 +1,127 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Diagnostics
+===========
+
+.. type:: diagnostic
+
+A :type:`diagnostic` is an opaque bundle of state for a particular
+diagnostic that is being constructed in memory.
+
+
+Lifecycle of a diagnostic
+*************************
+
+Diagnostics are
+
+* *created* from a :type:`diagnostic_manager` by using
+ :func:`diagnostic_begin`, then
+
+* *populated* with data, such as physical locations, logical locations,
+ metadata, execution paths, or fix-it hints, then
+
+* *finished*, in which a formatting string and arguments are given,
+ via a call to :func:`diagnostic_finish` or :func:`diagnostic_finish_va`.
+ The :type:`diagnostic_manager` will emit the diagnostic to all of the
+ manager's output sinks (either immediately, or at some later time,
+ depending on the sink).
+
+ Once a :type:`diagnostic` has had one of these "finish" functions called
+ on it, it is freed, and is no longer valid for use.
+
+ The formatting strings use their own syntax; see :doc:`message-formatting`.
+
+.. function:: diagnostic *diagnostic_begin (diagnostic_manager *diag_mgr, \
+ enum diagnostic_level level)
+
+ Create a new :type:`diagnostic` associated with the given
+ :type:`diagnostic_manager`.
+
+ The parameter ``diag_mgr`` must be non-NULL.
+
+ The parameter ``level`` describes the severity of the diagnostic.
+
+.. enum:: diagnostic_level
+
+ This enum describes the severity of a particular diagnostic.
+
+ .. macro:: DIAGNOSTIC_LEVEL_ERROR
+
+ A problem sufficiently severe that the program cannot successfully
+ complete, or where the input being analyzed is definitely wrong
+ (e.g. malformed).
+
+ .. macro:: DIAGNOSTIC_LEVEL_WARNING
+
+ A problem where the input is technically correct, but is likely
+ not what the user intended, such as common mistakes, or other
+ unusual conditions that *may* indicate trouble, such as use of
+ obsolete features.
+
+ .. macro:: DIAGNOSTIC_LEVEL_NOTE
+
+ A supplementary message added to another :type:`diagnostic`, giving
+ extra information that may help the user understand it.
+
+ .. macro:: DIAGNOSTIC_LEVEL_SORRY
+
+ A problem where the input is valid, but the tool isn't
+ able to handle it.
+
+.. function:: void diagnostic_finish (diagnostic *diag, const char *fmt, ...)
+
+ Emit ``diag`` to all sinks of its manager, and release ``diag``. It is not
+ valid to use ``diag`` after this call.
+
+ Use parameter ``fmt`` for the message.
+ Note that this uses gcc's pretty-print format, which is *not* printf.
+ See :doc:`message-formatting`.
+
+ Both ``diag`` and ``fmt`` must be non-NULL.
+
+ TODO: who is responsible for putting FMT through gettext?
+
+.. function:: void diagnostic_finish_va (diagnostic *diag, const char *fmt,
va_list *args)
+
+ This is equivalent to :func:`diagnostic_finish`, but using a
+ :type:`va_list` rather than directly taking variadic arguments.
+
+ All three parameters must be non-NULL.
+
+
+Diagnostic groups
+*****************
+
+See :doc:`the "adding notes" section of the tutorial <../tutorial/04-notes>`
+for an example of a diagnostic group.
+
+.. function:: void diagnostic_manager_begin_group (diagnostic_manager
*diag_mgr)
+
+ Begin a diagnostic group. All diagnostics emitted within
+ ``diag_mgr`` after the first one will be treated as additional information
+ relating to the initial diagnostic.
+
+ The parameter ``diag_mgr`` must be non-NULL.
+
+.. function:: void diagnostic_manager_end_group (diagnostic_manager *diag_mgr)
+
+ Finish a diagnostic group.
+
+ The parameter ``diag_mgr`` must be non-NULL.
diff --git a/gcc/doc/libdiagnostics/topics/execution-paths.rst
b/gcc/doc/libdiagnostics/topics/execution-paths.rst
new file mode 100644
index 000000000000..3f4109ce4f33
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/execution-paths.rst
@@ -0,0 +1,93 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Execution paths
+===============
+
+.. type:: diagnostic_execution_path
+
+A :type:`diagnostic` can optionally contain a :type:`diagnostic_execution_path`
+describing a path of execution through code.
+
+.. function:: diagnostic_execution_path * diagnostic_add_execution_path
(diagnostic *diag)
+
+ Create and borrow a pointer to an execution path for ``diag``.
+
+ The path is automatically cleaned up when ``diag`` is finished.
+
+ ``diag`` must be non-NULL.
+
+.. function:: diagnostic_execution_path *
diagnostic_manager_new_execution_path (diagnostic_manager *diag_mgr)
+
+ Create a new execution path. This is owned by the caller and must have
either
+ :func:`diagnostic_take_execution_path` or
+ :func:`diagnostic_execution_path_release` called on it.
+
+ ``diag_mgr`` must be non-NULL.
+
+.. function:: void diagnostic_take_execution_path (diagnostic *diag,
diagnostic_execution_path *path)
+
+ Set ``diag`` to use ``path`` as its execution path, taking ownership of
``path``.
+
+ Both parameters must be non-NULL.
+
+.. function:: void diagnostic_execution_path_release
(diagnostic_execution_path *path)
+
+ Release ownership of ``path``, which must not have been taken by a
diagnostic.
+
+.. type:: diagnostic_event_id
+
+A :type:`diagnostic_event_id` identifies a particular event within a
+:type:`diagnostic_execution_path` and can be used for expressing
+cross-references between events. In particular FIXME
+
+.. function:: diagnostic_event_id diagnostic_execution_path_add_event
(diagnostic_execution_path *path, \
+ const
diagnostic_physical_location *physical_loc, \
+ const
diagnostic_logical_location *logical_loc, \
+
unsigned stack_depth, \
+ const
char *fmt, ...)
+
+ Append an event to the end of ``path``, which must be non-NULL.
+
+ ``physical_loc`` can be NULL, or non-NULL to associate the event
+ with a :type:`diagnostic_physical_location`.
+
+ ``logical_loc`` can be NULL, or non-NULL to associate the event
+ with a :type:`diagnostic_logical_location`.
+
+ ``stack_depth`` is for use in interprocedural paths and identifies the
+ depth of the stack at the event. Purely intraprocedural paths should
+ use a stack depth of 1 for their events
+
+ ``fmt`` must be non-NULL. See :doc:`message-formatting` for details of
+ how to use it.
+
+.. function:: diagnostic_event_id diagnostic_execution_path_add_event_va
(diagnostic_execution_path *path, \
+
const diagnostic_physical_location *physical_loc, \
+
const diagnostic_logical_location *logical_loc, \
+
unsigned stack_depth, \
+
const char *fmt, \
+
va_list *args)
+
+ Equivalent to :func:`diagnostic_execution_path_add_event`, but using a
+ :type:`va_list` rather than directly taking variadic arguments.
+
+Paths are printed to text sinks, and for SARIF sinks each path is added as
+a ``codeFlow`` object (see SARIF 2.1.0
+`3.36 codeFlow object
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790990>`_).
diff --git a/gcc/doc/libdiagnostics/topics/fix-it-hints.rst
b/gcc/doc/libdiagnostics/topics/fix-it-hints.rst
new file mode 100644
index 000000000000..08acb7119a14
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/fix-it-hints.rst
@@ -0,0 +1,135 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Fix-it hints
+============
+
+Adding fix-it hints to a diagnostic
+***********************************
+
+A :type:`diagnostic` can contain "fix-it hints", giving suggestions
+for the user on how to edit their code to fix a problem. These
+can be expressed as insertions, replacements, and removals of text.
+
+There is only limited support for newline characters in fix-it hints:
+only hints with newlines which insert an entire new line are permitted,
+inserting at the start of a line, and finishing with a newline
+(with no interior newline characters). Other attempts to add
+fix-it hints containing newline characters will fail.
+Similarly, attempts to delete or replace a range *affecting* multiple
+lines will fail.
+
+The API handles these failures gracefully, so that diagnostics can attempt
+to add fix-it hints without each needing extensive checking.
+
+Fix-it hints are printed to text sinks, and are emitted by SARIF sinks
+as ``fix`` objects (see SARIF 2.1.0
+`3.55 fix object
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141791131>`_).
+
+Fix-it hints within a :type:`diagnostic` are "atomic": if any hints can't
+be applied, none of them will be, and no fix-its hints will be displayed
+for that diagnostic. This implies that diagnostic messages need to be worded
+in such a way that they make sense whether or not the fix-it hints
+are displayed.
+
+All fix-it hints within one :type:`diagnostic` must affect the same
+:type:`diagnostic_file`.
+
+.. function:: void diagnostic_add_fix_it_hint_insert_before (diagnostic *diag,
\
+ const
diagnostic_physical_location *loc, \
+ const char
*addition)
+
+ Add a fix-it hint to ``diag`` suggesting the insertion of the string
+ ``addition`` before ``LOC``.
+
+ For example::
+
+ ptr = arr[0];
+ ^~~~~~
+ &
+
+ This :type:`diagnostic` has a single location covering ``arr[0]``,
+ with the caret at the start. It has a single insertion fix-it hint,
+ inserting ``&`` before the start of ``loc``.
+
+.. function:: void diagnostic_add_fix_it_hint_insert_after (diagnostic *diag, \
+ const
diagnostic_physical_location *loc, \
+ const char
*addition)
+
+ Add a fix-it hint to ``diag`` suggesting the insertion of the string
+ ``addition`` after the end of ``LOC``.
+
+ For example, in::
+
+ #define FN(ARG0, ARG1, ARG2) fn(ARG0, ARG1, ARG2)
+ ^~~~ ^~~~ ^~~~
+ ( ) ( ) ( )
+
+
+ the :type:`diagnostic` has three physical locations, covering ``ARG0``,
+ ``ARG1``, and ``ARG2``, and 6 insertion fix-it hints: each arg
+ has a pair of insertion fix-it hints, suggesting wrapping
+ them with parentheses: one a '(' inserted before,
+ the other a ')' inserted after.
+
+.. function:: void diagnostic_add_fix_it_hint_replace (diagnostic *diag, \
+ const
diagnostic_physical_location *loc, \
+ const char *replacement)
+
+ Add a fix-it hint to ``diag`` suggesting the replacement of the text
+ at ``LOC`` with the string ``replacement``.
+
+ For example, in::
+
+ c = s.colour;
+ ^~~~~~
+ color
+
+ This :type:`diagnostic` has a single physical location covering ``colour``,
+ and a single "replace" fix-it hint, covering the same range, suggesting
+ replacing it with ``color``.
+
+.. function:: void diagnostic_add_fix_it_hint_delete (diagnostic *diag, \
+ const
diagnostic_physical_location *loc)
+
+ Add a fix-it hint to ``diag`` suggesting the deletion of the text
+ at ``LOC``.
+
+
+ For example, in::
+
+ struct s {int i};;
+ ^
+ -
+
+ This :type:`diagnostic` has a single physical location at the stray
+ trailing semicolon, along with a single removal fix-it hint, covering
+ the same location.
+
+
+Generating patches
+******************
+
+.. function:: void diagnostic_manager_write_patch (diagnostic_manager
*diag_mgr, \
+ FILE *dst_stream)
+
+ Write a patch to ``dst_stream`` consisting of the effect of all fix-it hints
+ on all diagnostics that have been finished on ``diag_mgr``.
+
+ Both parameters must be non-NULL.
diff --git a/gcc/doc/libdiagnostics/topics/index.rst
b/gcc/doc/libdiagnostics/topics/index.rst
new file mode 100644
index 000000000000..064340b98ba7
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/index.rst
@@ -0,0 +1,38 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+
+Topic reference
+===============
+
+.. toctree::
+ :maxdepth: 2
+
+ retrofitting.rst
+ diagnostic-manager.rst
+ diagnostics.rst
+ message-formatting.rst
+ physical-locations.rst
+ logical-locations.rst
+ metadata.rst
+ fix-it-hints.rst
+ execution-paths.rst
+ text-output.rst
+ sarif.rst
+ ux.rst
diff --git a/gcc/doc/libdiagnostics/topics/logical-locations.rst
b/gcc/doc/libdiagnostics/topics/logical-locations.rst
new file mode 100644
index 000000000000..85900b6344f2
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/logical-locations.rst
@@ -0,0 +1,109 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Logical locations
+=================
+
+A "logical" location is a location expressed in terms of
+construct in a programming language, such as ``within function 'foo'``
+(as opposed to a :doc:`"physical" location <physical-locations>`, which
+refers to a specific file, and line(s) and/or column(s))
+
+Creating location information
+*****************************
+
+.. type:: diagnostic_logical_location
+
+A :type:`diagnostic_logical_location` is an opaque type describing a "logical"
+source location
+
+.. function:: const diagnostic_logical_location *
diagnostic_manager_new_logical_location (diagnostic_manager *diag_mgr, \
+
enum diagnostic_logical_location_kind_t kind, \
+
const diagnostic_logical_location *parent, \
+
const char *short_name, \
+
const char *fully_qualified_name, \
+
const char *decorated_name)
+
+ Create a :type:`diagnostic_logical_location`.
+
+ ``diag_mgr`` must be non-NULL.
+
+ ``kind`` describes the kind of logical location:
+
+ .. enum:: diagnostic_logical_location_kind_t
+
+ This roughly corresponds to the ``kind`` property in SARIF v2.1.0
+ (`§3.33.7
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790976>`_).
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_NAMESPACE
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE
+
+ ``parent`` can be NULL; if non-NULL it can be used to express tree-like
+ nesting of logical locations, such as in::
+
+ namespace foo { namespace bar { class baz { baz (); }; } }
+
+ where a diagnostic within ``baz``'s constructor could be reported
+ as being within ``foo::bar::baz::baz`` where the logical locations
+ are two namespaces, a type, and a member, respectively.
+
+ ``short_name`` can be NULL, or else a string suitable for use by
+ the SARIF logicalLocation ``name`` property
+ (SARIF v2.1.0 `§3.33.4
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790973>`_).
+
+ ``fully_qualified_name`` can be NULL or else a string suitable for use by
+ the SARIF logicalLocation ``fullyQualifiedName`` property
+ (SARIF v2.1.0 `§3.33.5
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790974>`_).
+
+ ``decorated_name`` can be NULL or else a string suitable for use by
+ the SARIF logicalLocation ``decoratedName`` property
+ (SARIF v2.1.0 `§3.33.6
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790975>`_).
+
+.. function:: void diagnostic_manager_debug_dump_logical_location (const
diagnostic_manager *diag_mgr, \
+ const
diagnostic_logical_location *loc, \
+ FILE *out)
+
+ Write a representation of ``file`` to ``out``, for debugging.
+ Both ``diag_mgr`` and ``out`` must be non-NULL.
+ ``file`` may be NULL.
+
+ TODO: example of output
+
+Associating diagnostics with locations
+**************************************
+
+.. function:: void diagnostic_set_logical_location (diagnostic *diag, \
+ const
diagnostic_logical_location *logical_loc)
+
+ Set the logical location of ``diag``.
+
+ ``diag`` must be non-NULL; ``logical_loc`` can be NULL.
diff --git a/gcc/doc/libdiagnostics/topics/message-formatting.rst
b/gcc/doc/libdiagnostics/topics/message-formatting.rst
new file mode 100644
index 000000000000..9d42f8937d0d
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/message-formatting.rst
@@ -0,0 +1,224 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Message formatting
+==================
+
+Various libdiagnostics entrypoints take a format string and
+variadic arguments.
+
+The format strings take codes prefixed by ``%``, or ``%q`` to put
+the result in quotes. For example::
+
+ "hello %s", "world"
+
+would print::
+
+ hello world
+
+whereas::
+
+ "hello %qs", "world"
+
+would print::
+
+ hello `world'
+
+where ```world'`` would be displayed in bold if colorization were enabled
+in the terminal.
+
+The following format specifiers are accepted:
+
+
+Numbers
+*******
+
+``d`` and ``i`` (``signed int``), ``u`` (``unsigned int``)
+ ``%d``, ``%i``, and ``%u`` print integers in base ten. For example::
+
+ "the answer is %i", 42
+
+ would print::
+
+ the answer is 42
+
+``o`` (``unsigned int``)
+ Print the integer in base eight
+
+``x`` (``unsigned int``)
+ Print the integer in base sixteen
+
+The above can be prefixed with ``l`` and ``ll`` prefixes to take
+``long`` and ``long long`` values of the appropriate signedness.
+
+For example::
+
+ "address: %lx", (unsigned long)0x108b516
+
+would print::
+
+ address: 108b516
+
+Similarly, the prefix ``z`` can be used for ``size_t``::
+
+ "size: %zd", sizeof(struct foo)
+ size: 32
+
+and ``t`` for ptrdiff_t.
+
+``f`` (``double``)
+ ``%f`` prints a floating-point value. For example::
+
+ "value: %f", 1.0
+
+ might print::
+
+ value: 1.000000
+
+
+Strings
+*******
+
+``c`` (``char``)
+ ``%c`` prints a single character.
+
+``s`` (``const char *``)
+ ``%s`` prints a string.
+
+ Note that if the string refers to something that might
+ appear in the input file (such as the name of a function), it's better
+ to quote the value; for example::
+
+ "unrecognized identifier: %qs", "foo"
+
+ might print::
+
+ unrecognized identifier: `foo'
+
+``m`` (no argument)
+ Prints ``strerror(errno)``, for example::
+
+ "can't open %qs: %m"
+
+ might print::
+
+ can't open `foo.txt': No such file or directory
+
+``%`` (no argument)
+ ``%%`` prints a `%` character, for example::
+
+ "8%% of 75 is 75%% of 8, and is thus 6"
+
+ prints::
+
+ 8% of 75 is 75% of 8, and is thus 6
+
+``'`` (no argument)
+ ``%'`` prints an apostrophe. This should only be used in untranslated
messages;
+ translations should use appropriate punctuation directly.
+
+
+Other format specifiers
+***********************
+
+``p`` (pointer)
+ ``%p`` prints a pointer, although the precise format is
+ implementation-defined.
+
+``r`` (``const char *``)
+ ``%r`` starts colorization on suitable text sinks, where the argument
+ specifies the name of the kind of entity to be colored, such as ``error``.
+
+``R`` (no argument)
+ ``%R`` stops colorization
+
+``<`` and ``>`` (no arguments)
+ ``%<`` adds an opening quote and ``%>`` a closing quote, such as::
+
+ "missing element %<%s:%s%>", ns, name
+
+ which might be printed as::
+
+ missing element `xhtml:head'
+
+ If the thing to be quoted can be handled with another format specifier,
+ then it's simpler to use ``q`` with it. For example, it's much
+ simpler to print a ``const char *`` in quotes via::
+
+ "%qs", str
+
+ rather than the error-prone::
+
+ "%<%s%>", str
+
+``{`` (``const char *``)
+ ``%{`` starts a link; the argument is the URL. This will be displayed
+ in a suitably-capable terminal if a text sink is directly connected to
+ a tty, and will be captured in SARIF output.
+
+``}`` (no argument)
+ ``%}`` stops a link started with ``%{``.
+
+ For example::
+
+ "for more information see %{the documentation%}", "https://example.com"
+
+ would be printed as::
+
+ for more information see the documentation
+
+ with the URL emitted in suitable output sinks.
+
+``@`` (``diagnostic_event_id *``)
+ ``%@`` prints a reference to an event in a
+ :type:`diagnostic_execution_path`, where the :type:`diagnostic_event_id`
+ is passed by pointer.
+
+ For example, if ``event_id`` refers to the first event in a path, then::
+
+ "double-%qs of %qs; first %qs was at %@",
+ function, ptr, function, &event_id
+
+ might print::
+
+ double-`free' of `p'; first `free` was at (1)
+
+.. :
+
+ TODO:
+
+ %.*s: a substring the length of which is specified by an argument
+ integer.
+ %Ns: likewise, but length specified as constant in the format string.
+ %Z: Requires two arguments - array of int, and len. Prints elements
+ of the array.
+
+ %e: Consumes a pp_element * argument.
+
+ Arguments can be used sequentially, or through %N$ resp. *N$
+ notation Nth argument after the format string. If %N$ / *N$
+ notation is used, it must be used for all arguments, except %m, %%,
+ %<, %>, %} and %', which may not have a number, as they do not consume
+ an argument. When %M$.*N$s is used, M must be N + 1. (This may
+ also be written %M$.*s, provided N is not otherwise used.) The
+ format string must have conversion specifiers with argument numbers
+ 1 up to highest argument; each argument may only be used once.
+ A format string can have at most 30 arguments. */
+
+
diff --git a/gcc/doc/libdiagnostics/topics/metadata.rst
b/gcc/doc/libdiagnostics/topics/metadata.rst
new file mode 100644
index 000000000000..c62792a5b763
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/metadata.rst
@@ -0,0 +1,149 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Adding metadata
+===============
+
+Tool metadata
+*************
+
+It's possible to set up various metadata on the :type:`diagnostic_manager`
+as a whole, describing the program creating the diagnostics.
+
+.. note::
+
+ It's not required to set up any of this up on a
+ :type:`diagnostic_manager`. However, if you are doing
+ :doc:`SARIF output <sarif>`, then you need to at least call
+ :func:`diagnostic_manager_set_tool_name` or the generated ``.sarif``
+ file will not validate against the schema.
+
+.. function:: void diagnostic_manager_set_tool_name (diagnostic_manager
*diag_mgr, \
+ const char *value)
+
+ Set a string for the name of the tool emitting the diagnostics.
+
+ Both parameters must be non-NULL.
+
+ If set, this string will be used
+
+ * by :doc:`text output sinks <text-output>` as a prefix for output
+ when no physical location is available, replacing ``progname``
+ in the following:
+
+ .. code-block:: console
+
+ $ ./tut01-hello-world
+ progname: error: I'm sorry Dave, I'm afraid I can't do that
+
+ * by :doc:`SARIF output sinks <sarif>` as the value for the
+ ``name`` property of the ``driver``
+ (`SARIF v2.1.0 §3.19.8
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790791>`_).
+
+.. function:: void diagnostic_manager_set_full_name (diagnostic_manager
*diag_mgr, \
+ const char *value)
+
+ Set a string giving the name of the tool along with the its version and
+ other useful information::
+
+ diagnostic_manager_set_full_name (diag_mgr, "FooChecker 0.1 (en_US)");
+
+ If set, this string will be used by :doc:`SARIF output sinks <sarif>` as
+ the value for the ``fullName`` property of the ``driver``
+ (`SARIF v2.1.0 §3.19.9
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790792>`_).
+
+ Both parameters must be non-NULL.
+
+.. function:: void diagnostic_manager_set_version_string (diagnostic_manager
*diag_mgr, \
+ const char *value)
+
+ Set a string suitable for use as the value of the SARIF ``version`` property
+ of the ``driver``.
+ (`SARIF v2.1.0 §3.19.13
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790796>`_)::
+
+ diagnostic_manager_set_version_string (diag_mgr, "0.1");
+
+ Both parameters must be non-NULL.
+
+.. function:: void diagnostic_manager_set_version_url (diagnostic_manager
*diag_mgr, \
+ const char *value)
+
+ Set a string suitable for use as the value of the SARIF ``informationUri``
+ property of the ``driver``.
+ (`SARIF v2.1.0 §3.19.17
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790800>`_)::
+
+ diagnostic_manager_set_version_url (diag_mgr,
+
"https://www.example.com/foo-checker/releases/0.1/");
+
+ Both parameters must be non-NULL.
+
+Adding metadata to a diagnostic
+*******************************
+
+.. function:: void diagnostic_set_cwe (diagnostic *diag, \
+ unsigned cwe_id)
+
+ Associate ``diag`` with the given ID within
+ the `Common Weakness Enumeration <https://cwe.mitre.org/>`_::
+
+ /* CWE-242: Use of Inherently Dangerous Function. */
+ diagnostic_set_cwe (d, 242);
+
+ ``diag`` must be non-NULL.
+
+ The CWE value will be printed by text sinks after the message::
+
+ test-metadata.c:21:3: warning: never use 'gets' [CWE-242]
+
+ and in a sufficiently-capable terminal will be a link to
+ documentation about the CWE.
+
+.. function:: void diagnostic_add_rule (diagnostic *diag, \
+ const char *title, \
+ const char *url)
+
+ Associate this :type:`diagnostic` with a particular rule that has been
+ violated (such as in a coding standard, or within a specification).
+
+ A diagnostic can be associated with zero or more rules.
+
+ ``diag`` must be non-NULL. The rule must have at least one of a
+ title and a URL, but these can be NULL.
+
+ For example, given::
+
+ diagnostic_add_rule (d,
+ "MSC24-C",
+
"https://wiki.sei.cmu.edu/confluence/display/c/MSC24-C.+Do+not+use+deprecated+or+obsolescent+functions");
+
+ the rule name will be printed by text sinks after the message::
+
+ test-metadata.c:21:3: warning: never use 'gets' [MSC24-C]
+ 21 | gets (buf);
+ | ^~~~~~~~~~
+
+ and if so, the URL will be available in a sufficiently capable
+ terminal.
+
+ This can be used in conjunction with :func:`diagnostic_set_cwe`,
+ giving output like this::
+
+ test-metadata.c:21:3: warning: never use 'gets' [CWE-242] [MSC24-C]
+ 21 | gets (buf);
+ | ^~~~~~~~~~
diff --git a/gcc/doc/libdiagnostics/topics/physical-locations.rst
b/gcc/doc/libdiagnostics/topics/physical-locations.rst
new file mode 100644
index 000000000000..bad2b8db27fd
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/physical-locations.rst
@@ -0,0 +1,281 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Physical locations
+==================
+
+A "physical" source location is a location expressed in terms of
+a specific file, and line(s) and column(s) (as opposed to a
+:doc:`"logical" location <logical-locations>`,
+which refers to semantic constructs in a programming language).
+
+Creating location information
+*****************************
+
+The :type:`diagnostic_manager` manages various objects relating to
+locations.
+
+.. type:: diagnostic_file
+
+ A :type:`diagnostic_file` is an opaque type describing a particular input
file.
+
+.. function:: const diagnostic_file * diagnostic_manager_new_file
(diagnostic_manager *diag_mgr, \
+ const char
*name, \
+ const char
*sarif_source_language)
+
+ Create a new :type:`diagnostic_file` for file ``name``. Repeated calls
+ with strings that match ``name`` will return the same object.
+
+ Both ``diag_mgr`` and ``name`` must be non-NULL.
+
+ If ``sarif_source_language`` is non-NULL, it specifies a
+ ``sourceLanguage`` value for the file for use when writing
+ :doc:`SARIF <sarif>`
+ (`SARIF v2.1.0 §3.24.10
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790871>`_).
+ See
+ `SARIF v2.1.0 Appendix J
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141791197>`_
+ for suggested values for various programmming languages.
+
+ For example, this creates a :type:`diagnostic_file` for ``foo.c``
+ and identifies it as C source code::
+
+ foo_c = diagnostic_manager_new_file (diag_mgr,
+ "foo.c",
+ "c" /* source_language */);
+
+.. function:: void diagnostic_manager_debug_dump_file (diagnostic_manager
*diag_mgr, \
+ const diagnostic_file
*file, \
+ FILE *out)
+
+ Write a representation of ``file`` to ``out``, for debugging.
+ Both ``diag_mgr`` and ``out`` must be non-NULL.
+ `file`` may be NULL.
+
+ For example::
+
+ diagnostic_manager_debug_dump_file (diag_mgr, foo_c, stderr);
+
+ might lead to this output::
+
+ file(name="foo.c", sarif_source_language="c")
+
+.. type:: diagnostic_line_num_t
+
+A :type:`diagnostic_line_num_t` is used for representing line numbers
+within text files. libdiagnostics treats the first line of a text file
+as line 1.
+
+.. type:: diagnostic_column_num_t
+
+A :type:`diagnostic_column_num_t` is used for representing column numbers
+within text files. libdiagnostics treats the first column of a text line
+as column 1, **not** column 0.
+
+.. note::
+
+ Both libdiagnostics and Emacs number source *lines* starting at 1, but
+ they have differing conventions for *columns*.
+
+ libdiagnostics uses a 1-based convention for source columns,
+ whereas Emacs's ``M-x column-number-mode`` uses a 0-based convention.
+
+ For example, an error in the initial, left-hand
+ column of source line 3 is reported by libdiagnostics as::
+
+ some-file.c:3:1: error: ...etc...
+
+ On navigating to the location of that error in Emacs
+ (e.g. via ``next-error``),
+ the locus is reported in the Mode Line
+ (assuming ``M-x column-number-mode``) as::
+
+ some-file.c 10% (3, 0)
+
+ i.e. ``3:1:`` in libdiagnostics corresponds to ``(3, 0)`` in Emacs.
+
+.. type:: diagnostic_physical_location
+
+A :type:`diagnostic_physical_location` is an opaque type representing a
+key into a database of source locations within a :type:`diagnostic_manager`.
+
+:type:`diagnostic_physical_location` instances are created by various API
+calls into the :type:`diagnostic_manager` expressing source code points
+and ranges.
+
+They persist until the :type:`diagnostic_manager` is released, which
+cleans them up.
+
+A ``NULL`` value means "unknown", and can be returned by the
+:type:`diagnostic_manager` as a fallback when a problem occurs
+(e.g. too many locations).
+
+A :type:`diagnostic_physical_location` can be a single point within the
+source code, such as here (at the the '"' at the start of the string literal)::
+
+ int i = "foo";
+ ^
+
+or be a range with a start and finish, and a "caret" location::
+
+ a = (foo && bar)
+ ~~~~~^~~~~~~
+
+where the caret here is at the first "&", and the start and finish
+are at the parentheses.
+
+.. function:: const diagnostic_physical_location
*diagnostic_manager_new_location_from_file_and_line (diagnostic_manager
*diag_mgr, \
+
const diagnostic_file *file, \
+
diagnostic_line_num_t line_num)
+
+ Attempt to create a :type:`diagnostic_physical_location` representing
+ ``FILENAME:LINE_NUM``, with no column information (thus representing
+ the whole of the given line.
+
+ Both ``diag_mgr`` and ``file`` must be non-NULL.
+
+.. function:: const diagnostic_physical_location *
diagnostic_manager_new_location_from_file_line_column (diagnostic_manager
*diag_mgr, \
+
const diagnostic_file *file, \
+
diagnostic_line_num_t line_num, \
+
diagnostic_column_num_t column_num)
+
+ Attempt to create a :type:`diagnostic_physical_location` for
+ ``FILENAME:LINE_NUM:COLUMN_NUM`` representing a particular point
+ in the source file.
+
+ Both ``diag_mgr`` and ``file`` must be non-NULL.
+
+.. function:: const diagnostic_physical_location
*diagnostic_manager_new_location_from_range (diagnostic_manager *diag_mgr,\
+
const diagnostic_physical_location *loc_caret,\
+
const diagnostic_physical_location *loc_start,\
+
const diagnostic_physical_location *loc_end)
+
+ Attempt to create a diagnostic_physical_location representing a
+ range within a source file, with a highlighted "caret" location.
+
+ All must be within the same file, but they can be on different lines.
+
+ For example, consider the location of the binary expression below::
+
+ ...|__________1111111112222222
+ ...|12345678901234567890123456
+ ...|
+ 521|int sum (int foo, int bar)
+ 522|{
+ 523| return foo + bar;
+ ...| ~~~~^~~~~
+ 524|}
+
+ The location's caret is at the "+", line 523 column 15, but starts
+ earlier, at the "f" of "foo" at column 11. The finish is at the "r"
+ of "bar" at column 19.
+
+ ``diag_mgr`` must be non-NULL.
+
+.. function:: void diagnostic_manager_debug_dump_location (const
diagnostic_manager *diag_mgr,\
+ const
diagnostic_physical_location *loc, \
+ FILE *out)
+
+ Write a representation of ``loc`` to ``out``, for debugging.
+
+ Both ``diag_mgr`` and ``out`` must be non-NULL.
+ `loc`` may be NULL.
+
+ TODO: example of output
+
+Associating diagnostics with locations
+**************************************
+
+A :type:`diagnostic` has an optional primary physical location
+and zero or more secondary physical locations. For example::
+
+ a = (foo && bar)
+ ~~~~~^~~~~~~
+
+This diagnostic has a single :type:`diagnostic_physical_location`,
+with the caret at the first "&", and the start/finish at the parentheses.
+
+Contrast with::
+
+ a = (foo && bar)
+ ~~~ ^~ ~~~
+
+This diagnostic has three locations
+
+* The primary location (at "&&") has its caret and start location at
+ the first "&" and end at the second "&.
+
+* The secondary location for "foo" has its start and finish at the "f"
+ and "o" of "foo"; the caret is not displayed, but is perhaps at
+ the "f" of "foo".
+
+* Similarly, the other secondary location (for "bar") has its start and
+ finish at the "b" and "r" of "bar"; the caret is not displayed, but
+ is perhaps at the"b" of "bar".
+
+.. function:: void diagnostic_set_location (diagnostic *diag, \
+ const
diagnostic_physical_location * loc)
+
+ Set the primary location of ``diag``.
+
+ ``diag`` must be non-NULL; ``loc`` can be NULL.
+
+.. function:: void diagnostic_set_location_with_label (diagnostic *diag, \
+ const
diagnostic_physical_location *loc, \
+ const char *fmt, ...)
+
+ Set the primary location of ``diag``, with a label. The label is
+ formatted as per the rules FIXME
+
+ ``diag`` and ``fmt`` must be non-NULL; ``loc`` can be NULL.
+
+ See :doc:`message-formatting` for details of how to use ``fmt``.
+
+ TODO: example of use
+
+.. function:: void diagnostic_add_location (diagnostic *diag, \
+ const diagnostic_physical_location
* loc)
+
+ Add a secondary location to ``diag``.
+
+ ``diag`` must be non-NULL; ``loc`` can be NULL.
+
+
+.. function:: void diagnostic_add_location_with_label (diagnostic *diag, \
+ const
diagnostic_physical_location *loc, \
+ const char *text)
+
+ Add a secondary location to ``diag``, with a label. The label is
+ formatted as per the rules FIXME
+
+ ``diag`` and ``fmt`` must be non-NULL; ``loc`` can be NULL.
+
+ For example,
+
+ .. literalinclude::
../../../testsuite/libdiagnostics.dg/test-labelled-ranges.c
+ :language: c
+ :start-after: /* begin quoted source */
+ :end-before: /* end quoted source */
+
+ might give this text output::
+
+ test-labelled-ranges.c:9:6: error: mismatching types: 'int' and 'const
char *'
+ 19 | 42 + "foo"
+ | ~~ ^ ~~~~~
+ | | |
+ | int const char *
diff --git a/gcc/doc/libdiagnostics/topics/retrofitting.rst
b/gcc/doc/libdiagnostics/topics/retrofitting.rst
new file mode 100644
index 000000000000..d0340570733e
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/retrofitting.rst
@@ -0,0 +1,23 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Adding libdiagnostics to an existing project
+============================================
+
+TODO
diff --git a/gcc/doc/libdiagnostics/topics/sarif.rst
b/gcc/doc/libdiagnostics/topics/sarif.rst
new file mode 100644
index 000000000000..3fd75ed21c64
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/sarif.rst
@@ -0,0 +1,51 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+SARIF support
+=============
+
+`SARIF <https://www.sarif.info/>`_ is a machine-readable format, originally
+designed for the output of static analysis tools, but which can be used
+for diagnostics in general.
+
+.. function:: void diagnostic_manager_add_sarif_sink (diagnostic_manager
*diag_mgr, \
+ FILE *dst_stream, \
+ const diagnostic_file
*main_input_file, \
+ enum
diagnostic_sarif_version version)
+
+ Add a new output sink to ``diag_mgr``, which writes SARIF of the given
+ version to ``dst_stream``.
+
+ The output is not written until ``diag_mgr`` is released.
+
+ ``dst_stream`` is borrowed, and must outlive ``diag_mgr``.
+
+ For the result to be a valid SARIF file according to the schema,
+ ``diag_mgr`` must have had :func:`diagnostic_manager_set_tool_name`
+ called on it.
+
+ ``diag_mgr``, ``dst_stream``, and ``main_input_file`` must all be non-NULL.
+
+ .. enum:: diagnostic_sarif_version
+
+ An enum for choosing the SARIF version for a SARIF output sink.
+
+ .. macro:: DIAGNOSTIC_SARIF_VERSION_2_1_0
+
+ .. macro:: DIAGNOSTIC_SARIF_VERSION_2_2_PRERELEASE
diff --git a/gcc/doc/libdiagnostics/topics/text-output.rst
b/gcc/doc/libdiagnostics/topics/text-output.rst
new file mode 100644
index 000000000000..32b2a54f18a3
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/text-output.rst
@@ -0,0 +1,87 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Text output
+===========
+
+.. type:: diagnostic_text_sink
+
+.. function:: diagnostic_text_sink * diagnostic_manager_add_text_sink
(diagnostic_manager *diag_mgr,\
+ FILE
*dst_stream, \
+ enum
diagnostic_colorize colorize)
+
+ Add a new output sink to ``diag_mgr``, which writes GCC-style diagnostics
+ to ``dst_stream``.
+ Return a borrowed pointer to the sink, which is cleaned up when ``diag_mgr``
+ is released.
+
+ ``diag_mgr`` must be non-NULL.
+
+ ``dst_stream`` must be non-NULL. It is borrowed and must outlive
``DIAG_MGR``.
+
+ The output for each diagnostic is written and flushed as each
+ :type:`diagnostic` is finished.
+
+ .. enum:: diagnostic_colorize
+
+ An enum for determining if we should colorize a text output sink.
+
+ .. macro:: DIAGNOSTIC_COLORIZE_IF_TTY
+
+ Diagnostics should be colorized if the destination stream is
+ directly connected to a tty.
+
+ .. macro:: DIAGNOSTIC_COLORIZE_NO
+
+ Diagnostics should not be colorized.
+
+ .. macro:: DIAGNOSTIC_COLORIZE_YES
+
+ Diagnostics should be colorized.
+
+.. function:: void diagnostic_text_sink_set_source_printing_enabled
(diagnostic_text_sink *text_sink, \
+ int value)
+
+ Enable or disable printing of source text in the text sink.
+
+ ``text_sink`` must be non-NULL.
+
+ Default: enabled.
+
+.. function:: void diagnostic_text_sink_set_colorize (diagnostic_text_sink
*text_sink, \
+ enum diagnostic_colorize
colorize)
+
+ Update colorization of text sink.
+
+ ``text_sink`` must be non-NULL.
+
+.. function:: void
diagnostic_text_sink_set_labelled_source_colorization_enabled
(diagnostic_text_sink *text_sink, \
+
int value)
+
+ ``text_sink`` must be non-NULL.
+
+ Enable or disable colorization of the characters of source text
+ that are underlined.
+
+ This should be true for clients that generate range information
+ (so that the ranges of code are colorized), and false for clients that
+ merely specify points within the source code (to avoid e.g. colorizing
+ just the first character in a token, which would look strange).
+
+ Default: enabled.
diff --git a/gcc/doc/libdiagnostics/topics/ux.rst
b/gcc/doc/libdiagnostics/topics/ux.rst
new file mode 100644
index 000000000000..fc96e176eb67
--- /dev/null
+++ b/gcc/doc/libdiagnostics/topics/ux.rst
@@ -0,0 +1,26 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+User Experience
+===============
+
+Refer to
+`GCC's user experience guidelines
<https://gcc.gnu.org/onlinedocs/gccint/User-Experience-Guidelines.html>`_
+for notes on
+`what makes a good diagnostic
<https://gcc.gnu.org/onlinedocs/gccint/Guidelines-for-Diagnostics.html>`_.
diff --git a/gcc/doc/libdiagnostics/tutorial/01-hello-world.rst
b/gcc/doc/libdiagnostics/tutorial/01-hello-world.rst
new file mode 100644
index 000000000000..4635687fabd5
--- /dev/null
+++ b/gcc/doc/libdiagnostics/tutorial/01-hello-world.rst
@@ -0,0 +1,173 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Tutorial part 1: "Hello world"
+==============================
+
+Before we look at the details of the API, let's look at building and
+running programs that use the library.
+
+Here's a toy program that uses libdiagnostics to emit an error message
+to stderr.
+
+ .. literalinclude:: ../../../testsuite/libdiagnostics.dg/test-example-1.c
+ :language: c
+ :start-after: /* begin quoted source */
+ :end-before: /* end quoted source */
+
+Copy the above to `tut01-hello-world.c`.
+
+Assuming you have libdiagnostics installed, build the test program
+using:
+
+.. code-block:: console
+
+ $ gcc \
+ tut01-hello-world.c \
+ -o tut01-hello-world \
+ -ldiagnostics
+
+You should then be able to run the built program:
+
+.. code-block:: console
+
+ $ ./tut01-hello-world
+ progname: error: I'm sorry Dave, I'm afraid I can't do that
+
+If stderr is connected to a terminal, you should get colorized output
+(using `SGR control codes <https://en.wikipedia.org/wiki/ANSI_escape_code>`_).
+
+.. image:: example-1.png
+
+Otherwise, the output will be plain text.
+
+Obviously a trivial example like the above could be done using ``fprintf``
+on stderr, and it's fairly easy to colorize text at the terminal.
+
+In :doc:`the next part of the tutorial <02-physical-locations>` we'll add
+file/location information to our error messages, and libdiagnostics will
+quote the pertinent parts of the file, underlining them, which is less trivial
+to reimplement. libdiagnostics gives us many other such abilities, such as
+fix-it hints and execution paths, which we'll cover in the following
+tutorials. Also, once a program's diagnostics are using libdiagnostics,
+it is trivial to add support for outputting them in
+machine-readable form as :doc:`SARIF <../topics/sarif>`.
+
+
+Structure
+*********
+
+The above example shows the typical structure of a program using
+libdiagnostics:
+
+* **initialization**: create a :type:`diagnostic_manager` instance,
+ and create an output sink for it, and other one-time initialization
+
+* **emission**: create various :type:`diagnostic` instances, populating
+ them with data, and calling "finish" once they're ready to be emitted.
+ :doc:`Text sinks <../topics/text-output>` emit their diagnostics as soon
+ as "finish" is called on them.
+
+* **cleanup**: call :func:`diagnostic_manager_release` on the
+ :type:`diagnostic_manager` to finish and free up resources.
+ :doc:`SARIF sinks <../topics/sarif>` write their output when
+ :func:`diagnostic_manager_release` is called on the manager.
+
+For non-trivial examples we'll also want to create location information,
+which could happen during initialization, or during a parsing phase of
+the program using libdiagnostics. See :doc:`02-physical-locations` for
+more information.
+
+
+Formatted messages
+******************
+
+The above example uses :func:`diagnostic_finish`, which takes a format
+string and arguments. libdiagnostics has its own style of format
+string arguments used for :func:`diagnostic_finish` and some other
+entrypoints.
+
+.. note:: The format syntax is *not* the same as ``printf``; see
+ :doc:`supported formatting options <../topics/message-formatting>`.
+
+You can use the ``q`` modifier on arguments
+to quote them, so, for example ``%qs`` is a quoted string, consuming a
+``const char *`` argument::
+
+ diagnostic_finish (d, "can't find %qs", "foo");
+
+This gives output like this:
+
+.. code-block:: console
+
+ progname: error: can't find ‘foo’
+
+where the quoted string will appear in bold in a suitably-capable
+terminal, and the quotes will be internationalized, so that e.g. with
+``LANG=fr_FR.UTF8`` we might get:
+
+.. code-block:: console
+
+ progname: erreur: can't find « free »
+
+Note that:
+
+* the string ``error`` has been localized by libdiagnostics to
+ ``erreur``,
+
+* locale-specific quoting has been used (``«`` and ``»`` rather than
+ ``‘`` and ``’``),
+
+* ``foo`` hasn't been localized - you would typically use quoted strings
+ for referring to identifiers in the input language (such as function names
+ in code, property names in JSON, etc),
+
+* the message itself hasn't been localized: you are responsible for
+ passing a translated format string to :func:`diagnostic_finish` if you
+ want to internationalize the output.
+
+There are many :doc:`supported formatting options
<../topics/message-formatting>`.
+
+
+Naming the program
+******************
+
+In the above output the message was preceded with ``progname``. This
+appears for diagnostics that don't have any location information associated
+with them. We'll look at setting up location information in the
+:doc:`next tutorial <02-physical-locations>`, but we can override this
+default name via :func:`diagnostic_manager_set_tool_name`::
+
+ diagnostic_manager_set_tool_name (diag_mgr, "my-awesome-checker");
+
+leading to output like this::
+
+ my-awesome-checker: error: can't find ‘foo’
+
+There are various other functions for
+:doc:`supplying metadata to libdiagnostics <../../topics/metadata>`.
+
+
+Moving beyond trivial examples
+******************************
+
+Obviously it's not very useful if we can't refer to specific files and
+specific locations in those files in our diagnostics, so read
+:doc:`part 2 of the tutorial <02-physical-locations>` for information on
+how to do this.
diff --git a/gcc/doc/libdiagnostics/tutorial/02-physical-locations.rst
b/gcc/doc/libdiagnostics/tutorial/02-physical-locations.rst
new file mode 100644
index 000000000000..2e429de17349
--- /dev/null
+++ b/gcc/doc/libdiagnostics/tutorial/02-physical-locations.rst
@@ -0,0 +1,260 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Tutorial part 2: physical locations
+===================================
+
+libdiagnostics has two kinds of location:
+
+* *physical locations* expressed in terms of a specific file, and line(s)
+ and perhaps column(s), such as ``some-file.c:3:1``, or a range of
+ columns, such as in::
+
+ test-typo.c:19:13: error: unknown field 'colour'
+ 19 | return p->colour;
+ | ^~~~~~
+
+ or even a range spanning multiple lines of a file.
+
+ All of these are instances of :type:`diagnostic_physical_location`.
+
+* *logical locations* which refers to semantic constructs
+ in the input, such as ``within function 'foo'``, or within
+ namespace ``foo``'s class ``bar``'s member function ``get_color``.
+
+ These are instances of :type:`diagnostic_logical_location`,
+
+A :type:`diagnostic` can have zero or more physical locations,
+and optionally have a logical location.
+
+Let's extend the previous example to add a physical location to the
+:type:`diagnostic`; we'll cover logical locations in the
+:doc:`next section <03-logical-locations>`.
+
+
+Source files
+************
+
+Given these declarations::
+
+ static diagnostic_manager *diag_mgr;
+ static const diagnostic_file *main_file;
+
+we can create a :type:`diagnostic_file` describing an input file ``foo.c``
+via :func:`diagnostic_manager_new_file`::
+
+ foo_c = diagnostic_manager_new_file (diag_mgr,
+ "foo.c",
+ "c" /* source_language */);
+
+You can use :func:`diagnostic_manager_debug_dump_file` to print a
+representation of a :type:`diagnostic_file` for debugging.
+For example::
+
+ diagnostic_manager_debug_dump_file (diag_mgr, foo_c, stderr);
+
+might lead to this output on ``stderr``::
+
+ file(name="foo.c", sarif_source_language="c")
+
+Once we have a :type:`diagnostic_file` we can use it to create instances
+of :type:`diagnostic_physical_location` within the :type:`diagnostic_manager`.
+These are owned by the :type:`diagnostic_manager` and cleaned up
+automatically when :func:`diagnostic_manager_release` is called.
+
+Instances of :type:`diagnostic_physical_location` can refer to
+
+* a source line as a whole, created via
+ :func:`diagnostic_manager_new_location_from_file_and_line`.
+
+* a particular point within a source file (line/column), created via
+ :func:`diagnostic_manager_new_location_from_file_line_column`.
+
+* a range of text within of source file, created via
+ :func:`diagnostic_manager_new_location_from_range`.
+
+
+Diagnostics affecting a whole source line
+*****************************************
+
+If we want a diagnostic to refer to an entire source line,
+we can use :func:`diagnostic_manager_new_location_from_file_and_line`.
+
+For example, given this example input where the tool can't find the header::
+
+ #include <foo.h>
+
+we could complain about it via libdiagnostics via:
+
+.. literalinclude:: ../../../testsuite/libdiagnostics.dg/test-no-column.c
+ :language: c
+ :start-after: /* begin quoted source */
+ :end-before: /* end quoted source */
+
+leading to output like this::
+
+ foo.c:17: error: can't find 'foo.h'"
+ 17 | #include <foo.h>
+
+where libdiagnostics will attempt to load the source file and
+quote the pertinent line.
+
+If libdiagnostics cannot open the file, it will merely print::
+
+ foo.c:17: error: can't find 'foo.h'
+
+You can use :func:`diagnostic_manager_debug_dump_location` to dump a
+:type:`diagnostic_physical_location`. For the above example::
+
+ diagnostic_manager_debug_dump_location (diag_mgr, loc, stderr);
+
+might print::
+
+ foo.c:17
+
+to stderr.
+
+
+Columns and ranges
+******************
+
+If we want to generate output like this::
+
+ foo.c:17:11: error: can't find 'foo'"
+ 17 | #include <foo.h>
+ | ^~~~~
+
+where the diagnostic is marked as relating to the above range of
+characters in line 17, we need to express the range of characters
+within the line of interest.
+
+We can do this by creating a :type:`diagnostic_physical_location` for the
+start of the range, another one for the end of the range, and then using
+these two to create a :type:`diagnostic_physical_location` for the
+range as a whole:
+
+.. literalinclude:: ../../../testsuite/libdiagnostics.dg/test-error.c
+ :language: c
+ :start-after: /* begin quoted source */
+ :end-before: /* end quoted source */
+
+On compiling and running the program, we should get this output::
+
+ foo.c:17:11: error: can't find 'foo.h'
+ 17 | #include <foo.h>
+ | ^~~~~
+
+where libdiagnostics will attempt to load the source file and
+underling the pertinent part of the given line.
+
+If libdiagnostics cannot open the file, it will merely print::
+
+ foo.c:17:8: error: can't find 'foo'
+
+A range can span multiple lines within the same file.
+
+As before, you can use :func:`diagnostic_manager_debug_dump_location` to
+dump the locations. For the above example::
+
+ diagnostic_manager_debug_dump_location (diag_mgr, loc_start, stderr);
+
+and::
+
+ diagnostic_manager_debug_dump_location (diag_mgr, loc_range, stderr);
+
+might print::
+
+ foo.c:17:11
+
+to stderr, whereas::
+
+ diagnostic_manager_debug_dump_location (diag_mgr, loc_end, stderr);
+
+might print::
+
+ foo.c:17:15
+
+
+Multiple locations
+******************
+
+As well as the primary physical location seen above, a :type:`diagnostic`
+can have additional physical locations. You can add these secondary
+locations via :func:`diagnostic_add_location`.
+
+For example, for this valid but suspicious-looking C code::
+
+ const char *strs[3] = {"foo",
+ "bar"
+ "baz"};
+
+the following :type:`diagnostic` has its primary location where the missing
+comma should be, and secondary locations for each of the string literals
+``"foo"``, ``"bar"``, and ``"baz"``, added via :func:`diagnostic_add_location`:
+
+.. literalinclude:: ../../../testsuite/libdiagnostics.dg/test-multiple-lines.c
+ :language: c
+ :start-after: /* begin quoted source */
+ :end-before: /* end quoted source */
+
+where the text output might be::
+
+ test-multiple-lines.c:23:29: warning: missing comma
+ 22 | const char *strs[3] = {"foo",
+ | ~~~~~
+ 23 | "bar"
+ | ~~~~~^
+ 24 | "baz"};
+ | ~~~~~
+
+
+Labelling locations
+*******************
+
+You can give the locations labels using
+:func:`diagnostic_set_location_with_label` and
+:func:`diagnostic_add_location_with_label`.
+
+Consider emitting a "type mismatch" diagnostic for::
+
+ 42 + "foo"
+
+where the primary location is on the ``+``, with secondary locations on
the``42``
+and the ``"foo"``:
+
+.. literalinclude:: ../../../testsuite/libdiagnostics.dg/test-labelled-ranges.c
+ :language: c
+ :start-after: /* begin quoted source */
+ :end-before: /* end quoted source */
+
+giving this text output::
+
+ test-labelled-ranges.c:9:6: error: mismatching types: 'int' and 'const char
*'
+ 19 | 42 + "foo"
+ | ~~ ^ ~~~~~
+ | | |
+ | int const char *
+
+
+More on locations
+*****************
+
+For more details on the above, see :doc:`../topics/physical-locations`.
+Otherwise the :doc:`next part of the tutorial <03-logical-locations>`
+covers logical locations.
diff --git a/gcc/doc/libdiagnostics/tutorial/03-logical-locations.rst
b/gcc/doc/libdiagnostics/tutorial/03-logical-locations.rst
new file mode 100644
index 000000000000..d36ac098a809
--- /dev/null
+++ b/gcc/doc/libdiagnostics/tutorial/03-logical-locations.rst
@@ -0,0 +1,60 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Tutorial part 3: logical locations
+==================================
+
+Let's extend the previous example to add a
+:doc:`logical location <../topics/logical-locations>` to the
+:type:`diagnostic`.
+
+First we create a :type:`diagnostic_logical_location` representing a
+particular function::
+
+ const diagnostic_logical_location *logical_loc
+ = diagnostic_manager_new_logical_location (diag_mgr,
+
DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION,
+ NULL, /* parent */
+ "foo",
+ NULL,
+ NULL);
+
+In this simple example we specify that it is a function, and just give
+it a name (``foo``). For more complicated cases we can set up tree-like
+hierarchies of logical locations, set qualified names, "mangled" names,
+and so on; see :func:`diagnostic_manager_new_logical_location` for details.
+
+Once we have :type:`diagnostic_logical_location` we can associate it with
+a :type:`diagnostic` with :func:`diagnostic_set_logical_location`::
+
+ diagnostic_set_logical_location (d, logical_loc);
+
+The logical location will be printed by text output sinks like this::
+
+ In function 'foo':
+
+and will be captured in :doc:`SARIF <../topics/sarif>` output.
+
+
+Find out more
+*************
+
+For more details on the above, see :doc:`../topics/logical-locations`.
+Otherwise the :doc:`next part of the tutorial <04-notes>` covers adding
+supplementary "notes" to a :type:`diagnostic`.
diff --git a/gcc/doc/libdiagnostics/tutorial/04-notes.rst
b/gcc/doc/libdiagnostics/tutorial/04-notes.rst
new file mode 100644
index 000000000000..117eb6fa7ad8
--- /dev/null
+++ b/gcc/doc/libdiagnostics/tutorial/04-notes.rst
@@ -0,0 +1,66 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Tutorial part 4: adding notes
+=============================
+
+Let's further extend the previous example to add a "note" to it.
+
+We want to generate output like this::
+
+ test-with-note.c:17:11: error: can't find 'foo'
+ 17 | #include <foo.h>
+ | ^~~~~
+ test-with-note.c:17:11: note: have you looked behind the couch?
+
+The "error" and "note" are both instances of :type:`diagnostic`.
+We want to let libdiagnostics know that they are grouped together.
+The way to do this is to use :func:`diagnostic_manager_begin_group`
+and :func:`diagnostic_manager_end_group` around the "finish" calls
+to the diagnostics.
+
+.. literalinclude:: ../../../testsuite/libdiagnostics.dg/test-error-with-note.c
+ :language: c
+ :start-after: /* begin quoted source */
+ :end-before: /* end quoted source */
+
+On compiling and running the program, we should get the desired output::
+
+ test-with-note.c:17:11: error: can't find 'foo'
+ 17 | #include <foo.h>
+ | ^~~~~
+ test-with-note.c:17:11: note: have you looked behind the couch?
+
+The grouping doesn't affect text output sinks, but a
+:doc:`SARIF sink <../topics/sarif>` will group the note within the error
+(via the ``relatedLocations`` property of ``result`` objects; see SARIF v2.1.0
+`§3.27.22
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790910>`_).
+
+In the above, the note had the same physical location as the error
+(``loc_range``). This can be useful for splitting up a message into two
+parts to make localization easier, but they could have different locations,
such
+as in::
+
+ test.xml:10:2: error: 'foo' is not valid here
+ test.xml:5:1: note: within element 'bar'
+
+where each :type:`diagnostic` had its own :type:`diagnostic_physical_location`.
+
+In :doc:`the next tutorial <05-warnings>` we'll look at issuing warnings,
+rather than errors.
diff --git a/gcc/doc/libdiagnostics/tutorial/05-warnings.rst
b/gcc/doc/libdiagnostics/tutorial/05-warnings.rst
new file mode 100644
index 000000000000..1512ae78f987
--- /dev/null
+++ b/gcc/doc/libdiagnostics/tutorial/05-warnings.rst
@@ -0,0 +1,44 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Tutorial part 5: warnings
+=========================
+
+So far we've only emitted errors, but other kinds of diagnostic are possible,
+such as warnings.
+
+We can select different kinds of diagnostic via :enum:`diagnostic_level`
+when calling :func:`diagnostic_begin`:
+
+.. literalinclude:: ../../../testsuite/libdiagnostics.dg/test-warning.c
+ :language: c
+ :start-after: /* begin quoted source */
+ :end-before: /* end quoted source */
+
+On compiling and running the program, we should get output similar to::
+
+ test-warning.c:17:11: warning: this is a warning
+ 17 | #include <foo.h>
+ | ^~~~~
+
+Various severities are possible, see :enum:`diagnostic_level` for more
+information.
+
+In :doc:`the next section of the tutorial <06-fix-it-hints>` we'll look
+at adding fix-it hints to diagnostics.
diff --git a/gcc/doc/libdiagnostics/tutorial/06-fix-it-hints.rst
b/gcc/doc/libdiagnostics/tutorial/06-fix-it-hints.rst
new file mode 100644
index 000000000000..9486ab7f91c1
--- /dev/null
+++ b/gcc/doc/libdiagnostics/tutorial/06-fix-it-hints.rst
@@ -0,0 +1,61 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Tutorial part 6: fix-it hints
+=============================
+
+libdiagnostics supports adding "fix-it hints" to a :type:`diagnostic`:
+suggestions for the user on how to edit their code to fix a problem. These
+can be expressed as insertions, replacements, and removals of text.
+
+For example, here we add a replacement fix-it hint to a diagnostic:
+
+.. literalinclude:: ../../../testsuite/libdiagnostics.dg/test-fix-it-hint.c
+ :language: c
+ :start-after: /* begin quoted source */
+ :end-before: /* end quoted source */
+
+On compiling and running the program, we should get output similar to::
+
+ test-fix-it-hint.c:19:13: error: unknown field 'colour'; did you mean
'color'
+ 19 | return p->colour;
+ | ^~~~~~
+ | color
+
+We can also add a call to :func:`diagnostic_manager_write_patch` to the
+program cleanup code::
+
+ diagnostic_manager_write_patch (diag_mgr, stderr);
+
+This will write a patch to the stream (here ``stderr``) giving the effect
+of all fix-it hints on all diagnostics emitted by the
+:type:`diagnostic_manager`, giving something like::
+
+ @@ -16,7 +16,7 @@
+ struct rgb
+ get_color (struct object *p)
+ {
+ - return p->colour;
+ + return p->color;
+ }
+
+
+See the :doc:`guide to fix-it hints <../topics/fix-it-hints>`
+for more information, or go on to
+:doc:`the next section of the tutorial <07-execution-paths>`.
diff --git a/gcc/doc/libdiagnostics/tutorial/07-execution-paths.rst
b/gcc/doc/libdiagnostics/tutorial/07-execution-paths.rst
new file mode 100644
index 000000000000..0fbbed25d3a5
--- /dev/null
+++ b/gcc/doc/libdiagnostics/tutorial/07-execution-paths.rst
@@ -0,0 +1,141 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+.. default-domain:: c
+
+Tutorial part 7: execution paths
+================================
+
+A :type:`diagnostic` can optionally have a :type:`diagnostic_execution_path`
+describing a path of execution through code.
+
+For example, let's pretend we're writing a static analyis tool for finding
+bugs in `CPython extension code <https://docs.python.org/3/c-api/index.html>`_.
+
+Let's say we're analyzing this code:
+
+.. literalinclude::
../../../testsuite/libdiagnostics.dg/test-warning-with-path.c
+ :language: c
+ :start-after: begin fake source
+ :end-before: end fake source
+
+This code attempts to take an Python integer parameter and then build a
+list of that length, containing random integers. However, there are
+**numerous bugs** in this code: a type mismatch, mistakes in
+reference-counting, and an almost total lack of error-handling.
+
+For example, ``PyList_Append`` requires a non-NULL first parameter (``list``),
+but ``PyList_New`` can fail, returning NULL, and this isn't checked for,
+which would lead to a segfault if ``PyList_New`` fails.
+
+We can add a :type:`diagnostic_execution_path` to the :type:`diagnostic`
+via :func:`diagnostic_add_execution_path`, and then add events to it
+using :func:`diagnostic_execution_path_add_event`.
+
+For example, with::
+
+ diagnostic_event_id alloc_event_id
+ = diagnostic_execution_path_add_event (path,
+ loc_call_to_PyList_New,
+ logical_loc, 0,
+ "when %qs fails, returning NULL",
+ "PyList_New");
+
+we create an event that will be worded as::
+
+ (1) when `PyList_New' fails, returning NULL
+
+Note that :func:`diagnostic_execution_path_add_event` returns a
+:type:`diagnostic_event_id`. We can use this to refer to this event
+in another event using the ``%@`` format code in its message, which
+takes the address of a :type:`diagnostic_event_id`::
+
+ diagnostic_execution_path_add_event (path,
+ loc_call_to_PyList_Append,
+ logical_loc, 0,
+ "when calling %qs, passing NULL from %@
as argument %i",
+ "PyList_Append", &alloc_event_id, 1);
+
+where the latter event will be worded as::
+
+ (2) when calling `PyList_Append', passing NULL from (1) as argument 1
+
+where the ``%@`` reference to the other event has been printed as ``(1)``.
+In SARIF output the text "(1)" will have a embedded link referring within the
sarif
+log to the ``threadFlowLocation`` object for the other event, via JSON
+pointer (see `§3.10.3 "URIs that use the sarif scheme"
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790707>`_).
+
+Let's add an event between these describing control flow, creating three
+events in all:
+
+.. literalinclude::
../../../testsuite/libdiagnostics.dg/test-warning-with-path.c
+ :language: c
+ :start-after: begin path creation
+ :end-before: end path creation
+
+Assuming we also gave it :type:`diagnostic_logical_location` with:
+
+.. literalinclude::
../../../testsuite/libdiagnostics.dg/test-warning-with-path.c
+ :language: c
+ :start-after: begin create logical locs
+ :end-before: end create logical locs
+
+and finish the :type:`diagnostic` with :func:`diagnostic_finish` like this::
+
+ diagnostic_finish (d,
+ "passing NULL as argument %i to %qs"
+ " which requires a non-NULL parameter",
+ 1, "PyList_Append");
+
+then we should get output to text sinks similar to the following::
+
+ In function 'make_a_list_of_random_ints_badly':
+ test-warning-with-path.c:30:5: warning: passing NULL as argument 1 to
'PyList_Append' which requires a non-NULL parameter"
+ 30 | PyList_Append(list, item);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~
+ make_a_list_of_random_ints_badly': events 1-3
+ 26 | list = PyList_New(0);
+ | ^~~~~~~~~~~~~
+ | |
+ | (1) when 'PyList_New' fails, returning NULL
+ 27 |
+ 28 | for (i = 0; i < count; i++) {
+ | ~~~~~~~~~
+ | |
+ | (2) when 'i < count'
+ 29 | item = PyLong_FromLong(random());
+ 30 | PyList_Append(list, item);
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~
+ | |
+ | (3) when calling 'PyList_Append', passing NULL from (1) as
argument 1
+
+and for SARIF sinks the path will be added as a ``codeFlow`` object
+(see SARIF 2.1.0 `3.36 codeFlow object
<https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790990>`_).
+
+Here's the above example in full:
+
+.. literalinclude::
../../../testsuite/libdiagnostics.dg/test-warning-with-path.c
+ :language: c
+ :start-after: begin full example
+ :end-before: end full example
+
+
+Moving on
+*********
+
+That's the end of the tutorial. For more information on libdiagnostics, see
+the :doc:`topic guide <../topics/index>`.
diff --git a/gcc/doc/libdiagnostics/tutorial/example-1.png
b/gcc/doc/libdiagnostics/tutorial/example-1.png
new file mode 100644
index
0000000000000000000000000000000000000000..d637103036bd3fd4562bef0d7e30b40662cda1c4
GIT binary patch
literal 5646
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
U%9h0_Fsp@Vsp+ehK6oDXe;Xbzy8r+H
literal 0
HcmV?d00001
diff --git a/gcc/doc/libdiagnostics/tutorial/index.rst
b/gcc/doc/libdiagnostics/tutorial/index.rst
new file mode 100644
index 000000000000..6ea6866e2914
--- /dev/null
+++ b/gcc/doc/libdiagnostics/tutorial/index.rst
@@ -0,0 +1,32 @@
+.. Copyright (C) 2024 Free Software Foundation, Inc.
+ Originally contributed by David Malcolm <[email protected]>
+
+ This is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ <https://www.gnu.org/licenses/>.
+
+Tutorial
+========
+
+The following tutorial gives an overview of how to use libdiagnostics.
+
+.. toctree::
+ :maxdepth: 2
+
+ 01-hello-world.rst
+ 02-physical-locations.rst
+ 03-logical-locations.rst
+ 04-notes.rst
+ 05-warnings.rst
+ 06-fix-it-hints.rst
+ 07-execution-paths.rst
--
2.26.3