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 <dmalc...@redhat.com> --- 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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 <dmalc...@redhat.com> + + 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