3. Project Setup

GNAT SAS requires a GNAT project file (a.k.a. GPR project file) to run. If you are using a third party compiler, this chapter starts with a quick walk-through for the creation of an initial gpr file, as well as common configuration for this setup. If you already have a project file that you use to compile with gprbuild, you should look at the second section to ensure that it works well with GNAT SAS.

Finally, the last section explains how to configure the GNAT SAS analysis and goes on with describing specific configurations of integrated engines.

See also

Refer to the GNAT Project Manager section of the GPR Tool's User Guide for general documentation about projects.

3.1. Configuration for Third Party Compilers

This section guides you through the typical steps to setup your project in order to use GNAT SAS when you do not use GNAT to compile your sources.

  1. First, you need to create a GPR project file. In order to do so we recommend using codepeer-gprname as described here. Indeed, while the resulting project file needs to be updated each time you modify the sources included in the project, codepeer-gprname will highlight early problems that the analysis would eventually encounter.

    At this stage, the project file should contain enough information to identify all the sources of the project (if you used codeper-gprname, they are listed in the prj_source_list.txt file). By default, GNAT SAS will analyze all of them. However, if there are files that you do not wish to analyze, these should be excluded from the analysis in a second stage (see this section). Indeed, the project should be as "compilable" as possible for the analysis to perform correctly.

    Warning

    Your project should not include the sources of your run-time.

  2. You should set your target to "gnatsas" with the Target attribute:

    project <project_name> is
    
      for Target use "gnatsas";
    
      […]
    

    You should not use the Runtime attribute, in particular Section Using the GNAT Target Runtime Directory does not apply since it only works with a runtime from GNAT.

  3. You may want to specify a Target Configuration File in order to provide target dependent values, such as endianness, type sizes, etc.

  4. If you use supported compiler-specific packages, you need to set your project file to use them.

Once done, you should be able to confirm that the project is properly set up by running a first analysis with the command:

gnatsas analyze -P <project_name>.gpr

You can then look at how to run the tool in this section, and complete your project file by Configuring the Analysis.

3.2. Creating a Project File

In this section, we present different ways to create a project file if your project does not yet contain one:

  1. Create a project file interactively using the Project Wizard in GNAT Studio;

  2. Create a project file manually;

  3. Use codepeer-gprname to automatically generate it.

We recommend taking the time to follow either option 1 or 2, as the generated project files in option 3 may be hard to understand, modify and hence maintain.

3.2.1. Creating a Project File with GNAT Studio

Please refer to GNAT Studio's documentation to discover how to generate project files from GNAT Studio using the Project Wizard.

3.2.2. Creating a Project File Manually

If your source code follows the default naming scheme (.ads/ .adb), then you can create a project file that will look like:

project My_Project is
   for Source_Dirs use ("./**");
   for Target use "gnatsas";
end My_Project;

