Contents
--------

1. What is gnatcheck?
2. gnatcheck parameters
3. Currently implemented rule checks
4. Add the results of compiler checks to gnatcheck output
5. Output format

1. What is gnatcheck?
   ------------------

gnatcheck is the GNAT rule checking command-line-based tool. It takes a set of
compilable Ada sources as input and checks then against some set of rules.
gnatcheck performs only a static analysis of the argument Ada units, so all
the rules implemented in gnatcheck are static rules.

All diagnostic information and all information demonstrating the progress in
processing the given set of sources is sent to stderr.

gnatcheck is an ASIS-based tool. It compiles the given source to create the
corresponding tree file (all these compilations take place in the temporary
directory, this directory is created in the beginning of gnatcheck run and it
is deleted when the processing of the argument sources is completed). If a
source file specified as gnatcheck argument does not contain a legal Ada
program unit, gnatcheck cannot process it. If the specified source contains
an Ada unit which depends on Ada units located in other directories, the user
can either specify the source search path by means of a -I gnatcheck option in
the same way as the source search path can be specified for GNAT, or use a
GNAT project file to specify the compilation environment.

2. gnatcheck parameters
   --------------------

gnatcheck has the following command-line interface:

   gnatcheck [options] {filename}  {-files=filename} [-cargs gcc_switches]
      [-rules rule_switches]

where:

 options:
 -a              - process RTL units
 -d              - debug mode
 -dd             - progress indicator mode (for use in GPS)
 -h              - print out the list of the currently implemented rules
 -l              - use full source location chains in the report file (this
                   option turns off alignment of line and column numbers in the
                   first section of the report file)
 -q              - quiet mode (do not report detections in Stdout)
 -v              - verbose mode
 -s              - short form of the report file
 -sn             - include only section n (n in 1 .. 3) in the report file

 filename        - the name of the Ada source file to be checked.
                   Wildcards are allowed
 -files=filemane - filename is the name of the text file containing a list
                   of Ada source files to analyze

gcc_switches  - a list of switches that are valid switches for gcc

rule_switches - a list of the following switches
   +ALL                - turn all the rules ON
   -ALL                - turn all the rules OFF
   +R<rule_id>[:param] - turn ON a given rule [with given parameter(s)]
   -R<rule_id>         - turn OFF a given rule
where <rule_id> - ID of one of the currently implemented rules, use '-h' for
                  the full list
      param     - string representing parameter(s) of a given rule, more then
                  one parameter can be set separated by ','

All the rule checks by default are enabled, except the checks performed by
the compiler and checks for the global rules. Use the rule switches to choose
the needed set of rules to be checked. Use '-h' option to get a full set of
the currently implemented rules (with the corresponding rule IDs).

Note, that space characters can not be used inside a rule switch, because a
space character is treated as a separator when processing a command line.

Note, that gcc switches set in the gnatcheck command line are passed directly
to the GNAT compilation command used to create the ASIS tree file.

The project support for gnatcheck is provided by means of calling gnatcheck
throuugh the GNAT driver:

  $ gnat check -Pproject ...

3. Currently implemented rule checks
   ---------------------------------

Now gnatcheck performs rule checks inside the results of generic
instantiations only for global rules.

At the moment checks for the following rules are implemented (for each rule
subsection the corresponding rule ID is used as a subtitle, this Id that can
be used as a parameter of +R and -R options). Rules marked with the "under
construction" remark are not fully implemented and tested at the moment, they
can not be used for real checks and can only be viewed on some simple
examples.

Rules inmplemented in gnatcheck are subdivided into local rules and global
rules. A local rule is a rule that is formulated for a well-localized fragment
of a program text and that can be checked by analyzing only this fragment (the
analyzis may use the semantic information related to the components of this
fragment). A global rule requires analysis of some global properties of the
whole program (mostly related to the program call graph). At the current stage
of gnatcheck project global rules are not sufficiently tested. You can use
+GLOBAL option to turn all the global rules ON, and -GLOBAL rule option to
turn all the global rules OFF. All the global rules in the list below are
marked by the remark "GLOBAL".

Abstr_Types
-----------
The use of abstract types are be detected. In case of an abstract private
type, both private and full type declarations are detected.

Anonymous_Subtypes
------------------
Any use of an anonymous subtype is detected. A use of an anonymous subtype is
any use of a construct 'subtype_mark constraint' different from immediately
within a subtype declaration. Any use of range different from the situation
when this range is a constraint used immediatelly within a subtype declaration
is also considered as the use of an anonymous subtype and should be detected

Blocks
------
Block statements are detected.

Bool_Relation_Ops
-----------------
According to the definition of the Spark language, relation operations <, >,
<=, >=, = and /= cannot be used for the type Boolean.

