The rules in this section may be used to enforce various feature usages
consistent with good software engineering, for example
as described in Ada 95 Quality and Style.
3.1.5. Programming Practice
The rules in this subsection may be used to enforce feature usages that
relate to program maintainability.
3.1.5.1. Access_To_Local_Objects
Flag any 'Access
attribute reference if its prefix denotes an identifier
defined by a local object declaration or a subcomponent thereof. An object
declaration is considered as local if it is located anywhere except library-level
packages or bodies of library-level packages (including packages nested
in those). Here both package declarations and package instantiations are
considered as packages. If the attribute prefix is a dereference or
a subcomponent thereof, the attribute reference is not flagged.
This rule has no parameters.
Example
package body Pack
procedure Proc is
type Int_A is access all Integer;
Var1 : aliased Integer;
Var2 : Int_A := Var1'Access; -- FLAG
3.1.5.2. Actual_Parameters
Flag situations when a specific actual parameter is passed for a specific formal
parameter in the call to a specific subprogram. Subprograms, formal parameters and
actual parameters to check are specified by the rule parameters.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- Forbidden: list[string]
A list of strings formatted as following: subprogram:formal:actual
where
subprogram
should be a full expanded Ada name of a subprogram, formal
should be an identifier, it is treated as the name of a formal parameter of
the subprogram
and actual
should be a full expanded Ada name of a
function or a data object declared by object declaration, number declaration,
parameter specification, generic object declaration or object renaming
declaration.
Note
In LKQL rule options files, the Forbidden
parameter should be a list
of three-elements tuples. Mapping subprogram:formal:actual
to
(<subprogram>, <formal>, <actual>)
. For example:
val rules = @{
Actual_Parameters: {Forbidden: [("P.SubP", "Param", "Value")]}
}
For all the calls to subprogram
the rule checks if the called subprogram
has a formal parameter named as formal
, and if it does, it checks
if the actual for this parameter is either a call to a function denoted by
actual
or a reference to the data object denoted by actual
or one of the above in parenthesis, or a type conversion or a qualified
expression applied to one of the above. References to object components or
explicit dereferences are not checked.
Be aware that the rule does not follow renamings. The rule checks only calls that
use the subprogram
part of the rule parameter as a called name, and if this
name is declared by a subprogram renaming, the rule does not pay attention to
the calls that use subprogram name being renamed. When looking for the parameter
to check, the rule assumes that a formal parameter denoted by the formal
part of the rule parameter is declared as a part of the declaration of
subprogram
. The same for the actual
part of the rule parameter - only
those actual parameters that use actual
as the name of a called function
are considered. This is a user responsibility to provide as the rule
parameters all needed combinations of subprogram name and formal parameter name for
the subprogram of interest in case if renamings are used for the subprogram,
and all possible aliases if renaming is used for a function of interest if
its calls may be used as actuals.
Note also, that the rule does not make any overload resolution, so it will consider
all possible subprograms denoted by the subprogram
part of the rule parameter,
and all possible function denoted by the actual
part.
Example
-- Suppose the rule parameter is P.Proc:Par2:Q.Var
package P is
procedure Proc (B : Boolean; I : Integer);
procedure Proc (Par1 : Character; Par2 : Integer);
end P;
package Q is
Var : Integer;
end Q;
with P; use P;
with Q; use Q;
procedure Main is
begin
Proc (True, Var); -- NO FLAG
Proc (1, Var); -- FLAG
3.1.5.4. Ada_2022_In_Ghost_Code
Flag usages of Ada 2022 specific constructions used outside of Ghost code and
Assertion code.
This check is meant to allow users to use the new standard in code that is not
shipped with the final executable version of their application.
You can check this page
https://learn.adacore.com/courses/whats-new-in-ada-2022/index.html for a quick
overview of the new features of Ada 2022.
This rule has no parameters.
Example
procedure Test_Ghost_Code is
A : String := "hello";
B : String := A'Image; -- FLAG
procedure Foo
with Pre => A'Image = "hello"; -- NOFLAG
B : String := A'Image with Ghost; -- NOFLAG
function Bar return String is (A'Image) with Ghost; -- NOFLAG
package P with Ghost is
B : String := A'Image; -- NOFLAG
end P;
generic
package Gen_Pkg is
B : String := A'Image; -- FLAG (via instantiation line 23)
end Gen_Pkg;
package Inst is new Gen_Pkg;
begin
null;
end Test_Ghost_Code;
3.1.5.5. Address_Attribute_For_Non_Volatile_Objects
Flag any ‘Address attribute reference if its prefix denotes a data
object defined by a variable object declaration and this object is not
marked as Volatile. An entity is considered as being marked volatile
if it has an aspect Volatile, Atomic or Shared declared for it.
This rule has no parameters.
Example
Var1 : Integer with Volatile;
Var2 : Integer;
X : Integer with Address => Var1'Address;
Y : Integer with Address => Var2'Address; -- FLAG
3.1.5.6. Address_Specifications_For_Initialized_Objects
Flag address clauses and address aspect definitions if they are applied
to object declarations with explicit initializations.
This rule has no parameters.
Example
I : Integer := 0;
Var0 : Integer with Address => I'Address;
Var1 : Integer := 10;
for Var1'Address use Var0'Address; -- FLAG
3.1.5.7. Address_Specifications_For_Local_Objects
Flag address clauses and address aspect definitions if they are applied
to data objects declared in local subprogram bodies. Data objects
declared in library subprogram bodies are not flagged.
This rule has no parameters.
Example
package Pack is
Var : Integer;
procedure Proc (I : in out Integer);
end Pack;
package body Pack is
procedure Proc (I : in out Integer) is
Tmp : Integer with Address => Pack.Var'Address; -- FLAG
begin
I := Tmp;
end Proc;
end Pack;
3.1.5.8. Anonymous_Arrays
Flag all anonymous array type definitions (by Ada semantics these can only
occur in object declarations).
This rule has no parameters.
Example
type Arr is array (1 .. 10) of Integer;
Var1 : Arr;
Var2 : array (1 .. 10) of Integer; -- FLAG
3.1.5.9. Binary_Case_Statements
Flag a case statement if this statement has only two alternatives, one
containing exactly one choice, the other containing exactly one choice
or the others
choice.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- Except_Enums: bool
If true
, do not flag case statements whose selecting expression is of an
enumeration type.
Example
case Var is -- FLAG
when 1 =>
Var := Var + 1;
when others =>
null;
end case;
3.1.5.10. Boolean_Negations
Flag any infix call to the predefined NOT
operator for the predefined
Boolean type if its argument is an infix call to a predefined relation
operator or another call to the predefined NOT
operator. Such expressions
can be simplified by excluding the outer call to the predefined NOT
operator. Calls to NOT
operators for the types derived from
Standard.Boolean are not flagged.
This rule has no parameters.
Example
Is_Data_Available := not (Buffer_Length = 0); -- FLAG
3.1.5.11. Calls_In_Exception_Handlers
Flag an exception handler if its sequence of statements contains a call to one of
the subprograms specified as a rule parameter.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- Subprograms: list[string]
A list of full expanded Ada name of subprograms.
Note that if a rule parameter does not denote the name of an existing
subprogram, the parameter itself is (silently) ignored and does not have any
effect except for turning the rule ON.
Be aware that the rule does not follow renamings. So if a subprogram name specified
as a rule parameter denotes the name declared by subprogram renaming, the
rule will flag only exception handlers that calls this subprogram using this
name and does not respect and will pay no attention to the calls that use
original subprogram name, and the other way around. This is a user responsibility
to provide as the rule parameters all needed subprogram names the subprogram
of interest in case if renamings are used for this subprogram.
Note also, that the rule does not make any overload resolution, so if a rule
parameter refers to more than one overloaded subprograms, the rule will treat
calls to all these subprograms as the calls to the same subprogram.
Example
-- Suppose the rule parameter is P.Unsafe
package P is
procedure Safe;
procedure Unsafe;
end P;
with P; use P;
procedure Proc is
begin
...
exception
when Constraint_Error => -- NO FLAG
Safe;
when others => -- FLAG
Unsafe;
end Proc;
3.1.5.12. Calls_Outside_Elaboration
Flag subprogram calls outside library package elaboration code. Only calls to
the subprograms specified as a rule parameter are considered, renamings are
not followed.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- Forbidden: list[string]
A list of full expanded Ada name of subprograms.
Note that if a rule parameter does not denote the name of an existing
subprogram, the parameter itself is (silently) ignored and does not have any
effect except for turning the rule ON.
Note also, that the rule does not make any overload resolution, so if a rule
parameter refers to more than one overloaded subprograms, the rule will treat
calls to all these subprograms as the calls to the same subprogram.
Example
-- Suppose the rule is activated as +RCalls_Outside_Elaboration:P.Fun;
package P is
I : Integer := Fun (1); -- NO FLAG
J : Integer;
procedure Proc (I : in out Integer);
end P;
package body P is
procedure Proc (I : in out Integer) is
begin
I := Another_Fun (Fun (1)); -- FLAG
end Proc;
begin
J := Fun (I); -- NO FLAG
3.1.5.13. Concurrent_Interfaces
Flag synchronized, task, and protected interfaces.
This rule has no parameters.
Example
type Queue is limited interface; -- NO FLAG
type Synchronized_Queue is synchronized interface and Queue; -- FLAG
type Synchronized_Task is task interface; -- FLAG
type Synchronized_Protected is protected interface; -- FLAG
3.1.5.14. Constant_Overlays
Flag an overlay definition that has a form of an attribute definition
clause for Overlaying'Address use Overlaid'Address;
or a form of aspect definition
Address => Overlaid'Address
, and Overlaid
is a data object defined by a constant
declaration or a formal or generic formal parameter of mode IN
if
at least one of the following is true:
This rule has no parameters.
Example
C : constant Integer := 1;
V : Integer;
for V'Address use C'Address; -- FLAG
3.1.5.15. Default_Values_For_Record_Components
Flag a record component declaration if it contains a default expression.
Do not flag record component declarations in protected definitions.
Do not flag discriminant specifications.
This rule has no parameters.
Example
type Rec (D : Natural := 0) is record
I : Integer := 0; -- FLAG
B : Boolean;
case D is
when 0 =>
C : Character := 'A'; -- FLAG
when others =>
F : Float;
end case;
end record;
3.1.5.16. Direct_Equalities
Flag infix calls to the predefined =
and /=
operators when one of the
operands is a name of a data object provided as a rule parameter.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- Actuals: list[string]
A list of full expanded Ada name of a data objects declared by object
declaration, number declaration, parameter specification, generic object
declaration or object renaming declaration. Any other parameter does not
have any effect except of turning the rule ON.
Be aware that the rule does not follow renamings. It checks if an operand of
an (un)equality operator is exactly the name provided as rule parameter
(the short name is checked in case of expanded name given as (un)equality
operator), and that this name is given on its own, but not as a component
of some other expression or as a call parameter.
Example
-- suppose the rule parameter is P.Var
package P is
Var : Integer;
end P;
with P; use P;
procedure Proc (I : in out Integer) is
begin
if Var = I then -- FLAG
I := 0;
end if;
end Proc;
3.1.5.17. Deriving_From_Predefined_Type
Flag derived type declaration if the ultimate ancestor type is a
predefined Ada type. Do not flag record extensions and private
extensions. The rule is checked inside expanded generics.
This rule has no parameters.
Example
package Foo is
type T is private;
type My_String is new String; -- FLAG
private
type T is new Integer; -- FLAG
end Foo;
3.1.5.18. Duplicate_Branches
Flag a sequence of statements that is a component of an if
statement
or of a case
statement alternative, if the same if
or case
statement contains another sequence of statements as its component
(or a component of its case
statement alternative) that is
syntactically equivalent to the sequence of statements in question.
The check for syntactical equivalence of operands ignores line breaks,
white spaces and comments.
Small sequences of statements are not flagged by this rule. The rule has
two optional parameters that allow to specify the maximal size of statement
sequences that are not flagged:
- min_stmt: int
An integer literal. All statement sequences that contain more than min_stmt
statements (Stmt as defined in Libadalang) as subcomponents are flagged;
- min_size: int
An integer literal. All statement sequences that contain more than min_size
lexical elements (SingleTokNode in Libadalang terms) are flagged.
You have to use the param_name=value
formatting to pass arguments through
the +R
options. Example: +RDuplicate_Branches:min_stmt=20,min_size=42
.
If at least one of the two thresholds specified by the rule parameters is
exceeded, a statement sequence is flagged. The following defaults are used:
min_stmt=4,min_size=14
.
Example
if X > 0 then
declare -- FLAG: code duplicated at line 11
A : Integer := X;
B : Integer := A + 1;
C : Integer := B + 1;
D : Integer := C + 1;
begin
return D;
end;
else
declare
A : Integer := X;
B : Integer := A + 1;
C : Integer := B + 1;
D : Integer := C + 1;
begin
return D;
end;
end if;
3.1.5.19. Enumeration_Ranges_In_CASE_Statements
Flag each use of a range of enumeration literals as a choice in a
case
statement.
All forms for specifying a range (explicit ranges
such as A .. B
, subtype marks and 'Range
attributes) are flagged.
An enumeration range is
flagged even if contains exactly one enumeration value or no values at all. A
type derived from an enumeration type is considered as an enumeration type.
This rule helps prevent maintenance problems arising from adding an
enumeration value to a type and having it implicitly handled by an existing
case
statement with an enumeration range that includes the new literal.
This rule has no parameters.
Example
procedure Bar (I : in out Integer) is
type Enum is (A, B, C, D, E);
type Arr is array (A .. C) of Integer;
function F (J : Integer) return Enum is separate;
begin
case F (I) is
when Arr'Range => -- FLAG
I := I + 1;
when D .. E => -- FLAG
null;
end case;
end Bar;
3.1.5.20. Enumeration_Representation_Clauses
Flag enumeration representation clauses.
This rule has no parameters.
Example
type Enum1 is (A1, B1, C1);
for Enum1 use (A1 => 1, B1 => 11, C1 => 111); -- FLAG
3.1.5.21. Exception_Propagation_From_Callbacks
Flag an 'Address
or 'Access
attribute if:
this attribute is a reference to a subprogram;
this subprogram may propagate an exception;
this attribute is an actual parameter of a subprogram call, and both the
subprogram called and the corresponding formal parameter are specified by a
rule parameter.
A subprogram is considered as not propagating an exception if:
its body has an exception handler with others
exception choice;
no exception handler in the body contains a raise statement nor a call to
Ada.Exception.Raise_Exception
or Ada.Exception.Reraise_Occurrence
.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- Callbacks: list[string]
A list of strings which should have the following structure
subprogram_name.parameter
. subprogram_name
should be a full expanded
Ada name of a subprogram. parameter
should be a simple name of a
parameter of a subprogram defined by the subprogram_name
part of the
rule parameter. For such a rule parameter for calls to all the subprograms
named as subprogram_name
the rule checks if a reference to a subprogram
that may propagate an exception is passed as an actual for parameter named
parameter
.
Note
In LKQL rule options files, the Callbacks
parameter should be a list
of two-elements tuples. Mapping subprogram_name.parameter
to
(<subprogram_name>, <parameter>)
. For example:
val rules = @{
Exception_Propagation_From_Callbacks: {Forbidden: [("P.SubP", "Param")]}
}
Note that if a rule parameter does not denote the name of an existing
subprogram or if its parameter
part does not correspond to any formal
parameter of any subprogram defined by subprogram_name
part, the
parameter itself is (silently) ignored and does not have any effect except for
turning the rule ON.
Be aware that subprogram_name
is the name used in subprogram calls to look
for callback parameters that may raise an exception, and parameter
is the
name of a formal parameter that is defined in the declaration that defines
subprogram_name
. This is a user responsibility to provide as the rule
parameters all needed combinations of subprogram name and parameter name for
the subprogram of interest in case if renamings are used for this subprogram.
Note also, that the rule does not make any overload resolution, so calls to
all the subprograms corresponding to subprogram_name
are checked.
Note
Note that you can use both fully qualified names to
instantiated or non-instantiated generic subprograms, depending on the
granularity you wish for. However you cannot use a mix of the two, so
the names need to be either fully instantiated or fully uninstantiated.
Example
-- Suppose the rule parameter is P.Take_CB.Param1
package P is
procedure Good_CB; -- does not propagate an exception
procedure Bad_CB; -- may propagate an exception
procedure Take_CB
(I : Integer;
Param1 : access procedure;
Param2 : access procedure);
end P;
with P; use P;
procedure Proc is
begin
Take_CB (1, Bad_CB'Access, Good_CB'Access); -- FLAG
Take_CB (1, Good_CB'Access, Bad_CB'Access); -- NO FLAG
end Proc;
3.1.5.22. Exception_Propagation_From_Export
Flag a subprogram body if aspect or pragma Export
or Convention
is
applied to this subprogram and this subprogram may propagate an exception.
A subprogram is considered as not propagating an exception if:
its body has an exception handler with others
exception choice;
no exception handler in the body contains a raise statement nor a call to
Ada.Exception.Raise_Exception
or Ada.Exception.Reraise_Occurrence
.
This rule has no parameters.
Example
package P is
procedure Proc (I : in out Integer) with Export;
end P;
package body P is
procedure Proc (I : in out Integer) is -- FLAG
begin
I := I + 10;
end Proc;
end P;
3.1.5.23. Exception_Propagation_From_Tasks
Flag a task body if it does not contain and exception handler with others
exception choice or if it contains an exception handler with a raise statement or
a call to Ada.Exception.Raise_Exception
or
Ada.Exception.Reraise_Occurrence
.
This rule has no parameters.
Example
task T;
task body T is -- FLAG
begin
...
exception
when Constraint_Error => null;
end T;
3.1.5.24. Exceptions_As_Control_Flow
Flag each place where an exception is explicitly raised and handled in the
same subprogram body. A raise
statement in an exception handler,
package body, task body or entry body is not flagged.
The rule has no parameters.
Example
procedure Bar (I : in out Integer) is
begin
if I = Integer'Last then
raise Constraint_Error; -- FLAG
else
I := I - 1;
end if;
exception
when Constraint_Error =>
I := Integer'First;
end Bar;
3.1.5.25. Exits_From_Conditional_Loops
Flag any exit statement if it transfers the control out of a for
loop
or a while
loop. This includes cases when the exit
statement
applies to a for
or while
loop, and cases when it is enclosed
in some for
or while
loop, but transfers the control from some
outer (unconditional) loop
statement.
The rule has no parameters.
Example
function Bar (S : String) return Natural is
Result : Natural := 0;
begin
for J in S'Range loop
exit when S (J) = '@'; -- FLAG
Result := Result + J;
end loop;
return 0;
end Bar;
3.1.5.26. EXIT_Statements_With_No_Loop_Name
Flag each exit
statement that does not specify the name of the loop
being exited.
This rule has the following (optional) parameter for the +R
option and
for LKQL rule options files:
- Nested_Only: bool
If true
, flag only those exit statements with no loop name that exit from
nested loops.
Example
procedure Bar (I, J : in out Integer) is
begin
loop
exit when I < J; -- FLAG
I := I - 1;
J := J + 1;
end loop;
end Bar;
3.1.5.27. Final_Package
Check that package declarations annotated as final don’t have child
packages
Note
We don’t do a transitive check, so grandchild packages won’t
be flagged. We consider this is not necessary, because the child
package will be flagged anyway.
Here is an example:
package Pkg with Annotate => (GNATcheck, Final) is
end Pkg;
package Pkg.Child is -- FLAG
end Pkg.Child;
package Pkg.Child.Grandchild is -- NOFLAG
end Pkg.Child.Grandchild;
3.1.5.28. Global_Variables
Flag any variable declaration that appears immediately within the
specification of a library package or library generic package. Variable
declarations in nested packages and inside package instantiations are
not flagged.
This rule has the following (optional) parameter for the +R
option and
for LKQL rule options files:
- Only_Public: bool
If true
, do not flag variable declarations in private library (generic)
packages and in package private parts.
Example
package Foo is
Var1 : Integer; -- FLAG
procedure Proc;
private
Var2 : Boolean; -- FLAG
end Foo;
3.1.5.29. GOTO_Statements
Flag each occurrence of a goto
statement.
This rule has the following optional parameter for the +R
option and for
LKQL rule options files:
- Only_Unconditional: bool
If true
, Only flag unconditional goto statements, that is, goto statements
that are not directly enclosed in an if or a case statement.
Example
for K in 1 .. 10 loop
if K = 6 then
goto Quit; -- FLAG only if Only_Unconditional is false
end if;
null;
end loop;
goto Next; -- FLAG in any case
<<Quit>>
<<Next>>
null;
return;
3.1.5.30. Integer_Types_As_Enum
Flag each integer type declaration (including types derived from
integer types) if this integer type may benefit from
being replaced by an enumeration type. An integer type is considered
as being potentially replaceable by an enumeration type if all the
following conditions are true:
there is no infix calls to any arithmetic or bitwise operator for objects
of this type;
this type is not referenced in an actual parameter of a generics
instantiation;
there is no type conversion from or to this type;
no type is derived from this type;
no subtype is declared for this type.
This rule has no parameters.
Example
procedure Proc is
type Enum is range 1 .. 3; -- FLAG
type Int is range 1 .. 3; -- NO FLAG
X : Enum := 1;
Y : Int := 1;
begin
X := 2;
Y := Y + 1;
end Proc;
3.1.5.31. Improper_Returns
Flag each explicit return
statement in procedures, and
multiple return
statements in functions.
Diagnostic messages are generated for all return
statements
in a procedure (thus each procedure must be written so that it
returns implicitly at the end of its statement part),
and for all return
statements in a function after the first one.
This rule supports the stylistic convention that each subprogram
should have no more than one point of normal return.
This rule has no parameters.
Example
procedure Proc (I : in out Integer) is
begin
if I = 0 then
return; -- FLAG
end if;
I := I * (I + 1);
end Proc;
function Factorial (I : Natural) return Positive is
begin
if I = 0 then
return 1;
else
return I * Factorial (I - 1); -- FLAG
end if;
exception
when Constraint_Error =>
return Natural'Last; -- FLAG
end Factorial;
3.1.5.32. Local_Instantiations
Non library-level generic instantiations are flagged.
The rule has an optional parameter(s) for the +R
option and for LKQL rule
options files:
- Packages: list[string]
A list of fully expanded Ada names of generic units to flag local instantiations
of.
If the rule is activated without parameters, all local instantiations
are flagged, otherwise only instantiations of the generic units which names
are listed as rule parameters are flagged. Note that a rule parameter should
be a generic unit name but not the name defined by generic renaming declaration.
Note also, that if a rule parameter does not denote an existing generic unit
or if it denotes a name defined by generic renaming declaration, the parameter
itself is (silently) ignored and does not have any effect, but the presence of at
least one of such a parameter already means that the rule will not flag any
instantiation if the full expanded Ada name of the instantiated generic unit is
listed as a rule parameter.
Example
generic
package Pack_G is
I : Integer;
end Pack_G;
with Pack_G;
package Pack_I is new Pack_G; -- NO FLAG
with Pack_G;
procedure Proc is
package Inst is new Pack_G; -- FLAG
begin
...
3.1.5.33. Local_USE_Clauses
Use clauses that are not parts of compilation unit context clause are
flagged.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- Except_USE_TYPE_Clauses: bool
If true
, do not flag local use type clauses.
Example
with Pack1;
with Pack2;
procedure Proc is
use Pack1; -- FLAG
procedure Inner is
use type Pack2.T; -- FLAG (if Except_USE_TYPE_Clauses is not set)
...
3.1.5.34. Maximum_Lines
Flags the file containing the source text of a compilation unit if this
file contains more than N lines where N is a rule parameter
This rule has the following (mandatory) parameter for the +R
option and
for LKQL rule options files:
- N: int
Positive integer specifying the maximum allowed number of lines in
the compilation unit source text.
3.1.5.35. Maximum_OUT_Parameters
Flag any subprogram declaration, subprogram body declaration, expression
function declaration, null procedure declaration, subprogram
body stub or generic subprogram declaration if the corresponding
subprogram has more than N formal parameters of mode out
or
in out
, where N is a parameter of the rule.
A subprogram body, an expression function, a null procedure or
a subprogram body stub is flagged only if there is
no separate declaration for this subprogram. Subprogram renaming
declarations and subprogram instantiations, as well as declarations
inside expanded generic instantiations are never flagged.
This rule has the following (mandatory) parameter for the +R
option and
for LKQL rule options files:
- N: int
Positive integer specifying the maximum allowed total number of
subprogram formal parameters of modes out
and in out
.
Example
procedure Proc_1 (I : in out Integer); -- NO FLAG
procedure Proc_2 (I, J : in out Integer); -- NO FLAG
procedure Proc_3 (I, J, K : in out Integer); -- NO FLAG
procedure Proc_4 (I, J, K, L : in out Integer); -- FLAG (if rule parameter is 3)
3.1.5.36. Maximum_Parameters
Flag any subprogram declaration, subprogram body declaration, expression
function declaration, null procedure declaration, subprogram
body stub or generic subprogram declaration if the corresponding
subprogram has more than N formal parameters, where N is a
parameter of the rule.
A subprogram body, an expression function, a null procedure or
a subprogram body stub is flagged only if there is
no separate declaration for this subprogram. Subprogram renaming
declarations and subprogram instantiations, as well as declarations
inside expanded generic instantiations are never flagged.
This rule has the following (mandatory) parameter for the +R
option and
for LKQL rule options files:
- N: int
Positive integer specifying the maximum allowed total number of
subprogram formal parameters.
Example
package Foo is
procedure Proc_1 (I : in out Integer);
procedure Proc_2 (I, J : in out Integer);
procedure Proc_3 (I, J, K : in out Integer);
procedure Proc_4 (I, J, K, L : in out Integer); -- FLAG (if rule parameter is 3)
function Fun_4 -- FLAG (if rule parameter is 3)
(I : Integer;
J : Integer;
K : Integer;
L : Integer) return Integer is (I + J * K - L);
end Foo;
3.1.5.37. Misplaced_Representation_Items
Flag a representation item if there is any Ada construct except
another representation item for the same entity between this clause
and the declaration of the entity it applies to. A representation item
in the context of this rule is either a representation clause or one of
the following representation pragmas:
Atomic J.15.8(9/3)
Atomic_Components J.15.8(9/3)
Independent J.15.8(9/3)
Independent_Components J.15.8(9/3)
Pack J.15.3(1/3)
Unchecked_Union J.15.6(1/3)
Volatile J.15.8(9/3)
Volatile_Components J.15.8(9/3)
This rule has no parameters.
Example
type Int1 is range 0 .. 1024;
type Int2 is range 0 .. 1024;
for Int2'Size use 16; -- NO FLAG
for Int1'Size use 16; -- FLAG
3.1.5.38. Nested_Paths
Flag the beginning of a sequence of statements that is immediately enclosed
by an IF
statement if this sequence of statement can be moved outside
the enclosing IF
statement. The beginning of a sequence of statements is
flagged if:
The enclosing IF
statement contains IF
and ELSE
paths and
no ELSIF
path;
This sequence of statements does not end with a breaking statement but
the sequence of statement in another path does end with a breaking statement.
A breaking statement is either a raise statement, or a return statement,
or an unconditional exit statement, or a goto statement or a block
statement without an exception handler with the enclosed sequence of
statements that ends with some breaking statement.
This rule has no parameters.
Example
loop
if I > K then
K := K + I; -- FLAG
I := I + 1;
else
L := 10;
exit;
end if;
end loop;
3.1.5.39. Nested_Subprograms
Flag any subprogram declaration, subprogram body declaration, subprogram
instantiation, expression function declaration or subprogram body stub
that is not a completion of another subprogram declaration and that is
declared within subprogram body (including bodies of generic
subprograms), task body or entry body directly or indirectly (that is -
inside a local nested package). Protected subprograms are not flagged.
Null procedure declarations are not flagged. Procedure declarations
completed by null procedure declarations are not flagged.
This rule has no parameters.
Example
procedure Bar (I, J : in out Integer) is
procedure Foo (K : Integer) is null;
procedure Proc1; -- FLAG
procedure Proc2 is separate; -- FLAG
procedure Proc1 is
begin
I := I + J;
end Proc1;
begin
3.1.5.40. No_Closing_Names
Flag any program unit that is longer than N lines where N is a rule parameter
and does not repeat its name after the trailing END
keyword.
This rule has the following (mandatory) parameter for the +R
option and
for LKQL rule options files:
- N: int
Positive integer specifying the maximal allowed number of lines in the
program unit that allows not to repeat the unit name at the end.
Example
procedure Proc (I : in out Integer) is -- FLAG is rule parameter is 3 or less
begin
I := I + 1;
end;
3.1.5.41. No_Others_In_Exception_Handlers
Flag handled sequences of statements that do not contain exception
handler with others
, depending on the rule parameter(s)
specified.
This rule has three parameters for the +R
option and for LKQL rule
options files:
- Subprogram: bool
If true
, flag a subprogram body if the handled sequence of statements
of this body does not contain an exception handler with others
choice.
This includes the case when the body does not contain any exception handler
at all. The diagnostic message points to the beginning of the subprogram body.
- Task: bool
If true
, flag a task body if the handled sequence of statements of this
body does not contain an exception handler with others
choice. This
includes the case when the body does not contain any exception handler at all.
The diagnostic message points to the beginning of the task body.
- All_Handlers: bool
If true
, flag a handled sequence of statements if it does contain at least
one exception handler, but it does not contain an exception handler with
others
choice. If a handled sequence of statements does not have any
exception handler, nothing is flagged for it. The diagnostic message points
to the EXCEPTION
keyword in the handled sequence of statements.
At least one parameter should be specified for the rule. If
more than one parameter is specified, each of the specified
parameters has its effect.
Example
procedure Other (I, J : in out Integer) is
begin
begin
I := I + 1;
exception -- FLAG (if All_Handlers parameter is set)
when Constraint_Error => null;
end;
exception -- NO FLAG
when Constraint_Error =>
I := Integer'Last;
when others =>
I := J;
raise;
end Other;
3.1.5.42. Non_Component_In_Barriers
Flag a barrier condition expression in an entry body declaration
if this expression contains a reference to a data object that is
not a (sub)component of the enclosing record the entry belongs to.
This rule has no parameters.
Example
protected Obj is
entry E1;
entry E2;
private
Value : Integer;
Is_Set : Boolean := False;
end Obj;
Global_Bool : Boolean := False;
protected body Obj is
entry E1
when Is_Set and then Value > 0 is -- NO FLAG
begin
Value := Value - 1;
Is_Set := False;
end E1;
entry E2
when Global_Bool is -- FLAG
begin
Is_Set := True;
end E2;
end Obj;
3.1.5.43. Non_Constant_Overlays
Flag an overlay definition that has a form of an attribute definition
clause for Overlaying'Address use Overlaid'Address;
or a form of
aspect definition Address => Overlaid'Address
, and Overlaid
is a data object defined by a variable declaration , a formal parameter
of mode IN OUT
or OUT
or a generic formal parameter of mode IN OUT
if at least one of the following is true:
the overlaying object is a constant object;
overlaying object is not marked as Volatile;
if overlaid object is not a parameter, it is not marked as Volatile;
This rule has no parameters.
Example
V : Integer with Volatile;
C : constant Integer := 1;
for C'Address use V'Address; -- FLAG
3.1.5.44. Nonoverlay_Address_Specifications
Flag an attribute definition clause that defines 'Address
attribute if
it does not have the form for Overlaying'Address use Overlaid'Address;
where Overlaying
is an identifier defined by an object declaration
and Overlaid
is an identifier defined either by an object declaration
or a parameter specification. Flag an Address aspect specification if
this aspect specification is not a part of an object declaration and
if the aspect value does not have the form Overlaid'Address
where Overlaid
is an identifier defined either by an object
declaration or a parameter specification.
Address specifications given for program units are not flagged.
This rule has no parameters.
Example
type Rec is record
C : Integer;
end record;
Var_Rec : Rec;
Var_Int : Integer;
Var1 : Integer with Address => Var_Int'Address;
Var2 : Integer with Address => Var_Rec.C'Address; -- FLAG
3.1.5.45. Non_Short_Circuit_Operators
Flag all calls to predefined and
and or
operators for
any boolean type. Calls to
user-defined and
and or
and to operators defined by renaming
declarations are not flagged. Calls to predefined and
and or
operators for modular types or boolean array types are not flagged.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- Except_Assertions: bool
If true
, do not flag the use of non-short-circuit_operators inside
assertion-related pragmas or aspect specifications.
A pragma or an aspect is considered as assertion-related if its name
is from the following list:
Example
B1 := I > 0 and J > 0; -- FLAG
B2 := I < 0 and then J < 0;
B3 := I > J or J > 0; -- FLAG
B4 := I < J or else I < 0;
3.1.5.46. Not_Imported_Overlays
Flag an attribute definition clause that defines ‘Address attribute and
has the form for Overlaying'Address use Overlaid'Address;
where
Overlaying
and Overlaid
are identifiers
both defined by object declarations if Overlaying
is not marked as
imported. Flag an Address aspect specification if this aspect specification
is a part of an object declaration of the object Overlaying
and
if the aspect value has the form Overlaid'Address
where Overlaid
is an identifier defined by an object declaration if the object Overlaying
is not marked as imported.
This rule has no parameters.
Example
package Pack is
I : Integer;
J : Integer with Address => I'Address; -- FLAG
L : Integer;
for L'Address use I'Address; -- NO FLAG
pragma Import (C, L);
end Pack;
3.1.5.47. Null_Paths
Flag a statement sequence that is a component of an if
, case
or
loop
statement if this sequences consists of NULL statements only.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- Except_Enums: bool
If true
, do not flag null paths inside case statements whose selecting
expression is of an enumeration type.
Example
if I > 10 then
J := 5;
elsif I > 0 then
null; -- FLAG
else
J := J + 1;
end if;
case J is
when 1 =>
I := I + 1;
when 2 =>
null; -- FLAG
when 3 =>
J := J + 1;
when others =>
null; -- FLAG
end case;
3.1.5.48. Objects_Of_Anonymous_Types
Flag any object declaration located immediately within a package
declaration or a package body (including generic packages) if it uses
anonymous access or array type definition. Record component definitions
and parameter specifications are not flagged. Formal object declarations
defined with anonymous access definitions are flagged.
This rule has no parameters.
Example
package Foo is
type Arr is array (1 .. 10) of Integer;
type Acc is access Integer;
A : array (1 .. 10) of Integer; -- FLAG
B : Arr;
C : access Integer; -- FLAG
D : Acc;
generic
F1 : access Integer; -- FLAG
F2 : Acc;
procedure Proc_G
(P1 : access Integer;
P2 : Acc);
end Foo;
3.1.5.49. Operator_Renamings
Flag subprogram renaming declarations that have an operator symbol as
the name of renamed subprogram.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- Name_Mismatch: bool
If true
, only flag when the renamed subprogram is also an operator with
a different name.
Example
function Foo (I, J : Integer) -- FLAG
return Integer renames Standard."+";
function "-" (I, J : Integer) -- NO FLAG
return Integer renames Bar;
3.1.5.50. OTHERS_In_Aggregates
Flag each use of an others
choice in extension aggregates.
In record and array aggregates, an others
choice is flagged unless
it is used to refer to all components, or to all but one component.
If, in case of a named array aggregate, there are two associations, one
with an others
choice and another with a discrete range, the
others
choice is flagged even if the discrete range specifies
exactly one component; for example, (1..1 => 0, others => 1)
.
This rule has no parameters.
Example
package Foo is
type Arr is array (1 .. 10) of Integer;
type Rec is record
C1 : Integer;
C2 : Integer;
C3 : Integer;
C4 : Integer;
end record;
type Tagged_Rec is tagged record
C1 : Integer;
end record;
type New_Tagged_Rec is new Tagged_Rec with record
C2 : Integer;
C3 : Integer;
C4 : Integer;
end record;
Arr_Var1 : Arr := (others => 1);
Arr_Var2 : Arr := (1 => 1, 2=> 2, others => 0); -- FLAG
Rec_Var1 : Rec := (C1 => 1, others => 0);
Rec_Var2 : Rec := (1, 2, others => 3); -- FLAG
Tagged_Rec_Var : Tagged_Rec := (C1 => 1);
New_Tagged_Rec_Var : New_Tagged_Rec := (Tagged_Rec_Var with others => 0); -- FLAG
end Foo;
3.1.5.51. OTHERS_In_CASE_Statements
Flag any use of an others
choice in a case
statement.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- N: int
If specified, only flag if the others choice can be determined to span less
than N
values (0 means no minimum value).
Example
case J is
when 1 =>
I := I + 1;
when 3 =>
J := J + 1;
when others => -- FLAG
null;
end case;
3.1.5.52. OTHERS_In_Exception_Handlers
Flag any use of an others
choice in an exception handler.
This rule has no parameters.
Example
exception
when Constraint_Error =>
I:= Integer'Last;
when others => -- FLAG
I := I_Old;
raise;
3.1.5.53. Outbound_Protected_Assignments
Flag an assignment statement located in a protected body if the
variable name in the left part of the statement denotes an object
declared outside this protected type or object.
This rule has no parameters.
Example
package Pack is
Var : Integer;
protected P is
entry E (I : in out Integer);
procedure P (I : Integer);
private
Flag : Boolean;
end P;
end Pack;
package body Pack is
protected body P is
entry E (I : in out Integer) when Flag is
begin
I := Var + I;
Var := I; -- FLAG
end E;
procedure P (I : Integer) is
begin
Flag := I > 0;
end P;
end P;
end Pack;
3.1.5.54. Outside_References_From_Subprograms
Within a subprogram body or an expression function flag any identifier that
denotes a non global data object declared outside this body.
This rule analyzes generic instantiations and ignores generic packages to
avoid flagging all references to formal objects.
This rule has no parameters.
Example
procedure Enclosing is
Var : Integer;
procedure Proc (I : in out Integer) is
begin
I := I + Var; -- FLAG
3.1.5.55. Overly_Nested_Control_Structures
Flag each control structure whose nesting level exceeds the value provided
in the rule parameter.
The control structures checked are the following:
if
statement
case
statement
loop
statement
selective accept statement
timed entry call statement
conditional entry call statement
asynchronous select statement
The rule has the following (optional) parameters for the +R
option and for
LKQL rule options files:
- N: int
Positive integer specifying the maximal control structure nesting
level that is not flagged. Defaults to 3 if not specified.
- Loops_Only: bool
If true
, only loop statements are counted.
Example
if I > 0 then
for Idx in I .. J loop
if J < 0 then
case I is
when 1 =>
if Idx /= 0 then -- FLAG (if rule parameter is 3)
J := J / Idx;
end if;
when others =>
J := J + Idx;
end case;
end if;
end loop;
end if;
3.1.5.56. Overly_Nested_Scopes
Flag a nested scope if the nesting level of this scope is more than the
rule parameter. The following declarations are considered as scopes by this
rule:
package and generic package declarations and bodies;
subprogram and generic subprogram declarations and bodies;
task type and single task declarations and bodies;
protected type and single protected declarations and bodies;
entry bodies;
block statements;
This rule has the following (mandatory) parameter for the +R
option and
for LKQL rule options files:
- N: int
Non-negative integer specifying the maximal allowed depth of scope
constructs.
Example
with P; use P;
package Pack is
package Pack1 is
package Pack2 is
generic
package Pack_G is
procedure P; -- FLAG if rule parameter is 3 or less
package Inner_Pack is -- FLAG if rule parameter is 3 or less
I : Integer;
end Inner_Pack;
end Pack_G;
end Pack2;
end Pack1
end Pack;
3.1.5.57. Parameters_Aliasing
Flags subprogram calls for which it can be statically detected that the same
variable (or a variable and a subcomponent of this variable) is given as
an actual to more than one OUT
or IN OUT
parameter. The rule resolves
object renamings.
This rule has the following (optional) parameter for the +R
option and
for LKQL rule options files:
- In_Parameters: bool
Whether to consider aliasing between OUT
, IN OUT
and IN
parameters, except for those IN
parameters that are of a by-copy
type, see the definition of by-copy parameters in the Ada Standard.
Example
package Pack is
type Arr is array (1 .. 5) of Integer;
type Rec is record
Comp : Arr;
end record;
procedure Proc (P1 : in out : Rec; P2 : out Integer);
end Pack;
with Pack; use Pack;
procedure Test (I : Integer) is
Var : Rec;
begin
Proc (Var, Var.Comp (I)); -- FLAG
3.1.5.58. POS_On_Enumeration_Types
Flag 'Pos
attribute in case if the attribute prefix has an enumeration
type (including types derived from enumeration types).
This rule has no parameters.
Example
procedure Bar (Ch1, Ch2 : Character; I : in out Integer) is
begin
if Ch1'Pos in 32 .. 126 -- FLAG
and then
Ch2'Pos not in 0 .. 31 -- FLAG
then
I := (Ch1'Pos + Ch2'Pos) / 2; -- FLAG (twice)
end if;
end Bar;
3.1.5.59. Positional_Actuals_For_Defaulted_Generic_Parameters
Flag each generic actual parameter corresponding to a generic formal
parameter with a default initialization, if positional notation is used.
This rule has no parameters.
Example
package Foo is
function Fun_1 (I : Integer) return Integer;
function Fun_2 (I : Integer) return Integer;
generic
I_Par1 : Integer;
I_Par2 : Integer := 1;
with function Fun_1 (I : Integer) return Integer is <>;
with function Fun_3 (I : Integer) return Integer is Fun_2;
package Pack_G is
Var_1 : Integer := I_Par1;
Var_2 : Integer := I_Par2;
Var_3 : Integer := Fun_1 (Var_1);
Var_4 : Integer := Fun_3 (Var_2);
end Pack_G;
package Pack_I_1 is new Pack_G (1);
package Pact_I_2 is new Pack_G
(2, I_Par2 => 3, Fun_1 => Fun_2, Fun_3 => Fun_1);
package Pack_I_3 is new Pack_G (1,
2, -- FLAG
Fun_2, -- FLAG
Fun_1); -- FLAG
end Foo;
3.1.5.60. Positional_Actuals_For_Defaulted_Parameters
Flag each actual parameter to a subprogram or entry call where the
corresponding formal parameter has a default expression, if positional
notation is used.
This rule has no parameters.
Example
procedure Proc (I : in out Integer; J : Integer := 0) is
begin
I := I + J;
end Proc;
begin
Proc (Var1, Var2); -- FLAG
3.1.5.61. Positional_Components
Flag each array, record and extension aggregate that includes positional
notation.
This rule has no parameters.
Example
package Foo is
type Arr is array (1 .. 10) of Integer;
type Rec is record
C_Int : Integer;
C_Bool : Boolean;
C_Char : Character;
end record;
Var_Rec_1 : Rec := (C_Int => 1, C_Bool => True, C_Char => 'a');
Var_Rec_2 : Rec := (2, C_Bool => False, C_Char => 'b'); -- FLAG
Var_Rec_3 : Rec := (1, True, 'c'); -- FLAG
Var_Arr_1 : Arr := (1 => 1, others => 10);
Var_Arr_2 : Arr := (1, others => 10); -- FLAG
end Foo;
3.1.5.62. Positional_Generic_Parameters
Flag each positional actual generic parameter except for the case when
the generic unit being instantiated has exactly one generic formal
parameter.
This rule has no parameters.
Example
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Unchecked_Conversion;
procedure Bar (I : in out Integer) is
type My_Int is range -12345 .. 12345;
function To_My_Int is new Ada.Unchecked_Conversion
(Source => Integer, Target => My_Int);
function To_Integer is new Ada.Unchecked_Conversion
(My_Int, Integer); -- FLAG (twice)
package My_Int_IO is new Ada.Text_IO.Integer_IO (My_Int);
3.1.5.63. Positional_Parameters
Flag each positional parameter notation in a subprogram or entry call,
except for the following:
Parameters of calls to attribute subprograms are not flagged;
Parameters of prefix or infix calls to operator functions are not flagged;
If the called subprogram or entry has only one formal parameter,
the parameter of the call is not flagged;
If a subprogram call uses the Object.Operation notation, then
the first parameter (that is, Object) is not flagged;
if the called subprogram has only two parameters, the second parameter
of the call is not flagged;
This rule has the following (optional) parameter for the +R
option and
for LKQL rule options files:
- All: bool
If true
, all the positional parameter associations that can be replaced
with named associations according to language rules are flagged, except
parameters of the calls to operator functions.
Example
procedure Bar (I : in out Integer) is
function My_Max (Left, Right : Integer) return Integer renames Integer'Max;
procedure Proc1 (I : in out Integer) is
begin
I := I + 1;
end Proc1;
procedure Proc2 (I, J : in out Integer) is
begin
I := I + J;
end Proc2;
L, M : Integer := 1;
begin
Proc1 (L);
Proc2 (L, M); -- FLAG (twice)
Proc2 (I => M, J => L);
L := Integer'Max (10, M);
M := My_Max (100, Right => L); -- FLAG
end Bar;
3.1.5.64. Potential_Parameters_Aliasing
This rule is a complementary rule for the Parameters_Aliasing rule -
it flags subprogram calls where the same variable (or a variable and its
subcomponent) is given as an actual to more than one OUT
or IN OUT
parameter, but the fact of aliasing cannot be determined statically because
this variable is an array component, and the index value(s) is(are) not
known statically. The rule resolves object renamings.
Note that this rule does not flag calls that are flagged by the
Parameters_Aliasing rule and vice versa.
This rule has the following (optional) parameter for the +R
option and
for LKQL rule options files:
- In_Parameters: bool
Whether to consider aliasing between OUT
, IN OUT
and IN
parameters, except for those IN
parameters that are of a by-copy
type, see the definition of by-copy parameters in the Ada Standard.
Example
package Pack is
procedure Proc (P1 : out Integer; P2 : in out Integer);
type Arr is array (1 .. 10 ) of Integer;
end Pack;
with Pack; use Pack;
procedure Proc (X : in out Arr; I, J : Integer) is
begin
Proc (X (I), X (J)); -- FLAG
3.1.5.65. Profile_Discrepancies
Flag subprogram or entry body (or body stub) if its parameter (or
parameter and result) profile does not follow the lexical structure
of the profile in the corresponding subprogram or entry declaration.
This rule has no parameters.
Example
package Pack is
procedure Proc
(I : Integer;
J : Integer);
end Pack;
package body Pack is
procedure Proc (I, J : Integer) is -- FLAG
3.1.5.66. Recursive_Subprograms
Flags specs (and bodies that act as specs) of recursive subprograms. A
subprogram is considered as recursive in a given context if there exists
a chain of direct calls starting from the body of, and ending at
this subprogram within this context. A context is provided by the set
of Ada sources specified as arguments of a given gnatcheck
call.
Neither dispatching calls nor calls through access-to-subprograms
are considered as direct calls by this rule. If Follow_Dispatching_Calls
rule parameter is set, gnatcheck
considers a dispatching call as a set
of calls to all the subprograms the dispatching call may dispatch to,
otherwise dispatching calls are ignored. The current rule limitation is
that when processing dispatching calls the rule does not take into account
type primitive operations declared in generic instantiations.
This rule does not take into account calls to subprograms whose
bodies are not available because of any reason (a subprogram is imported,
the Ada source containing the body is not provided as gnatcheck
argument source etc.). The Unavailable_Body_Calls rule can be used to
detect these cases.
Generic subprograms and subprograms detected in generic units are not
flagged. Recursive subprograms in generic instantiations
are flagged.
Ghost code and assertion code such as pre & post conditions or code inside of
pragma Assert is not flagged either by default.
The rule does not take into account implicit calls that are the
result of computing default initial values for an object or a subcomponent
thereof as a part of the elaboration of an object declaration.
The rule also does not take into account subprogram calls inside
aspect definitions.
The rule has an optional parameter for the +R
option and for LKQL rule
options files:
- Follow_Dispatching_Calls: bool
Whether to treat a dispatching call as a set of calls to all the subprograms
the dispatching call may dispatch to.
- Follow_Ghost_Code: bool
Whether to analyze ghost code and assertion code, which isn’t analyzed by
this check by default.
Example
function Factorial (N : Natural) return Positive is -- FLAG
begin
if N = 0 then
return 1;
else
return N * Factorial (N - 1);
end if;
end Factorial;
3.1.5.67. Redundant_Boolean_Expressions
Flag constructs including boolean operations that can be simplified. The
following constructs are flagged:
if
statements that have if
and else
paths (and no elsif
path) if
both paths contain a single statement that is either:
where True
and False
are literals of the type Standard.Boolean
or any type derived from it. Note that in case of assignment statements the
variable names in the left part should be literally the same (case
insensitive);
if
expressions that have if
and else
paths (without any elseif
)
if one path expression is True
and the other is False
, where True
and False
are literals of the Standard.Boolean
type (or any type derived
from it).
infix call to a predefined =
or /=
operator when the right operand
is True
or False
where True
and False
are literals of the type
Standard.Boolean
or any type derived from it.
infix call to a predefined not
operator whose argument is an infix
call to a predefined ordering operator.
This rule has no parameters.
Example
if I + J > K then -- FLAG
return True;
else
return False;
end if;
3.1.5.68. Redundant_Null_Statements
Flag null statements that serve no purpose and can be removed. If a null
statement has a label it is not flagged.
This rule has no parameters.
Example
if I > 0 then
null; -- FLAG
pragma Assert (J > 0);
end if;
3.1.5.69. Restrictions
Flags violations of Ada predefined and GNAT-specific restrictions
according to the rule parameter(s) specified.
gnatcheck
does not check Ada or GNAT restrictions itself, instead
it compiles an argument source with a configuration file that
defines restrictions of interest,
analyses the style warnings generated by the GNAT compiler and
includes the information about restriction violations detected into
the gnatcheck
messages.
This rule allows parametric rule exemptions, the parameters
that are allowed in the definition of exemption sections are
the names of the restrictions except for the case when a restriction
requires a non-numeric parameter, in this case the parameter should be
the name of the restriction with the parameter, as it is given for the
rule.
The rule should have a parameter, the format of the rule parameter is the
same as the parameter of
the pragma Restrictions
or Restriction_Warnings
.
Note
In LKQL rule options files, this rule should have an Arg
named parameter
associated to a list of strings. Each element of this list should be a
restriction parameter, for example:
val rules = @{
Restrictions: {Arg: ["Max_Task_Entries=>2", "No_Access_Subprograms"]}
}
If your code contains pragmas Warnings
with parameter Off
, this may
result in false negatives for this rule, because the corresponding warnings
generated during compilation will be suppressed. The workaround is to
use for gnatcheck
call a configuration file that
contains pragma Ignore_Pragma (Warnings);
.
Warning
Note, that some restriction checks cannot be performed by gnatcheck
because they are either dynamic or require information from the code
generation phase. For such restrictions gnatcheck generates the
corresponding warnings and disables the Restrictions
rules.
Example
with Ada.Finalization; -- FLAG (+RRestrictions:No_Dependence=>Ada.Finalization)
procedure Proc is
type Access_Integer is access Integer;
Var : Access_Integer;
begin
Var := new Integer'(1); -- FLAG (+RRestrictions:No_Allocators)
end Proc;
3.1.5.70. Same_Logic
Flags expressions that contain a chain of infix calls to the same boolean
operator (and
, or
, and then
, or else
, xor
) if an expression
contains syntactically equivalent operands.
This rule has no parameters.
Example
B := Var1 and Var2; -- NO FLAG
return A or else B or else A; -- FLAG
3.1.5.71. Same_Operands
Flags infix calls to binary operators /
, =
, /=
, >
, >=
,
<
, <=
, -
, mod
, rem
(except when operating on floating
point types) if operands of a call are syntactically equivalent.
This rule has no parameters.
Example
Y := (X + 1) / (X - 1); -- NO FLAG
Z := (X + 1) / (X + 1); -- FLAG
3.1.5.72. Same_Tests
Flags condition expressions in if
statements or if
expressions if
a statement or expression contains another condition expression that is
syntactically equivalent to the first one.
This rule has no parameters.
Example
if Str = A then -- FLAG: same test at line 5
Put_Line("Hello, tata!");
elsif Str = B then
Put_Line("Hello, titi!");
elsif Str = A then
Put_Line("Hello, toto!");
else
Put_Line("Hello, world!");
end if;
3.1.5.73. Side_Effect_Parameters
Flag subprogram calls and generic instantiations that have at least two actual
parameters that are expressions containing a call to the same function as a
subcomponent. Only calls to the functions specified as a rule parameter are
considered.
The rule has an optional parameter(s) for the +R
option and for LKQL rule
options files:
- Functions: list[string]
A list of fully expanded Ada names of functions to flag parameters from.
Note that a rule parameter should be a function name but not the name defined
by a function renaming declaration. Note also, that if a rule parameter does not
denote the name of an existing function or if it denotes a name defined by
a function renaming declaration, the parameter itself is (silently) ignored
and does not have any effect.
Note also, that the rule does not make any overload resolution, so if
a rule parameter refers to more than one overloaded functions with the same
name, the rule will treat calls to all these function as the calls to the
same function.
Example
-- Suppose the rule is activated as +RSide_Effect_Parameters:P.Fun
package P is
function Fun return Integer;
function Fun (I : Integer) return Integer;
function Fun1 (I : Integer) return Integer;
end P;
with P; use P;
with Bar;
procedure Foo is
begin
Bar (Fun, 1, Fun1 (Fun)); -- FLAG
3.1.5.74. Silent_Exception_Handlers
Flag any exception handler in which there exists at least one an execution path
that does not raise an exception by a raise
statement or a call to
Ada.Exceptions.Raise_Exception
or to Ada.Exceptions.Reraise_Occurrence
nor contains a call to some subprogram specified by the rule parameter
Subprograms.
The rule has the following parameter for the +R
option and for LKQL rule
options files:
- Subprograms: list[string]
List of names of subprograms. An exception handler is not flagged if it
contains a call to a subprogram that has a fully expanded Ada names that
matches an element of this list.
This list may contains fully expanded Ada names AND case-insensitive
regular expression. From a +R
option, you can specify a regular
expression by providing an Ada string literal, and from an LKQL rule options
file, you have to append the |
character at the beginning of your regular
expression. For example:
+RSilent_Exception_Handlers:My.Expanded.Name,"My\.Regex\..*"
maps to:
val rules = @{
Silent_Exception_Handlers: {Subprograms: ["My.Expanded.Name", "|My\.Regex\..*"]}
}
Note that if you specify the rule with parameters in a command shell, you may
need to escape its parameters. The best and the safest way of using this rule
is to place it into a rule file and to use this rule file as a parameter of the
-from=
option, no escaping is needed in this case.
Example
with Ada.Exceptions; use Ada.Exceptions;
procedure Exc is
procedure Log (Msg : String) with Import;
-- Suppose the rule parameters are:
-- ada.exceptions.exception_message,"\.Log$"
I : Integer := 0;
begin
begin
I := I + 1;
exception
when others => -- FLAG
null;
end;
exception
when Constraint_Error => -- NO FLAG
raise;
when Program_Error => -- NO FLAG
Log ("");
when E : others => -- NO FLAG
I := 0;
Log (Exception_Message (E));
end Exc;
3.1.5.75. Single_Value_Enumeration_Types
Flag an enumeration type definition if it contains a single enumeration
literal specification
This rule has no parameters.
Example
type Enum3 is (A, B, C);
type Enum1 is (D); -- FLAG
3.1.5.76. SPARK_Procedures_Without_Globals
Flags SPARK procedures that don’t have a global aspect.
This rule has no parameters.
Example
package Test is
procedure P with SPARK_Mode => On; -- FLAG
procedure Q is null; -- NOFLAG
function Foo return Integer -- NOFLAG
is (12)
with SPARK_Mode => On;
V : Integer;
procedure T with Global => V; -- NOFLAG
function Bar return Integer with SPARK_Mode => On; -- NOFLAG
end Test;
3.1.5.77. Trivial_Exception_Handlers
Flag exception handlers that contain a raise statement with no exception name
as their first statement unless the enclosing handled sequence of
statements also contains a handler with OTHERS
exception choice that
starts with any statement but not a raise statement with no exception name.
This rule has no parameters.
Example
exception
when My_Exception => -- FLAG
raise;
end;
exception
when Constraint_Error => -- NO FLAG
raise;
when others =>
null;
end;
3.1.5.78. Unavailable_Body_Calls
Flag any subprogram call if the set of argument sources does not
contain a body of the called subprogram because of any reason.
Calls to formal subprograms in generic bodies are not flagged.
This rule can be useful as a complementary rule for the
Recursive_Subprograms rule - it flags potentially missing recursion
detection and identify potential missing checks.
This rule has the following (optional) parameter for the +R
option and
for LKQL rule options files:
- Indirect_Calls: bool
Whether to flag all the indirect calls (that is, calls through
access-to-subprogram values).
Example
procedure Calls is
procedure Unknown with Import;
type Proc_A is access procedure (X : Integer);
X : Proc_A := Some_Proc'Access;
begin
Unknown; -- FLAG
X (1); -- FLAG (if Indirect_Calls is enabled)
3.1.5.79. Unchecked_Address_Conversions
Flag instantiations of Ada.Unchecked_Conversion
if the actual for the
formal type Source is the System.Address
type (or a type derived from
it), and the actual for the formal type Target
is an access type
(including types derived from access types). This include cases when the
actual for Source
is a private type and its full declaration is a type
derived from System.Address
, and cases when the actual for Target
is
a private type and its full declaration is an access type. The rule is
checked inside expanded generics unless the No_Instantiations
parameter
is set.
The rule has the following optional parameters for the +R
option and for
LKQL rule options files:
- All: bool
If true
, all instantiations of Unchecked_Conversion to or from System.Address are
flagged.
- No_Instantiations: bool
If true
, Do not check inside expanded generics.
Example
with Ada.Unchecked_Conversion;
with System;
package Foo is
type My_Address is new System.Address;
type My_Integer is new Integer;
type My_Access is access all My_Integer;
function Address_To_Access is new Ada.Unchecked_Conversion -- FLAG
(Source => My_Address,
Target => My_Access);
end Foo;
3.1.5.80. Unchecked_Conversions_As_Actuals
Flag call to instantiation of Ada.Unchecked_Conversion
if it is an actual in
procedure or entry call or if it is a default value in a subprogram or
entry parameter specification.
This rule has no parameters.
Example
with Ada.Unchecked_Conversion;
procedure Bar (I : in out Integer) is
type T1 is array (1 .. 10) of Integer;
type T2 is array (1 .. 10) of Integer;
function UC is new Ada.Unchecked_Conversion (T1, T2);
Var1 : T1 := (others => 1);
Var2 : T2 := (others => 2);
procedure Init (X : out T2; Y : T2 := UC (Var1)) is -- FLAG
begin
X := Y;
end Init;
procedure Ident (X : T2; Y : out T2) is
begin
Y := X;
end Ident;
begin
Ident (UC (Var1), Var2); -- FLAG
end Bar;
3.1.5.81. Unconditional_Exits
Flag unconditional exit
statements.
This rule has no parameters.
Example
procedure Find_A (S : String; Idx : out Natural) is
begin
Idx := 0;
for J in S'Range loop
if S (J) = 'A' then
Idx := J;
exit; -- FLAG
end if;
end loop;
end Find_A;
3.1.5.82. Uninitialized_Global_Variables
Flag an object declaration that does not have an explicit initialization if it is
located in a library-level package or generic package or bodies of library-level package
or generic package (including packages and generic packages nested in those).
Do not flag deferred constant declarations.
This rule has no parameters.
Example
package Foo is
Var1 : Integer; -- FLAG
Var2 : Integer := 0;
end Foo;
3.1.5.83. Unnamed_Blocks_And_Loops
Flag each unnamed block statement. Flag a unnamed loop statement if this
statement is enclosed by another loop statement or if it encloses another
loop statement.
The rule has no parameters.
Example
procedure Bar (S : in out String) is
I : Integer := 1;
begin
if S'Length > 10 then
declare -- FLAG
S1 : String (S'Range);
Last : Positive := S1'Last;
Idx : Positive := 0;
begin
for J in S'Range loop -- FLAG
S1 (Last - Idx) := S (J);
Idx := Idx + 1;
for K in S'Range loop -- FLAG
S (K) := Character'Succ (S (K));
end loop;
end loop;
S := S1;
end;
end if;
end Bar;
3.1.5.84. Unnamed_Exits
Flags exit statements with no loop names that exit from named loops.
The rule has no parameters.
Example
Named: for I in 1 .. 10 loop
while J < 0 loop
J := J + K;
exit when J = L; -- NO FLAG
end loop;
exit when J > 10; -- FLAG
end loop Named;
3.1.5.85. Use_Array_Slices
Flag for
loops if a loop contains a single assignment statement, and
this statement is an assignment between array components or between an
array component and a constant value, and such a loop can
be replaced by a single assignment statement with array slices or
array objects as the source and the target of the assignment.
This rule has no parameters.
Example
type Table_Array_Type is array (1 .. 10) of Integer;
Primary_Table : Table_Array_Type;
Secondary_Table : Table_Array_Type;
begin
for I in Table_Array_Type'Range loop -- FLAG
Secondary_Table (I) := Primary_Table (I);
end loop;
for I in 2 .. 5 loop -- FLAG
Secondary_Table (I) := 1;
end loop;
3.1.5.86. Use_Case_Statements
Flag an if
statement if this statement could be replaced by a
case
statement. An if
statement is considered as being
replaceable by a case
statement if:
it contains at least one elsif
alternative;
all the conditions are infix calls to some predefined relation operator,
for all of them one operand is the reference to the same variable of some
discrete type;
for calls to relation operator another operand is some static expression;
This rule has no parameters.
Example
if I = 1 then -- FLAG
I := I + 1;
elsif I > 2 then
I := I + 2;
else
I := 0;
end if;
3.1.5.87. USE_Clauses
Flag names mentioned in use clauses. Use type clauses and names mentioned
in them are not flagged.
This rule has the following optional parameter for the +R
option and for
LKQL rule options files:
- Exempt_Operator_Packages: bool
If true
, do not flag a package name in a package use clause if it refers
to a package that only declares operators in its visible part.
Note
This rule has another parameter, only available when using an LKQL rule
options file: allowed
. It is a list of Ada names describing packages
to exempt from begin flagged when used in “use” clauses. Strings in this
list are case insensitive. Example:
val rules = @{
Use_Clauses: {Allowed: ["Ada.Strings.Unbounded", "Other.Package"]}
}
Example
package Pack is
I : Integer;
end Pack;
package Operator_Pack is
function "+" (L, R : Character) return Character;
end Operator_Pack;
with Pack, Operator_Pack;
use Pack; -- FLAG if "Pack" is not in Allowed
use Operator_Pack; -- FLAG only if Exempt_Operator_Packages is false
3.1.5.88. Use_For_Loops
Flag while
loops which could be replaced by a for
loop. The rule detects
the following code patterns:
...
Id : Some_Integer_Type ...;
... -- no write reference to Id
begin
...
while Id <relation_operator> <expression> loop
... -- no write reference to Id
Id := Id <increment_operator> 1;
end loop;
... -- no reference to Id
end;
where relation operator in the loop condition should be some predefined
relation operator, and increment_operator should be a predefined “+” or
“-” operator.
Note, that the rule only informs about a possibility to replace a
while
loop by a for
, but does not guarantee that this is
really possible, additional human analysis is required for all the
loops marked by the rule.
This rule has the following (optional) parameters for the +R
option and
for LKQL rule options files:
- No_Exit: bool
If true
, flag only loops that do not include an exit statement that
applies to them.
- No_Function: bool
If true
, <expression> must not contain any non-operator function call.
Example
Idx : Integer := 1;
begin
while Idx <= 10 loop -- FLAG
Idx := Idx + 1;
end loop;
end;
3.1.5.89. Use_For_Of_Loops
Flag for ... in
loops which could be replaced by a for ... of
loop,
that is, where the loop index is used only for indexing a single object
on a one dimension array.
The rule detects the following code patterns:
for Index in <array>'Range loop
-- where <array> is an array object
[all references to Index are of the form <array> (Index)]
end loop;
This rule has the following (optional) parameter for the +R
option and
for LKQL rule options files:
- N: int
Non-negative integer, indicates the minimal number of references of the form
<array> (Index)
in the loop to make the loop to be flagged.
If no parameter is used for the rule, this corresponds to the parameter value 1.
Example
for J in Arr'Range loop -- FLAG
Sum := Sum + Arr (J);
end loop;
for K in Left'Range loop
Res := Left (J) + Right (J);
end loop;
3.1.5.90. Use_If_Expressions
Flag if
statements which could be replaced by an if
expression.
This rule detects the following code patterns:
if ... then
return ...;
elsif ... then -- optional chain of elsif
return ...;
else
return ...;
end if;
and:
if ... then
<LHS> := ...;
elsif ... then -- optional chain of elsif
<LHS> := ...;
else
<LHS> := ...; -- same LHS on all branches
end if;
This rule has no parameters.
Example
if X = 1 then -- FLAG
return 1;
elsif X = 2 then
return 2;
else
return 3;
end if;
if X >= 2 then -- FLAG
X := X + 1;
elsif X <= 0 then
X := X - 1;
else
X := 0;
end if;
3.1.5.91. Use_Memberships
Flag expressions that could be rewritten as membership tests. Only expressions
that are not subexpressions of other expressions are flagged. An expression
is considered to be replaceable with an equivalent membership test if it is
a logical expression consisting of a call to one or more predefined or
operation(s), each relation that is an operand of the or
expression is
a comparison of the same variable of one of following forms:
a call to a predefined =
operator, the variable is the left operand
of this call;
a membership test applied to this variable;
a range test of the form Var >= E1 and Var <= E2
where Var
is
the variable in question and >=
, and
and <=
are predefined
operators;
This rule has the following (optional) parameter for the +R
option and
for LKQL rule options files:
- Short_Circuit: bool
Whether to consider the short circuit and then
and or else
operations
along with the predefined logical and
and or
operators.
Example
begin
Bool1 := A = 100 -- FLAG (if Short_Circuit is true)
or (A >= 1 and then A <= B);
Bool2 := A = 100 -- NO FLAG
or B in S;
Bool3 := A = 1 -- FLAG
or
A = B
or
A = B + A;
3.1.5.92. USE_PACKAGE_Clauses
Flag all use
clauses for packages; use type
clauses are
not flagged.
This rule has no parameters.
Example
with Ada.Text_IO;
use Ada.Text_IO; -- FLAG
procedure Bar (S : in out String) is
3.1.5.93. Use_Ranges
Flag expressions of the form Name'First .. Name'Last
that can be replaced
by Name'Range
or simply Name
. Also flag expressions of the form
Name'Range
that can be replaced with Name
.
This rule has no parameters.
Example
procedure Proc (S : String; I : in out Integer) is
begin
for J in Integer'First .. Integer'Last loop -- FLAG
if I in Natural'Range then -- FLAG
for K in S'Range loop -- NO FLAG
I := I + K;
end loop;
end if;
end loop;
end Proc;
3.1.5.94. Use_Record_Aggregates
Flag the first statement in the sequence of assignment statements if the targets
of all these assignment statements are components of the same record objects,
all the components of this objects get assigned as the result of such a
sequence, and the type of the record object does not have discriminants.
This rule helps to detect cases when a sequence of assignment statements
can be replaced with a single assignment statement with a record aggregate
as an expression being assigned, there is no guarantee that it detects all
such sequences.
This rule has no parameters.
Example
type Rec is record
Comp1, Comp2 : Integer;
end record;
Var1, Var2 : Rec;
begin
Var1.Comp1 := 1; -- FLAG
Var1.Comp2 := 2;
Var2.Comp1 := 1; -- NO FLAG
I := 1;
Var2.Comp2 := 2;
3.1.5.95. Use_Simple_Loops
Flag while
loop statements that have a condition statically known
to be TRUE
. Such loop statements can be replaced by simple loops.
This rule has no parameters.
Example
while True loop -- FLAG
I := I + 10;
exit when I > 0;
end loop;
3.1.5.96. Use_While_Loops
Flag simple loop statements that have the exit statement completing
execution of such a loop as the first statement in their sequence of
statements. Such loop statements can be replaced by WHILE
loops.
This rule has no parameters.
Example
loop -- FLAG
exit when I > 0;
I := I + 10;
end loop;
3.1.5.97. Variable_Scoping
Flag local object declarations that can be moved into declare blocks
nested into the declaration scope. A declaration is considered as movable
into a nested scope if:
The declaration does not contain an initialization expression;
The declared object is used only in a nested block statement,
and this block statement has a declare part;
the block statement is not enclosed into a loop statement.
This rule has no parameters.
Example
procedure Scope is
X : Integer; -- FLAG
begin
declare
Y : Integer := 42;
begin
X := Y;
end;
end;
3.1.5.98. Warnings
Flags construct that would result in issuing a GNAT warning if an argument
source would be compiled with warning options corresponding to the rule
parameter(s) specified. For GNAT warnings and corresponding warning control
options see the Warning Message Control section of the GNAT User’s Guide.
gnatcheck
does not check itself if this or that construct would result
in issuing a warning, instead it compiles the project sources with the
needed warning control compilation options combined with the -gnatc
switch, analyses the warnings generated by GNAT and adds the relevant
information to the gnatcheck
messages.
The rule should have a parameter, the format of the parameter should
be a valid static_string_expression
listing GNAT warnings switches
(the letter following -gnatw
in the Warning Message Control section
mentioned above).
Note
In LKQL rule options files, this rule should have an Arg
named parameter
associated to a string corresponding to the wanted GNAT warning switches.
Example:
val rules = @{ Warnings: {Arg: "u"} }
You can also use the shortcut argument format by associating a simple string
to the rule name:
val rules = @{
Warnings: "u"
}
Note that s
and e
parameters, corresponding respectively to GNAT
-gnatws
and -gnatwe
options, are not allowed for the Warnings
GNATcheck rule since they may have side effects on other rules.
Note also that some GNAT warnings are only emitted when generating code,
these warnings will not be generated by this rule. In other words, this
rule will only generate warnings that are enabled when using -gnatc
.
If your code contains pragmas Warnings
with parameter Off
, this may
result in false negatives for this rule, because the corresponding warnings
generated during compilation will be suppressed. The workaround is to
use a configuration file that contains pragma Ignore_Pragma (Warnings);
when running gnatcheck
.
This rule allows parametric rule exemptions, the parameters
that are allowed in the definition of exemption sections are the
same as the parameters of the rule itself.
Example
with Ada.Text_IO; -- FLAG (+RWarnings:u)
procedure Proc (I : in out Integer) is
begin
pragma Unrecognized; -- FLAG (+RWarnings:g)
I := I + 1;
end Proc;
3.1.6. Readability
The rules described in this subsection may be used to enforce feature usages
that contribute towards readability.
3.1.6.3. Identifier_Casing
Flag each defining identifier that does not have a casing corresponding to the
kind of entity being declared. All defining names are checked. For the
defining names from the following kinds of declarations a special casing scheme
can be defined:
type and subtype declarations;
enumeration literal specifications (not including character literals)
and function renaming declarations if the renaming entity is an
enumeration literal;
constant and number declarations (including object renaming
declarations if the renamed object is a constant);
exception declarations and exception renaming declarations.
The rule may have the following parameters for +R
option and for LKQL rule
options files:
- Type: casing_scheme
Specifies casing for names from type and subtype declarations.
- Enum: casing_scheme
Specifies the casing of defining enumeration literals and for the
defining names in a function renaming declarations if the renamed
entity is an enumeration literal.
- Constant: casing_scheme
Specifies the casing for defining names from constants and named number
declarations, including the object renaming declaration if the
renamed object is a constant
- Exception: casing_scheme
Specifies the casing for names from exception declarations and exception
renaming declarations.
- Others: casing_scheme
Specifies the casing for all defining names for which no special casing
scheme is specified. If this parameter is not set, the casing for the
entities that do not correspond to the specified parameters is not checked.
- Exclude: string
The name of a dictionary file to specify casing exceptions. The name of the
file may contain references to environment variables (e.g.
$REPOSITORY_ROOT/my_dict.txt), they are replaced by the values of these
variables.
Where casing_scheme is a string and:
casing_scheme ::= upper|lower|mixed
upper means that the defining identifier should be upper-case.
lower means that the defining identifier should be lower-case
mixed means that the first defining identifier letter and the first
letter after each underscore should be upper-case, and all the other
letters should be lower-case
You have to use the param_name=value
formatting to pass arguments through
the +R
options. Example: +RIdentifier_Casing:Type=mixed,Others=lower
.
If a defining identifier is from a declaration for which a specific casing
scheme can be set, but the corresponding parameter is not specified for the
rule, then the casing scheme defined by Others
parameter is used to
check this identifier. If Others
parameter also is not set, the
identifier is not checked.
Exclude is the name of the text file that contains casing exceptions. The way
how this rule is using the casing exception dictionary file is consistent with
using the casing exception dictionary in the GNAT pretty-printer gnatpp, see
GNAT User’s Guide.
There are two kinds of exceptions:
- identifier
If a dictionary file contains an identifier, then each occurrence of that
(defining) identifier in the checked source should use the casing specified
included in dictionary_file
- wildcard
A wildcard has the following syntax
wildcard ::= *simple_identifier* |
*simple_identifier |
simple_identifier*
simple_identifier ::= letter{letter_or_digit}
simple_identifier
specifies the casing of subwords (the term ‘subword’
is used below to denote the part of a name which is delimited by ‘_’ or by
the beginning or end of the word and which does not contain any ‘_’ inside).
A wildcard of the form simple_identifier*
defines the casing of the
first subword of a defining name to check, the wildcard of the form
*simple_identifier
specifies the casing of the last subword, and
the wildcard of the form *simple_identifier*
specifies the casing of
any subword.
If for a defining identifier some of its subwords can be mapped onto
wildcards, but some other cannot, the casing of the identifier subwords
that are not mapped onto wildcards from casing exception dictionary
is checked against the casing scheme defined for the corresponding
entity.
If some identifier is included in the exception dictionary both as a whole
identifier and can be mapped onto some wildcard from the
dictionary, then it is the identifier and not the wildcard that is used to check
the identifier casing.
If more than one dictionary file is specified, or a dictionary file contains
more than one exception variant for the same identifier, the new casing
exception overrides the previous one.
Casing check against dictionary file(s) has a higher priority than checks
against the casing scheme specified for a given entity/declaration kind.
The rule activation option should contain at least one parameter.
The rule allows parametric exemption, the parameters that are allowed in
the definition of exemption sections are:
- Type
Exempts check for type and subtype name casing
- Enum
Exempts check for enumeration literal name casing
- Constant
Exempts check for constant name casing
- Exception
Exempts check for exception name casing
- Others
Exempts check for defining names for which no special casing scheme is specified.
- Exclude
Exempts check for defining names for which casing schemes are specified in exception
dictionaries
Example
-- if the rule is activated as '+RIdentifier_Casing:Type=upper,Others=mixed'
package Foo is
type ENUM_1 is (A1, B1, C1);
type Enum_2 is (A2, B2, C2); -- FLAG
Var1 : Enum_1 := A1;
VAR2 : ENUM_2 := A2; -- FLAG
end Foo;
3.1.6.4. Identifier_Prefixes
Flag each defining identifier that does not have a prefix corresponding
to the kind of declaration it is defined by. The defining names in the
following kinds of declarations are checked:
type and subtype declarations (task, protected and access types are treated
separately);
enumeration literal specifications (not including character literals)
and function renaming declarations if the renaming entity is an
enumeration literal;
exception declarations and exception renaming declarations;
constant and number declarations (including object renaming
declarations if the renamed object is a constant).
Defining names declared by single task declarations or single protected
declarations are not checked by this rule.
The defining name from the full type declaration corresponding to a
private type declaration or a private extension declaration is never
flagged. A defining name from an incomplete type declaration is never
flagged.
The defining name from a subprogram renaming-as-body declaration is
never flagged.
For a deferred constant, the defining name in the corresponding full
constant declaration is never flagged.
The defining name from a body that is a completion of a program unit
declaration or a proper body of a subunit is never flagged.
The defining name from a body stub that is a completion of a program
unit declaration is never flagged.
Note that the rule checks only defining names. Usage name occurrence are
not checked and are never flagged.
The rule may have the following parameters for the +R
option and for LKQL
rule options files:
- Type: string
Specifies the prefix for a type or subtype name.
- Concurrent: string
Specifies the prefix for a task and protected type/subtype name. If this
parameter is set, it overrides for task and protected types the prefix set by
the Type parameter.
- Access: string
Specifies the prefix for an access type/subtype name. If this parameter is
set, it overrides for access types the prefix set by the Type
parameter.
- Class_Access: string
Specifies the prefix for the name of an access type/subtype that points to some
class-wide type. If this parameter is set, it overrides for such access types
and subtypes the prefix set by the Type
or Access
parameter.
- Subprogram_Access: string
Specifies the prefix for the name of an access type/subtype that points to a
subprogram. If this parameter is set, it overrides for such access
types/subtypes the prefix set by the Type
or Access
parameter.
- Derived: string
Specifies the prefix for a type that is directly derived from a given type or
from a subtype thereof. The parameter must have the string1:string2
format
where string1 should be a full expanded Ada name of the ancestor type
(starting from the full expanded compilation unit name) and string2 defines
the prefix to check. If this parameter is set, it overrides for types that
are directly derived from the given type the prefix set by the Type
parameter.
- Constant: string
Specifies the prefix for defining names from constants and named number
declarations, including the object renaming declaration if the
renamed object is a constant
- Enum: string
Specifies the prefix for defining enumeration literals and for the
defining names in a function renaming declarations if the renamed
entity is an enumeration literal.
- Exception: string
Specifies the prefix for defining names from exception declarations
and exception renaming declarations.
- Exclusive: bool
If true
, check that only those kinds of names for which specific prefix
is defined have that prefix (e.g., only type/subtype names have prefix T_,
but not variable or package names), and flag all defining names that have any
of the specified prefixes but do not belong to the kind of entities this
prefix is defined for. By default the exclusive check mode is ON.
You have to use the param_name=value
formatting to pass arguments through
the +R
options. Example: +RIdentifier_Prefixes:Type=Type_,Enum=Enum_
.
The +RIdentifier_Prefixes
option (with no parameter) does not create a new
instance for the rule; thus, it has no effect on the current GNATcheck run.
There is no default prefix setting for this rule. All checks for
name prefixes are case-sensitive
If any error is detected in a rule parameter, that parameter is ignored.
In such a case the options that are set for the rule are not specified.
The rule allows parametric exemption, the parameters that are allowed in
the definition of exemption sections are:
- Type
Exempts check for type and subtype name prefixes
- Concurrent
Exempts check for task and protected type/subtype name prefixes
- Access
Exempts check for access type/subtype name prefixes
- Class_Access
Exempts check for names of access types/subtypes that point to
some class-wide types
- Subprogram_Access
Exempts check for names of access types/subtypes that point to
subprograms
- Derived
Exempts check for derived type name prefixes
- Constant
Exempts check for constant and number name prefixes
- Exception
Exempts check for exception name prefixes
- Enum
Exempts check for enumeration literal name prefixes
- Exclusive
Exempts check that only names of specific kinds of entities have prefixes
specified for these kinds
Example
-- if the rule is activated as '+RIdentifier_Prefixes:Type=Type_,Constant=Const_,ExceptioN=X_'
package Foo is
type Type_Enum_1 is (A1, B1, C1);
type Enum_2 is (A2, B2, C2); -- FLAG
Const_C1 : constant Type_Enum_1 := A1;
Const2 : constant Enum_2 := A2; -- FLAG
X_Exc_1 : exception;
Exc_2 : exception; -- FLAG
end Foo;
3.1.6.5. Identifier_Suffixes
Because of upward compatibility reasons this rule has a synonym
Misnamed_Identifiers
.
Flag the declaration of each identifier that does not have a suffix
corresponding to the kind of entity being declared.
The following declarations are checked:
type declarations
subtype declarations
object declarations (variable and constant declarations, but not number,
declarations, record component declarations, parameter specifications,
extended return object declarations, formal object declarations)
package renaming declarations (but not generic package renaming
declarations)
The default checks (enforced by the Default rule parameter) are:
type-defining names end with _T
, unless the type is an access type,
in which case the suffix must be _A
constant names end with _C
names defining package renamings end with _R
the check for access type objects is not enabled
Defining identifiers from incomplete type declarations are never flagged.
For a private type declaration (including private extensions), the defining
identifier from the private type declaration is checked against the type
suffix (even if the corresponding full declaration is an access type
declaration), and the defining identifier from the corresponding full type
declaration is not checked.
For a deferred constant, the defining name in the corresponding full constant
declaration is not checked.
Defining names of formal types are not checked.
Check for the suffix of access type data objects is applied to the
following kinds of declarations:
variable and constant declaration
record component declaration
return object declaration
parameter specification
extended return object declaration
formal object declaration
If both checks for constant suffixes and for access object suffixes are
enabled, and if different suffixes are defined for them, then for constants
of access type the check for access object suffixes is applied.
The rule may have the following parameters for +R
option and for LKQL rule
options files:
- Default: bool
If true
, sets the default listed above for all the names to be checked.
- Type_Suffix: string
Specifies the suffix for a type name.
- Access_Suffix: string
Specifies the suffix for an access type name. If this parameter is set, it
overrides for access types the suffix set by the Type_Suffix
parameter.
For access types, this parameter may have the following format:
suffix1(suffix2). That means that an access type name should have the
suffix1 suffix except for the case when the designated type is also an
access type, in this case the type name should have the suffix1 & suffix2
suffix.
- Class_Access_Suffix: string
Specifies the suffix for the name of an access type that points to some
class-wide type.
If this parameter is set, it overrides for such access types the suffix
set by the Type_Suffix
or Access_Suffix
parameter.
- Class_Subtype_Suffix: string
Specifies the suffix for the name of a subtype that denotes a class-wide type.
- Constant_Suffix: string
Specifies the suffix for a constant name.
- Renaming_Suffix: string
Specifies the suffix for a package renaming name.
- Access_Obj_Suffix: string
Specifies the suffix for objects that have an access type (including types
derived from access types).
- Interrupt_Suffix: string
Specifies the suffix for protected subprograms used as interrupt handlers.
You have to use the param_name=value
formatting to pass arguments through
the +R
options. Example: +RIdentifier_Prefixes:Type=_T,Constant=_C
.
The +RIdentifier_Prefixes
option (with no parameter) does not create a new
instance for the rule; thus, it has no effect on the current GNATcheck run.
The string value must be a valid suffix for an Ada identifier (after
trimming all the leading and trailing space characters, if any).
Parameters are not case sensitive, except the string part.
If any error is detected in a rule parameter, the parameter is ignored.
In such a case the options that are set for the rule are not
specified.
The rule allows parametric exemption, the parameters that are allowed in
the definition of exemption sections are:
- Type
Exempts check for type name suffixes
- Access
Exempts check for access type name suffixes
- Access_Obj
Exempts check for access object name suffixes
- Class_Access
Exempts check for names of access types that point to
some class-wide types
- Class_Subtype
Exempts check for names of subtypes that denote class-wide types
- Constant
Exempts check for constant name suffixes
- Renaming
Exempts check for package renaming name suffixes
Example
-- if the rule is activated as '+RIdentifier_Suffixes:Access_Suffix=_PTR,Type_Suffix=_T,Constant_Suffix=_C'
package Foo is
type Int is range 0 .. 100; -- FLAG
type Int_T is range 0 .. 100;
type Int_A is access Int; -- FLAG
type Int_PTR is access Int;
Const : constant Int := 1; -- FLAG
Const_C : constant Int := 1;
end Foo;
3.1.6.6. Max_Identifier_Length
Flag any defining identifier that has length longer than specified by
the rule parameter. Defining identifiers of enumeration literals are not
flagged.
The rule has a mandatory parameter for the +R
option and for LKQL rule
options files:
- N: int
The maximal allowed identifier length specification.
Example
type My_Type is range -100 .. 100;
My_Variable_With_A_Long_Name : My_Type; -- FLAG (if rule parameter is 27 or smaller)
3.1.6.7. Min_Identifier_Length
Flag any defining identifier that has length shorter than specified by
the rule parameter. Defining identifiers of objects and components of
numeric types are not flagged.
The rule has a mandatory parameter for the +R
option and for LKQL rule
options files:
- N: int
The minimal allowed identifier length specification.
Example
I : Integer; -- NO FLAG
J : String (1 .. 10); -- FLAG
3.1.6.8. Misnamed_Controlling_Parameters
Flag a declaration of a dispatching operation, if the first parameter is
not a controlling one and its name is not This
(the check for
parameter name is not case-sensitive). Declarations of dispatching functions
with a controlling result and no controlling parameter are never flagged.
A subprogram body declaration, subprogram renaming declaration, or subprogram
body stub is flagged only if it is not a completion of a prior subprogram
declaration.
This rule has no parameters.
Example
package Foo is
type T is tagged private;
procedure P1 (This : in out T);
procedure P2 (That : in out T); -- FLAG
procedure P1 (I : Integer; This : in out T); -- FLAG
3.1.6.9. Name_Clashes
Check that certain names are not used as defining identifiers. The names that
should not be used as identifiers must be listed in a dictionary file that is
a rule parameter. A defining identifier is flagged if it is included in a
dictionary file specified as a rule parameter, the check is not case-sensitive.
Only the whole identifiers are checked, not substrings thereof.
More than one dictionary file can be specified as the rule parameter, in this
case the rule checks defining identifiers against the union of all the
identifiers from all the dictionary files provided as the rule parameters.
This rule has the following (mandatory) parameter for the +R
option and
for LKQL rule options files:
- Dictionary_File: string
The name of a dictionary file. The name may contain references to environment
variables (e.g. $REPOSITORY_ROOT/my_dict.txt), they are replaced by the
values of these variables.
A dictionary file is a plain text file. The maximum line length for this file
is 1024 characters. If the line is longer than this limit, extra characters
are ignored.
If the name of the dictionary file does not contain any path information and
the rule option is specifies in a rule file, first the tool tries to locate
the dictionary file in the same directory where the rule file is located, and
if the attempt fails - in the current directory.
Each line can be either an empty line, a comment line, or a line containing
a list of identifiers separated by space or HT characters.
A comment is an Ada-style comment (from --
to end-of-line).
Identifiers must follow the Ada syntax for identifiers.
A line containing one or more identifiers may end with a comment.
Example
-- If the dictionary file contains names 'One' and 'Two":
One : constant Integer := 1; -- FLAG
Two : constant Float := 2.0; -- FLAG
Constant_One : constant Float := 1.0;
3.1.6.11. Object_Declarations_Out_Of_Order
Flag any object declaration that is located in a library unit body if
this is preceding by a declaration of a program unit spec, stub or body.
This rule has no parameters.
Example
procedure Proc is
procedure Proc1 is separate;
I : Integer; -- FLAG
3.1.6.12. One_Construct_Per_Line
Flag any statement, declaration or representation clause if the code
line where this construct starts contains some other Ada code symbols
preceding or following this construct. The following constructs are not
flagged:
enumeration literal specification;
parameter specifications;
discriminant specifications;
mod clauses;
loop parameter specification;
entry index specification;
choice parameter specification;
In case if we have two or more declarations/statements/clauses on a
line and if there is no Ada code preceding the first construct, the
first construct is flagged
This rule has no parameters.
Example
procedure Swap (I, J : in out Integer) is
Tmp : Integer;
begin
Tmp := I;
I := J; J := Tmp; -- FLAG
end Swap;
3.1.6.13. Style_Checks
Flags violations of the source code presentation and formatting rules
specified in the Style Checking
section of the GNAT User's Guide
according to the rule parameter(s)
specified.
gnatcheck
does not check GNAT style rules itself, instead it compiles
an argument source with the needed style check compilation options,
analyses the style messages generated by the GNAT compiler and
includes the information about style violations detected into
the gnatcheck
messages.
This rule takes a parameter in one of the following forms:
All_Checks, which enables the standard style checks corresponding
to the -gnatyy
GNAT style check option,
A string with the same
structure and semantics as the string_LITERAL
parameter of the
GNAT pragma Style_Checks
(see Pragma Style_Checks
in the GNAT Reference Manual).
For instance, the +RStyle_Checks:O
rule option activates
the compiler style check that corresponds to -gnatyO
style check option.
Note
In LKQL rule options files, this rule should have an Arg
named parameter
associated to a string corresponding to the wanted GNAT style checks
switches. Example:
val rules = @{ Style_Checks: {Arg: "xz"} }
You can also use the shortcut argument format by associating a simple string
to the rule name:
val rules = @{
Style_Checks: "xz"
}
This rule allows parametric rule exemptions, the parameters
that are allowed in the definition of exemption sections are the
same as the parameters of the rule itself.
Example
package Pack is
I : Integer;
end; -- FLAG (for +RStyle_Checks:e)