saved in a file called my_project.gpr located in the root of the project tree. Note that you can specify as many source directories as needed as part of the Source_Dirs setting. The special syntax dir/** represents the directory dir and all its subdirectories recursively (in the above example, the current directory represented by . and all its subdirectories). Specifying gnatsas for the target will allow the analysis engines to find the Ada runtime bundled with GNAT SAS.

3.2.3. Generating a Project File

A project file can be generated from an existing directory structure using the codepeer-gprname utility. Whenever a new source file is added to the project or an existing source file is removed, codepeer-gprname needs to be re-run to update the project.

Here is the typical usage of codepeer-gprname:

codepeer-gprname -Pmy_project "-d./**" "*.ad?" "*.spc" "*.bdy"

It will create or update a project file called my_project.gpr listing all the Ada source files found under the current directory and all its subdirectories, whose name follow the given patterns (all files ending with .ad<any character>, all files ending with .spc and all files ending with .bdy).

Note that codepeer-gprname requires a writable temporary directory. If the project file generated is empty, you might need to set the environment variable TMPDIR to a writable directory.

See the gprname documentation in the GNAT User's Guide for more details on how to use gprname.

3.3. Ensuring compatibility with GNAT SAS

Note

This section assumes that a project file has been defined for the codebase to analyse. If that is not the case, refer to the instructions in Creating a Project File.

This section describes how to configure the project file so that:

  • specificities of the code to analyze and of the target are taken into account;

  • general aspects related to the analysis of Ada packages are considered;

  • specific aspects related to GNAT SAS analysis engines that rely on the GNAT compiler are taken into account;

  • ultimately, it can be correctly understood by GNAT SAS.

Warning

This section does not describe the configuration of the GNAT SAS analysis. That is described in Configuring the Analysis.

3.3.1. Using GNAT SAS-Specific Project Settings

If you are using project files also to build with GNAT and need to use e.g. different builder switches between GNAT builds and GNAT SAS analysis, you can then use the predefined GPR_TOOL variable to differentiate the two modes in your project file:

Tool := External ("GPR_TOOL", "");

package Builder is
   case Tool is
      when "gnatsas" =>
         for Global_Compilation_Switches ("Ada") use ("-gnatI");
         -- -gnatI is only relevant for GNAT SAS
      when others =>
         for Global_Compilation_Switches ("Ada") use ("-O", "-g");
         -- Switches only relevant when building
   end case;
end Builder;

In GNAT SAS 24, GPR_TOOL is set automatically by GNAT SAS to gnatsas, so you do not need any extra configuration or command line switches to use the above.

3.3.2. Support for UTF-8 encoding

GNAT SAS is able to analyze source files that have UTF-8 encoding. Simply add the GNAT switch -gnatW8 to the Compiler package as below. GNAT SAS will report messages from Infer, GNAT Warnings and GNATcheck with UTF-8 encoding. See the Wide_Character Encodings section in the GNAT User's Guide for more details.

package Compiler is
   for Switches ("Ada") use ("-gnatW8");
end Compiler;

Warning

Concatenation of -gnatW8 with other switches is not supported. Please specify -gnatW8 independently from other switches. E.g. use -gnatiw -gnatW8 instead of -gnatiwW8.

Note

For Inspector messages, UTF-8 encoding is not fully supported. UTF-8 characters are converted to a different representation and the GNAT SAS output may become hard to read.

To be able to use identifiers with characters outside of the Latin-1 character set, typically UTF-8 characters, one may also use the -gnatiw switch as described below. See the Character Set Control section in the GNAT User's Guide for more details.

package Compiler is
   for Switches ("Ada") use ("-gnatW8", "-gnatiw");
end Compiler;

3.3.3. Use of Libraries Installed with GNAT

If your project uses some of the libraries installed with GNAT (e.g. GNATcoll, XML/Ada, AWS...) and, when launching GNAT SAS, you encounter a message similar to:

gnatcoll.gpr (4 items)
  unknown project file: "gpr"

Then add the following section to your project file to use the "gnatsas" runtime packaged with the GNAT SAS installation:

for Target use "gnatsas";

3.3.4. Use of Predefined Ada Packages

The predefined Ada packages (in particular, children of Ada, System, and Interfaces) come packaged with GNAT SAS. Make sure your project file does not include alternative predefined Ada source packages that may be provided by some Ada compilers, since these predefined packages may contain non-portable constructs that GNAT SAS may not recognize.

For compiler-specific packages, see Use of Compiler-Specific Packages for accessing some of these. If this isn't sufficient, you will need to include at least the package specs from your target compiler as part of your project file as for any other source file.

3.3.5. Use of Compiler-Specific Packages

If your Ada code base uses compiler-specific packages, GNAT SAS provides some of these packages pre-installed under install/share/gpr and accessible as pre-configured project files.

In particular you will find the following project files:

  • aa.gpr: ApexAda specific packages.

  • am.gpr: AdaMulti and AdaMagic specific packages.

  • oa.gpr: ObjectAda specific packages.

  • vads.gpr: VADS specific packages.

  • xgc.gpr: XGC specific packages.

To use these project files, add for example the following line to your project file (adjust the name of the imported project as needed):

with "am";

project My_Project is
   --  other declarations...
end My_Project;

If some compiler-specific packages are missing, do not hesitate to contact your GNAT SAS support.

3.3.6. Using Preprocessing

In order to enable preprocessing, you can use the -gnateD and -gnatep switches, e.g.:

package Compiler is
   for Switches ("Ada") use ("-gnateDVAR1=xxx", "-gnateDVAR2=yyy");
end Compiler;

Note the use of the package Compiler here. The -gnateD switches in the Analyzer package are ignored. All the -gnateD switches are accumulated to find the defined symbols. If -gnatep is used, it should appear only once and the given file is used to specify the preprocessing data file. See also the section Form of Input Text for gnatprep in chapter Preprocessing with gnatprep for more details on the syntax supported by the preprocessor.

3.3.7. Arbitrary Naming Scheme

If you are using a different naming scheme than the default .ads/ .adb for your source files, you can define the naming scheme adding a package Naming if a single and consistent naming scheme is used for all your source files.

For instance:

project My_Project is
   ...

   package Naming is
      for Spec_Suffix ("Ada") use ".1.ada";
      for Body_Suffix ("Ada") use ".2.ada";
      for Separate_Suffix use ".2.ada";
      for Dot_Replacement use ".";
   end Naming;
end My_Project;

or:

project My_Project is
   ...

   package Naming is
      for Spec_Suffix ("ada") use "_.ada";
      for Body_Suffix ("ada") use ".ada";
      for Separate_Suffix use ".ada";
      for Dot_Replacement use "__";
   end Naming;
end My_Project;

If more complex naming schemes are used (e.g. files with mixed casing, no automatic mapping between unit names and file names, use of multiple units in a single file, etc...) then you have three options:

  • In GNAT Studio: use the File ‣ Project ‣ Add Complex File Naming Conventions... menu and follow the dialog. This will call the underlying command line tool codepeer-gprname and modify the project file for you. See the GNAT Studio documentation for more details.

  • Use the codepeer-gprname tool to generate the custom naming scheme automatically. See the section Generating a Project File for more details.

  • Use the codepeer-gnatchop tool:

    Your sources can be preprocessed to generate .ads/.adb files by running codepeer-gnatchop on all your Ada sources and use a simple project file on the generated sources, for instance under Linux:

    cd <root source directory>
    mkdir sources
    find . -name sources -prune -o -name '*.ad?' -exec codepeer-gnatchop {} sources \;
    

    This command will take all files ending with .ad<any character> under the current source tree, and generate a corresponding .ads/.adb file under a new directory called sources. You can then use in your project file:

    for Source_Dirs use ("sources");
    

3.3.8. Ada Language Version

Note

This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines.

By default, GNAT Warnings and Inspector assume that sources use the Ada 2012 language. If your sources use an older version of Ada, then you will need to add the following to your project file:

package Builder is
   for Global_Compilation_Switches ("Ada") use ("-gnat95");
end Builder;

The switches corresponding to the various Ada versions are: -gnat83, -gnat95, -gnat2005, -gnat2012, -gnat2022.

Note that some Ada 95 compilers support the overriding keyword but no other Ada 2005 features. In order to analyze such code, you need to add the -gnatd.D switch in your project file, in addition to the -gnat95 switch:

package Builder is
   for Global_Compilation_Switches ("Ada") use ("-gnat95", "-gnatd.D");
end Builder;

Note

Using Global_Compilation_Switches in the Builder package should be preferred over defining the switches in the Compiler package, since the former applies to the whole project hierarchy, while the latter only applies to the current project and not to subprojects.

3.3.9. Representation Clauses

Note

This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines.

If GNAT Warnings or Inspector generate errors related to Ada representation clauses, a simple way to address these errors is to add the -gnatI compiler switch to your project file:

package Compiler is
   for Switches ("Ada") use ("-gnatI");
end Compiler;

-gnatI instructs GNAT Warnings and Inspector to ignore representation clauses, as if they had been stripped from the source code.

3.3.10. Target Configuration File

Note

This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines.

Usually, using either the default GNAT SAS settings, the GNAT SAS --bits=32 switch (see 32-bits mode) or the Compiler package Ada's -gnatI switch (see Representation Clauses), is sufficient to analyze code for most targets.

If you need to configure GNAT Warnings and Inspector so that they have a deeper knowledge and understanding of the target compiler, and in particular setting target dependent values such as endianness or sizes and alignments of standard types, then you might need to add the following to your project file:

package Compiler is
   for Switches ("Ada") use ("-gnateT=" & project'Project_Dir & "/target.atp");
end Compiler;

where target.atp is a file stored here in the same directory as the project file my_project.gpr, which contains the target parametrization. This file can be generated by calling the GNAT compiler for your target with the switch -gnatet=target.atp. The format of this file is described in the GNAT User's Guide as part of the -gnateT switch description.

Here is an example of a configuration file for a bare board PowerPC 750 processor configured as big-endian:

Bits_BE                       1
Bits_Per_Unit                 8
Bits_Per_Word                32
Bytes_BE                      1
Char_Size                     8
Double_Float_Alignment        0
Double_Scalar_Alignment       0
Double_Size                  64
Float_Size                   32
Float_Words_BE                1
Int_Size                     32
Long_Double_Size             64
Long_Long_Long_Size          64
Long_Long_Size               64
Long_Size                    32
Maximum_Alignment            16
Max_Unaligned_Field          64
Pointer_Size                 32
Short_Enums                   0
Short_Size                   16
Strict_Alignment              1
System_Allocator_Alignment    8
Wchar_T_Size                 32
Words_BE                      1

float          6  I  32  32
double        15  I  64  64
long double   15  I  64  64

If your target compiler is not GNAT, or an old version of GNAT, then you can also build and run the small utility called generate_target which can be found under <gnatsas install>/share/gnatsas/target. See comments inside this file for instructions on how to use it.

Note that, depending on the Ada constructs you are using and the values specified in the target configuration file, some combinations will not be properly supported and will lead to errors. In this case, consider using the -gnatI switch instead, or contact GNAT SAS support for alternatives.

3.3.11. Using the GNAT Target Runtime Directory

Note

This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines.

As a general rule, we strongly recommend using for Target use "gnatsas"; in your project file (see Use of Libraries Installed with GNAT). If however you want to use a specific GNAT runtime, you can do so by following the explanations given in this section.

Warning

The runtime you intend to use must come from a version of GNAT identical to GNATSAS' one. A runtime coming from GNAT 22.2 will not be compatible with GNAT SAS 24.2. In such a case you will be forced to specify for Target use "gnatsas";

Let's assume you are using GNAT as your target compiler, and explicitly specify a runtime and target to use in your project:

for Target use "arm-eabi";
for Runtime ("Ada") use "ravenscar-sfp-stm32f4";

Inspector and GNAT Warnings will take such setting into account and will use the GNAT runtime directory, as long as your target compiler is found in your PATH environment variable. As mentioned above, you will need to use a matching version of GNAT and GNAT SAS (e.g. GNAT 24.0 and GNAT SAS 24.0).

The handling of runtimes of Inspector and GNAT Warnings is in fact unified with that of the GNAT compiler. For details, see "GNAT User's Guide Supplement for Cross Platforms", Section 3. If you specify a target, note that Inspector may use additional configuration, see the section Target Configuration File.

If for some reason you do not have access to the GNAT compiler on the same machine as GNAT SAS (e.g. the GNAT cross compiler is installed on a different host than GNAT SAS) you will first need to copy the GNAT runtime directory in the GNAT SAS installation, under <gnatsas-install-dir>/libexec/codepeer/lib/gcc/<gnatsas-platform>/<gnatsas-toolchain-version>/ where <gnatsas-platform> is either x86_64-pc-linux-gnu or x86_64-w64-mingw32 and <gnatsas-toolchain-version> is the version of GNAT SAS toolchain.

Note

This does not wave aside the requirement of having matching versions of GNAT SAS and GNAT.

For example, assuming you want to use a runtime called ravenscar-sfp-stm32f4, then first locate this runtime on the machine with the GNAT installation, e.g.:

$ arm-eabi-gnatls -v --RTS=ravenscar-sfp-stm32f4 | grep adalib

This command gives the path to <ravenscar-sfp-stm32f4 runtime>/adalib.

You then need to copy/transfer the <ravenscar-sfp-stm32f4 runtime> directory to the GNAT SAS installation, under <gnatsas-install-dir>/libexec/codepeer/lib/gcc/<gnatsas-platform>/<gnatsas-toolchain-version>/, for example using bash syntax:

$ scp -pr $(dirname $(arm-eabi-gnatls -v --RTS=ravenscar-sfp-stm32f4 | grep adalib)) \
  <gnat-sas-machine>:<gnatsas-install-dir>/libexec/codepeer/lib/gcc/<gnatsas-platform>/<gnatsas-toolchain-version>

Note

If you don't have access to the GNAT compiler and you copied the GNAT runtime directory in the GNAT SAS installation, you need to use for Target use "gnatsas";. You can then take the specificities of your target into account separately as described in Target Configuration File.

3.3.11.1. Working with target-specific configurations

Even when a specific target is used for compilation, we recommend using gnatsas as a target for the analysis when possible. To achieve this, you can either create a dedicated project file for the analysis or use a scenario variable to set different targets for compilation and analysis:

case Enable_GNATSAS is
  when "True" =>
    for Target use "gnatsas";
  when "False" =>
    for Target use "x86_64-pc-linux-gnu";
end case;

If a target other than gnatsas is necessary for the analysis, be aware that GNAT SAS takes such a target into account, however, the project's Target attribute will still be interpreted as having the value "gnatsas" when processing the project file in the context of GNAT SAS. This means that the project's 'Target attribute should not be directly referenced in other attributes (e.g. for Object_Dir use Project'Target) in parts of the project file that apply to GNAT SAS.

If the set of sources to analyze depends on the target, you can use a scenario variable to specify the set of sources for GNAT SAS:

Tool := External ("GPR_TOOL", "");
Target := project'Target;
Sources := (".");

case Tool is
  when "gnatsas" =>
    Sources := Sources & ("src/common/" & "x86_64-pc-linux-gnu");
  when others =>
    Sources := Sources & ("src/common/" & Target);
end case;

for Source_Dirs use Sources;

If you want to analyze a codebase with different targets and each target has specific sources, you can define a scenario variable defining such targets and use it instead of using Target directly. In this case, --subdirs or for Subdirs should be used to separate each target-specific analysis by creating a separate gnatsas directory for it. For example:

Tool := External ("GPR_TOOL", "");
type Gnatsas_Target_Type is ("x86_64-pc-linux-gnu", "aarch64-linux-gnu");
Gnatsas_Target : Gnatsas_Target_Type :=
  external("GNATSAS_TARGET", "x86_64-pc-linux-gnu");

Target := project'Target;

Sources := (".");

case Tool is
  when "gnatsas" =>
    Sources := Sources & ("src/common/" & Gnatsas_Target);
  when others =>
    Sources := Sources & ("src/common/" & Target);
end case;

for Source_Dirs use Sources;

package Analyzer is
  for Subdirs use Gnatsas_Target; -- will result in a gnatsas directory
                                  --  located in
                                   --  "<obj_dir>/<Gnatsas_Target>/gnatsas"
end Analyzer;

3.3.12. Configuration of System Package (system.ads)

Note

This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines.

Some Ada compilers provide additional, non-portable definitions in the predefined package System which might lead to errors when running Inspector and GNAT Warnings analyses.

A solution to address this issue automatically is to use the pragma Extend_System in a pragma configuration file, either using one of the predefined GNAT extensions (e.g. Aux_Dec for the DEC Ada compiler or VADS for the VADS compiler, available via the project file vads.gpr as described in Use of Compiler-Specific Packages), or by providing a customized s-auxcom.ads file.

For example, you can create a file called gnatsas.adc located under the same directory where your project file is, which will contain:

pragma Extend_System (Aux_Dec);

or alternatively:

pragma Extend_System (Aux_VADS);

And configure your project file to take this file into account:

package Builder is
   for Global_Configuration_Pragmas use "gnatsas.adc";
end Builder;

or if using Aux_VADS:

with "vads";
project My_Project is

   package Builder is
      for Global_Configuration_Pragmas use "gnatsas.adc";
   end Builder;

end My_Project;

Similarly, if your target compiler provides additional definitions, you can manually create a s-auxcom.ads file containing these additional definitions, e.g.:

package System.Aux_Compiler is
   pragma Preelaborate;

   function To_Integer (Addr : Address) return Integer;
   function To_Address (Int  : Integer) return Address;

   No_Addr      : constant Address := Null_Address;
   Address_Zero : constant Address := Null_Address;

   Assertion_Error : exception;

   ...
end System.Aux_Compiler;

and then specify:

pragma Extend_System (Aux_Compiler);

in gnatsas.adc.

See the GNAT Reference Manual for more details on Pragma Extend_System.

Also note that you should never include the compiler System package in your project file (either in your source file list or even in your source directories), as Inspector needs to use its own version of system.ads.

3.3.13. Ignoring Pragmas

Note

This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines.

In some cases, non-portable pragmas are used across Ada technologies in an incompatible way, generating some spurious error messages when Inspector or GNAT Warnings analyze these files. In order to address these issues, you can configure your project file to ignore a set of pragmas via the Ignore_Pragma pragma that you should place in a gnatsas.adc file as explained in Configuration of System Package (system.ads). For example, if you want to ignore pragmas called Import_Procedure and Import_Function you can put in your gnatsas.adc:

pragma Ignore_Pragma (Import_Procedure);
pragma Ignore_Pragma (Import_Function);

Similarly if you want to ignore pragma Global:

pragma Ignore_Pragma (Global);

If not already done, you need to configure your project file to take this file into account:

package Builder is
   for Global_Configuration_Pragmas use "gnatsas.adc";
end Builder;

3.3.14. Providing Stubs for Missing Generic Bodies

Note

This section only impacts GNAT-based engines (i.e. Inspector and GNAT Warnings), and has no impact on other engines.

GNAT Warnings and Inspector will ignore missing bodies and will make reasonable presumptions about calls to such unknown subprograms (see Inspector Presumptions).

However they will generate an error when they encounter a generic package whose body is missing at instantiation time. In order to work around this error, you can provide a skeleton for the generic package via the codepeer-gnatstub utility, e.g.:

codepeer-gnatstub -Pmy_project generic_package.ads

will generate a file generic_package.adb which can be used by GNAT Warnings and Inspector.

3.4. Configuring the Analysis

Note

This section assumes that a project file has been defined for the codebase to analyse and configured to be compatible with GNAT SAS. If that is not the case, refer to the instructions in Creating a Project File and Ensuring compatibility with GNAT SAS.

This section describes how the GNAT SAS analysis can be configured by users to adjust the scope of the analysis, its precision, control where files are generated, etc. It also explains the available configuration for each integrated analysis engine.

All analysis engines are enabled by default. It is possible to individually enable or disable any engine (see gnatsas analyze switches).

3.4.1. Analyzer package attributes

In addition to the project attributes described in the GPRbuild and GPR Companion Tools User's Guide and described in Project Setup (e.g. Source_Dirs, Object_Dir attributes, Naming and IDE packages, ...), the following optional project attributes are available in the Analyzer package:

  • Subdirs

    Relative path from the object directory (<object_dir> specified with Object_Dir, or project directory otherwise) to the gnatsas directory where results and intermediate files will be output. The path to the gnatsas directory will be [<object_dir>/]<subdirs>/gnatsas. Note that if the Output_Dir attribute is set, analysis results will be stored in that directory instead, whereas the location of intermediate files will remain as specified by the Subdirs attribute.

  • Output_Dir

    GNAT SAS output directory to use for this project. By default, the output directory is [<object_dir>/][<subdirs>/]gnatsas/<project>.outputs (or hereafter, <output_dir>), where <object_dir> is the directory specified by the Object_Dir project attribute, and <subdirs> is the relative path specified with Subdirs (see above). If you specify a relative directory, this directory is relative to the directory that contains the project file.

  • Review_File

    Review file to use for this project. By default, the review file is <output_dir>/<project>.sar. If you specify a relative path, this path is relative to the directory that contains the project file.

  • Excluded_Source_Files

    List of project source files (as base names) which should be excluded from GNAT SAS' analyses. See Excluding Files from Analysis for more info.

  • Excluded_Source_Dirs

    List of project source directories which should be excluded from GNAT SAS' analyses. See Excluding Directories from Analysis for more info.

  • Switches

    An associative array representing the additional switches that should be used for each GNAT SAS subcommand and analysis engines. Possible keys are:

    • "analyze"

    • "inspector", "infer", (and discouraged "gnat" and "gnatcheck", see below)

    • "report X", where X can be any format supported by the gnatsas report command (e.g. "report text" or "report csv"). Note that switches specified for a given format will not apply to other formats.

    • "baseline"

    Warning

    Using the Switches attribute in the Analyzer package is not recommended for configuring the analysis of GNATcheck and GNAT Warnings. Indeed, such configuration is not recognized by the corresponding tool when it is run standalone (i.e., not through GNAT SAS).

    The preferred workflow is to always configure GNATcheck through the Check package, and GNAT Warnings through the Compiler or Builder packages. Refer to Configuring GNATcheck and Configuring GNAT Warnings for more details about the configuration of those tools.

    project Prj is
          package Analyzer is
             for Switches ("analyze") use ("--mode=deep");
    
             --  This is NOT recommended:
             --  for Switches ("gnatcheck") use ("-rules", "+RLocal_Packages");
          end Analyzer;
    
          --  Use the Check package instead:
          package Check is
             for Default_Switches ("ada") use ("-rules", "+RLocal_Packages");
          end Check;
    end Prj;
    
  • Pending_Status, Not_A_Bug_Status, Bug_Status

    Lists of custom review status definitions, see Custom Review Status.

    See also

    Refer to the GNAT SAS CLI Reference for more information on supported switches.

3.4.1.1. 32-bits mode

By default GNAT SAS assumes that the compilation target is the same as the host on which it is run. This is often a sufficient default, although one typical case where this is not sufficient is when using GNAT SAS in 64-bits mode and analyzing code designed for 32-bits architectures. In this case, you can run GNAT SAS with the --bits=32 switch so that GNAT SAS will analyze the code assuming the same architecture, but in 32-bits mode instead of 64-bits. You can use this switch either from the command line, or specify it in the project file:

package Analyzer is
   for Switches ("analyze") use ("--bits=32");
end Analyzer;

See also Target Configuration File for advanced configuration of the target.

Warning

This is currently not supported for Infer and GNATcheck.

3.4.2. Partial Analysis

This section describes how to perform a partial analysis, and in particular, how to exclude entities (projects, directories, files, packages, subprograms) from analysis.

3.4.2.1. Selecting the Analysis Scope

GNAT SAS provides several switches allowing users to control the analysis scope, by passing them to the gnatsas analyze command line or specifying them in the project file:

  • The default behavior when none of the switches below are specified is to analyze the closure of the main units specified in the project file for the full project tree, except externally built units.

  • -U: analyze all files in the full project tree, except externally built ones.

  • -U FILE: analyze files contained in the closure of the FILE unit.

  • --no-subprojects: analyze all files in the root project only, ignoring all subprojects and also ignoring main units defined in the root project.

  • --file FILE: analyze a single file FILE.

  • --files-from FILE: analyze files listed in FILE.

See also

Refer to GNAT SAS CLI Reference for more information about GNAT SAS command-line usage.

In addition, it is possible to exclude entities from the analysis as explained in the following sections.

3.4.2.2. Excluding Subprograms or Packages from Analysis

Note

This section only applies to Infer and Inspector engines.

To selectively disable the analysis of a particular subprogram or set of subprograms for Infer and Inspector, you can add in your Ada source code a pragma Annotate of the form:

pragma Annotate (GNATSAS, Skip_Analysis);

When used in this way, an Annotate pragma takes exactly these two arguments. The pragma may be placed at the beginning (possibly preceded only by different Annotate pragmas) of the declaration list of a subprogram body, a package body, or package visible part.

In the case of a subprogram body, Infer and Inspector's analysis of that subprogram body (and anything declared therein, including nested subprograms) will not be performed. In the case of a package body, Infer and Inspector's analysis of any subprogram body occurring (directly or indirectly) within the package body will not be performed. In the case of a package visible part, analysis of subprogram bodies occurring in the package specification (as well as the package body) will not be performed; note that a subprogram body can occur in a package specification as part of an instantiation of a generic unit.

The subprogram or package in question may be a generic unit or may occur within a generic unit; in this case, the pragma will be replicated (as described in Ada RM 12.3(13)) when an instance of the generic unit is declared and will affect Inspector's analysis of the instance as described in this section.

When an Annotate pragma is used in this way to prevent Inspector and Infer's analysis of a subprogram body, the analysis of clients of the subprogram will be affected in the same way as if the body of the subprogram were unavailable for some other reason (e.g. a missing .adb file).

Here is an example of usage to disable analysis of a specific subprogram:

procedure Complex_Subprogram (...) is
   pragma Annotate (GNATSAS, Skip_Analysis);
begin
   ...
end Complex_Subprogram;

And similarly for a package:

package Complex_Package is
   pragma Annotate (GNATSAS, Skip_Analysis);

   ...
end Complex_Package;

3.4.2.3. Excluding Files from Analysis

If you want to exclude some files from the analysis (because e.g. GNAT SAS is taking lots of time analyzing them, and these files do not contain useful subprograms for GNAT SAS to analyze), you can use the Excluded_Source_Files project attribute in the Analyzer package, for example:

package Analyzer is
   for Excluded_Source_Files use ("xxx.adb");
   -- Analysis of xxx.adb generates lots of timeouts, skip it for now
end Analyzer;

For the values, ensure to always specify the basename of the excluded files, with no path information. The path information is computed automatically by GNAT SAS based on other project properties.

Warning

Project attributes in the Analyzer package (in particular Excluded_Source_Dirs and Excluded_Source_Files) are ignored when executing GNATcheck or GNAT Warnings as standalone tools.

Note

Note that excluding a specification file from the analysis also excludes the corresponding body file, if present. On the contrary, excluding a body file does not exclude the corresponding specification file.

3.4.2.3.1. Inspector-specific handling

The Inspector engine has some limitations when it comes to excluding files from the analysis. In the general case, exclusion can be done using the Analyzer package as previously described. However, in some specific cases file exclusion needs to be done differently. This section describes such cases and their impact.

Excluding a file containing a generic

When a file excluded from the analysis contains a generic, the generic will still be analyzed by Inspector if it is instantiated in at least one file that is not excluded. This is because Inspector doesn't analyze generics per se, but analyzes each instantiation of the generic as explained in Handling of Generic Units.

In such case, it is possible to exclude all instantiations of a generic package from the analysis as described in Excluding Subprograms or Packages from Analysis. Inspector will no longer attempt to analyze the excluded file (note, however, that it will still compile it and generate a SCIL for it; if that is not desirable, see the next paragraph).

Excluding a file from compilation and SCIL generation

If you want to not only exclude files from the analysis, but go further and also exclude it from compilation and SCIL generation; and if these files are not in the transitive closure of other files (e.g. a body file, as opposed to a specification file used by other Ada units); then the project-level Excluded_Source_Files attribute can be used instead of the Analyzer attribute:

project My_Project is
   for Excluded_Source_Files use ("xxx.adb");
end My_Project;

Warning

  • Unlike excluding a body file, excluding a specification file at the project level may cause compilation errors on the files depending on this spec and as a result prevent the analysis of those files.

  • If a specification or a body file of a module is excluded at the project level, Inspector will not be able to perform an incremental analysis of the modules depending on that module. This means that those modules will be fully re-analyzed by Inspector (even in fast mode).

Those effects do not occur if files are excluded using the Analyzer package.

See also

This mechanism may also be used to address some compilation errors as explained in Compilation Errors.

3.4.2.4. Excluding Directories from Analysis

If you want to exclude from analysis all source files from a given set of directories, you can use the Excluded_Source_Dirs project attribute in the Analyzer package, for example:

package Analyzer is
   for Excluded_Source_Dirs use ("directory1", "directory2");
end Analyzer;

Warning

Project attributes in the Analyzer package (in particular Excluded_Source_Dirs and Excluded_Source_Files) are ignored when executing GNATcheck or GNAT Warnings as standalone tools.

You can specify absolute directories or directories relative to the location of the project file (same as for source directories).

As explained in the section Excluding Files from Analysis, generic instantiations made in files not excluded from the analysis will be still analyzed. Note that it is possible to exclude all instantiations of a generic package from the analysis as described in Excluding Subprograms or Packages from Analysis.

3.4.2.5. Excluding Projects from Analysis

If you have a tree of project files (.gpr) and want to exclude some entire projects (aka subsystems) from GNAT SAS analysis, you can do it by adding the following project attributes to each of the projects involved:

for Externally_Built use "True";

This attribute tells GNAT SAS to disable analysis on all source files for this project.

Projects using files (e.g. spec) from this project will still be analyzed, as well as generic instantiations made in other projects.

3.4.3. Configuring GNATcheck

GNAT SAS uses a small selection of GNATcheck rules by default as listed in GNATcheck Messages. GNATcheck is enabled by default and can be disabled with the --no-gnatcheck switch. More rules can be checked by configuring the Check package of the project file.

See also

For more detailed information about configuring GNATcheck, see the GNATcheck Reference Manual.

The recommended workflow when using the GNATcheck engine in GNAT SAS is to configure the Check package of the project file. This ensures that the GNATcheck configuration defined for the project is consistently taken into account both by GNAT SAS and by GNATcheck when used as a standalone tool.

Some examples of configuration are provided below.

3.4.3.1. Differences with standalone GNATcheck tool

There exist noteworthy differences between using GNATcheck integrated in GNAT SAS and using GNATcheck as a standalone tool.

Note

In GNAT Studio, GNAT SAS with GNATcheck is available from the top-menu GNATSAS -> Analyze... (see GNAT SAS menu), while GNATcheck standalone is available from the menu Analyze -> Check Coding Standard.

In particular:

  • GNAT SAS runs five GNATcheck rules by default (see GNATcheck Messages), while standalone GNATcheck runs none.

  • The output of both tools is not stored and displayed in the same manner:

    • Standalone GNATcheck's default output directory is the directory specified by the Object_Dir of the project, or the current directory if no Object_Dir is specified. GNATcheck will generate a text report gnatcheck.out and other files under that directory. This behavior can be overridden with multiple switches defined in the Check package, such as --subdirs or -o. See the GNATcheck Reference Manual. for more details.

    • However, the results of the GNATcheck analysis integrated in GNAT SAS will be generated in the same format as messages from other engines (Message Files) and can be displayed in multiple ways (see Viewing Results). The default output directory is ./gnatsas/<PROJECT_NAME>.outputs if no Object_Dir is specified, and <OBJECT_DIR>/gnatsas/<PROJECT_NAME>.outputs otherwise. Internal GNATcheck output is also available under the <PROJECT_NAME>.gnatcheck directory at the same level. Other settings from the Check package will be ignored.

  • The set of sources analyzed by GNATcheck may differ (specified as "analyze" key switches in the Analyzer package or GNAT SAS command-line: -U, --file, --files-from, --no-subprojects``or ``for Source_Files; and specified as values of for Default_Switches ("ada"): -U, -files=, --no-subprojects in the Check package).

    • When running standalone GNATcheck, above settings from the Analyzer package will be ignored.

    • When running GNATcheck integrated in GNAT SAS, above settings from the Check package will be ignored.

  • Projects marked as externally built with the Externally_Built project attribute will not be analyzed when GNATcheck is ran through GNAT SAS.

  • The Annotate pragmas for GNAT SAS will only be taken into account when running GNATcheck through GNAT SAS. See Improve Your Code Specification.

  • The -j switch for controlling the number of jobs, can be specified through for Switches ("analyze") in the Analyzer package, which will override the settings set through for Default_Switches ("ada") in the Check package.

3.4.4. Configuring Infer

GNAT SAS runs some analyses based on Infer by default. Enabled by default, can be disabled with --no-infer.

Some Infer analyses can be activated and/or parameterized using Infer-specific switches. These switches can be specified using the index "infer" of the project attribute Switches in the Analyzer package:

project My_Project is
   package Analyzer is
      for Switches ("infer") use ("--side-effects");
   end Analyzer;
end My_Project;

This example will enable emitting a warning when a function has side effects.

The section Infer Messages contains a list of all Infer messages, with their description and detailed configuration parameters.

3.4.5. Configuring GNAT Warnings

The GNAT front-end warnings. Enabled by default, can be disabled with --no-gnat.

3.4.5.1. Specifying warnings to check

When enabled, GNAT SAS calls the GNAT front-end with the switches you enabled through the Default_Switches ("Ada") attribute of the Compiler package of your GPR file and a default selection of checks chosen by GNATSAS itself (see the table listing GNAT Warnings for an exact list). To disable or enable additional checks, add the relevant switches to the Analyzer package in your project file. Disabling warnings can be achieved by using the same mechanism as GNAT, i.e. specifying the warning switch using capital letters.

For example:

project prj is
   package Analyzer is
      for Switches ("gnat") use ("-gnatwbz.a");
      --  equivalent to:
      --  for Switches ("gnat") use ("-gnatwb", "-gnatwz", "-gnatw.a");
      --  disabled with:
      --  for Switches ("gnat") use ("-gnatwBZ.A");
   end Compiler;
end prj;

3.4.5.2. Ignoring Source File Timestamp Mismatch

If your environment changes the timestamps of your source files between GNAT SAS runs (with no actual changes in source files contents), then in order to minimize the regeneration of Inspector SCIL files or recomputation of GNAT Warnings, you can specify the --incrementality-method=checksums switch in the Analyzer package of your project file, so that checksums rather than timestamps should be used for determining whether source files have changed since the previous run:

package Analyzer is
   for Switches ("analyze") use ("--incrementality-method=checksums");
end Analyzer;

Note

This switch only impacts GNAT based engines, i.e., Inspector and GNAT Warnings.

Warning

When incrementality is based on checksums, some messages may end up referring to wrong source locations. Indeed:

Incrementality based on checksums internally relies on GPRbuild checksum computation. GPRbuild ignores comments when computing the checksum of a file. Hence, a file were only comments are modified between two gnatsas runs is not re-analyzed. While the messages on the file are still valid, they refer to source locations prior to the comments modifications.

3.4.6. Configuring Inspector

Inspector is the historical analysis engine of GNAT SAS. Enabled by default, can be disabled with --no-inspector.

See also

See Inspector Reference for more advanced Inspector configuration.

Example project file

Here is an example of a project file using some of the Inspector attributes described in the following sections:

project Prj1 is
   ...

   package Analyzer is
      for Excluded_Source_Files use ("file1.ads", "file2.adb");
      for Output_Dir use "/work/project1.outputs";
      for Switches ("analyze") use ("--keep-going");
      for Switches ("report text") use ("--show-backtraces");
      for Additional_Patterns use "ExtraMessagePatterns.xml";
   end Analyzer;
end Prj1;

3.4.6.1. Analyzer package attributes

  • Message_Patterns

    Alternate MessagePatterns.xml file that Inspector should use for this project.

  • Additional_Patterns

    Extra MessagePatterns.xml file that Inspector should use in addition to the default patterns file. This can be either a path relative to the project's directory, or an absolute path.

3.4.6.2. Ignoring Source File Timestamp Mismatch

See Ignoring Source File Timestamp Mismatch.

3.4.6.3. Ignoring Exception Handlers

By default Inspector tries to take exception handlers into account in its analysis, although by doing so this can lead to a loss of precision in the detection of possible (or certain) run-time errors. If you want Inspector to analyze the code by completely ignoring exception handlers (behave as if the exception handlers were stripped from the code) then you can add the -gnatd.x switch, e.g.:

package Analyzer is
   for Switches ("inspector") use ("-gnatd.x");
end Analyzer;

3.4.6.4. Handling Enumeration Representation Clauses

Even without -gnatI, Inspector by default ignores enumeration representation clauses, to reduce the various implicit representation transformations required by such clauses, which can produce confusing output. If your application uses Enum_Rep, Enum_Val, or Unchecked_Conversion to manipulate the underlying codes specified by an enumeration representation clause, then you may want to override this Inspector default by using the compiler switch -gnatd.I. This will cause Inspector to obey the enumeration representation clause and ensure that Enum_Rep, Enum_Val, and Unchecked_Conversion are interpreted correctly for this enumeration type. This switch can be added to your project file, as follows:

package Analyzer is
   for Switches ("inspector") use ("-gnatd.I");
end Analyzer;

3.4.6.5. Detection of Floating Point Overflow

Inspector assumes that floating point operations are carried out in single precision (binary32) or double precision (binary64) as defined in the IEEE-754 standard for floating point arithmetic. You should make sure that this is the case on your platform. For example, on x86 platforms, by default some intermediate computations may be carried out in extended precision, leading to unexpected results. With GNAT, you can specify the use of SSE arithmetic by using the compilation switches "-msse2 -mfpmath=sse" which cause all arithmetic to be done using the SSE instruction set which only provides 32-bit and 64-bit IEEE types, and does not provide extended precision. SSE arithmetic is also more efficient. Note that the ABI allows free mixing of units using the two types of floating-point, so it is not necessary to force all units in a program to use SSE arithmetic.

Inspector considers the floating point values which represent positive, negative infinity or NaN as invalid, and it checks that such values cannot occur.

By default, Inspector will only detect potential overflows on floating point operations on constrained floating point types (user floating point types with explicit ranges) and not on unconstrained types (e.g. predefined float types).

You can ask Inspector to check for possible floating point overflows on unconstrained types (which will then lead to infinite values) via the -gnateF compiler switch, e.g.:

package Compiler is
   for Switches ("Ada") use ("-gnateF");
end Compiler;