Calls to predefined relation operations (<, >, <=, >=, = and /=) of the
predefined Boolean type are detected.

Calls to predefined relation operations of any type derived from
Standard.Boolean are not detected.

Calls to user-defined functions with these designators are not detected

The use of an operation that is a renaming of a predefined relation operation
for Standard.Boolean is nopt detected

Ceiling_Pr_Consistency (under construction, GLOBAL)
----------------------
The situations when a protected operation is called by a higher priority
task is detected.

At the moment, the detection of violations of ceiling priority consistency is
performed with the following limitations:

- We consider only pragmas Priority and Interrupt_Priority as means to define
  a task/protected operation priority. We do not consider the effect of using
  Ada.Dynamic_Priorities.Set_Priority procedure;

- We consider only base task priorites, and no priority inheritance. That is,
  we do not make a difference between calls issued during task activation and
  execution of the sequence of statements from task body;

- Any situation when the priority of protected operation caller is set by a
  dynamic expression (that is, the corresponding Priority or
  Interrupt_Priority pragma has a non-static expression as an argument) we
  treat as a priority inconsistensy (and, therefore, detect this situation).

At the moment the notion of the main subprogram is not implemented in
gnatcheck, so any pragma Priority in a library level subprogram body (in case
if this subprogram Can_Be_Main_Program) changes the priority of an environment
task. So if we have more then one such pragma in the set of processed sources,
the pragma that is processed last, defines the priority of an environment
task.

Contr_Types
-----------
Declarations of controlled types are detected. A declaration of a private type
is detected if its full declaration defines a controlled type. A declaration
of a a derived type is detected if its ancestor type is controlled. Subtype
declarations are not detected. A declaration of a type that itself is not a
decendant of a type declared  in Ada.Finalization but has a controlled
component is not detected

Decl_Blocks
-----------
Block statements with local declarations are detected. A declare block with an
empty declarative_part or with a declarative part containing only pragmas
and/or use clauses is not detected.

Default_Par
-----------
Default expressions for subprogram parameters are detected. Parameter
declarations of formal and generic subprograms are also considered.

Derived_Types
-------------
Derived type declarations that does not have a record extension part are
detected.

Discr_Rec
---------
Declarations of record types with discriminants are detected. Only the
declarations of record and record extension types are detected. Incomplete,
formal, private, derived and private extension type declarations are not
detected. Task and protected type declarations also are not detected.

Float_Equality_Checks
---------------------
Calls to the predefined equality operations for floating point types are
detected. Both "=" and "/=" operations are checked. A floating point type here
is a type declared with floating point definition or a type derived from a
floating point type. User-defined equality operations are not detected. "="
and "/=" operations for fixed point types are not detected.

Global_Loop_Exit
----------------
An exit statement containing a loop name that is not the name of the
immediately enclosing loop statement is detected.

Goto
----
GOTO statements are detected.

LL_Subpr
--------
Library level subprograms (including subprogram instantiations) are detected.

Local_Pckg
----------
Local packages in package and generic package specs are detected. Local
packages in bodies are not detected

Max_Calls_To_PO_Entry (under construction, GLOBAL)
---------------------
Protected entries that can be called more then one task are detected.

One_Entry_In_PO
---------------
The situation when a protected definition defines more then one entry is
detected (diagnostic messages are generated for all the entry declarations
except the first one). An entry family is counted as one entry. Entries from
the private part of the protected definition are also counted

Overloaded_Operators
--------------------
A function declaration with an operator symbol as a defining designator is
detected. A function body is detected only if the body does not have a
separate spec. Formal functions are also considered for this rule. For a
renaming declarations, only renaming-as-declaration is detected

Proper_Returns
--------------
A return statement in a procedure body is detected The situation when there is
more then exactly one return statement in a function body is detected
(diagnostic message is generated for all the return statements except the
first one).

Qualified_Aggr
--------------
Non-qualified aggregates are detected. A non qualified aggregate is an
aggregate that is not an immediate component of some qualified expression. A
string literal is not considered as aggregate by this rule, but an array
aggregate of some string type is considered as a normal aggregate.

Recursion (under construction, GLOBAL)
---------
Recursion (cycles in the call graph) is detected. We detect declarations of
recursive subprograms but not calls to recursive subprograms.

Restrict_Name_Space
-------------------
Detect that some names are not used as defining identifiers. To activate this
rule, one have to provide a reference to a dictionary file as a rule
parameter(s), more then one dictionary file can be specificed. If no
dictionary file is set, nothing is detcted. Only defining identifiers are
detected. but not references. The check is not case-sensitive.

