.. _Analyzing_Code: ************** Analyzing Code ************** .. note:: This section assumes that a project file exists for your codebase and has been configured to be compatible with GNAT SAS according to :ref:`Project_Setup`. If there is no project file defined, follow :ref:`Creating_Project_File`. This section describes how to run an analysis with GNAT SAS and presents in more details some analysis features such as :ref:`Analysis_modes` and :ref:`Timeline`. It also provides recommendations to get the best out of the analysis depending on your needs, see :ref:`Getting_the_Right_GNAT_SAS_Settings`. .. seealso:: The analysis can be configured in various ways (analysis scope, precision, :term:`output directory`...). This is described in details in :ref:`Configuring_Analysis`. Running GNAT SAS Analysis ========================= .. _Running_GNAT_SAS_From_The_Command_Line: Running GNAT SAS from the Command Line -------------------------------------- GNAT SAS can be run from the command line, when doing simple experiments, development or for running jobs automatically. A typical invocation of GNAT SAS will look like: .. code-block:: sh $ gnatsas analyze -Pmy_project Once done, GNAT SAS generates a `SAM file` that contains the results of the analysis (see :ref:`GNAT_SAS_Files`). You can then view the results in multiple formats or IDEs (e.g. GNAT Studio, a Web browser, a SARIF viewer...), or directly in text format from your terminal with: .. code-block:: sh $ gnatsas report -Pmy_project alias.adb:10:11: high: divide by zero fails here: requires Page_Size /= 0 .. seealso:: * See :ref:`CLI_Reference` for more details about the GNAT SAS command line. * See :ref:`How_to_View_GNAT_SAS_Output` for more details about the ways to view the GNAT SAS output. Running GNAT SAS from GNAT Studio --------------------------------- GNAT SAS can also be run from GNAT Studio where it is fully integrated. See :ref:`Running_GNAT_SAS_from_GNAT_Studio`. .. _Analysis_modes: Analysis modes ============== You can vary the thorougness of GNAT SAS' analysis by changing its `mode`. Two modes are available, and can be selected from the command-line or from GNAT Studio: `fast` and `deep`. Analyses are done in fast mode by default. Command-line examples: Fast mode .. code-block:: sh $ gnatsas analyze -Pmy_project or $ gnatsas analyze -Pmy_project --mode fast Deep mode .. code-block:: sh $ gnatsas analyze -Pmy_project --mode deep For selecting the mode in GNAT Studio, see :ref:`Invocation_from_GNAT_Studio`. We recommend developers run fast mode, as it offers the best precision/performance trade-off. Also, incrementality is very important to get fast analysis times e.g. when running from GNAT Studio. Deep mode should be reserved when a more precise analysis is meaningful, e.g. during nightly testing. .. note:: Note that changing the mode currently only impacts Inspector's results and has no impact on other engines. The impact on Inspector is as below. * In fast mode, Inspector analyzes each library unit separately. This allows Inspector's analysis to be `incremental`: when re-analyzing a project, only the units that have changed will need to be re-inspected. * In deep mode, Inspector performs the analysis by group of units, whose size depend on factors depending in :ref:`Partitioning_of_Analysis`. The analysis will start from scratch each time, and will be more thorough overall. Importantly, for each analysis mode, GNAT SAS generates a separate baseline. Each new run in a given mode is automatically compared to the associated baseline. The implications are described in the next section. .. _Timeline: Timelines ========= The fact that GNAT SAS uses a separate baseline for each :ref:`analysis mode`, and is able to compare runs in a given mode to the associated baseline, is due to the existence of `timelines`. A timeline is exactly that: a name associated to a baseline run, and the automatic comparison of each new run to that baseline. As such, timelines are separate from one another. Both fast and deep modes, as well as combinations of an analysis mode and switches that have an influence on the scope of the analysis (detailed below), are automatically associated to a separate timeline. More specifically, the timeline name is computed as follows: * The timeline for the default mode (fast mode) of a given project ``MyProject.gpr`` when none of the switches below are specified is ``"fast"``, and the timeline of a deep analysis is ``"deep"``. * with ``--file FILE_NAME`` or ``--file FILE_PATH``: ``"[.deep]"`` * with ``--files-from FILE_NAME`` or ``--files-from FILE_PATH``: ``"[.deep]"`` * with ``-U``: ``"_U[.deep]"`` * with ``-U FILE_NAME`` or ``-U FILE_PATH``: ``"_U_[.deep]"`` * with ``--no-subprojects``: ``"_no_sub[.deep]"`` where ``.deep`` is appended in deep mode. .. seealso:: * See :ref:`CLI_Reference` for more details about the GNAT SAS command line and supported switches. * See also :ref:`DB_Migration` for timelines generated by a CodePeer database importation. Using custom timelines ---------------------- In some cases, it may be desirable to manipulate specific timelines different from the default generated ones. For example: * When you want to perform an analysis in a given mode, but due to the settings large discrepancies are expected. Typically, when using different scenario variables values in the project file. As an example, consider a case where you want to have a finer control over the scope of the analysis (typically excluding some directories or projects), and you do not want to mix the results with the results from an analysis of the whole project tree. The analysis can be run on the whole project tree in one timeline, and then on a more restricted project tree in another. * You may also want to do that in order to later merge otherwise separated timelines (e.g. fast and deep mode). To support such use cases, GNAT SAS provides the capability to create and use new timelines with the ``--timeline`` switch. The ``--timeline `` switch can be set to the ``gnatsas analyze`` subcommand, with the following effects: * The first analysis of a timeline becomes the baseline of the said timeline *(unless a baseline was specifically set prior to it with* ``gnatsas baseline --timeline --set-baseline `` *, see* :ref:`GNAT_SAS_Baseline` *)*. * All analyses are automatically compared to the timeline's baseline. The ``--timeline `` switch can be set for the ``gnatsas report`` subcommand too. The effect is to display the results of the specified timeline's last run (instead of the actual last run's results). The ``--timeline `` switch can be specified in the ``gnatsas baseline`` subcommand in order to manipulate the specified timeline's baseline (see :ref:`GNAT_SAS_Baseline`), or current run (see use cases in :ref:`Importing_GNAT_SAS_Results` and :ref:`SAM-FROM-DB`). Displaying timeline information ------------------------------- Information about available timelines can be displayed using the ``--list-timelines`` switch. This switch will display all timelines that were automatically created by the tool or explicitly specified by users for the specified project. For example: .. code-block:: sh $ gnatsas analyze -Pprj $ gnatsas analyze -Pprj --mode=deep $ gnatsas analyze -Pprj --list-timelines will display the list of timelines (fast, deep) and related information, such as the date of last run, command-line and project switches used for the analysis, paths to SAM file and baseline file. .. seealso:: See :ref:`CLI_Reference` for more details about the GNAT SAS command line and supported switches. .. _Getting_the_Right_GNAT_SAS_Settings: Getting the Right GNAT SAS Settings =================================== We recommend that you first get familiar with :ref:`System_Requirements` for a proper recommended configuration to run GNAT SAS. Analyze Messages ---------------- If a given run contains many messages, start analyzing them and identify if there are groups of uninteresting or incorrect messages. You can disable a category of messages producing uninteresting results in text output using the ``--show`` switch (see :ref:`Filtering_Messages` for more details). For example if messages related to *access checks* are not producing interesting results in your code base, you can disable these messages in text output using ``--show kind-access_check`` with ``gnatsas report``. If many uninteresting or incorrect messages are issued for a file, you can exclude this file from analysis via the ``Analyzer'Excluded_Source_Files`` project attribute or via ``pragma Annotate (GNATSAS, Skip_Analysis)`` as explained in :ref:`Partial_Analysis`. Also choose the relevant messages based on ranking: GNAT SAS ranks messages in categories depending on how interesting and likely to happen they are (see :ref:`Categorization_of_Messages`). While analyzing existing code, you should start looking at *High* messages first, then *Medium*, and finally if it makes sense, *Low* messages. A recommended setting is to consider *High* and *Medium* messages, which is what is displayed by default in the GNAT Studio report. If the run is mostly clean or contains mainly interesting messages, then try to see if there are messages disabled by default which may be interesting in your context. These are some :ref:`Infer_messages`, some :ref:`GNAT_Warnings_Messages`, some :ref:`GNATcheck_Messages`, and :ref:`Race_Condition_Messages`. .. seealso:: During this analysis of the results, you may want to start triaging and reviewing some messages. Refer to :ref:`Reviewing_Results_And_Improving_Code` for more details about the review process. Run GNAT SAS Faster ------------------- If runs are too slow for your needs (e.g. quick user feedback as opposed to nightly runs) then you should consider disabling some analysis engines (see :ref:`gnatsas analyze switches `), making sure you are using the ``-j0`` switch (enabled by default unless you are using another ``-jxx`` switch explicitly) and using a machine with as many cores as possible as well as using local fast drives, as explained in :ref:`System_Requirements`. If this isn't sufficient, or you don't want to disable an analysis engine that takes a lot of time, the next step is to identify the files that are taking a long time to analyze and exclude them from the analysis as per :ref:`Partial_Analysis`. Identifying files that take a long time to analyze by Inspector ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ To identify the files that are taking a long time to analyze by Inspector, you can save GNAT SAS' default output and sort it on the 4th column (timing info): .. code-block:: none analyzed main.scil in 0.05 seconds analyzed main__body.scil in 620.31 seconds analyzed pack1__body.scil in 20.02 seconds analyzed pack2__body.scil in 5.13 seconds For example using the sort utility: .. code-block:: sh $ gnatsas analyze -Pprj |& grep "^analyzed " | tee gnatsas-output.txt sort -r -g -k 4 gnatsas-output.txt You'll get: .. code-block:: none analyzed main__body.scil in 620.31 seconds analyzed pack1__body.scil in 20.02 seconds analyzed pack2__body.scil in 5.13 seconds analyzed main.scil in 0.05 seconds In this simple example, skipping the analysis of the body of unit main (e.g. :file:`main.adb`) will produce a 25 seconds analysis instead of taking more than 10 minutes. If it is not acceptable to exclude the whole file from the analysis, it is possible to use the switch ``--dbg-on dbg_slow_analyses`` to get Inspector timings for individual subprograms and :ref:`exclude only particular subprograms from the analysis `, like this: .. code-block:: gpr package Analyzer is for Switches ("inspector") use ("--dbg-on", "dbg_slow_analyses"); end Analyzer; Identifying files that take a long time to analyze by Infer ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. warning:: This section is specific to Unix systems. In particular, it does not apply to Windows systems. For Infer, you can use an interactive progress bar to get the information where Infer spent long time. You can enable this progress-bar by using ``-Q --progress-bar-style multiline``, like this: .. code-block:: gpr package Analyzer is for Switches ("infer") use ("-Q", "--progress-bar-style", "multiline"); end Analyzer;