8. Predefined Rules¶
The description of the rules currently implemented in gnatcheck is
given in this chapter.
The rule identifier is
used as a parameter of gnatcheck‘s +R
or -R
switches.
Be aware that most of these rules apply to specialized coding requirements developed by individual users and may well not make sense in other environments. In particular, there are many rules that conflict with one another. Proper usage of gnatcheck involves selecting the rules you wish to apply by looking at your independently developed coding standards and finding the corresponding gnatcheck rules.
If not otherwise specified, a rule does not do any check for the results of generic instantiations.
8.2. Feature Usage Rules¶
The rules in this section can be used to enforce specific usage patterns for a variety of language features.
8.2.1. Abstract_Type_Declarations
¶
Flag all declarations of abstract types. For an abstract private type, both the private and full type declarations are flagged.
This rule has no parameters.
8.2.2. Anonymous_Subtypes
¶
Flag all uses of anonymous subtypes (except cases when subtype indication is a part of a record component definition, and this subtype indication depends on a discriminant). A use of an anonymous subtype is any instance of a subtype indication with a constraint, other than one that occurs immediately within a subtype declaration. Any use of a range other than as a constraint used immediately within a subtype declaration is considered as an anonymous subtype.
The rule does not flag ranges in the component clauses from a record representation clause, because the language rules do not allow to use subtype names there.
An effect of this rule is that for
loops such as the following are
flagged (since 1..N
is formally a ‘range’):
for I in 1 .. N loop
...
end loop;
Declaring an explicit subtype solves the problem:
subtype S is Integer range 1..N;
...
for I in S loop
...
end loop;
This rule has no parameters.
8.2.4. Complex_Inlined_Subprograms
¶
Flag a subprogram (or generic subprogram, or instantiation of a subprogram) if pragma Inline is applied to it and at least one of the following conditions is met:
- it contains at least one complex declaration such as a subprogram body,
package, task, protected declaration, or a generic instantiation
(except instantiation of
Ada.Unchecked_Conversion
); - it contains at least one complex statement such as a loop, a case or an if statement;
- the number of statements exceeds a value specified by the N rule parameter;
Subprogram renamings are also considered.
This rule has the following (mandatory) parameter for the +R
option:
- N
- Positive integer specifying the maximum allowed total number of statements in the subprogram body.
8.2.5. Conditional_Expressions
¶
Flag use of conditional expression.
This rule has the following (optional) parameters for the +R
option:
- Except_Assertions
- Do not flag a conditional expression if it is a subcomponent of the following constructs:
argument of the following pragmas
Language-defined
Assert
GNAT-specific
Assert_And_Cut
Assume
Contract_Cases
Debug
Invariant
Loop_Invariant
Loop_Variant
Postcondition
Precondition
Predicate
Refined_Post
definition of the following aspects
Language-defined
Static_Predicate
Dynamic_Predicate
Pre
Pre'Class
Post
Post'Class
Type_Invariant
Type_Invariant'Class
GNAT-specific
Contract_Cases
Invariant
Invariant'Class
Predicate
Refined_Post
8.2.6. Controlled_Type_Declarations
¶
Flag all declarations of controlled types. A declaration of a private type
is flagged if its full declaration declares a controlled type. A declaration
of a derived type is flagged if its ancestor type is controlled. Subtype
declarations are not checked. A declaration of a type that itself is not a
descendant of a type declared in Ada.Finalization
but has a controlled
component is not checked.
This rule has no parameters.
8.2.7. Declarations_In_Blocks
¶
Flag all block statements containing local declarations. A declare
block with an empty declarative_part or with a declarative part
containing only pragmas and/or use
clauses is not flagged.
This rule has no parameters.
8.2.8. Deeply_Nested_Inlining
¶
Flag a subprogram (or generic subprogram) if pragma Inline has been applied to it, and it calls another subprogram to which pragma Inline applies, resulting in potential nested inlining, with a nesting depth exceeding the value specified by the N rule parameter.
This rule requires the global analysis of all the compilation units that are gnatcheck arguments; such analysis may affect the tool’s performance.
This rule has the following (mandatory) parameter for the +R
option:
- N
- Positive integer specifying the maximum level of nested calls to subprograms to which pragma Inline has been applied.
8.2.9. Default_Parameters
¶
Flag all default expressions in parameters specifications. All parameter specifications are checked: in subprograms (including formal, generic and protected subprograms) and in task and protected entries (including accept statements and entry bodies).
This rule has no parameters.
8.2.10. Discriminated_Records
¶
Flag all declarations of record types with discriminants. Only the declarations of record and record extension types are checked. Incomplete, formal, private, derived and private extension type declarations are not checked. Task and protected type declarations also are not checked.
This rule has no parameters.
8.2.11. Explicit_Full_Discrete_Ranges
¶
Flag each discrete range that has the form A'First .. A'Last
.
This rule has no parameters.
8.2.12. Fixed_Equality_Checks
¶
Flag all calls to the predefined equality operations for fixed-point types.
Both ‘=
‘ and ‘/=
‘ operations are checked.
User-defined equality operations are not flagged, nor are uses of operators
that are renamings of the predefined equality operations.
Also, the ‘=
‘ and ‘/=
‘ operations for floating-point types
are not flagged.
This rule has no parameters.
8.2.13. Float_Equality_Checks
¶
Flag all calls to the predefined equality operations for floating-point types.
Both ‘=
‘ and ‘/=
‘ operations are checked.
User-defined equality operations are not flagged, nor are uses of operators
that are renamings of the predefined equality operations.
Also, the ‘=
‘ and ‘/=
‘ operations for fixed-point types
are not flagged.
This rule has no parameters.
8.2.14. Function_Style_Procedures
¶
Flag each procedure that can be rewritten as a function. A procedure can be
converted into a function if it has exactly one parameter of mode out
and no parameters of mode in out
. Procedure declarations,
formal procedure declarations, and generic procedure declarations are always
checked. Procedure
bodies and body stubs are flagged only if they do not have corresponding
separate declarations. Procedure renamings and procedure instantiations are
not flagged.
If a procedure can be rewritten as a function, but its out
parameter is
of a limited type, it is not flagged.
Protected procedures are not flagged. Null procedures also are not flagged.
This rule has no parameters.
8.2.15. Generics_In_Subprograms
¶
Flag each declaration of a generic unit in a subprogram. Generic declarations in the bodies of generic subprograms are also flagged. A generic unit nested in another generic unit is not flagged. If a generic unit is declared in a local package that is declared in a subprogram body, the generic unit is flagged.
This rule has no parameters.
8.2.16. Implicit_IN_Mode_Parameters
¶
Flag each occurrence of a formal parameter with an implicit in
mode.
Note that access
parameters, although they technically behave
like in
parameters, are not flagged.
This rule has no parameters.
8.2.17. Improperly_Located_Instantiations
¶
Flag all generic instantiations in library-level package specs (including library generic packages) and in all subprogram bodies.
Instantiations in task and entry bodies are not flagged. Instantiations in the bodies of protected subprograms are flagged.
This rule has no parameters.
8.2.18. Library_Level_Subprograms
¶
Flag all library-level subprograms (including generic subprogram instantiations).
This rule has no parameters.
8.2.19. Membership_Tests
¶
Flag use of membership test expression.
This rule has the following (optional) parameters for the +R
option:
- Multi_Alternative_Only
- Flag only those membership test expressions that have more than one membership choice in the membership choice list.
- Except_Assertions
- Do not flag a membership test expression if it is a subcomponent of the following constructs:
argument of the following pragmas
Language-defined
Assert
GNAT-specific
Assert_And_Cut
Assume
Contract_Cases
Debug
Invariant
Loop_Invariant
Loop_Variant
Postcondition
Precondition
Predicate
Refined_Post
definition of the following aspects
Language-defined
Static_Predicate
Dynamic_Predicate
Pre
Pre'Class
Post
Post'Class
Type_Invariant
Type_Invariant'Class
GNAT-specific
Contract_Cases
Invariant
Invariant'Class
Predicate
Refined_Post
These two parameters are independent on each other.
8.2.20. Non_Qualified_Aggregates
¶
Flag each non-qualified aggregate. A non-qualified aggregate is an aggregate that is not the expression of a qualified expression. A string literal is not considered an aggregate, but an array aggregate of a string type is considered as a normal aggregate. Aggregates of anonymous array types are not flagged.
This rule has no parameters.
8.2.21. Numeric_Literals
¶
Flag each use of a numeric literal in an index expression, and in any circumstance except for the following:
- a literal occurring in the initialization expression for a constant declaration or a named number declaration, or
- a literal occurring in an aspect definition or in an aspect clause, or
- an integer literal that is less than or equal to a value specified by the N rule parameter.
- a literal occurring in a declaration in case the Statements_Only rule parameter is given
This rule may have the following parameters for the +R
option:
- N
- N is an integer literal used as the maximal value that is not flagged (i.e., integer literals not exceeding this value are allowed)
ALL
- All integer literals are flagged
Statements_Only
- Numeric literals are flagged only when used in statements
If no parameters are set, the maximum unflagged value is 1, and the check for literals is not limited by statements only.
The last specified check limit (or the fact that there is no limit at
all) is used when multiple +R
options appear.
The -R
option for this rule has no parameters.
It disables the rule and restores its default operation mode.
If the +R
option subsequently appears, will be 1, and the check will
not be limited by statements only.
8.2.22. Parameters_Out_Of_Order
¶
Flag each subprogram and entry declaration whose formal parameters are not ordered according to the following scheme:
in
andaccess
parameters first, thenin out
parameters, and thenout
parameters;- for
in
mode, parameters with default initialization expressions occur last
Only the first violation of the described order is flagged.
The following constructs are checked:
- subprogram declarations (including null procedures);
- generic subprogram declarations;
- formal subprogram declarations;
- entry declarations;
- subprogram bodies and subprogram body stubs that do not have separate specifications
Subprogram renamings are not checked.
This rule has no parameters.
8.2.23. Predicate_Testing
¶
Flag a subtype mark if it denotes a subtype defined with (static or dynamic) subtype predicate and is used as a membership choice in a membership test expression.
Flags ‘Valid attribute reference if the nominal subtype of the attribute prefix has (static or dynamic) subtype predicate.
This rule has the following (optional) parameters for the +R
option:
- Except_Assertions
- Do not flag a construct described above if it is a subcomponent of the following constructs:
argument of the following pragmas
Language-defined
Assert
GNAT-specific
Assert_And_Cut
Assume
Contract_Cases
Debug
Invariant
Loop_Invariant
Loop_Variant
Postcondition
Precondition
Predicate
Refined_Post
definition of the following aspects
Language-defined
Static_Predicate
Dynamic_Predicate
Pre
Pre'Class
Post
Post'Class
Type_Invariant
Type_Invariant'Class
GNAT-specific
Contract_Cases
Invariant
Invariant'Class
Predicate
Refined_Post
8.2.24. Quantified_Expressions
¶
Flag use of quantified expression.
This rule has the following (optional) parameters for the +R
option:
- Except_Assertions
- Do not flag a conditional expression if it is a subcomponent of the following constructs:
argument of the following pragmas
Language-defined
Assert
GNAT-specific
Assert_And_Cut
Assume
Contract_Cases
Debug
Invariant
Loop_Invariant
Loop_Variant
Postcondition
Precondition
Predicate
Refined_Post
definition of the following aspects
Language-defined
Static_Predicate
Dynamic_Predicate
Pre
Pre'Class
Post
Post'Class
Type_Invariant
Type_Invariant'Class
GNAT-specific
Contract_Cases
Invariant
Invariant'Class
Predicate
Refined_Post
8.2.25. Raising_Predefined_Exceptions
¶
Flag each raise
statement that raises a predefined exception
(i.e., one of the exceptions Constraint_Error
, Numeric_Error
,
Program_Error
, Storage_Error
, or Tasking_Error
).
This rule has no parameters.
8.2.26. Unassigned_OUT_Parameters
¶
Flag procedures’ out
parameters that are not assigned.
An out
parameter is flagged if the sequence of statements of
the procedure body (before the procedure body’s exception part, if any)
contains no assignment to the parameter.
An out
parameter is flagged in an exception handler in the exception
part of the procedure body, if the exception handler contains neither an
assignment to the parameter nor a raise statement.
Bodies of generic procedures are also considered.
The following are treated as assignments to an out
parameter:
- an assignment statement, with the parameter or some component as the target
- passing the parameter (or one of its components) as an
out
orin out
parameter, except for the case when it is passed to the call of an attribute subprogram.
This rule has no parameters.
Warning
This rule only detects a trivial case of an unassigned variable
and doesn’t provide a guarantee that there is no uninitialized access.
The rule does not check function parameters (starting from Ada 2012 functions
can have out
parameters). It is not a replacement for rigorous check for
uninitialized access provided by advanced static analysis tools.
8.2.27. Unconstrained_Array_Returns
¶
Flag each function returning an unconstrained array. Function declarations, function bodies (and body stubs) having no separate specifications, and generic function instantiations are flagged. Function calls and function renamings are not flagged.
Generic function declarations, and function declarations in generic packages, are not flagged. Instead, this rule flags the results of generic instantiations (that is, expanded specification and expanded body corresponding to an instantiation).
This rule has the following (optional) parameters for the +R
option:
- Except_String
- Do not flag functions that return the predefined
String
type or a type derived from it, directly or indirectly.
8.4. SPARK Ada Rules¶
The rules in this section can be used to enforce compliance with the Ada subset allowed by the SPARK tools.
8.4.1. Annotated_Comments
¶
Flags comments that are used as annotations or as special sentinels/markers. Such comments have the following structure
--<special_character> <comment_marker>
where
- <special_character>
- character (such as ‘#’, ‘$’, ‘|’ etc.) indicating that the comment is used for a specific purpose
- <comment_marker>
- a word identifying the annotation or special usage (word here is any sequence of characters except white space)
There may be any amount of white space (including none at all) between
<special_character>
and <comment_marker>
, but no white space
is permitted between '--'
and <special_character>
. (A
white space here is either a space character or horizontal tabulation)
<comment_marker>
must not contain any white space.
<comment_marker>
may be empty, in which case the rule
flags each comment that starts with --<special_character>
and
that does not contain any other character except white space
The rule has the following (mandatory) parameter for the +R
option:
- S
- String with the following interpretation: the first character is the special comment character, and the rest is the comment marker. S must not contain white space.
The -R
option erases all definitions of special comment annotations
specified by the previous +R options.
The rule is case-sensitive.
Example:
The rule
+RAnnotated_Comments:#hide
will flag the following comment lines
--#hide
--# hide
--# hide
I := I + 1; --# hide
But the line
-- # hide
will not be flagged, because of the space between ‘–’ and ‘#’.
The line
--#Hide
will not be flagged, because the string parameter is case sensitive.
8.4.2. Boolean_Relational_Operators
¶
Flag each call to a predefined relational operator (‘<’, ‘>’, ‘<=’, ‘>=’, ‘=’ and ‘/=’) for the predefined Boolean type. (This rule is useful in enforcing the SPARK language restrictions.)
Calls to predefined relational operators of any type derived from
Standard.Boolean
are not detected. Calls to user-defined functions
with these designators, and uses of operators that are renamings
of the predefined relational operators for Standard.Boolean
,
are likewise not detected.
This rule has no parameters.
8.4.3. Expanded_Loop_Exit_Names
¶
Flag all expanded loop names in exit
statements.
This rule has no parameters.
8.4.4. Non_SPARK_Attributes
¶
The SPARK language defines the following subset of Ada 95 attribute designators as those that can be used in SPARK programs. The use of any other attribute is flagged.
'Adjacent
'Aft
'Base
'Ceiling
'Component_Size
'Compose
'Copy_Sign
'Delta
'Denorm
'Digits
'Exponent
'First
'Floor
'Fore
'Fraction
'Last
'Leading_Part
'Length
'Machine
'Machine_Emax
'Machine_Emin
'Machine_Mantissa
'Machine_Overflows
'Machine_Radix
'Machine_Rounds
'Max
'Min
'Model
'Model_Emin
'Model_Epsilon
'Model_Mantissa
'Model_Small
'Modulus
'Pos
'Pred
'Range
'Remainder
'Rounding
'Safe_First
'Safe_Last
'Scaling
'Signed_Zeros
'Size
'Small
'Succ
'Truncation
'Unbiased_Rounding
'Val
'Valid
This rule has no parameters.
8.4.5. Non_Tagged_Derived_Types
¶
Flag all derived type declarations that do not have a record extension part.
This rule has no parameters.
8.4.6. Outer_Loop_Exits
¶
Flag each exit
statement containing a loop name that is not the name
of the immediately enclosing loop
statement.
This rule has no parameters.
8.4.7. Overloaded_Operators
¶
Flag each function declaration that overloads an operator symbol. A function body is checked only if the body does not have a separate spec. Formal functions are also checked. For a renaming declaration, only renaming-as-declaration is checked
This rule has no parameters.
8.4.9. Universal_Ranges
¶
Flag discrete ranges that are a part of an index constraint, constrained
array definition, or for
-loop parameter specification, and whose bounds
are both of type universal_integer. Ranges that have at least one
bound of a specific type (such as 1 .. N
, where N
is a variable
or an expression of non-universal type) are not flagged.
This rule has no parameters.