At the moment this rule is enabled by default, but without setting a
dictionary to check defining names with, it checks nothing

A dictionary file is a plain text file. The length of the lines in this file
is limited by 1024 characters. If the line is longer then 1024 characters, the
part of the line that folows 1024th character is not processed.

Each line can be either an empty line, a comment line or it may contain a list
of identifiers separated by space or HT characters. A comment is an Ada-stype
comment - it starts from '--' and ends till the end of a line. Identifiers
shold follow the Ada syntax for identifiers. A line containing identifie(s)
may end up with a comment.

Side_Effect_Functions (under construction, GLOBAL)
---------------------
Functions with side effect are detected.

We define a side effect as changing any data object that is not local for the
body of this function.

At the moment, we do NOT consider a side effect any input-output operations
(changing a state or a content of any file).

We do not consider protected functions for this rule (???)

There are the following sources of side effect:

1. Explicit (or direct) side-effect:

   - direct assignment to a non-local variable;

   - direct call to an entity that is known to change some data object that is
     not local for the body of this function (Note, that if F1 calls F2 and F2
     does have a side effect, this does not automatically mean that F1 also
     have a side effect, because it may be the case that F2 is declared in
     F1's body and it changes some data object that is global for F2, but
     local for F1);

2. Indirect side-effect:

   - Subprogram calls implicitly issued by:
       - computing initialization expressions from type declarations as a part
         of object elaboration or allocator evaluation;
       - computing implicit parameters of subprogram or entry calls or generic
         instantiations;

   - activation of a task that change some non-local data object (directly or
     indirectly);

   - elaboration code of a package that is a result of a package instantiation;

   - controlled objects;

3. Situations when we can suspect a side-effect, but the full static check is
   either impossible or too hard:

   - assignment to access variables or to the objects pointed by access
     variables;

   - call to a subprogram pointed by access-to-subprogram value

   - dispatching calls;

Simple_Loop_Exit_Names
----------------------
Expanded loop name in an exit statement is detected

Slices
------
Use of slices is detected

Spark_Attributes
----------------
The definition of the Spark language defines a subset  of Ada 95 attribute
designators that can be used in Spark programs. The use of any attribute that
is not from this subset is detected

Here is the Spark Ada 95 attribute subset in terms of the Asis.Attribute_Kinds
type values:
   An_Adjacent_Attribute
   An_Aft_Attribute
   A_Base_Attribute
   A_Ceiling_Attribute
   A_Component_Size_Attribute
   A_Compose_Attribute
   A_Copy_Sign_Attribute
   A_Delta_Attribute
   A_Denorm_Attribute
   A_Digits_Attribute
   An_Exponent_Attribute
   A_First_Attribute
   A_Floor_Attribute
   A_Fore_Attribute
   A_Fraction_Attribute
   A_Last_Attribute
   A_Leading_Part_Attribute
   A_Length_Attribute
   A_Machine_Attribute
   A_Machine_Emax_Attribute
   A_Machine_Emin_Attribute
   A_Machine_Mantissa_Attribute
   A_Machine_Overflows_Attribute
   A_Machine_Radix_Attribute
   A_Machine_Rounds_Attribute
   A_Max_Attribute
   A_Min_Attribute
   A_Model_Attribute
   A_Model_Emin_Attribute
   A_Model_Epsilon_Attribute
   A_Model_Mantissa_Attribute
   A_Model_Small_Attribute
   A_Modulus_Attribute
   A_Pos_Attribute
   A_Pred_Attribute
   A_Range_Attribute
   A_Remainder_Attribute
   A_Rounding_Attribute
   A_Safe_First_Attribute
   A_Safe_Last_Attribute
   A_Scaling_Attribute
   A_Signed_Zeros_Attribute
   A_Size_Attribute
   A_Small_Attribute
   A_Succ_Attribute
   A_Truncation_Attribute
   An_Unbiased_Rounding_Attribute
   A_Val_Attribute
   A_Valid_Attribute

Unconstr_Array_Return
---------------------
Functions returning unconstrained arrays are detected. Functions declarations,
function bodies (and body stubs) having no separate declarations and function
instantiations are detected. Function calls are not detected. Function
renamings are not detected.

Universal_Ranges
----------------
Discrete ranges that are a part of index constraint, constrained array
definition, or FOR-loop parameter specification, and that have both bounds of
the unuversal type integer type are detected. Ranges that have at least one
bound of a specific type, (suc as '1 .. N', where N is a variable or an
expression of non-universal type) are not detected.

Unused_Subpr (under construction, GLOBAL)
------------
Unused subprograms are detected.

Use_Pckg_Clauses
----------------
Use package clauses are detected. Use type clauses are not detected.

Volatile_Requires_Addr_Clause
-----------------------------
A volatile object that does not have an address clause applied to it is
detected.

At the moment we check the following. If the pragma Volatile is applied to a
data object or to the type of this data object, then the address clause should
be applied to this object.

We do not check this rule for the components of data objects. We do not
consider the array components that are volatile as a result of the pragma
Volatile_Components. We also do not consider objects that are volatile because
they are atomic as a result of pragmas Atomic or Atomic_Components.

Only variable declarations, but not constant declarations are detected.


4. Add the results of compiler checks to gnatcheck output
   ------------------------------------------------------

The GNAT compiler itself can perform a big number of various useful checks
that can be interesting in the context of the source code analysis,
certification and qualification. These compiler-performed checks result in
warnings generated by the compiler. There are three different kinds of checks:

- restriction checks, these checks can be configured by the GNAT pragma
  Restriction_Warnings (note, that pragma Restrictions causes an error message
  in case if a restriction violation is detected, and the corresponding source
  is treated as illegal, this prevents it analysis with an ASIS tool, whereas
  the pragma Restriction_Warnings in the same situations generates warnings,
  and the source is not treated as illegal because of detecting restriction
  violations).

- style checks, these checks can be configured by '-gnaty' option or by the
  GNAT pragma Style_Checks;

- general warnings, these checks can be configured by '-gnatw' option or by
  the GNAT pragma Warnings;

By default all the compiler checks are OFF, to activate and to configure them,
the 'restrictions', 'style_checks or 'warnings' rule option(s) should be used
with the corresponding parameter(s).

A parameter of 'restrictions' option should have exactly the same structure as
an argument of pragmas Restriction/Restriction_Warnings, it turns ON the check
for the corresponding restriction. For example,

$gnatcheck ... foo.adb -rules \
   +RRestrictions:No_Allocators,Max_Protected_Entries=>1

will collect and report warnings that would be generated when compiling
foo.adn with pragma Restrictions (No_Allocators, Max_Protected_Entries => 1)
placed into the configuration file

A parameter of 'style_checks' option should either be ALL_CHECKS, it sets ON
all the style check, or a string that is a valid string_literal argument of
the GNAT pragma Style_Checks (in other words - the string that is a valid
parameter of the GNAT '-gnaty' option). For example,

$gnatcheck ... foo.adb -rules +Style_Checks:kp

will collect and report warnings that would be generated when compiling
foo.adb with '-gnatykp' option or with placing pragma Style_Checks ("kp") into
the configuration file. This will check keywords ('k') and pragma names ('p')
casing.

A parameter of 'warnings' option should be a string that is a valid
static_string_expression argument of the GNAT pragma Warnings (in other words
- the string that is a valid parameter of the GNAT '-gnatw' option). For
example,

$gnatcheck ... foo.adb -rules +Warnings:g

will collect and report warnings that would be generated when compiling
foo.adb with '-gnatwg' option or with pragma Warnings ("g") placed in the
configuration file.

'warnings' and 'restrictions' gnatcheck options that have illegal structure or
illegal parameters are ignored.

Note, that by default all the compiler warnings are turned OFF in gnatcheck.
So if you would like to use a particular warning, you have to turn it ON
explicitly by the corresponding '-gnatw*' parameter of the gnatcheck
'warnings' option, or you can use '-gnata' to turn ON all the warnings. Using
'-gnatwn' will not help - it cancels '-gnatws' mode, but all the warnings
remain turned OFF.

Parameters of the gnatcheck 'restrictions', 'style_checks' and 'warnings' have
a cumulative effect - that is, they change the compiler warnings and style
check options according to the order these parameters are set for gnatcheck.
For example, the following option '+Rwarnings:ugA' first set ON warnings for
unused entities (-gnatwu) and unrecognized pragmas (-gnatwg), but then all the
warnings are set off (-gnatwA)

5. Output format
   -------------

The current gnatcheck version does not allow to redirect the output generated
by the tool and it has a very limited possibilities to control it.
gnatcheck sends all the diagnoses
about all the rule violations detected in the argument sources into Stdout
unless '-q' option is set. It also creates in the current
directory the text file named gnatcheck.out that contains the complete report
of the gnatcheck run: the list of Ada source files being checked, a list of
enabled and disabled rule checks, and a list of the diagnostic messages
ordered in three different ways and collected in three separate sections: in
compiler-like style, by rules and then by files, by files and then by rules.
'-s' option allows to get the short format of the report (no version
information, no lists of enabled and disabled riles, no section delimiters
etc.) '-sn' option, where n = 1, 2 or 3 allows to include in the gnatcheck
report file only explicitly specified sections
